Skip to content

Commit

Permalink
Support prune empty directories during recursive delete
Browse files Browse the repository at this point in the history
  • Loading branch information
romangurevitch committed Nov 2, 2016
1 parent 8b01530 commit a66ae2b
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 58 deletions.
2 changes: 1 addition & 1 deletion artifactory/commands/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func isDirectoryDelete(deleteFile *utils.Files) (bool, error) {
func getDirsForDeleteFromFilesPaths(deletePattern string, filesToDelete []utils.AqlSearchResultItem) ([]utils.AqlSearchResultItem, error) {
paths := make(map[string]bool)
for _, file := range filesToDelete {
path, err := utils.WilcardToDirsPath(deletePattern, file.GetFullUrl())
path, err := utils.WildcardToDirsPath(deletePattern, file.GetFullUrl())
if err != nil {
return []utils.AqlSearchResultItem{}, err
}
Expand Down
49 changes: 7 additions & 42 deletions artifactory/utils/deleteutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,21 @@ import (
"errors"
)

// Extract folder path form searchResult by matching the deletePattern.
// At first we replace each * with (.*)
// After finding the matching groups we replace each occurrence of (.*) with the correlated group.
func WilcardToDirsPath(deletePattern, searchResult string) (string, error) {
func WildcardToDirsPath(deletePattern, searchResult string) (string, error) {
if !strings.HasSuffix(deletePattern, "/") {
return "", errors.New("Delete pattern must end with \"/\"")
}
tempPattern := strings.Replace(deletePattern, "**", "*", -1)
for deletePattern != tempPattern {
deletePattern = tempPattern
tempPattern = strings.Replace(deletePattern, "**", "*", -1)
}

splitedDeletePattern := strings.Split(deletePattern, "/")
splitedLen := len(splitedDeletePattern)

if splitedLen > 1 && strings.Contains(splitedDeletePattern[splitedLen - 2], "*") && strings.Contains(splitedDeletePattern[splitedLen - 3], "*") {
removedPath := splitedDeletePattern[splitedLen - 2:]
newDeletePattern := strings.Join(splitedDeletePattern[:splitedLen - 2], "/") + "/"
del, e := WilcardToDirsPath(newDeletePattern, searchResult)
if e != nil {
return "", e
}
return WilcardToDirsPath(del + removedPath[0] + "/", searchResult)
}

regexpPattern := cliutils.PathToRegExp(deletePattern)
regexpPattern = strings.Replace(regexpPattern, ".*", "(.*)", -1)
regexpPattern := "^" + strings.Replace(deletePattern, "*", "([^/]*|.*)", -1)
r, err := regexp.Compile(regexpPattern)
cliutils.CheckError(err)
if err != nil {
return "", err
}

groups := r.FindStringSubmatch(searchResult)
result := deletePattern
for i := 1; i < len(groups) - 1; i++ {
// In case the deletePattern ends with * like a/a/a/*/
// We only need the first level of the matching pattern
// for example: if the matching result is b/c/d/e/ the c/d/e/ path is redundant.
if i == (len(groups) - 2) {
splited := strings.Split(result, "/")
if strings.Contains(splited[len(splited) - 2], "*") {
forReplace := strings.Split(groups[i], "/")
result = strings.Replace(result, "*", forReplace[0], 1)
continue
}
result = strings.Replace(result, "*", groups[i], 1)
}
result = strings.Replace(result, "*", groups[i], 1)
if len(groups) > 0 {
return groups[0], nil
}

return result, err
}
return "", nil
}
30 changes: 15 additions & 15 deletions artifactory/utils/deleteutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,35 @@ import (

func TestMatchingDelete(t *testing.T) {
var actual string
actual, _ = WilcardToDirsPath("s/*/path/", "s/a/path/b.zip")
actual, _ = WildcardToDirsPath("s/*/path/", "s/a/path/b.zip")
assertDeletePattern("s/a/path/", actual, t)
actual, _ = WilcardToDirsPath("s/*/path/", "s/a/b/c/path/b.zip")
actual, _ = WildcardToDirsPath("s/*/path/", "s/a/b/c/path/b.zip")
assertDeletePattern("s/a/b/c/path/", actual, t)
actual, _ = WilcardToDirsPath("s/a/*/", "s/a/b/path/b.zip")
actual, _ = WildcardToDirsPath("s/a/*/", "s/a/b/path/b.zip")
assertDeletePattern("s/a/b/", actual, t)
actual, _ = WilcardToDirsPath("s/*/path/*/", "s/a/path/a/b.zip")
actual, _ = WildcardToDirsPath("s/*/path/*/", "s/a/path/a/b.zip")
assertDeletePattern("s/a/path/a/", actual, t)
actual, _ = WilcardToDirsPath("s/*/path/*/", "s/a/a/path/a/b/c/d/b.zip")
actual, _ = WildcardToDirsPath("s/*/path/*/", "s/a/a/path/a/b/c/d/b.zip")
assertDeletePattern("s/a/a/path/a/", actual, t)
actual, _ = WilcardToDirsPath("s/*/", "s/a/a/path/a/b/c/d/b.zip")
actual, _ = WildcardToDirsPath("s/*/", "s/a/a/path/a/b/c/d/b.zip")
assertDeletePattern("s/a/", actual, t)
actual, _ = WilcardToDirsPath("s/*/a/*/", "s/a/a/path/k/b/c/d/b.zip")
actual, _ = WildcardToDirsPath("s/*/a/*/", "s/a/a/path/k/b/c/d/b.zip")
assertDeletePattern("s/a/a/path/", actual, t)
actual, _ = WilcardToDirsPath("s/*/a/*/*/", "s/a/a/path/k/b/c/d/b.zip")
actual, _ = WildcardToDirsPath("s/*/a/*/*/", "s/a/a/path/k/b/c/d/b.zip")
assertDeletePattern("s/a/a/path/k/", actual, t)
actual, _ = WilcardToDirsPath("s/*/*l*/*/*/", "s/a/l/path/k/b/c/d/b.zip")
actual, _ = WildcardToDirsPath("s/*/*l*/*/*/", "s/a/l/path/k/b/c/d/b.zip")
assertDeletePattern("s/a/l/path/k/", actual, t)
actual, _ = WilcardToDirsPath("s/*/a*/", "s/a/a/path/k/b/c/d/b.zip")
actual, _ = WildcardToDirsPath("s/*/a*/", "s/a/a/path/k/b/c/d/b.zip")
assertDeletePattern("s/a/a/", actual, t)
actual, _ = WilcardToDirsPath("s/a*/", "s/a/a/path/k/b/c/d/b.zip")
actual, _ = WildcardToDirsPath("s/a*/", "s/a/a/path/k/b/c/d/b.zip")
assertDeletePattern("s/a/", actual, t)
actual, _ = WilcardToDirsPath("s/*/", "s/a/a/path/k/b/c/d/b.zip")
actual, _ = WildcardToDirsPath("s/*/", "s/a/a/path/k/b/c/d/b.zip")
assertDeletePattern("s/a/", actual, t)
actual, _ = WilcardToDirsPath("s/*/*path*/", "s/a/h/path/k/b/c/d/b.zip")
actual, _ = WildcardToDirsPath("s/*/*path*/", "s/a/h/path/k/b/c/d/b.zip")
assertDeletePattern("s/a/h/path/", actual, t)
actual, _ = WilcardToDirsPath("a/b/*********/*******/", "a/b/c/d/e.zip")
actual, _ = WildcardToDirsPath("a/b/*********/*******/", "a/b/c/d/e.zip")
assertDeletePattern("a/b/c/d/", actual, t)
actual, err := WilcardToDirsPath("s/*/a/*/*", "s/a/a/path/k/b/c/d/b.zip")
actual, err := WildcardToDirsPath("s/*/a/*/*", "s/a/a/path/k/b/c/d/b.zip")
assertDeletePatternErr(err.Error(), "Delete pattern must end with \"/\"", t)
}

Expand Down

0 comments on commit a66ae2b

Please sign in to comment.