Page MenuHomeSoftware Heritage

D4737.diff
No OneTemporary

D4737.diff

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

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

Event Timeline