diff --git a/minecode_pipelines/miners/cargo.py b/minecode_pipelines/miners/cargo.py new file mode 100644 index 00000000..f9d8e755 --- /dev/null +++ b/minecode_pipelines/miners/cargo.py @@ -0,0 +1,137 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# purldb is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# See http://www.apache.org/licenses/LICENSE-2.0 for the license text. +# See https://github.com/aboutcode-org/purldb for support or download. +# See https://aboutcode.org for more information about nexB OSS projects. +# +from datetime import datetime + +from minecode_pipelines.pipes import get_checkpoint_from_file +from minecode_pipelines.pipes import get_commit_at_distance_ahead +from minecode_pipelines.pipes import update_checkpoints_in_github +from minecode_pipelines.pipes import get_changed_files +from minecode_pipelines.pipes.cargo import store_cargo_packages +from scanpipe.pipes.federatedcode import commit_changes +from scanpipe.pipes.federatedcode import push_changes +from minecode_pipelines import VERSION + +import json +from pathlib import Path + + +PACKAGE_BATCH_SIZE = 500 +COMMIT_BATCH_SIZE = 10 + +CARGO_CHECKPOINT_PATH = "cargo/checkpoints.json" + + +def process_cargo_packages(cargo_index_repo, cloned_data_repo, config_repo, logger): + """ + Process Cargo index files commit by commit. + Push changes to fed_repo after: + - every `commit_batch` commits, OR when reaching HEAD. + """ + + base_path = Path(cargo_index_repo.working_tree_dir) + + while True: + cargo_checkpoints = get_checkpoint_from_file( + cloned_repo=config_repo, path=CARGO_CHECKPOINT_PATH + ) + + checkpoints_last_commit = cargo_checkpoints.get("last_commit") + + try: + next_commit = get_commit_at_distance_ahead( + cargo_index_repo, + checkpoints_last_commit, + num_commits_ahead=COMMIT_BATCH_SIZE, + branch_name="master", + ) + except ValueError as e: + logger(str(e)) + break + + if next_commit == checkpoints_last_commit: + logger("No new commits to mine") + break + + changed_files = get_changed_files( + cargo_index_repo, commit_x=checkpoints_last_commit, commit_y=next_commit + ) + logger(f"Found {len(changed_files)} changed files in Cargo index.") + + file_counter = 0 + purl_files = [] + purls = [] + for idx, rel_path in enumerate(changed_files): + file_path = base_path / rel_path + logger(f"Found {file_path}.") + + if not file_path.is_file() or file_path.name in { + "config.json", + "README.md", + "update-dl-url.yml", + }: + continue + + packages = [] + with open(file_path, encoding="utf-8") as f: + for line in f: + if line.strip(): + try: + packages.append(json.loads(line)) + except json.JSONDecodeError as e: + logger(f"Skipping invalid JSON in {file_path}: {e}") + + file_counter += 1 + + # Commit and push after each full batch or when processing the last file + commit_and_push = (file_counter % PACKAGE_BATCH_SIZE == 0) or ( + idx == len(changed_files) - 1 + ) + + result_store = store_cargo_packages(packages, cloned_data_repo) + if result_store: + purl_file, base_purl = result_store + logger(f"writing packageURLs for package: {base_purl} at: {purl_file}") + + purl_files.append(purl_file) + purls.append(str(base_purl)) + + if not commit_and_push: + continue + + commit_changes( + repo=cloned_data_repo, + files_to_commit=purl_files, + purls=purls, + mine_type="packageURL", + tool_name="pkg:pypi/minecode-pipelines", + tool_version=VERSION, + ) + + push_changes(repo=cloned_data_repo) + purl_files = [] + purls = [] + + if logger: + logger( + f"Updating checkpoint at: {CARGO_CHECKPOINT_PATH} with last commit: {checkpoints_last_commit}" + ) + + if next_commit != checkpoints_last_commit: + settings_data = { + "date": str(datetime.now()), + "last_commit": next_commit, + } + + update_checkpoints_in_github( + checkpoint=settings_data, + cloned_repo=config_repo, + path=CARGO_CHECKPOINT_PATH, + ) + + logger(f"Pushed batch for commit range {checkpoints_last_commit}:{next_commit}.") diff --git a/minecode_pipelines/pipelines/mine_cargo.py b/minecode_pipelines/pipelines/mine_cargo.py new file mode 100644 index 00000000..1bd1defe --- /dev/null +++ b/minecode_pipelines/pipelines/mine_cargo.py @@ -0,0 +1,84 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# http://nexb.com and https://github.com/aboutcode-org/scancode.io +# The ScanCode.io software is licensed under the Apache License version 2.0. +# Data generated with ScanCode.io is provided as-is without warranties. +# ScanCode is a trademark of nexB Inc. +# +# You may not use this software except in compliance with the License. +# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# +# Data Generated with ScanCode.io is provided on an "AS IS" BASIS, WITHOUT WARRANTIES +# OR CONDITIONS OF ANY KIND, either express or implied. No content created from +# ScanCode.io should be considered or used as legal advice. Consult an Attorney +# for any legal advice. +# +# ScanCode.io is a free software code scanning tool from nexB Inc. and others. +# Visit https://github.com/aboutcode-org/scancode.io for support and download. + +import os +from scanpipe.pipelines import Pipeline +from scanpipe.pipes import federatedcode +from minecode_pipelines.miners import cargo +from minecode_pipelines import pipes +from minecode_pipelines.pipes import MINECODE_PIPELINES_CONFIG_REPO + +MINECODE_DATA_CARGO_REPO = os.environ.get( + "MINECODE_DATA_CARGO_REPO", "https://github.com/aboutcode-data/minecode-data-cargo-test" +) +MINECODE_CARGO_INDEX_REPO = "https://github.com/rust-lang/crates.io-index" + + +class MineCargo(Pipeline): + """Pipeline to mine Cargo (crates.io) packages and publish them to FederatedCode.""" + + @classmethod + def steps(cls): + return ( + cls.check_federatedcode_eligibility, + cls.clone_cargo_repos, + cls.mine_and_publish_cargo_packageurls, + cls.delete_cloned_repos, + ) + + def check_federatedcode_eligibility(self): + """ + Check if the project fulfills the following criteria for + pushing the project result to FederatedCode. + """ + federatedcode.check_federatedcode_configured_and_available(logger=self.log) + + def clone_cargo_repos(self): + """ + Clone the Cargo-related repositories (index, data, and pipelines config) + and store their Repo objects in the corresponding instance variables. + """ + self.cargo_index_repo = federatedcode.clone_repository(MINECODE_CARGO_INDEX_REPO) + self.cloned_data_repo = federatedcode.clone_repository(MINECODE_DATA_CARGO_REPO) + self.cloned_config_repo = federatedcode.clone_repository(MINECODE_PIPELINES_CONFIG_REPO) + + if self.log: + self.log( + f"{MINECODE_CARGO_INDEX_REPO} repo cloned at: {self.cargo_index_repo.working_dir}" + ) + self.log( + f"{MINECODE_DATA_CARGO_REPO} repo cloned at: {self.cloned_data_repo.working_dir}" + ) + self.log( + f"{MINECODE_PIPELINES_CONFIG_REPO} repo cloned at: {self.cloned_config_repo.working_dir}" + ) + + def mine_and_publish_cargo_packageurls(self): + cargo.process_cargo_packages( + self.cargo_index_repo, self.cloned_data_repo, self.cloned_config_repo, self.log + ) + + def delete_cloned_repos(self): + pipes.delete_cloned_repos( + repos=[self.cargo_index_repo, self.cloned_data_repo, self.cloned_config_repo], + logger=self.log, + ) diff --git a/minecode_pipelines/pipes/__init__.py b/minecode_pipelines/pipes/__init__.py index 5d030617..595712b8 100644 --- a/minecode_pipelines/pipes/__init__.py +++ b/minecode_pipelines/pipes/__init__.py @@ -15,6 +15,8 @@ import saneyaml from aboutcode.hashid import PURLS_FILENAME +from git import Repo + from scanpipe.pipes.federatedcode import delete_local_clone from scanpipe.pipes.federatedcode import commit_and_push_changes @@ -34,7 +36,7 @@ def fetch_checkpoint_from_github(config_repo, checkpoint_path): ) response = requests.get(checkpoints_file) if not response.ok: - return + return {} checkpoint_data = json.loads(response.text) return checkpoint_data @@ -112,3 +114,66 @@ def delete_cloned_repos(repos, logger=None): if logger: logger(f"Deleting local clone at: {repo.working_dir}") delete_local_clone(repo) + + +def get_changed_files(repo: Repo, commit_x: str = None, commit_y: str = None): + """ + Return a list of files changed between two commits using GitPython. + Includes added, modified, deleted, and renamed files. + - commit_x: base commit (or the empty tree hash for the first commit) + - commit_y: target commit (defaults to HEAD if not provided) + """ + EMPTY_TREE_HASH = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" + + if commit_y is None: + commit_y = repo.head.commit.hexsha + commit_y_obj = repo.commit(commit_y) + + if commit_x is None or commit_x == EMPTY_TREE_HASH: + # First commit case: diff against empty tree + diff_index = commit_y_obj.diff(EMPTY_TREE_HASH, R=True) + else: + commit_x_obj = repo.commit(commit_x) + diff_index = commit_x_obj.diff(commit_y_obj, R=True) + + changed_files = {item.a_path or item.b_path for item in diff_index} + return list(changed_files) + + +def get_last_commit(repo, ecosystem): + """ + Retrieve the last mined commit for a given ecosystem. + This function reads a JSON checkpoint file from the repository, which stores + mining progress. Each checkpoint contains the "last_commit" from the package + index (e.g., PyPI) that was previously mined. + https://github.com/AyanSinhaMahapatra/minecode-test/blob/main/minecode_checkpoints/pypi.json + https://github.com/ziadhany/cargo-test/blob/main/minecode_checkpoints/cargo.json + """ + + last_commit_file_path = ( + Path(repo.working_tree_dir) / "minecode_checkpoints" / f"{ecosystem}.json" + ) + try: + with open(last_commit_file_path) as f: + settings_data = json.load(f) + except FileNotFoundError: + return + return settings_data.get("last_commit") + + +def get_commit_at_distance_ahead( + repo: Repo, + current_commit: str, + num_commits_ahead: int = 10, + branch_name: str = "master", +) -> str: + """ + Return the commit hash that is `num_commits_ahead` commits ahead of `current_commit` + on the given branch. + """ + if not current_commit: + current_commit = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" + revs = repo.git.rev_list(f"^{current_commit}", branch_name).splitlines() + if len(revs) < num_commits_ahead: + raise ValueError(f"Not enough commits ahead; only {len(revs)} available.") + return revs[-num_commits_ahead] diff --git a/minecode_pipelines/pipes/cargo.py b/minecode_pipelines/pipes/cargo.py new file mode 100644 index 00000000..4ea0ab12 --- /dev/null +++ b/minecode_pipelines/pipes/cargo.py @@ -0,0 +1,32 @@ +from pathlib import Path + +from aboutcode import hashid +from packageurl import PackageURL +from aboutcode.hashid import get_core_purl + +from minecode_pipelines.pipes import write_data_to_yaml_file + + +def store_cargo_packages(packages, repo): + """Collect Cargo package versions into purls and write them to the repo.""" + + if not packages: + return + + first_pkg = packages[0] + name = first_pkg.get("name") + version = first_pkg.get("vers") + purl = PackageURL(type="cargo", name=name, version=version) + base_purl = get_core_purl(purl) + + updated_purls = [] + for package in packages: + name = package.get("name") + version = package.get("vers") + purl = PackageURL(type="cargo", name=name, version=version).to_string() + updated_purls.append(purl) + + ppath = hashid.get_package_purls_yml_file_path(base_purl) + purl_file_full_path = Path(repo.working_dir) / ppath + write_data_to_yaml_file(path=purl_file_full_path, data=updated_purls) + return purl_file_full_path, base_purl diff --git a/minecode_pipelines/pipes/pypi.py b/minecode_pipelines/pipes/pypi.py index 75717eac..b8fdc7c9 100644 --- a/minecode_pipelines/pipes/pypi.py +++ b/minecode_pipelines/pipes/pypi.py @@ -45,6 +45,7 @@ from aboutcode.hashid import get_package_base_dir from packageurl import PackageURL from scanpipe.pipes.federatedcode import clone_repository + from scanpipe.pipes.federatedcode import commit_changes from scanpipe.pipes.federatedcode import push_changes diff --git a/minecode_pipelines/tests/pipes/test_cargo.py b/minecode_pipelines/tests/pipes/test_cargo.py new file mode 100644 index 00000000..742f428a --- /dev/null +++ b/minecode_pipelines/tests/pipes/test_cargo.py @@ -0,0 +1,85 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# purldb is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# See http://www.apache.org/licenses/LICENSE-2.0 for the license text. +# See https://github.com/aboutcode-org/purldb for support or download. +# See https://aboutcode.org for more information about nexB OSS projects. +# + +import json +import tempfile +from pathlib import Path +from unittest import mock +from unittest.mock import Mock, patch +import saneyaml +from django.test import TestCase + +from minecode_pipelines.pipes import write_data_to_yaml_file +from minecode_pipelines.pipes.cargo import store_cargo_packages + +DATA_DIR = Path(__file__).parent.parent / "test_data" / "cargo" + + +class CargoPipelineTests(TestCase): + @patch("minecode_pipelines.pipes.cargo.write_data_to_yaml_file") + def test_collect_packages_from_cargo_calls_write(self, mock_write): + packages_file = DATA_DIR / "c5store" + expected_file = DATA_DIR / "c5store-expected.yaml" + + packages = [] + with open(packages_file, encoding="utf-8") as f: + for line in f: + if line.strip(): + packages.append(json.loads(line)) + + with open(expected_file, encoding="utf-8") as f: + expected = saneyaml.load(f) + + with tempfile.TemporaryDirectory() as tmpdir: + repo = Mock() + repo.working_dir = tmpdir + + store_cargo_packages(packages, repo) + + mock_write.assert_called_once() + args, kwargs = mock_write.call_args + base_purl, written_packages = kwargs["path"], kwargs["data"] + + expected_base_purl = ( + Path(tmpdir) / "aboutcode-packages-cargo-0" / "cargo" / "c5store" / "purls.yml" + ) + + self.assertEqual(str(base_purl), str(expected_base_purl)) + self.assertEqual(written_packages, expected) + + def _assert_purls_written(self, purls): + with tempfile.TemporaryDirectory() as tmpdir: + repo_dir = Path(tmpdir) + + mock_repo = mock.MagicMock() + mock_repo.working_dir = str(repo_dir) + mock_repo.index.add = mock.MagicMock() + + purls_file = repo_dir / "purls.yaml" + + write_data_to_yaml_file(purls_file, purls) + + self.assertTrue(purls_file.exists()) + + with open(purls_file, encoding="utf-8") as f: + content = saneyaml.load(f) + + self.assertEqual(content, purls) + + def test_add_purl_result_with_mock_repo(self): + self._assert_purls_written( + [{"purl": "pkg:pypi/django@4.2.0"}, {"purl": "pkg:pypi/django@4.3.0"}] + ) + + def test_add_empty_purl_result_with_mock_repo(self): + self._assert_purls_written([]) + + def test_add_invalid_purl_with_mock_repo(self): + # invalid but still written as empty file + self._assert_purls_written([{"purl": "pkg:pypi/django"}]) diff --git a/minecode_pipelines/tests/pipes/test_pipes.py b/minecode_pipelines/tests/pipes/test_pipes.py new file mode 100644 index 00000000..1c8161bc --- /dev/null +++ b/minecode_pipelines/tests/pipes/test_pipes.py @@ -0,0 +1,65 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# purldb is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# See http://www.apache.org/licenses/LICENSE-2.0 for the license text. +# See https://github.com/aboutcode-org/purldb for support or download. +# See https://aboutcode.org for more information about nexB OSS projects. +# +import tempfile +from pathlib import Path +from unittest import TestCase +from git import Repo + +from minecode_pipelines.pipes import get_commit_at_distance_ahead + + +class GetCommitAtDistanceAheadIntegrationTests(TestCase): + def setUp(self): + # Create a temporary directory and init a repo + self.tmpdir = tempfile.TemporaryDirectory() + self.repo_path = Path(self.tmpdir.name) + self.repo = Repo.init(self.repo_path) + + # Configure identity (needed for commits) + with self.repo.config_writer() as cw: + cw.set_value("user", "name", "Test User") + cw.set_value("user", "email", "test@example.com") + + # Create 5 commits + self.commits = [] + for i in range(5): + file_path = self.repo_path / f"file{i}.txt" + file_path.write_text(f"content {i}") + self.repo.index.add([str(file_path)]) + commit = self.repo.index.commit(f"commit {i}") + self.commits.append(commit.hexsha) + + # By construction, self.commits[0] = first commit, self.commits[-1] = latest commit + + def tearDown(self): + self.tmpdir.cleanup() + + def test_get_commit_at_distance_none_current_commit(self): + # If current_commit is None, it should start from the empty tree hash + result = get_commit_at_distance_ahead( + self.repo, None, num_commits_ahead=3, branch_name="master" + ) + # Should return the 3rd commit in history + self.assertEqual(result, self.commits[2]) + + def test_get_commit_at_distance(self): + # current_commit = first commit, ask for 3 commits ahead + result = get_commit_at_distance_ahead( + self.repo, self.commits[0], num_commits_ahead=3, branch_name="master" + ) + # Should return the 3rd commit from start (self.commits[3]) + self.assertEqual(result, self.commits[3]) + + def test_raises_if_not_enough_commits(self): + # From latest commit, ask for 10 ahead (only 0 available) + with self.assertRaises(ValueError) as cm: + get_commit_at_distance_ahead( + self.repo, self.commits[-1], num_commits_ahead=10, branch_name="master" + ) + self.assertIn("Not enough commits ahead; only 0 available.", str(cm.exception)) diff --git a/minecode_pipelines/tests/test_data/cargo/c5store b/minecode_pipelines/tests/test_data/cargo/c5store new file mode 100644 index 00000000..46b93b08 --- /dev/null +++ b/minecode_pipelines/tests/test_data/cargo/c5store @@ -0,0 +1,14 @@ +{"name":"c5store","vers":"0.1.0","deps":[{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natord","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.3","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.10","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1.0","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^2.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.3","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"yaml-rust","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"}],"cksum":"8d0338954ccebef3aafc0f338219861bb04e4b7f9af67cf0d5cb38418980385b","features":{},"yanked":false} +{"name":"c5store","vers":"0.2.0","deps":[{"name":"base64","req":"^0.13","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0.1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1.0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natord","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.11","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1.0","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.9","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^2.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"yaml-rust","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"}],"cksum":"680a74300cd6393972d36b2ec3b3922573e438b49e3dda2612b5b5f410192c45","features":{},"yanked":false} +{"name":"c5store","vers":"0.2.1","deps":[{"name":"base64","req":"^0.13","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0.1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1.0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natord","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.11","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1.0","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.9","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^2.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"yaml-rust","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"}],"cksum":"19d948501daaf3350548e8a476e8e2928377f2cb9664fe3d800c29c081cbdbaf","features":{},"yanked":false} +{"name":"c5store","vers":"0.2.2","deps":[{"name":"base64","req":"^0.13","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0.1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1.0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natord","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.11","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1.0","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.9","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^2.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"yaml-rust","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"}],"cksum":"93fb874be3d0f54ce67ef3eeda2a2d455a0cde4ffd4da49dd057a4bc0735ef6c","features":{},"yanked":false} +{"name":"c5store","vers":"0.2.3","deps":[{"name":"base64","req":"^0.13","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0.1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1.0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natord","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.11","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1.0","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.9","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^2.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"yaml-rust","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"}],"cksum":"5cdbd1960746beb170e2054ccdde793283e202e33c0a35c3b39cb09b40bb77ed","features":{},"yanked":false} +{"name":"c5store","vers":"0.2.4","deps":[{"name":"base64","req":"^0.13","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0.1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1.0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natord","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.11","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"paste","req":"^1.0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1.0","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.9","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^2.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"yaml-rust","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"}],"cksum":"e559cc84dd9f14038b831b9227b5394b26e343758b112ba7d7adaab34d38d2ea","features":{},"yanked":false} +{"name":"c5store","vers":"0.2.5","deps":[{"name":"base64","req":"^0.13","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1.0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natord","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.11","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"paste","req":"^1.0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1.0","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.9","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^2.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"yaml-rust","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"}],"cksum":"1eacfb944c4b337cb9e6373878ba75ad27573dc05a122ff116ded02faf6c5abb","features":{},"yanked":false} +{"name":"c5store","vers":"0.2.6","deps":[{"name":"base64","req":"^0.13","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1.0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natord","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.11","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"paste","req":"^1.0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1.0","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0.8","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.9","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^2.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"yaml-rust","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"}],"cksum":"535d1ded0d73dd95f0909d40ff72ed3f4ef330201bbf7f7ac2abde5f2b177da0","features":{},"yanked":false} +{"name":"c5store","vers":"0.2.7","deps":[{"name":"base64","req":"^0.22","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.10","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natord","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"paste","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.10","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^3.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.5","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"}],"cksum":"57eaafc115042c8c69fcddd5dbf5c5c62be93fc3493d21ea67bd77f55b000237","features":{},"yanked":false} +{"name":"c5store","vers":"0.3.0","deps":[{"name":"base64","req":"^0.22","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"dotenvy","req":"^0.15","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.10","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natord","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"paste","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.10","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^3.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.5","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"thiserror","req":"^2.0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"toml","req":"^0.8","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"}],"cksum":"5b4dd483681f3aaeec256e302f3226b8267444cee93df19e56afc499ab425e62","features":{},"features2":{"default":["secrets"],"dotenv":["dep:dotenvy"],"full":["dotenv","toml","secrets"],"secrets":["dep:ecies_25519","dep:curve25519-parser","dep:sha2"],"toml":["dep:toml"]},"yanked":false,"v":2} +{"name":"c5store","vers":"0.3.1","deps":[{"name":"base64","req":"^0.22","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"dotenvy","req":"^0.15","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.10","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natlex_sort","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"paste","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.10","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^3.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.5","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"thiserror","req":"^2.0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"toml","req":"^0.8","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"}],"cksum":"055ea0dbc26388254d2cef557d0f134bce351691695fe4ef014adfc818d91ae6","features":{},"features2":{"default":["secrets"],"dotenv":["dep:dotenvy"],"full":["dotenv","toml","secrets"],"secrets":["dep:ecies_25519","dep:curve25519-parser","dep:sha2"],"toml":["dep:toml"]},"yanked":false,"v":2} +{"name":"c5store","vers":"0.4.0","deps":[{"name":"base64","req":"^0.22","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"dotenvy","req":"^0.15","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.10","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natlex_sort","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"paste","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"reqwest","req":"^0.12","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"sha2","req":"^0.10","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^3.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.5","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"thiserror","req":"^2.0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"tokio","req":"^1","features":["fs","macros","rt-multi-thread"],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"toml","req":"^0.8","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"url","req":"^2.3","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"}],"cksum":"bc5e0f7cd5d907f970384e6c9f352367bfbd59a9a7e90a704e1e8fbbb2f9523f","features":{},"features2":{"bootstrapper":["dep:reqwest","dep:tokio","dep:url"],"default":["secrets"],"dotenv":["dep:dotenvy"],"full":["dotenv","toml","secrets","bootstrapper"],"secrets":["dep:ecies_25519","dep:curve25519-parser","dep:sha2"],"toml":["dep:toml"]},"yanked":false,"v":2} +{"name":"c5store","vers":"0.4.1","deps":[{"name":"base64","req":"^0.22","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"dotenvy","req":"^0.15","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.10","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natlex_sort","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"paste","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"reqwest","req":"^0.12","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serial_test","req":"^3.2.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"sha2","req":"^0.10","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^3.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.5","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"thiserror","req":"^2.0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"tokio","req":"^1","features":["fs","macros","rt-multi-thread"],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"toml","req":"^0.8","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"url","req":"^2.3","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"}],"cksum":"74039262902fbe52f8f0cf43f8015a5d99109e2e3988448ed387105f3c3a360d","features":{},"features2":{"bootstrapper":["dep:reqwest","dep:tokio","dep:url"],"default":["secrets"],"dotenv":["dep:dotenvy"],"full":["dotenv","toml","secrets","bootstrapper"],"secrets":["dep:ecies_25519","dep:curve25519-parser","dep:sha2"],"toml":["dep:toml"]},"yanked":false,"v":2} +{"name":"c5store","vers":"0.4.2","deps":[{"name":"base64","req":"^0.22","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"curve25519-parser","req":"^0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"dotenvy","req":"^0.15","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"ecies_25519","req":"^0","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"log","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"maplit","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"multimap","req":"^0.10","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"natlex_sort","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-rational","req":"^0.4","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"num-traits","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"parking_lot","req":"^0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"paste","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"reqwest","req":"^0.12","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"scheduled-thread-pool","req":"^0.2","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde","req":"^1","features":["derive"],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_json","req":"^1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serde_test","req":"^1.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"serde_yaml","req":"^0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"serial_test","req":"^3.2.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev"},{"name":"sha2","req":"^0.10","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"shellexpand","req":"^3.0","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"skiplist","req":"^0.5","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"thiserror","req":"^2.0.12","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal"},{"name":"tokio","req":"^1","features":["fs","macros","rt-multi-thread"],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"toml","req":"^0.8","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"},{"name":"url","req":"^2.3","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal"}],"cksum":"11d63d9e525154071e657b5ae4f39d704ee912cf5d383aab756652a5205f4d08","features":{},"features2":{"bootstrapper":["dep:reqwest","dep:tokio","dep:url"],"default":["secrets"],"dotenv":["dep:dotenvy"],"full":["dotenv","toml","secrets","bootstrapper"],"secrets":["dep:ecies_25519","dep:curve25519-parser","dep:sha2"],"secrets_systemd":["secrets"],"toml":["dep:toml"]},"yanked":false,"v":2} \ No newline at end of file diff --git a/minecode_pipelines/tests/test_data/cargo/c5store-expected.yaml b/minecode_pipelines/tests/test_data/cargo/c5store-expected.yaml new file mode 100644 index 00000000..c74d51b9 --- /dev/null +++ b/minecode_pipelines/tests/test_data/cargo/c5store-expected.yaml @@ -0,0 +1,14 @@ +- pkg:cargo/c5store@0.1.0 +- pkg:cargo/c5store@0.2.0 +- pkg:cargo/c5store@0.2.1 +- pkg:cargo/c5store@0.2.2 +- pkg:cargo/c5store@0.2.3 +- pkg:cargo/c5store@0.2.4 +- pkg:cargo/c5store@0.2.5 +- pkg:cargo/c5store@0.2.6 +- pkg:cargo/c5store@0.2.7 +- pkg:cargo/c5store@0.3.0 +- pkg:cargo/c5store@0.3.1 +- pkg:cargo/c5store@0.4.0 +- pkg:cargo/c5store@0.4.1 +- pkg:cargo/c5store@0.4.2 \ No newline at end of file diff --git a/minecode_pipelines/utils.py b/minecode_pipelines/utils.py index a583536f..004cc043 100644 --- a/minecode_pipelines/utils.py +++ b/minecode_pipelines/utils.py @@ -6,10 +6,8 @@ # See https://github.com/aboutcode-org/purldb for support or download. # See https://aboutcode.org for more information about nexB OSS projects. # - -import os import tempfile - +import os from commoncode.fileutils import create_dir from itertools import zip_longest diff --git a/pyproject-minecode_pipeline.toml b/pyproject-minecode_pipeline.toml index 834f4a29..bad010fb 100644 --- a/pyproject-minecode_pipeline.toml +++ b/pyproject-minecode_pipeline.toml @@ -47,6 +47,7 @@ urls = { Homepage = "https://github.com/aboutcode-org/purldb" } [project.entry-points."scancodeio_pipelines"] mine_pypi = "minecode_pipelines.pipelines.mine_pypi:MinePypi" mine_maven = "minecode_pipeline.pipelines.mine_maven:MineMaven" +mine_cargo = "minecode_pipelines.pipelines.mine_cargo:MineCargo" mine_debian = "minecode_pipelines.pipelines.mine_debian:MineDebian" [tool.bumpversion]