Skip to content

Commit

Permalink
Leading directories unwantedly preserved with copy/move
Browse files Browse the repository at this point in the history
  • Loading branch information
TamirHadad committed May 14, 2017
1 parent 7fd4f08 commit dd83b0a
Show file tree
Hide file tree
Showing 14 changed files with 352 additions and 244 deletions.
2 changes: 1 addition & 1 deletion artifactory/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ func createDefaultMoveSpec(c *cli.Context) *utils.SpecFiles {
recursive := cliutils.GetBoolFlagValue(c, "recursive", true)
flat := cliutils.GetBoolFlagValue(c, "flat", false)

return utils.CreateSpec(pattern, target, props, build, recursive, flat, false, false)
return utils.CreateSpec(pattern, target, props, build, recursive, flat, false, true)
}

func getMoveSpec(c *cli.Context) (searchSpec *utils.SpecFiles, err error) {
Expand Down
71 changes: 10 additions & 61 deletions artifactory/commands/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/jfrogdev/jfrog-cli-go/utils/config"
"github.com/jfrogdev/jfrog-cli-go/utils/cliutils"
"github.com/jfrogdev/jfrog-cli-go/utils/cliutils/log"
"strings"
"errors"
)

Expand Down Expand Up @@ -36,9 +35,10 @@ func GetPathsToDelete(deleteSpec *utils.SpecFiles, flags *DeleteFlags) ([]utils.
func getPathsToDeleteInternal(deleteSpec *utils.SpecFiles, flags *DeleteFlags) (resultItems []utils.AqlSearchResultItem, err error) {
log.Info("Searching artifacts...")
for i := 0; i < len(deleteSpec.Files); i++ {
currentSpec := deleteSpec.Get(i)
// Search paths using AQL.
if deleteSpec.Get(i).GetSpecType() == utils.AQL {
if resultItemsTemp, e := utils.AqlSearchBySpec(deleteSpec.Get(i), flags); e == nil {
if currentSpec.GetSpecType() == utils.AQL {
if resultItemsTemp, e := utils.AqlSearchBySpec(currentSpec, flags); e == nil {
resultItems = append(resultItems, resultItemsTemp...)
continue
} else {
Expand All @@ -47,36 +47,23 @@ func getPathsToDeleteInternal(deleteSpec *utils.SpecFiles, flags *DeleteFlags) (
}
}
// Simple directory delete, no need to search in Artifactory.
if simpleDir, e := isSimpleDirectoryDelete(deleteSpec.Get(i)); simpleDir && e == nil {
simplePathItem := utils.AqlSearchResultItem{Path:deleteSpec.Get(i).Pattern}
if simpleDir, e := isSimpleDirectoryDelete(currentSpec); simpleDir && e == nil {
simplePathItem := utils.AqlSearchResultItem{Path:currentSpec.Pattern}
resultItems = append(resultItems, []utils.AqlSearchResultItem{simplePathItem}...)
continue
} else if e != nil {
err = e
return
}
// Directory with wildcard pattern, searching with special AQL query.
if directoryDelete, e := isDirectoryDelete(deleteSpec.Get(i)); directoryDelete && e == nil {
query := utils.BuildAqlFolderSearchQuery(deleteSpec.Get(i).Pattern, utils.GetDefaultQueryReturnFields())
tempResultItems, e := utils.AqlSearch(query, flags)
if e != nil {
err = e
return
}
paths := reduceDirResult(tempResultItems)
resultItems = append(resultItems, paths...)
continue
} else if e != nil {
err = e
return
}
// All other use cases, pattern with/without wildcard files.
tempResultItems, e := utils.AqlSearchDefaultReturnFields(deleteSpec.Get(i), flags)

currentSpec.IncludeDirs = "true"
tempResultItems, e := utils.AqlSearchDefaultReturnFields(currentSpec, flags)
if e != nil {
err = e
return
}
resultItems = append(resultItems, tempResultItems...)
paths := utils.ReduceDirResult(tempResultItems)
resultItems = append(resultItems, paths...)
}
utils.LogSearchResults(len(resultItems))
return
Expand All @@ -95,44 +82,6 @@ func isSimpleDirectoryDelete(deleteFile *utils.File) (bool, error) {
return utils.IsSimpleDirectoryPath(deleteFile.Pattern) && isRecursive && deleteFile.Props == "", nil
}

// The diffrence between isSimpleDirectoryDelete to isDirectoryDelete is:
// isDirectoryDelete returns true when the deleteFile path contains wildcatds.
func isDirectoryDelete(deleteFile *utils.File) (bool, error) {
isRecursive, err := cliutils.StringToBool(deleteFile.Recursive, true)
if err != nil {
return false, err
}
return utils.IsDirectoryPath(deleteFile.Pattern) && isRecursive && deleteFile.Props == "", nil
}

// Remove unnecessary paths.
// For example if we have two paths for delete a/b/c/ and a/b/
// it's enough to delete only a/b/
func reduceDirResult(foldersToDelete []utils.AqlSearchResultItem) []utils.AqlSearchResultItem {
paths := make(map[string]utils.AqlSearchResultItem)
for _, file := range foldersToDelete {
if file.Name == "." {
continue
}
paths[file.GetFullUrl()] = file
}

for k := range paths {
for k2 := range paths {
if k != k2 && strings.HasPrefix(k, k2) {
delete(paths, k);
continue
}
}
}
var result []utils.AqlSearchResultItem
for _, v := range paths {
v.Name += "/"
result = append(result, v)
}
return result
}

func DeleteFiles(resultItems []utils.AqlSearchResultItem, flags *DeleteFlags) error {
if err := utils.PreCommandSetup(flags); err != nil {
return err
Expand Down
68 changes: 0 additions & 68 deletions artifactory/commands/delete_test.go

This file was deleted.

12 changes: 6 additions & 6 deletions artifactory/commands/upload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import (

func TestSingleFileUpload(t *testing.T) {
flags := getUploadFlags()
spec := utils.CreateSpec("testdata/a.txt", "repo-local", "", "", false, true, false)
spec := utils.CreateSpec("testdata/a.txt", "repo-local", "", "", false, true, false, false)
uploaded1, _, err := Upload(spec, flags)
checkUploaded(t, uploaded1, err, 1)

spec = utils.CreateSpec("testdata/aa.txt", "repo-local", "", "", false, true, false)
spec = utils.CreateSpec("testdata/aa.txt", "repo-local", "", "", false, true, false, false)
uploaded2, _, err := Upload(spec, flags)
checkUploaded(t, uploaded2, err, 1)

spec = utils.CreateSpec("testdata/aa1*.txt", "repo-local", "", "", false, true, false)
spec = utils.CreateSpec("testdata/aa1*.txt", "repo-local", "", "", false, true, false, false)
uploaded3, _, err := Upload(spec, flags)
checkUploaded(t, uploaded3, err, 0)

Expand All @@ -36,15 +36,15 @@ func TestPatternNonRecursiveUpload(t *testing.T) {

func testPatternUpload(t *testing.T, recursive bool, flags *UploadFlags) {
sep := cliutils.GetTestsFileSeperator()
spec := utils.CreateSpec("testdata" + sep + "*", "repo-local", "", "", recursive, true, false)
spec := utils.CreateSpec("testdata" + sep + "*", "repo-local", "", "", recursive, true, false, false)
uploaded1, _, err := Upload(spec, flags)
checkUploaded(t, uploaded1, err, 3)

spec = utils.CreateSpec("testdata" + sep + "a*", "repo-local", "", "", recursive, true, false)
spec = utils.CreateSpec("testdata" + sep + "a*", "repo-local", "", "", recursive, true, false, false)
uploaded2, _, err := Upload(spec, flags)
checkUploaded(t, uploaded2, err, 2)

spec = utils.CreateSpec("testdata" + sep + "b*", "repo-local", "", "", recursive, true, false)
spec = utils.CreateSpec("testdata" + sep + "b*", "repo-local", "", "", recursive, true, false, false)
uploaded3, _, err := Upload(spec, flags)
checkUploaded(t, uploaded3, err, 1)
}
Expand Down
38 changes: 6 additions & 32 deletions artifactory/utils/aqlquerybuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,6 @@ import (
"github.com/jfrogdev/jfrog-cli-go/utils/cliutils"
)

//Returns an AQL query string to search folders in Artifactory according to the pattern and return fields provided.
func BuildAqlFolderSearchQuery(searchPattern string, aqlReturnFields []string) string {
pairs := createPathFolderPairs(searchPattern)
index := strings.Index(searchPattern, "/")
repo := searchPattern[:index]

size := len(pairs)
json := "{\"repo\": \"" + repo + "\",\"$or\": ["

for i := 0; i < size; i++ {
json += "{" + buildInnerQuery(pairs[i].path, pairs[i].file, "folder") + "}"
if i + 1 < size {
json += ","
}
}

json += "]}"
return "items.find(" + json + ").include(" + buildAqlReturnFieldsString(aqlReturnFields) + ")"
}

// Returns an AQL body string to search file in Artifactory according the the specified arguments requirements.
func createAqlBodyForItem(specFile *File) (string, error) {
var itemType string
Expand All @@ -44,6 +24,7 @@ func createAqlBodyForItem(specFile *File) (string, error) {
}

pairs := createPathFilePairs(searchPattern, recursive)
includeRoot := strings.LastIndex(searchPattern, "/") < 0
size := len(pairs)
propsQuery, err := buildPropsQuery(specFile.Props)
if err != nil {
Expand All @@ -52,10 +33,10 @@ func createAqlBodyForItem(specFile *File) (string, error) {

json := "{\"repo\": \"" + repo + "\"," + propsQuery + "\"$or\": ["
if size == 0 {
json += "{" + buildInnerQuery(".", searchPattern, itemType) + "}"
json += "{" + buildInnerQuery(".", searchPattern, itemType, true) + "}"
} else {
for i := 0; i < size; i++ {
json += "{" + buildInnerQuery(pairs[i].path, pairs[i].file, itemType) + "}"
json += "{" + buildInnerQuery(pairs[i].path, pairs[i].file, itemType, includeRoot) + "}"
if i+1 < size {
json += ","
}
Expand Down Expand Up @@ -114,13 +95,13 @@ func buildPropsQuery(props string) (string, error) {
return query, nil
}

func buildInnerQuery(path, name, itemType string) string {
func buildInnerQuery(path, name, itemType string, includeRoot bool) string {
itemTypeQuery := ""
if itemType != "" {
itemTypeQuery = ",\"type\": {\"$eq\": \"" + itemType + "\"}"
}
nePath := ""
if itemType == "folder" && path == "*" && name == "*" {
if !includeRoot {
nePath = "\"path\": {\"$ne\": \".\"},"
}

Expand Down Expand Up @@ -198,14 +179,7 @@ func createPathFilePairs(pattern string, recursive bool) []PathFilePair {
} else {
path = pattern[:slashIndex]
name = pattern[slashIndex+1:]
if path == "*" {
pairs = append(pairs, PathFilePair{path + "/*", name})
if name == "*" {
return pairs
}
} else {
pairs = append(pairs, PathFilePair{path, name})
}
pairs = append(pairs, PathFilePair{path, name})
}
if !recursive {
return pairs
Expand Down
10 changes: 4 additions & 6 deletions artifactory/utils/aqlquerybuilder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestBuildAqlSearchQueryRecursiveSimple(t *testing.T) {
func TestBuildAqlSearchQueryRecursiveWildcard(t *testing.T) {
specFile := CreateSpec("repo-local2/a*b*c/dd/", "", "", "", true, true, false, false).Files[0]
aqlResult, _ := createAqlBodyForItem(&specFile)
expected := "{\"repo\": \"repo-local2\",\"$or\": [{\"$and\": [{\"path\": {\"$match\": \"a*b*c/dd\"},\"name\": {\"$match\": \"*\"}}]},{\"$and\": [{\"path\": {\"$match\": \"a*b*c/dd/*\"},\"name\": {\"$match\": \"*\"}}]}]}"
expected := "{\"repo\": \"repo-local2\",\"$or\": [{\"$and\": [{\"path\": {\"$match\": \"a*b*c/dd\"},\"path\": {\"$ne\": \".\"},\"name\": {\"$match\": \"*\"}}]},{\"$and\": [{\"path\": {\"$match\": \"a*b*c/dd/*\"},\"path\": {\"$ne\": \".\"},\"name\": {\"$match\": \"*\"}}]}]}"

if aqlResult != expected {
t.Error("Unexpected download AQL query built. \nExpected: " + expected + " \nGot: " + aqlResult)
Expand All @@ -37,7 +37,7 @@ func TestBuildAqlSearchQueryNonRecursiveSimple(t *testing.T) {
func TestBuildAqlSearchQueryNonRecursiveWildcard(t *testing.T) {
specFile := CreateSpec("repo-local2/a*b*c/dd/", "", "", "", false, true, false, false).Files[0]
aqlResult, _ := createAqlBodyForItem(&specFile)
expected := "{\"repo\": \"repo-local2\",\"$or\": [{\"$and\": [{\"path\": {\"$match\": \"a*b*c/dd\"},\"name\": {\"$match\": \"*\"}}]}]}"
expected := "{\"repo\": \"repo-local2\",\"$or\": [{\"$and\": [{\"path\": {\"$match\": \"a*b*c/dd\"},\"path\": {\"$ne\": \".\"},\"name\": {\"$match\": \"*\"}}]}]}"

if aqlResult != expected {
t.Error("Unexpected download AQL query built. \nExpected: " + expected + " \nGot: " + aqlResult)
Expand All @@ -59,12 +59,10 @@ func TestCreatePathFilePairs(t *testing.T) {
validatePathPairs(createPathFilePairs("*/a*/*b*a*", true), pairs, "*/a*/*b*a*", t)
pairs = []PathFilePair{{"*", "*"}}
validatePathPairs(createPathFilePairs("*", true), pairs, "*", t)
pairs = []PathFilePair{{"*/*", "*"}}
pairs = []PathFilePair{{"*", "*"}, {"*/*", "*"}}
validatePathPairs(createPathFilePairs("*/*", true), pairs, "*/*", t)
pairs = []PathFilePair{{"*/*", "a.z"}}
pairs = []PathFilePair{{"*", "a.z"}}
validatePathPairs(createPathFilePairs("*/a.z", true), pairs, "*/a.z", t)
pairs = []PathFilePair{{"*/*", "*"}}
validatePathPairs(createPathFilePairs("*/*", false), pairs, "*/*", t)
pairs = []PathFilePair{{".", "a"}}
validatePathPairs(createPathFilePairs("a", false), pairs, "a", t)
pairs = []PathFilePair{{"", "*"}}
Expand Down
Loading

0 comments on commit dd83b0a

Please sign in to comment.