Skip to content

Commit 6dc86d5

Browse files
committed
Add a test for mine cargo
Signed-off-by: ziad hany <[email protected]>
1 parent 2f26f8d commit 6dc86d5

File tree

7 files changed

+139
-18
lines changed

7 files changed

+139
-18
lines changed

minecode_pipeline/pipelines/mine_cargo.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
from pathlib import Path
2424

2525
from minecode_pipeline.pipes import cargo
26-
from scanpipe.pipelines.publish_to_federatedcode import PublishToFederatedCode
26+
27+
from scanpipe.pipelines import Pipeline
2728
from fetchcode.vcs import fetch_via_vcs
29+
from scanpipe.pipes import federatedcode
2830

2931

30-
class MineCargo(PublishToFederatedCode):
32+
class MineCargo(Pipeline):
3133
"""Pipeline to mine Cargo (crates.io) packages and publish them to FederatedCode."""
3234

3335
repo_url = "git+https://github.com/rust-lang/crates.io-index"
@@ -36,13 +38,18 @@ class MineCargo(PublishToFederatedCode):
3638
def steps(cls):
3739
return (
3840
cls.check_federatedcode_eligibility,
39-
cls.clone_cargo_index,
40-
cls.clone_repository,
41+
cls.clone_cargo_repo,
4142
cls.collect_packages_from_cargo,
42-
cls.delete_local_clone,
4343
)
4444

45-
def clone_cargo_index(self, repo_url):
45+
def check_federatedcode_eligibility(self):
46+
"""
47+
Check if the project fulfills the following criteria for
48+
pushing the project result to FederatedCode.
49+
"""
50+
federatedcode.check_federatedcode_eligibility(project=self.project)
51+
52+
def clone_cargo_repo(self, repo_url):
4653
"""
4754
Clone the repo at repo_url and return the VCSResponse object
4855
"""
@@ -62,10 +69,21 @@ def collect_packages_from_cargo(self):
6269
for idx, file_path in enumerate(json_files, start=1):
6370
try:
6471
with open(file_path, encoding="utf-8") as f:
65-
packages = json.load(f)
72+
packages = []
73+
for line in f:
74+
if line.strip():
75+
packages.append(json.loads(line))
76+
6677
except (json.JSONDecodeError, UnicodeDecodeError):
6778
continue
6879

6980
if packages:
7081
push_commit = idx == len(json_files) # only True on last
7182
cargo.collect_packages_from_cargo(packages, self.vcs_response, push_commit)
83+
84+
def clean_cargo_repo(self):
85+
"""
86+
Delete the VCS response repository if it exists.
87+
"""
88+
if self.vcs_response:
89+
self.vcs_response.delete()

minecode_pipeline/pipes/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
remote_name = "origin"
1919

2020

21-
def write_purls_to_repo(repo, package, packages_yaml, push_commit=False):
21+
def write_purls_to_repo(repo, package, updated_purls, push_commit=False):
2222
"""Write or update package purls in the repo and optionally commit/push changes."""
2323

2424
ppath = hashid.get_package_purls_yml_file_path(package)
25-
add_purl_result(packages_yaml, repo, ppath)
25+
add_purl_result(updated_purls, repo, ppath)
2626

2727
if push_commit:
2828
change_type = "Add" if ppath in repo.untracked_files else "Update"
@@ -40,7 +40,7 @@ def write_purls_to_repo(repo, package, packages_yaml, push_commit=False):
4040

4141
def add_purl_result(purls, repo, purls_file):
4242
"""Add package urls result to the local Git repository."""
43-
relative_purl_file_path = Path(*purls_file.parts[1:])
43+
relative_purl_file_path = Path(purls_file)
4444

4545
write_to = Path(repo.working_dir) / relative_purl_file_path
4646
write_to.parent.mkdir(parents=True, exist_ok=True)

minecode_pipeline/pipes/cargo.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,20 @@
66
def collect_packages_from_cargo(packages, repo, push_commit=False):
77
"""Collect Cargo package versions into purls and write them to the repo."""
88

9-
if not packages and len(packages) > 0:
9+
if not packages:
1010
raise ValueError("No packages found")
1111

12-
updated_purls = []
1312
first_pkg = packages[0]
14-
version = first_pkg.get("vers")
1513
name = first_pkg.get("name")
14+
version = first_pkg.get("vers")
1615
purl = PackageURL(type="cargo", name=name, version=version)
1716
base_purl = get_core_purl(purl)
1817

18+
updated_purls = []
1919
for package in packages:
20-
version = package.get("vers")
2120
name = package.get("name")
22-
21+
version = package.get("vers")
2322
purl = PackageURL(type="cargo", name=name, version=version).to_string()
2423
updated_purls.append(purl)
2524

26-
write_purls_to_repo(repo, base_purl, packages, push_commit)
25+
write_purls_to_repo(repo, base_purl, updated_purls, push_commit)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import json
2+
import tempfile
3+
from pathlib import Path
4+
from unittest import mock
5+
from unittest.mock import Mock, patch
6+
import saneyaml
7+
8+
from django.test import TestCase
9+
from packageurl import PackageURL
10+
11+
from minecode_pipeline.pipes import add_purl_result
12+
from minecode_pipeline.pipes.cargo import collect_packages_from_cargo
13+
14+
DATA_DIR = Path(__file__).parent / "test_data"
15+
16+
17+
class CargoPipelineTests(TestCase):
18+
def _get_temp_dir(self):
19+
import tempfile
20+
21+
return tempfile.mkdtemp()
22+
23+
@patch("minecode_pipeline.pipes.cargo.write_purls_to_repo")
24+
def test_collect_packages_from_cargo_calls_write(self, mock_write):
25+
packages_file = DATA_DIR / "c5store"
26+
expected_file = DATA_DIR / "c5store-expected.yaml"
27+
28+
packages = []
29+
with open(packages_file, encoding="utf-8") as f:
30+
for line in f:
31+
if line.strip():
32+
packages.append(json.loads(line))
33+
34+
with open(expected_file, encoding="utf-8") as f:
35+
expected = saneyaml.load(f)
36+
37+
repo = Mock()
38+
result = collect_packages_from_cargo(packages, repo)
39+
self.assertIsNone(result)
40+
41+
mock_write.assert_called_once()
42+
args, kwargs = mock_write.call_args
43+
called_repo, base_purl, written_packages, push_commit = args
44+
45+
self.assertEqual(called_repo, repo)
46+
47+
first_pkg = packages[0]
48+
expected_base_purl = PackageURL(
49+
type="cargo",
50+
name=first_pkg["name"],
51+
)
52+
self.assertEqual(str(base_purl), str(expected_base_purl))
53+
54+
self.assertEqual(written_packages, expected)
55+
56+
def test_add_purl_result_with_mock_repo(self):
57+
purls = [{"purl": "pkg:pypi/[email protected]"}, {"purl": "pkg:pypi/[email protected]"}]
58+
59+
with tempfile.TemporaryDirectory() as tmpdir:
60+
repo_dir = Path(tmpdir)
61+
62+
mock_repo = mock.MagicMock()
63+
mock_repo.working_dir = str(repo_dir)
64+
mock_repo.index.add = mock.MagicMock()
65+
66+
purls_file = repo_dir / "purls.yaml"
67+
68+
relative_path = add_purl_result(purls, mock_repo, purls_file)
69+
70+
written_file = repo_dir / relative_path
71+
self.assertTrue(written_file.exists())
72+
73+
with open(written_file, encoding="utf-8") as f:
74+
content = saneyaml.load(f)
75+
self.assertEqual(content, purls)
76+
77+
mock_repo.index.add.assert_called_once_with([relative_path])

0 commit comments

Comments
 (0)