github.com/osievert/jfrog-cli-core@v1.2.7/artifactory/commands/generic/delete.go (about) 1 package generic 2 3 import ( 4 "github.com/jfrog/jfrog-cli-core/artifactory/spec" 5 "github.com/jfrog/jfrog-cli-core/artifactory/utils" 6 "github.com/jfrog/jfrog-client-go/artifactory/services" 7 clientutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" 8 "github.com/jfrog/jfrog-client-go/utils/errorutils" 9 "github.com/jfrog/jfrog-client-go/utils/io/content" 10 ) 11 12 type DeleteCommand struct { 13 GenericCommand 14 quiet bool 15 threads int 16 } 17 18 func NewDeleteCommand() *DeleteCommand { 19 return &DeleteCommand{GenericCommand: *NewGenericCommand()} 20 } 21 22 func (dc *DeleteCommand) Threads() int { 23 return dc.threads 24 } 25 26 func (dc *DeleteCommand) SetThreads(threads int) *DeleteCommand { 27 dc.threads = threads 28 return dc 29 } 30 31 func (dc *DeleteCommand) Quiet() bool { 32 return dc.quiet 33 } 34 35 func (dc *DeleteCommand) SetQuiet(quiet bool) *DeleteCommand { 36 dc.quiet = quiet 37 return dc 38 } 39 40 func (dc *DeleteCommand) CommandName() string { 41 return "rt_delete" 42 } 43 44 func (dc *DeleteCommand) Run() error { 45 reader, err := dc.GetPathsToDelete() 46 if err != nil { 47 return err 48 } 49 defer reader.Close() 50 allowDelete := true 51 if !dc.quiet { 52 allowDelete, err = utils.ConfirmDelete(reader) 53 if err != nil { 54 return err 55 } 56 } 57 if allowDelete { 58 success, failed, err := dc.DeleteFiles(reader) 59 result := dc.Result() 60 result.SetFailCount(failed) 61 result.SetSuccessCount(success) 62 return err 63 } 64 return nil 65 } 66 67 func (dc *DeleteCommand) GetPathsToDelete() (*content.ContentReader, error) { 68 rtDetails, err := dc.RtDetails() 69 if errorutils.CheckError(err) != nil { 70 return nil, err 71 } 72 servicesManager, err := utils.CreateServiceManager(rtDetails, dc.DryRun()) 73 if err != nil { 74 return nil, err 75 } 76 temp := []*content.ContentReader{} 77 defer func() { 78 for _, reader := range temp { 79 reader.Close() 80 } 81 }() 82 for i := 0; i < len(dc.Spec().Files); i++ { 83 deleteParams, err := getDeleteParams(dc.Spec().Get(i)) 84 if err != nil { 85 return nil, err 86 } 87 reader, err := servicesManager.GetPathsToDelete(deleteParams) 88 if err != nil { 89 return nil, err 90 } 91 temp = append(temp, reader) 92 } 93 tempMergedReader, err := content.MergeReaders(temp, content.DefaultKey) 94 if err != nil { 95 return nil, err 96 } 97 defer tempMergedReader.Close() 98 99 // After merge, remove top chain dirs as we may encounter duplicates and collisions between files and directories to delete. 100 // For example: 101 // Reader1: {"a"} 102 // Reader2: {"a/b","a/c"} 103 // After merge, received a Reader: {"a","a/b","a/c"}. 104 // If "a" is deleted prior to "a/b" or "a/c", the delete operation returns a failure. 105 return clientutils.ReduceTopChainDirResult(clientutils.ResultItem{}, tempMergedReader) 106 } 107 108 func (dc *DeleteCommand) DeleteFiles(reader *content.ContentReader) (successCount, failedCount int, err error) { 109 rtDetails, err := dc.RtDetails() 110 if errorutils.CheckError(err) != nil { 111 return 0, 0, err 112 } 113 servicesManager, err := utils.CreateDeleteServiceManager(rtDetails, dc.Threads(), dc.DryRun()) 114 if err != nil { 115 return 0, 0, err 116 } 117 deletedCount, err := servicesManager.DeleteFiles(reader) 118 length, err := reader.Length() 119 if err != nil { 120 return 0, 0, err 121 } 122 return deletedCount, length - deletedCount, err 123 } 124 125 func getDeleteParams(f *spec.File) (deleteParams services.DeleteParams, err error) { 126 deleteParams = services.NewDeleteParams() 127 deleteParams.ArtifactoryCommonParams = f.ToArtifactoryCommonParams() 128 deleteParams.ExcludeArtifacts, err = f.IsExcludeArtifacts(false) 129 if err != nil { 130 return 131 } 132 deleteParams.IncludeDeps, err = f.IsIncludeDeps(false) 133 if err != nil { 134 return 135 } 136 deleteParams.Recursive, err = f.IsRecursive(true) 137 return 138 }