Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F7122952
D4737.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Subscribers
None
D4737.diff
View Options
diff --git a/swh/deposit/cli/client.py b/swh/deposit/cli/client.py
--- a/swh/deposit/cli/client.py
+++ b/swh/deposit/cli/client.py
@@ -486,3 +486,53 @@
click.echo(yaml.dump(data))
else:
logger.info(data)
+
+
+@deposit.command("metadata-only")
+@click.option(
+ "--url",
+ default="https://deposit.softwareheritage.org",
+ help="(Optional) Deposit server api endpoint. By default, "
+ "https://deposit.softwareheritage.org/1",
+)
+@click.option("--username", required=True, help="(Mandatory) User's name")
+@click.option(
+ "--password", required=True, help="(Mandatory) User's associated password"
+)
+@click.option(
+ "--metadata",
+ "metadata_path",
+ type=click.Path(exists=True),
+ required=True,
+ help="Path to xml metadata file",
+)
+@click.option(
+ "-f",
+ "--format",
+ "output_format",
+ default="logging",
+ type=click.Choice(["logging", "yaml", "json"]),
+ help="Output format results.",
+)
+@click.pass_context
+def metadata_only(ctx, url, username, password, metadata_path, output_format):
+ """Deposit metadata only upload
+
+ """
+ from swh.deposit.client import PublicApiDepositClient
+ from swh.deposit.utils import parse_swh_reference, parse_xml
+
+ # Parse to check for a swhid presence within the metadata file
+ with open(metadata_path, "r") as f:
+ metadata_raw = f.read()
+ actual_swhid = parse_swh_reference(parse_xml(metadata_raw))
+
+ if not actual_swhid:
+ raise InputError("A SWHID must be provided for a metadata-only deposit")
+
+ with trap_and_report_exceptions():
+ client = PublicApiDepositClient(url=_url(url), auth=(username, password))
+ collection = _collection(client)
+ result = client.deposit_metadata_only(collection, metadata_path)
+
+ print_result(result, output_format)
diff --git a/swh/deposit/client.py b/swh/deposit/client.py
--- a/swh/deposit/client.py
+++ b/swh/deposit/client.py
@@ -545,6 +545,28 @@
return "put"
+class CreateMetadataOnlyDepositClient(BaseCreateDepositClient):
+ """Create metadata-only deposit."""
+
+ def compute_information(self, *args, **kwargs) -> Dict[str, Any]:
+ return {
+ "headers": {"CONTENT-TYPE": "application/atom+xml;type=entry",},
+ "filepath": kwargs["metadata_path"],
+ }
+
+ def parse_result_ok(self, xml_content):
+ """Given an xml content as string, returns a deposit dict.
+
+ """
+ data = parse_xml(xml_content)
+ keys = [
+ "deposit_id",
+ "deposit_status",
+ "deposit_date",
+ ]
+ return {key: data.get("swh:" + key) for key in keys}
+
+
class CreateMultipartDepositClient(BaseCreateDepositClient):
"""Create a multipart deposit client."""
@@ -712,3 +734,11 @@
if "error" in r:
return r
return self.deposit_status(collection, deposit_id)
+
+ def deposit_metadata_only(
+ self, collection: str, metadata: Optional[str] = None,
+ ):
+ assert metadata is not None
+ return CreateMetadataOnlyDepositClient(
+ url=self.base_url, auth=self.auth
+ ).execute(collection, metadata_path=metadata)
diff --git a/swh/deposit/tests/cli/test_client.py b/swh/deposit/tests/cli/test_client.py
--- a/swh/deposit/tests/cli/test_client.py
+++ b/swh/deposit/tests/cli/test_client.py
@@ -25,6 +25,7 @@
)
from swh.deposit.client import MaintenanceError, PublicApiDepositClient
from swh.deposit.parsers import parse_xml
+from swh.model.exceptions import ValidationError
from ..conftest import TEST_USER
@@ -637,3 +638,103 @@
"deposit_status": "partial",
"deposit_id": 321,
}
+
+
+def test_cli_metadata_only_deposit_full_metadata_file(
+ datadir, requests_mock_datadir, cli_runner, atom_dataset, tmp_path,
+):
+ """Post metadata-only deposit through cli
+
+ The metadata file posted by the client already contains the swhid
+
+ """
+ api_url_basename = "deposit.test.metadataonly"
+ swhid = "swh:1:dir:ef04a768181417fbc5eef4243e2507915f24deea"
+ metadata = atom_dataset["entry-data-with-swhid"].format(swhid=swhid)
+ metadata_path = os.path.join(tmp_path, "entry-data-with-swhid.xml")
+ with open(metadata_path, "w") as m:
+ m.write(metadata)
+
+ expected_deposit_status = {
+ "deposit_id": "100",
+ "deposit_status": "done",
+ "deposit_date": "2020-10-08T13:52:34.509655",
+ }
+
+ assert expected_deposit_status["deposit_status"] == "done"
+
+ # fmt: off
+ result = cli_runner.invoke(
+ cli,
+ [
+ "metadata-only",
+ "--url", f"https://{api_url_basename}/1",
+ "--username", TEST_USER["username"],
+ "--password", TEST_USER["password"],
+ "--metadata", metadata_path,
+ "--format", "json",
+ ],
+ )
+ # fmt: on
+ assert result.exit_code == 0, result.output
+ actual_deposit_status = json.loads(result.output)
+ assert "error" not in actual_deposit_status
+ assert actual_deposit_status == expected_deposit_status
+
+
+def test_cli_metadata_only_deposit_invalid_swhid(
+ datadir, requests_mock_datadir, cli_runner, atom_dataset, tmp_path,
+):
+ """Post metadata-only deposit through cli with invalid swhid raises
+
+ """
+ api_url_basename = "deposit.test.metadataonly"
+ invalid_swhid = "ssh:2:sth:xxx"
+ metadata = atom_dataset["entry-data-with-swhid"].format(swhid=invalid_swhid)
+ metadata_path = os.path.join(tmp_path, "entry-data-with-swhid.xml")
+ with open(metadata_path, "w") as f:
+ f.write(metadata)
+
+ # fmt: off
+ with pytest.raises(ValidationError, match="Invalid"):
+ cli_runner.invoke(
+ cli,
+ [
+ "metadata-only",
+ "--url", f"https://{api_url_basename}/1",
+ "--username", TEST_USER["username"],
+ "--password", TEST_USER["password"],
+ "--metadata", metadata_path,
+ "--format", "json",
+ ],
+ catch_exceptions=False,
+ )
+ # fmt: on
+
+
+def test_cli_metadata_only_deposit_no_swhid(
+ datadir, requests_mock_datadir, cli_runner, atom_dataset, tmp_path,
+):
+ """Post metadata-only deposit through cli with invalid swhid raises
+
+ """
+ api_url_basename = "deposit.test.metadataonly"
+ metadata = atom_dataset["entry-data-minimal"]
+ metadata_path = os.path.join(tmp_path, "entry-data-minimal.xml")
+ with open(metadata_path, "w") as f:
+ f.write(metadata)
+
+ with pytest.raises(InputError, match="SWHID must be provided"):
+ cli_runner.invoke(
+ cli,
+ [
+ "metadata-only",
+ "--url", f"https://{api_url_basename}/1",
+ "--username", TEST_USER["username"],
+ "--password", TEST_USER["password"],
+ "--metadata", metadata_path,
+ "--format", "json",
+ ],
+ catch_exceptions=False,
+ )
+ # fmt: on
diff --git a/swh/deposit/tests/data/https_deposit.test.metadataonly/1_servicedocument b/swh/deposit/tests/data/https_deposit.test.metadataonly/1_servicedocument
new file mode 100644
--- /dev/null
+++ b/swh/deposit/tests/data/https_deposit.test.metadataonly/1_servicedocument
@@ -0,0 +1,26 @@
+<?xml version="1.0" ?>
+<service xmlns:dcterms="http://purl.org/dc/terms/"
+ xmlns:sword="http://purl.org/net/sword/terms/"
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ xmlns="http://www.w3.org/2007/app">
+
+ <sword:version>2.0</sword:version>
+ <sword:maxUploadSize>209715200</sword:maxUploadSize>
+
+ <workspace>
+ <atom:title>The Software Heritage (SWH) Archive</atom:title>
+ <collection href="test">
+ <atom:title>test Software Collection</atom:title>
+ <accept>application/zip</accept>
+ <accept>application/x-tar</accept>
+ <sword:collectionPolicy>Collection Policy</sword:collectionPolicy>
+ <dcterms:abstract>Software Heritage Archive</dcterms:abstract>
+ <sword:treatment>Collect, Preserve, Share</sword:treatment>
+ <sword:mediation>false</sword:mediation>
+ <sword:metadataRelevantHeader>false</sword:metadataRelevantHeader>
+ <sword:acceptPackaging>http://purl.org/net/sword/package/SimpleZip</sword:acceptPackaging>
+ <sword:service>https://deposit.test.metadataonly/1/test/</sword:service>
+ <sword:name>test</sword:name>
+ </collection>
+ </workspace>
+</service>
diff --git a/swh/deposit/tests/data/https_deposit.test.metadataonly/1_test b/swh/deposit/tests/data/https_deposit.test.metadataonly/1_test
new file mode 100644
--- /dev/null
+++ b/swh/deposit/tests/data/https_deposit.test.metadataonly/1_test
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<entry xmlns="http://www.w3.org/2005/Atom"
+ xmlns:sword="http://purl.org/net/sword/terms/"
+ xmlns:dcterms="http://purl.org/dc/terms/"
+ xmlns:sd="https://www.softwareheritage.org/schema/2018/deposit">
+ <sd:deposit_id>100</sd:deposit_id>
+ <sd:deposit_date>2020-10-08T13:52:34.509655</sd:deposit_date>
+ <sd:deposit_status>done</sd:deposit_status>
+ <sd:deposit_swh_id>swh:1:dir:ef04a768181417fbc5eef4243e2507915f24deea</sd:deposit_swh_id>
+ <sd:deposit_swh_id_context>swh:1:dir:ef04a768181417fbc5eef4243e2507915f24deea;origin=https://www.softwareheritage.org/check-deposit-2020-10-08T13:52:34.509655;visit=swh:1:snp:c477c6ef51833127b13a86ece7d75e5b3cc4e93d;anchor=swh:1:rev:f26f3960c175f15f6e24200171d446b86f6f7230;path=/</sd:deposit_swh_id_context>
+
+</entry>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Dec 17, 1:08 PM (3 d, 4 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3214662
Attached To
D4737: Allow metadata-only deposit client side
Event Timeline
Log In to Comment