From 03db2f42a0287a01999a5d46fd003d033856bdc5 Mon Sep 17 00:00:00 2001 From: Frank Viernau Date: Fri, 17 Jun 2022 12:50:11 +0200 Subject: [PATCH] GoMod: Distinguish main module depencencies from development-only ones The produced "vendor" scope, which is the only scope contained in the result, contains all modules needed for building and testing the main module. Introduce the scope "main" containing the dependencies of the main modules only. Determine the main module dependencies by utilizing [1], see also the discussion around [2]. [1] `go list -deps -f '{{with .Module}}{{.Path}} {{.Version}}{{end}}' ./...` [2] https://github.com/golang/go/issues/26955#issuecomment-437476523 Signed-off-by: Frank Viernau --- .../synthetic/gomod-expected-output.yml | 14 ++++++++ .../gomod-subpkg-expected-output.yml | 11 +++++++ analyzer/src/main/kotlin/managers/GoMod.kt | 33 ++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/analyzer/src/funTest/assets/projects/synthetic/gomod-expected-output.yml b/analyzer/src/funTest/assets/projects/synthetic/gomod-expected-output.yml index d20d9a909e520..02525ab3bdec5 100644 --- a/analyzer/src/funTest/assets/projects/synthetic/gomod-expected-output.yml +++ b/analyzer/src/funTest/assets/projects/synthetic/gomod-expected-output.yml @@ -16,6 +16,20 @@ project: path: "" homepage_url: "" scopes: + - name: "main" + dependencies: + - id: "GoMod::github.com/fatih/color:v1.13.0" + linkage: "PROJECT_STATIC" + - id: "GoMod::github.com/google/uuid:v1.0.0" + linkage: "PROJECT_STATIC" + - id: "GoMod::github.com/mattn/go-colorable:v0.1.12" + linkage: "PROJECT_STATIC" + - id: "GoMod::github.com/mattn/go-isatty:v0.0.14" + linkage: "PROJECT_STATIC" + - id: "GoMod::github.com/pborman/uuid:v1.2.1" + linkage: "PROJECT_STATIC" + - id: "GoMod::golang.org/x/sys:v0.0.0-20220610221304-9f5ed59c137d" + linkage: "PROJECT_STATIC" - name: "vendor" dependencies: - id: "GoMod::github.com/davecgh/go-spew:v1.1.0" diff --git a/analyzer/src/funTest/assets/projects/synthetic/gomod-subpkg-expected-output.yml b/analyzer/src/funTest/assets/projects/synthetic/gomod-subpkg-expected-output.yml index a97de11f97727..9e801bae0992e 100644 --- a/analyzer/src/funTest/assets/projects/synthetic/gomod-subpkg-expected-output.yml +++ b/analyzer/src/funTest/assets/projects/synthetic/gomod-subpkg-expected-output.yml @@ -16,6 +16,17 @@ project: path: "" homepage_url: "" scopes: + - name: "main" + dependencies: + - id: "GoMod::github.com/fatih/color:v1.7.0" + linkage: "PROJECT_STATIC" + - id: "GoMod::github.com/mattn/go-colorable:v0.1.4" + linkage: "PROJECT_STATIC" + - id: "GoMod::github.com/mattn/go-isatty:v0.0.10" + linkage: "PROJECT_STATIC" + dependencies: + - id: "GoMod::golang.org/x/sys:v0.0.0-20191008105621-543471e840be" + linkage: "PROJECT_STATIC" - name: "vendor" dependencies: - id: "GoMod::github.com/fatih/color:v1.7.0" diff --git a/analyzer/src/main/kotlin/managers/GoMod.kt b/analyzer/src/main/kotlin/managers/GoMod.kt index 06c5a349e04ed..75d9810852b1c 100644 --- a/analyzer/src/main/kotlin/managers/GoMod.kt +++ b/analyzer/src/main/kotlin/managers/GoMod.kt @@ -96,8 +96,20 @@ class GoMod( val packageIds = graph.nodes() - projectId val packages = packageIds.mapTo(sortedSetOf()) { createPackage(it) } val projectVcs = processProjectVcs(projectDir) + + val dependenciesScopePackageIds = getTransitiveMainModuleDependencies(projectDir).let { moduleNames -> + graph.nodes().filterTo(mutableSetOf()) { it.name in moduleNames } + } + val scopes = sortedSetOf( - Scope(name = "vendor", dependencies = graph.toPackageReferenceForest(projectId)) + Scope( + name = "main", + dependencies = graph.subgraph(dependenciesScopePackageIds).toPackageReferenceForest(projectId) + ), + Scope( + name = "vendor", + dependencies = graph.toPackageReferenceForest(projectId) + ) ) return listOf( @@ -199,6 +211,25 @@ class GoMod( return graph.nodes().filterTo(mutableSetOf()) { it.name in vendorModuleNames } } + /** + * Return the module names of all transitive main module dependencies. This excludes test-only dependencies. + */ + private fun getTransitiveMainModuleDependencies(projectDir: File): Set { + val result = mutableSetOf() + + val list = run("list", "-deps", "-f", "{{with .Module}}{{.Path}} {{.Version}}{{end}}", "./...", + workingDir = projectDir) + + list.stdout.lines().forEach { line -> + val columns = line.split(' ') + if (columns.size != 2) return@forEach + + result += columns[0] + } + + return result + } + private fun createPackage(id: Identifier): Package { val vcsInfo = id.toVcsInfo().takeUnless { it.type == VcsType.UNKNOWN }.orEmpty()