Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F9347229
D4611.id16409.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
39 KB
Subscribers
None
D4611.id16409.diff
View Options
diff --git a/docs/metadata.rst b/docs/metadata.rst
--- a/docs/metadata.rst
+++ b/docs/metadata.rst
@@ -36,7 +36,11 @@
.. code:: xml
- <codemeta:url>www.url-example.com</codemeta:url>
+ <codemeta:url>http://example.com/my_project</codemeta:url>
+
+- **the create\_origin** tag *SHOULD* be used to specify the URL of the origin
+ to create (otherwise, a fallback is created using the slug, or a random
+ string if missing)
- **the description** of the software deposit *SHOULD* be provided
[codemeta:description]: short or long description of the software
@@ -55,11 +59,17 @@
.. code:: xml
<?xml version="1.0"?>
- <entry xmlns="http://www.w3.org/2005/Atom">
+ <entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:swhdeposit="https://www.softwareheritage.org/schema/2018/deposit">
<title>Awesome Compiler</title>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2017-10-07T15:17:08Z</updated>
<author>some awesome author</author>
+ <swhdeposit:deposit>
+ <swhdeposit:create_origin>
+ <swhdeposit:origin url="http://example.com/my_project" />
+ </swhdeposit:create_origin>
+ </swhdeposit:deposit>
</entry>
Using Atom with CodeMeta
@@ -69,9 +79,15 @@
<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom"
- xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0">
+ xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0"
+ xmlns:swhdeposit="https://www.softwareheritage.org/schema/2018/deposit">
<title>Awesome Compiler</title>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <swhdeposit:deposit>
+ <swhdeposit:create_origin>
+ <swhdeposit:origin url="http://example.com/1785io25c695" />
+ </swhdeposit:create_origin>
+ </swhdeposit:deposit>
<codemeta:id>1785io25c695</codemeta:id>
<codemeta:url>origin url</codemeta:url>
<codemeta:identifier>other identifier, DOI, ARK</codemeta:identifier>
@@ -129,9 +145,15 @@
<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:dcterms="http://purl.org/dc/terms/"
- xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0">
+ xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0"
+ xmlns:swhdeposit="https://www.softwareheritage.org/schema/2018/deposit">
<title>Awesome Compiler</title>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <swhdeposit:deposit>
+ <swhdeposit:create_origin>
+ <swhdeposit:origin url="http://example.com/225c695-cfb8-4ebb-aaaa-80da344efa6a" />
+ </swhdeposit:create_origin>
+ <swhdeposit:deposit>
<dcterms:identifier>hal-01587361</dcterms:identifier>
<dcterms:identifier>doi:10.5281/zenodo.438684</dcterms:identifier>
<dcterms:title xml:lang="en">The assignment problem</dcterms:title>
diff --git a/docs/specs/metadata_example.xml b/docs/specs/metadata_example.xml
--- a/docs/specs/metadata_example.xml
+++ b/docs/specs/metadata_example.xml
@@ -23,6 +23,9 @@
<codemeta:affiliation> UPMC </codemeta:affiliation>
</codemeta:author>
<swh:deposit>
+ <swh:create_origin>
+ <swh:origin url="http://has.archives-ouvertes.fr/hal-01243573" />
+ </swh:create_origin>
<swh:bindings>
<swh:binding source="path/to/file.txt" destination="aaaaaaaaaaa..."/>
</swh:bindings>
diff --git a/docs/specs/spec-loading.rst b/docs/specs/spec-loading.rst
--- a/docs/specs/spec-loading.rst
+++ b/docs/specs/spec-loading.rst
@@ -54,7 +54,8 @@
Origin artifact
~~~~~~~~~~~~~~~
-We create an origin URL by concatenating the client's `provider_url` and the
+If the ``<swh:create_origin>`` is missing,
+we create an origin URL by concatenating the client's `provider_url` and the
value of the Slug header of the initial POST request of the deposit
(or a randomly generated slug if it is missing).
diff --git a/docs/specs/swh.xsd b/docs/specs/swh.xsd
--- a/docs/specs/swh.xsd
+++ b/docs/specs/swh.xsd
@@ -7,6 +7,12 @@
<xsd:element name="deposit">
<xsd:complexType>
<xsd:choice>
+ <!-- code deposit on a new origin -->
+ <xsd:element name="create_origin" >
+ <xsd:complexType>
+ <xsd:element ref="swh:origin" />
+ </xsd:complexType>
+ </xsd:element>
<!-- metadata-only deposit -->
<xsd:element name="reference">
diff --git a/docs/user-manual.rst b/docs/user-manual.rst
--- a/docs/user-manual.rst
+++ b/docs/user-manual.rst
@@ -98,7 +98,8 @@
(deposit)$ cat metadata.xml
<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
- xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0">
+ xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit">
<title>Verifiable online voting system</title>
<id>belenios-01243065</id>
<codemeta:url>https://gitlab.inria.fr/belenios/belenios</codemeta:url>
@@ -119,6 +120,11 @@
<codemeta:author>
<codemeta:name>Belenios Test User</codemeta:name>
</codemeta:author>
+ <swh:deposit>
+ <swh:create_origin>
+ <swh:origin url="http://has.archives-ouvertes.fr/test-01243065" />
+ </swh:create_origin>
+ </swh:deposit>
</entry>
(deposit)$
diff --git a/swh/deposit/api/common.py b/swh/deposit/api/common.py
--- a/swh/deposit/api/common.py
+++ b/swh/deposit/api/common.py
@@ -728,7 +728,7 @@
"Please ensure your metadata file is correctly formatted.",
)
- if not metadata:
+ if metadata is None:
raise DepositError(
BAD_REQUEST,
"Empty body request is not supported",
@@ -736,18 +736,30 @@
"If the body is empty, there is no metadata.",
)
- if (
- "atom:external_identifier" in metadata
- and headers.slug
- and metadata["atom:external_identifier"] != headers.slug
- ):
- # TODO: When clients stopped using it, raise this error
- # even when they are equal.
- raise DepositError(
- BAD_REQUEST,
- "The 'external_identifier' tag is deprecated, "
- "the Slug header should be used instead.",
- )
+ create_origin = metadata.get("swh:deposit", {}).get("swh:create_origin")
+ if create_origin:
+ origin_url = create_origin["swh:origin"]["@url"]
+ deposit.origin_url = origin_url
+
+ if "atom:external_identifier" in metadata:
+ # Deprecated tag.
+ # When clients stopped using it, this should raise an error
+ # unconditionally
+
+ if deposit.origin_url:
+ raise DepositError(
+ BAD_REQUEST,
+ "<external_identifier> is deprecated, you should only use "
+ "<swh:create_origin> from now on.",
+ )
+
+ if headers.slug and metadata["atom:external_identifier"] != headers.slug:
+ raise DepositError(
+ BAD_REQUEST,
+ "The 'external_identifier' tag is deprecated, "
+ "the Slug header should be used instead.",
+ )
+
# Determine if we are in the metadata-only deposit case
try:
swhid = parse_swh_reference(metadata)
@@ -756,6 +768,16 @@
PARSING_ERROR, "Invalid SWHID reference", str(e),
)
+ if swhid is not None and (
+ deposit.origin_url or deposit.parent or deposit.external_id
+ ):
+ raise DepositError(
+ BAD_REQUEST,
+ "<swh:reference> is for metadata-only deposits and "
+ "<swh:create_origin> / Slug are for code deposits, "
+ "only one may be used on a given deposit.",
+ )
+
self._deposit_put(
deposit=deposit, in_progress=headers.in_progress,
)
diff --git a/swh/deposit/tests/api/test_collection.py b/swh/deposit/tests/api/test_collection.py
--- a/swh/deposit/tests/api/test_collection.py
+++ b/swh/deposit/tests/api/test_collection.py
@@ -105,23 +105,28 @@
def test_add_deposit_when_partial_makes_new_deposit(
- authenticated_client, deposit_collection, partial_deposit, atom_dataset
+ authenticated_client,
+ deposit_collection,
+ partial_deposit,
+ atom_dataset,
+ deposit_user,
):
"""Posting deposit on collection when previous is partial makes new deposit
"""
deposit = partial_deposit
assert deposit.status == DEPOSIT_STATUS_PARTIAL
+ origin_url = deposit_user.provider_url + deposit.external_id
# adding a new deposit with the same external id
response = authenticated_client.post(
reverse(COL_IRI, args=[deposit_collection.name]),
content_type="application/atom+xml;type=entry",
- data=atom_dataset["entry-data0"],
+ data=atom_dataset["entry-data0"] % origin_url,
HTTP_SLUG=deposit.external_id,
)
- assert response.status_code == status.HTTP_201_CREATED
+ assert response.status_code == status.HTTP_201_CREATED, response.content.decode()
response_content = parse_xml(BytesIO(response.content))
deposit_id = response_content["swh:deposit_id"]
@@ -133,7 +138,7 @@
def test_add_deposit_when_failed_makes_new_deposit_with_no_parent(
- authenticated_client, deposit_collection, failed_deposit, atom_dataset
+ authenticated_client, deposit_collection, failed_deposit, atom_dataset, deposit_user
):
"""Posting deposit on collection when deposit done makes new deposit with
parent
@@ -141,13 +146,14 @@
"""
deposit = failed_deposit
assert deposit.status == DEPOSIT_STATUS_LOAD_FAILURE
+ origin_url = deposit_user.provider_url + deposit.external_id
# adding a new deposit with the same external id as a completed deposit
# creates the parenting chain
response = authenticated_client.post(
reverse(COL_IRI, args=[deposit_collection.name]),
content_type="application/atom+xml;type=entry",
- data=atom_dataset["entry-data0"],
+ data=atom_dataset["entry-data0"] % origin_url,
HTTP_SLUG=deposit.external_id,
)
@@ -163,7 +169,11 @@
def test_add_deposit_when_done_makes_new_deposit_with_parent_old_one(
- authenticated_client, deposit_collection, completed_deposit, atom_dataset
+ authenticated_client,
+ deposit_collection,
+ completed_deposit,
+ atom_dataset,
+ deposit_user,
):
"""Posting deposit on collection when deposit done makes new deposit with
parent
@@ -172,13 +182,14 @@
# given multiple deposit already loaded
deposit = completed_deposit
assert deposit.status == DEPOSIT_STATUS_LOAD_SUCCESS
+ origin_url = deposit_user.provider_url + deposit.external_id
# adding a new deposit with the same external id as a completed deposit
# creates the parenting chain
response = authenticated_client.post(
reverse(COL_IRI, args=[deposit_collection.name]),
content_type="application/atom+xml;type=entry",
- data=atom_dataset["entry-data0"],
+ data=atom_dataset["entry-data0"] % origin_url,
HTTP_SLUG=deposit.external_id,
)
@@ -190,7 +201,7 @@
new_deposit = Deposit.objects.get(pk=deposit_id)
assert deposit.collection == new_deposit.collection
- assert deposit.external_id == new_deposit.external_id
+ assert deposit.origin_url == origin_url
assert new_deposit != deposit
assert new_deposit.parent == deposit
@@ -203,12 +214,14 @@
deposit_another_collection,
atom_dataset,
sample_archive,
+ deposit_user,
):
"""Posting a deposit with an external_id conflicting with an external_id
of a different client does not create a parent relationship
"""
external_id = "foobar"
+ origin_url = deposit_user.provider_url + external_id
# create a deposit for that other user, with the same slug
other_deposit = create_deposit(
@@ -223,7 +236,7 @@
response = authenticated_client.post(
reverse(COL_IRI, args=[deposit_collection.name]),
content_type="application/atom+xml;type=entry",
- data=atom_dataset["entry-data0"],
+ data=atom_dataset["entry-data0"] % origin_url,
HTTP_SLUG=external_id,
)
@@ -246,6 +259,7 @@
completed_deposit,
atom_dataset,
sample_archive,
+ deposit_user,
):
"""Posting a deposit with an external_id conflicting with an external_id
of a different client creates a parent relationship with the deposit
@@ -255,6 +269,7 @@
# given multiple deposit already loaded
deposit = completed_deposit
assert deposit.status == DEPOSIT_STATUS_LOAD_SUCCESS
+ origin_url = deposit_user.provider_url + deposit.external_id
# create a deposit for that other user, with the same slug
other_deposit = create_deposit(
@@ -269,7 +284,7 @@
response = authenticated_client.post(
reverse(COL_IRI, args=[deposit_collection.name]),
content_type="application/atom+xml;type=entry",
- data=atom_dataset["entry-data0"],
+ data=atom_dataset["entry-data0"] % origin_url,
HTTP_SLUG=deposit.external_id,
)
diff --git a/swh/deposit/tests/api/test_collection_post_atom.py b/swh/deposit/tests/api/test_collection_post_atom.py
--- a/swh/deposit/tests/api/test_collection_post_atom.py
+++ b/swh/deposit/tests/api/test_collection_post_atom.py
@@ -34,7 +34,7 @@
)
# then
- assert response.status_code == status.HTTP_201_CREATED
+ assert response.status_code == status.HTTP_201_CREATED, response.content.decode()
response_content = parse_xml(BytesIO(response.content))
deposit_id = response_content["swh:deposit_id"]
@@ -99,19 +99,49 @@
def test_post_deposit_atom_no_slug_header(
authenticated_client, deposit_collection, deposit_user, atom_dataset, mocker
):
- """Posting an atom entry without a slug header should generate one
+ """Posting an atom entry with a slug header but no origin url generates
+ an origin url from the slug
"""
url = reverse(COL_IRI, args=[deposit_collection.name])
- id_ = str(uuid.uuid4())
- mocker.patch("uuid.uuid4", return_value=id_)
+ slug = str(uuid.uuid4())
# when
response = authenticated_client.post(
url,
content_type="application/atom+xml;type=entry",
- data=atom_dataset["entry-data0"],
+ data=atom_dataset["entry-data-no-origin-url"],
+ HTTP_IN_PROGRESS="false",
+ HTTP_SLUG=slug,
+ )
+
+ assert response.status_code == status.HTTP_201_CREATED
+ response_content = parse_xml(BytesIO(response.content))
+ deposit_id = response_content["swh:deposit_id"]
+
+ deposit = Deposit.objects.get(pk=deposit_id)
+ assert deposit.collection == deposit_collection
+ assert deposit.origin_url == deposit_user.provider_url + slug
+ assert deposit.status == DEPOSIT_STATUS_DEPOSITED
+
+
+def test_post_deposit_atom_no_origin_url_nor_slug_header(
+ authenticated_client, deposit_collection, deposit_user, atom_dataset, mocker
+):
+ """Posting an atom entry without an origin url or a slug header should generate one
+
+ """
+ url = reverse(COL_IRI, args=[deposit_collection.name])
+
+ slug = str(uuid.uuid4())
+ mocker.patch("uuid.uuid4", return_value=slug)
+
+ # when
+ response = authenticated_client.post(
+ url,
+ content_type="application/atom+xml;type=entry",
+ data=atom_dataset["entry-data-no-origin-url"],
# + headers
HTTP_IN_PROGRESS="false",
)
@@ -122,7 +152,7 @@
deposit = Deposit.objects.get(pk=deposit_id)
assert deposit.collection == deposit_collection
- assert deposit.origin_url == deposit_user.provider_url + id_
+ assert deposit.origin_url == deposit_user.provider_url + slug
assert deposit.status == DEPOSIT_STATUS_DEPOSITED
@@ -132,13 +162,14 @@
"""Posting an atom entry without a slug header should return a 400
"""
+ external_id = "foobar"
url = reverse(COL_IRI, args=[deposit_collection.name])
# when
response = authenticated_client.post(
url,
content_type="application/atom+xml;type=entry",
- data=atom_dataset["error-with-external-identifier"],
+ data=atom_dataset["error-with-external-identifier"] % external_id,
# + headers
HTTP_IN_PROGRESS="false",
HTTP_SLUG="something",
@@ -148,6 +179,61 @@
assert response.status_code == status.HTTP_400_BAD_REQUEST
+def test_post_deposit_atom_with_create_origin_and_external_identifier(
+ authenticated_client, deposit_collection, atom_dataset, deposit_user
+):
+ """<atom:external_identifier> was deprecated before <swh:create_origin>
+ was introduced, clients should get an error when trying to use both
+
+ """
+ external_id = "foobar"
+ origin_url = deposit_user.provider_url + external_id
+ url = reverse(COL_IRI, args=[deposit_collection.name])
+
+ document = atom_dataset["error-with-external-identifier-and-create-origin"].format(
+ external_id=external_id, url=origin_url,
+ )
+
+ # when
+ response = authenticated_client.post(
+ url,
+ content_type="application/atom+xml;type=entry",
+ data=document,
+ # + headers
+ HTTP_IN_PROGRESS="false",
+ )
+
+ assert b"<external_identifier> is deprecated" in response.content
+ assert response.status_code == status.HTTP_400_BAD_REQUEST
+
+
+def test_post_deposit_atom_with_create_origin_and_reference(
+ authenticated_client, deposit_collection, atom_dataset, deposit_user
+):
+ """<swh:reference> and <swh:create_origin> are mutually exclusive
+
+ """
+ external_id = "foobar"
+ origin_url = deposit_user.provider_url + external_id
+ url = reverse(COL_IRI, args=[deposit_collection.name])
+
+ document = atom_dataset["error-with-reference-and-create-origin"].format(
+ external_id=external_id, url=origin_url,
+ )
+
+ # when
+ response = authenticated_client.post(
+ url,
+ content_type="application/atom+xml;type=entry",
+ data=document,
+ # + headers
+ HTTP_IN_PROGRESS="false",
+ )
+
+ assert b"only one may be used on a given deposit" in response.content
+ assert response.status_code == status.HTTP_400_BAD_REQUEST
+
+
def test_post_deposit_atom_unknown_collection(authenticated_client, atom_dataset):
"""Posting an atom entry to an unknown collection should return a 404
@@ -167,37 +253,36 @@
def test_post_deposit_atom_entry_initial(
- authenticated_client, deposit_collection, atom_dataset
+ authenticated_client, deposit_collection, atom_dataset, deposit_user
):
"""Posting an initial atom entry should return 201 with deposit receipt
"""
# given
- external_id = "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a"
+ origin_url = deposit_user.provider_url + "1225c695-cfb8-4ebb-aaaa-80da344efa6a"
with pytest.raises(Deposit.DoesNotExist):
- Deposit.objects.get(external_id=external_id)
+ Deposit.objects.get(origin_url=origin_url)
- atom_entry_data = atom_dataset["entry-data0"]
+ atom_entry_data = atom_dataset["entry-data0"] % origin_url
# when
response = authenticated_client.post(
reverse(COL_IRI, args=[deposit_collection.name]),
content_type="application/atom+xml;type=entry",
data=atom_entry_data,
- HTTP_SLUG=external_id,
HTTP_IN_PROGRESS="false",
)
# then
- assert response.status_code == status.HTTP_201_CREATED
+ assert response.status_code == status.HTTP_201_CREATED, response.content.decode()
response_content = parse_xml(BytesIO(response.content))
deposit_id = response_content["swh:deposit_id"]
deposit = Deposit.objects.get(pk=deposit_id)
assert deposit.collection == deposit_collection
- assert deposit.external_id == external_id
+ assert deposit.origin_url == origin_url
assert deposit.status == DEPOSIT_STATUS_DEPOSITED
# one associated request to a deposit
@@ -208,24 +293,23 @@
def test_post_deposit_atom_entry_with_codemeta(
- authenticated_client, deposit_collection, atom_dataset
+ authenticated_client, deposit_collection, atom_dataset, deposit_user
):
"""Posting an initial atom entry should return 201 with deposit receipt
"""
# given
- external_id = "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a"
+ origin_url = deposit_user.provider_url + "1225c695-cfb8-4ebb-aaaa-80da344efa6a"
with pytest.raises(Deposit.DoesNotExist):
- Deposit.objects.get(external_id=external_id)
+ Deposit.objects.get(origin_url=origin_url)
- atom_entry_data = atom_dataset["codemeta-sample"]
+ atom_entry_data = atom_dataset["codemeta-sample"] % origin_url
# when
response = authenticated_client.post(
reverse(COL_IRI, args=[deposit_collection.name]),
content_type="application/atom+xml;type=entry",
data=atom_entry_data,
- HTTP_SLUG=external_id,
HTTP_IN_PROGRESS="false",
)
@@ -238,7 +322,7 @@
deposit = Deposit.objects.get(pk=deposit_id)
assert deposit.collection == deposit_collection
- assert deposit.external_id == external_id
+ assert deposit.origin_url == origin_url
assert deposit.status == DEPOSIT_STATUS_DEPOSITED
# one associated request to a deposit
@@ -249,16 +333,16 @@
def test_post_deposit_atom_entry_multiple_steps(
- authenticated_client, deposit_collection, atom_dataset
+ authenticated_client, deposit_collection, atom_dataset, deposit_user
):
"""After initial deposit, updating a deposit should return a 201
"""
# given
- external_id = "urn:uuid:2225c695-cfb8-4ebb-aaaa-80da344efa6a"
+ origin_url = deposit_user.provider_url + "2225c695-cfb8-4ebb-aaaa-80da344efa6a"
with pytest.raises(Deposit.DoesNotExist):
- deposit = Deposit.objects.get(external_id=external_id)
+ deposit = Deposit.objects.get(origin_url=origin_url)
# when
response = authenticated_client.post(
@@ -266,7 +350,6 @@
content_type="application/atom+xml;type=entry",
data=atom_dataset["entry-data1"],
HTTP_IN_PROGRESS="True",
- HTTP_SLUG=external_id,
)
# then
@@ -277,14 +360,14 @@
deposit = Deposit.objects.get(pk=deposit_id)
assert deposit.collection == deposit_collection
- assert deposit.external_id == external_id
+ assert deposit.origin_url is None # not provided yet
assert deposit.status == "partial"
# one associated request to a deposit
deposit_requests = DepositRequest.objects.filter(deposit=deposit)
assert len(deposit_requests) == 1
- atom_entry_data = atom_dataset["entry-data-minimal"]
+ atom_entry_data = atom_dataset["entry-only-create-origin"] % (origin_url)
for link in response_content["atom:link"]:
if link["@rel"] == "http://purl.org/net/sword/terms/add":
@@ -302,14 +385,14 @@
)
# then
- assert response.status_code == status.HTTP_201_CREATED, response.content
+ assert response.status_code == status.HTTP_201_CREATED, response.content.decode()
response_content = parse_xml(BytesIO(response.content))
deposit_id = int(response_content["swh:deposit_id"])
deposit = Deposit.objects.get(pk=deposit_id)
assert deposit.collection == deposit_collection
- assert deposit.external_id == external_id
+ assert deposit.origin_url == origin_url
assert deposit.status == DEPOSIT_STATUS_DEPOSITED
assert len(Deposit.objects.all()) == 1
diff --git a/swh/deposit/tests/api/test_deposit_private_read_metadata.py b/swh/deposit/tests/api/test_deposit_private_read_metadata.py
--- a/swh/deposit/tests/api/test_deposit_private_read_metadata.py
+++ b/swh/deposit/tests/api/test_deposit_private_read_metadata.py
@@ -341,7 +341,10 @@
actual_data = response.json()
assert actual_data == {
- "origin": {"type": "deposit", "url": None,},
+ "origin": {
+ "type": "deposit",
+ "url": "https://hal-test.archives-ouvertes.fr/hal-01243065",
+ },
"metadata_raw": [codemeta_entry_data],
"metadata_dict": parse_xml(codemeta_entry_data),
"provider": {
diff --git a/swh/deposit/tests/api/test_deposit_update.py b/swh/deposit/tests/api/test_deposit_update.py
--- a/swh/deposit/tests/api/test_deposit_update.py
+++ b/swh/deposit/tests/api/test_deposit_update.py
@@ -12,6 +12,7 @@
from swh.deposit.api.common import ACCEPT_ARCHIVE_CONTENT_TYPES
from swh.deposit.config import (
+ COL_IRI,
DEPOSIT_STATUS_DEPOSITED,
DEPOSIT_STATUS_PARTIAL,
EDIT_IRI,
@@ -105,13 +106,15 @@
partial_deposit_with_metadata,
deposit_collection,
atom_dataset,
+ deposit_user,
):
"""Replace all metadata with another one should return a 204 response
"""
# given
deposit = partial_deposit_with_metadata
- raw_metadata0 = atom_dataset["entry-data0"]
+ origin_url = deposit_user.provider_url + deposit.external_id
+ raw_metadata0 = atom_dataset["entry-data0"] % origin_url
requests_meta = DepositRequest.objects.filter(deposit=deposit, type="metadata")
assert len(requests_meta) == 1
@@ -210,11 +213,13 @@
deposit_collection,
partial_deposit_with_metadata,
atom_dataset,
+ deposit_user,
):
"""Add metadata with another one should return a 204 response
"""
deposit = partial_deposit_with_metadata
+ origin_url = deposit_user.provider_url + deposit.external_id
requests = DepositRequest.objects.filter(deposit=deposit, type="metadata")
assert len(requests) == 1
@@ -236,7 +241,7 @@
)
assert len(requests) == 2
- expected_raw_meta0 = atom_dataset["entry-data0"]
+ expected_raw_meta0 = atom_dataset["entry-data0"] % origin_url
# a new one was added
assert requests[0].raw_metadata == expected_raw_meta0
assert requests[1].raw_metadata == atom_entry
@@ -253,6 +258,7 @@
partial_deposit_with_metadata,
atom_dataset,
sample_archive,
+ deposit_user,
):
"""Scenario: Add both a new archive and new metadata to a partial deposit is ok
@@ -260,6 +266,7 @@
"""
deposit = partial_deposit_with_metadata
+ origin_url = deposit_user.provider_url + deposit.external_id
requests = DepositRequest.objects.filter(deposit=deposit, type="metadata")
assert len(requests) == 1
@@ -299,7 +306,7 @@
)
assert len(requests) == 1 + 1, "New deposit request archive got added"
- expected_raw_meta0 = atom_dataset["entry-data0"]
+ expected_raw_meta0 = atom_dataset["entry-data0"] % origin_url
# a new one was added
assert requests[0].raw_metadata == expected_raw_meta0
assert requests[1].raw_metadata == data_atom_entry
@@ -508,6 +515,7 @@
deposit_collection,
atom_dataset,
sample_archive,
+ deposit_user,
):
"""Scenario: Replace metadata and archive(s) with new ones should be ok
@@ -516,7 +524,8 @@
"""
# given
deposit = partial_deposit_with_metadata
- raw_metadata0 = atom_dataset["entry-data0"]
+ origin_url = deposit_user.provider_url + deposit.external_id
+ raw_metadata0 = atom_dataset["entry-data0"] % origin_url
requests_meta = DepositRequest.objects.filter(deposit=deposit, type="metadata")
assert len(requests_meta) == 1
@@ -792,3 +801,84 @@
b"- Mandatory alternate fields are missing (atom:name or atom:title)"
in response.content
)
+
+
+def test_put_atom_with_create_origin_and_external_identifier(
+ authenticated_client, deposit_collection, atom_dataset, deposit_user
+):
+ """<atom:external_identifier> was deprecated before <swh:create_origin>
+ was introduced, clients should get an error when trying to use both
+
+ """
+ external_id = "foobar"
+ origin_url = deposit_user.provider_url + external_id
+ url = reverse(COL_IRI, args=[deposit_collection.name])
+
+ response = authenticated_client.post(
+ url,
+ content_type="application/atom+xml;type=entry",
+ data=atom_dataset["entry-data0"] % origin_url,
+ HTTP_IN_PROGRESS="true",
+ )
+
+ assert response.status_code == status.HTTP_201_CREATED
+ response_content = parse_xml(BytesIO(response.content))
+
+ for link in response_content["atom:link"]:
+ if link["@rel"] == "edit":
+ edit_iri = link["@href"]
+ break
+ else:
+ assert False, response_content
+
+ # when
+ response = authenticated_client.put(
+ edit_iri,
+ content_type="application/atom+xml;type=entry",
+ data=atom_dataset["error-with-external-identifier"] % external_id,
+ # + headers
+ HTTP_IN_PROGRESS="false",
+ )
+
+ assert b"<external_identifier> is deprecated" in response.content
+ assert response.status_code == status.HTTP_400_BAD_REQUEST
+
+
+def test_put_atom_with_create_origin_and_reference(
+ authenticated_client, deposit_collection, atom_dataset, deposit_user
+):
+ """<swh:reference> and <swh:create_origin> are mutually exclusive
+
+ """
+ external_id = "foobar"
+ origin_url = deposit_user.provider_url + external_id
+ url = reverse(COL_IRI, args=[deposit_collection.name])
+
+ response = authenticated_client.post(
+ url,
+ content_type="application/atom+xml;type=entry",
+ data=atom_dataset["entry-data0"] % origin_url,
+ HTTP_IN_PROGRESS="true",
+ )
+
+ assert response.status_code == status.HTTP_201_CREATED
+ response_content = parse_xml(BytesIO(response.content))
+
+ for link in response_content["atom:link"]:
+ if link["@rel"] == "edit":
+ edit_iri = link["@href"]
+ break
+ else:
+ assert False, response_content
+
+ # when
+ response = authenticated_client.put(
+ edit_iri,
+ content_type="application/atom+xml;type=entry",
+ data=atom_dataset["entry-data-with-origin-reference"].format(url=origin_url),
+ # + headers
+ HTTP_IN_PROGRESS="false",
+ )
+
+ assert b"only one may be used on a given deposit" in response.content
+ assert response.status_code == status.HTTP_400_BAD_REQUEST
diff --git a/swh/deposit/tests/conftest.py b/swh/deposit/tests/conftest.py
--- a/swh/deposit/tests/conftest.py
+++ b/swh/deposit/tests/conftest.py
@@ -347,11 +347,12 @@
**kwargs,
)
+ origin_url = deposit.client.provider_url + deposit.external_id
+
response = authenticated_client.post(
reverse(SE_IRI, args=[collection_name, deposit.id]),
content_type="application/atom+xml;type=entry",
- data=atom_dataset["entry-data0"],
- HTTP_SLUG=deposit.external_id,
+ data=atom_dataset["entry-data0"] % origin_url,
HTTP_IN_PROGRESS="true",
)
diff --git a/swh/deposit/tests/data/atom/codemeta-sample.xml b/swh/deposit/tests/data/atom/codemeta-sample.xml
--- a/swh/deposit/tests/data/atom/codemeta-sample.xml
+++ b/swh/deposit/tests/data/atom/codemeta-sample.xml
@@ -1,7 +1,13 @@
<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:dcterms="http://purl.org/dc/terms/"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit"
xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0">
+ <swh:deposit>
+ <swh:create_origin>
+ <swh:origin url="%s" />
+ </swh:create_origin>
+ </swh:deposit>
<dcterms:identifier>hal-01587361</dcterms:identifier>
<dcterms:identifier>https://hal.inria.fr/hal-01587361</dcterms:identifier>
<dcterms:identifier>https://hal.inria.fr/hal-01587361/document</dcterms:identifier>
diff --git a/swh/deposit/tests/data/atom/entry-data0.xml b/swh/deposit/tests/data/atom/entry-data-no-origin-url.xml
copy from swh/deposit/tests/data/atom/entry-data0.xml
copy to swh/deposit/tests/data/atom/entry-data-no-origin-url.xml
--- a/swh/deposit/tests/data/atom/entry-data0.xml
+++ b/swh/deposit/tests/data/atom/entry-data-no-origin-url.xml
@@ -1,5 +1,6 @@
<?xml version="1.0"?>
-<entry xmlns="http://www.w3.org/2005/Atom">
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit">
<title>Awesome Compiler</title>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2017-10-07T15:17:08Z</updated>
@@ -22,3 +23,4 @@
<developmentStatus>running</developmentStatus>
<runtimePlatform>all</runtimePlatform>
</entry>
+
diff --git a/swh/deposit/tests/data/atom/entry-data-with-origin-reference.xml b/swh/deposit/tests/data/atom/entry-data-with-origin-reference.xml
new file mode 100644
--- /dev/null
+++ b/swh/deposit/tests/data/atom/entry-data-with-origin-reference.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit">
+ <title>Awesome Compiler</title>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <author>dudess</author>
+ <swh:deposit>
+ <swh:reference>
+ <swh:origin url="{url}" />
+ </swh:reference>
+ </swh:deposit>
+</entry>
diff --git a/swh/deposit/tests/data/atom/entry-data0.xml b/swh/deposit/tests/data/atom/entry-data0.xml
--- a/swh/deposit/tests/data/atom/entry-data0.xml
+++ b/swh/deposit/tests/data/atom/entry-data0.xml
@@ -1,5 +1,6 @@
<?xml version="1.0"?>
-<entry xmlns="http://www.w3.org/2005/Atom">
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit">
<title>Awesome Compiler</title>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2017-10-07T15:17:08Z</updated>
@@ -21,4 +22,10 @@
<version>0.0.1</version>
<developmentStatus>running</developmentStatus>
<runtimePlatform>all</runtimePlatform>
+
+ <swh:deposit>
+ <swh:create_origin>
+ <swh:origin url="%s" />
+ </swh:create_origin>
+ </swh:deposit>
</entry>
diff --git a/swh/deposit/tests/data/atom/entry-data2.xml b/swh/deposit/tests/data/atom/entry-data2.xml
--- a/swh/deposit/tests/data/atom/entry-data2.xml
+++ b/swh/deposit/tests/data/atom/entry-data2.xml
@@ -1,5 +1,12 @@
<?xml version="1.0"?>
-<entry xmlns="http://www.w3.org/2005/Atom">
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit">
<url>https://hal-test.archives-ouvertes.fr/some-external-id</url>
<author>some awesome author</author>
+
+ <swh:deposit>
+ <swh:create_origin>
+ <swh:origin url="https://hal-test.archives-ouvertes.fr/some-external-id" />
+ </swh:create_origin>
+ </swh:deposit>
</entry>
diff --git a/swh/deposit/tests/data/atom/entry-only-create-origin.xml b/swh/deposit/tests/data/atom/entry-only-create-origin.xml
new file mode 100644
--- /dev/null
+++ b/swh/deposit/tests/data/atom/entry-only-create-origin.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit">
+ <swh:deposit>
+ <swh:create_origin>
+ <swh:origin url="%s" />
+ </swh:create_origin>
+ </swh:deposit>
+</entry>
+
diff --git a/swh/deposit/tests/data/atom/error-with-decimal.xml b/swh/deposit/tests/data/atom/error-with-decimal.xml
--- a/swh/deposit/tests/data/atom/error-with-decimal.xml
+++ b/swh/deposit/tests/data/atom/error-with-decimal.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
-<entry xmlns="http://www.w3.org/2005/Atom" xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0">
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit">
<title>Composing a Web of Audio Applications</title>
<id>hal-01243065</id>
<codemeta:url>https://hal-test.archives-ouvertes.fr/hal-01243065</codemeta:url>
@@ -33,4 +35,10 @@
<email>someone@nice.fr</email>
<codemeta:affiliation>FFJ</codemeta:affiliation>
</contributor>
+
+ <swh:deposit>
+ <swh:create_origin>
+ <swh:origin url="https://hal-test.archives-ouvertes.fr/hal-01243065" />
+ </swh:create_origin>
+ </swh:deposit>
</entry>
diff --git a/swh/deposit/tests/data/atom/error-with-external-identifier-and-create-origin.xml b/swh/deposit/tests/data/atom/error-with-external-identifier-and-create-origin.xml
new file mode 100644
--- /dev/null
+++ b/swh/deposit/tests/data/atom/error-with-external-identifier-and-create-origin.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit">
+ <title>Composing a Web of Audio Applications</title>
+ <id>hal-01243065</id>
+ <external_identifier>{external_id}</external_identifier>
+ <author>someone</author>
+ <swh:deposit>
+ <swh:create_origin>
+ <swh:origin url="{url}" />
+ </swh:create_origin>
+ </swh:deposit>
+</entry>
diff --git a/swh/deposit/tests/data/atom/error-with-external-identifier.xml b/swh/deposit/tests/data/atom/error-with-external-identifier.xml
--- a/swh/deposit/tests/data/atom/error-with-external-identifier.xml
+++ b/swh/deposit/tests/data/atom/error-with-external-identifier.xml
@@ -2,5 +2,6 @@
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0">
<title>Composing a Web of Audio Applications</title>
<id>hal-01243065</id>
- <external_identifier>hal-01243065</external_identifier>
+ <author>someone</author>
+ <external_identifier>%s</external_identifier>
</entry>
diff --git a/swh/deposit/tests/data/atom/error-with-reference-and-create-origin.xml b/swh/deposit/tests/data/atom/error-with-reference-and-create-origin.xml
new file mode 100644
--- /dev/null
+++ b/swh/deposit/tests/data/atom/error-with-reference-and-create-origin.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit">
+ <title>Composing a Web of Audio Applications</title>
+ <id>hal-01243065</id>
+ <author>someone</author>
+ <swh:deposit>
+ <swh:create_origin>
+ <swh:origin url="{url}" />
+ </swh:create_origin>
+ <swh:reference>
+ <swh:origin url="{url}" />
+ </swh:reference>
+ </swh:deposit>
+</entry>
diff --git a/swh/deposit/tests/data/atom/metadata.xml b/swh/deposit/tests/data/atom/metadata.xml
--- a/swh/deposit/tests/data/atom/metadata.xml
+++ b/swh/deposit/tests/data/atom/metadata.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
-xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0">
+ xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0"
+ xmlns:swh="https://www.softwareheritage.org/schema/2018/deposit">
<title>Composing a Web of Audio Applications</title>
<id>hal-01243065</id>
<codemeta:url>https://hal-test.archives-ouvertes.fr/hal-01243065</codemeta:url>
@@ -26,5 +27,12 @@
<codemeta:author>
<codemeta:name>Morane Gruenpeter</codemeta:name>
</codemeta:author>
+
+ <swh:deposit>
+ <swh:create_origin>
+ <swh:origin url="https://hal-test.archives-ouvertes.fr/hal-01243065" />
+ </swh:create_origin>
+ </swh:deposit>
+
%s
</entry>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 3, 5:12 PM (3 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3230726
Attached To
D4611: Add tag <swh:create_origin>, to replace the Slug header.
Event Timeline
Log In to Comment