github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/artifactory/commands/generic/upload.go (about) 1 package generic 2 3 import ( 4 "errors" 5 "github.com/jfrog/jfrog-cli-go/artifactory/spec" 6 "github.com/jfrog/jfrog-cli-go/artifactory/utils" 7 "github.com/jfrog/jfrog-cli-go/utils/cliutils" 8 "github.com/jfrog/jfrog-cli-go/utils/progressbar" 9 "github.com/jfrog/jfrog-client-go/artifactory/buildinfo" 10 "github.com/jfrog/jfrog-client-go/artifactory/services" 11 clientutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" 12 "github.com/jfrog/jfrog-client-go/utils/errorutils" 13 ioUtils "github.com/jfrog/jfrog-client-go/utils/io" 14 "github.com/jfrog/jfrog-client-go/utils/log" 15 "os" 16 "strconv" 17 "strings" 18 "time" 19 ) 20 21 type UploadCommand struct { 22 GenericCommand 23 uploadConfiguration *utils.UploadConfiguration 24 buildConfiguration *utils.BuildConfiguration 25 logFile *os.File 26 } 27 28 func NewUploadCommand() *UploadCommand { 29 return &UploadCommand{GenericCommand: *NewGenericCommand()} 30 } 31 32 func (uc *UploadCommand) LogFile() *os.File { 33 return uc.logFile 34 } 35 36 func (uc *UploadCommand) SetBuildConfiguration(buildConfiguration *utils.BuildConfiguration) *UploadCommand { 37 uc.buildConfiguration = buildConfiguration 38 return uc 39 } 40 41 func (uc *UploadCommand) UploadConfiguration() *utils.UploadConfiguration { 42 return uc.uploadConfiguration 43 } 44 45 func (uc *UploadCommand) SetUploadConfiguration(uploadConfiguration *utils.UploadConfiguration) *UploadCommand { 46 uc.uploadConfiguration = uploadConfiguration 47 return uc 48 } 49 50 func (uc *UploadCommand) CommandName() string { 51 return "rt_upload" 52 } 53 54 func (uc *UploadCommand) Run() error { 55 return uc.upload() 56 } 57 58 // Uploads the artifacts in the specified local path pattern to the specified target path. 59 // Returns the total number of artifacts successfully uploaded. 60 func (uc *UploadCommand) upload() error { 61 // In case of sync-delete get the user to confirm first, and save the operation timestamp. 62 syncDeletesProp := "" 63 if !uc.DryRun() && uc.SyncDeletesPath() != "" { 64 if !uc.Quiet() && !cliutils.InteractiveConfirm("Sync-deletes may delete some artifacts in Artifactory. Are you sure you want to continue?\n"+ 65 "You can avoid this confirmation message by adding --quiet to the command.") { 66 return nil 67 } 68 timestamp := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10) 69 syncDeletesProp = ";sync.deletes.timestamp=" + timestamp 70 } 71 // Initialize Progress bar, set logger to a log file 72 var err error 73 var progressBar ioUtils.Progress 74 addVcsProps := false 75 progressBar, uc.logFile, err = progressbar.InitProgressBarIfPossible() 76 if err != nil { 77 return err 78 } 79 if progressBar != nil { 80 defer progressBar.Quit() 81 } 82 83 // Create Service Manager: 84 uc.uploadConfiguration.MinChecksumDeploySize, err = getMinChecksumDeploySize() 85 if err != nil { 86 return err 87 } 88 rtDetails, err := uc.RtDetails() 89 if errorutils.CheckError(err) != nil { 90 return err 91 } 92 servicesManager, err := utils.CreateUploadServiceManager(rtDetails, uc.uploadConfiguration.Threads, uc.DryRun(), progressBar) 93 if err != nil { 94 return err 95 } 96 97 // Build Info Collection: 98 isCollectBuildInfo := len(uc.buildConfiguration.BuildName) > 0 && len(uc.buildConfiguration.BuildNumber) > 0 99 if isCollectBuildInfo && !uc.DryRun() { 100 addVcsProps = true 101 if err := utils.SaveBuildGeneralDetails(uc.buildConfiguration.BuildName, uc.buildConfiguration.BuildNumber); err != nil { 102 return err 103 } 104 for i := 0; i < len(uc.Spec().Files); i++ { 105 addBuildProps(&uc.Spec().Get(i).Props, uc.buildConfiguration.BuildName, uc.buildConfiguration.BuildNumber) 106 } 107 } 108 109 var errorOccurred = false 110 var uploadParamsArray []services.UploadParams 111 // Create UploadParams for all File-Spec groups. 112 for i := 0; i < len(uc.Spec().Files); i++ { 113 file := uc.Spec().Get(i) 114 file.Props += syncDeletesProp 115 uploadParams, err := getUploadParams(file, uc.uploadConfiguration, addVcsProps) 116 if err != nil { 117 errorOccurred = true 118 log.Error(err) 119 continue 120 } 121 uploadParamsArray = append(uploadParamsArray, uploadParams) 122 } 123 124 // Perform upload. 125 filesInfo, successCount, failCount, err := servicesManager.UploadFiles(uploadParamsArray...) 126 if err != nil { 127 errorOccurred = true 128 log.Error(err) 129 } 130 result := uc.Result() 131 result.SetSuccessCount(successCount) 132 result.SetFailCount(failCount) 133 if errorOccurred { 134 err = errors.New("Upload finished with errors, Please review the logs.") 135 return err 136 } 137 if failCount > 0 { 138 return err 139 } 140 141 if !uc.DryRun() { 142 // Handle sync-deletes 143 if uc.SyncDeletesPath() != "" { 144 err = uc.handleSyncDeletes(syncDeletesProp) 145 if err != nil { 146 return err 147 } 148 } 149 // Build Info 150 if isCollectBuildInfo { 151 buildArtifacts := convertFileInfoToBuildArtifacts(filesInfo) 152 populateFunc := func(partial *buildinfo.Partial) { 153 partial.Artifacts = buildArtifacts 154 partial.ModuleId = uc.buildConfiguration.Module 155 } 156 err = utils.SavePartialBuildInfo(uc.buildConfiguration.BuildName, uc.buildConfiguration.BuildNumber, populateFunc) 157 } 158 } 159 return err 160 } 161 162 func convertFileInfoToBuildArtifacts(filesInfo []clientutils.FileInfo) []buildinfo.Artifact { 163 buildArtifacts := make([]buildinfo.Artifact, len(filesInfo)) 164 for i, fileInfo := range filesInfo { 165 buildArtifacts[i] = fileInfo.ToBuildArtifacts() 166 } 167 return buildArtifacts 168 } 169 170 func getMinChecksumDeploySize() (int64, error) { 171 minChecksumDeploySize := os.Getenv("JFROG_CLI_MIN_CHECKSUM_DEPLOY_SIZE_KB") 172 if minChecksumDeploySize == "" { 173 return 10240, nil 174 } 175 minSize, err := strconv.ParseInt(minChecksumDeploySize, 10, 64) 176 err = errorutils.CheckError(err) 177 if err != nil { 178 return 0, err 179 } 180 return minSize * 1000, nil 181 } 182 183 func addBuildProps(props *string, buildName, buildNumber string) error { 184 if buildName == "" || buildNumber == "" { 185 return nil 186 } 187 buildProps, err := utils.CreateBuildProperties(buildName, buildNumber) 188 if err != nil { 189 return err 190 } 191 192 if len(*props) > 0 && !strings.HasSuffix(*props, ";") && len(buildProps) > 0 { 193 *props += ";" 194 } 195 *props += buildProps 196 return nil 197 } 198 199 func getUploadParams(f *spec.File, configuration *utils.UploadConfiguration, addVcsProps bool) (uploadParams services.UploadParams, err error) { 200 uploadParams = services.NewUploadParams() 201 uploadParams.ArtifactoryCommonParams = f.ToArtifactoryCommonParams() 202 uploadParams.Deb = configuration.Deb 203 uploadParams.Symlink = configuration.Symlink 204 uploadParams.MinChecksumDeploy = configuration.MinChecksumDeploySize 205 uploadParams.AddVcsProps = addVcsProps 206 207 uploadParams.Recursive, err = f.IsRecursive(true) 208 if err != nil { 209 return 210 } 211 212 uploadParams.Regexp, err = f.IsRegexp(false) 213 if err != nil { 214 return 215 } 216 217 uploadParams.IncludeDirs, err = f.IsIncludeDirs(false) 218 if err != nil { 219 return 220 } 221 222 uploadParams.Flat, err = f.IsFlat(true) 223 if err != nil { 224 return 225 } 226 227 uploadParams.ExplodeArchive, err = f.IsExplode(false) 228 if err != nil { 229 return 230 } 231 232 return 233 } 234 235 func (uc *UploadCommand) handleSyncDeletes(syncDeletesProp string) error { 236 servicesManager, err := utils.CreateServiceManager(uc.rtDetails, false) 237 if err != nil { 238 return err 239 } 240 deleteSpec := createDeleteSpecForSync(uc.SyncDeletesPath(), syncDeletesProp) 241 deleteParams, err := getDeleteParams(deleteSpec.Get(0)) 242 if err != nil { 243 return err 244 } 245 resultItems, err := servicesManager.GetPathsToDelete(deleteParams) 246 if err != nil { 247 return err 248 } 249 _, err = servicesManager.DeleteFiles(resultItems) 250 return err 251 } 252 253 func createDeleteSpecForSync(deletePattern string, syncDeletesProp string) *spec.SpecFiles { 254 return spec.NewBuilder(). 255 Pattern(deletePattern). 256 ExcludeProps(syncDeletesProp). 257 Recursive(true). 258 BuildSpec() 259 }