diff --git a/src/packagedcode/go_mod.py b/src/packagedcode/go_mod.py index 527931c2dcc..151d0f92407 100644 --- a/src/packagedcode/go_mod.py +++ b/src/packagedcode/go_mod.py @@ -21,6 +21,7 @@ class GoModule(object): module = attr.ib(default=None) require = attr.ib(default=None) exclude = attr.ib(default=None) + local_replacements = attr.ib(default=None) def purl(self, include_version=True): version = None @@ -50,6 +51,13 @@ def purl(self, include_version=True): r'(?P(.*))' ).match +parse_rep_link = re.compile( + r"(?P\S+)" + r"(?:\s+(?P\S+))?" + r"\s*=>\s*" + r"(?P\S+)" + r"(?:\s+(?P\S+))?" +).match def preprocess(line): """ @@ -60,6 +68,60 @@ def preprocess(line): line = line.strip() return line +def parse_replace_directive(line): + parsed_replace = parse_rep_link(line) + ns_name = parsed_replace.group("ns_name") + version = parsed_replace.group("version") + namespace, _, name = ns_name.rpartition("/") + original_module = { + "namespace": namespace, + "name": name, + "version": version + } + + replacement_ns_name = parsed_replace.group("replacement_ns_name") + replacement_version = parsed_replace.group("replacement_version") + is_local = replacement_ns_name.startswith("./") or replacement_ns_name.startswith("../") + + if is_local: + replacement_namespace = None + replacement_name = replacement_ns_name + else: + replacement_namespace, _, replacement_name = replacement_ns_name.rpartition("/") + + replacement_module = { + "namespace": replacement_namespace, + "name": replacement_name, + "version": replacement_version, + "is_local": is_local, + "local_path": replacement_ns_name if is_local else None + } + + return original_module, replacement_module + +def handle_replace_directive(line, require, exclude, local_replacements): + original, replacement = parse_replace_directive(line) + exclude.append( + GoModule( + namespace=original.get('namespace'), + name=original.get('name'), + version=original.get('version'), + ) + ) + + if replacement.get('is_local'): + local_replacements.append({ + 'replaces': f"{original.get('namespace')}/{original.get('name')}", + 'local_path': replacement.get('local_path') + }) + else: + require.append( + GoModule( + namespace=replacement.get('namespace'), + name=replacement.get('name'), + version=replacement.get('version') + ) + ) def parse_gomod(location): """ @@ -120,6 +182,7 @@ def parse_gomod(location): gomods = GoModule() require = [] exclude = [] + local_replacements = [] for i, line in enumerate(lines): line = preprocess(line) @@ -158,6 +221,19 @@ def parse_gomod(location): ) continue + if 'replace' in line and '(' in line: + for rep in lines[i + 1:]: + rep = preprocess(rep) + if ')' in rep: + break + handle_replace_directive(rep, require, exclude, local_replacements) + continue + + if 'replace' in line and '=>' in line: + line = line.lstrip("replace").strip() + handle_replace_directive(line, require, exclude, local_replacements) + continue + parsed_module_name = parse_module(line) if parsed_module_name: ns_name = parsed_module_name.group('ns_name') @@ -188,6 +264,7 @@ def parse_gomod(location): gomods.require = require gomods.exclude = exclude + gomods.local_replacements = local_replacements return gomods @@ -202,7 +279,6 @@ def parse_gomod(location): r'h1:(?P[^\s]*)' ).match - def parse_gosum(location): """ Return a list of GoSum from parsing the go.sum file at `location`. diff --git a/src/packagedcode/golang.py b/src/packagedcode/golang.py index c45be7a5e3a..dacd1427cd8 100644 --- a/src/packagedcode/golang.py +++ b/src/packagedcode/golang.py @@ -7,6 +7,8 @@ # See https://aboutcode.org for more information about nexB OSS projects. # +import os +import posixpath from packagedcode import go_mod from packagedcode import models @@ -24,6 +26,27 @@ # TODO: use the LICENSE file convention! # TODO: support "vendor" and "workspace" layouts +# Tracing flags +TRACE = False or os.environ.get("SCANCODE_DEBUG_PACKAGE", False) + + +# Tracing flags +def logger_debug(*args): + pass + + +if TRACE: + import logging + import sys + + logger = logging.getLogger(__name__) + logging.basicConfig(stream=sys.stdout) + logger.setLevel(logging.DEBUG) + + def logger_debug(*args): + return logger.debug(" ".join(isinstance(a, str) and a or repr(a) for a in args)) + + class BaseGoModuleHandler(models.DatafileHandler): @@ -32,6 +55,16 @@ def assemble(cls, package_data, resource, codebase, package_adder): """ Always use go.mod first then go.sum """ + + if not codebase.has_single_resource: + cls.resolve_local_replacements( + package_data=package_data, + resource=resource, + codebase=codebase, + ) + + resource.package_data[0] = package_data.to_dict() + yield from cls.assemble_from_many_datafiles( datafile_name_patterns=('go.mod', 'go.sum',), directory=resource.parent(codebase), @@ -39,6 +72,76 @@ def assemble(cls, package_data, resource, codebase, package_adder): package_adder=package_adder, ) + @classmethod + def resolve_local_replacements(cls, package_data, resource, codebase): + """ + Resolve local paths present in replace directives + """ + + local_replacements = package_data.extra_data.get('local_replacements', []) + if not local_replacements: + logger_debug(f"resolve_local_replacements: No local replacements found") + return + + base_dir = resource.parent(codebase) + base_path = base_dir.path + + for idx, replacement in enumerate(local_replacements): + local_path = replacement. get('local_path') + if not local_path: + logger_debug(f"resolve_local_replacements: Skipping replacement {idx + 1} - no local_path found") + continue + + full_path = posixpath.normpath( + posixpath.join(base_path, local_path) + ) + + local_resource = codebase.get_resource(full_path) + if not local_resource: + logger_debug(f"resolve_local_replacements: Resource not found at {full_path}") + continue + + local_gomod = None + for child in local_resource. children(codebase): + if child.name == 'go.mod': + local_gomod = child + break + + if not local_gomod or not local_gomod. package_data: + logger_debug(f"resolve_local_replacements: No go.mod or package_data found in {full_path}") + continue + + try: + local_pkg_dict = local_gomod.package_data[0] + local_pkg_data = models.PackageData.from_dict(local_pkg_dict) + except (IndexError, KeyError, TypeError) as e: + logger_debug(f"resolve_local_replacements: Failed to parse package data: {e}") + continue + + if not local_pkg_data. purl: + logger_debug(f"resolve_local_replacements: No purl found in local package data") + continue + + resolved_dependency = models.DependentPackage( + purl=local_pkg_data.purl, + extracted_requirement=local_pkg_data.version or None, + resolved_package=local_pkg_data.to_dict(), + scope='require', + is_runtime=True, + is_optional=False, + extra_data={ + 'replaces': replacement.get('replaces'), + 'resolved_from_local': True, + 'local_path': local_path, + 'local_resolved_path': full_path, + } + ) + + if not any(dep.purl == resolved_dependency.purl for dep in package_data.dependencies): + package_data.dependencies.append(resolved_dependency) + logger_debug(f"resolve_local_replacements: Added dependency: {resolved_dependency.purl}") + else: + logger_debug(f"resolve_local_replacements: Dependency already exists, skipping: {resolved_dependency. purl}") class GoModHandler(BaseGoModuleHandler): datasource_id = 'go_mod' @@ -79,6 +182,10 @@ def parse(cls, location, package_only=False): ) ) + extra_data = { + 'local_replacements': gomods.local_replacements + } + name = gomods.name namespace = gomods.namespace @@ -98,6 +205,7 @@ def parse(cls, location, package_only=False): homepage_url=homepage_url, repository_homepage_url=repository_homepage_url, dependencies=dependencies, + extra_data=extra_data if gomods.local_replacements else {}, primary_language=cls.default_primary_language, ) yield models.PackageData.from_data(package_data, package_only) diff --git a/tests/packagedcode/data/golang/gomod/gopls/go.mod b/tests/packagedcode/data/golang/gomod/gopls/go.mod new file mode 100644 index 00000000000..1d6fdd3d6b7 --- /dev/null +++ b/tests/packagedcode/data/golang/gomod/gopls/go.mod @@ -0,0 +1,30 @@ +module golang.org/x/tools/gopls + +go 1.18 + +require ( + github.com/google/go-cmp v0.5.9 + github.com/jba/printsrc v0.2.2 + github.com/jba/templatecheck v0.6.0 + github.com/sergi/go-diff v1.1.0 + golang.org/x/mod v0.12.0 + golang.org/x/sync v0.3.0 + golang.org/x/sys v0.11.0 + golang.org/x/telemetry v0.0.0-20230808152233-a65b40c0fdb0 + golang.org/x/text v0.12.0 + golang.org/x/tools v0.6.0 + golang.org/x/vuln v0.0.0-20230110180137-6ad3e3d07815 + gopkg.in/yaml.v3 v3.0.1 + honnef.co/go/tools v0.4.2 + mvdan.cc/gofumpt v0.4.0 + mvdan.cc/xurls/v2 v2.4.0 +) + +require ( + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/google/safehtml v0.1.0 // indirect + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect + golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338 // indirect +) + +replace golang.org/x/tools => ../ diff --git a/tests/packagedcode/data/golang/gomod/gopls/output.expected.json b/tests/packagedcode/data/golang/gomod/gopls/output.expected.json new file mode 100644 index 00000000000..e6caecd5f96 --- /dev/null +++ b/tests/packagedcode/data/golang/gomod/gopls/output.expected.json @@ -0,0 +1,274 @@ +[ + { + "type": "golang", + "namespace": "golang.org/x/tools", + "name": "gopls", + "version": null, + "qualifiers": {}, + "subpath": null, + "primary_language": "Go", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": "https://pkg.go.dev/golang.org/x/tools/gopls", + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": "https://golang.org/x/tools/gopls.git", + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "local_replacements": [ + { + "replaces": "golang.org/x/tools", + "local_path": "../" + } + ] + }, + "dependencies": [ + { + "purl": "pkg:golang/github.com/google/go-cmp@v0.5.9", + "extracted_requirement": "v0.5.9", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/jba/printsrc@v0.2.2", + "extracted_requirement": "v0.2.2", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/jba/templatecheck@v0.6.0", + "extracted_requirement": "v0.6.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/sergi/go-diff@v1.1.0", + "extracted_requirement": "v1.1.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/mod@v0.12.0", + "extracted_requirement": "v0.12.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/sync@v0.3.0", + "extracted_requirement": "v0.3.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/sys@v0.11.0", + "extracted_requirement": "v0.11.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/telemetry@v0.0.0-20230808152233-a65b40c0fdb0", + "extracted_requirement": "v0.0.0-20230808152233-a65b40c0fdb0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/text@v0.12.0", + "extracted_requirement": "v0.12.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/tools@v0.6.0", + "extracted_requirement": "v0.6.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/vuln@v0.0.0-20230110180137-6ad3e3d07815", + "extracted_requirement": "v0.0.0-20230110180137-6ad3e3d07815", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/gopkg.in/yaml.v3@v3.0.1", + "extracted_requirement": "v3.0.1", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/honnef.co/go/tools@v0.4.2", + "extracted_requirement": "v0.4.2", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/mvdan.cc/gofumpt@v0.4.0", + "extracted_requirement": "v0.4.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/mvdan.cc/xurls/v2@v2.4.0", + "extracted_requirement": "v2.4.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/BurntSushi/toml@v1.2.1", + "extracted_requirement": "v1.2.1", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/google/safehtml@v0.1.0", + "extracted_requirement": "v0.1.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/exp@v0.0.0-20220722155223-a9213eeb770e", + "extracted_requirement": "v0.0.0-20220722155223-a9213eeb770e", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/exp/typeparams@v0.0.0-20221212164502-fae10dda9338", + "extracted_requirement": "v0.0.0-20221212164502-fae10dda9338", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/tools", + "extracted_requirement": null, + "scope": "exclude", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://pkg.go.dev/golang.org/x/tools/gopls", + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "go_mod", + "purl": "pkg:golang/golang.org/x/tools/gopls" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/golang/gomod/milvus/go.mod b/tests/packagedcode/data/golang/gomod/milvus/go.mod new file mode 100644 index 00000000000..d4be3913a9a --- /dev/null +++ b/tests/packagedcode/data/golang/gomod/milvus/go.mod @@ -0,0 +1,24 @@ +module github.com/milvus-io/milvus + +go 1.20 + +require github.com/apache/arrow/go/v12 v12.0.1 + +require github.com/milvus-io/milvus-storage/go v0.0.0-20231227072638-ebd0b8e56d70 + +require ( + github.com/go-playground/validator/v10 v10.14.0 + github.com/quasilyte/go-ruleguard/dsl v0.3.22 + golang.org/x/net v0.19.0 +) + +replace ( + github.com/apache/pulsar-client-go => github.com/milvus-io/pulsar-client-go v0.6.10 + github.com/bketelsen/crypt v0.0.3 => github.com/bketelsen/crypt v0.0.4 // Fix security alert for core-os/etcd + github.com/expr-lang/expr => github.com/SimFG/expr v0.0.0-20231218130003-94d085776dc5 + github.com/milvus-io/milvus/pkg => ./pkg +) + +replace github.com/streamnative/pulsarctl => github.com/xiaofan-luan/pulsarctl v0.5.1 + +exclude github.com/apache/pulsar-client-go/oauth2 v0.0.0-20211108044248-fe3b7c4e445b diff --git a/tests/packagedcode/data/golang/gomod/milvus/output.expected.json b/tests/packagedcode/data/golang/gomod/milvus/output.expected.json new file mode 100644 index 00000000000..1c4073967f9 --- /dev/null +++ b/tests/packagedcode/data/golang/gomod/milvus/output.expected.json @@ -0,0 +1,219 @@ +[ + { + "type": "golang", + "namespace": "github.com/milvus-io", + "name": "milvus", + "version": null, + "qualifiers": {}, + "subpath": null, + "primary_language": "Go", + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": "https://pkg.go.dev/github.com/milvus-io/milvus", + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": "https://github.com/milvus-io/milvus.git", + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "local_replacements": [ + { + "replaces": "github.com/milvus-io/milvus/pkg", + "local_path": "./pkg" + } + ] + }, + "dependencies": [ + { + "purl": "pkg:golang/github.com/apache/arrow/go/v12@v12.0.1", + "extracted_requirement": "v12.0.1", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/milvus-io/milvus-storage/go@v0.0.0-20231227072638-ebd0b8e56d70", + "extracted_requirement": "v0.0.0-20231227072638-ebd0b8e56d70", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/go-playground/validator/v10@v10.14.0", + "extracted_requirement": "v10.14.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/quasilyte/go-ruleguard/dsl@v0.3.22", + "extracted_requirement": "v0.3.22", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/golang.org/x/net@v0.19.0", + "extracted_requirement": "v0.19.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/milvus-io/pulsar-client-go@v0.6.10", + "extracted_requirement": "v0.6.10", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/bketelsen/crypt@v0.0.4", + "extracted_requirement": "v0.0.4", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/SimFG/expr@v0.0.0-20231218130003-94d085776dc5", + "extracted_requirement": "v0.0.0-20231218130003-94d085776dc5", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/xiaofan-luan/pulsarctl@v0.5.1", + "extracted_requirement": "v0.5.1", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/apache/pulsar-client-go", + "extracted_requirement": null, + "scope": "exclude", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/bketelsen/crypt@v0.0.3", + "extracted_requirement": "v0.0.3", + "scope": "exclude", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/expr-lang/expr", + "extracted_requirement": null, + "scope": "exclude", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/milvus-io/milvus/pkg", + "extracted_requirement": null, + "scope": "exclude", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/streamnative/pulsarctl", + "extracted_requirement": null, + "scope": "exclude", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/apache/pulsar-client-go/oauth2@v0.0.0-20211108044248-fe3b7c4e445b", + "extracted_requirement": "v0.0.0-20211108044248-fe3b7c4e445b", + "scope": "exclude", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": "https://pkg.go.dev/github.com/milvus-io/milvus", + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "go_mod", + "purl": "pkg:golang/github.com/milvus-io/milvus" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/golang/gomod/opencensus-service/output.expected.json b/tests/packagedcode/data/golang/gomod/opencensus-service/output.expected.json index df05ab713ce..8ad089103a9 100644 --- a/tests/packagedcode/data/golang/gomod/opencensus-service/output.expected.json +++ b/tests/packagedcode/data/golang/gomod/opencensus-service/output.expected.json @@ -58,6 +58,28 @@ "is_direct": true, "resolved_package": {}, "extra_data": {} + }, + { + "purl": "pkg:golang/github.com/apache/thrift@v0.12.0", + "extracted_requirement": "v0.12.0", + "scope": "require", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:golang/git.apache.org/thrift.git", + "extracted_requirement": null, + "scope": "exclude", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} } ], "repository_homepage_url": "https://pkg.go.dev/github.com/census-instrumentation/opencensus-service", diff --git a/tests/packagedcode/test_golang.py b/tests/packagedcode/test_golang.py index 58feea2def0..b5d64170682 100644 --- a/tests/packagedcode/test_golang.py +++ b/tests/packagedcode/test_golang.py @@ -48,6 +48,18 @@ def test_parse_gomod_sample(self): package = golang.GoModHandler.parse(test_file) self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + def test_parse_gomod_milvus(self): + test_file = self.get_test_loc('golang/gomod/milvus/go.mod') + expected_loc = self.get_test_loc('golang/gomod/milvus/output.expected.json') + package = golang.GoModHandler.parse(test_file) + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_gomod_gopls(self): + test_file = self.get_test_loc('golang/gomod/gopls/go.mod') + expected_loc = self.get_test_loc('golang/gomod/gopls/output.expected.json') + package = golang.GoModHandler.parse(test_file) + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + def test_parse_gomod_uap_go(self): test_file = self.get_test_loc('golang/gomod/uap-go/go.mod') expected_loc = self.get_test_loc('golang/gomod/uap-go/output.expected.json')