github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/artifactory/commands/buildinfo/adddependencies.go (about) 1 package buildinfo 2 3 import ( 4 "errors" 5 commandsutils "github.com/jfrog/jfrog-cli-go/artifactory/commands/utils" 6 "github.com/jfrog/jfrog-cli-go/artifactory/spec" 7 "github.com/jfrog/jfrog-cli-go/artifactory/utils" 8 "github.com/jfrog/jfrog-cli-go/utils/config" 9 "github.com/jfrog/jfrog-client-go/artifactory/buildinfo" 10 "github.com/jfrog/jfrog-client-go/artifactory/services/fspatterns" 11 specutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" 12 clientutils "github.com/jfrog/jfrog-client-go/utils" 13 "github.com/jfrog/jfrog-client-go/utils/errorutils" 14 "github.com/jfrog/jfrog-client-go/utils/io/fileutils" 15 "github.com/jfrog/jfrog-client-go/utils/log" 16 regxp "regexp" 17 "strconv" 18 ) 19 20 type BuildAddDependenciesCommand struct { 21 buildConfiguration *utils.BuildConfiguration 22 dependenciesSpec *spec.SpecFiles 23 dryRun bool 24 result *commandsutils.Result 25 } 26 27 func NewBuildAddDependenciesCommand() *BuildAddDependenciesCommand { 28 return &BuildAddDependenciesCommand{result: new(commandsutils.Result)} 29 } 30 31 func (badc *BuildAddDependenciesCommand) Result() *commandsutils.Result { 32 return badc.result 33 } 34 35 func (badc *BuildAddDependenciesCommand) CommandName() string { 36 return "rt_build_add_dependencies" 37 } 38 39 func (badc *BuildAddDependenciesCommand) RtDetails() (*config.ArtifactoryDetails, error) { 40 return config.GetDefaultArtifactoryConf() 41 } 42 43 func (badc *BuildAddDependenciesCommand) Run() error { 44 log.Info("Running Build Add Dependencies command...") 45 if !badc.dryRun { 46 if err := utils.SaveBuildGeneralDetails(badc.buildConfiguration.BuildName, badc.buildConfiguration.BuildNumber); err != nil { 47 return err 48 } 49 } 50 51 dependenciesPaths, errorOccurred := badc.collectDependenciesBySpec() 52 dependenciesDetails, errorOccurred, failures := collectDependenciesChecksums(dependenciesPaths, errorOccurred) 53 if !badc.dryRun { 54 err := badc.saveDependenciesToFileSystem(dependenciesDetails) 55 if err != nil { 56 errorOccurred = true 57 log.Error(err) 58 // mark all as failures and clean the succeeded 59 failures += len(dependenciesDetails) 60 dependenciesDetails = make(map[string]*fileutils.FileDetails) 61 } 62 } 63 badc.result.SetSuccessCount(len(dependenciesDetails)) 64 badc.result.SetFailCount(failures) 65 if errorOccurred { 66 return errors.New("Build Add Dependencies command finished with errors. Please review the logs.") 67 } 68 return nil 69 } 70 71 func (badc *BuildAddDependenciesCommand) SetDryRun(dryRun bool) *BuildAddDependenciesCommand { 72 badc.dryRun = dryRun 73 return badc 74 } 75 76 func (badc *BuildAddDependenciesCommand) SetDependenciesSpec(dependenciesSpec *spec.SpecFiles) *BuildAddDependenciesCommand { 77 badc.dependenciesSpec = dependenciesSpec 78 return badc 79 } 80 81 func (badc *BuildAddDependenciesCommand) SetBuildConfiguration(buildConfiguration *utils.BuildConfiguration) *BuildAddDependenciesCommand { 82 badc.buildConfiguration = buildConfiguration 83 return badc 84 } 85 86 func collectDependenciesChecksums(dependenciesPaths map[string]string, errorOccurred bool) (map[string]*fileutils.FileDetails, bool, int) { 87 failures := 0 88 dependenciesDetails := make(map[string]*fileutils.FileDetails) 89 for _, dependencyPath := range dependenciesPaths { 90 var details *fileutils.FileDetails 91 var err error 92 if fileutils.IsPathSymlink(dependencyPath) { 93 log.Info("Adding symlink dependency:", dependencyPath) 94 details, err = fspatterns.CreateSymlinkFileDetails() 95 } else { 96 log.Info("Adding dependency:", dependencyPath) 97 details, err = fileutils.GetFileDetails(dependencyPath) 98 } 99 if err != nil { 100 errorOccurred = true 101 log.Error(err) 102 failures++ 103 continue 104 } 105 dependenciesDetails[dependencyPath] = details 106 } 107 return dependenciesDetails, errorOccurred, failures 108 } 109 110 func (badc *BuildAddDependenciesCommand) collectDependenciesBySpec() (map[string]string, bool) { 111 errorOccurred := false 112 dependenciesPaths := make(map[string]string) 113 for _, specFile := range badc.dependenciesSpec.Files { 114 params, err := prepareArtifactoryParams(specFile) 115 if err != nil { 116 errorOccurred = true 117 log.Error(err) 118 continue 119 } 120 paths, err := getDependenciesBySpecFileParams(params) 121 if err != nil { 122 errorOccurred = true 123 log.Error(err) 124 continue 125 } 126 for _, path := range paths { 127 log.Debug("Found matching path:", path) 128 dependenciesPaths[path] = path 129 } 130 } 131 return dependenciesPaths, errorOccurred 132 } 133 134 func prepareArtifactoryParams(specFile spec.File) (*specutils.ArtifactoryCommonParams, error) { 135 params := specFile.ToArtifactoryCommonParams() 136 recursive, err := clientutils.StringToBool(specFile.Recursive, true) 137 if err != nil { 138 return nil, err 139 } 140 141 params.Recursive = recursive 142 regexp, err := clientutils.StringToBool(specFile.Regexp, false) 143 if err != nil { 144 return nil, err 145 } 146 147 params.Regexp = regexp 148 return params, nil 149 } 150 151 func getDependenciesBySpecFileParams(addDepsParams *specutils.ArtifactoryCommonParams) ([]string, error) { 152 addDepsParams.SetPattern(clientutils.ReplaceTildeWithUserHome(addDepsParams.GetPattern())) 153 // Save parentheses index in pattern, witch have corresponding placeholder. 154 rootPath, err := fspatterns.GetRootPath(addDepsParams.GetPattern(), addDepsParams.GetTarget(), addDepsParams.IsRegexp(), false) 155 if err != nil { 156 return nil, err 157 } 158 159 isDir, err := fileutils.IsDirExists(rootPath, false) 160 if err != nil { 161 return nil, err 162 } 163 164 if !isDir || fileutils.IsPathSymlink(addDepsParams.GetPattern()) { 165 artifact, err := fspatterns.GetSingleFileToUpload(rootPath, "", false, false) 166 if err != nil { 167 return nil, err 168 } 169 return []string{artifact.LocalPath}, nil 170 } 171 return collectPatternMatchingFiles(addDepsParams, rootPath) 172 } 173 174 func collectPatternMatchingFiles(addDepsParams *specutils.ArtifactoryCommonParams, rootPath string) ([]string, error) { 175 addDepsParams.SetPattern(clientutils.PrepareLocalPathForUpload(addDepsParams.Pattern, addDepsParams.IsRegexp())) 176 excludePathPattern := fspatterns.PrepareExcludePathPattern(addDepsParams) 177 patternRegex, err := regxp.Compile(addDepsParams.Pattern) 178 if errorutils.CheckError(err) != nil { 179 return nil, err 180 } 181 182 paths, err := fspatterns.GetPaths(rootPath, addDepsParams.IsRecursive(), addDepsParams.IsIncludeDirs(), true) 183 if err != nil { 184 return nil, err 185 } 186 result := []string{} 187 188 for _, path := range paths { 189 matches, _, _, err := fspatterns.PrepareAndFilterPaths(path, excludePathPattern, true, false, patternRegex) 190 if err != nil { 191 log.Error(err) 192 continue 193 } 194 if len(matches) > 0 { 195 result = append(result, path) 196 } 197 } 198 return result, nil 199 } 200 201 func (badc *BuildAddDependenciesCommand) saveDependenciesToFileSystem(files map[string]*fileutils.FileDetails) error { 202 log.Debug("Saving", strconv.Itoa(len(files)), "dependencies.") 203 populateFunc := func(partial *buildinfo.Partial) { 204 partial.Dependencies = convertFileInfoToDependencies(files) 205 } 206 return utils.SavePartialBuildInfo(badc.buildConfiguration.BuildName, badc.buildConfiguration.BuildNumber, populateFunc) 207 } 208 209 func convertFileInfoToDependencies(files map[string]*fileutils.FileDetails) []buildinfo.Dependency { 210 var buildDependencies []buildinfo.Dependency 211 for filePath, fileInfo := range files { 212 dependency := buildinfo.Dependency{Checksum: &buildinfo.Checksum{}} 213 dependency.Md5 = fileInfo.Checksum.Md5 214 dependency.Sha1 = fileInfo.Checksum.Sha1 215 filename, _ := fileutils.GetFileAndDirFromPath(filePath) 216 dependency.Id = filename 217 buildDependencies = append(buildDependencies, dependency) 218 } 219 return buildDependencies 220 }