Skip to content

Commit

Permalink
Go - Support projects with embed files
Browse files Browse the repository at this point in the history
  • Loading branch information
Or-Geva committed Oct 19, 2023
1 parent 065c8b1 commit af5bf2d
Show file tree
Hide file tree
Showing 10 changed files with 92 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
42 changes: 30 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,10 +204,16 @@ 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) {
walkdir.find(sourceDir, { follow_symlinks: false, sync: true }, function(curPath: string, stat: fs.Stats) {
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 (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.
Expand All @@ -219,20 +230,27 @@ 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;
if (curPath.endsWith('_test.go')) {
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.
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');

// Call the function with test directories
GoUtils.prepareProjectWorkspace(sourceDir, targetDir, '', logManager, () => { return });

// Assert that the .git directory in the source was skipped
assert.isFalse(fs.existsSync(targetDir), 'The target directory should not exist since all files should be excluded');
});
});
});

0 comments on commit af5bf2d

Please sign in to comment.