From 11f5d3df3ae92965639fccbfbdc7a84c69baf678 Mon Sep 17 00:00:00 2001 From: Shrashti1234 Date: Thu, 5 Nov 2026 09:53:33 +0530 Subject: [PATCH] Preserve explicit authors of Cargo workspace members Signed-off-by: Shrashti1234 --- AUTHORS.rst | 1 + CHANGELOG.rst | 3 + src/packagedcode/cargo.py | 2 +- .../cargo-with-workspace/boring.expected.json | 150 +++++++++++++++++- tests/packagedcode/test_cargo.py | 38 +++++ 5 files changed, 185 insertions(+), 9 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 9a8224dc7da..72a9863d2b1 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -84,6 +84,7 @@ The following organizations or individuals have contributed to ScanCode: - Sebastian Schuberth @sschuberth - Shankhadeep Dey @Iamshankhadeep - Sharikzama @ZamaSharik +- Shrashti @Shrashti1234 - Shrijal Acharya @OctoPie23 - Shivam Chauhan @chashiv - Shivam Sandbhor @sbs2001 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index abc3ae41ad2..34113f23529 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,9 @@ Changelog Next release -------------- +- Preserve Cargo workspace members' own authors and inherit workspace authors + only when a member explicitly declares ``authors.workspace = true``. + - Fix the optional ``licenses`` extra dependency typo to install ``licensedcode-data``. https://github.com/aboutcode-org/scancode-toolkit/pull/5056 diff --git a/src/packagedcode/cargo.py b/src/packagedcode/cargo.py index 3b2d342d828..1a47b3db914 100644 --- a/src/packagedcode/cargo.py +++ b/src/packagedcode/cargo.py @@ -132,7 +132,7 @@ def update_resource_package_data(cls, workspace, workspace_package_data, resourc replace_by_value = workspace_package_data.get(replace_by_attribute) if replace_by_value: resource_package_data[attribute] = replace_by_value - elif attribute == "parties": + elif attribute == "parties" and "authors" in extra_data: resource_package_data[attribute] = list(get_parties( person_names=workspace_package_data.get("authors", []), party_role='author', diff --git a/tests/packagedcode/data/cargo/cargo-with-workspace/boring.expected.json b/tests/packagedcode/data/cargo/cargo-with-workspace/boring.expected.json index da9c2aa0335..8f59a47d1ee 100644 --- a/tests/packagedcode/data/cargo/cargo-with-workspace/boring.expected.json +++ b/tests/packagedcode/data/cargo/cargo-with-workspace/boring.expected.json @@ -10,7 +10,22 @@ "primary_language": "Rust", "description": "BoringSSL bindings", "release_date": null, - "parties": [], + "parties": [ + { + "type": "person", + "role": "author", + "name": "Steven Fackler", + "email": "sfackler@gmail.com", + "url": null + }, + { + "type": "person", + "role": "author", + "name": "Ivan Nikulin", + "email": "ifaaan@gmail.com", + "url": null + } + ], "keywords": [ "crypto", "tls", @@ -91,7 +106,29 @@ "primary_language": "Rust", "description": "FFI bindings to BoringSSL", "release_date": null, - "parties": [], + "parties": [ + { + "type": "person", + "role": "author", + "name": "Alex Crichton", + "email": "alex@alexcrichton.com", + "url": null + }, + { + "type": "person", + "role": "author", + "name": "Steven Fackler", + "email": "sfackler@gmail.com", + "url": null + }, + { + "type": "person", + "role": "author", + "name": "Ivan Nikulin", + "email": "ifaaan@gmail.com", + "url": null + } + ], "keywords": [ "cryptography", "external-ffi-bindings" @@ -168,7 +205,22 @@ "primary_language": "Rust", "description": "An implementation of SSL streams for Tokio backed by BoringSSL", "release_date": null, - "parties": [], + "parties": [ + { + "type": "person", + "role": "author", + "name": "Alex Crichton", + "email": "alex@alexcrichton.com", + "url": null + }, + { + "type": "person", + "role": "author", + "name": "Ivan Nikulin", + "email": "ifaaan@gmail.com", + "url": null + } + ], "keywords": [], "homepage_url": "https://github.com/cloudflare/boring", "download_url": null, @@ -242,7 +294,22 @@ "primary_language": "Rust", "description": "Hyper TLS support via BoringSSL", "release_date": null, - "parties": [], + "parties": [ + { + "type": "person", + "role": "author", + "name": "Steven Fackler", + "email": "sfackler@gmail.com", + "url": null + }, + { + "type": "person", + "role": "author", + "name": "Ivan Nikulin", + "email": "ifaaan@gmail.com", + "url": null + } + ], "keywords": [], "homepage_url": null, "download_url": null, @@ -954,7 +1021,29 @@ "primary_language": "Rust", "description": "FFI bindings to BoringSSL", "release_date": null, - "parties": [], + "parties": [ + { + "type": "person", + "role": "author", + "name": "Alex Crichton", + "email": "alex@alexcrichton.com", + "url": null + }, + { + "type": "person", + "role": "author", + "name": "Steven Fackler", + "email": "sfackler@gmail.com", + "url": null + }, + { + "type": "person", + "role": "author", + "name": "Ivan Nikulin", + "email": "ifaaan@gmail.com", + "url": null + } + ], "keywords": [ "cryptography", "external-ffi-bindings" @@ -1082,7 +1171,22 @@ "primary_language": "Rust", "description": "BoringSSL bindings", "release_date": null, - "parties": [], + "parties": [ + { + "type": "person", + "role": "author", + "name": "Steven Fackler", + "email": "sfackler@gmail.com", + "url": null + }, + { + "type": "person", + "role": "author", + "name": "Ivan Nikulin", + "email": "ifaaan@gmail.com", + "url": null + } + ], "keywords": [ "crypto", "tls", @@ -1254,7 +1358,22 @@ "primary_language": "Rust", "description": "Hyper TLS support via BoringSSL", "release_date": null, - "parties": [], + "parties": [ + { + "type": "person", + "role": "author", + "name": "Steven Fackler", + "email": "sfackler@gmail.com", + "url": null + }, + { + "type": "person", + "role": "author", + "name": "Ivan Nikulin", + "email": "ifaaan@gmail.com", + "url": null + } + ], "keywords": [], "homepage_url": null, "download_url": null, @@ -1501,7 +1620,22 @@ "primary_language": "Rust", "description": "An implementation of SSL streams for Tokio backed by BoringSSL", "release_date": null, - "parties": [], + "parties": [ + { + "type": "person", + "role": "author", + "name": "Alex Crichton", + "email": "alex@alexcrichton.com", + "url": null + }, + { + "type": "person", + "role": "author", + "name": "Ivan Nikulin", + "email": "ifaaan@gmail.com", + "url": null + } + ], "keywords": [], "homepage_url": "https://github.com/cloudflare/boring", "download_url": null, diff --git a/tests/packagedcode/test_cargo.py b/tests/packagedcode/test_cargo.py index 2f6a2baa796..290ee50d1b2 100644 --- a/tests/packagedcode/test_cargo.py +++ b/tests/packagedcode/test_cargo.py @@ -7,6 +7,7 @@ # See https://aboutcode.org for more information about nexB OSS projects. # +import json import os import pytest @@ -17,6 +18,43 @@ from scancode.cli_test_utils import check_json_scan +@pytest.mark.parametrize('workspace_authors, member_authors, expected_names', [ + ('', 'authors = ["Member Author"]\n', ['Member Author']), + ('authors = ["Workspace Author"]\n', 'authors = ["Member Author"]\n', ['Member Author']), + ('authors = ["Workspace Author"]\n', 'authors.workspace = true\n', ['Workspace Author']), + ('authors = ["Workspace Author"]\n', '', []), + ('', '', []), +]) +def test_workspace_preserves_member_authors( + workspace_authors, member_authors, expected_names, tmp_path, +): + workspace = tmp_path / 'workspace' + member = workspace / 'crates/member' + member.mkdir(parents=True) + (workspace / 'Cargo.toml').write_text( + '[workspace]\nmembers = ["crates/member"]\n' + '[workspace.package]\nversion = "1.2.3"\n' + 'repository = "https://example.com/workspace"\n' + f'{workspace_authors}', + encoding='utf-8', + ) + (member / 'Cargo.toml').write_text( + '[package]\nname = "workspace-member"\n' + 'version.workspace = true\nrepository.workspace = true\n' + f'{member_authors}', + encoding='utf-8', + ) + result_file = tmp_path / 'results.json' + run_scan_click(['--package', str(workspace), '--json', str(result_file)]) + results = json.loads(result_file.read_text(encoding='utf-8')) + packages = results['packages'] + assert len(packages) == 1 + package = packages[0] + assert package['purl'] == 'pkg:cargo/workspace-member@1.2.3' + assert package['vcs_url'] == 'https://example.com/workspace' + assert [party['name'] for party in package['parties']] == expected_names + + class TestCargo(PackageTester): test_data_dir = os.path.join(os.path.dirname(__file__), 'data')