From cccfab91f012da6f004fb13e26063a277eb2e3cc Mon Sep 17 00:00:00 2001 From: Assaf Attias <49212512+attiasas@users.noreply.github.com> Date: Mon, 12 Feb 2024 15:05:31 +0200 Subject: [PATCH 1/3] Use Go-Sec 2.18.0 (#1127) --- .github/workflows/analysis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 5ca78123e..23a98a6e9 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -37,6 +37,7 @@ jobs: go-version: 1.20.x - name: Run Gosec Security Scanner - uses: securego/gosec@master + # Temporarily set version 2.18.0 to workaround https://github.com/securego/gosec/issues/1046 + uses: securego/gosec@v2.18.0 with: args: -exclude G204,G301,G302,G304,G306 -tests -exclude-dir \.*test\.* ./... From d52f433aa28185321ffab76ddedcff28bacb14f3 Mon Sep 17 00:00:00 2001 From: Asaf Ambar Date: Mon, 12 Feb 2024 16:23:42 +0200 Subject: [PATCH 2/3] Maven support for curation audit cmd (#1118) --- .../maven-example-with-many-types/pom.xml | 53 +++++++++++ utils/java/deptreemanager.go | 47 ++++----- utils/java/gradle.go | 2 +- utils/java/mvn.go | 42 +++++--- utils/java/mvn_test.go | 95 ++++++++++++++++++- utils/xray/xrayutils.go | 35 +++++-- 6 files changed, 218 insertions(+), 56 deletions(-) create mode 100644 tests/testdata/maven-example-with-many-types/pom.xml diff --git a/tests/testdata/maven-example-with-many-types/pom.xml b/tests/testdata/maven-example-with-many-types/pom.xml new file mode 100644 index 000000000..6d2096c96 --- /dev/null +++ b/tests/testdata/maven-example-with-many-types/pom.xml @@ -0,0 +1,53 @@ + + 4.0.0 + + org.jfrog + cli-test + 1.0 + jar + + cli-test + http://maven.apache.org + + + UTF-8 + 1.8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + + + + + + + + junit + junit + 4.11 + test + + + commons-io + commons-io + 1.2 + test + + + org.webjars + lodash + 4.17.21 + pom + + + \ No newline at end of file diff --git a/utils/java/deptreemanager.go b/utils/java/deptreemanager.go index 071e2192d..e323fad1e 100644 --- a/utils/java/deptreemanager.go +++ b/utils/java/deptreemanager.go @@ -5,7 +5,6 @@ import ( "os" "strings" - "github.com/jfrog/gofrog/datastructures" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli-core/v2/utils/xray" @@ -17,22 +16,20 @@ const ( GavPackageTypeIdentifier = "gav://" ) -func BuildDependencyTree(serverDetails *config.ServerDetails, depsRepo string, useWrapper, isMavenDepTreeInstalled bool, tech coreutils.Technology) ([]*xrayUtils.GraphNode, []string, error) { - depTreeParams := &DepTreeParams{ - UseWrapper: useWrapper, - Server: serverDetails, - DepsRepo: depsRepo, - } +func BuildDependencyTree(depTreeParams DepTreeParams, tech coreutils.Technology) ([]*xrayUtils.GraphNode, map[string][]string, error) { if tech == coreutils.Maven { - return buildMavenDependencyTree(depTreeParams, isMavenDepTreeInstalled) + return buildMavenDependencyTree(&depTreeParams) } - return buildGradleDependencyTree(depTreeParams) + return buildGradleDependencyTree(&depTreeParams) } type DepTreeParams struct { - UseWrapper bool - Server *config.ServerDetails - DepsRepo string + UseWrapper bool + Server *config.ServerDetails + DepsRepo string + IsMavenDepTreeInstalled bool + IsCurationCmd bool + CurationCacheFolder string } type DepTreeManager struct { @@ -47,36 +44,31 @@ func NewDepTreeManager(params *DepTreeParams) DepTreeManager { // The structure of a dependency tree of a module in a Gradle/Maven project, as created by the gradle-dep-tree and maven-dep-tree plugins. type moduleDepTree struct { - Root string `json:"root"` - Nodes map[string]depTreeNode `json:"nodes"` -} - -type depTreeNode struct { - Children []string `json:"children"` + Root string `json:"root"` + Nodes map[string]xray.DepTreeNode `json:"nodes"` } // Reads the output files of the gradle-dep-tree and maven-dep-tree plugins and returns them as a slice of GraphNodes. // It takes the output of the plugin's run (which is a byte representation of a list of paths of the output files, separated by newlines) as input. -func getGraphFromDepTree(outputFilePaths string) (depsGraph []*xrayUtils.GraphNode, uniqueDeps []string, err error) { +func getGraphFromDepTree(outputFilePaths string) (depsGraph []*xrayUtils.GraphNode, uniqueDepsMap map[string][]string, err error) { modules, err := parseDepTreeFiles(outputFilePaths) if err != nil { return } - allModulesUniqueDeps := datastructures.MakeSet[string]() + uniqueDepsMap = map[string][]string{} for _, module := range modules { moduleTree, moduleUniqueDeps := GetModuleTreeAndDependencies(module) depsGraph = append(depsGraph, moduleTree) - for _, depToAdd := range moduleUniqueDeps { - allModulesUniqueDeps.Add(depToAdd) + for depToAdd, depTypes := range moduleUniqueDeps { + uniqueDepsMap[depToAdd] = depTypes } } - uniqueDeps = allModulesUniqueDeps.ToSlice() return } // Returns a dependency tree and a flat list of the module's dependencies for the given module -func GetModuleTreeAndDependencies(module *moduleDepTree) (*xrayUtils.GraphNode, []string) { - moduleTreeMap := make(map[string][]string) +func GetModuleTreeAndDependencies(module *moduleDepTree) (*xrayUtils.GraphNode, map[string][]string) { + moduleTreeMap := make(map[string]xray.DepTreeNode) moduleDeps := module.Nodes for depName, dependency := range moduleDeps { dependencyId := GavPackageTypeIdentifier + depName @@ -85,8 +77,9 @@ func GetModuleTreeAndDependencies(module *moduleDepTree) (*xrayUtils.GraphNode, childId := GavPackageTypeIdentifier + childName childrenList = append(childrenList, childId) } - if len(childrenList) > 0 { - moduleTreeMap[dependencyId] = childrenList + moduleTreeMap[dependencyId] = xray.DepTreeNode{ + Types: dependency.Types, + Children: childrenList, } } return xray.BuildXrayDependencyTree(moduleTreeMap, GavPackageTypeIdentifier+module.Root) diff --git a/utils/java/gradle.go b/utils/java/gradle.go index 013a2f3a6..57ceff8bd 100644 --- a/utils/java/gradle.go +++ b/utils/java/gradle.go @@ -56,7 +56,7 @@ type gradleDepTreeManager struct { DepTreeManager } -func buildGradleDependencyTree(params *DepTreeParams) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps []string, err error) { +func buildGradleDependencyTree(params *DepTreeParams) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps map[string][]string, err error) { manager := &gradleDepTreeManager{DepTreeManager: NewDepTreeManager(params)} outputFileContent, err := manager.runGradleDepTree() if err != nil { diff --git a/utils/java/mvn.go b/utils/java/mvn.go index 56deee17c..5b38db6c0 100644 --- a/utils/java/mvn.go +++ b/utils/java/mvn.go @@ -7,6 +7,7 @@ import ( "net/url" "os" "os/exec" + "path" "path/filepath" "strings" @@ -21,7 +22,7 @@ const ( mavenDepTreeJarFile = "maven-dep-tree.jar" mavenDepTreeOutputFile = "mavendeptree.out" // Changing this version also requires a change in MAVEN_DEP_TREE_VERSION within buildscripts/download_jars.sh - mavenDepTreeVersion = "1.0.2" + mavenDepTreeVersion = "1.1.0" settingsXmlFile = "settings.xml" ) @@ -42,25 +43,31 @@ var mavenDepTreeJar []byte type MavenDepTreeManager struct { DepTreeManager - isInstalled bool - cmdName MavenDepTreeCmd - settingsXmlPath string + isInstalled bool + // this flag its curation command, it will set dedicated cache and download url. + isCurationCmd bool + // path to the curation dedicated cache + curationCacheFolder string + cmdName MavenDepTreeCmd + settingsXmlPath string } -func NewMavenDepTreeManager(params *DepTreeParams, cmdName MavenDepTreeCmd, isDepTreeInstalled bool) *MavenDepTreeManager { +func NewMavenDepTreeManager(params *DepTreeParams, cmdName MavenDepTreeCmd) *MavenDepTreeManager { depTreeManager := NewDepTreeManager(&DepTreeParams{ Server: params.Server, DepsRepo: params.DepsRepo, }) return &MavenDepTreeManager{ - DepTreeManager: depTreeManager, - isInstalled: isDepTreeInstalled, - cmdName: cmdName, + DepTreeManager: depTreeManager, + isInstalled: params.IsMavenDepTreeInstalled, + cmdName: cmdName, + isCurationCmd: params.IsCurationCmd, + curationCacheFolder: params.CurationCacheFolder, } } -func buildMavenDependencyTree(params *DepTreeParams, isDepTreeInstalled bool) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps []string, err error) { - manager := NewMavenDepTreeManager(params, Tree, isDepTreeInstalled) +func buildMavenDependencyTree(params *DepTreeParams) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps map[string][]string, err error) { + manager := NewMavenDepTreeManager(params, Tree) outputFilePaths, clearMavenDepTreeRun, err := manager.RunMavenDepTree() if err != nil { if clearMavenDepTreeRun != nil { @@ -68,11 +75,9 @@ func buildMavenDependencyTree(params *DepTreeParams, isDepTreeInstalled bool) (d } return } - defer func() { err = errors.Join(err, clearMavenDepTreeRun()) }() - dependencyTree, uniqueDeps, err = getGraphFromDepTree(outputFilePaths) return } @@ -123,6 +128,9 @@ func (mdt *MavenDepTreeManager) execMavenDepTree(depTreeExecDir string) (string, func (mdt *MavenDepTreeManager) runTreeCmd(depTreeExecDir string) (string, error) { mavenDepTreePath := filepath.Join(depTreeExecDir, mavenDepTreeOutputFile) goals := []string{"com.jfrog:maven-dep-tree:" + mavenDepTreeVersion + ":" + string(Tree), "-DdepsTreeOutputFile=" + mavenDepTreePath, "-B"} + if mdt.isCurationCmd { + goals = append(goals, "-Dmaven.repo.local="+mdt.curationCacheFolder) + } if _, err := mdt.RunMvnCmd(goals); err != nil { return "", err } @@ -199,16 +207,20 @@ func removeMavenConfig() (func() error, error) { // Creates a new settings.xml file configured with the provided server and repository from the current MavenDepTreeManager instance. // The settings.xml will be written to the given path. -func (mdt *MavenDepTreeManager) createSettingsXmlWithConfiguredArtifactory(path string) error { +func (mdt *MavenDepTreeManager) createSettingsXmlWithConfiguredArtifactory(settingsXmlPath string) error { username, password, err := getArtifactoryAuthFromServer(mdt.server) if err != nil { return err } - remoteRepositoryFullPath, err := url.JoinPath(mdt.server.ArtifactoryUrl, mdt.depsRepo) + endPoint := mdt.depsRepo + if mdt.isCurationCmd { + endPoint = path.Join("api/curation/audit", endPoint) + } + remoteRepositoryFullPath, err := url.JoinPath(mdt.server.ArtifactoryUrl, endPoint) if err != nil { return err } - mdt.settingsXmlPath = filepath.Join(path, settingsXmlFile) + mdt.settingsXmlPath = filepath.Join(settingsXmlPath, settingsXmlFile) settingsXmlContent := fmt.Sprintf(settingsXmlTemplate, username, password, remoteRepositoryFullPath) return errorutils.CheckError(os.WriteFile(mdt.settingsXmlPath, []byte(settingsXmlContent), 0600)) diff --git a/utils/java/mvn_test.go b/utils/java/mvn_test.go index fb141a3d9..b588806c4 100644 --- a/utils/java/mvn_test.go +++ b/utils/java/mvn_test.go @@ -1,11 +1,14 @@ package java import ( + "github.com/jfrog/build-info-go/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/config" coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "github.com/jfrog/jfrog-client-go/utils/tests" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" "os" "path/filepath" "strings" @@ -32,6 +35,26 @@ const ( * +` + //#nosec G101 - dummy token for testing + settingsXmlWithUsernameAndPasswordAndCurationDedicatedAPi = ` + + + + artifactory + testUser + testPass + + + + + artifactory + https://myartifactory.com/artifactory/api/curation/audit/testRepo + * + + ` //#nosec G101 - dummy token for testing settingsXmlWithUsernameAndToken = ` @@ -95,9 +118,9 @@ func TestMavenTreesMultiModule(t *testing.T) { GavPackageTypeIdentifier + "hsqldb:hsqldb:1.8.0.10", } // Run getModulesDependencyTrees - modulesDependencyTrees, uniqueDeps, err := buildMavenDependencyTree(&DepTreeParams{}, false) + modulesDependencyTrees, uniqueDeps, err := buildMavenDependencyTree(&DepTreeParams{}) if assert.NoError(t, err) && assert.NotEmpty(t, modulesDependencyTrees) { - assert.ElementsMatch(t, uniqueDeps, expectedUniqueDeps, "First is actual, Second is Expected") + assert.ElementsMatch(t, maps.Keys(uniqueDeps), expectedUniqueDeps, "First is actual, Second is Expected") // Check root module multi := coreTests.GetAndAssertNode(t, modulesDependencyTrees, "org.jfrog.test:multi:3.7-SNAPSHOT") if assert.NotNil(t, multi) { @@ -145,9 +168,9 @@ func TestMavenWrapperTrees(t *testing.T) { GavPackageTypeIdentifier + "javax.servlet:servlet-api:2.5", } - modulesDependencyTrees, uniqueDeps, err := buildMavenDependencyTree(&DepTreeParams{}, false) + modulesDependencyTrees, uniqueDeps, err := buildMavenDependencyTree(&DepTreeParams{}) if assert.NoError(t, err) && assert.NotEmpty(t, modulesDependencyTrees) { - assert.ElementsMatch(t, uniqueDeps, expectedUniqueDeps, "First is actual, Second is Expected") + assert.ElementsMatch(t, maps.Keys(uniqueDeps), expectedUniqueDeps, "First is actual, Second is Expected") // Check root module multi := coreTests.GetAndAssertNode(t, modulesDependencyTrees, "org.jfrog.test:multi:3.7-SNAPSHOT") if assert.NotNil(t, multi) { @@ -166,6 +189,58 @@ func TestMavenWrapperTrees(t *testing.T) { } } +func TestMavenWrapperTreesTypes(t *testing.T) { + // Create and change directory to test workspace + _, cleanUp := coreTests.CreateTestWorkspace(t, filepath.Join("..", "..", "tests", "testdata", "maven-example-with-many-types")) + defer cleanUp() + tree, uniqueDeps, err := buildMavenDependencyTree(&DepTreeParams{}) + require.NoError(t, err) + // dependency of pom type + depWithPomType := uniqueDeps["gav://org.webjars:lodash:4.17.21"] + assert.NotEmpty(t, depWithPomType) + assert.Equal(t, depWithPomType[0], "pom") + existInTreePom := false + for _, node := range tree[0].Nodes { + if node.Id == "gav://org.webjars:lodash:4.17.21" { + nodeTypes := *node.Types + assert.Equal(t, nodeTypes[0], "pom") + existInTreePom = true + } + } + assert.True(t, existInTreePom) + + // dependency of jar type + depWithJarType := uniqueDeps["gav://junit:junit:4.11"] + assert.NotEmpty(t, depWithJarType) + assert.Equal(t, depWithJarType[0], "jar") + existInTreeJar := false + for _, node := range tree[0].Nodes { + if node.Id == "gav://junit:junit:4.11" { + nodeTypes := *node.Types + assert.Equal(t, nodeTypes[0], "jar") + existInTreeJar = true + } + } + assert.True(t, existInTreeJar) +} + +func TestDepTreeWithDedicatedCache(t *testing.T) { + // Create and change directory to test workspace + _, cleanUp := coreTests.CreateTestWorkspace(t, filepath.Join("..", "..", "tests", "testdata", "maven-example-with-wrapper")) + err := os.Chmod("mvnw", 0700) + defer cleanUp() + assert.NoError(t, err) + tempDir := t.TempDir() + defer assert.NoError(t, utils.RemoveTempDir(tempDir)) + manager := NewMavenDepTreeManager(&DepTreeParams{IsCurationCmd: true, CurationCacheFolder: tempDir}, Tree) + _, err = manager.runTreeCmd(tempDir) + require.NoError(t, err) + // validate one of the jars exist in the dedicated cache for curation + fileExist, err := utils.IsFileExists(filepath.Join(tempDir, "org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar"), false) + require.NoError(t, err) + assert.True(t, fileExist) +} + func TestGetMavenPluginInstallationArgs(t *testing.T) { args := GetMavenPluginInstallationGoals("testPlugin") assert.Equal(t, "org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file", args[0]) @@ -196,6 +271,16 @@ func TestCreateSettingsXmlWithConfiguredArtifactory(t *testing.T) { assert.NoError(t, err) assert.Equal(t, settingsXmlWithUsernameAndPassword, string(actualContent)) + // check curation command write a dedicated api for curation. + mdt.isCurationCmd = true + err = mdt.createSettingsXmlWithConfiguredArtifactory(tempDir) + require.NoError(t, err) + actualContent, err = os.ReadFile(settingsXmlPath) + actualContent = []byte(strings.ReplaceAll(string(actualContent), "\r\n", "\n")) + assert.NoError(t, err) + assert.Equal(t, settingsXmlWithUsernameAndPasswordAndCurationDedicatedAPi, string(actualContent)) + mdt.isCurationCmd = false + mdt.server.Password = "" // jfrog-ignore mdt.server.AccessToken = dummyToken @@ -223,7 +308,7 @@ func TestRunProjectsCmd(t *testing.T) { // Create and change directory to test workspace _, cleanUp := coreTests.CreateTestWorkspace(t, filepath.Join("..", "..", "tests", "testdata", "maven-example")) defer cleanUp() - mvnDepTreeManager := NewMavenDepTreeManager(&DepTreeParams{}, Projects, false) + mvnDepTreeManager := NewMavenDepTreeManager(&DepTreeParams{}, Projects) output, clearMavenDepTreeRun, err := mvnDepTreeManager.RunMavenDepTree() assert.NoError(t, err) assert.NotNil(t, clearMavenDepTreeRun) diff --git a/utils/xray/xrayutils.go b/utils/xray/xrayutils.go index 7f34d82a6..fc2f0f928 100644 --- a/utils/xray/xrayutils.go +++ b/utils/xray/xrayutils.go @@ -5,7 +5,6 @@ import ( clientconfig "github.com/jfrog/jfrog-client-go/config" "github.com/jfrog/jfrog-client-go/xray" xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils" - "golang.org/x/exp/maps" ) func CreateXrayServiceManager(serviceDetails *config.ServerDetails) (*xray.XrayServicesManager, error) { @@ -36,26 +35,46 @@ func CreateXrayServiceManagerAndGetVersion(serviceDetails *config.ServerDetails) const maxUniqueAppearances = 10 -func BuildXrayDependencyTree(treeHelper map[string][]string, nodeId string) (*xrayUtils.GraphNode, []string) { +type DepTreeNode struct { + Types *[]string `json:"types"` + Children []string `json:"children"` +} + +func toNodeTypesMap(depMap map[string]DepTreeNode) map[string][]string { + mapOfTypes := map[string][]string{} + for nodId, value := range depMap { + mapOfTypes[nodId] = nil + if value.Types != nil { + mapOfTypes[nodId] = *value.Types + } + } + return mapOfTypes +} + +func BuildXrayDependencyTree(treeHelper map[string]DepTreeNode, nodeId string) (*xrayUtils.GraphNode, map[string][]string) { rootNode := &xrayUtils.GraphNode{ Id: nodeId, Nodes: []*xrayUtils.GraphNode{}, } dependencyAppearances := map[string]int8{} - populateXrayDependencyTree(rootNode, treeHelper, &dependencyAppearances) - return rootNode, maps.Keys(dependencyAppearances) + populateXrayDependencyTree(rootNode, treeHelper, dependencyAppearances) + return rootNode, toNodeTypesMap(treeHelper) } -func populateXrayDependencyTree(currNode *xrayUtils.GraphNode, treeHelper map[string][]string, dependencyAppearances *map[string]int8) { - (*dependencyAppearances)[currNode.Id]++ +func populateXrayDependencyTree(currNode *xrayUtils.GraphNode, treeHelper map[string]DepTreeNode, dependencyAppearances map[string]int8) { + dependencyAppearances[currNode.Id]++ + if _, ok := treeHelper[currNode.Id]; !ok { + treeHelper[currNode.Id] = DepTreeNode{} + } // Recursively create & append all node's dependencies. - for _, childDepId := range treeHelper[currNode.Id] { + for _, childDepId := range treeHelper[currNode.Id].Children { childNode := &xrayUtils.GraphNode{ Id: childDepId, Nodes: []*xrayUtils.GraphNode{}, Parent: currNode, + Types: treeHelper[childDepId].Types, } - if (*dependencyAppearances)[childDepId] >= maxUniqueAppearances || childNode.NodeHasLoop() { + if dependencyAppearances[childDepId] >= maxUniqueAppearances || childNode.NodeHasLoop() { continue } currNode.Nodes = append(currNode.Nodes, childNode) From 4bf1fe83505dc6d0431f8b7c478c2158850a7f15 Mon Sep 17 00:00:00 2001 From: Omer Zidkoni <50792403+omerzi@users.noreply.github.com> Date: Tue, 13 Feb 2024 09:51:15 +0200 Subject: [PATCH 3/3] Export "isProcessRunning" (#1126) --- utils/lock/lock.go | 7 ++++--- utils/{lock => osutils}/utils_unix.go | 7 ++++--- utils/{lock => osutils}/utils_windows.go | 7 ++++--- 3 files changed, 12 insertions(+), 9 deletions(-) rename utils/{lock => osutils}/utils_unix.go (93%) rename utils/{lock => osutils}/utils_windows.go (93%) diff --git a/utils/lock/lock.go b/utils/lock/lock.go index 0e8358809..57c5281af 100644 --- a/utils/lock/lock.go +++ b/utils/lock/lock.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/jfrog/jfrog-cli-core/v2/utils/osutils" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "github.com/jfrog/jfrog-client-go/utils/log" @@ -129,9 +130,9 @@ func (lock *Lock) removeOtherLockOrWait(otherLock Lock, filesList *[]string) err log.Debug("Lock hasn't been acquired.") // Check if the process is running. - // There are two implementation of the 'isProcessRunning'. + // There are two implementation of the 'IsProcessRunning'. // One for Windows and one for Unix based systems. - running, err := isProcessRunning(otherLock.pid) + running, err := osutils.IsProcessRunning(otherLock.pid) if err != nil { return err } @@ -241,7 +242,7 @@ func GetLastLockTimestamp(lockDirPath string) (int64, error) { lastLock := locks[len(locks)-1] // If the lock isn't acquired by a running process, an unexpected error was occurred. - running, err := isProcessRunning(lastLock.pid) + running, err := osutils.IsProcessRunning(lastLock.pid) if err != nil { return 0, err } diff --git a/utils/lock/utils_unix.go b/utils/osutils/utils_unix.go similarity index 93% rename from utils/lock/utils_unix.go rename to utils/osutils/utils_unix.go index 476ac23ce..c70c907e5 100644 --- a/utils/lock/utils_unix.go +++ b/utils/osutils/utils_unix.go @@ -1,19 +1,20 @@ //go:build linux || darwin || freebsd // +build linux darwin freebsd -package lock +package osutils import ( - "github.com/jfrog/jfrog-client-go/utils/log" "os" "syscall" + + "github.com/jfrog/jfrog-client-go/utils/log" ) // This file will be compiled only on unix systems. // Checks if the process is running. // If error occurs, check if the error is part of the OS permission errors. This means the process is running. // Else means the process is not running. -func isProcessRunning(pid int) (bool, error) { +func IsProcessRunning(pid int) (bool, error) { process, err := os.FindProcess(pid) if err != nil { return false, err diff --git a/utils/lock/utils_windows.go b/utils/osutils/utils_windows.go similarity index 93% rename from utils/lock/utils_windows.go rename to utils/osutils/utils_windows.go index 504d1c97f..2711fcd1d 100644 --- a/utils/lock/utils_windows.go +++ b/utils/osutils/utils_windows.go @@ -1,15 +1,16 @@ -package lock +package osutils import ( - "github.com/jfrog/jfrog-client-go/utils/errorutils" "syscall" + + "github.com/jfrog/jfrog-client-go/utils/errorutils" ) // This file will be compiled on Windows. // Checks if the process can be reached. // If an error occurs, check if the error is part of the invalid parameter. This means the process is not running. // Else find the exit code. If the exit code 259 means the process is running. -func isProcessRunning(pid int) (bool, error) { +func IsProcessRunning(pid int) (bool, error) { process, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, true, uint32(pid)) if err != nil { // Check if err is of type of syscall.Errno, which is a Windows error number.