From a27a255923d89be13e20f8516db39c95bac574f2 Mon Sep 17 00:00:00 2001 From: Or Geva Date: Tue, 7 Nov 2023 18:18:42 +0200 Subject: [PATCH] Go - Support projects with embed files (#434) --- .../dependenciesRoot/goTree.ts | 3 ++ src/main/utils/goUtils.ts | 43 ++++++++++++----- src/test/resources/go/embedProject/go.mod | 8 ++++ src/test/resources/go/embedProject/main.go | 13 +++++ .../resources/go/embedProject/version.txt | 0 .../go/prepareProjectWorkspace/.vscode/b | 0 .../go/prepareProjectWorkspace/testdata/d | 0 src/test/resources/go/project2/go.sum | 2 +- src/test/tests/goUtils.test.ts | 47 +++++++++++++++---- 9 files changed, 93 insertions(+), 23 deletions(-) create mode 100644 src/test/resources/go/embedProject/go.mod create mode 100644 src/test/resources/go/embedProject/main.go create mode 100644 src/test/resources/go/embedProject/version.txt create mode 100644 src/test/resources/go/prepareProjectWorkspace/.vscode/b create mode 100644 src/test/resources/go/prepareProjectWorkspace/testdata/d diff --git a/src/main/treeDataProviders/dependenciesTree/dependenciesRoot/goTree.ts b/src/main/treeDataProviders/dependenciesTree/dependenciesRoot/goTree.ts index b033aee15..eb72b27ce 100644 --- a/src/main/treeDataProviders/dependenciesTree/dependenciesRoot/goTree.ts +++ b/src/main/treeDataProviders/dependenciesTree/dependenciesRoot/goTree.ts @@ -91,6 +91,9 @@ export class GoTreeNode extends RootNode { directDependenciesGeneralInfos.push(new GeneralInfo(nameVersionTuple[0], nameVersionTuple[1], ['None'], '', PackageType.Go)); } + // Filter out go min version that is written in go mod e.g. go@v1.19 + directDependenciesGeneralInfos = directDependenciesGeneralInfos.filter(generalInfo => !generalInfo.artifactId.startsWith('go@')); + // Create a set of packages that are actually in use in the project let goListPackages: Set = new Set(); goList.forEach((dependency: string) => { diff --git a/src/main/utils/goUtils.ts b/src/main/utils/goUtils.ts index cae7100d1..1b5e5d8f5 100644 --- a/src/main/utils/goUtils.ts +++ b/src/main/utils/goUtils.ts @@ -150,7 +150,7 @@ export class GoUtils { try { goModAbsDir = this.prepareGoModAbs(logManager); - this.prepareProjectWorkspace(workspaceDir, targetDir, goModAbsDir); + this.prepareProjectWorkspace(workspaceDir, targetDir, goModAbsDir, logManager, GoUtils.executeGoRun); } finally { if (goModAbsDir) { try { @@ -167,6 +167,11 @@ export class GoUtils { return tmpGoModPath; } + private static executeGoRun(destPath: string, sourceDir: string, goModAbsDir: string) { + const cmd: string = `go run . -goModPath=${destPath} -wd=${sourceDir}`; + ScanUtils.executeCmd(cmd, goModAbsDir); + } + /** * Copy gomod-absolutizer Go files to a temp directory. * The gomod-absolutizer is used to change relative paths in go.mod files to absolute paths. @@ -199,11 +204,23 @@ export class GoUtils { * @param targetDir - Target directory to copy relevant files to. * @param goModAbsDir - Path to the location of the gomod-absolutizer tool. */ - private static prepareProjectWorkspace(sourceDir: string, targetDir: string, goModAbsDir: string) { + public static prepareProjectWorkspace( + sourceDir: string, + targetDir: string, + goModAbsDir: string, + logManager: LogManager, + executeCmdFunction: (goModPath: string, sourceDir: string, goModAbsDir: string) => void + ) { + logManager.logMessage('Copy go workspace from' + sourceDir + ', to' + targetDir, 'DEBUG'); walkdir.find(sourceDir, { follow_symlinks: false, sync: true }, function(curPath: string, stat: fs.Stats) { let destPath: string = path.resolve(targetDir, path.relative(sourceDir, curPath)); + if (stat.isDirectory()) { - if (!(curPath === sourceDir)) { + if (GoUtils.shouldSkipDirectory(curPath, '.git', 'testdata', '.idea', '.vscode')) { + this.ignore(curPath); + return; + } + if (curPath !== sourceDir) { // Skip subdirectories with go.mod files. // These directories are different Go projects and their go files should not be in the root project. let files: string[] = fs.readdirSync(curPath).filter(fn => fn === 'go.mod'); @@ -219,20 +236,22 @@ export class GoUtils { return; } - // Files other than go.mod and *.go files are not necessary to build the dependency tree of used Go packages. - // Go files should be copied to allow running `go list -f "{{with .Module}}{{.Path}} {{.Version}}{{end}}" all` - // and to get the list package that are actually in use by the Go project. - if (curPath.endsWith('.go')) { - fs.copySync(curPath, destPath); - return; - } + logManager.logMessage('Copying ' + curPath + ' to ' + destPath, 'DEBUG'); + fs.copySync(curPath, destPath); // The root go.mod file is copied and relative path in "replace" are resolved to absolute paths. if (path.basename(curPath) === 'go.mod') { - fs.copySync(curPath, destPath); - ScanUtils.executeCmd('go run . -goModPath=' + destPath + ' -wd=' + sourceDir, goModAbsDir); + executeCmdFunction(destPath, sourceDir, goModAbsDir); return; } }); } + private static shouldSkipDirectory(dirPath: string, ...dirToIgnore: string[]) { + for (let dir of dirToIgnore) { + if (dirPath.includes(path.sep + dir)) { + return true; + } + } + return false; + } } diff --git a/src/test/resources/go/embedProject/go.mod b/src/test/resources/go/embedProject/go.mod new file mode 100644 index 000000000..67987fab9 --- /dev/null +++ b/src/test/resources/go/embedProject/go.mod @@ -0,0 +1,8 @@ +module embedProject + +go 1.16 + +require ( + github.com/jfrog/jfrog-cli-core v1.9.0 + github.com/jfrog/jfrog-client-go v0.26.1 // indirect +) diff --git a/src/test/resources/go/embedProject/main.go b/src/test/resources/go/embedProject/main.go new file mode 100644 index 000000000..90897b212 --- /dev/null +++ b/src/test/resources/go/embedProject/main.go @@ -0,0 +1,13 @@ +package embedProject + +import ( + _ "embed" + "github.com/jfrog/jfrog-cli-core/artifactory/commands/curl" + "github.com/jfrog/jfrog-cli-core/common/commands" +) +//go:embed version.txt +var buildVersion string + +func main() { + curl.NewRtCurlCommand(commands.CurlCommand{}) +} diff --git a/src/test/resources/go/embedProject/version.txt b/src/test/resources/go/embedProject/version.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/go/prepareProjectWorkspace/.vscode/b b/src/test/resources/go/prepareProjectWorkspace/.vscode/b new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/go/prepareProjectWorkspace/testdata/d b/src/test/resources/go/prepareProjectWorkspace/testdata/d new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/go/project2/go.sum b/src/test/resources/go/project2/go.sum index ba82dee07..6dd2c2065 100644 --- a/src/test/resources/go/project2/go.sum +++ b/src/test/resources/go/project2/go.sum @@ -6,7 +6,7 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbaEHo= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= diff --git a/src/test/tests/goUtils.test.ts b/src/test/tests/goUtils.test.ts index fe8d7791d..cc22bab22 100644 --- a/src/test/tests/goUtils.test.ts +++ b/src/test/tests/goUtils.test.ts @@ -1,5 +1,6 @@ import { assert } from 'chai'; import { before } from 'mocha'; +import fs from 'fs-extra'; import * as path from 'path'; import * as vscode from 'vscode'; import { ConnectionManager } from '../../main/connect/connectionManager'; @@ -132,6 +133,18 @@ describe('Go Utils Tests', async () => { assert.deepEqual(child.parent, parent.children[0]); }); + /** + * The project is with dependencies, and embed file + */ + it('Create go dependencies with embed file', async () => { + let projectName: string = 'embedProject'; + let expectedChildren: Map = new Map(); + expectedChildren.set('github.com/jfrog/jfrog-cli-core:1.9.0', 10); + expectedChildren.set('github.com/jfrog/jfrog-client-go:0.26.1', 8); + expectedChildren.set('github.com/golang/go:' + GoUtils.getGoVersion().format(), 0); + await createGoDependencyTreeAndValidate(projectName, expectedChildren); + }); + /** * The project is with dependencies, but without go.sum */ @@ -140,17 +153,19 @@ describe('Go Utils Tests', async () => { let expectedChildren: Map = new Map(); expectedChildren.set('github.com/jfrog/jfrog-cli-core:1.9.0', 11); expectedChildren.set('github.com/jfrog/jfrog-client-go:0.26.1', 9); - createGoDependencyTreeAndValidate(projectName, expectedChildren); + expectedChildren.set('github.com/golang/go:' + GoUtils.getGoVersion().format(), 0); + await createGoDependencyTreeAndValidate(projectName, expectedChildren); }); /** - * The project is with dependencies and go.sum, but with checksum mismatch on github.com/dsnet/compress + * The project is with dependencies and go.sum, */ it('Project 2 - Create go project with dependencies', async () => { let projectName: string = 'project2'; let expectedChildren: Map = new Map(); expectedChildren.set('github.com/jfrog/gocmd:0.1.12', 2); - createGoDependencyTreeAndValidate(projectName, expectedChildren); + expectedChildren.set('github.com/golang/go:' + GoUtils.getGoVersion().format(), 0); + await createGoDependencyTreeAndValidate(projectName, expectedChildren); }); /** @@ -161,7 +176,8 @@ describe('Go Utils Tests', async () => { let projectName: string = 'project3'; let expectedChildren: Map = new Map(); expectedChildren.set('github.com/test/subproject:0.0.0-00010101000000-000000000000', 1); - createGoDependencyTreeAndValidate(projectName, expectedChildren); + expectedChildren.set('github.com/golang/go:' + GoUtils.getGoVersion().format(), 0); + await createGoDependencyTreeAndValidate(projectName, expectedChildren); }); /** @@ -172,7 +188,8 @@ describe('Go Utils Tests', async () => { let projectName: string = 'project4'; let expectedChildren: Map = new Map(); expectedChildren.set('github.com/test/subproject:0.0.0-00010101000000-000000000000', 1); - createGoDependencyTreeAndValidate(projectName, expectedChildren); + expectedChildren.set('github.com/golang/go:' + GoUtils.getGoVersion().format(), 0); + await createGoDependencyTreeAndValidate(projectName, expectedChildren); }); async function runCreateGoDependenciesTrees(workspaceFolders: vscode.WorkspaceFolder[], parent: DependenciesTreeNode) { @@ -195,12 +212,8 @@ describe('Go Utils Tests', async () => { function validateDependencyTreeResults(projectName: string, expectedChildren: Map, node: DependenciesTreeNode) { let parent: DependenciesTreeNode | null = getNodeByArtifactId(node, projectName); - if (!parent) { - assert.isNotNull(node); - return; - } - let children: DependenciesTreeNode[] = parent.children; + let children: DependenciesTreeNode[] = parent?.children || []; assert.lengthOf(children, expectedChildren.size); children.forEach(child => { assert.isTrue(expectedChildren.has(child.componentId)); @@ -218,4 +231,18 @@ describe('Go Utils Tests', async () => { } as vscode.WorkspaceFolder ]; } + + describe('prepareProjectWorkspace util', () => { + it('Exclude all kind of files', () => { + // Define the source and target directories for testing + const sourceDir: string = path.join(tmpDir, 'prepareProjectWorkspace'); + const targetDir: string = path.join(tmpDir, 'tmpDir'); + + GoUtils.prepareProjectWorkspace(sourceDir, targetDir, '', logManager, () => { + return; + }); + + assert.isFalse(fs.existsSync(targetDir), 'The target directory should not exist since all files should be excluded'); + }); + }); });