Skip to content

Commit

Permalink
Go - Support projects with embed files (#434)
Browse files Browse the repository at this point in the history
  • Loading branch information
Or-Geva authored Nov 7, 2023
1 parent 4441383 commit a27a255
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> = new Set<string>();
goList.forEach((dependency: string) => {
Expand Down
43 changes: 31 additions & 12 deletions src/main/utils/goUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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.
Expand Down Expand Up @@ -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');
Expand All @@ -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;
}
}
8 changes: 8 additions & 0 deletions src/test/resources/go/embedProject/go.mod
Original file line number Diff line number Diff line change
@@ -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
)
13 changes: 13 additions & 0 deletions src/test/resources/go/embedProject/main.go
Original file line number Diff line number Diff line change
@@ -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{})
}
Empty file.
Empty file.
Empty file.
2 changes: 1 addition & 1 deletion src/test/resources/go/project2/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
47 changes: 37 additions & 10 deletions src/test/tests/goUtils.test.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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<string, number> = 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
*/
Expand All @@ -140,17 +153,19 @@ describe('Go Utils Tests', async () => {
let expectedChildren: Map<string, number> = 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<string, number> = 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);
});

/**
Expand All @@ -161,7 +176,8 @@ describe('Go Utils Tests', async () => {
let projectName: string = 'project3';
let expectedChildren: Map<string, number> = 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);
});

/**
Expand All @@ -172,7 +188,8 @@ describe('Go Utils Tests', async () => {
let projectName: string = 'project4';
let expectedChildren: Map<string, number> = 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) {
Expand All @@ -195,12 +212,8 @@ describe('Go Utils Tests', async () => {

function validateDependencyTreeResults(projectName: string, expectedChildren: Map<string, number>, 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));
Expand All @@ -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');
});
});
});

0 comments on commit a27a255

Please sign in to comment.