diff --git a/access_test.go b/access_test.go index ba092b1d1..8374c5b65 100644 --- a/access_test.go +++ b/access_test.go @@ -23,7 +23,7 @@ import ( var ( accessDetails *config.ServerDetails - accessCli *tests.JfrogCli + accessCli *coreTests.JfrogCli accessHttpDetails httputils.HttpClientDetails ) @@ -37,7 +37,7 @@ func initAccessCli() { if accessCli != nil { return } - accessCli = tests.NewJfrogCli(execMain, "jfrog", authenticateAccess()) + accessCli = coreTests.NewJfrogCli(execMain, "jfrog", authenticateAccess()) } func InitAccessTests() { @@ -115,7 +115,7 @@ func TestRefreshableAccessTokens(t *testing.T) { defer deleteServerConfig(t) // Upload a file and assert the refreshable tokens were generated. - artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "") + artifactoryCommandExecutor := coreTests.NewJfrogCli(execMain, "jfrog rt", "") uploadedFiles := 1 err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/a1.in", uploadedFiles) if !assert.NoError(t, err) { @@ -260,7 +260,7 @@ func TestAccessTokenCreate(t *testing.T) { assertNotEmptyIfExpected(t, test.expectedReference, token.ReferenceToken) // Try pinging Artifactory with the new token. - assert.NoError(t, tests.NewJfrogCli(execMain, "jfrog rt", + assert.NoError(t, coreTests.NewJfrogCli(execMain, "jfrog rt", "--url="+*tests.JfrogUrl+tests.ArtifactoryEndpoint+" --access-token="+token.AccessToken).Exec("ping")) }) } diff --git a/artifactory/cli.go b/artifactory/cli.go index 12c21dac5..ef9ce9081 100644 --- a/artifactory/cli.go +++ b/artifactory/cli.go @@ -31,13 +31,14 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" containerutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" "github.com/jfrog/jfrog-cli-core/v2/common/build" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" + "github.com/jfrog/jfrog-cli-core/v2/common/progressbar" "github.com/jfrog/jfrog-cli-core/v2/common/project" "github.com/jfrog/jfrog-cli-core/v2/common/spec" corecommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" coreConfig "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/ioutils" "github.com/jfrog/jfrog-cli/buildtools" "github.com/jfrog/jfrog-cli/docs/artifactory/accesstokencreate" "github.com/jfrog/jfrog-cli/docs/artifactory/buildadddependencies" @@ -110,7 +111,6 @@ import ( "github.com/jfrog/jfrog-cli/docs/artifactory/yarnconfig" "github.com/jfrog/jfrog-cli/docs/common" "github.com/jfrog/jfrog-cli/utils/cliutils" - "github.com/jfrog/jfrog-cli/utils/progressbar" buildinfocmd "github.com/jfrog/jfrog-client-go/artifactory/buildinfo" "github.com/jfrog/jfrog-client-go/artifactory/services" clientutils "github.com/jfrog/jfrog-client-go/utils" @@ -2682,23 +2682,11 @@ func createDefaultBuildAddDependenciesSpec(c *cli.Context) *spec.SpecFiles { func fixWinPathsForDownloadCmd(uploadSpec *spec.SpecFiles, c *cli.Context) { if coreutils.IsWindows() { for i, file := range uploadSpec.Files { - uploadSpec.Files[i].Target = fixWinPathBySource(file.Target, c.IsSet("spec")) + uploadSpec.Files[i].Target = commonCliUtils.FixWinPathBySource(file.Target, c.IsSet("spec")) } } } -func fixWinPathBySource(path string, fromSpec bool) string { - if strings.Count(path, "/") > 0 { - // Assuming forward slashes - not doubling backslash to allow regexp escaping - return ioutils.UnixToWinPathSeparator(path) - } - if fromSpec { - // Doubling backslash only for paths from spec files (that aren't forward slashed) - return ioutils.DoubleWinPathSeparator(path) - } - return path -} - func createUploadConfiguration(c *cli.Context) (uploadConfiguration *utils.UploadConfiguration, err error) { uploadConfiguration = new(utils.UploadConfiguration) uploadConfiguration.Threads, err = cliutils.GetThreadsCount(c) diff --git a/artifactory_test.go b/artifactory_test.go index 028321b80..bbcd133c9 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -30,9 +30,11 @@ import ( "github.com/jfrog/gofrog/version" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" "github.com/jfrog/jfrog-cli-core/v2/common/project" "github.com/jfrog/jfrog-cli-core/v2/common/spec" + commontests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "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/dependencies" @@ -68,13 +70,13 @@ import ( const terraformMinArtifactoryVersion = "7.38.4" // JFrog CLI for Artifactory sub-commands (jfrog rt ...) -var artifactoryCli *tests.JfrogCli +var artifactoryCli *coretests.JfrogCli // JFrog CLI for Platform commands (jfrog ...) -var platformCli *tests.JfrogCli +var platformCli *coretests.JfrogCli // JFrog CLI for config command only (doesn't pass the --ssh-passphrase flag) -var configCli *tests.JfrogCli +var configCli *coretests.JfrogCli var serverDetails *config.ServerDetails var artAuth auth.ServiceDetails @@ -126,11 +128,11 @@ func authenticate(configCli bool) string { // A Jfrog CLI to be used to execute a config task. // Removed the ssh-passphrase flag that cannot be passed to with a config command -func createConfigJfrogCLI(cred string) *tests.JfrogCli { +func createConfigJfrogCLI(cred string) *coretests.JfrogCli { if strings.Contains(cred, " --ssh-passphrase=") { cred = strings.ReplaceAll(cred, " --ssh-passphrase="+*tests.JfrogSshPassphrase, "") } - return tests.NewJfrogCli(execMain, "jfrog config", cred) + return coretests.NewJfrogCli(execMain, "jfrog config", cred) } func getArtifactoryTestCredentials() string { @@ -212,7 +214,7 @@ func TestArtifactorySimpleUploadSpecUsingConfig(t *testing.T) { passphrase, err := createServerConfigAndReturnPassphrase(t) defer deleteServerConfig(t) assert.NoError(t, err) - artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "") + artifactoryCommandExecutor := coretests.NewJfrogCli(execMain, "jfrog rt", "") specFile, err := tests.CreateSpec(tests.UploadFlatRecursive) assert.NoError(t, err) assert.NoError(t, artifactoryCommandExecutor.Exec("upload", "--spec="+specFile, "--server-id="+tests.ServerId, passphrase)) @@ -349,7 +351,7 @@ func TestArtifactoryDownloadFromVirtual(t *testing.T) { func TestArtifactoryDownloadAndUploadWithProgressBar(t *testing.T) { initArtifactoryTest(t, "") - callback := tests.MockProgressInitialization() + callback := commontests.MockProgressInitialization() defer callback() runRt(t, "upload", "testdata/a/*", tests.RtRepo1, "--flat=false") @@ -793,7 +795,7 @@ func verifyUsersExistInArtifactory(csvFilePath string, t *testing.T) { break } user, password := record[0], record[1] - err = tests.NewJfrogCli(execMain, "jfrog rt", "--url="+serverDetails.ArtifactoryUrl+" --user="+user+" --password="+password).Exec("ping") + err = coretests.NewJfrogCli(execMain, "jfrog rt", "--url="+serverDetails.ArtifactoryUrl+" --user="+user+" --password="+password).Exec("ping") assert.NoError(t, err) } @@ -1805,7 +1807,7 @@ func TestXrayScanBuild(t *testing.T) { initArtifactoryTest(t, "") xrayServerPort := xray.StartXrayMockServer() serverUrl := "--url=http://localhost:" + strconv.Itoa(xrayServerPort) - artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", serverUrl+getArtifactoryTestCredentials()) + artifactoryCommandExecutor := coretests.NewJfrogCli(execMain, "jfrog rt", serverUrl+getArtifactoryTestCredentials()) assert.NoError(t, artifactoryCommandExecutor.Exec("build-scan", xray.CleanScanBuildName, "3")) cleanArtifactoryTest() @@ -3090,7 +3092,7 @@ func prepareDownloadByBuildWithDependenciesTests(t *testing.T) { runRt(t, "upload", "--spec="+specFileB) // Add build dependencies. - artifactoryCliNoCreds := tests.NewJfrogCli(execMain, "jfrog rt", "") + artifactoryCliNoCreds := coretests.NewJfrogCli(execMain, "jfrog rt", "") assert.NoError(t, artifactoryCliNoCreds.Exec("bad", "--spec="+specFileB, tests.RtBuildName1, buildNumber)) // Publish build. @@ -4222,7 +4224,7 @@ func TestUploadDetailedSummary(t *testing.T) { func createUploadConfiguration() *utils.UploadConfiguration { uploadConfiguration := new(utils.UploadConfiguration) - uploadConfiguration.Threads = cliutils.Threads + uploadConfiguration.Threads = commonCliUtils.Threads return uploadConfiguration } @@ -5098,9 +5100,9 @@ func TestConfigEncryption(t *testing.T) { assert.NoError(t, configCli.Exec("add", "server-2")) // Expect no error after reading it - assert.NoError(t, tests.NewJfrogCli(execMain, "jfrog config", "").Exec("show")) - assert.NoError(t, tests.NewJfrogCli(execMain, "jfrog rt", "--server-id=server-1").Exec("ping")) - assert.NoError(t, tests.NewJfrogCli(execMain, "jfrog rt", "--server-id=server-2").Exec("ping")) + assert.NoError(t, coretests.NewJfrogCli(execMain, "jfrog config", "").Exec("show")) + assert.NoError(t, coretests.NewJfrogCli(execMain, "jfrog rt", "--server-id=server-1").Exec("ping")) + assert.NoError(t, coretests.NewJfrogCli(execMain, "jfrog rt", "--server-id=server-2").Exec("ping")) } func TestConfigEncryptionMissingKey(t *testing.T) { @@ -5194,7 +5196,7 @@ func pipeStdinSecret(t *testing.T, secret string) func() { func TestArtifactoryReplicationCreate(t *testing.T) { initArtifactoryTest(t, "") // Configure server with dummy credentials - err := tests.NewJfrogCli(execMain, "jfrog config", "").Exec("add", tests.ServerId, "--artifactory-url="+*tests.JfrogUrl+tests.ArtifactoryEndpoint, "--user=admin", "--password=password", "--enc-password=false") + err := coretests.NewJfrogCli(execMain, "jfrog config", "").Exec("add", tests.ServerId, "--artifactory-url="+*tests.JfrogUrl+tests.ArtifactoryEndpoint, "--user=admin", "--password=password", "--enc-password=false") defer deleteServerConfig(t) assert.NoError(t, err) @@ -5244,7 +5246,7 @@ func TestArtifactoryAccessTokenCreate(t *testing.T) { *tests.JfrogAccessToken = origAccessToken }() *tests.JfrogAccessToken = "" - err := tests.NewJfrogCli(execMain, "jfrog rt", authenticate(false)).Exec("atc") + err := coretests.NewJfrogCli(execMain, "jfrog rt", authenticate(false)).Exec("atc") assert.NoError(t, err) } else { runRt(t, "atc") @@ -5273,7 +5275,7 @@ func checkAccessToken(t *testing.T, buffer *bytes.Buffer) { assert.NoError(t, err) // Try ping with the new token - err = tests.NewJfrogCli(execMain, "jfrog rt", "--url="+*tests.JfrogUrl+tests.ArtifactoryEndpoint+" --access-token="+token).Exec("ping") + err = coretests.NewJfrogCli(execMain, "jfrog rt", "--url="+*tests.JfrogUrl+tests.ArtifactoryEndpoint+" --access-token="+token).Exec("ping") assert.NoError(t, err) } @@ -5290,7 +5292,7 @@ func TestRefreshableArtifactoryTokens(t *testing.T) { assert.NoError(t, err) // Upload a file and assert the refreshable tokens were generated. - artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "") + artifactoryCommandExecutor := coretests.NewJfrogCli(execMain, "jfrog rt", "") uploadedFiles := 1 err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/a1.in", uploadedFiles) if err != nil { @@ -5415,7 +5417,7 @@ func assertTokensChanged(t *testing.T, curAccessToken, curRefreshToken string) ( return newAccessToken, newRefreshToken, nil } -func uploadWithSpecificServerAndVerify(t *testing.T, cli *tests.JfrogCli, source string, expectedResults int) error { +func uploadWithSpecificServerAndVerify(t *testing.T, cli *coretests.JfrogCli, source string, expectedResults int) error { err := cli.Exec("upload", source, tests.RtRepo1, "--server-id="+tests.ServerId) if err != nil { assert.NoError(t, err) diff --git a/buildinfo_test.go b/buildinfo_test.go index a86de6eb9..b783aa706 100644 --- a/buildinfo_test.go +++ b/buildinfo_test.go @@ -161,7 +161,7 @@ func TestBuildAddDependenciesDryRun(t *testing.T) { chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, "testdata") defer chdirCallback() - noCredsCli := tests.NewJfrogCli(execMain, "jfrog rt", "") + noCredsCli := coretests.NewJfrogCli(execMain, "jfrog rt", "") // Execute the bad command on the local file system assert.NoError(t, noCredsCli.Exec("bad", tests.RtBuildName1, "1", "a/*", "--dry-run=true")) buildDir, err := build.GetBuildDir(tests.RtBuildName1, "1", "") @@ -660,7 +660,7 @@ func TestBuildAddGitEnvBuildNameAndNumber(t *testing.T) { func testBuildAddGit(t *testing.T, useEnvBuildNameAndNumber bool) { initArtifactoryTest(t, "") - gitCollectCliRunner := tests.NewJfrogCli(execMain, "jfrog rt", "") + gitCollectCliRunner := coretests.NewJfrogCli(execMain, "jfrog rt", "") buildNumber := "13" // Populate cli config with 'default' server @@ -843,7 +843,7 @@ func TestModuleName(t *testing.T) { } func collectDepsAndPublishBuild(badTest buildAddDepsBuildInfoTestParams, useEnvBuildNameAndNumber bool, t *testing.T) { - noCredsCli := tests.NewJfrogCli(execMain, "jfrog rt", "") + noCredsCli := coretests.NewJfrogCli(execMain, "jfrog rt", "") // Remove old tests data from fs if exists err := build.RemoveBuildDir(badTest.buildName, badTest.buildNumber, "") assert.NoError(t, err) diff --git a/buildtools/cli.go b/buildtools/cli.go index 082d79d2f..92c09bd69 100644 --- a/buildtools/cli.go +++ b/buildtools/cli.go @@ -19,6 +19,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/yarn" containerutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" "github.com/jfrog/jfrog-cli-core/v2/common/build" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" outputFormat "github.com/jfrog/jfrog-cli-core/v2/common/format" "github.com/jfrog/jfrog-cli-core/v2/common/project" @@ -602,7 +603,7 @@ func extractThreadsFlag(args []string) (cleanArgs []string, threadsCount int, er cleanArgs = append([]string(nil), args...) threadsFlagIndex, threadsValueIndex, threads, err := coreutils.FindFlag("--threads", cleanArgs) if err != nil || threadsFlagIndex < 0 { - threadsCount = cliutils.Threads + threadsCount = commonCliUtils.Threads return } coreutils.RemoveFlagFromCommand(&cleanArgs, threadsFlagIndex, threadsValueIndex) diff --git a/completion_test.go b/completion_test.go index 944b94fcc..040e9125d 100644 --- a/completion_test.go +++ b/completion_test.go @@ -3,6 +3,7 @@ package main import ( "testing" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/completion/shells/bash" "github.com/jfrog/jfrog-cli/completion/shells/zsh" "github.com/jfrog/jfrog-cli/utils/tests" @@ -10,21 +11,21 @@ import ( ) func TestBashCompletion(t *testing.T) { - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") content, err := tests.GetCmdOutput(t, jfrogCli, "completion", "bash") assert.NoError(t, err) assert.Equal(t, bash.BashAutocomplete, string(content)) } func TestZshCompletion(t *testing.T) { - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") content, err := tests.GetCmdOutput(t, jfrogCli, "completion", "zsh") assert.NoError(t, err) assert.Equal(t, zsh.ZshAutocomplete, string(content)) } func TestFishCompletion(t *testing.T) { - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") content, err := tests.GetCmdOutput(t, jfrogCli, "completion", "fish") assert.NoError(t, err) assert.Contains(t, string(content), "complete -c") diff --git a/distribution/cli.go b/distribution/cli.go index 0a0664a29..bc118b1e3 100644 --- a/distribution/cli.go +++ b/distribution/cli.go @@ -2,6 +2,7 @@ package distribution import ( "errors" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" "github.com/jfrog/jfrog-cli-core/v2/common/spec" distributionCommands "github.com/jfrog/jfrog-cli-core/v2/distribution/commands" @@ -311,7 +312,7 @@ func populateReleaseNotesSyntax(c *cli.Context) (distributionServicesUtils.Relea } func createDistributionDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { - dsDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, cliutils.Ds) + dsDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, commonCliUtils.Ds) if err != nil { return nil, err } diff --git a/distribution_test.go b/distribution_test.go index 5c5d12869..c1d5751a7 100644 --- a/distribution_test.go +++ b/distribution_test.go @@ -36,7 +36,7 @@ var ( distAuth auth.ServiceDetails distHttpDetails httputils.HttpClientDetails // JFrog CLI for Distribution commands - distributionCli *tests.JfrogCli + distributionCli *coreTests.JfrogCli ) func InitDistributionTests() { @@ -80,7 +80,7 @@ func initDistributionCli() { return } cred := authenticateDistribution() - distributionCli = tests.NewJfrogCli(execMain, "jfrog ds", cred) + distributionCli = coreTests.NewJfrogCli(execMain, "jfrog ds", cred) } func initDistributionTest(t *testing.T) { @@ -610,7 +610,7 @@ func TestDistributeSyncTimeout(t *testing.T) { maxWaitMinutes := 1 distributionRulesPath := filepath.Join(tests.GetTestResourcesPath(), "distribution", tests.DistributionRules) - mockDsCli := tests.NewJfrogCli(execMain, "jfrog ds", "--url="+mockServerDetails.DistributionUrl) + mockDsCli := coreTests.NewJfrogCli(execMain, "jfrog ds", "--url="+mockServerDetails.DistributionUrl) err := mockDsCli.Exec("rbd", tests.BundleName, bundleVersion, "--dist-rules="+distributionRulesPath, "--sync", "--max-wait-minutes="+strconv.Itoa(maxWaitMinutes), "--create-repo") assert.ErrorContains(t, err, "executor timeout after") assert.ErrorAs(t, err, &clientUtils.RetryExecutorTimeoutError{}) diff --git a/docker_test.go b/docker_test.go index 28a9b79e9..154dd78e7 100644 --- a/docker_test.go +++ b/docker_test.go @@ -19,7 +19,9 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" "github.com/jfrog/jfrog-cli-core/v2/common/build" "github.com/jfrog/jfrog-cli-core/v2/common/spec" + commonTests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/inttestutils" "github.com/jfrog/jfrog-cli/utils/tests" "github.com/jfrog/jfrog-client-go/auth" @@ -105,7 +107,7 @@ func TestContainerPushWithDetailedSummary(t *testing.T) { func() { imageTag, err := inttestutils.BuildTestImage(imageName+":1", "", repo, containerManager) assert.NoError(t, err) - defer inttestutils.DeleteTestImage(t, imageTag, containerManager) + defer commonTests.DeleteTestImage(t, imageTag, containerManager) // Testing detailed summary without build-info pushCommand := coreContainer.NewPushCommand(containerManager) pushCommand.SetThreads(1).SetDetailedSummary(true).SetCmdParams([]string{"push", imageTag}).SetBuildConfiguration(new(build.BuildConfiguration)).SetRepo(tests.DockerLocalRepo).SetServerDetails(serverDetails).SetImageTag(imageTag) @@ -159,7 +161,7 @@ func TestContainerPushWithMultipleSlash(t *testing.T) { func runPushTest(containerManager container.ContainerManagerType, imageName, module string, withModule bool, t *testing.T, repo string) { imageTag, err := inttestutils.BuildTestImage(imageName+":1", "", repo, containerManager) assert.NoError(t, err) - defer inttestutils.DeleteTestImage(t, imageTag, containerManager) + defer commonTests.DeleteTestImage(t, imageTag, containerManager) buildNumber := "1" if withModule { @@ -290,7 +292,7 @@ func TestContainerPushBuildNameNumberFromEnv(t *testing.T) { func() { imageTag, err := inttestutils.BuildTestImage(tests.DockerImageName+":1", "", tests.DockerLocalRepo, containerManager) assert.NoError(t, err) - defer inttestutils.DeleteTestImage(t, imageTag, containerManager) + defer commonTests.DeleteTestImage(t, imageTag, containerManager) buildNumber := "1" setEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, coreutils.BuildName, tests.DockerBuildName) defer setEnvCallBack() @@ -313,7 +315,7 @@ func TestContainerPull(t *testing.T) { func() { imageName, err := inttestutils.BuildTestImage(tests.DockerImageName+":1", "", tests.DockerLocalRepo, containerManager) assert.NoError(t, err) - defer inttestutils.DeleteTestImage(t, imageName, containerManager) + defer commonTests.DeleteTestImage(t, imageName, containerManager) for _, repo := range []string{tests.DockerVirtualRepo, tests.DockerLocalRepo} { // Push container image @@ -353,7 +355,7 @@ func TestContainerFatManifestPull(t *testing.T) { func() { // Pull container image imageTag := path.Join(*tests.ContainerRegistry, dockerRepo, imageName+":2.2") - defer inttestutils.DeleteTestImage(t, imageTag, containerManager) + defer commonTests.DeleteTestImage(t, imageTag, containerManager) runCmdWithRetries(t, jfrogRtCliTask(containerManager.String()+"-pull", imageTag, dockerRepo, "--build-name="+tests.DockerBuildName, "--build-number="+buildNumber)) runRt(t, "build-publish", tests.DockerBuildName, buildNumber) @@ -383,7 +385,7 @@ func TestDockerPromote(t *testing.T) { // Build and push image imageName, err := inttestutils.BuildTestImage(tests.DockerImageName+":1", "", tests.DockerLocalRepo, container.DockerClient) assert.NoError(t, err) - defer inttestutils.DeleteTestImage(t, imageName, container.DockerClient) + defer commonTests.DeleteTestImage(t, imageName, container.DockerClient) // Push image runCmdWithRetries(t, jfrogRtCliTask("docker-push", imageName, tests.DockerLocalRepo)) @@ -517,13 +519,13 @@ func TestNativeDockerPushPull(t *testing.T) { runRt(t, "build-publish", tests.DockerBuildName, pushBuildNumber) imagePath := path.Join(tests.DockerLocalRepo, tests.DockerImageName, pushBuildNumber) + "/" validateContainerBuild(tests.DockerBuildName, pushBuildNumber, imagePath, module, 7, 5, 7, t) - inttestutils.DeleteTestImage(t, image, container.DockerClient) + commonTests.DeleteTestImage(t, image, container.DockerClient) runCmdWithRetries(t, jfCliTask("docker", "-D", "pull", image, "--build-name="+tests.DockerBuildName, "--build-number="+pullBuildNumber, "--module="+module)) runRt(t, "build-publish", tests.DockerBuildName, pullBuildNumber) imagePath = path.Join(tests.DockerLocalRepo, tests.DockerImageName, pullBuildNumber) + "/" validateContainerBuild(tests.DockerBuildName, pullBuildNumber, imagePath, module, 0, 7, 0, t) - inttestutils.DeleteTestImage(t, image, container.DockerClient) + commonTests.DeleteTestImage(t, image, container.DockerClient) inttestutils.ContainerTestCleanup(t, serverDetails, artHttpDetails, tests.DockerImageName, tests.DockerBuildName, tests.DockerLocalRepo) } @@ -557,7 +559,7 @@ func jfrogRtCliTask(args ...string) func() error { func jfCliTask(args ...string) func() error { return func() error { - return tests.NewJfrogCli(execMain, "jf", "").WithoutCredentials().Exec(args...) + return coreTests.NewJfrogCli(execMain, "jf", "").WithoutCredentials().Exec(args...) } } diff --git a/general/envsetup/envsetup.go b/general/envsetup/envsetup.go index 2a261f463..db6cee91b 100644 --- a/general/envsetup/envsetup.go +++ b/general/envsetup/envsetup.go @@ -1,10 +1,10 @@ package envsetup import ( + "github.com/jfrog/jfrog-cli-core/v2/common/progressbar" "github.com/jfrog/jfrog-cli-core/v2/general/envsetup" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli/utils/cliutils" - "github.com/jfrog/jfrog-cli/utils/progressbar" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/urfave/cli" ) diff --git a/general/token/cli.go b/general/token/cli.go index 748a0f0a1..bb35fd983 100644 --- a/general/token/cli.go +++ b/general/token/cli.go @@ -3,6 +3,7 @@ package token import ( "errors" "fmt" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" generic "github.com/jfrog/jfrog-cli-core/v2/general/token" coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -67,7 +68,7 @@ func AccessTokenCreateCmd(c *cli.Context) error { } func createPlatformDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { - platformDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, cliutils.Platform) + platformDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, commonCliUtils.Platform) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index 011fab6f9..c0459a6cc 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.23.0 github.com/urfave/cli v1.22.14 - github.com/vbauerster/mpb/v7 v7.5.3 github.com/xeipuuv/gojsonschema v1.2.0 golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc golang.org/x/term v0.16.0 @@ -106,6 +105,7 @@ require ( github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/ulikunitz/xz v0.5.9 // indirect + github.com/vbauerster/mpb/v7 v7.5.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect @@ -128,9 +128,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240107151040-a15eecc3fe2d - -// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20231220105505-e62769dde9da +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240110073910-2461fe7e7b4f // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20231220102935-c8776c613ad8 diff --git a/go.sum b/go.sum index af6b4d436..09ec6fdbc 100644 --- a/go.sum +++ b/go.sum @@ -135,8 +135,8 @@ github.com/jfrog/gofrog v1.5.0 h1:OLaXpNaEniliE4Kq8lJ5evVYzzt3zdYtpMIBu6TO++c= github.com/jfrog/gofrog v1.5.0/go.mod h1:wQqagqq2VpuCWRPlq/65GbH9gsRz+7Bgc1Q+PKD4Y+k= github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY= github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240107151040-a15eecc3fe2d h1:zuTDefsqMTdOyGe9eKxvAiXrYIyKWAJ9D7bLIPiGgls= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240107151040-a15eecc3fe2d/go.mod h1:dFpRoGR5/Qe+bvszvRPYGqMEdwmjNhjFLXlovGs9sII= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240110073910-2461fe7e7b4f h1:UETEUtFCOm0bhd7AeRgaf9QxPsSgnPgHgjfo7OHOOXQ= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240110073910-2461fe7e7b4f/go.mod h1:dFpRoGR5/Qe+bvszvRPYGqMEdwmjNhjFLXlovGs9sII= github.com/jfrog/jfrog-client-go v1.35.6 h1:nVS94x6cwSRkhtj8OM3elbUcGgQhqsK8YMPvC/gf5sk= github.com/jfrog/jfrog-client-go v1.35.6/go.mod h1:V+XKC27k6GA5OcWIAItpnxZAZnCigg8xCkpXKP905Fk= github.com/jszwec/csvutil v1.9.0 h1:iTmq9G1P0e+AUq/MkFg6tetJ+1BH3fOX8Xi0RAcwiGc= diff --git a/go_test.go b/go_test.go index 153892df6..77bfff423 100644 --- a/go_test.go +++ b/go_test.go @@ -52,7 +52,7 @@ func TestGoGetSpecificVersion(t *testing.T) { runGo(t, "", tests.GoBuildName, buildNumber, 4, 0, "go", "build", "--mod=mod", "--build-name="+tests.GoBuildName, "--build-number="+buildNumber) // Go get one of the known dependencies - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") err = execGo(jfrogCli, "go", "get", "rsc.io/quote@v1.5.2", "--build-name="+tests.GoBuildName, "--build-number="+buildNumber) if err != nil { assert.NoError(t, err) @@ -90,7 +90,7 @@ func TestGoGetNestedPackage(t *testing.T) { wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") prepareGoProject("project1", t, true) - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") // Download 'mockgen', which is a nested package inside 'github.com/golang/mock@v1.4.1'. Then validate it was downloaded correctly. err = execGo(jfrogCli, "go", "get", "github.com/golang/mock/mockgen@v1.4.1") @@ -152,7 +152,7 @@ func TestGoPublishWithDetailedSummary(t *testing.T) { // Publish with detailed summary and buildinfo. // Build project buildNumber := "1" - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") assert.NoError(t, execGo(jfrogCli, "go", "build", "--mod=mod", "--build-name="+tests.GoBuildName, "--build-number="+buildNumber, "--module="+ModuleNameJFrogTest)) // GoPublish with detailed summary without buildinfo. @@ -193,7 +193,7 @@ func TestGoPublishWithDeploymentView(t *testing.T) { wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") prepareGoProject("project1", t, true) - jfrogCli := tests.NewJfrogCli(execMain, "jf", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jf", "") err = execGo(jfrogCli, "gp", "v1.1.1") if err != nil { assert.NoError(t, err) @@ -224,7 +224,7 @@ func TestGoPublishWithExclusions(t *testing.T) { } for _, test := range testData { prepareGoProject("project4", t, true) - jfrogCli := tests.NewJfrogCli(execMain, "jf", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jf", "") err = execGo(jfrogCli, "gp", "v1.1.1", "--exclusions", test.exclusions) assert.NoError(t, err) @@ -263,7 +263,7 @@ func TestGoVcsFallback(t *testing.T) { assert.NoError(t, err, "Failed to get current dir") _ = prepareGoProject("vcsfallback", t, false) - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") // Run "go get github.com/octocat/Hello-World" with --no-fallback. // This package is not a Go package, and therefore we'd expect the command to fail. err = execGo(jfrogCli, "go", "get", "github.com/octocat/Hello-World", "--no-fallback") @@ -341,7 +341,7 @@ func createGoProject(t *testing.T, projectName string, includeDirs bool) string // runGo runs 'jfrog' command with the given args, publishes a build info, validates it and finally deletes it. func runGo(t *testing.T, module, buildName, buildNumber string, expectedDependencies, expectedArtifacts int, args ...string) { - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") err := execGo(jfrogCli, args...) if err != nil { assert.NoError(t, err) @@ -372,7 +372,7 @@ func runGo(t *testing.T, module, buildName, buildNumber string, expectedDependen validateBuildInfo(buildInfo, t, expectedDependencies, expectedArtifacts, module, buildinfo.Go) } -func execGo(cli *tests.JfrogCli, args ...string) error { +func execGo(cli *coretests.JfrogCli, args ...string) error { return cli.WithoutCredentials().Exec(args...) } diff --git a/inttestutils/distribution.go b/inttestutils/distribution.go index 8e13aab6b..90b1bfde0 100644 --- a/inttestutils/distribution.go +++ b/inttestutils/distribution.go @@ -11,8 +11,8 @@ import ( "time" "github.com/jfrog/jfrog-cli-core/v2/common/spec" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/buger/jsonparser" "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -220,7 +220,7 @@ func getLocalBundle(t *testing.T, bundleName, bundleVersion string, distHttpDeta return resp, body } -func CleanUpOldBundles(distHttpDetails httputils.HttpClientDetails, bundleVersion string, distributionCli *tests.JfrogCli) { +func CleanUpOldBundles(distHttpDetails httputils.HttpClientDetails, bundleVersion string, distributionCli *coreTests.JfrogCli) { getActualItems := func() ([]string, error) { return ListAllBundlesNames(distHttpDetails) } deleteItem := func(bundleName string) { err := distributionCli.Exec("rbdel", bundleName, bundleVersion, "--site=*", "--delete-from-dist", "--quiet") diff --git a/inttestutils/docker.go b/inttestutils/docker.go index 5b537d2db..5fdc2d946 100644 --- a/inttestutils/docker.go +++ b/inttestutils/docker.go @@ -1,8 +1,6 @@ package inttestutils import ( - "io" - "os/exec" "path" "path/filepath" "strings" @@ -14,6 +12,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" + commonTests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli/utils/tests" "github.com/jfrog/jfrog-client-go/utils/io/httputils" @@ -21,194 +20,14 @@ import ( "github.com/stretchr/testify/assert" ) -// Image get parent image id command -type BuildDockerImage struct { - // The build command builds images from a Dockerfile and a context. - // A build's context is the set of files located in the specified PATH. - // The build process can refer to any of the files in the context. - // For example, The build can use a COPY instruction to reference a file in the context. - buildContext string - dockerFileName string - imageName string - containerManager container.ContainerManagerType -} - -func NewBuildDockerImage(imageTag, dockerFilePath string, containerManager container.ContainerManagerType) *BuildDockerImage { - return &BuildDockerImage{imageName: imageTag, buildContext: dockerFilePath, containerManager: containerManager} -} - -func (image *BuildDockerImage) SetDockerFileName(name string) *BuildDockerImage { - image.dockerFileName = name - return image -} - -func (image *BuildDockerImage) GetCmd() *exec.Cmd { - var cmd []string - cmd = append(cmd, "build") - cmd = append(cmd, "--tag", image.imageName) - if image.dockerFileName != "" { - cmd = append(cmd, "--file", path.Join(image.buildContext, image.dockerFileName)) - - } - cmd = append(cmd, image.buildContext) - return exec.Command(image.containerManager.String(), cmd...) -} - -func (image *BuildDockerImage) GetEnv() map[string]string { - return map[string]string{} -} - -func (image *BuildDockerImage) GetStdWriter() io.WriteCloser { - return nil -} - -func (image *BuildDockerImage) GetErrWriter() io.WriteCloser { - return nil -} - -// The ExecDockerImage command runs a new command in a running container. -type ExecDockerImage struct { - Args []string - errCloser io.WriteCloser - stdWriter io.WriteCloser - containerManager container.ContainerManagerType -} - -func NewExecDockerImage(containerManager container.ContainerManagerType, args ...string) *ExecDockerImage { - return &ExecDockerImage{Args: args, containerManager: containerManager} -} - -func (e *ExecDockerImage) GetCmd() *exec.Cmd { - var cmd []string - cmd = append(cmd, "exec") - cmd = append(cmd, e.Args...) - return exec.Command(e.containerManager.String(), cmd...) -} - -func (e *ExecDockerImage) GetEnv() map[string]string { - return map[string]string{} -} - -func (e *ExecDockerImage) GetStdWriter() io.WriteCloser { - return e.stdWriter -} - -func (e *ExecDockerImage) SetStdWriter(writer io.WriteCloser) { - e.stdWriter = writer -} - -func (e *ExecDockerImage) GetErrWriter() io.WriteCloser { - return e.errCloser -} - -func (e *ExecDockerImage) SetErrWriter(writer io.WriteCloser) { - e.errCloser = writer -} - -type RunDockerImage struct { - Args []string - containerManager container.ContainerManagerType -} - -func NewRunDockerImage(containerManager container.ContainerManagerType, args ...string) *RunDockerImage { - return &RunDockerImage{Args: args, containerManager: containerManager} -} - -func (run *RunDockerImage) GetCmd() *exec.Cmd { - var cmd []string - cmd = append(cmd, "run") - cmd = append(cmd, run.Args...) - return exec.Command(run.containerManager.String(), cmd...) -} - -func (run *RunDockerImage) GetEnv() map[string]string { - return map[string]string{} -} - -func (run *RunDockerImage) GetStdWriter() io.WriteCloser { - return nil -} - -func (run *RunDockerImage) GetErrWriter() io.WriteCloser { - return nil -} - -type DeleteDockerImage struct { - imageTag string - containerManager container.ContainerManagerType -} - -func NewDeleteDockerImage(imageTag string, containerManager container.ContainerManagerType) *DeleteDockerImage { - return &DeleteDockerImage{imageTag: imageTag, containerManager: containerManager} -} - -func (image *DeleteDockerImage) GetCmd() *exec.Cmd { - var cmd []string - cmd = append(cmd, "image") - cmd = append(cmd, "rm") - cmd = append(cmd, image.imageTag) - return exec.Command(image.containerManager.String(), cmd...) -} - -func (image *DeleteDockerImage) GetEnv() map[string]string { - return map[string]string{} -} - -func (image *DeleteDockerImage) GetStdWriter() io.WriteCloser { - return nil -} - -func (image *DeleteDockerImage) GetErrWriter() io.WriteCloser { - return nil -} - -type DeleteContainer struct { - containerName string - containerManager container.ContainerManagerType -} - -func NewDeleteContainer(containerName string, containerManager container.ContainerManagerType) *DeleteContainer { - return &DeleteContainer{containerName: containerName, containerManager: containerManager} -} - -func (image *DeleteContainer) GetCmd() *exec.Cmd { - var cmd []string - cmd = append(cmd, "rm") - cmd = append(cmd, "--force") - cmd = append(cmd, image.containerName) - return exec.Command(image.containerManager.String(), cmd...) -} - -func (image *DeleteContainer) GetEnv() map[string]string { - return map[string]string{} -} - -func (image *DeleteContainer) GetStdWriter() io.WriteCloser { - return nil -} - -func (image *DeleteContainer) GetErrWriter() io.WriteCloser { - return nil -} - func BuildTestImage(imageName, dockerfileName, repo string, containerManagerType container.ContainerManagerType) (string, error) { log.Info("Building image", imageName, "with", containerManagerType.String()) imageName = path.Join(*tests.ContainerRegistry, repo, imageName) dockerFilePath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "docker") - imageBuilder := NewBuildDockerImage(imageName, dockerFilePath, containerManagerType).SetDockerFileName(dockerfileName) + imageBuilder := commonTests.NewBuildDockerImage(imageName, dockerFilePath, containerManagerType).SetDockerFileName(dockerfileName) return imageName, gofrogcmd.RunCmd(imageBuilder) } -func DeleteTestImage(t *testing.T, imageTag string, containerManagerType container.ContainerManagerType) { - imageBuilder := NewDeleteDockerImage(imageTag, containerManagerType) - assert.NoError(t, gofrogcmd.RunCmd(imageBuilder)) -} - -func DeleteTestContainer(t *testing.T, containerName string, containerManagerType container.ContainerManagerType) { - containerDelete := NewDeleteContainer(containerName, containerManagerType) - assert.NoError(t, gofrogcmd.RunCmd(containerDelete)) -} - func ContainerTestCleanup(t *testing.T, serverDetails *config.ServerDetails, artHttpDetails httputils.HttpClientDetails, imageName, buildName, repo string) { // Remove build from Artifactory DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) diff --git a/inttestutils/transfer.go b/inttestutils/transfer.go index 1422d5649..53338bed6 100644 --- a/inttestutils/transfer.go +++ b/inttestutils/transfer.go @@ -13,6 +13,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/common/spec" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/utils/tests" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/io/httputils" @@ -27,7 +28,7 @@ const ( // Create test repositories in the target Artifactory // targetArtifactoryCli - Target Artifactory CLI -func CreateTargetRepos(targetArtifactoryCli *tests.JfrogCli) { +func CreateTargetRepos(targetArtifactoryCli *coreTests.JfrogCli) { log.Info("Creating repositories in target Artifactory...") for _, template := range tests.CreatedNonVirtualRepositories { repoTemplate := filepath.Join("testdata", template) @@ -39,7 +40,7 @@ func CreateTargetRepos(targetArtifactoryCli *tests.JfrogCli) { // Delete test repositories in the target Artifactory // targetArtifactoryCli - Target Artifactory CLI -func DeleteTargetRepos(targetArtifactoryCli *tests.JfrogCli) { +func DeleteTargetRepos(targetArtifactoryCli *coreTests.JfrogCli) { for repoKey := range tests.CreatedNonVirtualRepositories { coreutils.ExitOnErr(targetArtifactoryCli.Exec("repo-delete", *repoKey)) } @@ -47,7 +48,7 @@ func DeleteTargetRepos(targetArtifactoryCli *tests.JfrogCli) { // Clean test repositories content in the target Artifactory // targetArtifactoryCli - Target Artifactory CLI -func CleanTargetRepos(targetArtifactoryCli *tests.JfrogCli) { +func CleanTargetRepos(targetArtifactoryCli *coreTests.JfrogCli) { for repoKey := range tests.CreatedNonVirtualRepositories { coreutils.ExitOnErr(targetArtifactoryCli.Exec("del", *repoKey)) } @@ -73,7 +74,7 @@ func AuthenticateTarget() (string, *config.ServerDetails, *httputils.HttpClientD // sourceArtifactoryCli - Source Artifactory CLI // serverDetails - Source server details // t - The testing object -func UploadTransferTestFilesAndAssert(sourceArtifactoryCli *tests.JfrogCli, serverDetails *config.ServerDetails, t *testing.T) (string, string) { +func UploadTransferTestFilesAndAssert(sourceArtifactoryCli *coreTests.JfrogCli, serverDetails *config.ServerDetails, t *testing.T) (string, string) { // Upload files assert.NoError(t, sourceArtifactoryCli.Exec("upload", "testdata/a/*", tests.RtRepo1)) assert.NoError(t, sourceArtifactoryCli.Exec("upload", "testdata/a/b/*", tests.RtRepo2)) @@ -130,7 +131,7 @@ func WaitForCreationInArtifactory(pattern string, serverDetails *config.ServerDe // wg - Wait group to update when done // filesTransferFinished - Changes to true when the file transfer process finished // t - The testing object -func AsyncExecTransferFiles(artifactoryCli *tests.JfrogCli, wg *sync.WaitGroup, filesTransferFinished *bool, t *testing.T) { +func AsyncExecTransferFiles(artifactoryCli *coreTests.JfrogCli, wg *sync.WaitGroup, filesTransferFinished *bool, t *testing.T) { wg.Add(1) go func() { defer func() { diff --git a/lifecycle/cli.go b/lifecycle/cli.go index eaf201222..e4b29edbd 100644 --- a/lifecycle/cli.go +++ b/lifecycle/cli.go @@ -2,6 +2,7 @@ package lifecycle import ( "errors" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" coreCommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" "github.com/jfrog/jfrog-cli-core/v2/lifecycle" @@ -169,7 +170,7 @@ func assertSigningKeyProvided(c *cli.Context) error { } func createLifecycleDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { - lcDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, cliutils.Platform) + lcDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, commonCliUtils.Platform) if err != nil { return nil, err } diff --git a/lifecycle_test.go b/lifecycle_test.go index 719834409..1519f0197 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -6,6 +6,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" configUtils "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/inttestutils" lifecycleCli "github.com/jfrog/jfrog-cli/lifecycle" "github.com/jfrog/jfrog-cli/utils/cliutils" @@ -37,7 +38,7 @@ const ( var ( lcDetails *configUtils.ServerDetails - lcCli *tests.JfrogCli + lcCli *coreTests.JfrogCli ) func TestLifecycle(t *testing.T) { @@ -254,7 +255,7 @@ func initLifecycleCli() { if lcCli != nil { return } - lcCli = tests.NewJfrogCli(execMain, "jfrog", authenticateLifecycle()) + lcCli = coreTests.NewJfrogCli(execMain, "jfrog", authenticateLifecycle()) } func CleanLifecycleTests() { diff --git a/main_test.go b/main_test.go index ca2f51214..e4b6fd3b5 100644 --- a/main_test.go +++ b/main_test.go @@ -133,11 +133,11 @@ func createJfrogHomeConfig(t *testing.T, encryptPassword bool) { // Delete the default server if exist config, err := commands.GetConfig("default", false) if err == nil && config.ServerId != "" { - err = tests.NewJfrogCli(execMain, "jfrog config", "").Exec("rm", "default", "--quiet") + err = coreTests.NewJfrogCli(execMain, "jfrog config", "").Exec("rm", "default", "--quiet") assert.NoError(t, err) } *tests.JfrogUrl = utils.AddTrailingSlashIfNeeded(*tests.JfrogUrl) - err = tests.NewJfrogCli(execMain, "jfrog config", credentials).Exec("add", "default", "--interactive=false", "--url="+*tests.JfrogUrl, "--enc-password="+strconv.FormatBool(encryptPassword)) + err = coreTests.NewJfrogCli(execMain, "jfrog config", credentials).Exec("add", "default", "--interactive=false", "--url="+*tests.JfrogUrl, "--enc-password="+strconv.FormatBool(encryptPassword)) assert.NoError(t, err) } @@ -185,11 +185,11 @@ func initArtifactoryCli() { return } *tests.JfrogUrl = utils.AddTrailingSlashIfNeeded(*tests.JfrogUrl) - artifactoryCli = tests.NewJfrogCli(execMain, "jfrog rt", authenticate(false)) + artifactoryCli = coreTests.NewJfrogCli(execMain, "jfrog rt", authenticate(false)) if (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestPlugins || *tests.TestArtifactoryProject || *tests.TestAccess || *tests.TestTransfer || *tests.TestLifecycle { configCli = createConfigJfrogCLI(authenticate(true)) - platformCli = tests.NewJfrogCli(execMain, "jfrog", authenticate(false)) + platformCli = coreTests.NewJfrogCli(execMain, "jfrog", authenticate(false)) } } @@ -239,7 +239,7 @@ func runJfrogCli(t *testing.T, args ...string) { } func runJfrogCliWithoutAssertion(args ...string) error { - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") return jfrogCli.Exec(args...) } diff --git a/maven_test.go b/maven_test.go index 7d3958ca1..bd6a46421 100644 --- a/maven_test.go +++ b/maven_test.go @@ -148,7 +148,7 @@ func TestInsecureTlsMavenBuild(t *testing.T) { oldHomeDir := changeWD(t, pomDir) defer clientTestUtils.ChangeDirAndAssert(t, oldHomeDir) - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") // First, try to run without the insecure-tls flag, failure is expected. err = jfrogCli.Exec("mvn", "clean", "install", "-B", repoLocalSystemProp) diff --git a/missioncontrol/cli.go b/missioncontrol/cli.go index 4e7a6341a..d086d1832 100644 --- a/missioncontrol/cli.go +++ b/missioncontrol/cli.go @@ -3,6 +3,7 @@ package missioncontrol import ( "strconv" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" coreCommonCommands "github.com/jfrog/jfrog-cli-core/v2/common/commands" corecommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" "github.com/jfrog/jfrog-cli-core/v2/missioncontrol/commands" @@ -140,7 +141,7 @@ func licenseRelease(c *cli.Context) error { } func offerConfig(c *cli.Context) (*config.ServerDetails, error) { - confirmed, err := cliutils.ShouldOfferConfig() + confirmed, err := commonCliUtils.ShouldOfferConfig() if !confirmed || err != nil { return nil, err } diff --git a/npm_test.go b/npm_test.go index 55e6bc843..564cfbe96 100644 --- a/npm_test.go +++ b/npm_test.go @@ -353,7 +353,7 @@ func prepareArtifactoryForNpmBuild(t *testing.T, workingDirectory string) { caches := ioutils.DoubleWinPathSeparator(filepath.Join(workingDirectory, "caches")) // Run install with -cache argument to download the artifacts from Artifactory // This done to be sure the artifacts exists in Artifactory - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") assert.NoError(t, jfrogCli.Exec("npm", "install", "-cache="+caches)) clientTestUtils.RemoveAllAndAssert(t, filepath.Join(workingDirectory, "node_modules")) @@ -508,7 +508,7 @@ func TestYarn(t *testing.T) { assert.NoError(t, yarn.ConfigSet("unsafeHttpWhitelist", origWhitelist, yarnExecPath, true)) }() - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") assert.NoError(t, jfrogCli.Exec("yarn", "--build-name="+tests.YarnBuildName, "--build-number=1", "--module="+ModuleNameJFrogTest)) validateNpmLocalBuildInfo(t, tests.YarnBuildName, "1", ModuleNameJFrogTest) @@ -563,7 +563,7 @@ func TestGenericNpm(t *testing.T) { chdirCallBack := clientTestUtils.ChangeDirWithCallback(t, wd, npmPath) defer chdirCallBack() - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") args := []string{"npm", "version"} output := jfrogCli.WithoutCredentials().RunCliCmdWithOutput(t, args...) assert.Contains(t, output, "'jfrog-cli-tests': 'v1.0.0'") @@ -573,6 +573,6 @@ func TestGenericNpm(t *testing.T) { } func runGenericNpm(t *testing.T, args ...string) { - jfCli := tests.NewJfrogCli(execMain, "jf", "") + jfCli := coretests.NewJfrogCli(execMain, "jf", "") assert.NoError(t, jfCli.WithoutCredentials().Exec(args...)) } diff --git a/nuget_test.go b/nuget_test.go index c8bf733d2..e8b42d2bb 100644 --- a/nuget_test.go +++ b/nuget_test.go @@ -184,7 +184,7 @@ func assertNugetMultiPackagesConfigDependencies(t *testing.T, module buildInfo.M } func runNuGet(t *testing.T, args ...string) error { - artifactoryNuGetCli := tests.NewJfrogCli(execMain, "jfrog", "") + artifactoryNuGetCli := coreTests.NewJfrogCli(execMain, "jfrog", "") err := artifactoryNuGetCli.Exec(args...) assert.NoError(t, err) return err diff --git a/pip_test.go b/pip_test.go index 70772e6ec..fac79e04b 100644 --- a/pip_test.go +++ b/pip_test.go @@ -112,7 +112,7 @@ func testPipCmd(t *testing.T, projectPath, buildNumber, module string, expectedD args = append(args, "--build-number="+buildNumber) - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") err = jfrogCli.Exec(args...) if err != nil { assert.Fail(t, "Failed executing pip install command", err.Error()) diff --git a/pipenv_test.go b/pipenv_test.go index f5b7b9bc6..807690135 100644 --- a/pipenv_test.go +++ b/pipenv_test.go @@ -9,6 +9,7 @@ import ( buildinfo "github.com/jfrog/build-info-go/entities" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/inttestutils" "github.com/jfrog/jfrog-cli/utils/tests" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" @@ -66,7 +67,7 @@ func testPipenvCmd(t *testing.T, projectPath, buildNumber, module string, args [ args = append(args, "--build-number="+buildNumber) - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") err = jfrogCli.WithoutCredentials().Exec(args...) if err != nil { assert.Fail(t, "Failed executing pipenv-install command", err.Error()) diff --git a/plugins/commands/install.go b/plugins/commands/install.go index e1bd7e70d..913d043a4 100644 --- a/plugins/commands/install.go +++ b/plugins/commands/install.go @@ -14,9 +14,9 @@ import ( commandsUtils "github.com/jfrog/jfrog-cli/plugins/commands/utils" clientUtils "github.com/jfrog/jfrog-client-go/utils" + "github.com/jfrog/jfrog-cli-core/v2/common/progressbar" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli/utils/cliutils" - "github.com/jfrog/jfrog-cli/utils/progressbar" "github.com/jfrog/jfrog-client-go/http/httpclient" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" diff --git a/plugins/commands/publish.go b/plugins/commands/publish.go index 8d740b62c..9bb76dc78 100644 --- a/plugins/commands/publish.go +++ b/plugins/commands/publish.go @@ -6,6 +6,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic" commandsutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" rtutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/spec" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" @@ -303,6 +304,6 @@ func createResourcesUploadSpec(source, target string) *spec.SpecFiles { func createUploadConfiguration() *rtutils.UploadConfiguration { uploadConfiguration := new(rtutils.UploadConfiguration) - uploadConfiguration.Threads = cliutils.Threads + uploadConfiguration.Threads = commonCliUtils.Threads return uploadConfiguration } diff --git a/plugins_test.go b/plugins_test.go index dcbe0e187..d0cd684c0 100644 --- a/plugins_test.go +++ b/plugins_test.go @@ -11,6 +11,7 @@ import ( clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" "github.com/buger/jsonparser" + commonTests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/plugins" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" pluginsutils "github.com/jfrog/jfrog-cli-core/v2/utils/plugins" @@ -47,7 +48,7 @@ func TestPluginInstallUninstallOfficialRegistry(t *testing.T) { clientTestUtils.SetEnvAndAssert(t, utils.PluginsRepoEnv, oldRepo) }() clientTestUtils.SetEnvAndAssert(t, utils.PluginsRepoEnv, "") - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") // Try installing a plugin with specific version. err = installAndAssertPlugin(t, jfrogCli, officialPluginVersion) @@ -76,7 +77,7 @@ func TestPluginInstallUninstallOfficialRegistry(t *testing.T) { func TestPluginInstallWithProgressBar(t *testing.T) { initPluginsTest(t) - callback := tests.MockProgressInitialization() + callback := commonTests.MockProgressInitialization() defer callback() // Create temp jfrog home @@ -97,7 +98,7 @@ func TestPluginInstallWithProgressBar(t *testing.T) { clientTestUtils.SetEnvAndAssert(t, utils.PluginsRepoEnv, oldRepo) }() clientTestUtils.SetEnvAndAssert(t, utils.PluginsRepoEnv, "") - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") // Try installing a plugin with specific version. err = installAndAssertPlugin(t, jfrogCli, officialPluginVersion) @@ -112,7 +113,7 @@ func TestPluginInstallWithProgressBar(t *testing.T) { } } -func installAndAssertPlugin(t *testing.T, jfrogCli *tests.JfrogCli, pluginVersion string) error { +func installAndAssertPlugin(t *testing.T, jfrogCli *coreTests.JfrogCli, pluginVersion string) error { // If version required, concat to plugin name identifier := officialPluginForTest if pluginVersion != "" { @@ -138,7 +139,7 @@ func installAndAssertPlugin(t *testing.T, jfrogCli *tests.JfrogCli, pluginVersio return verifyPluginVersion(t, jfrogCli, pluginVersion) } -func verifyPluginSignature(t *testing.T, jfrogCli *tests.JfrogCli) error { +func verifyPluginSignature(t *testing.T, jfrogCli *coreTests.JfrogCli) error { // Get signature from plugin. content, err := tests.GetCmdOutput(t, jfrogCli, officialPluginForTest, plugins.SignatureCommandName) if err != nil { @@ -163,7 +164,7 @@ func verifyPluginSignature(t *testing.T, jfrogCli *tests.JfrogCli) error { return nil } -func verifyPluginVersion(t *testing.T, jfrogCli *tests.JfrogCli, expectedVersion string) error { +func verifyPluginVersion(t *testing.T, jfrogCli *coreTests.JfrogCli, expectedVersion string) error { // Run plugin's -v command. content, err := tests.GetCmdOutput(t, jfrogCli, officialPluginForTest, "-v") if err != nil { @@ -264,7 +265,7 @@ func TestPublishInstallCustomServer(t *testing.T) { func testPublishAndInstall(t *testing.T, resources bool) { // Publish the CLI as a plugin to the registry. - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") err := jfrogCli.Exec("plugin", "p", customPluginName, cliutils.GetVersion()) if err != nil { assert.NoError(t, err) diff --git a/scan/cli.go b/scan/cli.go index 43301312c..e9efabc25 100644 --- a/scan/cli.go +++ b/scan/cli.go @@ -7,8 +7,9 @@ import ( "os" "strings" - "github.com/jfrog/jfrog-cli/utils/progressbar" + "github.com/jfrog/jfrog-cli-core/v2/common/progressbar" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" outputFormat "github.com/jfrog/jfrog-cli-core/v2/common/format" "github.com/jfrog/jfrog-cli-core/v2/common/spec" @@ -196,7 +197,7 @@ func AuditCmd(c *cli.Context) error { } func AuditSpecificCmd(c *cli.Context, technology coreutils.Technology) error { - cliutils.LogNonGenericAuditCommandDeprecation(c.Command.Name) + commonCliUtils.LogNonGenericAuditCommandDeprecation(c.Command.Name) auditCmd, err := createAuditCmd(c) if err != nil { return err diff --git a/transfer_test.go b/transfer_test.go index 943476aa5..592dc9ea3 100644 --- a/transfer_test.go +++ b/transfer_test.go @@ -37,7 +37,7 @@ import ( var targetArtHttpDetails *httputils.HttpClientDetails var targetServerDetails *config.ServerDetails -var targetArtifactoryCli *tests.JfrogCli +var targetArtifactoryCli *coretests.JfrogCli func InitTransferTests() { initArtifactoryCli() @@ -47,7 +47,7 @@ func InitTransferTests() { createRequiredRepos() var creds string creds, targetServerDetails, targetArtHttpDetails = inttestutils.AuthenticateTarget() - targetArtifactoryCli = tests.NewJfrogCli(execMain, "jfrog rt", creds) + targetArtifactoryCli = coretests.NewJfrogCli(execMain, "jfrog rt", creds) inttestutils.CreateTargetRepos(targetArtifactoryCli) } @@ -77,7 +77,7 @@ func initTransferTest(t *testing.T) func() { assert.NoError(t, err) } *tests.JfrogUrl = utils.AddTrailingSlashIfNeeded(*tests.JfrogUrl) - err = tests.NewJfrogCli(execMain, "jfrog config", "--access-token="+*tests.JfrogTargetAccessToken).Exec("add", inttestutils.TargetServerId, "--interactive=false", "--url="+*tests.JfrogTargetUrl) + err = coretests.NewJfrogCli(execMain, "jfrog config", "--access-token="+*tests.JfrogTargetAccessToken).Exec("add", inttestutils.TargetServerId, "--interactive=false", "--url="+*tests.JfrogTargetUrl) assert.NoError(t, err) if *tests.InstallDataTransferPlugin { diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index 6cd1a2f8d..7067f5e05 100644 --- a/utils/cliutils/cli_consts.go +++ b/utils/cliutils/cli_consts.go @@ -27,15 +27,13 @@ const ( // Common Retries = 3 RetryWaitMilliSecs = 0 - Threads = 3 ArtifactoryTokenExpiry = 3600 DefaultLicenseCount = 1 LatestCliVersionCheckInterval = time.Hour * 6 // Env - BuildUrl = "JFROG_CLI_BUILD_URL" - EnvExclude = "JFROG_CLI_ENV_EXCLUDE" - UserAgent = "JFROG_CLI_USER_AGENT" - JfrogCliAvoidDeprecationWarnings = "JFROG_CLI_AVOID_DEPRECATION_WARNINGS" - JfrogCliAvoidNewVersionWarning = "JFROG_CLI_AVOID_NEW_VERSION_WARNING" + BuildUrl = "JFROG_CLI_BUILD_URL" + EnvExclude = "JFROG_CLI_ENV_EXCLUDE" + UserAgent = "JFROG_CLI_USER_AGENT" + JfrogCliAvoidNewVersionWarning = "JFROG_CLI_AVOID_NEW_VERSION_WARNING" ) diff --git a/utils/cliutils/codegangstautils.go b/utils/cliutils/codegangstautils.go index 5df4443b0..036936332 100644 --- a/utils/cliutils/codegangstautils.go +++ b/utils/cliutils/codegangstautils.go @@ -1,12 +1,12 @@ package cliutils import ( - "errors" "golang.org/x/exp/slices" "sort" "strconv" "strings" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-client-go/utils" "github.com/urfave/cli" ) @@ -28,15 +28,7 @@ func GetStringsArrFlagValue(c *cli.Context, flagName string) (resultArray []stri } func GetThreadsCount(c *cli.Context) (threads int, err error) { - threads = Threads - if c.String("threads") != "" { - threads, err = strconv.Atoi(c.String("threads")) - if err != nil || threads < 1 { - err = errors.New("the '--threads' option should have a numeric positive value") - return 0, err - } - } - return threads, nil + return commonCliUtils.GetThreadsCount(c.String("threads")) } func ExtractCommand(c *cli.Context) []string { diff --git a/utils/cliutils/commandsflags.go b/utils/cliutils/commandsflags.go index 3607aafd9..6a410f23d 100644 --- a/utils/cliutils/commandsflags.go +++ b/utils/cliutils/commandsflags.go @@ -5,6 +5,7 @@ import ( "sort" "strconv" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli-core/v2/xray/commands/offlineupdate" @@ -711,7 +712,7 @@ var flagsMap = map[string]cli.Flag{ threads: cli.StringFlag{ Name: threads, Value: "", - Usage: "[Default: " + strconv.Itoa(Threads) + "] Number of working threads.` `", + Usage: "[Default: " + strconv.Itoa(commonCliUtils.Threads) + "] Number of working threads.` `", }, retries: cli.StringFlag{ Name: retries, @@ -1140,7 +1141,7 @@ var flagsMap = map[string]cli.Flag{ deploymentThreads: cli.StringFlag{ Name: threads, Value: "", - Usage: "[Default: " + strconv.Itoa(Threads) + "] Number of threads for uploading build artifacts.` `", + Usage: "[Default: " + strconv.Itoa(commonCliUtils.Threads) + "] Number of threads for uploading build artifacts.` `", }, skipLogin: cli.BoolFlag{ Name: skipLogin, diff --git a/utils/cliutils/utils.go b/utils/cliutils/utils.go index fe9b7f32e..7cff55dc9 100644 --- a/utils/cliutils/utils.go +++ b/utils/cliutils/utils.go @@ -4,8 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/jfrog/gofrog/version" - "github.com/jfrog/jfrog-client-go/utils/log" "io" "net/http" "os" @@ -14,17 +12,21 @@ import ( "strings" "time" + "github.com/jfrog/gofrog/version" + "github.com/jfrog/jfrog-client-go/utils/log" + corecontainercmds "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/container" commandUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" artifactoryUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" containerutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" buildUtils "github.com/jfrog/jfrog-cli-core/v2/common/build" - coreCommonCommands "github.com/jfrog/jfrog-cli-core/v2/common/commands" + "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" + commonCommands "github.com/jfrog/jfrog-cli-core/v2/common/commands" "github.com/jfrog/jfrog-cli-core/v2/common/project" speccore "github.com/jfrog/jfrog-cli-core/v2/common/spec" coreConfig "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/ioutils" "github.com/jfrog/jfrog-cli/utils/summary" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" @@ -32,15 +34,6 @@ import ( "github.com/urfave/cli" ) -type CommandDomain string - -const ( - Rt CommandDomain = "rt" - Ds CommandDomain = "ds" - Xr CommandDomain = "xr" - Platform CommandDomain = "platform" -) - // Error modes (how should the application behave when the CheckError function is invoked): type OnError string @@ -261,16 +254,11 @@ func CreateBuildInfoSummaryReportString(success, failed int, sha256 string, err } func PrintHelpAndReturnError(msg string, context *cli.Context) error { - log.Error(msg + " " + GetDocumentationMessage()) - err := cli.ShowCommandHelp(context, context.Command.Name) - if err != nil { - msg = msg + ". " + err.Error() - } - return errors.New(msg) + return commonCliUtils.PrintHelpAndReturnError(msg, GetPrintCurrentCmdHelp(context)) } func WrongNumberOfArgumentsHandler(context *cli.Context) error { - return PrintHelpAndReturnError(fmt.Sprintf("Wrong number of arguments (%d).", context.NArg()), context) + return commonCliUtils.WrongNumberOfArgumentsHandler(context.NArg(), GetPrintCurrentCmdHelp(context)) } // This function indicates whether the command should be executed without @@ -335,31 +323,6 @@ func getOrDefaultEnv(arg, envKey string) string { return os.Getenv(envKey) } -func ShouldOfferConfig() (bool, error) { - exists, err := coreConfig.IsServerConfExists() - if err != nil || exists { - return false, err - } - var ci bool - if ci, err = clientutils.GetBoolEnvValue(coreutils.CI, false); err != nil { - return false, err - } - if ci { - return false, nil - } - - msg := fmt.Sprintf("To avoid this message in the future, set the %s environment variable to true.\n"+ - "The CLI commands require the URL and authentication details\n"+ - "Configuring JFrog CLI with these parameters now will save you having to include them as command options.\n"+ - "You can also configure these parameters later using the 'jfrog c' command.\n"+ - "Configure now?", coreutils.CI) - confirmed := coreutils.AskYesNo(msg, false) - if !confirmed { - return false, nil - } - return true, nil -} - func CreateServerDetailsFromFlags(c *cli.Context) (details *coreConfig.ServerDetails, err error) { details = new(coreConfig.ServerDetails) details.Url = clientutils.AddTrailingSlashIfNeeded(c.String(url)) @@ -390,34 +353,7 @@ func CreateServerDetailsFromFlags(c *cli.Context) (details *coreConfig.ServerDet } func handleSecretInput(c *cli.Context, stringFlag, stdinFlag string) (secret string, err error) { - secret = c.String(stringFlag) - isStdinSecret := c.Bool(stdinFlag) - if isStdinSecret && secret != "" { - err = errorutils.CheckErrorf("providing both %s and %s flags is not supported", stringFlag, stdinFlag) - return - } - - if isStdinSecret { - var stat os.FileInfo - stat, err = os.Stdin.Stat() - if err != nil { - return - } - if (stat.Mode() & os.ModeCharDevice) == 0 { - var rawSecret []byte - rawSecret, err = io.ReadAll(os.Stdin) - if err != nil { - return - } - secret = strings.TrimSpace(string(rawSecret)) - if secret != "" { - log.Debug("Using", stringFlag, "provided via Stdin") - return - } - } - err = errorutils.CheckErrorf("no %s provided via Stdin", stringFlag) - } - return + return commonCliUtils.HandleSecretInput(stringFlag, c.String(stringFlag), stdinFlag, c.Bool(stdinFlag)) } func GetSpec(c *cli.Context, isDownload bool) (specFiles *speccore.SpecFiles, err error) { @@ -435,6 +371,19 @@ func GetSpec(c *cli.Context, isDownload bool) (specFiles *speccore.SpecFiles, er return } +func GetFileSystemSpec(c *cli.Context) (fsSpec *speccore.SpecFiles, err error) { + fsSpec, err = speccore.CreateSpecFromFile(c.String("spec"), coreutils.SpecVarsStringToMap(c.String("spec-vars"))) + if err != nil { + return + } + // Override spec with CLI options + for i := 0; i < len(fsSpec.Files); i++ { + fsSpec.Get(i).Target = strings.TrimPrefix(fsSpec.Get(i).Target, "/") + OverrideFieldsIfSet(fsSpec.Get(i), c) + } + return +} + // If `fieldName` exist in the cli args, read it to `field` as a string. func overrideStringIfSet(field *string, c *cli.Context, fieldName string) { if c.IsSet(fieldName) { @@ -456,81 +405,25 @@ func overrideIntIfSet(field *int, c *cli.Context, fieldName string) { } } -func offerConfig(c *cli.Context, domain CommandDomain) (*coreConfig.ServerDetails, error) { - confirmed, err := ShouldOfferConfig() - if !confirmed || err != nil { - return nil, err - } - details, err := createServerDetailsFromFlags(c, domain) - if err != nil { - return nil, err - } - configCmd := coreCommonCommands.NewConfigCommand(coreCommonCommands.AddOrEdit, details.ServerId).SetDefaultDetails(details).SetInteractive(true).SetEncPassword(true) - err = configCmd.Run() - if err != nil { - return nil, err - } - - return configCmd.ServerDetails() -} - // Exclude refreshable tokens parameter should be true when working with external tools (build tools, curl, etc) // or when sending requests not via ArtifactoryHttpClient. -func CreateServerDetailsWithConfigOffer(c *cli.Context, excludeRefreshableTokens bool, domain CommandDomain) (*coreConfig.ServerDetails, error) { - createdDetails, err := offerConfig(c, domain) - if err != nil { - return nil, err - } - if createdDetails != nil { - return createdDetails, err - } - - details, err := createServerDetailsFromFlags(c, domain) - if err != nil { - return nil, err - } - // If urls or credentials were passed as options, use options as they are. - // For security reasons, we'd like to avoid using part of the connection details from command options and the rest from the config. - // Either use command options only or config only. - if credentialsChanged(details) { - return details, nil - } - - // Else, use details from config for requested serverId, or for default server if empty. - confDetails, err := coreCommonCommands.GetConfig(details.ServerId, excludeRefreshableTokens) - if err != nil { - return nil, err - } - - // Take insecureTls value from options since it is not saved in config. - confDetails.InsecureTls = details.InsecureTls - confDetails.Url = clientutils.AddTrailingSlashIfNeeded(confDetails.Url) - confDetails.DistributionUrl = clientutils.AddTrailingSlashIfNeeded(confDetails.DistributionUrl) - - // Create initial access token if needed. - if !excludeRefreshableTokens { - err = coreConfig.CreateInitialRefreshableTokensIfNeeded(confDetails) - if err != nil { - return nil, err - } - } - - return confDetails, nil +func CreateServerDetailsWithConfigOffer(c *cli.Context, excludeRefreshableTokens bool, domain cliutils.CommandDomain) (*coreConfig.ServerDetails, error) { + return cliutils.CreateServerDetailsWithConfigOffer(func() (*coreConfig.ServerDetails, error) { return createServerDetailsFromFlags(c, domain) }, excludeRefreshableTokens) } -func createServerDetailsFromFlags(c *cli.Context, domain CommandDomain) (details *coreConfig.ServerDetails, err error) { +func createServerDetailsFromFlags(c *cli.Context, domain cliutils.CommandDomain) (details *coreConfig.ServerDetails, err error) { details, err = CreateServerDetailsFromFlags(c) if err != nil { return } switch domain { - case Rt: + case cliutils.Rt: details.ArtifactoryUrl = details.Url - case Xr: + case cliutils.Xr: details.XrayUrl = details.Url - case Ds: + case cliutils.Ds: details.DistributionUrl = details.Url - case Platform: + case cliutils.Platform: return } details.Url = "" @@ -538,24 +431,17 @@ func createServerDetailsFromFlags(c *cli.Context, domain CommandDomain) (details return } -func credentialsChanged(details *coreConfig.ServerDetails) bool { - return details.Url != "" || details.ArtifactoryUrl != "" || details.DistributionUrl != "" || details.XrayUrl != "" || - details.User != "" || details.Password != "" || details.SshKeyPath != "" || details.SshPassphrase != "" || details.AccessToken != "" || - details.ClientCertKeyPath != "" || details.ClientCertPath != "" +func GetPrintCurrentCmdHelp(c *cli.Context) func() error { + return func() error { + return cli.ShowCommandHelp(c, c.Command.Name) + } } // This function checks whether the command received --help as a single option. // If it did, the command's help is shown and true is returned. // This function should be used iff the SkipFlagParsing option is used. func ShowCmdHelpIfNeeded(c *cli.Context, args []string) (bool, error) { - if len(args) != 1 { - return false, nil - } - if args[0] == "--help" || args[0] == "-h" { - err := cli.ShowCommandHelp(c, c.Command.Name) - return true, err - } - return false, nil + return commonCliUtils.ShowCmdHelpIfNeeded(args, GetPrintCurrentCmdHelp(c)) } // This function checks whether the command received --help as a single option. @@ -574,19 +460,6 @@ func ShowGenericCmdHelpIfNeeded(c *cli.Context, args []string, cmdName string) ( return false, nil } -func GetFileSystemSpec(c *cli.Context) (fsSpec *speccore.SpecFiles, err error) { - fsSpec, err = speccore.CreateSpecFromFile(c.String("spec"), coreutils.SpecVarsStringToMap(c.String("spec-vars"))) - if err != nil { - return - } - // Override spec with CLI options - for i := 0; i < len(fsSpec.Files); i++ { - fsSpec.Get(i).Target = strings.TrimPrefix(fsSpec.Get(i).Target, "/") - OverrideFieldsIfSet(fsSpec.Get(i), c) - } - return -} - func OverrideFieldsIfSet(spec *speccore.File, c *cli.Context) { overrideArrayIfSet(&spec.Exclusions, c, "exclusions") overrideArrayIfSet(&spec.SortBy, c, "sort-by") @@ -614,38 +487,18 @@ func OverrideFieldsIfSet(spec *speccore.File, c *cli.Context) { } func FixWinPathsForFileSystemSourcedCmds(uploadSpec *speccore.SpecFiles, c *cli.Context) { - if coreutils.IsWindows() { - for i, file := range uploadSpec.Files { - uploadSpec.Files[i].Pattern = fixWinPathBySource(file.Pattern, c.IsSet("spec")) - for j, exclusion := range uploadSpec.Files[i].Exclusions { - // If exclusions are set, they override the spec value - uploadSpec.Files[i].Exclusions[j] = fixWinPathBySource(exclusion, c.IsSet("spec") && !c.IsSet("exclusions")) - } - } - } -} - -func fixWinPathBySource(path string, fromSpec bool) string { - if strings.Count(path, "/") > 0 { - // Assuming forward slashes - not doubling backslash to allow regexp escaping - return ioutils.UnixToWinPathSeparator(path) - } - if fromSpec { - // Doubling backslash only for paths from spec files (that aren't forward slashed) - return ioutils.DoubleWinPathSeparator(path) - } - return path + commonCliUtils.FixWinPathsForFileSystemSourcedCmds(uploadSpec, c.IsSet("spec"), c.IsSet("exclusions")) } func CreateConfigCmd(c *cli.Context, confType project.ProjectType) error { if c.NArg() != 0 { return WrongNumberOfArgumentsHandler(c) } - return coreCommonCommands.CreateBuildConfig(c, confType) + return commonCommands.CreateBuildConfig(c, confType) } func RunNativeCmdWithDeprecationWarning(cmdName string, projectType project.ProjectType, c *cli.Context, cmd func(c *cli.Context) error) error { - if shouldLogWarning() { + if cliutils.ShouldLogWarning() { LogNativeCommandDeprecation(cmdName, projectType.String()) } return cmd(c) @@ -684,42 +537,16 @@ func NotSupportedNativeDockerCommand(oldCmdName string) error { func RunConfigCmdWithDeprecationWarning(cmdName, oldSubcommand string, confType project.ProjectType, c *cli.Context, cmd func(c *cli.Context, confType project.ProjectType) error) error { - logNonNativeCommandDeprecation(cmdName, oldSubcommand) + commonCliUtils.LogNonNativeCommandDeprecation(cmdName, oldSubcommand) return cmd(c, confType) } func RunCmdWithDeprecationWarning(cmdName, oldSubcommand string, c *cli.Context, cmd func(c *cli.Context) error) error { - logNonNativeCommandDeprecation(cmdName, oldSubcommand) + commonCliUtils.LogNonNativeCommandDeprecation(cmdName, oldSubcommand) return cmd(c) } -func logNonNativeCommandDeprecation(cmdName, oldSubcommand string) { - if shouldLogWarning() { - log.Warn( - `You are using a deprecated syntax of the command. - Instead of: - $ ` + coreutils.GetCliExecutableName() + ` ` + oldSubcommand + ` ` + cmdName + ` ... - Use: - $ ` + coreutils.GetCliExecutableName() + ` ` + cmdName + ` ...`) - } -} - -func LogNonGenericAuditCommandDeprecation(cmdName string) { - if shouldLogWarning() { - log.Warn( - `You are using a deprecated syntax of the command. - Instead of: - $ ` + coreutils.GetCliExecutableName() + ` ` + cmdName + ` ... - Use: - $ ` + coreutils.GetCliExecutableName() + ` audit ...`) - } -} - -func shouldLogWarning() bool { - return strings.ToLower(os.Getenv(JfrogCliAvoidDeprecationWarnings)) != "true" -} - func SetCliExecutableName(executablePath string) { coreutils.SetCliExecutableName(filepath.Base(executablePath)) } @@ -747,7 +574,7 @@ func CreateBuildConfigurationWithModule(c *cli.Context) (buildConfigConfiguratio } func CreateArtifactoryDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { - artDetails, err := CreateServerDetailsWithConfigOffer(c, false, Rt) + artDetails, err := CreateServerDetailsWithConfigOffer(c, false, cliutils.Rt) if err != nil { return nil, err } diff --git a/utils/progressbar/filesprogressbar.go b/utils/progressbar/filesprogressbar.go deleted file mode 100644 index 5046c7058..000000000 --- a/utils/progressbar/filesprogressbar.go +++ /dev/null @@ -1,338 +0,0 @@ -package progressbar - -import ( - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "net/url" - "os" - "strings" - "sync" - "sync/atomic" - "time" - - "github.com/jfrog/jfrog-cli-core/v2/common/commands" - corelog "github.com/jfrog/jfrog-cli-core/v2/utils/log" - "github.com/jfrog/jfrog-cli-core/v2/utils/progressbar" - ioUtils "github.com/jfrog/jfrog-client-go/utils/io" - "github.com/jfrog/jfrog-client-go/utils/log" - - "github.com/vbauerster/mpb/v7" - "github.com/vbauerster/mpb/v7/decor" -) - -var terminalWidth int - -type filesProgressBarManager struct { - // A list of progress bar objects. - bars []progressBar - // A wait group for all progress bars. - barsWg *sync.WaitGroup - // A container of all external mpb bar objects to be displayed. - container *mpb.Progress - // A synchronization lock object. - barsRWMutex sync.RWMutex - // A general work indicator spinner. - headlineBar *mpb.Bar - // A general tasks completion indicator. - generalProgressBar *mpb.Bar - // A cumulative amount of tasks - tasksCount int64 - // The log file - logFile *os.File -} - -type progressBarUnit struct { - bar *mpb.Bar - incrChannel chan int - description string -} - -type progressBar interface { - ioUtils.Progress - getProgressBarUnit() *progressBarUnit -} - -func (p *filesProgressBarManager) InitProgressReaders() { - p.newHeadlineBar(" Working") - p.tasksCount = 0 - p.newGeneralProgressBar() -} - -// Initializes a new reader progress indicator for a new file transfer. -// Input: 'total' - file size. -// -// 'label' - the title of the operation. -// 'path' - the path of the file being processed. -// -// Output: progress indicator id -func (p *filesProgressBarManager) NewProgressReader(total int64, label, path string) (bar ioUtils.Progress) { - // Write Lock when appending a new bar to the slice - p.barsRWMutex.Lock() - defer p.barsRWMutex.Unlock() - p.barsWg.Add(1) - newBar := p.container.New(total, - mpb.BarStyle().Lbound("|").Filler("🟩").Tip("🟩").Padding("⬛").Refiller("").Rbound("|"), - mpb.BarRemoveOnComplete(), - mpb.AppendDecorators( - // Extra chars length is the max length of the KibiByteCounter - decor.Name(buildProgressDescription(label, path, 17)), - decor.CountersKibiByte("%3.1f/%3.1f"), - ), - ) - - // Add bar to bars array - unit := initNewBarUnit(newBar, path) - barId := len(p.bars) + 1 - readerProgressBar := ReaderProgressBar{progressBarUnit: unit, Id: barId} - p.bars = append(p.bars, &readerProgressBar) - return &readerProgressBar -} - -// Changes progress indicator state and acts accordingly. -func (p *filesProgressBarManager) SetProgressState(id int, state string) { - if state == "Merging" { - p.addNewMergingSpinner(id) - } -} - -// Initializes a new progress bar, that replaces the progress bar with the given replacedBarId -func (p *filesProgressBarManager) addNewMergingSpinner(replacedBarId int) { - // Write Lock when appending a new bar to the slice - p.barsRWMutex.Lock() - defer p.barsRWMutex.Unlock() - replacedBar := p.bars[replacedBarId-1].getProgressBarUnit() - p.bars[replacedBarId-1].Abort() - newBar := p.container.New(1, - mpb.SpinnerStyle(createSpinnerFramesArray()...).PositionLeft(), - mpb.AppendDecorators( - decor.Name(buildProgressDescription(" Merging ", replacedBar.description, 0)), - ), - ) - // Bar replacement is a simple spinner and thus does not implement any read functionality - unit := &progressBarUnit{bar: newBar, description: replacedBar.description} - progressBar := SimpleProgressBar{progressBarUnit: unit, Id: replacedBarId} - p.bars[replacedBarId-1] = &progressBar -} - -func buildProgressDescription(label, path string, extraCharsLen int) string { - separator := " | " - // Max line length after decreasing bar width (*2 in case unicode chars with double width are used) and the extra chars - descMaxLength := terminalWidth - (progressbar.ProgressBarWidth*2 + extraCharsLen) - return buildDescByLimits(descMaxLength, " "+label+separator, shortenUrl(path), separator) -} - -func shortenUrl(path string) string { - if _, err := url.ParseRequestURI(path); err != nil { - return path - } - - semicolonIndex := strings.Index(path, ";") - if semicolonIndex == -1 { - return path - } - return path[:semicolonIndex] -} - -func buildDescByLimits(descMaxLength int, prefix, path, suffix string) string { - desc := prefix + path + suffix - - // Verify that the whole description doesn't exceed the max length - if len(desc) <= descMaxLength { - return desc - } - - // If it does exceed, check if shortening the path will help (+3 is for "...") - if len(desc)-len(path)+3 > descMaxLength { - // Still exceeds, do not display desc - return "" - } - - // Shorten path from the beginning - path = "..." + path[len(desc)-descMaxLength+3:] - return prefix + path + suffix -} - -func initNewBarUnit(bar *mpb.Bar, path string) *progressBarUnit { - ch := make(chan int, 1000) - unit := &progressBarUnit{bar: bar, incrChannel: ch, description: path} - go incrBarFromChannel(unit) - return unit -} - -func incrBarFromChannel(unit *progressBarUnit) { - // Increase bar while channel is open - for n := range unit.incrChannel { - unit.bar.IncrBy(n) - } -} - -func createSpinnerFramesArray() []string { - black := "⬛" - green := "🟩" - spinnerFramesArray := make([]string, progressbar.ProgressBarWidth) - for i := 1; i < progressbar.ProgressBarWidth-1; i++ { - cur := "|" + strings.Repeat(black, i-1) + green + strings.Repeat(black, progressbar.ProgressBarWidth-2-i) + "|" - spinnerFramesArray[i] = cur - } - return spinnerFramesArray -} - -// Aborts a progress bar. -// Should be called even if bar completed successfully. -// The progress component's Abort method has no effect if bar has already completed, so can always be safely called anyway -func (p *filesProgressBarManager) RemoveProgress(id int) { - p.barsRWMutex.RLock() - defer p.barsWg.Done() - defer p.barsRWMutex.RUnlock() - p.bars[id-1].Abort() -} - -// Increases general progress bar by 1 -func (p *filesProgressBarManager) IncrementGeneralProgress() { - p.generalProgressBar.Increment() -} - -// Quits the progress bar while aborting the initial bars. -func (p *filesProgressBarManager) Quit() (err error) { - if p.headlineBar != nil { - p.headlineBar.Abort(true) - p.barsWg.Done() - p.headlineBar = nil - } - if p.generalProgressBar != nil { - p.generalProgressBar.Abort(true) - p.barsWg.Done() - p.generalProgressBar = nil - } - // Wait a refresh rate to make sure all aborts have finished - time.Sleep(progressbar.ProgressRefreshRate) - p.container.Wait() - // Close the created log file (once) - if p.logFile != nil { - err = corelog.CloseLogFile(p.logFile) - p.logFile = nil - // Set back the default logger - corelog.SetDefaultLogger() - } - return -} - -func (p *filesProgressBarManager) GetProgress(id int) ioUtils.Progress { - return p.bars[id-1] -} - -// Initializes progress bar if possible (all conditions in 'shouldInitProgressBar' are met). -// Returns nil, nil, err if failed. -func InitFilesProgressBarIfPossible(showLogFilePath bool) (ioUtils.ProgressMgr, error) { - shouldInit, err := progressbar.ShouldInitProgressBar() - if !shouldInit || err != nil { - return nil, err - } - - logFile, err := corelog.CreateLogFile() - if err != nil { - return nil, err - } - if showLogFilePath { - log.Info("Log path:", logFile.Name()) - } - log.SetLogger(log.NewLogger(corelog.GetCliLogLevel(), logFile)) - - newProgressBar := &filesProgressBarManager{} - newProgressBar.barsWg = new(sync.WaitGroup) - - // Initialize the progressBar container with wg, to create a single joint point - newProgressBar.container = mpb.New( - mpb.WithOutput(os.Stderr), - mpb.WithWaitGroup(newProgressBar.barsWg), - mpb.WithWidth(progressbar.ProgressBarWidth), - mpb.WithRefreshRate(progressbar.ProgressRefreshRate)) - - newProgressBar.logFile = logFile - - return newProgressBar, nil -} - -// Initializes a new progress bar for general progress indication -func (p *filesProgressBarManager) newGeneralProgressBar() { - p.barsWg.Add(1) - p.generalProgressBar = p.container.New(p.tasksCount, - mpb.BarStyle().Lbound("|").Filler("⬜").Tip("⬜").Padding("⬛").Refiller("").Rbound("|"), - mpb.BarRemoveOnComplete(), - mpb.AppendDecorators( - decor.Name(" Tasks: "), - decor.CountersNoUnit("%d/%d"), - ), - ) -} - -// Initializes a new progress bar for headline, with a spinner -func (p *filesProgressBarManager) newHeadlineBar(headline string) { - p.barsWg.Add(1) - p.headlineBar = p.container.New(1, - mpb.SpinnerStyle("∙∙∙∙∙∙", "●∙∙∙∙∙", "∙●∙∙∙∙", "∙∙●∙∙∙", "∙∙∙●∙∙", "∙∙∙∙●∙", "∙∙∙∙∙●", "∙∙∙∙∙∙").PositionLeft(), - mpb.BarRemoveOnComplete(), - mpb.PrependDecorators( - decor.Name(headline), - ), - ) -} - -func (p *filesProgressBarManager) SetHeadlineMsg(msg string) { - if p.headlineBar != nil { - current := p.headlineBar - p.barsRWMutex.RLock() - // First abort, then mark progress as done and finally release the lock. - defer p.barsRWMutex.RUnlock() - defer p.barsWg.Done() - defer current.Abort(true) - } - // Remove emojis from non-supported terminals - msg = coreutils.RemoveEmojisIfNonSupportedTerminal(msg) - p.newHeadlineBar(msg) -} - -func (p *filesProgressBarManager) ClearHeadlineMsg() { - if p.headlineBar != nil { - p.barsRWMutex.RLock() - p.headlineBar.Abort(true) - p.barsWg.Done() - p.barsRWMutex.RUnlock() - // Wait a refresh rate to make sure the abort has finished - time.Sleep(progressbar.ProgressRefreshRate) - } - p.headlineBar = nil -} - -// IncGeneralProgressTotalBy increments the general progress bar total count by given n. -func (p *filesProgressBarManager) IncGeneralProgressTotalBy(n int64) { - atomic.AddInt64(&p.tasksCount, n) - if p.generalProgressBar != nil { - p.generalProgressBar.SetTotal(p.tasksCount, false) - } -} - -type CommandWithProgress interface { - commands.Command - SetProgress(ioUtils.ProgressMgr) -} - -func ExecWithProgress(cmd CommandWithProgress) (err error) { - // Show log file path on all progress bars except 'setup' command - showLogFilePath := cmd.CommandName() != "setup" - // Init progress bar. - progressBar, err := InitFilesProgressBarIfPossible(showLogFilePath) - if err != nil { - return err - } - if progressBar != nil { - cmd.SetProgress(progressBar) - defer func() { - e := progressBar.Quit() - if err == nil { - err = e - } - }() - } - err = commands.Exec(cmd) - return -} diff --git a/utils/progressbar/filesprogressbar_test.go b/utils/progressbar/filesprogressbar_test.go deleted file mode 100644 index 0f9c6fea3..000000000 --- a/utils/progressbar/filesprogressbar_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package progressbar - -import ( - "github.com/jfrog/jfrog-cli-core/v2/utils/progressbar" - "testing" -) - -func TestBuildProgressDescription(t *testing.T) { - // Set an arbitrary terminal width - terminalWidth = 100 - tests := getTestCases() - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - desc := buildProgressDescription(test.prefix, test.path, test.extraCharsLen) - - // Validate result - if desc != test.expectedDesc { - t.Errorf("Expected value of: \"%s\", got: \"%s\".", test.expectedDesc, desc) - } - }) - } -} - -func getTestCases() []testCase { - prefix := " downloading" - path := "/a/path/to/a/file" - separator := " | " - - fullDesc := " " + prefix + separator + path + separator - emptyPathDesc := " " + prefix + separator + "..." + separator - shortenedDesc := " " + prefix + separator + "...ggggg/path/to/a/file" + separator - - widthMinusProgress := terminalWidth - progressbar.ProgressBarWidth*2 - return []testCase{ - {"commonUseCase", prefix, path, 17, fullDesc}, - {"zeroExtraChars", prefix, path, 0, fullDesc}, - {"minDescLength", prefix, path, widthMinusProgress - len(emptyPathDesc), emptyPathDesc}, - {"longPath", prefix, "/a/longggggggggggggggggggggg/path/to/a/file", 17, shortenedDesc}, - {"longPrefix", "longggggggggggggggggggggggggg prefix", path, 17, ""}, - {"manyExtraChars", prefix, path, widthMinusProgress - len(emptyPathDesc) + 1, ""}, - } -} - -type testCase struct { - name string - prefix string - path string - extraCharsLen int - expectedDesc string -} diff --git a/utils/progressbar/readerprogressbar.go b/utils/progressbar/readerprogressbar.go deleted file mode 100644 index 0ccef8190..000000000 --- a/utils/progressbar/readerprogressbar.go +++ /dev/null @@ -1,75 +0,0 @@ -package progressbar - -import ( - "io" -) - -type ReaderProgressBar struct { - *progressBarUnit - Id int -} - -// Wraps an io.Reader for bytes reading tracking -type proxyReader struct { - unit *progressBarUnit - io.ReadCloser -} - -// Used to update the progress bar progress. -func (p *ReaderProgressBar) ActionWithProgress(reader io.Reader) (results io.Reader) { - return p.readWithProgress(reader) -} - -// Abort aborts a progress indicator. Called on both successful and unsuccessful operations -func (p *ReaderProgressBar) Abort() { - close(p.incrChannel) - p.bar.Abort(true) -} - -// GetId Returns the ProgressBar ID -// -//nolint:gocritic -func (p *ReaderProgressBar) GetId() (Id int) { - return p.Id -} - -func (p *ReaderProgressBar) getProgressBarUnit() (unit *progressBarUnit) { - return p.progressBarUnit -} - -// Wraps a body of a response (io.Reader) and increments bar accordingly -func (p *ReaderProgressBar) readWithProgress(reader io.Reader) (wrappedReader io.Reader) { - wrappedReader = initProxyReader(p.progressBarUnit, reader) - return wrappedReader -} - -func initProxyReader(unit *progressBarUnit, reader io.Reader) io.ReadCloser { - if reader == nil { - return nil - } - rc, ok := reader.(io.ReadCloser) - if !ok { - rc = io.NopCloser(reader) - } - return &proxyReader{unit, rc} -} - -// Overrides the Read method of the original io.Reader. -func (pr *proxyReader) Read(p []byte) (n int, err error) { - n, err = pr.ReadCloser.Read(p) - if n > 0 && (err == nil || err == io.EOF) { - pr.incrChannel(n) - } - return -} - -func (pr *proxyReader) incrChannel(n int) { - // When an upload / download error occurs (for example, a bad HTTP error code), - // The progress bar's Abort method is invoked and closes the channel. - // Therefore, the channel may be already closed at this stage, which leads to a panic. - // We therefore need to recover if that happens. - defer func() { - _ = recover() - }() - pr.unit.incrChannel <- n -} diff --git a/utils/progressbar/simpleprogressbar.go b/utils/progressbar/simpleprogressbar.go deleted file mode 100644 index a6695acf3..000000000 --- a/utils/progressbar/simpleprogressbar.go +++ /dev/null @@ -1,32 +0,0 @@ -package progressbar - -import ( - "io" -) - -type SimpleProgressBar struct { - *progressBarUnit - Id int -} - -// Used to update the progress bar progress. -func (p *SimpleProgressBar) ActionWithProgress(reader io.Reader) (results io.Reader) { - p.bar.Increment() - return nil -} - -// Abort aborts a progress indicator. Called on both successful and unsuccessful operations -func (p *SimpleProgressBar) Abort() { - p.bar.Abort(true) -} - -// GetId Returns the ProgressBar ID -// -//nolint:gocritic -func (p *SimpleProgressBar) GetId() (Id int) { - return p.Id -} - -func (p *SimpleProgressBar) getProgressBarUnit() (unit *progressBarUnit) { - return p.progressBarUnit -} diff --git a/utils/tests/utils.go b/utils/tests/utils.go index bf276700c..d113ddcff 100644 --- a/utils/tests/utils.go +++ b/utils/tests/utils.go @@ -24,16 +24,16 @@ import ( commandutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" artUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/common/spec" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" corelog "github.com/jfrog/jfrog-cli-core/v2/utils/log" - "github.com/jfrog/jfrog-cli-core/v2/utils/progressbar" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/utils/summary" "github.com/jfrog/jfrog-client-go/artifactory/services" "github.com/jfrog/jfrog-client-go/artifactory/services/utils" "github.com/jfrog/jfrog-client-go/auth" clientutils "github.com/jfrog/jfrog-client-go/utils" - "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" "github.com/jfrog/jfrog-client-go/utils/tests" @@ -216,83 +216,6 @@ type PackageSearchResultItem struct { Published bool } -type JfrogCli struct { - main func() error - prefix string - credentials string -} - -func NewJfrogCli(mainFunc func() error, prefix, credentials string) *JfrogCli { - return &JfrogCli{mainFunc, prefix, credentials} -} - -func (cli *JfrogCli) SetPrefix(prefix string) *JfrogCli { - cli.prefix = prefix - return cli -} - -func (cli *JfrogCli) Exec(args ...string) error { - spaceSplit := " " - os.Args = strings.Split(cli.prefix, spaceSplit) - output := strings.Split(cli.prefix, spaceSplit) - for _, v := range args { - if v == "" { - continue - } - args := strings.Split(v, spaceSplit) - os.Args = append(os.Args, v) - output = append(output, args...) - } - if cli.credentials != "" { - args := strings.Split(cli.credentials, spaceSplit) - os.Args = append(os.Args, args...) - } - - log.Info("[Command]", strings.Join(output, " ")) - return cli.main() -} - -// Run `jfrog` command, redirect the stdout and return the output -func (cli *JfrogCli) RunCliCmdWithOutput(t *testing.T, args ...string) string { - newStdout, stdWriter, previousStdout := RedirectStdOutToPipe() - previousLog := log.Logger - log.SetLogger(log.NewLogger(corelog.GetCliLogLevel(), nil)) - // Restore previous stdout when the function returns - defer func() { - os.Stdout = previousStdout - log.SetLogger(previousLog) - assert.NoError(t, newStdout.Close()) - }() - go func() { - err := cli.Exec(args...) - assert.NoError(t, err) - // Closing the temp stdout in order to be able to read it's content. - assert.NoError(t, stdWriter.Close()) - }() - content, err := io.ReadAll(newStdout) - assert.NoError(t, err) - log.Debug(string(content)) - return string(content) -} - -func (cli *JfrogCli) LegacyBuildToolExec(args ...string) error { - spaceSplit := " " - os.Args = strings.Split(cli.prefix, spaceSplit) - os.Args = append(os.Args, args...) - - log.Info("[Command]", os.Args) - - if cli.credentials != "" { - args := strings.Split(cli.credentials, spaceSplit) - os.Args = append(os.Args, args...) - } - return cli.main() -} - -func (cli *JfrogCli) WithoutCredentials() *JfrogCli { - return &JfrogCli{cli.main, cli.prefix, ""} -} - func DeleteFiles(deleteSpec *spec.SpecFiles, serverDetails *config.ServerDetails) (successCount, failCount int, err error) { deleteCommand := generic.NewDeleteCommand() deleteCommand.SetThreads(3).SetSpec(deleteSpec).SetServerDetails(serverDetails).SetDryRun(false) @@ -613,33 +536,7 @@ func AddTimestampToGlobalVars() { // path - Path to the input file. // destPath - Path to the output file. If empty, the output file will be under ${CWD}/tmp/. func ReplaceTemplateVariables(path, destPath string) (string, error) { - content, err := os.ReadFile(path) - if err != nil { - return "", errorutils.CheckError(err) - } - - for name, value := range getSubstitutionMap() { - content = bytes.ReplaceAll(content, []byte(name), []byte(value)) - } - if destPath == "" { - destPath, err = os.Getwd() - if err != nil { - return "", errorutils.CheckError(err) - } - destPath = filepath.Join(destPath, Temp) - } - err = os.MkdirAll(destPath, 0700) - if err != nil { - return "", errorutils.CheckError(err) - } - specPath := filepath.Join(destPath, filepath.Base(path)) - log.Info("Creating spec file at:", specPath) - err = os.WriteFile(specPath, content, 0700) - if err != nil { - return "", errorutils.CheckError(err) - } - - return specPath, nil + return commonCliUtils.ReplaceTemplateVariables(path, destPath, getSubstitutionMap()) } func CreateSpec(fileName string) (string, error) { @@ -700,15 +597,6 @@ func CleanUpOldItems(baseItemNames []string, getActualItems func() ([]string, er } } -// Redirect stdout to new temp, os.pipe -// Caller is responsible to close the pipe and to set the old stdout back. -func RedirectStdOutToPipe() (reader *os.File, writer *os.File, previousStdout *os.File) { - previousStdout = os.Stdout - reader, writer, _ = os.Pipe() - os.Stdout = writer - return -} - // Set new logger with output redirection to a null logger. This is useful for negative tests. // Caller is responsible to set the old log back. func RedirectLogOutputToNil() (previousLog log.Log) { @@ -720,21 +608,10 @@ func RedirectLogOutputToNil() (previousLog log.Log) { return previousLog } -// Set progressbar.ShouldInitProgressBar func to always return true -// so the progress bar library will be initialized and progress will be displayed. -// The returned callback sets the original func back. -func MockProgressInitialization() func() { - originFunc := progressbar.ShouldInitProgressBar - progressbar.ShouldInitProgressBar = func() (bool, error) { return true, nil } - return func() { - progressbar.ShouldInitProgressBar = originFunc - } -} - // Redirect output to a file, execute the command and read output. // The reason for redirecting to a file and not to a buffer is the limited // size of the buffer while using os.Pipe. -func GetCmdOutput(t *testing.T, jfrogCli *JfrogCli, cmd ...string) ([]byte, error) { +func GetCmdOutput(t *testing.T, jfrogCli *coreTests.JfrogCli, cmd ...string) ([]byte, error) { oldStdout := os.Stdout temp, err := os.CreateTemp("", "output") assert.NoError(t, err) diff --git a/xray_test.go b/xray_test.go index 0581b383c..8e19cd5b6 100644 --- a/xray_test.go +++ b/xray_test.go @@ -36,7 +36,6 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/xray/commands/scan" "github.com/jfrog/jfrog-cli-core/v2/xray/formats" "github.com/jfrog/jfrog-cli-core/v2/xray/utils" - "github.com/jfrog/jfrog-cli/inttestutils" "github.com/jfrog/jfrog-cli/utils/cliutils" "github.com/jfrog/jfrog-cli/utils/tests" "github.com/jfrog/jfrog-client-go/auth" @@ -61,7 +60,7 @@ var ( xrayDetails *config.ServerDetails xrayAuth auth.ServiceDetails // JFrog CLI for Xray commands - xrayCli *tests.JfrogCli + xrayCli *coretests.JfrogCli ) func InitXrayTests() { @@ -102,7 +101,7 @@ func initXrayCli() { return } cred := authenticateXray() - xrayCli = tests.NewJfrogCli(execMain, "jfrog", cred) + xrayCli = coretests.NewJfrogCli(execMain, "jfrog", cred) } // Tests basic binary scan by providing pattern (path to testdata binaries) and --licenses flag @@ -118,14 +117,14 @@ func TestXrayBinaryScanSimpleJson(t *testing.T) { } func TestXrayBinaryScanJsonWithProgress(t *testing.T) { - callback := tests.MockProgressInitialization() + callback := commontests.MockProgressInitialization() defer callback() output := testXrayBinaryScan(t, string(format.Json)) verifyJsonScanResults(t, output, 0, 1, 1) } func TestXrayBinaryScanSimpleJsonWithProgress(t *testing.T) { - callback := tests.MockProgressInitialization() + callback := commontests.MockProgressInitialization() defer callback() output := testXrayBinaryScan(t, string(format.SimpleJson)) verifySimpleJsonScanResults(t, output, 1, 1) @@ -695,7 +694,7 @@ func TestDockerScan(t *testing.T) { } func TestDockerScanWithProgressBar(t *testing.T) { - callback := tests.MockProgressInitialization() + callback := commontests.MockProgressInitialization() defer callback() TestDockerScan(t) } @@ -706,7 +705,7 @@ func runDockerScan(t *testing.T, imageName, watchName string, minViolations, min dockerPullCommand := coreContainer.NewPullCommand(container.DockerClient) dockerPullCommand.SetCmdParams([]string{"pull", imageTag}).SetImageTag(imageTag).SetRepo(tests.DockerVirtualRepo).SetServerDetails(serverDetails).SetBuildConfiguration(new(build.BuildConfiguration)) if assert.NoError(t, dockerPullCommand.Run()) { - defer inttestutils.DeleteTestImage(t, imageTag, container.DockerClient) + defer commontests.DeleteTestImage(t, imageTag, container.DockerClient) args := []string{"docker", "scan", imageTag, "--server-id=default", "--licenses", "--format=json", "--fail=false", "--min-severity=low", "--fixable-only"}