Page MenuHomeSoftware Heritage

D6316.id23039.diff
No OneTemporary

D6316.id23039.diff

diff --git a/swh/lister/opam/lister.py b/swh/lister/opam/lister.py
--- a/swh/lister/opam/lister.py
+++ b/swh/lister/opam/lister.py
@@ -7,7 +7,7 @@
import logging
import os
from subprocess import PIPE, Popen, call
-from typing import Iterator, Optional
+from typing import Any, Dict, Iterator, Optional
from swh.lister.pattern import StatelessLister
from swh.scheduler.interface import SchedulerInterface
@@ -53,24 +53,12 @@
self.env = os.environ.copy()
# Opam root folder is initialized in the :meth:`get_pages` method as no
# side-effect should happen in the constructor to ease instantiation
- self.opamroot = os.path.join(opam_root, self.instance)
+ self.opam_root = opam_root
def get_pages(self) -> Iterator[PageType]:
- # Initialize the opam root directory with the opam instance data to list.
- call(
- [
- "opam",
- "init",
- "--reinit",
- "--bare",
- "--no-setup",
- "--root",
- self.opamroot,
- self.instance,
- self.url,
- ],
- env=self.env,
- )
+ # Initialize the opam root directory
+ opam_init(self.opam_root, self.instance, self.url, self.env)
+
# Actually list opam instance data
proc = Popen(
[
@@ -78,10 +66,11 @@
"list",
"--all",
"--no-switch",
+ "--safe",
"--repos",
self.instance,
"--root",
- self.opamroot,
+ self.opam_root,
"--normalise",
"--short",
],
@@ -103,9 +92,50 @@
url=url,
last_update=None,
extra_loader_arguments={
- "opam_root": self.opamroot,
+ "opam_root": self.opam_root,
"opam_instance": self.instance,
"opam_url": self.url,
"opam_package": page,
},
)
+
+
+def opam_init(opam_root: str, instance: str, url: str, env: Dict[str, Any]) -> None:
+ """Initialize an opam_root folder.
+
+ Args:
+ opam_root: The opam root folder to initialize
+ instance: Name of the opam repository to add or initialize
+ url: The associated url of the opam repository to add or initialize
+ env: The global environment to use for the opam command.
+
+ Returns:
+ None.
+
+ """
+ if not os.path.exists(opam_root) or not os.listdir(opam_root):
+ command = [
+ "opam",
+ "init",
+ "--reinit",
+ "--bare",
+ "--no-setup",
+ "--root",
+ opam_root,
+ instance,
+ url,
+ ]
+ else:
+ # The repository exists and is populated, we just add another instance in the
+ # repository. If it's already setup, it's a noop
+ command = [
+ "opam",
+ "repository",
+ "add",
+ "--root",
+ opam_root,
+ instance,
+ url,
+ ]
+ # Actually execute the command
+ call(command, env=env)
diff --git a/swh/lister/opam/tests/test_lister.py b/swh/lister/opam/tests/test_lister.py
--- a/swh/lister/opam/tests/test_lister.py
+++ b/swh/lister/opam/tests/test_lister.py
@@ -4,12 +4,13 @@
# See top-level LICENSE file for more information
import io
+import os
from tempfile import mkdtemp
from unittest.mock import MagicMock
import pytest
-from swh.lister.opam.lister import OpamLister
+from swh.lister.opam.lister import OpamLister, opam_init
module_name = "swh.lister.opam.lister"
@@ -29,6 +30,45 @@
return mock_init, mock_open
+def test_mock_init_repository_init(mock_opam, tmp_path, datadir):
+ """Initializing opam root directory with an instance should be ok
+
+ """
+ mock_init, mock_popen = mock_opam
+
+ instance = "fake"
+ instance_url = f"file://{datadir}/{instance}"
+ opam_root = str(tmp_path / "test-opam")
+ assert not os.path.exists(opam_root)
+
+ # This will initialize an opam directory with the instance
+ opam_init(opam_root, instance, instance_url, {})
+
+ assert mock_init.called
+
+
+def test_mock_init_repository_update(mock_opam, tmp_path, datadir):
+ """Updating opam root directory with another instance should be ok
+
+ """
+ mock_init, mock_popen = mock_opam
+
+ instance = "fake_opam_repo"
+ instance_url = f"file://{datadir}/{instance}"
+ opam_root = str(tmp_path / "test-opam")
+
+ os.makedirs(opam_root, exist_ok=True)
+ with open(os.path.join(opam_root, "opam"), "w") as f:
+ f.write("one file to avoid empty folder")
+
+ assert os.path.exists(opam_root)
+ assert os.listdir(opam_root) == ["opam"] # not empty
+ # This will update the repository opam with another instance
+ opam_init(opam_root, instance, instance_url, {})
+
+ assert mock_init.called
+
+
def test_lister_opam_optional_instance(swh_scheduler):
"""Instance name should be optional and default to be built out of the netloc."""
netloc = "opam.ocaml.org"
@@ -36,21 +76,19 @@
lister = OpamLister(swh_scheduler, url=instance_url,)
assert lister.instance == netloc
- assert lister.opamroot.endswith(lister.instance)
+ assert lister.opam_root == "/tmp/opam/"
def test_urls(swh_scheduler, mock_opam):
mock_init, mock_popen = mock_opam
-
instance_url = "https://opam.ocaml.org"
+ tmp_folder = mkdtemp(prefix="swh_opam_lister")
lister = OpamLister(
- swh_scheduler,
- url=instance_url,
- instance="opam",
- opam_root=mkdtemp(prefix="swh_opam_lister"),
+ swh_scheduler, url=instance_url, instance="opam", opam_root=tmp_folder,
)
assert lister.instance == "opam"
+ assert lister.opam_root == tmp_folder
# call the lister and get all listed origins urls
stats = lister.run()
@@ -101,3 +139,32 @@
result_urls = [origin.url for origin in scheduler_origins]
assert expected_urls == result_urls
+
+
+def test_opam_multi_instance(datadir, swh_scheduler):
+ instance_url = f"file://{datadir}/fake_opam_repo"
+
+ lister = OpamLister(
+ swh_scheduler,
+ url=instance_url,
+ instance="fake",
+ opam_root=mkdtemp(prefix="swh_opam_lister"),
+ )
+
+ stats = lister.run()
+
+ assert stats.pages == 4
+ assert stats.origins == 4
+
+ scheduler_origins = swh_scheduler.get_listed_origins(lister.lister_obj.id).results
+
+ expected_urls = [
+ f"opam+{instance_url}/packages/agrid/",
+ f"opam+{instance_url}/packages/calculon/",
+ f"opam+{instance_url}/packages/directories/",
+ f"opam+{instance_url}/packages/ocb/",
+ ]
+
+ result_urls = [origin.url for origin in scheduler_origins]
+
+ assert expected_urls == result_urls

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 3, 3:36 PM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3229895

Event Timeline