github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/artifactory/cli.go (about)

     1  package artifactory
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"strconv"
    11  	"strings"
    12  
    13  	"github.com/codegangsta/cli"
    14  	"github.com/jfrog/jfrog-cli-go/artifactory/commands"
    15  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/buildinfo"
    16  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/curl"
    17  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/distribution"
    18  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/docker"
    19  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/generic"
    20  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/golang"
    21  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/gradle"
    22  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/mvn"
    23  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/npm"
    24  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/nuget"
    25  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/pip"
    26  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/replication"
    27  	"github.com/jfrog/jfrog-cli-go/artifactory/commands/repository"
    28  	commandUtils "github.com/jfrog/jfrog-cli-go/artifactory/commands/utils"
    29  	"github.com/jfrog/jfrog-cli-go/artifactory/spec"
    30  	"github.com/jfrog/jfrog-cli-go/artifactory/utils"
    31  	npmUtils "github.com/jfrog/jfrog-cli-go/artifactory/utils/npm"
    32  	piputils "github.com/jfrog/jfrog-cli-go/artifactory/utils/pip"
    33  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/buildadddependencies"
    34  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/buildaddgit"
    35  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/buildclean"
    36  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/buildcollectenv"
    37  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/builddiscard"
    38  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/builddistribute"
    39  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/buildpromote"
    40  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/buildpublish"
    41  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/buildscan"
    42  	configdocs "github.com/jfrog/jfrog-cli-go/docs/artifactory/config"
    43  	copydocs "github.com/jfrog/jfrog-cli-go/docs/artifactory/copy"
    44  	curldocs "github.com/jfrog/jfrog-cli-go/docs/artifactory/curl"
    45  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/delete"
    46  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/deleteprops"
    47  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/dockerpull"
    48  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/dockerpush"
    49  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/download"
    50  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/gitlfsclean"
    51  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/gocommand"
    52  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/goconfig"
    53  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/gopublish"
    54  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/gorecursivepublish"
    55  	gradledoc "github.com/jfrog/jfrog-cli-go/docs/artifactory/gradle"
    56  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/gradleconfig"
    57  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/move"
    58  	mvndoc "github.com/jfrog/jfrog-cli-go/docs/artifactory/mvn"
    59  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/mvnconfig"
    60  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/npmci"
    61  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/npmconfig"
    62  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/npminstall"
    63  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/npmpublish"
    64  	nugetdocs "github.com/jfrog/jfrog-cli-go/docs/artifactory/nuget"
    65  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/nugetconfig"
    66  	nugettree "github.com/jfrog/jfrog-cli-go/docs/artifactory/nugetdepstree"
    67  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/ping"
    68  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/pipconfig"
    69  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/pipinstall"
    70  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/releasebundlecreate"
    71  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/releasebundledelete"
    72  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/releasebundledistribute"
    73  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/releasebundlesign"
    74  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/releasebundleupdate"
    75  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/replicationcreate"
    76  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/replicationdelete"
    77  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/replicationtemplate"
    78  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/repocreate"
    79  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/repodelete"
    80  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/repotemplate"
    81  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/repoupdate"
    82  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/search"
    83  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/setprops"
    84  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/upload"
    85  	"github.com/jfrog/jfrog-cli-go/docs/artifactory/use"
    86  	"github.com/jfrog/jfrog-cli-go/docs/common"
    87  	"github.com/jfrog/jfrog-cli-go/utils/cliutils"
    88  	"github.com/jfrog/jfrog-cli-go/utils/config"
    89  	"github.com/jfrog/jfrog-cli-go/utils/ioutils"
    90  	logUtils "github.com/jfrog/jfrog-cli-go/utils/log"
    91  	buildinfocmd "github.com/jfrog/jfrog-client-go/artifactory/buildinfo"
    92  	"github.com/jfrog/jfrog-client-go/artifactory/services"
    93  	distributionServices "github.com/jfrog/jfrog-client-go/distribution/services"
    94  	distributionServicesUtils "github.com/jfrog/jfrog-client-go/distribution/services/utils"
    95  	clientutils "github.com/jfrog/jfrog-client-go/utils"
    96  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    97  	"github.com/jfrog/jfrog-client-go/utils/log"
    98  	"github.com/mattn/go-shellwords"
    99  )
   100  
   101  func GetCommands() []cli.Command {
   102  	return []cli.Command{
   103  		{
   104  			Name:         "config",
   105  			Flags:        getConfigFlags(),
   106  			Aliases:      []string{"c"},
   107  			Usage:        configdocs.Description,
   108  			HelpName:     common.CreateUsage("rt config", configdocs.Description, configdocs.Usage),
   109  			UsageText:    configdocs.Arguments,
   110  			ArgsUsage:    common.CreateEnvVars(),
   111  			BashComplete: common.CreateBashCompletionFunc("show", "delete", "clear", "import", "export"),
   112  			Action: func(c *cli.Context) error {
   113  				return configCmd(c)
   114  			},
   115  		},
   116  		{
   117  			Name:         "use",
   118  			Usage:        use.Description,
   119  			HelpName:     common.CreateUsage("rt use", use.Description, use.Usage),
   120  			UsageText:    use.Arguments,
   121  			ArgsUsage:    common.CreateEnvVars(),
   122  			BashComplete: common.CreateBashCompletionFunc(commands.GetAllArtifactoryServerIds()...),
   123  			Action: func(c *cli.Context) error {
   124  				return useCmd(c)
   125  			},
   126  		},
   127  		{
   128  			Name:         "upload",
   129  			Flags:        getUploadFlags(),
   130  			Aliases:      []string{"u"},
   131  			Usage:        upload.Description,
   132  			HelpName:     common.CreateUsage("rt upload", upload.Description, upload.Usage),
   133  			UsageText:    upload.Arguments,
   134  			ArgsUsage:    common.CreateEnvVars(upload.EnvVar),
   135  			BashComplete: common.CreateBashCompletionFunc(),
   136  			Action: func(c *cli.Context) error {
   137  				return uploadCmd(c)
   138  			},
   139  		},
   140  		{
   141  			Name:         "download",
   142  			Flags:        getDownloadFlags(),
   143  			Aliases:      []string{"dl"},
   144  			Usage:        download.Description,
   145  			HelpName:     common.CreateUsage("rt download", download.Description, download.Usage),
   146  			UsageText:    download.Arguments,
   147  			ArgsUsage:    common.CreateEnvVars(),
   148  			BashComplete: common.CreateBashCompletionFunc(),
   149  			Action: func(c *cli.Context) error {
   150  				return downloadCmd(c)
   151  			},
   152  		},
   153  		{
   154  			Name:         "move",
   155  			Flags:        getMoveFlags(),
   156  			Aliases:      []string{"mv"},
   157  			Usage:        move.Description,
   158  			HelpName:     common.CreateUsage("rt move", move.Description, move.Usage),
   159  			UsageText:    move.Arguments,
   160  			ArgsUsage:    common.CreateEnvVars(),
   161  			BashComplete: common.CreateBashCompletionFunc(),
   162  			Action: func(c *cli.Context) error {
   163  				return moveCmd(c)
   164  			},
   165  		},
   166  		{
   167  			Name:         "copy",
   168  			Flags:        getCopyFlags(),
   169  			Aliases:      []string{"cp"},
   170  			Usage:        copydocs.Description,
   171  			HelpName:     common.CreateUsage("rt copy", copydocs.Description, copydocs.Usage),
   172  			UsageText:    copydocs.Arguments,
   173  			ArgsUsage:    common.CreateEnvVars(),
   174  			BashComplete: common.CreateBashCompletionFunc(),
   175  			Action: func(c *cli.Context) error {
   176  				return copyCmd(c)
   177  			},
   178  		},
   179  		{
   180  			Name:         "delete",
   181  			Flags:        getDeleteFlags(),
   182  			Aliases:      []string{"del"},
   183  			Usage:        delete.Description,
   184  			HelpName:     common.CreateUsage("rt delete", delete.Description, delete.Usage),
   185  			UsageText:    delete.Arguments,
   186  			ArgsUsage:    common.CreateEnvVars(),
   187  			BashComplete: common.CreateBashCompletionFunc(),
   188  			Action: func(c *cli.Context) error {
   189  				return deleteCmd(c)
   190  			},
   191  		},
   192  		{
   193  			Name:         "search",
   194  			Flags:        getSearchFlags(),
   195  			Aliases:      []string{"s"},
   196  			Usage:        search.Description,
   197  			HelpName:     common.CreateUsage("rt search", search.Description, search.Usage),
   198  			UsageText:    search.Arguments,
   199  			ArgsUsage:    common.CreateEnvVars(),
   200  			BashComplete: common.CreateBashCompletionFunc(),
   201  			Action: func(c *cli.Context) error {
   202  				return searchCmd(c)
   203  			},
   204  		},
   205  		{
   206  			Name:         "set-props",
   207  			Flags:        getSetOrDeletePropsFlags(),
   208  			Aliases:      []string{"sp"},
   209  			Usage:        setprops.Description,
   210  			HelpName:     common.CreateUsage("rt set-props", setprops.Description, setprops.Usage),
   211  			UsageText:    setprops.Arguments,
   212  			ArgsUsage:    common.CreateEnvVars(),
   213  			BashComplete: common.CreateBashCompletionFunc(),
   214  			Action: func(c *cli.Context) error {
   215  				return setPropsCmd(c)
   216  			},
   217  		},
   218  		{
   219  			Name:         "delete-props",
   220  			Flags:        getSetOrDeletePropsFlags(),
   221  			Aliases:      []string{"delp"},
   222  			Usage:        deleteprops.Description,
   223  			HelpName:     common.CreateUsage("rt delete-props", deleteprops.Description, deleteprops.Usage),
   224  			UsageText:    deleteprops.Arguments,
   225  			ArgsUsage:    common.CreateEnvVars(),
   226  			BashComplete: common.CreateBashCompletionFunc(),
   227  			Action: func(c *cli.Context) error {
   228  				return deletePropsCmd(c)
   229  			},
   230  		},
   231  		{
   232  			Name:         "build-publish",
   233  			Flags:        getBuildPublishFlags(),
   234  			Aliases:      []string{"bp"},
   235  			Usage:        buildpublish.Description,
   236  			HelpName:     common.CreateUsage("rt build-publish", buildpublish.Description, buildpublish.Usage),
   237  			UsageText:    buildpublish.Arguments,
   238  			ArgsUsage:    common.CreateEnvVars(),
   239  			BashComplete: common.CreateBashCompletionFunc(),
   240  			Action: func(c *cli.Context) error {
   241  				return buildPublishCmd(c)
   242  			},
   243  		},
   244  		{
   245  			Name:         "build-collect-env",
   246  			Aliases:      []string{"bce"},
   247  			Usage:        buildcollectenv.Description,
   248  			HelpName:     common.CreateUsage("rt build-collect-env", buildcollectenv.Description, buildcollectenv.Usage),
   249  			UsageText:    buildcollectenv.Arguments,
   250  			ArgsUsage:    common.CreateEnvVars(),
   251  			BashComplete: common.CreateBashCompletionFunc(),
   252  			Action: func(c *cli.Context) error {
   253  				return buildCollectEnvCmd(c)
   254  			},
   255  		},
   256  		{
   257  			Name:         "build-add-dependencies",
   258  			Flags:        getBuildAddDependenciesFlags(),
   259  			Aliases:      []string{"bad"},
   260  			Usage:        buildadddependencies.Description,
   261  			HelpName:     common.CreateUsage("rt build-add-dependencies", buildadddependencies.Description, buildadddependencies.Usage),
   262  			UsageText:    buildadddependencies.Arguments,
   263  			ArgsUsage:    common.CreateEnvVars(),
   264  			BashComplete: common.CreateBashCompletionFunc(),
   265  			Action: func(c *cli.Context) error {
   266  				return buildAddDependenciesCmd(c)
   267  			},
   268  		},
   269  		{
   270  			Name:         "build-add-git",
   271  			Flags:        getBuildAddGitFlags(),
   272  			Aliases:      []string{"bag"},
   273  			Usage:        buildaddgit.Description,
   274  			HelpName:     common.CreateUsage("rt build-add-git", buildaddgit.Description, buildaddgit.Usage),
   275  			UsageText:    buildaddgit.Arguments,
   276  			ArgsUsage:    common.CreateEnvVars(),
   277  			BashComplete: common.CreateBashCompletionFunc(),
   278  			Action: func(c *cli.Context) error {
   279  				return buildAddGitCmd(c)
   280  			},
   281  		},
   282  		{
   283  			Name:         "build-scan",
   284  			Flags:        getBuildScanFlags(),
   285  			Aliases:      []string{"bs"},
   286  			Usage:        buildscan.Description,
   287  			HelpName:     common.CreateUsage("rt build-scan", buildscan.Description, buildscan.Usage),
   288  			UsageText:    buildscan.Arguments,
   289  			ArgsUsage:    common.CreateEnvVars(),
   290  			BashComplete: common.CreateBashCompletionFunc(),
   291  			Action: func(c *cli.Context) error {
   292  				return buildScanCmd(c)
   293  			},
   294  		},
   295  		{
   296  			Name:         "build-clean",
   297  			Aliases:      []string{"bc"},
   298  			Usage:        buildclean.Description,
   299  			HelpName:     common.CreateUsage("rt build-clean", buildclean.Description, buildclean.Usage),
   300  			UsageText:    buildclean.Arguments,
   301  			ArgsUsage:    common.CreateEnvVars(),
   302  			BashComplete: common.CreateBashCompletionFunc(),
   303  			Action: func(c *cli.Context) error {
   304  				return buildCleanCmd(c)
   305  			},
   306  		},
   307  		{
   308  			Name:         "build-promote",
   309  			Flags:        getBuildPromotionFlags(),
   310  			Aliases:      []string{"bpr"},
   311  			Usage:        buildpromote.Description,
   312  			HelpName:     common.CreateUsage("rt build-promote", buildpromote.Description, buildpromote.Usage),
   313  			UsageText:    buildpromote.Arguments,
   314  			ArgsUsage:    common.CreateEnvVars(),
   315  			BashComplete: common.CreateBashCompletionFunc(),
   316  			Action: func(c *cli.Context) error {
   317  				return buildPromoteCmd(c)
   318  			},
   319  		},
   320  		{
   321  			Name:         "build-distribute",
   322  			Flags:        getBuildDistributeFlags(),
   323  			Aliases:      []string{"bd"},
   324  			Usage:        builddistribute.Description,
   325  			HelpName:     common.CreateUsage("rt build-distribute", builddistribute.Description, builddistribute.Usage),
   326  			UsageText:    builddistribute.Arguments,
   327  			ArgsUsage:    common.CreateEnvVars(),
   328  			BashComplete: common.CreateBashCompletionFunc(),
   329  			Action: func(c *cli.Context) error {
   330  				return buildDistributeCmd(c)
   331  			},
   332  		},
   333  		{
   334  			Name:         "build-discard",
   335  			Flags:        getBuildDiscardFlags(),
   336  			Aliases:      []string{"bdi"},
   337  			Usage:        builddiscard.Description,
   338  			HelpName:     common.CreateUsage("rt build-discard", builddiscard.Description, builddiscard.Usage),
   339  			UsageText:    builddiscard.Arguments,
   340  			ArgsUsage:    common.CreateEnvVars(),
   341  			BashComplete: common.CreateBashCompletionFunc(),
   342  			Action: func(c *cli.Context) error {
   343  				return buildDiscardCmd(c)
   344  			},
   345  		},
   346  		{
   347  			Name:         "git-lfs-clean",
   348  			Flags:        getGitLfsCleanFlags(),
   349  			Aliases:      []string{"glc"},
   350  			Usage:        gitlfsclean.Description,
   351  			HelpName:     common.CreateUsage("rt git-lfs-clean", gitlfsclean.Description, gitlfsclean.Usage),
   352  			UsageText:    gitlfsclean.Arguments,
   353  			ArgsUsage:    common.CreateEnvVars(),
   354  			BashComplete: common.CreateBashCompletionFunc(),
   355  			Action: func(c *cli.Context) error {
   356  				return gitLfsCleanCmd(c)
   357  			},
   358  		},
   359  		{
   360  			Name:         "mvn-config",
   361  			Aliases:      []string{"mvnc"},
   362  			Flags:        getMavenConfigFlags(),
   363  			Usage:        mvnconfig.Description,
   364  			HelpName:     common.CreateUsage("rt mvn-config", mvnconfig.Description, mvnconfig.Usage),
   365  			ArgsUsage:    common.CreateEnvVars(),
   366  			BashComplete: common.CreateBashCompletionFunc(),
   367  			Action: func(c *cli.Context) error {
   368  				return createMvnConfigCmd(c)
   369  			},
   370  		},
   371  		{
   372  			Name:            "mvn",
   373  			Flags:           getMavenFlags(),
   374  			Usage:           mvndoc.Description,
   375  			HelpName:        common.CreateUsage("rt mvn", mvndoc.Description, mvndoc.Usage),
   376  			UsageText:       mvndoc.Arguments,
   377  			ArgsUsage:       common.CreateEnvVars(mvndoc.EnvVar),
   378  			SkipFlagParsing: shouldSkipMavenFlagParsing(),
   379  			BashComplete:    common.CreateBashCompletionFunc(),
   380  			Action: func(c *cli.Context) error {
   381  				return mvnCmd(c)
   382  			},
   383  		},
   384  		{
   385  			Name:         "gradle-config",
   386  			Aliases:      []string{"gradlec"},
   387  			Flags:        getGradleConfigFlags(),
   388  			Usage:        gradleconfig.Description,
   389  			HelpName:     common.CreateUsage("rt gradle-config", gradleconfig.Description, gradleconfig.Usage),
   390  			ArgsUsage:    common.CreateEnvVars(),
   391  			BashComplete: common.CreateBashCompletionFunc(),
   392  			Action: func(c *cli.Context) error {
   393  				return createGradleConfigCmd(c)
   394  			},
   395  		},
   396  		{
   397  			Name:            "gradle",
   398  			Flags:           getGradleFlags(),
   399  			Usage:           gradledoc.Description,
   400  			HelpName:        common.CreateUsage("rt gradle", gradledoc.Description, gradledoc.Usage),
   401  			UsageText:       gradledoc.Arguments,
   402  			ArgsUsage:       common.CreateEnvVars(gradledoc.EnvVar),
   403  			SkipFlagParsing: shouldSkipGradleFlagParsing(),
   404  			BashComplete:    common.CreateBashCompletionFunc(),
   405  			Action: func(c *cli.Context) error {
   406  				return gradleCmd(c)
   407  			},
   408  		},
   409  		{
   410  			Name:         "docker-push",
   411  			Flags:        getDockerPushFlags(),
   412  			Aliases:      []string{"dp"},
   413  			Usage:        dockerpush.Description,
   414  			HelpName:     common.CreateUsage("rt docker-push", dockerpush.Description, dockerpush.Usage),
   415  			UsageText:    dockerpush.Arguments,
   416  			ArgsUsage:    common.CreateEnvVars(),
   417  			BashComplete: common.CreateBashCompletionFunc(),
   418  			Action: func(c *cli.Context) error {
   419  				return dockerPushCmd(c)
   420  			},
   421  		},
   422  		{
   423  			Name:         "docker-pull",
   424  			Flags:        getDockerPullFlags(),
   425  			Aliases:      []string{"dpl"},
   426  			Usage:        dockerpull.Description,
   427  			HelpName:     common.CreateUsage("rt docker-pull", dockerpull.Description, dockerpull.Usage),
   428  			UsageText:    dockerpull.Arguments,
   429  			ArgsUsage:    common.CreateEnvVars(),
   430  			BashComplete: common.CreateBashCompletionFunc(),
   431  			Action: func(c *cli.Context) error {
   432  				return dockerPullCmd(c)
   433  			},
   434  		},
   435  		{
   436  			Name:         "npm-config",
   437  			Flags:        getCommonBuildToolsConfigFlags(),
   438  			Aliases:      []string{"npmc"},
   439  			Usage:        goconfig.Description,
   440  			HelpName:     common.CreateUsage("rt npm-config", npmconfig.Description, npmconfig.Usage),
   441  			ArgsUsage:    common.CreateEnvVars(),
   442  			BashComplete: common.CreateBashCompletionFunc(),
   443  			Action: func(c *cli.Context) error {
   444  				return createNpmConfigCmd(c)
   445  			},
   446  		},
   447  		{
   448  			Name:            "npm-install",
   449  			Flags:           getNpmFlags(),
   450  			Aliases:         []string{"npmi"},
   451  			Usage:           npminstall.Description,
   452  			HelpName:        common.CreateUsage("rt npm-install", npminstall.Description, npminstall.Usage),
   453  			ArgsUsage:       common.CreateEnvVars(),
   454  			SkipFlagParsing: shouldSkipNpmFlagParsing(),
   455  			BashComplete:    common.CreateBashCompletionFunc(),
   456  			Action: func(c *cli.Context) error {
   457  				return npmInstallCmd(c, npm.NewNpmInstallCommand(), npmLegacyInstallCmd)
   458  			},
   459  		},
   460  		{
   461  			Name:            "npm-ci",
   462  			Flags:           getNpmFlags(),
   463  			Aliases:         []string{"npmci"},
   464  			Usage:           npmci.Description,
   465  			HelpName:        common.CreateUsage("rt npm-ci", npmci.Description, npminstall.Usage),
   466  			ArgsUsage:       common.CreateEnvVars(),
   467  			SkipFlagParsing: shouldSkipNpmFlagParsing(),
   468  			BashComplete:    common.CreateBashCompletionFunc(),
   469  			Action: func(c *cli.Context) error {
   470  				return npmInstallCmd(c, npm.NewNpmCiCommand(), npmLegacyCiCmd)
   471  			},
   472  		},
   473  		{
   474  			Name:            "npm-publish",
   475  			Flags:           getNpmCommonFlags(),
   476  			Aliases:         []string{"npmp"},
   477  			Usage:           npmpublish.Description,
   478  			HelpName:        common.CreateUsage("rt npm-publish", npmpublish.Description, npmpublish.Usage),
   479  			ArgsUsage:       common.CreateEnvVars(),
   480  			SkipFlagParsing: shouldSkipNpmFlagParsing(),
   481  			BashComplete:    common.CreateBashCompletionFunc(),
   482  			Action: func(c *cli.Context) error {
   483  				return npmPublishCmd(c)
   484  			},
   485  		},
   486  		{
   487  			Name:         "nuget-config",
   488  			Flags:        getCommonBuildToolsConfigFlags(),
   489  			Aliases:      []string{"nugetc"},
   490  			Usage:        goconfig.Description,
   491  			HelpName:     common.CreateUsage("rt nuget-config", nugetconfig.Description, nugetconfig.Usage),
   492  			ArgsUsage:    common.CreateEnvVars(),
   493  			BashComplete: common.CreateBashCompletionFunc(),
   494  			Action: func(c *cli.Context) error {
   495  				return createNugetConfigCmd(c)
   496  			},
   497  		},
   498  		{
   499  			Name:            "nuget",
   500  			Flags:           getNugetFlags(),
   501  			Usage:           nugetdocs.Description,
   502  			HelpName:        common.CreateUsage("rt nuget", nugetdocs.Description, nugetdocs.Usage),
   503  			UsageText:       nugetdocs.Arguments,
   504  			ArgsUsage:       common.CreateEnvVars(),
   505  			SkipFlagParsing: shouldSkipNugetFlagParsing(),
   506  			BashComplete:    common.CreateBashCompletionFunc(),
   507  			Action: func(c *cli.Context) error {
   508  				return nugetCmd(c)
   509  			},
   510  		},
   511  		{
   512  			Name:         "nuget-deps-tree",
   513  			Aliases:      []string{"ndt"},
   514  			Usage:        nugettree.Description,
   515  			HelpName:     common.CreateUsage("rt nuget-deps-tree", nugettree.Description, nugettree.Usage),
   516  			UsageText:    nugettree.Arguments,
   517  			ArgsUsage:    common.CreateEnvVars(),
   518  			BashComplete: common.CreateBashCompletionFunc(),
   519  			Action: func(c *cli.Context) error {
   520  				return nugetDepsTreeCmd(c)
   521  			},
   522  		},
   523  		{
   524  			Name:         "go-config",
   525  			Flags:        getCommonBuildToolsConfigFlags(),
   526  			Usage:        goconfig.Description,
   527  			HelpName:     common.CreateUsage("rt go-config", goconfig.Description, goconfig.Usage),
   528  			ArgsUsage:    common.CreateEnvVars(),
   529  			BashComplete: common.CreateBashCompletionFunc(),
   530  			Action: func(c *cli.Context) error {
   531  				return createGoConfigCmd(c)
   532  			},
   533  		},
   534  		{
   535  			Name:         "go-publish",
   536  			Flags:        getGoPublishFlags(),
   537  			Aliases:      []string{"gp"},
   538  			Usage:        gopublish.Description,
   539  			HelpName:     common.CreateUsage("rt go-publish", gopublish.Description, gopublish.Usage),
   540  			UsageText:    gopublish.Arguments,
   541  			ArgsUsage:    common.CreateEnvVars(),
   542  			BashComplete: common.CreateBashCompletionFunc(),
   543  			Action: func(c *cli.Context) error {
   544  				return goPublishCmd(c)
   545  			},
   546  		},
   547  		{
   548  			Name:            "go",
   549  			Flags:           getGoAndBuildToolFlags(),
   550  			Aliases:         []string{"go"},
   551  			Usage:           gocommand.Description,
   552  			HelpName:        common.CreateUsage("rt go", gocommand.Description, gocommand.Usage),
   553  			UsageText:       gocommand.Arguments,
   554  			ArgsUsage:       common.CreateEnvVars(),
   555  			SkipFlagParsing: shouldSkipGoFlagParsing(),
   556  			BashComplete:    common.CreateBashCompletionFunc(),
   557  			Action: func(c *cli.Context) error {
   558  				return goCmd(c)
   559  			},
   560  		},
   561  		{
   562  			Name:         "go-recursive-publish",
   563  			Flags:        getGoRecursivePublishFlags(),
   564  			Aliases:      []string{"grp"},
   565  			Usage:        gorecursivepublish.Description,
   566  			HelpName:     common.CreateUsage("rt grp", gorecursivepublish.Description, gorecursivepublish.Usage),
   567  			UsageText:    gorecursivepublish.Arguments,
   568  			ArgsUsage:    common.CreateEnvVars(),
   569  			BashComplete: common.CreateBashCompletionFunc(),
   570  			Action: func(c *cli.Context) error {
   571  				return goRecursivePublishCmd(c)
   572  			},
   573  		},
   574  		{
   575  			Name:         "ping",
   576  			Flags:        getPingFlags(),
   577  			Aliases:      []string{"p"},
   578  			Usage:        ping.Description,
   579  			HelpName:     common.CreateUsage("rt ping", ping.Description, ping.Usage),
   580  			UsageText:    ping.Arguments,
   581  			ArgsUsage:    common.CreateEnvVars(),
   582  			BashComplete: common.CreateBashCompletionFunc(),
   583  			Action: func(c *cli.Context) error {
   584  				return pingCmd(c)
   585  			},
   586  		},
   587  		{
   588  			Name:            "curl",
   589  			Flags:           getCurlFlags(),
   590  			Aliases:         []string{"cl"},
   591  			Usage:           curldocs.Description,
   592  			HelpName:        common.CreateUsage("rt curl", curldocs.Description, curldocs.Usage),
   593  			UsageText:       curldocs.Arguments,
   594  			ArgsUsage:       common.CreateEnvVars(),
   595  			BashComplete:    common.CreateBashCompletionFunc(),
   596  			SkipFlagParsing: true,
   597  			Action: func(c *cli.Context) error {
   598  				return curlCmd(c)
   599  			},
   600  		},
   601  		{
   602  			Name:         "pip-config",
   603  			Flags:        getCommonBuildToolsConfigFlags(),
   604  			Aliases:      []string{"pipc"},
   605  			Usage:        pipconfig.Description,
   606  			HelpName:     common.CreateUsage("rt pipc", pipconfig.Description, pipconfig.Usage),
   607  			ArgsUsage:    common.CreateEnvVars(),
   608  			BashComplete: common.CreateBashCompletionFunc(),
   609  			Action: func(c *cli.Context) error {
   610  				return createPipConfigCmd(c)
   611  			},
   612  		},
   613  		{
   614  			Name:            "pip-install",
   615  			Flags:           getPipInstallFlags(),
   616  			Aliases:         []string{"pipi"},
   617  			Usage:           pipinstall.Description,
   618  			HelpName:        common.CreateUsage("rt pipi", pipinstall.Description, pipinstall.Usage),
   619  			UsageText:       pipinstall.Arguments,
   620  			ArgsUsage:       common.CreateEnvVars(),
   621  			SkipFlagParsing: true,
   622  			BashComplete:    common.CreateBashCompletionFunc(),
   623  			Action: func(c *cli.Context) error {
   624  				return pipInstallCmd(c)
   625  			},
   626  		},
   627  		{
   628  			Name:         "release-bundle-create",
   629  			Flags:        getReleaseBundleCreateUpdateFlags(),
   630  			Aliases:      []string{"rbc"},
   631  			Usage:        releasebundlecreate.Description,
   632  			HelpName:     common.CreateUsage("rt rbc", releasebundlecreate.Description, releasebundlecreate.Usage),
   633  			UsageText:    releasebundlecreate.Arguments,
   634  			ArgsUsage:    common.CreateEnvVars(),
   635  			BashComplete: common.CreateBashCompletionFunc(),
   636  			Action: func(c *cli.Context) error {
   637  				return releaseBundleCreateCmd(c)
   638  			},
   639  		},
   640  		{
   641  			Name:         "release-bundle-update",
   642  			Flags:        getReleaseBundleCreateUpdateFlags(),
   643  			Aliases:      []string{"rbu"},
   644  			Usage:        releasebundleupdate.Description,
   645  			HelpName:     common.CreateUsage("rt rbu", releasebundleupdate.Description, releasebundleupdate.Usage),
   646  			UsageText:    releasebundleupdate.Arguments,
   647  			ArgsUsage:    common.CreateEnvVars(),
   648  			BashComplete: common.CreateBashCompletionFunc(),
   649  			Action: func(c *cli.Context) error {
   650  				return releaseBundleUpdateCmd(c)
   651  			},
   652  		},
   653  		{
   654  			Name:         "release-bundle-sign",
   655  			Flags:        getReleaseBundleSignFlags(),
   656  			Aliases:      []string{"rbs"},
   657  			Usage:        releasebundlesign.Description,
   658  			HelpName:     common.CreateUsage("rt rbs", releasebundlesign.Description, releasebundlesign.Usage),
   659  			UsageText:    releasebundlesign.Arguments,
   660  			ArgsUsage:    common.CreateEnvVars(),
   661  			BashComplete: common.CreateBashCompletionFunc(),
   662  			Action: func(c *cli.Context) error {
   663  				return releaseBundleSignCmd(c)
   664  			},
   665  		},
   666  		{
   667  			Name:         "release-bundle-distribute",
   668  			Flags:        getReleaseBundleDistributeFlags(),
   669  			Aliases:      []string{"rbd"},
   670  			Usage:        releasebundledistribute.Description,
   671  			HelpName:     common.CreateUsage("rt rbd", releasebundledistribute.Description, releasebundledistribute.Usage),
   672  			UsageText:    releasebundledistribute.Arguments,
   673  			ArgsUsage:    common.CreateEnvVars(),
   674  			BashComplete: common.CreateBashCompletionFunc(),
   675  			Action: func(c *cli.Context) error {
   676  				return releaseBundleDistributeCmd(c)
   677  			},
   678  		},
   679  		{
   680  			Name:         "release-bundle-delete",
   681  			Flags:        getReleaseBundleDeleteFlags(),
   682  			Aliases:      []string{"rbdel"},
   683  			Usage:        releasebundledelete.Description,
   684  			HelpName:     common.CreateUsage("rt rbdel", releasebundledelete.Description, releasebundledelete.Usage),
   685  			UsageText:    releasebundledelete.Arguments,
   686  			ArgsUsage:    common.CreateEnvVars(),
   687  			BashComplete: common.CreateBashCompletionFunc(),
   688  			Action: func(c *cli.Context) error {
   689  				return releaseBundleDeleteCmd(c)
   690  			},
   691  		},
   692  		{
   693  			Name:            "repo-template",
   694  			Aliases:         []string{"rpt"},
   695  			Usage:           repotemplate.Description,
   696  			HelpName:        common.CreateUsage("rt rpt", repotemplate.Description, repotemplate.Usage),
   697  			UsageText:       repotemplate.Arguments,
   698  			ArgsUsage:       common.CreateEnvVars(),
   699  			SkipFlagParsing: true,
   700  			BashComplete:    common.CreateBashCompletionFunc(),
   701  			Action: func(c *cli.Context) error {
   702  				return repoTemplateCmd(c)
   703  			},
   704  		},
   705  		{
   706  			Name:         "repo-create",
   707  			Aliases:      []string{"rc"},
   708  			Flags:        getTemplateUsersFlags(),
   709  			Usage:        repocreate.Description,
   710  			HelpName:     common.CreateUsage("rt rc", repocreate.Description, repocreate.Usage),
   711  			UsageText:    repocreate.Arguments,
   712  			ArgsUsage:    common.CreateEnvVars(),
   713  			BashComplete: common.CreateBashCompletionFunc(),
   714  			Action: func(c *cli.Context) error {
   715  				return repoCreateCmd(c)
   716  			},
   717  		},
   718  		{
   719  			Name:         "repo-update",
   720  			Aliases:      []string{"ru"},
   721  			Flags:        getTemplateUsersFlags(),
   722  			Usage:        repoupdate.Description,
   723  			HelpName:     common.CreateUsage("rt ru", repoupdate.Description, repoupdate.Usage),
   724  			UsageText:    repoupdate.Arguments,
   725  			ArgsUsage:    common.CreateEnvVars(),
   726  			BashComplete: common.CreateBashCompletionFunc(),
   727  			Action: func(c *cli.Context) error {
   728  				return repoUpdateCmd(c)
   729  			},
   730  		},
   731  		{
   732  			Name:         "repo-delete",
   733  			Aliases:      []string{"rdel"},
   734  			Flags:        getRepoDeleteFlags(),
   735  			Usage:        repodelete.Description,
   736  			HelpName:     common.CreateUsage("rt rd", repodelete.Description, repodelete.Usage),
   737  			UsageText:    repodelete.Arguments,
   738  			ArgsUsage:    common.CreateEnvVars(),
   739  			BashComplete: common.CreateBashCompletionFunc(),
   740  			Action: func(c *cli.Context) error {
   741  				return repoDeleteCmd(c)
   742  			},
   743  		},
   744  		{
   745  			Name:         "replication-template",
   746  			Aliases:      []string{"rplt"},
   747  			Flags:        getTemplateUsersFlags(),
   748  			Usage:        replicationtemplate.Description,
   749  			HelpName:     common.CreateUsage("rt rplt", replicationtemplate.Description, replicationtemplate.Usage),
   750  			UsageText:    replicationtemplate.Arguments,
   751  			ArgsUsage:    common.CreateEnvVars(),
   752  			BashComplete: common.CreateBashCompletionFunc(),
   753  			Action: func(c *cli.Context) error {
   754  				return replicationTemplateCmd(c)
   755  			},
   756  		},
   757  		{
   758  			Name:         "replication-create",
   759  			Aliases:      []string{"rplc"},
   760  			Flags:        getTemplateUsersFlags(),
   761  			Usage:        replicationcreate.Description,
   762  			HelpName:     common.CreateUsage("rt rplc", replicationcreate.Description, replicationcreate.Usage),
   763  			UsageText:    replicationcreate.Arguments,
   764  			ArgsUsage:    common.CreateEnvVars(),
   765  			BashComplete: common.CreateBashCompletionFunc(),
   766  			Action: func(c *cli.Context) error {
   767  				return replicationCreateCmd(c)
   768  			},
   769  		},
   770  		{
   771  			Name:         "replication-delete",
   772  			Aliases:      []string{"rpldel"},
   773  			Flags:        getReplicationDeleteFlags(),
   774  			Usage:        replicationdelete.Description,
   775  			HelpName:     common.CreateUsage("rt rpldel", replicationdelete.Description, replicationdelete.Usage),
   776  			UsageText:    replicationdelete.Arguments,
   777  			ArgsUsage:    common.CreateEnvVars(),
   778  			BashComplete: common.CreateBashCompletionFunc(),
   779  			Action: func(c *cli.Context) error {
   780  				return replicationDeleteCmd(c)
   781  			},
   782  		},
   783  	}
   784  }
   785  
   786  func getBaseBuildToolsConfigFlags() []cli.Flag {
   787  	return []cli.Flag{
   788  		cli.BoolFlag{
   789  			Name:  commandUtils.Global,
   790  			Usage: "[Default: false] Set to true if you'd like the configuration to be global (for all projects). Specific projects can override the global configuration.` `",
   791  		},
   792  		cli.StringFlag{
   793  			Name:  commandUtils.ResolutionServerId,
   794  			Usage: "[Optional] Artifactory server ID for resolution. The server should configured using the 'jfrog rt c' command.` `",
   795  		},
   796  		cli.StringFlag{
   797  			Name:  commandUtils.DeploymentServerId,
   798  			Usage: "[Optional] Artifactory server ID for deployment. The server should configured using the 'jfrog rt c' command.` `",
   799  		},
   800  	}
   801  }
   802  
   803  func getCommonBuildToolsConfigFlags() []cli.Flag {
   804  	return append(getBaseBuildToolsConfigFlags(),
   805  		cli.StringFlag{
   806  			Name:  commandUtils.ResolutionRepo,
   807  			Usage: "[Optional] Repository for dependencies resolution.` `",
   808  		},
   809  		cli.StringFlag{
   810  			Name:  commandUtils.DeploymentRepo,
   811  			Usage: "[Optional] Repository for artifacts deployment.` `",
   812  		},
   813  	)
   814  }
   815  
   816  func getMavenConfigFlags() []cli.Flag {
   817  	return append(getBaseBuildToolsConfigFlags(),
   818  		cli.StringFlag{
   819  			Name:  commandUtils.ResolutionReleasesRepo,
   820  			Usage: "[Optional] Resolution repository for release dependencies.` `",
   821  		},
   822  		cli.StringFlag{
   823  			Name:  commandUtils.ResolutionSnapshotsRepo,
   824  			Usage: "[Optional] Resolution repository for snapshot dependencies.` `",
   825  		},
   826  		cli.StringFlag{
   827  			Name:  commandUtils.DeploymentReleasesRepo,
   828  			Usage: "[Optional] Deployment repository for release artifacts.` `",
   829  		},
   830  		cli.StringFlag{
   831  			Name:  commandUtils.DeploymentSnapshotsRepo,
   832  			Usage: "[Optional] Deployment repository for snapshot artifacts.` `",
   833  		},
   834  	)
   835  }
   836  
   837  func getGradleConfigFlags() []cli.Flag {
   838  	return append(getCommonBuildToolsConfigFlags(),
   839  		cli.BoolFlag{
   840  			Name:  commandUtils.UsesPlugin,
   841  			Usage: "[Default: false] Set to true if the Gradle Artifactory Plugin is already applied in the build script.` `",
   842  		},
   843  		cli.BoolFlag{
   844  			Name:  commandUtils.UseWrapper,
   845  			Usage: "[Default: false] Set to true if you'd like to use the Gradle wrapper.` `",
   846  		},
   847  		cli.BoolTFlag{
   848  			Name:  commandUtils.DeployMavenDesc,
   849  			Usage: "[Default: true] Set to false if you do not wish to deploy Maven descriptors.` `",
   850  		},
   851  		cli.BoolTFlag{
   852  			Name:  commandUtils.DeployIvyDesc,
   853  			Usage: "[Default: true] Set to false if you do not wish to deploy Ivy descriptors.` `",
   854  		},
   855  		cli.StringFlag{
   856  			Name:  commandUtils.IvyDescPattern,
   857  			Usage: "[Default: '[organization]/[module]/ivy-[revision].xml' Set the deployed Ivy descriptor pattern.` `",
   858  		},
   859  		cli.StringFlag{
   860  			Name:  commandUtils.IvyArtifactsPattern,
   861  			Usage: "[Default: '[organization]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]' Set the deployed Ivy artifacts pattern.` `",
   862  		},
   863  	)
   864  }
   865  
   866  func getUrlFlags() []cli.Flag {
   867  	return []cli.Flag{
   868  		cli.StringFlag{
   869  			Name:  "url",
   870  			Usage: "[Optional] Artifactory URL.` `",
   871  		},
   872  		cli.StringFlag{
   873  			Name:  "dist-url",
   874  			Usage: "[Optional] Distribution URL.` `",
   875  		},
   876  	}
   877  }
   878  
   879  func getBaseFlags() []cli.Flag {
   880  	return append(getUrlFlags(),
   881  		cli.StringFlag{
   882  			Name:  "user",
   883  			Usage: "[Optional] Artifactory username.` `",
   884  		},
   885  		cli.StringFlag{
   886  			Name:  "password",
   887  			Usage: "[Optional] Artifactory password.` `",
   888  		},
   889  		cli.StringFlag{
   890  			Name:  "apikey",
   891  			Usage: "[Optional] Artifactory API key.` `",
   892  		},
   893  		cli.StringFlag{
   894  			Name:  "access-token",
   895  			Usage: "[Optional] Artifactory access token.` `",
   896  		})
   897  }
   898  
   899  func getInsecureTlsFlag() cli.Flag {
   900  	return cli.BoolFlag{
   901  		Name:  "insecure-tls",
   902  		Usage: "[Default: false] Set to true to skip TLS certificates verification.` `",
   903  	}
   904  }
   905  
   906  func getClientCertsFlags() []cli.Flag {
   907  	return []cli.Flag{
   908  		cli.StringFlag{
   909  			Name:  "client-cert-path",
   910  			Usage: "[Optional] Client certificate file in PEM format.` `",
   911  		},
   912  		cli.StringFlag{
   913  			Name:  "client-cert-key-path",
   914  			Usage: "[Optional] Private key file for the client certificate in PEM format.` `",
   915  		},
   916  	}
   917  }
   918  
   919  func getCommonFlags() []cli.Flag {
   920  	flags := append(getBaseFlags(),
   921  		cli.StringFlag{
   922  			Name:  "ssh-passphrase",
   923  			Usage: "[Optional] SSH key passphrase.` `",
   924  		})
   925  	return append(flags, getSshKeyPathFlag()...)
   926  }
   927  
   928  func getServerFlags() []cli.Flag {
   929  	return append(getCommonFlags(), getServerIdFlag())
   930  }
   931  
   932  func getServerWithClientCertsFlags() []cli.Flag {
   933  	return append(getServerFlags(), getClientCertsFlags()...)
   934  }
   935  
   936  func getPingFlags() []cli.Flag {
   937  	return append(getServerWithClientCertsFlags(), getInsecureTlsFlag())
   938  }
   939  
   940  func getSortLimitFlags() []cli.Flag {
   941  	return []cli.Flag{
   942  		cli.StringFlag{
   943  			Name:  "sort-by",
   944  			Usage: "[Optional] A list of semicolon-separated fields to sort by. The fields must be part of the 'items' AQL domain. For more information, see https://www.jfrog.com/confluence/display/RTF/Artifactory+Query+Language#ArtifactoryQueryLanguage-EntitiesandFields` `",
   945  		},
   946  		cli.StringFlag{
   947  			Name:  "sort-order",
   948  			Usage: "[Default: asc] The order by which fields in the 'sort-by' option should be sorted. Accepts 'asc' or 'desc'.` `",
   949  		},
   950  		cli.StringFlag{
   951  			Name:  "limit",
   952  			Usage: "[Optional] The maximum number of items to fetch. Usually used with the 'sort-by' option.` `",
   953  		},
   954  		cli.StringFlag{
   955  			Name:  "offset",
   956  			Usage: "[Optional] The offset from which to fetch items (i.e. how many items should be skipped). Usually used with the 'sort-by' option.` `",
   957  		},
   958  	}
   959  }
   960  
   961  func getUploadFlags() []cli.Flag {
   962  	uploadFlags := append(getServerWithClientCertsFlags(), getSpecFlags()...)
   963  	uploadFlags = append(uploadFlags, getBuildAndModuleFlags()...)
   964  	uploadFlags = append(uploadFlags, getUploadExclusionsFlags()...)
   965  	return append(uploadFlags, []cli.Flag{
   966  		cli.StringFlag{
   967  			Name:  "deb",
   968  			Usage: "[Optional] Used for Debian packages in the form of distribution/component/architecture. If the value for distribution, component or architecture includes a slash, the slash should be escaped with a back-slash.` `",
   969  		},
   970  		cli.BoolTFlag{
   971  			Name:  "recursive",
   972  			Usage: "[Default: true] Set to false if you do not wish to collect artifacts in sub-folders to be uploaded to Artifactory.` `",
   973  		},
   974  		cli.BoolTFlag{
   975  			Name:  "flat",
   976  			Usage: "[Default: true] If set to false, files are uploaded according to their file system hierarchy.` `",
   977  		},
   978  		cli.BoolFlag{
   979  			Name:  "regexp",
   980  			Usage: "[Default: false] Set to true to use a regular expression instead of wildcards expression to collect files to upload.` `",
   981  		},
   982  		cli.StringFlag{
   983  			Name:  "retries",
   984  			Usage: "[Default: " + strconv.Itoa(cliutils.Retries) + "] Number of upload retries.` `",
   985  		},
   986  		cli.BoolFlag{
   987  			Name:  "dry-run",
   988  			Usage: "[Default: false] Set to true to disable communication with Artifactory.` `",
   989  		},
   990  		cli.BoolFlag{
   991  			Name:  "explode",
   992  			Usage: "[Default: false] Set to true to extract an archive after it is deployed to Artifactory.` `",
   993  		},
   994  		cli.BoolFlag{
   995  			Name:  "symlinks",
   996  			Usage: "[Default: false] Set to true to preserve symbolic links structure in Artifactory.` `",
   997  		},
   998  		getIncludeDirsFlag(),
   999  		getPropertiesFlag("Those properties will be attached to the uploaded artifacts."),
  1000  		getFailNoOpFlag(),
  1001  		getThreadsFlag(),
  1002  		getSyncDeletesFlag("[Optional] Specific path in Artifactory, under which to sync artifacts after the upload. After the upload, this path will include only the artifacts uploaded during this upload operation. The other files under this path will be deleted.` `"),
  1003  		getQuiteFlag("[Default: $CI] Set to true to skip the sync-deletes confirmation message.` `"),
  1004  		getInsecureTlsFlag(),
  1005  	}...)
  1006  }
  1007  
  1008  func getDownloadFlags() []cli.Flag {
  1009  	downloadFlags := append(getServerWithClientCertsFlags(), getSortLimitFlags()...)
  1010  	downloadFlags = append(downloadFlags, getSpecFlags()...)
  1011  	downloadFlags = append(downloadFlags, getBuildAndModuleFlags()...)
  1012  	downloadFlags = append(downloadFlags, getExclusionsFlags()...)
  1013  	return append(downloadFlags, []cli.Flag{
  1014  		cli.BoolTFlag{
  1015  			Name:  "recursive",
  1016  			Usage: "[Default: true] Set to false if you do not wish to include the download of artifacts inside sub-folders in Artifactory.` `",
  1017  		},
  1018  		cli.BoolFlag{
  1019  			Name:  "flat",
  1020  			Usage: "[Default: false] Set to true if you do not wish to have the Artifactory repository path structure created locally for your downloaded files.` `",
  1021  		},
  1022  		cli.StringFlag{
  1023  			Name:  "build",
  1024  			Usage: "[Optional] If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number.` `",
  1025  		},
  1026  		cli.StringFlag{
  1027  			Name:  "min-split",
  1028  			Value: "",
  1029  			Usage: "[Default: " + strconv.Itoa(cliutils.DownloadMinSplitKb) + "] Minimum file size in KB to split into ranges when downloading. Set to -1 for no splits.` `",
  1030  		},
  1031  		cli.StringFlag{
  1032  			Name:  "split-count",
  1033  			Value: "",
  1034  			Usage: "[Default: " + strconv.Itoa(cliutils.DownloadSplitCount) + "] Number of parts to split a file when downloading. Set to 0 for no splits.` `",
  1035  		},
  1036  		cli.StringFlag{
  1037  			Name:  "retries",
  1038  			Usage: "[Default: " + strconv.Itoa(cliutils.Retries) + "] Number of download retries.` `",
  1039  		},
  1040  		cli.BoolFlag{
  1041  			Name:  "dry-run",
  1042  			Usage: "[Default: false] Set to true to disable communication with Artifactory.` `",
  1043  		},
  1044  		cli.BoolFlag{
  1045  			Name:  "explode",
  1046  			Usage: "[Default: false] Set to true to extract an archive after it is downloaded from Artifactory.` `",
  1047  		},
  1048  		cli.BoolFlag{
  1049  			Name:  "validate-symlinks",
  1050  			Usage: "[Default: false] Set to true to perform a checksum validation when downloading symbolic links.` `",
  1051  		},
  1052  		getBundleFlag(),
  1053  		getIncludeDirsFlag(),
  1054  		getPropertiesFlag("Only artifacts with these properties will be downloaded."),
  1055  		getExcludePropertiesFlag("Only artifacts without the specified properties will be downloaded"),
  1056  		getFailNoOpFlag(),
  1057  		getThreadsFlag(),
  1058  		getArchiveEntriesFlag(),
  1059  		getSyncDeletesFlag("[Optional] Specific path in the local file system, under which to sync dependencies after the download. After the download, this path will include only the dependencies downloaded during this download operation. The other files under this path will be deleted.` `"),
  1060  		getQuiteFlag("[Default: $CI] Set to true to skip the sync-deletes confirmation message.` `"),
  1061  		getInsecureTlsFlag(),
  1062  	}...)
  1063  }
  1064  
  1065  func getTemplateUsersFlags() []cli.Flag {
  1066  	return append(getServerWithClientCertsFlags(), cli.StringFlag{
  1067  		Name:  "vars",
  1068  		Usage: "[Optional] List of variables in the form of \"key1=value1;key2=value2;...\" to be replaced in the template. In the template, the variables should be used as follows: ${key1}.` `",
  1069  	})
  1070  }
  1071  
  1072  func getRepoDeleteFlags() []cli.Flag {
  1073  	return append(getServerWithClientCertsFlags(), getQuiteFlag("[Default: $CI] Set to true to skip the delete confirmation message.` `"))
  1074  }
  1075  
  1076  func getReplicationDeleteFlags() []cli.Flag {
  1077  	return getRepoDeleteFlags()
  1078  }
  1079  
  1080  func getBuildFlags() []cli.Flag {
  1081  	return []cli.Flag{
  1082  		cli.StringFlag{
  1083  			Name:  "build-name",
  1084  			Usage: "[Optional] Providing this option will collect and record build info for this build name. Build number option is mandatory when this option is provided.` `",
  1085  		},
  1086  		cli.StringFlag{
  1087  			Name:  "build-number",
  1088  			Usage: "[Optional] Providing this option will collect and record build info for this build number. Build name option is mandatory when this option is provided.` `",
  1089  		},
  1090  	}
  1091  }
  1092  
  1093  func getBuildAndModuleFlags() []cli.Flag {
  1094  	return append(getBuildFlags(), cli.StringFlag{
  1095  		Name:  "module",
  1096  		Usage: "[Optional] Optional module name for the build-info. Build name and number options are mandatory when this option is provided.` `",
  1097  	})
  1098  }
  1099  
  1100  func getSkipLoginFlag() cli.Flag {
  1101  	return cli.BoolFlag{
  1102  		Name:  "skip-login",
  1103  		Usage: "[Default: false] Set to true if you'd like the command to skip performing docker login.` `",
  1104  	}
  1105  }
  1106  
  1107  func getServerIdFlag() cli.Flag {
  1108  	return cli.StringFlag{
  1109  		Name:  "server-id",
  1110  		Usage: "[Optional] Artifactory server ID configured using the config command.` `",
  1111  	}
  1112  }
  1113  
  1114  func getFailNoOpFlag() cli.Flag {
  1115  	return cli.BoolFlag{
  1116  		Name:  "fail-no-op",
  1117  		Usage: "[Default: false] Set to true if you'd like the command to return exit code 2 in case of no files are affected.` `",
  1118  	}
  1119  }
  1120  
  1121  func getExclusionsFlags() []cli.Flag {
  1122  	return []cli.Flag{
  1123  		cli.StringFlag{
  1124  			Name:   "exclude-patterns",
  1125  			Usage:  "[Optional] Semicolon-separated list of exclude patterns. Exclude patterns may contain the * and the ? wildcards. Unlike the Source path, it must not include the repository name at the beginning of the path.` `",
  1126  			Hidden: true,
  1127  		},
  1128  		cli.StringFlag{
  1129  			Name:  "exclusions",
  1130  			Usage: "[Optional] Semicolon-separated list of exclusions. Exclusions can include the * and the ? wildcards.` `",
  1131  		},
  1132  	}
  1133  }
  1134  
  1135  func getUploadExclusionsFlags() []cli.Flag {
  1136  	return []cli.Flag{
  1137  		cli.StringFlag{
  1138  			Name:   "exclude-patterns",
  1139  			Usage:  "[Optional] Semicolon-separated list of exclude patterns. Exclude patterns may contain the * and the ? wildcards or a regex pattern, according to the value of the 'regexp' option.` `",
  1140  			Hidden: true,
  1141  		},
  1142  		cli.StringFlag{
  1143  			Name:  "exclusions",
  1144  			Usage: "[Optional] Semicolon-separated list of exclude patterns. Exclude patterns may contain the * and the ? wildcards or a regex pattern, according to the value of the 'regexp' option.` `",
  1145  		},
  1146  	}
  1147  }
  1148  
  1149  func getSpecFlags() []cli.Flag {
  1150  	return []cli.Flag{
  1151  		cli.StringFlag{
  1152  			Name:  "spec",
  1153  			Usage: "[Optional] Path to a File Spec.` `",
  1154  		},
  1155  		cli.StringFlag{
  1156  			Name:  "spec-vars",
  1157  			Usage: "[Optional] List of variables in the form of \"key1=value1;key2=value2;...\" to be replaced in the File Spec. In the File Spec, the variables should be used as follows: ${key1}.` `",
  1158  		},
  1159  	}
  1160  }
  1161  
  1162  func getGradleFlags() []cli.Flag {
  1163  	return append(getBuildFlags(), getDeploymentThreadsFlag())
  1164  }
  1165  
  1166  func getMavenFlags() []cli.Flag {
  1167  	flags := append(getBuildFlags(), getDeploymentThreadsFlag())
  1168  	return append(flags, getInsecureTlsFlag())
  1169  }
  1170  
  1171  func getDockerPushFlags() []cli.Flag {
  1172  	var flags []cli.Flag
  1173  	flags = append(flags, getDockerFlags()...)
  1174  	flags = append(flags, getThreadsFlag())
  1175  	return flags
  1176  }
  1177  
  1178  func getDockerPullFlags() []cli.Flag {
  1179  	return getDockerFlags()
  1180  }
  1181  
  1182  func getDockerFlags() []cli.Flag {
  1183  	var flags []cli.Flag
  1184  	flags = append(flags, getBuildAndModuleFlags()...)
  1185  	flags = append(flags, getServerFlags()...)
  1186  	flags = append(flags, getSkipLoginFlag())
  1187  	return flags
  1188  }
  1189  func getDeprecatedFlags() []cli.Flag {
  1190  	return []cli.Flag{
  1191  		cli.StringFlag{
  1192  			Name:  "url",
  1193  			Usage: "[Deprecated] [Optional] Artifactory URL.` `",
  1194  		},
  1195  		cli.StringFlag{
  1196  			Name:  "user",
  1197  			Usage: "[Deprecated] [Optional] Artifactory username.` `",
  1198  		},
  1199  		cli.StringFlag{
  1200  			Name:  "password",
  1201  			Usage: "[Deprecated] [Optional] Artifactory password.` `",
  1202  		},
  1203  		cli.StringFlag{
  1204  			Name:  "apikey",
  1205  			Usage: "[Deprecated] [Optional] Artifactory API key.` `",
  1206  		},
  1207  		cli.StringFlag{
  1208  			Name:  "access-token",
  1209  			Usage: "[Deprecated] [Optional] Artifactory access token.` `",
  1210  		},
  1211  	}
  1212  }
  1213  
  1214  //This flag are not valid for native npm commands.
  1215  func getNpmLegacyFlags() []cli.Flag {
  1216  	npmFlags := cli.StringFlag{
  1217  		Name:  "npm-args",
  1218  		Usage: "[Deprecated] [Optional] A list of npm arguments and options in the form of \"--arg1=value1 --arg2=value2\"` `",
  1219  	}
  1220  	return append(getDeprecatedFlags(), npmFlags)
  1221  }
  1222  
  1223  func getNpmCommonFlags() []cli.Flag {
  1224  	npmFlags := getNpmLegacyFlags()
  1225  	return append(getBuildAndModuleFlags(), npmFlags...)
  1226  }
  1227  
  1228  func getNpmFlags() []cli.Flag {
  1229  	npmFlags := getNpmCommonFlags()
  1230  	flag := cli.StringFlag{
  1231  		Name:  "threads",
  1232  		Value: "",
  1233  		Usage: "[Default: 3] Number of working threads for build-info collection.` `",
  1234  	}
  1235  	return append([]cli.Flag{flag}, npmFlags...)
  1236  }
  1237  
  1238  func getBasicBuildToolsFlags() []cli.Flag {
  1239  	return append(getBaseFlags(), getServerIdFlag())
  1240  }
  1241  
  1242  func getNugetFlags() []cli.Flag {
  1243  	nugetFlags := getNugetCommonFlags()
  1244  	return append(getBuildAndModuleFlags(), nugetFlags...)
  1245  }
  1246  
  1247  func getNugetCommonFlags() []cli.Flag {
  1248  	commonNugetFlags := []cli.Flag{
  1249  		cli.StringFlag{
  1250  			Name:  "nuget-args",
  1251  			Usage: "[Deprecated] [Optional] A list of NuGet arguments and options in the form of \"arg1 arg2 arg3\"` `",
  1252  		},
  1253  		cli.StringFlag{
  1254  			Name:  "solution-root",
  1255  			Usage: "[Deprecated] [Default: .] Path to the root directory of the solution. If the directory includes more than one sln files, then the first argument passed in the --nuget-args option should be the name (not the path) of the sln file.` `",
  1256  		},
  1257  	}
  1258  	commonNugetFlags = append(commonNugetFlags, getDeprecatedFlags()...)
  1259  	return commonNugetFlags
  1260  }
  1261  
  1262  func getGoFlags() []cli.Flag {
  1263  	flags := []cli.Flag{
  1264  		cli.BoolFlag{
  1265  			Name:  "no-registry",
  1266  			Usage: "[Deprecated] [Default: false] Set to true if you don't want to use Artifactory as your proxy` `",
  1267  		},
  1268  		cli.BoolFlag{
  1269  			Name:  "publish-deps",
  1270  			Usage: "[Deprecated] [Default: false] Set to true if you wish to publish missing dependencies to Artifactory` `",
  1271  		},
  1272  	}
  1273  	flags = append(flags, getDeprecatedFlags()...)
  1274  	return flags
  1275  }
  1276  
  1277  func getGoAndBuildToolFlags() []cli.Flag {
  1278  	flags := getGoFlags()
  1279  	flags = append(getBuildAndModuleFlags(), flags...)
  1280  	return flags
  1281  }
  1282  
  1283  func getGoRecursivePublishFlags() []cli.Flag {
  1284  	return getBasicBuildToolsFlags()
  1285  }
  1286  
  1287  func getGoPublishFlags() []cli.Flag {
  1288  	flags := []cli.Flag{
  1289  		cli.StringFlag{
  1290  			Name:  "deps",
  1291  			Value: "",
  1292  			Usage: "[Optional] List of project dependencies in the form of \"dep1-name:version,dep2-name:version...\" to be published to Artifactory. Use \"ALL\" to publish all dependencies.` `",
  1293  		},
  1294  		cli.BoolTFlag{
  1295  			Name:  "self",
  1296  			Usage: "[Default: true] Set false to skip publishing the project package zip file to Artifactory..` `",
  1297  		},
  1298  	}
  1299  	flags = append(flags, getBasicBuildToolsFlags()...)
  1300  	flags = append(flags, getBuildAndModuleFlags()...)
  1301  	return flags
  1302  }
  1303  
  1304  func getMoveFlags() []cli.Flag {
  1305  	moveFlags := append(getServerWithClientCertsFlags(), getSortLimitFlags()...)
  1306  	moveFlags = append(moveFlags, getSpecFlags()...)
  1307  	moveFlags = append(moveFlags, getExclusionsFlags()...)
  1308  	return append(moveFlags, []cli.Flag{
  1309  		cli.BoolTFlag{
  1310  			Name:  "recursive",
  1311  			Usage: "[Default: true] Set to false if you do not wish to move artifacts inside sub-folders in Artifactory.` `",
  1312  		},
  1313  		cli.BoolFlag{
  1314  			Name:  "flat",
  1315  			Usage: "[Default: false] If set to false, files are moved according to their file system hierarchy.` `",
  1316  		},
  1317  		cli.BoolFlag{
  1318  			Name:  "dry-run",
  1319  			Usage: "[Default: false] Set to true to disable communication with Artifactory.` `",
  1320  		},
  1321  		cli.StringFlag{
  1322  			Name:  "build",
  1323  			Usage: "[Optional] If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number.` `",
  1324  		},
  1325  		getPropertiesFlag("Only artifacts with these properties will be moved."),
  1326  		getExcludePropertiesFlag("Only artifacts without the specified properties will be moved"),
  1327  		getFailNoOpFlag(),
  1328  		getArchiveEntriesFlag(),
  1329  		getInsecureTlsFlag(),
  1330  	}...)
  1331  
  1332  }
  1333  
  1334  func getCopyFlags() []cli.Flag {
  1335  	copyFlags := append(getServerWithClientCertsFlags(), getSortLimitFlags()...)
  1336  	copyFlags = append(copyFlags, getSpecFlags()...)
  1337  	copyFlags = append(copyFlags, getExclusionsFlags()...)
  1338  	return append(copyFlags, []cli.Flag{
  1339  		cli.BoolTFlag{
  1340  			Name:  "recursive",
  1341  			Usage: "[Default: true] Set to false if you do not wish to copy artifacts inside sub-folders in Artifactory.` `",
  1342  		},
  1343  		cli.BoolFlag{
  1344  			Name:  "flat",
  1345  			Usage: "[Default: false] If set to false, files are copied according to their file system hierarchy.` `",
  1346  		},
  1347  		cli.BoolFlag{
  1348  			Name:  "dry-run",
  1349  			Usage: "[Default: false] Set to true to disable communication with Artifactory.` `",
  1350  		},
  1351  		cli.StringFlag{
  1352  			Name:  "build",
  1353  			Usage: "[Optional] If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number.` `",
  1354  		},
  1355  		getBundleFlag(),
  1356  		getPropertiesFlag("Only artifacts with these properties will be copied."),
  1357  		getExcludePropertiesFlag("Only artifacts without the specified properties will be copied"),
  1358  		getFailNoOpFlag(),
  1359  		getArchiveEntriesFlag(),
  1360  		getInsecureTlsFlag(),
  1361  	}...)
  1362  }
  1363  
  1364  func getDeleteFlags() []cli.Flag {
  1365  	deleteFlags := append(getServerWithClientCertsFlags(), getSortLimitFlags()...)
  1366  	deleteFlags = append(deleteFlags, getSpecFlags()...)
  1367  	deleteFlags = append(deleteFlags, getExclusionsFlags()...)
  1368  	return append(deleteFlags, []cli.Flag{
  1369  		cli.BoolTFlag{
  1370  			Name:  "recursive",
  1371  			Usage: "[Default: true] Set to false if you do not wish to delete artifacts inside sub-folders in Artifactory.` `",
  1372  		},
  1373  		cli.BoolFlag{
  1374  			Name:  "dry-run",
  1375  			Usage: "[Default: false] Set to true to disable communication with Artifactory.` `",
  1376  		},
  1377  		cli.StringFlag{
  1378  			Name:  "build",
  1379  			Usage: "[Optional] If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number.` `",
  1380  		},
  1381  		getQuiteFlag("[Default: $CI] Set to true to skip the delete confirmation message.` `"),
  1382  		getPropertiesFlag("Only artifacts with these properties will be deleted."),
  1383  		getExcludePropertiesFlag("Only artifacts without the specified properties will be deleted"),
  1384  		getFailNoOpFlag(),
  1385  		getThreadsFlag(),
  1386  		getArchiveEntriesFlag(),
  1387  		getInsecureTlsFlag(),
  1388  	}...)
  1389  }
  1390  
  1391  func getSearchFlags() []cli.Flag {
  1392  	searchFlags := append(getServerWithClientCertsFlags(), getSortLimitFlags()...)
  1393  	searchFlags = append(searchFlags, getSpecFlags()...)
  1394  	searchFlags = append(searchFlags, getExclusionsFlags()...)
  1395  	return append(searchFlags, []cli.Flag{
  1396  		cli.BoolTFlag{
  1397  			Name:  "recursive",
  1398  			Usage: "[Default: true] Set to false if you do not wish to search artifacts inside sub-folders in Artifactory.` `",
  1399  		},
  1400  		cli.StringFlag{
  1401  			Name:  "build",
  1402  			Usage: "[Optional] If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number.` `",
  1403  		},
  1404  		cli.BoolFlag{
  1405  			Name:  "count",
  1406  			Usage: "[Optional] Set to true to display only the total of files or folders found.` `",
  1407  		},
  1408  		getBundleFlag(),
  1409  		getIncludeDirsFlag(),
  1410  		getPropertiesFlag("Only artifacts with these properties will be returned."),
  1411  		getExcludePropertiesFlag("Only artifacts without the specified properties will be returned"),
  1412  		getFailNoOpFlag(),
  1413  		getArchiveEntriesFlag(),
  1414  		getInsecureTlsFlag(),
  1415  	}...)
  1416  }
  1417  
  1418  func getSyncDeletesFlag(description string) cli.Flag {
  1419  	return cli.StringFlag{
  1420  		Name:  "sync-deletes",
  1421  		Usage: description,
  1422  	}
  1423  }
  1424  
  1425  func getSetOrDeletePropsFlags() []cli.Flag {
  1426  	flags := append(getSpecFlags(), []cli.Flag{
  1427  		getPropertiesFlag("Only artifacts with these properties are affected."),
  1428  		getExcludePropertiesFlag("Only artifacts without the specified properties are affected"),
  1429  		getInsecureTlsFlag(),
  1430  	}...)
  1431  	return append(flags, getPropertiesFlags()...)
  1432  }
  1433  
  1434  func getPropertiesFlag(description string) cli.Flag {
  1435  	return cli.StringFlag{
  1436  		Name:  "props",
  1437  		Usage: fmt.Sprintf("[Optional] List of properties in the form of \"key1=value1;key2=value2,...\". %s ` `", description),
  1438  	}
  1439  }
  1440  
  1441  func getExcludePropertiesFlag(description string) cli.Flag {
  1442  	return cli.StringFlag{
  1443  		Name:  "exclude-props",
  1444  		Usage: fmt.Sprintf("[Optional] List of properties in the form of \"key1=value1;key2=value2,...\". %s ` `", description),
  1445  	}
  1446  }
  1447  
  1448  func getQuiteFlag(description string) cli.Flag {
  1449  	return cli.BoolFlag{
  1450  		Name:  "quiet",
  1451  		Usage: description,
  1452  	}
  1453  }
  1454  
  1455  func getPropertiesFlags() []cli.Flag {
  1456  	propsFlags := append(getServerWithClientCertsFlags(), getSortLimitFlags()...)
  1457  	propsFlags = append(propsFlags, getExclusionsFlags()...)
  1458  	return append(propsFlags, []cli.Flag{
  1459  		cli.BoolTFlag{
  1460  			Name:  "recursive",
  1461  			Usage: "[Default: true] When false, artifacts inside sub-folders in Artifactory will not be affected.` `",
  1462  		},
  1463  		cli.StringFlag{
  1464  			Name:  "build",
  1465  			Usage: "[Optional] If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number.` `",
  1466  		},
  1467  		getBundleFlag(),
  1468  		getIncludeDirsFlag(),
  1469  		getFailNoOpFlag(),
  1470  		getThreadsFlag(),
  1471  		getArchiveEntriesFlag(),
  1472  	}...)
  1473  }
  1474  
  1475  func getIncludeDirsFlag() cli.Flag {
  1476  	return cli.BoolFlag{
  1477  		Name:  "include-dirs",
  1478  		Usage: "[Default: false] Set to true if you'd like to also apply the source path pattern for directories and not just for files.` `",
  1479  	}
  1480  }
  1481  
  1482  func getArchiveEntriesFlag() cli.Flag {
  1483  	return cli.StringFlag{
  1484  		Name:  "archive-entries",
  1485  		Usage: "[Optional] If specified, only archive artifacts containing entries matching this pattern are matched. You can use wildcards to specify multiple artifacts.` `",
  1486  	}
  1487  }
  1488  
  1489  func getDeploymentThreadsFlag() cli.Flag {
  1490  	return cli.StringFlag{
  1491  		Name:  "threads",
  1492  		Value: "",
  1493  		Usage: "[Default: 3] Number of threads for uploading build artifacts.` `",
  1494  	}
  1495  }
  1496  
  1497  func getThreadsFlag() cli.Flag {
  1498  	return cli.StringFlag{
  1499  		Name:  "threads",
  1500  		Value: "",
  1501  		Usage: "[Default: 3] Number of working threads.` `",
  1502  	}
  1503  }
  1504  
  1505  func getBundleFlag() cli.Flag {
  1506  	return cli.StringFlag{
  1507  		Name:  "bundle",
  1508  		Usage: "[Optional] If specified, only artifacts of the specified bundle are matched. The value format is bundle-name/bundle-version.` `",
  1509  	}
  1510  }
  1511  
  1512  func getBuildPublishFlags() []cli.Flag {
  1513  	return append(getServerFlags(), []cli.Flag{
  1514  		cli.StringFlag{
  1515  			Name:  "build-url",
  1516  			Usage: "[Optional] Can be used for setting the CI server build URL in the build-info.` `",
  1517  		},
  1518  		cli.BoolFlag{
  1519  			Name:  "dry-run",
  1520  			Usage: "[Default: false] Set to true to disable communication with Artifactory.` `",
  1521  		},
  1522  		cli.StringFlag{
  1523  			Name:  "env-include",
  1524  			Usage: "[Default: *] List of patterns in the form of \"value1;value2;...\" Only environment variables match those patterns will be included.` `",
  1525  		},
  1526  		cli.StringFlag{
  1527  			Name:  "env-exclude",
  1528  			Usage: "[Default: *password*;*secret*;*key*;*token*] List of case insensitive patterns in the form of \"value1;value2;...\". Environment variables match those patterns will be excluded.` `",
  1529  		},
  1530  		getInsecureTlsFlag(),
  1531  	}...)
  1532  }
  1533  
  1534  func getBuildAddDependenciesFlags() []cli.Flag {
  1535  	buildAddDependenciesFlags := append(getSpecFlags(), getUploadExclusionsFlags()...)
  1536  	return append(buildAddDependenciesFlags, []cli.Flag{
  1537  		cli.BoolTFlag{
  1538  			Name:  "recursive",
  1539  			Usage: "[Default: true] Set to false if you do not wish to collect artifacts in sub-folders to be added to the build info.` `",
  1540  		},
  1541  		cli.BoolFlag{
  1542  			Name:  "regexp",
  1543  			Usage: "[Default: false] Set to true to use a regular expression instead of wildcards expression to collect files to be added to the build info.` `",
  1544  		},
  1545  		cli.BoolFlag{
  1546  			Name:  "dry-run",
  1547  			Usage: "[Default: false] Set to true to only get a summery of the dependencies that will be added to the build info.` `",
  1548  		},
  1549  	}...)
  1550  }
  1551  
  1552  func getBuildPromotionFlags() []cli.Flag {
  1553  	return append(getServerFlags(), []cli.Flag{
  1554  		cli.StringFlag{
  1555  			Name:  "status",
  1556  			Usage: "[Optional] Build promotion status.` `",
  1557  		},
  1558  		cli.StringFlag{
  1559  			Name:  "comment",
  1560  			Usage: "[Optional] Build promotion comment.` `",
  1561  		},
  1562  		cli.StringFlag{
  1563  			Name:  "source-repo",
  1564  			Usage: "[Optional] Build promotion source repository.` `",
  1565  		},
  1566  		cli.BoolFlag{
  1567  			Name:  "include-dependencies",
  1568  			Usage: "[Default: false] If set to true, the build dependencies are also promoted.` `",
  1569  		},
  1570  		cli.BoolFlag{
  1571  			Name:  "copy",
  1572  			Usage: "[Default: false] If set true, the build artifacts and dependencies are copied to the target repository, otherwise they are moved.` `",
  1573  		},
  1574  		cli.BoolFlag{
  1575  			Name:  "dry-run",
  1576  			Usage: "[Default: false] If true, promotion is only simulated. The build is not promoted.` `",
  1577  		},
  1578  		getPropertiesFlag("A list of properties to attach to the build artifacts."),
  1579  		getInsecureTlsFlag(),
  1580  	}...)
  1581  }
  1582  
  1583  func getBuildDistributeFlags() []cli.Flag {
  1584  	return append(getServerFlags(), []cli.Flag{
  1585  		cli.StringFlag{
  1586  			Name:  "source-repos",
  1587  			Usage: "[Optional] List of local repositories in the form of \"repo1,repo2,...\" from which build artifacts should be deployed.` `",
  1588  		},
  1589  		cli.StringFlag{
  1590  			Name:  "passphrase",
  1591  			Usage: "[Optional] If specified, Artifactory will GPG sign the build deployed to Bintray and apply the specified passphrase.` `",
  1592  		},
  1593  		cli.BoolTFlag{
  1594  			Name:  "publish",
  1595  			Usage: "[Default: true] If true, builds are published when deployed to Bintray.` `",
  1596  		},
  1597  		cli.BoolFlag{
  1598  			Name:  "override",
  1599  			Usage: "[Default: false] If true, Artifactory overwrites builds already existing in the target path in Bintray.` `",
  1600  		},
  1601  		cli.BoolFlag{
  1602  			Name:  "async",
  1603  			Usage: "[Default: false] If true, the build will be distributed asynchronously.` `",
  1604  		},
  1605  		cli.BoolFlag{
  1606  			Name:  "dry-run",
  1607  			Usage: "[Default: false] If true, distribution is only simulated. No files are actually moved.` `",
  1608  		},
  1609  		getInsecureTlsFlag(),
  1610  	}...)
  1611  }
  1612  
  1613  func getGitLfsCleanFlags() []cli.Flag {
  1614  	return append(getServerFlags(), []cli.Flag{
  1615  		cli.StringFlag{
  1616  			Name:  "refs",
  1617  			Usage: "[Default: refs/remotes/*] List of Git references in the form of \"ref1,ref2,...\" which should be preserved.` `",
  1618  		},
  1619  		cli.StringFlag{
  1620  			Name:  "repo",
  1621  			Usage: "[Optional] Local Git LFS repository which should be cleaned. If omitted, this is detected from the Git repository.` `",
  1622  		},
  1623  		cli.BoolFlag{
  1624  			Name:  "dry-run",
  1625  			Usage: "[Default: false] If true, cleanup is only simulated. No files are actually deleted.` `",
  1626  		},
  1627  		getQuiteFlag("[Default: $CI] Set to true to skip the delete confirmation message.` `"),
  1628  		getInsecureTlsFlag(),
  1629  	}...)
  1630  }
  1631  
  1632  func getConfigFlags() []cli.Flag {
  1633  	flags := []cli.Flag{
  1634  		cli.BoolTFlag{
  1635  			Name:  "interactive",
  1636  			Usage: "[Default: true, unless $CI is true] Set to false if you do not want the config command to be interactive. If true, the --url option becomes optional.` `",
  1637  		},
  1638  		cli.BoolTFlag{
  1639  			Name:  "enc-password",
  1640  			Usage: "[Default: true] If set to false then the configured password will not be encrypted using Artifactory's encryption API.` `",
  1641  		},
  1642  	}
  1643  	flags = append(flags, getBaseFlags()...)
  1644  	flags = append(flags, getClientCertsFlags()...)
  1645  	return append(flags,
  1646  		getSshKeyPathFlag()...)
  1647  }
  1648  
  1649  func getSshKeyPathFlag() []cli.Flag {
  1650  	return []cli.Flag{
  1651  		cli.StringFlag{
  1652  			Name:  "ssh-key-path",
  1653  			Usage: "[Optional] SSH key file path.` `",
  1654  		},
  1655  	}
  1656  }
  1657  
  1658  func getBuildDiscardFlags() []cli.Flag {
  1659  	return append(getServerFlags(), []cli.Flag{
  1660  		cli.StringFlag{
  1661  			Name:  "max-days",
  1662  			Usage: "[Optional] The maximum number of days to keep builds in Artifactory.` `",
  1663  		},
  1664  		cli.StringFlag{
  1665  			Name:  "max-builds",
  1666  			Usage: "[Optional] The maximum number of builds to store in Artifactory.` `",
  1667  		},
  1668  		cli.StringFlag{
  1669  			Name:  "exclude-builds",
  1670  			Usage: "[Optional] List of build numbers in the form of \"value1,value2,...\", that should not be removed from Artifactory.` `",
  1671  		},
  1672  		cli.BoolFlag{
  1673  			Name:  "delete-artifacts",
  1674  			Usage: "[Default: false] If set to true, automatically removes build artifacts stored in Artifactory.` `",
  1675  		},
  1676  		cli.BoolFlag{
  1677  			Name:  "async",
  1678  			Usage: "[Default: false] If set to true, build discard will run asynchronously and will not wait for response.` `",
  1679  		},
  1680  		getInsecureTlsFlag(),
  1681  	}...)
  1682  }
  1683  
  1684  func getReleaseBundleCreateUpdateFlags() []cli.Flag {
  1685  	releaseBundleFlags := append(getServerFlags(), getSpecFlags()...)
  1686  	return append(releaseBundleFlags, []cli.Flag{
  1687  		cli.BoolFlag{
  1688  			Name:  "dry-run",
  1689  			Usage: "[Default: false] Set to true to disable communication with JFrog Distribution.` `",
  1690  		},
  1691  		cli.BoolFlag{
  1692  			Name:  "sign",
  1693  			Usage: "[Default: false] If set to true, automatically signs the release bundle version.` `",
  1694  		},
  1695  		cli.StringFlag{
  1696  			Name:  "desc",
  1697  			Usage: "[Optional] Description of the release bundle.` `",
  1698  		},
  1699  		cli.StringFlag{
  1700  			Name:  "release-notes-path",
  1701  			Usage: "[Optional] Path to a file describes the release notes for the release bundle version.` `",
  1702  		},
  1703  		cli.StringFlag{
  1704  			Name:  "release-notes-syntax",
  1705  			Usage: "[Default: plain_text] The syntax for the release notes. Can be one of 'markdown', 'asciidoc', or 'plain_text` `",
  1706  		},
  1707  		cli.StringFlag{
  1708  			Name:  "exclusions",
  1709  			Usage: "[Optional] Semicolon-separated list of exclusions. Exclusions can include the * and the ? wildcards.` `",
  1710  		},
  1711  		getDistributionPassphraseFlag(),
  1712  		getStoringRepositoryFlag(),
  1713  	}...)
  1714  }
  1715  
  1716  func getReleaseBundleSignFlags() []cli.Flag {
  1717  	return append(getServerFlags(), getDistributionPassphraseFlag(), getStoringRepositoryFlag())
  1718  }
  1719  
  1720  func getDistributionPassphraseFlag() cli.Flag {
  1721  	return cli.StringFlag{
  1722  		Name:  "passphrase",
  1723  		Usage: "[Optional] The passphrase for the signing key. ` `",
  1724  	}
  1725  }
  1726  
  1727  func getStoringRepositoryFlag() cli.Flag {
  1728  	return cli.StringFlag{
  1729  		Name:  "repo",
  1730  		Usage: "[Optional] A repository name at source Artifactory to store release bundle artifacts in. If not provided, Artifactory will use the default one.` `",
  1731  	}
  1732  }
  1733  
  1734  func getReleaseBundleDistributeFlags() []cli.Flag {
  1735  	return append(getServerFlags(), []cli.Flag{
  1736  		cli.BoolFlag{
  1737  			Name:  "dry-run",
  1738  			Usage: "[Default: false] Set to true to disable communication with Artifactory.` `",
  1739  		},
  1740  		cli.StringFlag{
  1741  			Name:  "dist-rules",
  1742  			Usage: "Path to distribution rules.` `",
  1743  		},
  1744  		cli.StringFlag{
  1745  			Name:  "site",
  1746  			Usage: "[Default: '*'] Wildcard filter for site name. ` `",
  1747  		},
  1748  		cli.StringFlag{
  1749  			Name:  "city",
  1750  			Usage: "[Default: '*'] Wildcard filter for site city name. ` `",
  1751  		},
  1752  		cli.StringFlag{
  1753  			Name:  "country-codes",
  1754  			Usage: "[Default: '*'] Semicolon-separated list of wildcard filters for site country codes. ` `",
  1755  		},
  1756  	}...)
  1757  }
  1758  
  1759  func getReleaseBundleDeleteFlags() []cli.Flag {
  1760  	return append(getReleaseBundleDistributeFlags(), []cli.Flag{
  1761  		cli.BoolFlag{
  1762  			Name:  "delete-from-dist",
  1763  			Usage: "[Default: false] Set to true to delete release bundle version in JFrog Distribution itself after deletion is complete in the specified Edge node/s.` `",
  1764  		},
  1765  		getQuiteFlag("[Default: false] Set to true to skip the delete confirmation message.` `"),
  1766  	}...)
  1767  }
  1768  
  1769  func getBuildScanFlags() []cli.Flag {
  1770  	return append(getServerFlags(), []cli.Flag{
  1771  		cli.BoolTFlag{
  1772  			Name:  "fail",
  1773  			Usage: "[Default: true] Set to false if you do not wish the command to return exit code 3, even if the 'Fail Build' rule is matched by Xray.` `",
  1774  		},
  1775  		getInsecureTlsFlag(),
  1776  	}...)
  1777  }
  1778  
  1779  func getBuildAddGitFlags() []cli.Flag {
  1780  	return []cli.Flag{
  1781  		cli.StringFlag{
  1782  			Name:  "config",
  1783  			Usage: "[Optional] Path to a configuration file.` `",
  1784  		},
  1785  	}
  1786  }
  1787  
  1788  func getCurlFlags() []cli.Flag {
  1789  	return []cli.Flag{getServerIdFlag()}
  1790  }
  1791  
  1792  func getPipInstallFlags() []cli.Flag {
  1793  	return getBuildAndModuleFlags()
  1794  }
  1795  
  1796  func createArtifactoryDetailsByFlags(c *cli.Context, distribution bool) (*config.ArtifactoryDetails, error) {
  1797  	artDetails, err := createArtifactoryDetails(c, true)
  1798  	if err != nil {
  1799  		return nil, err
  1800  	}
  1801  	if distribution {
  1802  		if artDetails.DistributionUrl == "" {
  1803  			return nil, errors.New("the --dist-url option is mandatory")
  1804  		}
  1805  	} else {
  1806  		if artDetails.Url == "" {
  1807  			return nil, errors.New("the --url option is mandatory")
  1808  		}
  1809  	}
  1810  
  1811  	return artDetails, nil
  1812  }
  1813  
  1814  func getSplitCount(c *cli.Context) (splitCount int, err error) {
  1815  	splitCount = cliutils.DownloadSplitCount
  1816  	err = nil
  1817  	if c.String("split-count") != "" {
  1818  		splitCount, err = strconv.Atoi(c.String("split-count"))
  1819  		if err != nil {
  1820  			err = errors.New("The '--split-count' option should have a numeric value. " + cliutils.GetDocumentationMessage())
  1821  		}
  1822  		if splitCount > cliutils.DownloadMaxSplitCount {
  1823  			err = errors.New("The '--split-count' option value is limited to a maximum of " + strconv.Itoa(cliutils.DownloadMaxSplitCount) + ".")
  1824  		}
  1825  		if splitCount < 0 {
  1826  			err = errors.New("the '--split-count' option cannot have a negative value")
  1827  		}
  1828  	}
  1829  	return
  1830  }
  1831  
  1832  func getThreadsCount(c *cli.Context) (threads int, err error) {
  1833  	threads = 3
  1834  	err = nil
  1835  	if c.String("threads") != "" {
  1836  		threads, err = strconv.Atoi(c.String("threads"))
  1837  		if err != nil || threads < 1 {
  1838  			err = errors.New("the '--threads' option should have a numeric positive value")
  1839  			return 0, err
  1840  		}
  1841  	}
  1842  	return threads, nil
  1843  }
  1844  
  1845  func getMinSplit(c *cli.Context) (minSplitSize int64, err error) {
  1846  	minSplitSize = cliutils.DownloadMinSplitKb
  1847  	err = nil
  1848  	if c.String("min-split") != "" {
  1849  		minSplitSize, err = strconv.ParseInt(c.String("min-split"), 10, 64)
  1850  		if err != nil {
  1851  			err = errors.New("The '--min-split' option should have a numeric value. " + cliutils.GetDocumentationMessage())
  1852  			return 0, err
  1853  		}
  1854  	}
  1855  
  1856  	return minSplitSize, nil
  1857  }
  1858  
  1859  func getRetries(c *cli.Context) (retries int, err error) {
  1860  	retries = cliutils.Retries
  1861  	err = nil
  1862  	if c.String("retries") != "" {
  1863  		retries, err = strconv.Atoi(c.String("retries"))
  1864  		if err != nil {
  1865  			err = errors.New("The '--retries' option should have a numeric value. " + cliutils.GetDocumentationMessage())
  1866  			return 0, err
  1867  		}
  1868  	}
  1869  
  1870  	return retries, nil
  1871  }
  1872  
  1873  func validateServerId(serverId string) error {
  1874  	reservedIds := []string{"delete", "use", "show", "clear"}
  1875  	for _, reservedId := range reservedIds {
  1876  		if serverId == reservedId {
  1877  			return errors.New(fmt.Sprintf("Server can't have one of the following ID's: %s\n %s", strings.Join(reservedIds, ", "), cliutils.GetDocumentationMessage()))
  1878  		}
  1879  	}
  1880  	return nil
  1881  }
  1882  
  1883  func validateCommand(args []string, notAllowedFlags []cli.Flag) error {
  1884  	for _, arg := range args {
  1885  		for _, flag := range notAllowedFlags {
  1886  			// Cli flags are in the format of --key, therefore, the -- need to be added to the name
  1887  			if strings.Contains(arg, "--"+flag.GetName()) {
  1888  				return errorutils.CheckError(fmt.Errorf("flag --%s can't be used with config file", flag.GetName()))
  1889  			}
  1890  		}
  1891  	}
  1892  	return nil
  1893  }
  1894  
  1895  func useCmd(c *cli.Context) error {
  1896  	var serverId string
  1897  	var err error = nil
  1898  	if len(c.Args()) == 1 {
  1899  		serverId = c.Args()[0]
  1900  		err = validateServerId(serverId)
  1901  		if err != nil {
  1902  			return err
  1903  		}
  1904  		err = commands.Use(serverId)
  1905  		if err != nil {
  1906  			return err
  1907  		}
  1908  	} else {
  1909  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  1910  	}
  1911  
  1912  	return err
  1913  }
  1914  
  1915  func configCmd(c *cli.Context) error {
  1916  	if len(c.Args()) > 2 {
  1917  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  1918  	}
  1919  
  1920  	var serverId string
  1921  	configCommandConfiguration, err := createConfigCommandConfiguration(c)
  1922  	if err != nil {
  1923  		return err
  1924  	}
  1925  	if len(c.Args()) == 2 {
  1926  		if c.Args()[0] == "import" {
  1927  			return commands.Import(c.Args()[1])
  1928  		}
  1929  		serverId = c.Args()[1]
  1930  		if err := validateServerId(serverId); err != nil {
  1931  			return err
  1932  		}
  1933  		artDetails, err := config.GetArtifactorySpecificConfig(serverId)
  1934  		if err != nil {
  1935  			return err
  1936  		}
  1937  		if artDetails.IsEmpty() {
  1938  			log.Info("\"" + serverId + "\" configuration could not be found.")
  1939  			return nil
  1940  		}
  1941  		if c.Args()[0] == "delete" {
  1942  			if configCommandConfiguration.Interactive {
  1943  				if !cliutils.InteractiveConfirm("Are you sure you want to delete \"" + serverId + "\" configuration?") {
  1944  					return nil
  1945  				}
  1946  			}
  1947  			return commands.DeleteConfig(serverId)
  1948  		}
  1949  		if c.Args()[0] == "export" {
  1950  			return commands.Export(serverId)
  1951  		}
  1952  	}
  1953  	if len(c.Args()) > 0 {
  1954  		if c.Args()[0] == "show" {
  1955  			return commands.ShowConfig(serverId)
  1956  		}
  1957  		if c.Args()[0] == "clear" {
  1958  			commands.ClearConfig(configCommandConfiguration.Interactive)
  1959  			return nil
  1960  		}
  1961  		serverId = c.Args()[0]
  1962  		err = validateServerId(serverId)
  1963  		if err != nil {
  1964  			return err
  1965  		}
  1966  	}
  1967  	err = validateConfigFlags(configCommandConfiguration)
  1968  	if err != nil {
  1969  		return err
  1970  	}
  1971  	configCmd := commands.NewConfigCommand().SetDetails(configCommandConfiguration.ArtDetails).SetInteractive(configCommandConfiguration.Interactive).SetServerId(serverId).SetEncPassword(configCommandConfiguration.EncPassword)
  1972  	return configCmd.Config()
  1973  }
  1974  
  1975  func mvnLegacyCmd(c *cli.Context) error {
  1976  	log.Warn(deprecatedWarning(utils.Maven, os.Args[2], "mvnc"))
  1977  	if c.NArg() != 2 {
  1978  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  1979  	}
  1980  	configuration, err := createBuildConfigurationWithModule(c)
  1981  	if err != nil {
  1982  		return err
  1983  	}
  1984  	threads, err := getThreadsCount(c)
  1985  	if err != nil {
  1986  		return err
  1987  	}
  1988  	mvnCmd := mvn.NewMvnCommand().SetConfiguration(configuration).SetConfigPath(c.Args().Get(1)).SetGoals(c.Args().Get(0)).SetThreads(threads)
  1989  
  1990  	return commands.Exec(mvnCmd)
  1991  }
  1992  
  1993  func mvnCmd(c *cli.Context) error {
  1994  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  1995  		return err
  1996  	}
  1997  
  1998  	configFilePath, exists, err := utils.GetProjectConfFilePath(utils.Maven)
  1999  	if err != nil {
  2000  		return err
  2001  	}
  2002  	if exists {
  2003  		// Found a config file. Continue as native command.
  2004  		if c.NArg() < 1 {
  2005  			return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2006  		}
  2007  		args, err := shellwords.Parse(strings.Join(extractCommand(c), " "))
  2008  		if err != nil {
  2009  			return errorutils.CheckError(err)
  2010  		}
  2011  		// Validates the mvn command. If a config file is found, the only flags that can be used are build-name, build-number and module.
  2012  		// Otherwise, throw an error.
  2013  		if err := validateCommand(args, getBasicBuildToolsFlags()); err != nil {
  2014  			return err
  2015  		}
  2016  		filteredMavenArgs, insecureTls, err := utils.ExtractInsecureTlsFromArgs(args)
  2017  		if err != nil {
  2018  			return err
  2019  		}
  2020  		filteredMavenArgs, buildConfiguration, err := utils.ExtractBuildDetailsFromArgs(filteredMavenArgs)
  2021  		if err != nil {
  2022  			return err
  2023  		}
  2024  		filteredMavenArgs, threads, err := extractThreadsFlag(filteredMavenArgs)
  2025  		if err != nil {
  2026  			return err
  2027  		}
  2028  		mvnCmd := mvn.NewMvnCommand().SetConfiguration(buildConfiguration).SetConfigPath(configFilePath).SetGoals(strings.Join(filteredMavenArgs, " ")).SetThreads(threads).SetInsecureTls(insecureTls)
  2029  		return commands.Exec(mvnCmd)
  2030  	}
  2031  	return mvnLegacyCmd(c)
  2032  }
  2033  
  2034  func gradleCmd(c *cli.Context) error {
  2035  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  2036  		return err
  2037  	}
  2038  
  2039  	configFilePath, exists, err := utils.GetProjectConfFilePath(utils.Gradle)
  2040  	if err != nil {
  2041  		return err
  2042  	}
  2043  	if exists {
  2044  		// Found a config file. Continue as native command.
  2045  		if c.NArg() < 1 {
  2046  			return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2047  		}
  2048  		args, err := shellwords.Parse(strings.Join(extractCommand(c), " "))
  2049  		if err != nil {
  2050  			return errorutils.CheckError(err)
  2051  		}
  2052  		// Validates the gradle command. If a config file is found, the only flags that can be used are build-name, build-number and module.
  2053  		// Otherwise, throw an error.
  2054  		if err := validateCommand(args, getBasicBuildToolsFlags()); err != nil {
  2055  			return err
  2056  		}
  2057  		filteredGradleArgs, buildConfiguration, err := utils.ExtractBuildDetailsFromArgs(args)
  2058  		if err != nil {
  2059  			return err
  2060  		}
  2061  		filteredGradleArgs, threads, err := extractThreadsFlag(filteredGradleArgs)
  2062  		if err != nil {
  2063  			return err
  2064  		}
  2065  		gradleCmd := gradle.NewGradleCommand().SetConfiguration(buildConfiguration).SetTasks(strings.Join(filteredGradleArgs, " ")).SetConfigPath(configFilePath).SetThreads(threads)
  2066  		return commands.Exec(gradleCmd)
  2067  	}
  2068  	return gradleLegacyCmd(c)
  2069  }
  2070  
  2071  func gradleLegacyCmd(c *cli.Context) error {
  2072  	log.Warn(deprecatedWarning(utils.Gradle, os.Args[2], "gradlec"))
  2073  
  2074  	if c.NArg() != 2 {
  2075  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2076  	}
  2077  	configuration, err := createBuildConfigurationWithModule(c)
  2078  	if err != nil {
  2079  		return err
  2080  	}
  2081  	threads, err := getThreadsCount(c)
  2082  	if err != nil {
  2083  		return err
  2084  	}
  2085  	gradleCmd := gradle.NewGradleCommand()
  2086  	gradleCmd.SetConfiguration(configuration).SetTasks(c.Args().Get(0)).SetConfigPath(c.Args().Get(1)).SetThreads(threads)
  2087  
  2088  	return commands.Exec(gradleCmd)
  2089  }
  2090  
  2091  func dockerPushCmd(c *cli.Context) error {
  2092  	if c.NArg() != 2 {
  2093  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2094  	}
  2095  	artDetails, err := createArtifactoryDetailsByFlags(c, false)
  2096  	if err != nil {
  2097  		return err
  2098  	}
  2099  	imageTag := c.Args().Get(0)
  2100  	targetRepo := c.Args().Get(1)
  2101  	skipLogin := c.Bool("skip-login")
  2102  
  2103  	buildConfiguration, err := createBuildConfigurationWithModule(c)
  2104  	if err != nil {
  2105  		return err
  2106  	}
  2107  	dockerPushCommand := docker.NewDockerPushCommand()
  2108  	threads, err := getThreadsCount(c)
  2109  	if err != nil {
  2110  		return err
  2111  	}
  2112  	dockerPushCommand.SetThreads(threads).SetBuildConfiguration(buildConfiguration).SetRepo(targetRepo).SetSkipLogin(skipLogin).SetRtDetails(artDetails).SetImageTag(imageTag)
  2113  
  2114  	return commands.Exec(dockerPushCommand)
  2115  }
  2116  
  2117  func dockerPullCmd(c *cli.Context) error {
  2118  	if c.NArg() != 2 {
  2119  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2120  	}
  2121  	artDetails, err := createArtifactoryDetailsByFlags(c, false)
  2122  	if err != nil {
  2123  		return err
  2124  	}
  2125  	imageTag := c.Args().Get(0)
  2126  	sourceRepo := c.Args().Get(1)
  2127  	skipLogin := c.Bool("skip-login")
  2128  	buildConfiguration, err := createBuildConfigurationWithModule(c)
  2129  	if err != nil {
  2130  		return err
  2131  	}
  2132  	dockerPullCommand := docker.NewDockerPullCommand()
  2133  	dockerPullCommand.SetImageTag(imageTag).SetRepo(sourceRepo).SetSkipLogin(skipLogin).SetRtDetails(artDetails).SetBuildConfiguration(buildConfiguration)
  2134  
  2135  	return commands.Exec(dockerPullCommand)
  2136  }
  2137  
  2138  func nugetCmd(c *cli.Context) error {
  2139  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  2140  		return err
  2141  	}
  2142  
  2143  	configFilePath, exists, err := utils.GetProjectConfFilePath(utils.Nuget)
  2144  	if err != nil {
  2145  		return err
  2146  	}
  2147  
  2148  	if exists {
  2149  		if c.NArg() < 1 {
  2150  			return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2151  		}
  2152  		// Found a config file.
  2153  		args, err := shellwords.Parse(strings.Join(extractCommand(c), " "))
  2154  		if err != nil {
  2155  			return errorutils.CheckError(err)
  2156  		}
  2157  		// Validates the nuget command. If a config file is found, the only flags that can be used are build-name, build-number and module.
  2158  		// Otherwise, throw an error.
  2159  		if err := validateCommand(args, getNugetCommonFlags()); err != nil {
  2160  			return err
  2161  		}
  2162  		nugetCmd := nuget.NewNugetCommand()
  2163  		nugetCmd.SetConfigFilePath(configFilePath).SetArgs(strings.Join(args, " "))
  2164  		return commands.Exec(nugetCmd)
  2165  	}
  2166  	// If config file not found, use nuget legacy command
  2167  	return nugetLegacyCmd(c)
  2168  }
  2169  
  2170  func nugetLegacyCmd(c *cli.Context) error {
  2171  	log.Warn(deprecatedWarning(utils.Nuget, os.Args[2], "nugetc"))
  2172  	if c.NArg() != 2 {
  2173  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2174  	}
  2175  	nugetCmd := nuget.NewLegacyNugetCommand()
  2176  	buildConfiguration, err := createBuildConfigurationWithModule(c)
  2177  	if err != nil {
  2178  		return err
  2179  	}
  2180  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2181  	if err != nil {
  2182  		return err
  2183  	}
  2184  	nugetCmd.SetArgs(c.Args().Get(0)).SetFlags(c.String("nuget-args")).
  2185  		SetRepoName(c.Args().Get(1)).
  2186  		SetBuildConfiguration(buildConfiguration).
  2187  		SetSolutionPath(c.String("solution-root")).
  2188  		SetRtDetails(rtDetails)
  2189  
  2190  	return commands.Exec(nugetCmd)
  2191  }
  2192  
  2193  func nugetDepsTreeCmd(c *cli.Context) error {
  2194  	if c.NArg() != 0 {
  2195  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2196  	}
  2197  
  2198  	return nuget.DependencyTreeCmd()
  2199  }
  2200  
  2201  func npmLegacyInstallCmd(c *cli.Context) error {
  2202  	log.Warn(deprecatedWarning(utils.Npm, os.Args[2], "npmc"))
  2203  	if c.NArg() != 1 {
  2204  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2205  	}
  2206  	buildConfiguration, err := createBuildConfigurationWithModule(c)
  2207  	if err != nil {
  2208  		return err
  2209  	}
  2210  	npmCmd := npm.NewNpmLegacyInstallCommand()
  2211  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2212  	if err != nil {
  2213  		return err
  2214  	}
  2215  	threads, err := getThreadsCount(c)
  2216  	if err != nil {
  2217  		return err
  2218  	}
  2219  	npmInstallArgs, err := shellwords.Parse(c.String("npm-args"))
  2220  	if err != nil {
  2221  		return err
  2222  	}
  2223  	npmCmd.SetThreads(threads).SetBuildConfiguration(buildConfiguration).SetRepo(c.Args().Get(0)).SetNpmArgs(npmInstallArgs).SetRtDetails(rtDetails)
  2224  
  2225  	return commands.Exec(npmCmd)
  2226  }
  2227  
  2228  func npmInstallCmd(c *cli.Context, npmCmd *npm.NpmInstallCommand, npmLegacyCommand func(*cli.Context) error) error {
  2229  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  2230  		return err
  2231  	}
  2232  
  2233  	configFilePath, exists, err := utils.GetProjectConfFilePath(utils.Npm)
  2234  	if err != nil {
  2235  		return err
  2236  	}
  2237  
  2238  	if exists {
  2239  		// Found a config file. Continue as native command.
  2240  		args, err := shellwords.Parse(strings.Join(extractCommand(c), " "))
  2241  		if err != nil {
  2242  			return errorutils.CheckError(err)
  2243  		}
  2244  		// Validates the npm command. If a config file is found, the only flags that can be used are threads, build-name, build-number and module.
  2245  		// Otherwise, throw an error.
  2246  		if err := validateCommand(args, getNpmLegacyFlags()); err != nil {
  2247  			return err
  2248  		}
  2249  		npmCmd.SetConfigFilePath(configFilePath).SetArgs(args)
  2250  		return commands.Exec(npmCmd)
  2251  	}
  2252  	// If config file not found, use Npm legacy command
  2253  	return npmLegacyCommand(c)
  2254  }
  2255  
  2256  func npmLegacyCiCmd(c *cli.Context) error {
  2257  	log.Warn(deprecatedWarning(utils.Npm, os.Args[2], "npmc"))
  2258  	if c.NArg() != 1 {
  2259  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2260  	}
  2261  	buildConfiguration, err := createBuildConfigurationWithModule(c)
  2262  	if err != nil {
  2263  		return err
  2264  	}
  2265  	npmCmd := npm.NewNpmLegacyCiCommand()
  2266  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2267  	if err != nil {
  2268  		return err
  2269  	}
  2270  	threads, err := getThreadsCount(c)
  2271  	if err != nil {
  2272  		return err
  2273  	}
  2274  	npmCmd.SetThreads(threads).SetBuildConfiguration(buildConfiguration).SetRepo(c.Args().Get(0)).SetRtDetails(rtDetails)
  2275  	return commands.Exec(npmCmd)
  2276  }
  2277  
  2278  func npmPublishCmd(c *cli.Context) error {
  2279  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  2280  		return err
  2281  	}
  2282  
  2283  	configFilePath, exists, err := utils.GetProjectConfFilePath(utils.Npm)
  2284  	if err != nil {
  2285  		return err
  2286  	}
  2287  	if exists {
  2288  		// Found a config file. Continue as native command.
  2289  		args, err := shellwords.Parse(strings.Join(extractCommand(c), " "))
  2290  		if err != nil {
  2291  			return errorutils.CheckError(err)
  2292  		}
  2293  		// Validates the npm command. If a config file is found, the only flags that can be used are build-name, build-number and module.
  2294  		// Otherwise, throw an error.
  2295  		if err := validateCommand(args, getNpmLegacyFlags()); err != nil {
  2296  			return err
  2297  		}
  2298  		npmCmd := npm.NewNpmPublishCommand()
  2299  		npmCmd.SetConfigFilePath(configFilePath).SetArgs(args)
  2300  		return commands.Exec(npmCmd)
  2301  	}
  2302  	// If config file not found, use Npm legacy command
  2303  	return npmLegacyPublishCmd(c)
  2304  }
  2305  
  2306  func npmLegacyPublishCmd(c *cli.Context) error {
  2307  	log.Warn(deprecatedWarning(utils.Npm, os.Args[2], "npmc"))
  2308  	if c.NArg() != 1 {
  2309  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2310  	}
  2311  	buildConfiguration, err := createBuildConfigurationWithModule(c)
  2312  	if err != nil {
  2313  		return err
  2314  	}
  2315  	npmPublicCmd := npm.NewNpmPublishCommand()
  2316  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2317  	if err != nil {
  2318  		return err
  2319  	}
  2320  	npmPublicArgs, err := shellwords.Parse(c.String("npm-args"))
  2321  	if err != nil {
  2322  		return err
  2323  	}
  2324  	npmPublicCmd.SetBuildConfiguration(buildConfiguration).SetRepo(c.Args().Get(0)).SetNpmArgs(npmPublicArgs).SetRtDetails(rtDetails)
  2325  
  2326  	return commands.Exec(npmPublicCmd)
  2327  }
  2328  
  2329  func goPublishCmd(c *cli.Context) error {
  2330  	// When "self" set to true (default), there must be two arguments passed: target repo and the version
  2331  	if c.BoolT("self") && c.NArg() != 2 {
  2332  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2333  	}
  2334  	// When "self" set to false, the target repository is mandatory but the version is not.
  2335  	// The version is only needed for publishing the project
  2336  	// But for automation purposes of users, keeping the possibility to pass the version without failing
  2337  	if !c.BoolT("self") && c.NArg() > 2 {
  2338  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2339  	}
  2340  
  2341  	buildConfiguration, err := createBuildConfigurationWithModule(c)
  2342  	if err != nil {
  2343  		return err
  2344  	}
  2345  	targetRepo := c.Args().Get(0)
  2346  	version := c.Args().Get(1)
  2347  	details, err := createArtifactoryDetailsByFlags(c, false)
  2348  	if err != nil {
  2349  		return err
  2350  	}
  2351  	goPublishCmd := golang.NewGoPublishCommand()
  2352  	goPublishCmd.SetBuildConfiguration(buildConfiguration).SetVersion(version).SetDependencies(c.String("deps")).SetPublishPackage(c.BoolT("self")).SetTargetRepo(targetRepo).SetRtDetails(details)
  2353  	err = commands.Exec(goPublishCmd)
  2354  	result := goPublishCmd.Result()
  2355  
  2356  	return cliutils.PrintSummaryReport(result.SuccessCount(), result.FailCount(), err)
  2357  }
  2358  
  2359  // This function checks whether the command received --help as a single option.
  2360  // If it did, the command's help is shown and true is returned.
  2361  func showCmdHelpIfNeeded(c *cli.Context) (bool, error) {
  2362  	if len(c.Args()) != 1 {
  2363  		return false, nil
  2364  	}
  2365  	if c.Args()[0] == "--help" {
  2366  		err := cli.ShowCommandHelp(c, c.Command.Name)
  2367  		return true, err
  2368  	}
  2369  	return false, nil
  2370  }
  2371  
  2372  func shouldSkipGoFlagParsing() bool {
  2373  	// This function is executed by code-gangsta, regardless of the CLI command being executed.
  2374  	// There's no need to run the code of this function, if the command is not "jfrog rt go*".
  2375  	if len(os.Args) < 3 || os.Args[2] != "go" {
  2376  		return false
  2377  	}
  2378  
  2379  	_, exists, err := utils.GetProjectConfFilePath(utils.Go)
  2380  	if err != nil {
  2381  		cliutils.ExitOnErr(err)
  2382  	}
  2383  	return exists
  2384  }
  2385  
  2386  func shouldSkipNpmFlagParsing() bool {
  2387  	// This function is executed by code-gangsta, regardless of the CLI command being executed.
  2388  	// There's no need to run the code of this function, if the command is not "jfrog rt npm*".
  2389  	if len(os.Args) < 3 || !npmUtils.IsNpmCommand(os.Args[2]) {
  2390  		return false
  2391  	}
  2392  
  2393  	_, exists, err := utils.GetProjectConfFilePath(utils.Npm)
  2394  	if err != nil {
  2395  		cliutils.ExitOnErr(err)
  2396  	}
  2397  	return exists
  2398  }
  2399  
  2400  func shouldSkipNugetFlagParsing() bool {
  2401  	// This function is executed by code-gangsta, regardless of the CLI command being executed.
  2402  	// There's no need to run the code of this function, if the command is not "jfrog rt nuget*".
  2403  	if len(os.Args) < 3 || os.Args[2] != "nuget" {
  2404  		return false
  2405  	}
  2406  
  2407  	_, exists, err := utils.GetProjectConfFilePath(utils.Nuget)
  2408  	if err != nil {
  2409  		cliutils.ExitOnErr(err)
  2410  	}
  2411  	return exists
  2412  }
  2413  
  2414  func shouldSkipMavenFlagParsing() bool {
  2415  	// This function is executed by code-gangsta, regardless of the CLI command being executed.
  2416  	// There's no need to run the code of this function, if the command is not "jfrog rt mvn*".
  2417  	if len(os.Args) < 3 || os.Args[2] != "mvn" {
  2418  		return false
  2419  	}
  2420  	_, exists, err := utils.GetProjectConfFilePath(utils.Maven)
  2421  	if err != nil {
  2422  		cliutils.ExitOnErr(err)
  2423  	}
  2424  	return exists
  2425  }
  2426  
  2427  func shouldSkipGradleFlagParsing() bool {
  2428  	// This function is executed by code-gangsta, regardless of the CLI command being executed.
  2429  	// There's no need to run the code of this function, if the command is not "jfrog rt gradle*".
  2430  	if len(os.Args) < 3 || os.Args[2] != "gradle" {
  2431  		return false
  2432  	}
  2433  	_, exists, err := utils.GetProjectConfFilePath(utils.Gradle)
  2434  	if err != nil {
  2435  		cliutils.ExitOnErr(err)
  2436  	}
  2437  	return exists
  2438  }
  2439  
  2440  func goCmd(c *cli.Context) error {
  2441  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  2442  		return err
  2443  	}
  2444  
  2445  	configFilePath, exists, err := utils.GetProjectConfFilePath(utils.Go)
  2446  	if err != nil {
  2447  		return err
  2448  	}
  2449  
  2450  	if exists {
  2451  		log.Debug("Go config file was found in:", configFilePath)
  2452  		return goNativeCmd(c, configFilePath)
  2453  	}
  2454  	log.Debug("Go config file wasn't found.")
  2455  	// If config file not found, use Go legacy command
  2456  	return goLegacyCmd(c)
  2457  }
  2458  
  2459  func goLegacyCmd(c *cli.Context) error {
  2460  	log.Warn(deprecatedWarning(utils.Go, os.Args[2], "go-config"))
  2461  	// When the no-registry set to false (default), two arguments are mandatory: go command and the target repository
  2462  	if !c.Bool("no-registry") && c.NArg() != 2 {
  2463  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2464  	}
  2465  	// When the no-registry is set to true this means that the resolution will not be done via Artifactory.
  2466  	// For automation purposes of users, keeping the possibility to pass the repository although we are not using it.
  2467  	if c.Bool("no-registry") && c.NArg() > 2 {
  2468  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2469  	}
  2470  	goArg, err := shellwords.Parse(c.Args().Get(0))
  2471  	if err != nil {
  2472  		err = cliutils.PrintSummaryReport(0, 1, err)
  2473  	}
  2474  	targetRepo := c.Args().Get(1)
  2475  	details, err := createArtifactoryDetailsByFlags(c, false)
  2476  	if err != nil {
  2477  		return err
  2478  	}
  2479  	publishDeps := c.Bool("publish-deps")
  2480  	buildConfiguration, err := createBuildConfigurationWithModule(c)
  2481  	if err != nil {
  2482  		return err
  2483  	}
  2484  	resolverRepo := &utils.RepositoryConfig{}
  2485  	resolverRepo.SetTargetRepo(targetRepo).SetRtDetails(details)
  2486  	goCmd := golang.NewGoCommand().SetBuildConfiguration(buildConfiguration).
  2487  		SetGoArg(goArg).SetNoRegistry(c.Bool("no-registry")).
  2488  		SetPublishDeps(publishDeps).SetResolverParams(resolverRepo)
  2489  	if publishDeps {
  2490  		goCmd.SetDeployerParams(resolverRepo)
  2491  	}
  2492  	err = commands.Exec(goCmd)
  2493  	if err != nil {
  2494  		err = cliutils.PrintSummaryReport(0, 1, err)
  2495  	}
  2496  	return err
  2497  }
  2498  
  2499  func goNativeCmd(c *cli.Context, configFilePath string) error {
  2500  	// Found a config file. Continue as native command.
  2501  	if c.NArg() < 1 {
  2502  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2503  	}
  2504  	args := extractCommand(c)
  2505  	// Validates the go command. If a config file is found, the only flags that can be used are build-name, build-number and module.
  2506  	// Otherwise, throw an error.
  2507  	if err := validateCommand(args, getGoFlags()); err != nil {
  2508  		return err
  2509  	}
  2510  	goNative := golang.NewGoNativeCommand()
  2511  	goNative.SetConfigFilePath(configFilePath).SetGoArg(args)
  2512  	return commands.Exec(goNative)
  2513  }
  2514  
  2515  func goRecursivePublishCmd(c *cli.Context) error {
  2516  	if c.NArg() != 1 {
  2517  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2518  	}
  2519  
  2520  	targetRepo := c.Args().Get(0)
  2521  	if targetRepo == "" {
  2522  		return cliutils.PrintHelpAndReturnError("Missing target repo.", c)
  2523  	}
  2524  	details, err := createArtifactoryDetailsByFlags(c, false)
  2525  	if err != nil {
  2526  		return err
  2527  	}
  2528  	goRecursivePublishCmd := golang.NewGoRecursivePublishCommand()
  2529  	goRecursivePublishCmd.SetRtDetails(details).SetTargetRepo(targetRepo)
  2530  
  2531  	return commands.Exec(goRecursivePublishCmd)
  2532  }
  2533  
  2534  func createGradleConfigCmd(c *cli.Context) error {
  2535  	if c.NArg() != 0 {
  2536  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2537  	}
  2538  	return commandUtils.CreateBuildConfig(c, utils.Gradle)
  2539  }
  2540  
  2541  func createMvnConfigCmd(c *cli.Context) error {
  2542  	if c.NArg() != 0 {
  2543  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2544  	}
  2545  	return commandUtils.CreateBuildConfig(c, utils.Maven)
  2546  }
  2547  
  2548  func createGoConfigCmd(c *cli.Context) error {
  2549  	if c.NArg() != 0 {
  2550  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2551  	}
  2552  	return commandUtils.CreateBuildConfig(c, utils.Go)
  2553  }
  2554  
  2555  func createNpmConfigCmd(c *cli.Context) error {
  2556  	if c.NArg() != 0 {
  2557  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2558  	}
  2559  	return commandUtils.CreateBuildConfig(c, utils.Npm)
  2560  }
  2561  
  2562  func createNugetConfigCmd(c *cli.Context) error {
  2563  	if c.NArg() != 0 {
  2564  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2565  	}
  2566  	return commandUtils.CreateBuildConfig(c, utils.Nuget)
  2567  }
  2568  
  2569  func createPipConfigCmd(c *cli.Context) error {
  2570  	if c.NArg() != 0 {
  2571  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2572  	}
  2573  	return commandUtils.CreateBuildConfig(c, utils.Pip)
  2574  }
  2575  
  2576  func pingCmd(c *cli.Context) error {
  2577  	if c.NArg() > 0 {
  2578  		return cliutils.PrintHelpAndReturnError("No arguments should be sent.", c)
  2579  	}
  2580  	artDetails, err := createArtifactoryDetailsByFlags(c, false)
  2581  	if err != nil {
  2582  		return err
  2583  	}
  2584  	pingCmd := generic.NewPingCommand()
  2585  	pingCmd.SetRtDetails(artDetails)
  2586  	err = commands.Exec(pingCmd)
  2587  	resString := clientutils.IndentJson(pingCmd.Response())
  2588  	if err != nil {
  2589  		return errors.New(err.Error() + "\n" + resString)
  2590  	}
  2591  	log.Output(resString)
  2592  
  2593  	return err
  2594  }
  2595  
  2596  func downloadCmd(c *cli.Context) error {
  2597  	if c.NArg() > 0 && c.IsSet("spec") {
  2598  		return cliutils.PrintHelpAndReturnError("No arguments should be sent when the spec option is used.", c)
  2599  	}
  2600  	if !(c.NArg() == 1 || c.NArg() == 2 || (c.NArg() == 0 && (c.IsSet("spec") || c.IsSet("build") || c.IsSet("bundle")))) {
  2601  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2602  	}
  2603  
  2604  	var downloadSpec *spec.SpecFiles
  2605  	var err error
  2606  	if c.IsSet("spec") {
  2607  		downloadSpec, err = getSpec(c, true)
  2608  	} else {
  2609  		downloadSpec, err = createDefaultDownloadSpec(c)
  2610  	}
  2611  	if err != nil {
  2612  		return err
  2613  	}
  2614  	err = spec.ValidateSpec(downloadSpec.Files, false, true)
  2615  	if err != nil {
  2616  		return err
  2617  	}
  2618  	fixWinPathsForDownloadCmd(downloadSpec, c)
  2619  	configuration, err := createDownloadConfiguration(c)
  2620  	if err != nil {
  2621  		return err
  2622  	}
  2623  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2624  	if err != nil {
  2625  		return err
  2626  	}
  2627  	buildConfiguration, err := createBuildConfigurationWithModule(c)
  2628  	if err != nil {
  2629  		return err
  2630  	}
  2631  	downloadCommand := generic.NewDownloadCommand()
  2632  	downloadCommand.SetConfiguration(configuration).SetBuildConfiguration(buildConfiguration).SetSpec(downloadSpec).SetRtDetails(rtDetails).SetDryRun(c.Bool("dry-run")).SetSyncDeletesPath(c.String("sync-deletes")).SetQuiet(cliutils.GetQuietValue(c))
  2633  	err = commands.Exec(downloadCommand)
  2634  	defer logUtils.CloseLogFile(downloadCommand.LogFile())
  2635  	result := downloadCommand.Result()
  2636  	err = cliutils.PrintSummaryReport(result.SuccessCount(), result.FailCount(), err)
  2637  
  2638  	return cliutils.GetCliError(err, result.SuccessCount(), result.FailCount(), isFailNoOp(c))
  2639  }
  2640  
  2641  func uploadCmd(c *cli.Context) error {
  2642  	if c.NArg() > 0 && c.IsSet("spec") {
  2643  		return cliutils.PrintHelpAndReturnError("No arguments should be sent when the spec option is used.", c)
  2644  	}
  2645  	if !(c.NArg() == 2 || (c.NArg() == 0 && c.IsSet("spec"))) {
  2646  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2647  	}
  2648  
  2649  	var uploadSpec *spec.SpecFiles
  2650  	var err error
  2651  	if c.IsSet("spec") {
  2652  		uploadSpec, err = getFileSystemSpec(c)
  2653  	} else {
  2654  		uploadSpec, err = createDefaultUploadSpec(c)
  2655  	}
  2656  	if err != nil {
  2657  		return err
  2658  	}
  2659  	err = spec.ValidateSpec(uploadSpec.Files, true, false)
  2660  	if err != nil {
  2661  		return err
  2662  	}
  2663  	fixWinPathsForFileSystemSourcedCmds(uploadSpec, c)
  2664  	configuration, err := createUploadConfiguration(c)
  2665  	if err != nil {
  2666  		return err
  2667  	}
  2668  	buildConfiguration, err := createBuildConfigurationWithModule(c)
  2669  	if err != nil {
  2670  		return err
  2671  	}
  2672  	uploadCmd := generic.NewUploadCommand()
  2673  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2674  	if err != nil {
  2675  		return err
  2676  	}
  2677  	uploadCmd.SetUploadConfiguration(configuration).SetBuildConfiguration(buildConfiguration).SetSpec(uploadSpec).SetRtDetails(rtDetails).SetDryRun(c.Bool("dry-run")).SetSyncDeletesPath(c.String("sync-deletes")).SetQuiet(cliutils.GetQuietValue(c))
  2678  	err = commands.Exec(uploadCmd)
  2679  	defer logUtils.CloseLogFile(uploadCmd.LogFile())
  2680  	result := uploadCmd.Result()
  2681  	err = cliutils.PrintSummaryReport(result.SuccessCount(), result.FailCount(), err)
  2682  
  2683  	return cliutils.GetCliError(err, result.SuccessCount(), result.FailCount(), isFailNoOp(c))
  2684  }
  2685  
  2686  func moveCmd(c *cli.Context) error {
  2687  	if c.NArg() > 0 && c.IsSet("spec") {
  2688  		return cliutils.PrintHelpAndReturnError("No arguments should be sent when the spec option is used.", c)
  2689  	}
  2690  	if !(c.NArg() == 2 || (c.NArg() == 0 && (c.IsSet("spec") || c.IsSet("build")))) {
  2691  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2692  	}
  2693  
  2694  	var moveSpec *spec.SpecFiles
  2695  	var err error
  2696  	if c.IsSet("spec") {
  2697  		moveSpec, err = getSpec(c, false)
  2698  	} else {
  2699  		moveSpec, err = createDefaultCopyMoveSpec(c)
  2700  	}
  2701  	if err != nil {
  2702  		return err
  2703  	}
  2704  	err = spec.ValidateSpec(moveSpec.Files, true, true)
  2705  	if err != nil {
  2706  		return err
  2707  	}
  2708  	moveCmd := generic.NewMoveCommand()
  2709  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2710  	if err != nil {
  2711  		return err
  2712  	}
  2713  	moveCmd.SetDryRun(c.Bool("dry-run")).SetRtDetails(rtDetails).SetSpec(moveSpec)
  2714  	err = commands.Exec(moveCmd)
  2715  	result := moveCmd.Result()
  2716  	err = cliutils.PrintSummaryReport(result.SuccessCount(), result.FailCount(), err)
  2717  
  2718  	return cliutils.GetCliError(err, result.SuccessCount(), result.FailCount(), isFailNoOp(c))
  2719  }
  2720  
  2721  func copyCmd(c *cli.Context) error {
  2722  	if c.NArg() > 0 && c.IsSet("spec") {
  2723  		return cliutils.PrintHelpAndReturnError("No arguments should be sent when the spec option is used.", c)
  2724  	}
  2725  	if !(c.NArg() == 2 || (c.NArg() == 0 && (c.IsSet("spec") || c.IsSet("build")))) {
  2726  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2727  	}
  2728  
  2729  	var copySpec *spec.SpecFiles
  2730  	var err error
  2731  	if c.IsSet("spec") {
  2732  		copySpec, err = getSpec(c, false)
  2733  	} else {
  2734  		copySpec, err = createDefaultCopyMoveSpec(c)
  2735  	}
  2736  	if err != nil {
  2737  		return err
  2738  	}
  2739  	err = spec.ValidateSpec(copySpec.Files, true, true)
  2740  	if err != nil {
  2741  		return err
  2742  	}
  2743  
  2744  	copyCommand := generic.NewCopyCommand()
  2745  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2746  	if err != nil {
  2747  		return err
  2748  	}
  2749  	copyCommand.SetSpec(copySpec).SetDryRun(c.Bool("dry-run")).SetRtDetails(rtDetails)
  2750  	err = commands.Exec(copyCommand)
  2751  	result := copyCommand.Result()
  2752  	err = cliutils.PrintSummaryReport(result.SuccessCount(), result.FailCount(), err)
  2753  
  2754  	return cliutils.GetCliError(err, result.SuccessCount(), result.FailCount(), isFailNoOp(c))
  2755  }
  2756  
  2757  func deleteCmd(c *cli.Context) error {
  2758  	if c.NArg() > 0 && c.IsSet("spec") {
  2759  		return cliutils.PrintHelpAndReturnError("No arguments should be sent when the spec option is used.", c)
  2760  	}
  2761  	if !(c.NArg() == 1 || (c.NArg() == 0 && (c.IsSet("spec") || c.IsSet("build")))) {
  2762  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2763  	}
  2764  
  2765  	var deleteSpec *spec.SpecFiles
  2766  	var err error
  2767  	if c.IsSet("spec") {
  2768  		deleteSpec, err = getSpec(c, false)
  2769  	} else {
  2770  		deleteSpec, err = createDefaultDeleteSpec(c)
  2771  	}
  2772  	if err != nil {
  2773  		return err
  2774  	}
  2775  	err = spec.ValidateSpec(deleteSpec.Files, false, true)
  2776  	if err != nil {
  2777  		return err
  2778  	}
  2779  
  2780  	deleteCommand := generic.NewDeleteCommand()
  2781  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2782  	if err != nil {
  2783  		return err
  2784  	}
  2785  
  2786  	threads, err := getThreadsCount(c)
  2787  	if err != nil {
  2788  		return err
  2789  	}
  2790  	deleteCommand.SetThreads(threads).SetQuiet(cliutils.GetQuietValue(c)).SetDryRun(c.Bool("dry-run")).SetRtDetails(rtDetails).SetSpec(deleteSpec)
  2791  	err = commands.Exec(deleteCommand)
  2792  	result := deleteCommand.Result()
  2793  	err = cliutils.PrintSummaryReport(result.SuccessCount(), result.FailCount(), err)
  2794  
  2795  	return cliutils.GetCliError(err, result.SuccessCount(), result.FailCount(), isFailNoOp(c))
  2796  }
  2797  
  2798  func searchCmd(c *cli.Context) error {
  2799  	if c.NArg() > 0 && c.IsSet("spec") {
  2800  		return cliutils.PrintHelpAndReturnError("No arguments should be sent when the spec option is used.", c)
  2801  	}
  2802  	if !(c.NArg() == 1 || (c.NArg() == 0 && (c.IsSet("spec") || c.IsSet("build")))) {
  2803  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2804  	}
  2805  
  2806  	var searchSpec *spec.SpecFiles
  2807  	var err error
  2808  	if c.IsSet("spec") {
  2809  		searchSpec, err = getSpec(c, false)
  2810  	} else {
  2811  		searchSpec, err = createDefaultSearchSpec(c)
  2812  	}
  2813  	if err != nil {
  2814  		return err
  2815  	}
  2816  	err = spec.ValidateSpec(searchSpec.Files, false, true)
  2817  	if err != nil {
  2818  		return err
  2819  	}
  2820  	artDetails, err := createArtifactoryDetailsByFlags(c, false)
  2821  	if err != nil {
  2822  		return err
  2823  	}
  2824  	searchCmd := generic.NewSearchCommand()
  2825  	searchCmd.SetRtDetails(artDetails).SetSpec(searchSpec)
  2826  	err = commands.Exec(searchCmd)
  2827  	if err != nil {
  2828  		return err
  2829  	}
  2830  	result, err := json.Marshal(searchCmd.SearchResult())
  2831  	err = cliutils.GetCliError(err, len(searchCmd.SearchResult()), 0, isFailNoOp(c))
  2832  	if err != nil {
  2833  		return err
  2834  	}
  2835  	if c.Bool("count") {
  2836  		log.Output(len(searchCmd.SearchResult()))
  2837  	} else {
  2838  		log.Output(clientutils.IndentJson(result))
  2839  	}
  2840  
  2841  	return err
  2842  }
  2843  
  2844  func preparePropsCmd(c *cli.Context) (*generic.PropsCommand, error) {
  2845  	if c.NArg() > 1 && c.IsSet("spec") {
  2846  		return nil, cliutils.PrintHelpAndReturnError("Only the 'artifact properties' argument should be sent when the spec option is used.", c)
  2847  	}
  2848  	if !(c.NArg() == 2 || (c.NArg() == 1 && c.IsSet("spec"))) {
  2849  		return nil, cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2850  	}
  2851  
  2852  	var propsSpec *spec.SpecFiles
  2853  	var err error
  2854  	var props string
  2855  	if c.IsSet("spec") {
  2856  		props = c.Args()[0]
  2857  		propsSpec, err = getSpec(c, false)
  2858  	} else {
  2859  		props = c.Args()[1]
  2860  		propsSpec, err = createDefaultPropertiesSpec(c)
  2861  	}
  2862  	if err != nil {
  2863  		return nil, err
  2864  	}
  2865  	err = spec.ValidateSpec(propsSpec.Files, false, true)
  2866  	if err != nil {
  2867  		return nil, err
  2868  	}
  2869  
  2870  	command := generic.NewPropsCommand()
  2871  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2872  	if err != nil {
  2873  		return nil, err
  2874  	}
  2875  	threads, err := getThreadsCount(c)
  2876  	if err != nil {
  2877  		return nil, err
  2878  	}
  2879  
  2880  	cmd := command.SetProps(props)
  2881  	cmd.SetThreads(threads).SetSpec(propsSpec).SetDryRun(c.Bool("dry-run")).SetRtDetails(rtDetails)
  2882  	return cmd, nil
  2883  }
  2884  
  2885  func setPropsCmd(c *cli.Context) error {
  2886  	cmd, err := preparePropsCmd(c)
  2887  	if err != nil {
  2888  		return err
  2889  	}
  2890  
  2891  	propsCmd := generic.NewSetPropsCommand().SetPropsCommand(*cmd)
  2892  	err = commands.Exec(propsCmd)
  2893  	result := propsCmd.Result()
  2894  	err = cliutils.PrintSummaryReport(result.SuccessCount(), result.FailCount(), err)
  2895  
  2896  	return cliutils.GetCliError(err, result.SuccessCount(), result.FailCount(), isFailNoOp(c))
  2897  }
  2898  
  2899  func deletePropsCmd(c *cli.Context) error {
  2900  	cmd, err := preparePropsCmd(c)
  2901  	if err != nil {
  2902  		return err
  2903  	}
  2904  
  2905  	propsCmd := generic.NewDeletePropsCommand().DeletePropsCommand(*cmd)
  2906  	err = commands.Exec(propsCmd)
  2907  	result := propsCmd.Result()
  2908  	err = cliutils.PrintSummaryReport(result.SuccessCount(), result.FailCount(), err)
  2909  
  2910  	return cliutils.GetCliError(err, result.SuccessCount(), result.FailCount(), isFailNoOp(c))
  2911  }
  2912  
  2913  func buildPublishCmd(c *cli.Context) error {
  2914  	if c.NArg() > 2 {
  2915  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2916  	}
  2917  	buildConfiguration := createBuildConfiguration(c)
  2918  	if err := validateBuildConfiguration(c, buildConfiguration); err != nil {
  2919  		return err
  2920  	}
  2921  	buildInfoConfiguration := createBuildInfoConfiguration(c)
  2922  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  2923  	if err != nil {
  2924  		return err
  2925  	}
  2926  	buildPublishCmd := buildinfo.NewBuildPublishCommand().SetRtDetails(rtDetails).SetBuildConfiguration(buildConfiguration).SetConfig(buildInfoConfiguration)
  2927  
  2928  	return commands.Exec(buildPublishCmd)
  2929  }
  2930  
  2931  func buildAddDependenciesCmd(c *cli.Context) error {
  2932  	if c.NArg() > 2 && c.IsSet("spec") {
  2933  		return cliutils.PrintHelpAndReturnError("Only path or spec is allowed, not both.", c)
  2934  	}
  2935  	buildConfiguration := createBuildConfiguration(c)
  2936  	if err := validateBuildConfiguration(c, buildConfiguration); err != nil {
  2937  		return err
  2938  	}
  2939  	// Odd number of args - Use pattern arg
  2940  	// Even number of args - Use spec flag
  2941  	if c.NArg() > 3 || !(c.NArg()%2 == 1 || (c.NArg()%2 == 0 && c.IsSet("spec"))) {
  2942  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2943  	}
  2944  
  2945  	var dependenciesSpec *spec.SpecFiles
  2946  	var err error
  2947  	if c.IsSet("spec") {
  2948  		dependenciesSpec, err = getFileSystemSpec(c)
  2949  		if err != nil {
  2950  			return err
  2951  		}
  2952  	} else {
  2953  		dependenciesSpec = createDefaultBuildAddDependenciesSpec(c)
  2954  	}
  2955  	fixWinPathsForFileSystemSourcedCmds(dependenciesSpec, c)
  2956  	buildAddDependenciesCmd := buildinfo.NewBuildAddDependenciesCommand().SetDryRun(c.Bool("dry-run")).SetBuildConfiguration(buildConfiguration).SetDependenciesSpec(dependenciesSpec)
  2957  	err = commands.Exec(buildAddDependenciesCmd)
  2958  	result := buildAddDependenciesCmd.Result()
  2959  	err = cliutils.PrintSummaryReport(result.SuccessCount(), result.FailCount(), err)
  2960  	if err != nil {
  2961  		return err
  2962  	}
  2963  
  2964  	return cliutils.GetCliError(err, result.SuccessCount(), result.FailCount(), isFailNoOp(c))
  2965  }
  2966  
  2967  func buildCollectEnvCmd(c *cli.Context) error {
  2968  	if c.NArg() > 2 {
  2969  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2970  	}
  2971  	buildConfiguration := createBuildConfiguration(c)
  2972  	if err := validateBuildConfiguration(c, buildConfiguration); err != nil {
  2973  		return err
  2974  	}
  2975  	buildCollectEnvCmd := buildinfo.NewBuildCollectEnvCommand().SetBuildConfiguration(buildConfiguration)
  2976  
  2977  	return commands.Exec(buildCollectEnvCmd)
  2978  }
  2979  
  2980  func buildAddGitCmd(c *cli.Context) error {
  2981  	if c.NArg() > 3 {
  2982  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  2983  	}
  2984  	buildConfiguration := createBuildConfiguration(c)
  2985  	if err := validateBuildConfiguration(c, buildConfiguration); err != nil {
  2986  		return err
  2987  	}
  2988  
  2989  	buildAddGitConfigurationCmd := buildinfo.NewBuildAddGitCommand().SetBuildConfiguration(buildConfiguration).SetConfigFilePath(c.String("config"))
  2990  	if c.NArg() == 3 {
  2991  		buildAddGitConfigurationCmd.SetDotGitPath(c.Args().Get(2))
  2992  	} else if c.NArg() == 1 {
  2993  		buildAddGitConfigurationCmd.SetDotGitPath(c.Args().Get(0))
  2994  	}
  2995  	return commands.Exec(buildAddGitConfigurationCmd)
  2996  }
  2997  
  2998  func buildScanCmd(c *cli.Context) error {
  2999  	if c.NArg() > 2 {
  3000  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3001  	}
  3002  	buildConfiguration := createBuildConfiguration(c)
  3003  	if err := validateBuildConfiguration(c, buildConfiguration); err != nil {
  3004  		return err
  3005  	}
  3006  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  3007  	if err != nil {
  3008  		return err
  3009  	}
  3010  	buildScanCmd := buildinfo.NewBuildScanCommand().SetRtDetails(rtDetails).SetFailBuild(c.BoolT("fail")).SetBuildConfiguration(buildConfiguration)
  3011  	err = commands.Exec(buildScanCmd)
  3012  
  3013  	return checkBuildScanError(err)
  3014  }
  3015  
  3016  func checkBuildScanError(err error) error {
  3017  	// If the build was found vulnerable, exit with ExitCodeVulnerableBuild.
  3018  	if err == utils.GetBuildScanError() {
  3019  		return cliutils.CliError{ExitCode: cliutils.ExitCodeVulnerableBuild, ErrorMsg: err.Error()}
  3020  	}
  3021  	// If the scan operation failed, for example due to HTTP timeout, exit with ExitCodeError.
  3022  	if err != nil {
  3023  		return cliutils.CliError{ExitCode: cliutils.ExitCodeError, ErrorMsg: err.Error()}
  3024  	}
  3025  	return nil
  3026  }
  3027  
  3028  func buildCleanCmd(c *cli.Context) error {
  3029  	if c.NArg() > 2 {
  3030  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3031  	}
  3032  	buildConfiguration := createBuildConfiguration(c)
  3033  	if err := validateBuildConfiguration(c, buildConfiguration); err != nil {
  3034  		return err
  3035  	}
  3036  	buildCleanCmd := buildinfo.NewBuildCleanCommand().SetBuildConfiguration(buildConfiguration)
  3037  
  3038  	return commands.Exec(buildCleanCmd)
  3039  }
  3040  
  3041  func buildPromoteCmd(c *cli.Context) error {
  3042  	if c.NArg() > 3 {
  3043  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3044  	}
  3045  	if err := validateBuildConfiguration(c, createBuildConfiguration(c)); err != nil {
  3046  		return err
  3047  	}
  3048  	configuration := createBuildPromoteConfiguration(c)
  3049  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  3050  	if err != nil {
  3051  		return err
  3052  	}
  3053  	buildPromotionCmd := buildinfo.NewBuildPromotionCommand().SetDryRun(c.Bool("dry-run")).SetRtDetails(rtDetails).SetPromotionParams(configuration)
  3054  
  3055  	return commands.Exec(buildPromotionCmd)
  3056  }
  3057  
  3058  func buildDistributeCmd(c *cli.Context) error {
  3059  	if c.NArg() > 3 {
  3060  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3061  	}
  3062  	if err := validateBuildConfiguration(c, createBuildConfiguration(c)); err != nil {
  3063  		return err
  3064  	}
  3065  	configuration := createBuildDistributionConfiguration(c)
  3066  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  3067  	if err != nil {
  3068  		return err
  3069  	}
  3070  	buildDistributeCmd := buildinfo.NewBuildDistributeCommnad().SetDryRun(c.Bool("dry-run")).SetRtDetails(rtDetails).SetBuildDistributionParams(configuration)
  3071  
  3072  	return commands.Exec(buildDistributeCmd)
  3073  }
  3074  
  3075  func buildDiscardCmd(c *cli.Context) error {
  3076  	if c.NArg() > 1 {
  3077  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3078  	}
  3079  	configuration := createBuildDiscardConfiguration(c)
  3080  	if configuration.BuildName == "" {
  3081  		return cliutils.PrintHelpAndReturnError("Build name is expected as a command argument or environment variable.", c)
  3082  	}
  3083  	buildDiscardCmd := buildinfo.NewBuildDiscardCommand()
  3084  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  3085  	if err != nil {
  3086  		return err
  3087  	}
  3088  	buildDiscardCmd.SetRtDetails(rtDetails).SetDiscardBuildsParams(configuration)
  3089  
  3090  	return commands.Exec(buildDiscardCmd)
  3091  }
  3092  
  3093  func releaseBundleCreateCmd(c *cli.Context) error {
  3094  	if !(c.NArg() == 2 && c.IsSet("spec") || (c.NArg() == 3 && !c.IsSet("spec"))) {
  3095  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3096  	}
  3097  	var releaseBundleCreateSpec *spec.SpecFiles
  3098  	var err error
  3099  	if c.IsSet("spec") {
  3100  		releaseBundleCreateSpec, err = getSpec(c, true)
  3101  	} else {
  3102  		releaseBundleCreateSpec = createDefaultReleaseBundleSpec(c)
  3103  	}
  3104  	if err != nil {
  3105  		return err
  3106  	}
  3107  	err = spec.ValidateSpec(releaseBundleCreateSpec.Files, false, true)
  3108  	if err != nil {
  3109  		return err
  3110  	}
  3111  
  3112  	params, err := createReleaseBundleCreateUpdateParams(c, c.Args().Get(0), c.Args().Get(1))
  3113  	if err != nil {
  3114  		return err
  3115  	}
  3116  	releaseBundleCreateCmd := distribution.NewReleaseBundleCreateCommand()
  3117  	rtDetails, err := createArtifactoryDetailsByFlags(c, true)
  3118  	if err != nil {
  3119  		return err
  3120  	}
  3121  	releaseBundleCreateCmd.SetRtDetails(rtDetails).SetReleaseBundleCreateParams(params).SetSpec(releaseBundleCreateSpec).SetDryRun(c.Bool("dry-run"))
  3122  
  3123  	return commands.Exec(releaseBundleCreateCmd)
  3124  }
  3125  
  3126  func releaseBundleUpdateCmd(c *cli.Context) error {
  3127  	if !(c.NArg() == 2 && c.IsSet("spec") || (c.NArg() == 3 && !c.IsSet("spec"))) {
  3128  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3129  	}
  3130  	var releaseBundleUpdateSpec *spec.SpecFiles
  3131  	var err error
  3132  	if c.IsSet("spec") {
  3133  		releaseBundleUpdateSpec, err = getSpec(c, true)
  3134  	} else {
  3135  		releaseBundleUpdateSpec = createDefaultReleaseBundleSpec(c)
  3136  	}
  3137  	if err != nil {
  3138  		return err
  3139  	}
  3140  	err = spec.ValidateSpec(releaseBundleUpdateSpec.Files, false, true)
  3141  	if err != nil {
  3142  		return err
  3143  	}
  3144  
  3145  	params, err := createReleaseBundleCreateUpdateParams(c, c.Args().Get(0), c.Args().Get(1))
  3146  	if err != nil {
  3147  		return err
  3148  	}
  3149  	releaseBundleUpdateCmd := distribution.NewReleaseBundleUpdateCommand()
  3150  	rtDetails, err := createArtifactoryDetailsByFlags(c, true)
  3151  	if err != nil {
  3152  		return err
  3153  	}
  3154  	releaseBundleUpdateCmd.SetRtDetails(rtDetails).SetReleaseBundleUpdateParams(params).SetSpec(releaseBundleUpdateSpec).SetDryRun(c.Bool("dry-run"))
  3155  
  3156  	return commands.Exec(releaseBundleUpdateCmd)
  3157  }
  3158  
  3159  func releaseBundleSignCmd(c *cli.Context) error {
  3160  	if c.NArg() != 2 {
  3161  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3162  	}
  3163  
  3164  	params := distributionServices.NewSignBundleParams(c.Args().Get(0), c.Args().Get(1))
  3165  	params.StoringRepository = c.String("repo")
  3166  	params.GpgPassphrase = c.String("passphrase")
  3167  	releaseBundleSignCmd := distribution.NewReleaseBundleSignCommand()
  3168  	rtDetails, err := createArtifactoryDetailsByFlags(c, true)
  3169  	if err != nil {
  3170  		return err
  3171  	}
  3172  	releaseBundleSignCmd.SetRtDetails(rtDetails).SetReleaseBundleSignParams(params)
  3173  	return commands.Exec(releaseBundleSignCmd)
  3174  }
  3175  
  3176  func releaseBundleDistributeCmd(c *cli.Context) error {
  3177  	if c.NArg() != 2 {
  3178  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3179  	}
  3180  	var distributionRules *spec.DistributionRules
  3181  	if c.IsSet("dist-rules") {
  3182  		if c.IsSet("site") || c.IsSet("city") || c.IsSet("country-code") {
  3183  			return cliutils.PrintHelpAndReturnError("flag --dist-rules can't be used with --site, --city or --country-code", c)
  3184  		}
  3185  		var err error
  3186  		distributionRules, err = spec.CreateDistributionRulesFromFile(c.String("dist-rules"))
  3187  		if err != nil {
  3188  			return err
  3189  		}
  3190  	} else {
  3191  		distributionRules = createDefaultDistributionRules(c)
  3192  	}
  3193  
  3194  	params := distributionServices.NewDistributeReleaseBundleParams(c.Args().Get(0), c.Args().Get(1))
  3195  	releaseBundleDistributeCmd := distribution.NewReleaseBundleDistributeCommand()
  3196  	rtDetails, err := createArtifactoryDetailsByFlags(c, true)
  3197  	if err != nil {
  3198  		return err
  3199  	}
  3200  	releaseBundleDistributeCmd.SetRtDetails(rtDetails).SetDistributeBundleParams(params).SetDistributionRules(distributionRules).SetDryRun(c.Bool("dry-run"))
  3201  
  3202  	return commands.Exec(releaseBundleDistributeCmd)
  3203  }
  3204  
  3205  func releaseBundleDeleteCmd(c *cli.Context) error {
  3206  	if c.NArg() != 2 {
  3207  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3208  	}
  3209  	var distributionRules *spec.DistributionRules
  3210  	if c.IsSet("dist-rules") {
  3211  		if c.IsSet("site") || c.IsSet("city") || c.IsSet("country-code") {
  3212  			return cliutils.PrintHelpAndReturnError("flag --dist-rules can't be used with --site, --city or --country-code", c)
  3213  		}
  3214  		var err error
  3215  		distributionRules, err = spec.CreateDistributionRulesFromFile(c.String("dist-rules"))
  3216  		if err != nil {
  3217  			return err
  3218  		}
  3219  	} else {
  3220  		distributionRules = createDefaultDistributionRules(c)
  3221  	}
  3222  
  3223  	params := distributionServices.NewDeleteReleaseBundleParams(c.Args().Get(0), c.Args().Get(1))
  3224  	params.DeleteFromDistribution = c.BoolT("delete-from-dist")
  3225  	distributeBundleCmd := distribution.NewReleaseBundleDeleteParams()
  3226  	rtDetails, err := createArtifactoryDetailsByFlags(c, true)
  3227  	if err != nil {
  3228  		return err
  3229  	}
  3230  	distributeBundleCmd.SetQuiet(c.Bool("quiet")).SetRtDetails(rtDetails).SetDistributeBundleParams(params).SetDistributionRules(distributionRules).SetDryRun(c.Bool("dry-run"))
  3231  
  3232  	return commands.Exec(distributeBundleCmd)
  3233  }
  3234  
  3235  func gitLfsCleanCmd(c *cli.Context) error {
  3236  	if c.NArg() > 1 {
  3237  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3238  	}
  3239  	configuration := createGitLfsCleanConfiguration(c)
  3240  	gitLfsCmd := generic.NewGitLfsCommand()
  3241  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  3242  	if err != nil {
  3243  		return err
  3244  	}
  3245  	gitLfsCmd.SetConfiguration(configuration).SetRtDetails(rtDetails).SetDryRun(c.Bool("dry-run"))
  3246  
  3247  	return commands.Exec(gitLfsCmd)
  3248  }
  3249  
  3250  func curlCmd(c *cli.Context) error {
  3251  	if c.NArg() < 1 {
  3252  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3253  	}
  3254  	curlCommand := curl.NewCurlCommand().SetArguments(extractCommand(c))
  3255  	rtDetails, err := curlCommand.GetArtifactoryDetails()
  3256  	if err != nil {
  3257  		return err
  3258  	}
  3259  	curlCommand.SetRtDetails(rtDetails)
  3260  	return commands.Exec(curlCommand)
  3261  }
  3262  
  3263  func pipInstallCmd(c *cli.Context) error {
  3264  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  3265  		return err
  3266  	}
  3267  
  3268  	if c.NArg() < 1 {
  3269  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3270  	}
  3271  
  3272  	// Get pip configuration.
  3273  	pipConfig, err := piputils.GetPipConfiguration()
  3274  	if err != nil {
  3275  		return errors.New(fmt.Sprintf("Error occurred while attempting to read pip-configuration file: %s\n"+
  3276  			"Please run 'jfrog rt pip-config' command prior to running 'jfrog rt %s'.", err.Error(), "pip-install"))
  3277  	}
  3278  
  3279  	// Set arg values.
  3280  	rtDetails, err := pipConfig.RtDetails()
  3281  	if err != nil {
  3282  		return err
  3283  	}
  3284  
  3285  	// Run command.
  3286  	pipCmd := pip.NewPipInstallCommand()
  3287  	pipCmd.SetRtDetails(rtDetails).SetRepo(pipConfig.TargetRepo()).SetArgs(extractCommand(c))
  3288  	return commands.Exec(pipCmd)
  3289  }
  3290  
  3291  func repoTemplateCmd(c *cli.Context) error {
  3292  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  3293  		return err
  3294  	}
  3295  
  3296  	if c.NArg() != 1 {
  3297  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3298  	}
  3299  
  3300  	// Run command.
  3301  	repoTemplateCmd := repository.NewRepoTemplateCommand()
  3302  	repoTemplateCmd.SetTemplatePath(c.Args().Get(0))
  3303  	return commands.Exec(repoTemplateCmd)
  3304  }
  3305  
  3306  func repoCreateCmd(c *cli.Context) error {
  3307  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  3308  		return err
  3309  	}
  3310  
  3311  	if c.NArg() != 1 {
  3312  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3313  	}
  3314  
  3315  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  3316  	if err != nil {
  3317  		return err
  3318  	}
  3319  
  3320  	// Run command.
  3321  	repoCreateCmd := repository.NewCreateRepoCommand()
  3322  	repoCreateCmd.SetTemplatePath(c.Args().Get(0)).SetRtDetails(rtDetails).SetVars(c.String("vars"))
  3323  	return commands.Exec(repoCreateCmd)
  3324  }
  3325  
  3326  func repoUpdateCmd(c *cli.Context) error {
  3327  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  3328  		return err
  3329  	}
  3330  
  3331  	if c.NArg() != 1 {
  3332  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3333  	}
  3334  
  3335  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  3336  	if err != nil {
  3337  		return err
  3338  	}
  3339  
  3340  	// Run command.
  3341  	repoCreateCmd := repository.NewUpdateRepoCommand()
  3342  	repoCreateCmd.SetTemplatePath(c.Args().Get(0)).SetRtDetails(rtDetails).SetVars(c.String("vars"))
  3343  	return commands.Exec(repoCreateCmd)
  3344  }
  3345  
  3346  func repoDeleteCmd(c *cli.Context) error {
  3347  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  3348  		return err
  3349  	}
  3350  
  3351  	if c.NArg() != 1 {
  3352  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3353  	}
  3354  
  3355  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  3356  	if err != nil {
  3357  		return err
  3358  	}
  3359  
  3360  	repoDeleteCmd := repository.NewRepoDeleteCommand()
  3361  	repoDeleteCmd.SetRepoKey(c.Args().Get(0)).SetRtDetails(rtDetails).SetQuiet(cliutils.GetQuietValue(c))
  3362  	return commands.Exec(repoDeleteCmd)
  3363  }
  3364  
  3365  func replicationTemplateCmd(c *cli.Context) error {
  3366  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  3367  		return err
  3368  	}
  3369  	if c.NArg() != 1 {
  3370  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3371  	}
  3372  	replicationTemplateCmd := replication.NewReplicationTemplateCommand()
  3373  	replicationTemplateCmd.SetTemplatePath(c.Args().Get(0))
  3374  	return commands.Exec(replicationTemplateCmd)
  3375  }
  3376  
  3377  func replicationCreateCmd(c *cli.Context) error {
  3378  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  3379  		return err
  3380  	}
  3381  	if c.NArg() != 1 {
  3382  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3383  	}
  3384  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  3385  	if err != nil {
  3386  		return err
  3387  	}
  3388  	replicationCreateCmd := replication.NewReplicationCreateCommand()
  3389  	replicationCreateCmd.SetTemplatePath(c.Args().Get(0)).SetRtDetails(rtDetails).SetVars(c.String("vars"))
  3390  	return commands.Exec(replicationCreateCmd)
  3391  }
  3392  
  3393  func replicationDeleteCmd(c *cli.Context) error {
  3394  	if show, err := showCmdHelpIfNeeded(c); show || err != nil {
  3395  		return err
  3396  	}
  3397  	if c.NArg() != 1 {
  3398  		return cliutils.PrintHelpAndReturnError("Wrong number of arguments.", c)
  3399  	}
  3400  	rtDetails, err := createArtifactoryDetailsByFlags(c, false)
  3401  	if err != nil {
  3402  		return err
  3403  	}
  3404  	replicationDeleteCmd := replication.NewReplicationDeleteCommand()
  3405  	replicationDeleteCmd.SetRepoKey(c.Args().Get(0)).SetRtDetails(rtDetails).SetQuiet(cliutils.GetQuietValue(c))
  3406  	return commands.Exec(replicationDeleteCmd)
  3407  }
  3408  
  3409  func validateBuildConfiguration(c *cli.Context, buildConfiguration *utils.BuildConfiguration) error {
  3410  	if buildConfiguration.BuildName == "" || buildConfiguration.BuildNumber == "" {
  3411  		return cliutils.PrintHelpAndReturnError("Build name and build number are expected as command arguments or environment variables.", c)
  3412  	}
  3413  	return nil
  3414  }
  3415  
  3416  func offerConfig(c *cli.Context) (*config.ArtifactoryDetails, error) {
  3417  	var exists bool
  3418  	exists, err := config.IsArtifactoryConfExists()
  3419  	if err != nil || exists {
  3420  		return nil, err
  3421  	}
  3422  
  3423  	var ci bool
  3424  	if ci, err = clientutils.GetBoolEnvValue(cliutils.CI, false); err != nil {
  3425  		return nil, err
  3426  	}
  3427  	var offerConfig bool
  3428  	if offerConfig, err = clientutils.GetBoolEnvValue(cliutils.OfferConfig, !ci); err != nil {
  3429  		return nil, err
  3430  	}
  3431  	if !offerConfig {
  3432  		config.SaveArtifactoryConf(make([]*config.ArtifactoryDetails, 0))
  3433  		return nil, nil
  3434  	}
  3435  
  3436  	msg := fmt.Sprintf("To avoid this message in the future, set the %s environment variable to false.\n"+
  3437  		"The CLI commands require the Artifactory URL and authentication details\n"+
  3438  		"Configuring JFrog CLI with these parameters now will save you having to include them as command options.\n"+
  3439  		"You can also configure these parameters later using the 'jfrog rt c' command.\n"+
  3440  		"Configure now?", cliutils.OfferConfig)
  3441  	confirmed := cliutils.InteractiveConfirm(msg)
  3442  	if !confirmed {
  3443  		config.SaveArtifactoryConf(make([]*config.ArtifactoryDetails, 0))
  3444  		return nil, nil
  3445  	}
  3446  	details, err := createArtifactoryDetails(c, false)
  3447  	if err != nil {
  3448  		return nil, err
  3449  	}
  3450  	encPassword := c.BoolT("enc-password")
  3451  	configCmd := commands.NewConfigCommand().SetDefaultDetails(details).SetInteractive(true).SetEncPassword(encPassword)
  3452  	err = configCmd.Config()
  3453  	if err != nil {
  3454  		return nil, err
  3455  	}
  3456  
  3457  	return configCmd.RtDetails()
  3458  }
  3459  
  3460  func createArtifactoryDetails(c *cli.Context, includeConfig bool) (details *config.ArtifactoryDetails, err error) {
  3461  	if includeConfig {
  3462  		details, err := offerConfig(c)
  3463  		if err != nil {
  3464  			return nil, err
  3465  		}
  3466  		if details != nil {
  3467  			return details, err
  3468  		}
  3469  	}
  3470  	details = new(config.ArtifactoryDetails)
  3471  	details.Url = c.String("url")
  3472  	details.DistributionUrl = c.String("dist-url")
  3473  	details.ApiKey = c.String("apikey")
  3474  	details.User = c.String("user")
  3475  	details.Password = c.String("password")
  3476  	details.SshKeyPath = c.String("ssh-key-path")
  3477  	details.SshPassphrase = c.String("ssh-passphrase")
  3478  	details.AccessToken = c.String("access-token")
  3479  	details.ClientCertPath = c.String("client-cert-path")
  3480  	details.ClientCertKeyPath = c.String("client-cert-key-path")
  3481  	details.ServerId = c.String("server-id")
  3482  	details.InsecureTls = c.Bool("insecure-tls")
  3483  	if details.ApiKey != "" && details.User != "" && details.Password == "" {
  3484  		// The API Key is deprecated, use password option instead.
  3485  		details.Password = details.ApiKey
  3486  		details.ApiKey = ""
  3487  	}
  3488  
  3489  	if includeConfig && !credentialsChanged(details) {
  3490  		confDetails, err := commands.GetConfig(details.ServerId)
  3491  		if err != nil {
  3492  			return nil, err
  3493  		}
  3494  
  3495  		if details.Url == "" {
  3496  			details.Url = confDetails.Url
  3497  		}
  3498  		if details.DistributionUrl == "" {
  3499  			details.DistributionUrl = confDetails.DistributionUrl
  3500  		}
  3501  
  3502  		if !isAuthMethodSet(details) {
  3503  			if details.ApiKey == "" {
  3504  				details.ApiKey = confDetails.ApiKey
  3505  			}
  3506  			if details.User == "" {
  3507  				details.User = confDetails.User
  3508  			}
  3509  			if details.Password == "" {
  3510  				details.Password = confDetails.Password
  3511  			}
  3512  			if details.SshKeyPath == "" {
  3513  				details.SshKeyPath = confDetails.SshKeyPath
  3514  			}
  3515  			if details.AccessToken == "" {
  3516  				details.AccessToken = confDetails.AccessToken
  3517  			}
  3518  			if details.ClientCertPath == "" {
  3519  				details.ClientCertPath = confDetails.ClientCertPath
  3520  			}
  3521  			if details.ClientCertKeyPath == "" {
  3522  				details.ClientCertKeyPath = confDetails.ClientCertKeyPath
  3523  			}
  3524  		}
  3525  	}
  3526  	details.Url = clientutils.AddTrailingSlashIfNeeded(details.Url)
  3527  	details.DistributionUrl = clientutils.AddTrailingSlashIfNeeded(details.DistributionUrl)
  3528  	return
  3529  }
  3530  
  3531  func credentialsChanged(details *config.ArtifactoryDetails) bool {
  3532  	return details.Url != "" || details.User != "" || details.Password != "" ||
  3533  		details.ApiKey != "" || details.SshKeyPath != "" || details.SshAuthHeaderSet() ||
  3534  		details.AccessToken != ""
  3535  }
  3536  
  3537  func isAuthMethodSet(details *config.ArtifactoryDetails) bool {
  3538  	return (details.User != "" && details.Password != "") || details.SshKeyPath != "" || details.ApiKey != "" || details.AccessToken != ""
  3539  }
  3540  
  3541  func getDebFlag(c *cli.Context) (deb string, err error) {
  3542  	deb = c.String("deb")
  3543  	slashesCount := strings.Count(deb, "/") - strings.Count(deb, "\\/")
  3544  	if deb != "" && slashesCount != 2 {
  3545  		return "", errors.New("the --deb option should be in the form of distribution/component/architecture")
  3546  	}
  3547  	return deb, nil
  3548  }
  3549  
  3550  func createDefaultCopyMoveSpec(c *cli.Context) (*spec.SpecFiles, error) {
  3551  	offset, limit, err := getOffsetAndLimitValues(c)
  3552  	if err != nil {
  3553  		return nil, err
  3554  	}
  3555  	return spec.NewBuilder().
  3556  		Pattern(c.Args().Get(0)).
  3557  		Props(c.String("props")).
  3558  		ExcludeProps(c.String("exclude-props")).
  3559  		Build(c.String("build")).
  3560  		Bundle(c.String("bundle")).
  3561  		Offset(offset).
  3562  		Limit(limit).
  3563  		SortOrder(c.String("sort-order")).
  3564  		SortBy(cliutils.GetStringsArrFlagValue(c, "sort-by")).
  3565  		Recursive(c.BoolT("recursive")).
  3566  		ExcludePatterns(cliutils.GetStringsArrFlagValue(c, "exclude-patterns")).
  3567  		Exclusions(cliutils.GetStringsArrFlagValue(c, "exclusions")).
  3568  		Flat(c.Bool("flat")).
  3569  		IncludeDirs(true).
  3570  		Target(c.Args().Get(1)).
  3571  		ArchiveEntries(c.String("archive-entries")).
  3572  		BuildSpec(), nil
  3573  }
  3574  
  3575  func getSpec(c *cli.Context, isDownload bool) (specFiles *spec.SpecFiles, err error) {
  3576  	specFiles, err = spec.CreateSpecFromFile(c.String("spec"), cliutils.SpecVarsStringToMap(c.String("spec-vars")))
  3577  	if err != nil {
  3578  		return nil, err
  3579  	}
  3580  	// Override spec with CLI options
  3581  	for i := 0; i < len(specFiles.Files); i++ {
  3582  		if isDownload {
  3583  			specFiles.Get(i).Pattern = strings.TrimPrefix(specFiles.Get(i).Pattern, "/")
  3584  		}
  3585  		overrideFieldsIfSet(specFiles.Get(i), c)
  3586  	}
  3587  	return
  3588  }
  3589  
  3590  func createDefaultDeleteSpec(c *cli.Context) (*spec.SpecFiles, error) {
  3591  	offset, limit, err := getOffsetAndLimitValues(c)
  3592  	if err != nil {
  3593  		return nil, err
  3594  	}
  3595  	return spec.NewBuilder().
  3596  		Pattern(c.Args().Get(0)).
  3597  		Props(c.String("props")).
  3598  		ExcludeProps(c.String("exclude-props")).
  3599  		Build(c.String("build")).
  3600  		Offset(offset).
  3601  		Limit(limit).
  3602  		SortOrder(c.String("sort-order")).
  3603  		SortBy(cliutils.GetStringsArrFlagValue(c, "sort-by")).
  3604  		Recursive(c.BoolT("recursive")).
  3605  		ExcludePatterns(cliutils.GetStringsArrFlagValue(c, "exclude-patterns")).
  3606  		Exclusions(cliutils.GetStringsArrFlagValue(c, "exclusions")).
  3607  		ArchiveEntries(c.String("archive-entries")).
  3608  		BuildSpec(), nil
  3609  }
  3610  
  3611  func createDefaultSearchSpec(c *cli.Context) (*spec.SpecFiles, error) {
  3612  	offset, limit, err := getOffsetAndLimitValues(c)
  3613  	if err != nil {
  3614  		return nil, err
  3615  	}
  3616  	return spec.NewBuilder().
  3617  		Pattern(c.Args().Get(0)).
  3618  		Props(c.String("props")).
  3619  		ExcludeProps(c.String("exclude-props")).
  3620  		Build(c.String("build")).
  3621  		Bundle(c.String("bundle")).
  3622  		Offset(offset).
  3623  		Limit(limit).
  3624  		SortOrder(c.String("sort-order")).
  3625  		SortBy(cliutils.GetStringsArrFlagValue(c, "sort-by")).
  3626  		Recursive(c.BoolT("recursive")).
  3627  		ExcludePatterns(cliutils.GetStringsArrFlagValue(c, "exclude-patterns")).
  3628  		Exclusions(cliutils.GetStringsArrFlagValue(c, "exclusions")).
  3629  		IncludeDirs(c.Bool("include-dirs")).
  3630  		ArchiveEntries(c.String("archive-entries")).
  3631  		BuildSpec(), nil
  3632  }
  3633  
  3634  func createDefaultPropertiesSpec(c *cli.Context) (*spec.SpecFiles, error) {
  3635  	offset, limit, err := getOffsetAndLimitValues(c)
  3636  	if err != nil {
  3637  		return nil, err
  3638  	}
  3639  	return spec.NewBuilder().
  3640  		Pattern(c.Args().Get(0)).
  3641  		Props(c.String("props")).
  3642  		ExcludeProps(c.String("exclude-props")).
  3643  		Build(c.String("build")).
  3644  		Bundle(c.String("bundle")).
  3645  		Offset(offset).
  3646  		Limit(limit).
  3647  		SortOrder(c.String("sort-order")).
  3648  		SortBy(cliutils.GetStringsArrFlagValue(c, "sort-by")).
  3649  		Recursive(c.BoolT("recursive")).
  3650  		ExcludePatterns(cliutils.GetStringsArrFlagValue(c, "exclude-patterns")).
  3651  		Exclusions(cliutils.GetStringsArrFlagValue(c, "exclusions")).
  3652  		IncludeDirs(c.Bool("include-dirs")).
  3653  		ArchiveEntries(c.String("archive-entries")).
  3654  		BuildSpec(), nil
  3655  }
  3656  
  3657  func createBuildInfoConfiguration(c *cli.Context) *buildinfocmd.Configuration {
  3658  	flags := new(buildinfocmd.Configuration)
  3659  	flags.BuildUrl = utils.GetBuildUrl(c.String("build-url"))
  3660  	flags.DryRun = c.Bool("dry-run")
  3661  	flags.EnvInclude = c.String("env-include")
  3662  	flags.EnvExclude = utils.GetEnvExclude(c.String("env-exclude"))
  3663  	if flags.EnvInclude == "" {
  3664  		flags.EnvInclude = "*"
  3665  	}
  3666  	// Allow to use `env-exclude=""` and get no filters
  3667  	if flags.EnvExclude == "" {
  3668  		flags.EnvExclude = "*password*;*secret*;*key*;*token*"
  3669  	}
  3670  	return flags
  3671  }
  3672  
  3673  func createBuildPromoteConfiguration(c *cli.Context) services.PromotionParams {
  3674  	promotionParamsImpl := services.NewPromotionParams()
  3675  	promotionParamsImpl.Comment = c.String("comment")
  3676  	promotionParamsImpl.SourceRepo = c.String("source-repo")
  3677  	promotionParamsImpl.Status = c.String("status")
  3678  	promotionParamsImpl.IncludeDependencies = c.Bool("include-dependencies")
  3679  	promotionParamsImpl.Copy = c.Bool("copy")
  3680  	promotionParamsImpl.Properties = c.String("props")
  3681  	promotionParamsImpl.BuildName, promotionParamsImpl.BuildNumber = utils.GetBuildNameAndNumber(c.Args().Get(0), c.Args().Get(1))
  3682  	promotionParamsImpl.TargetRepo = c.Args().Get(2)
  3683  	return promotionParamsImpl
  3684  }
  3685  
  3686  func createBuildDiscardConfiguration(c *cli.Context) services.DiscardBuildsParams {
  3687  	discardParamsImpl := services.NewDiscardBuildsParams()
  3688  	discardParamsImpl.DeleteArtifacts = c.Bool("delete-artifacts")
  3689  	discardParamsImpl.MaxBuilds = c.String("max-builds")
  3690  	discardParamsImpl.MaxDays = c.String("max-days")
  3691  	discardParamsImpl.ExcludeBuilds = c.String("exclude-builds")
  3692  	discardParamsImpl.Async = c.Bool("async")
  3693  	discardParamsImpl.BuildName = utils.GetBuildName(c.Args().Get(0))
  3694  	return discardParamsImpl
  3695  }
  3696  
  3697  func createBuildDistributionConfiguration(c *cli.Context) services.BuildDistributionParams {
  3698  	distributeParamsImpl := services.NewBuildDistributionParams()
  3699  	distributeParamsImpl.Publish = c.BoolT("publish")
  3700  	distributeParamsImpl.OverrideExistingFiles = c.Bool("override")
  3701  	distributeParamsImpl.GpgPassphrase = c.String("passphrase")
  3702  	distributeParamsImpl.Async = c.Bool("async")
  3703  	distributeParamsImpl.SourceRepos = c.String("source-repos")
  3704  	distributeParamsImpl.BuildName, distributeParamsImpl.BuildNumber = utils.GetBuildNameAndNumber(c.Args().Get(0), c.Args().Get(1))
  3705  	distributeParamsImpl.TargetRepo = c.Args().Get(2)
  3706  	return distributeParamsImpl
  3707  }
  3708  
  3709  func createReleaseBundleCreateUpdateParams(c *cli.Context, bundleName, bundleVersion string) (distributionServicesUtils.ReleaseBundleParams, error) {
  3710  	releaseBundleParams := distributionServicesUtils.NewReleaseBundleParams(bundleName, bundleVersion)
  3711  	releaseBundleParams.SignImmediately = c.Bool("sign")
  3712  	releaseBundleParams.StoringRepository = c.String("repo")
  3713  	releaseBundleParams.GpgPassphrase = c.String("passphrase")
  3714  	releaseBundleParams.Description = c.String("desc")
  3715  	if c.IsSet("release-notes-path") {
  3716  		bytes, err := ioutil.ReadFile(c.String("release-notes-path"))
  3717  		if err != nil {
  3718  			return releaseBundleParams, errorutils.CheckError(err)
  3719  		}
  3720  		releaseBundleParams.ReleaseNotes = string(bytes)
  3721  		releaseBundleParams.ReleaseNotesSyntax, err = populateReleaseNotesSyntax(c)
  3722  		if err != nil {
  3723  			return releaseBundleParams, err
  3724  		}
  3725  	}
  3726  	return releaseBundleParams, nil
  3727  }
  3728  
  3729  func createGitLfsCleanConfiguration(c *cli.Context) (gitLfsCleanConfiguration *generic.GitLfsCleanConfiguration) {
  3730  	gitLfsCleanConfiguration = new(generic.GitLfsCleanConfiguration)
  3731  
  3732  	gitLfsCleanConfiguration.Refs = c.String("refs")
  3733  	if len(gitLfsCleanConfiguration.Refs) == 0 {
  3734  		gitLfsCleanConfiguration.Refs = "refs/remotes/*"
  3735  	}
  3736  
  3737  	gitLfsCleanConfiguration.Repo = c.String("repo")
  3738  	gitLfsCleanConfiguration.Quiet = cliutils.GetQuietValue(c)
  3739  	dotGitPath := ""
  3740  	if c.NArg() == 1 {
  3741  		dotGitPath = c.Args().Get(0)
  3742  	}
  3743  	gitLfsCleanConfiguration.GitPath = dotGitPath
  3744  	return
  3745  }
  3746  
  3747  func createDefaultDownloadSpec(c *cli.Context) (*spec.SpecFiles, error) {
  3748  	offset, limit, err := getOffsetAndLimitValues(c)
  3749  	if err != nil {
  3750  		return nil, err
  3751  	}
  3752  	return spec.NewBuilder().
  3753  		Pattern(strings.TrimPrefix(c.Args().Get(0), "/")).
  3754  		Props(c.String("props")).
  3755  		ExcludeProps(c.String("exclude-props")).
  3756  		Build(c.String("build")).
  3757  		Bundle(c.String("bundle")).
  3758  		Offset(offset).
  3759  		Limit(limit).
  3760  		SortOrder(c.String("sort-order")).
  3761  		SortBy(cliutils.GetStringsArrFlagValue(c, "sort-by")).
  3762  		Recursive(c.BoolT("recursive")).
  3763  		ExcludePatterns(cliutils.GetStringsArrFlagValue(c, "exclude-patterns")).
  3764  		Exclusions(cliutils.GetStringsArrFlagValue(c, "exclusions")).
  3765  		Flat(c.Bool("flat")).
  3766  		Explode(c.String("explode")).
  3767  		IncludeDirs(c.Bool("include-dirs")).
  3768  		Target(c.Args().Get(1)).
  3769  		ArchiveEntries(c.String("archive-entries")).
  3770  		BuildSpec(), nil
  3771  }
  3772  
  3773  func createDownloadConfiguration(c *cli.Context) (downloadConfiguration *utils.DownloadConfiguration, err error) {
  3774  	downloadConfiguration = new(utils.DownloadConfiguration)
  3775  	downloadConfiguration.ValidateSymlink = c.Bool("validate-symlinks")
  3776  	downloadConfiguration.MinSplitSize, err = getMinSplit(c)
  3777  	if err != nil {
  3778  		return nil, err
  3779  	}
  3780  	downloadConfiguration.SplitCount, err = getSplitCount(c)
  3781  	if err != nil {
  3782  		return nil, err
  3783  	}
  3784  	downloadConfiguration.Threads, err = getThreadsCount(c)
  3785  	if err != nil {
  3786  		return nil, err
  3787  	}
  3788  	downloadConfiguration.Retries, err = getRetries(c)
  3789  	if err != nil {
  3790  		return nil, err
  3791  	}
  3792  	downloadConfiguration.Symlink = true
  3793  	return
  3794  }
  3795  
  3796  func createDefaultUploadSpec(c *cli.Context) (*spec.SpecFiles, error) {
  3797  	offset, limit, err := getOffsetAndLimitValues(c)
  3798  	if err != nil {
  3799  		return nil, err
  3800  	}
  3801  	return spec.NewBuilder().
  3802  		Pattern(c.Args().Get(0)).
  3803  		Props(c.String("props")).
  3804  		Build(c.String("build")).
  3805  		Offset(offset).
  3806  		Limit(limit).
  3807  		SortOrder(c.String("sort-order")).
  3808  		SortBy(cliutils.GetStringsArrFlagValue(c, "sort-by")).
  3809  		Recursive(c.BoolT("recursive")).
  3810  		ExcludePatterns(cliutils.GetStringsArrFlagValue(c, "exclude-patterns")).
  3811  		Exclusions(cliutils.GetStringsArrFlagValue(c, "exclusions")).
  3812  		Flat(c.BoolT("flat")).
  3813  		Explode(c.String("explode")).
  3814  		Regexp(c.Bool("regexp")).
  3815  		IncludeDirs(c.Bool("include-dirs")).
  3816  		Target(strings.TrimPrefix(c.Args().Get(1), "/")).
  3817  		BuildSpec(), nil
  3818  }
  3819  
  3820  func createDefaultBuildAddDependenciesSpec(c *cli.Context) *spec.SpecFiles {
  3821  	pattern := c.Args().Get(2)
  3822  	if pattern == "" {
  3823  		// Build name and build number from env
  3824  		pattern = c.Args().Get(0)
  3825  	}
  3826  	return spec.NewBuilder().
  3827  		Pattern(pattern).
  3828  		Recursive(c.BoolT("recursive")).
  3829  		ExcludePatterns(cliutils.GetStringsArrFlagValue(c, "exclude-patterns")).
  3830  		Exclusions(cliutils.GetStringsArrFlagValue(c, "exclusions")).
  3831  		Regexp(c.Bool("regexp")).
  3832  		BuildSpec()
  3833  }
  3834  
  3835  func createDefaultReleaseBundleSpec(c *cli.Context) *spec.SpecFiles {
  3836  	return spec.NewBuilder().
  3837  		Pattern(c.Args().Get(2)).
  3838  		Props(c.String("props")).
  3839  		Build(c.String("build")).
  3840  		Bundle(c.String("bundle")).
  3841  		Exclusions(cliutils.GetStringsArrFlagValue(c, "exclusions")).
  3842  		Regexp(c.Bool("regexp")).
  3843  		BuildSpec()
  3844  }
  3845  
  3846  func createDefaultDistributionRules(c *cli.Context) *spec.DistributionRules {
  3847  	return &spec.DistributionRules{
  3848  		DistributionRules: []spec.DistributionRule{{
  3849  			SiteName:     c.String("site"),
  3850  			CityName:     c.String("city"),
  3851  			CountryCodes: cliutils.GetStringsArrFlagValue(c, "country-codes"),
  3852  		}},
  3853  	}
  3854  }
  3855  
  3856  func getFileSystemSpec(c *cli.Context) (fsSpec *spec.SpecFiles, err error) {
  3857  	fsSpec, err = spec.CreateSpecFromFile(c.String("spec"), cliutils.SpecVarsStringToMap(c.String("spec-vars")))
  3858  	if err != nil {
  3859  		return
  3860  	}
  3861  	// Override spec with CLI options
  3862  	for i := 0; i < len(fsSpec.Files); i++ {
  3863  		fsSpec.Get(i).Target = strings.TrimPrefix(fsSpec.Get(i).Target, "/")
  3864  		overrideFieldsIfSet(fsSpec.Get(i), c)
  3865  	}
  3866  	return
  3867  }
  3868  
  3869  func fixWinPathsForFileSystemSourcedCmds(uploadSpec *spec.SpecFiles, c *cli.Context) {
  3870  	if cliutils.IsWindows() {
  3871  		for i, file := range uploadSpec.Files {
  3872  			uploadSpec.Files[i].Pattern = fixWinPathBySource(file.Pattern, c.IsSet("spec"))
  3873  			for j, exclusion := range uploadSpec.Files[i].Exclusions {
  3874  				// If exclusions are set, they override the spec value
  3875  				uploadSpec.Files[i].Exclusions[j] = fixWinPathBySource(exclusion, c.IsSet("spec") && !c.IsSet("exclusions"))
  3876  			}
  3877  			for j, excludePattern := range uploadSpec.Files[i].ExcludePatterns {
  3878  				// If exclude patterns are set, they override the spec value
  3879  				uploadSpec.Files[i].ExcludePatterns[j] = fixWinPathBySource(excludePattern, c.IsSet("spec") && !c.IsSet("exclude-patterns"))
  3880  			}
  3881  		}
  3882  	}
  3883  }
  3884  
  3885  func fixWinPathsForDownloadCmd(uploadSpec *spec.SpecFiles, c *cli.Context) {
  3886  	if cliutils.IsWindows() {
  3887  		for i, file := range uploadSpec.Files {
  3888  			uploadSpec.Files[i].Target = fixWinPathBySource(file.Target, c.IsSet("spec"))
  3889  		}
  3890  	}
  3891  }
  3892  
  3893  func fixWinPathBySource(path string, fromSpec bool) string {
  3894  	if strings.Count(path, "/") > 0 {
  3895  		// Assuming forward slashes - not doubling backslash to allow regexp escaping
  3896  		return ioutils.UnixToWinPathSeparator(path)
  3897  	}
  3898  	if fromSpec {
  3899  		// Doubling backslash only for paths from spec files (that aren't forward slashed)
  3900  		return ioutils.DoubleWinPathSeparator(path)
  3901  	}
  3902  	return path
  3903  }
  3904  
  3905  func createUploadConfiguration(c *cli.Context) (uploadConfiguration *utils.UploadConfiguration, err error) {
  3906  	uploadConfiguration = new(utils.UploadConfiguration)
  3907  	uploadConfiguration.Symlink = c.Bool("symlinks")
  3908  	uploadConfiguration.Retries, err = getRetries(c)
  3909  	if err != nil {
  3910  		return nil, err
  3911  	}
  3912  	uploadConfiguration.Threads, err = getThreadsCount(c)
  3913  	if err != nil {
  3914  		return nil, err
  3915  	}
  3916  	uploadConfiguration.Deb, err = getDebFlag(c)
  3917  	if err != nil {
  3918  		return
  3919  	}
  3920  	return
  3921  }
  3922  
  3923  func createBuildConfigurationWithModule(c *cli.Context) (buildConfigConfiguration *utils.BuildConfiguration, err error) {
  3924  	buildConfigConfiguration = new(utils.BuildConfiguration)
  3925  	buildConfigConfiguration.BuildName, buildConfigConfiguration.BuildNumber = utils.GetBuildNameAndNumber(c.String("build-name"), c.String("build-number"))
  3926  	buildConfigConfiguration.Module = c.String("module")
  3927  	err = utils.ValidateBuildAndModuleParams(buildConfigConfiguration)
  3928  	return
  3929  }
  3930  
  3931  func createConfigCommandConfiguration(c *cli.Context) (configCommandConfiguration *commands.ConfigCommandConfiguration, err error) {
  3932  	configCommandConfiguration = new(commands.ConfigCommandConfiguration)
  3933  	configCommandConfiguration.ArtDetails, err = createArtifactoryDetails(c, false)
  3934  	if err != nil {
  3935  		return
  3936  	}
  3937  	configCommandConfiguration.EncPassword = c.BoolT("enc-password")
  3938  	configCommandConfiguration.Interactive = cliutils.GetInteractiveValue(c)
  3939  	return
  3940  }
  3941  
  3942  func validateConfigFlags(configCommandConfiguration *commands.ConfigCommandConfiguration) error {
  3943  	if !configCommandConfiguration.Interactive && configCommandConfiguration.ArtDetails.Url == "" {
  3944  		return errors.New("the --url option is mandatory when the --interactive option is set to false or the CI environment variable is set to true.")
  3945  	}
  3946  	return nil
  3947  }
  3948  
  3949  // If `fieldName` exist in the cli args, read it to `field` as a string.
  3950  func overrideStringIfSet(field *string, c *cli.Context, fieldName string) {
  3951  	if c.IsSet(fieldName) {
  3952  		*field = c.String(fieldName)
  3953  	}
  3954  }
  3955  
  3956  // If `fieldName` exist in the cli args, read it to `field` as an array split by `;`.
  3957  func overrideArrayIfSet(field *[]string, c *cli.Context, fieldName string) {
  3958  	if c.IsSet(fieldName) {
  3959  		*field = nil
  3960  		for _, singleValue := range strings.Split(c.String(fieldName), ";") {
  3961  			*field = append(*field, singleValue)
  3962  		}
  3963  	}
  3964  }
  3965  
  3966  // If `fieldName` exist in the cli args, read it to `field` as a int.
  3967  func overrideIntIfSet(field *int, c *cli.Context, fieldName string) {
  3968  	if c.IsSet(fieldName) {
  3969  		*field = c.Int(fieldName)
  3970  	}
  3971  }
  3972  
  3973  func overrideFieldsIfSet(spec *spec.File, c *cli.Context) {
  3974  	overrideArrayIfSet(&spec.ExcludePatterns, c, "exclude-patterns")
  3975  	overrideArrayIfSet(&spec.Exclusions, c, "exclusions")
  3976  	overrideArrayIfSet(&spec.SortBy, c, "sort-by")
  3977  	overrideIntIfSet(&spec.Offset, c, "offset")
  3978  	overrideIntIfSet(&spec.Limit, c, "limit")
  3979  	overrideStringIfSet(&spec.SortOrder, c, "sort-order")
  3980  	overrideStringIfSet(&spec.Props, c, "props")
  3981  	overrideStringIfSet(&spec.ExcludeProps, c, "exclude-props")
  3982  	overrideStringIfSet(&spec.Build, c, "build")
  3983  	overrideStringIfSet(&spec.Bundle, c, "bundle")
  3984  	overrideStringIfSet(&spec.Recursive, c, "recursive")
  3985  	overrideStringIfSet(&spec.Flat, c, "flat")
  3986  	overrideStringIfSet(&spec.Explode, c, "explode")
  3987  	overrideStringIfSet(&spec.Regexp, c, "regexp")
  3988  	overrideStringIfSet(&spec.IncludeDirs, c, "include-dirs")
  3989  }
  3990  
  3991  func getOffsetAndLimitValues(c *cli.Context) (offset, limit int, err error) {
  3992  	offset, err = cliutils.GetIntFlagValue(c, "offset", 0)
  3993  	if err != nil {
  3994  		return 0, 0, err
  3995  	}
  3996  	limit, err = cliutils.GetIntFlagValue(c, "limit", 0)
  3997  	if err != nil {
  3998  		return 0, 0, err
  3999  	}
  4000  
  4001  	return
  4002  }
  4003  
  4004  func isFailNoOp(context *cli.Context) bool {
  4005  	if context == nil {
  4006  		return false
  4007  	}
  4008  	return context.Bool("fail-no-op")
  4009  }
  4010  
  4011  // Returns build configuration struct using the params provided from the console.
  4012  func createBuildConfiguration(c *cli.Context) *utils.BuildConfiguration {
  4013  	buildConfiguration := new(utils.BuildConfiguration)
  4014  	buildNameArg, buildNumberArg := c.Args().Get(0), c.Args().Get(1)
  4015  	if buildNameArg == "" || buildNumberArg == "" {
  4016  		buildNameArg = ""
  4017  		buildNumberArg = ""
  4018  	}
  4019  	buildConfiguration.BuildName, buildConfiguration.BuildNumber = utils.GetBuildNameAndNumber(buildNameArg, buildNumberArg)
  4020  	return buildConfiguration
  4021  }
  4022  
  4023  func extractCommand(c *cli.Context) (command []string) {
  4024  	command = make([]string, len(c.Args()))
  4025  	copy(command, c.Args())
  4026  	return command
  4027  }
  4028  
  4029  func deprecatedWarning(projectType utils.ProjectType, command, configCommand string) string {
  4030  	return `You are using a deprecated syntax of the "` + command + `" command.
  4031  	To use the new syntax, the command expects the details of the Artifactory server and repositories to be pre-configured.
  4032  	To create this configuration, run the following command from the root directory of the project:
  4033  	$ jfrog rt ` + configCommand + `
  4034  	This will create the configuration inside the .jfrog directory under the root directory of the project.
  4035  	The new command syntax looks very similar to the ` + projectType.String() + ` CLI command i.e.:
  4036  	$ jfrog rt ` + command + ` [` + projectType.String() + ` args and option] --build-name=*BUILD_NAME* --build-number=*BUILD_NUMBER*`
  4037  }
  4038  
  4039  func extractThreadsFlag(args []string) (cleanArgs []string, threadsCount int, err error) {
  4040  	// Extract threads flag.
  4041  	cleanArgs = append([]string(nil), args...)
  4042  	threadsFlagIndex, threadsValueIndex, threads, err := utils.FindFlag("--threads", cleanArgs)
  4043  	if err != nil || threadsFlagIndex < 0 {
  4044  		return
  4045  	}
  4046  	utils.RemoveFlagFromCommand(&cleanArgs, threadsFlagIndex, threadsValueIndex)
  4047  
  4048  	// Convert flag value to int.
  4049  	threadsCount, err = strconv.Atoi(threads)
  4050  	if err != nil {
  4051  		err = errors.New("The '--threads' option should have a numeric value. " + cliutils.GetDocumentationMessage())
  4052  	}
  4053  
  4054  	return
  4055  }
  4056  
  4057  func populateReleaseNotesSyntax(c *cli.Context) (distributionServicesUtils.ReleaseNotesSyntax, error) {
  4058  	// If release notes syntax is set, use it
  4059  	releaseNotexSyntax := c.String("release-notes-syntax")
  4060  	if releaseNotexSyntax != "" {
  4061  		switch releaseNotexSyntax {
  4062  		case "markdown":
  4063  			return distributionServicesUtils.Markdown, nil
  4064  		case "asciidoc":
  4065  			return distributionServicesUtils.Asciidoc, nil
  4066  		case "plain_text":
  4067  			return distributionServicesUtils.PlainText, nil
  4068  		default:
  4069  			return distributionServicesUtils.PlainText, errorutils.CheckError(errors.New("--release-notes-syntax must be one of: markdown, asciidoc or plain_text."))
  4070  		}
  4071  	}
  4072  	// If the file extension is ".md" or ".markdown", use the markdonwn syntax
  4073  	extension := strings.ToLower(filepath.Ext(c.String("release-notes-path")))
  4074  	if extension == ".md" || extension == ".markdown" {
  4075  		return distributionServicesUtils.Markdown, nil
  4076  	}
  4077  	return distributionServicesUtils.PlainText, nil
  4078  }