Keep directories when moving glob results
Patterns containing multiple globs or a recurisve glob may match
files with the same name in multiple directories. Keep the relative
directories of matches after the path entry containing a glob.
Bug: 117295826
Test: zip2zip_test.go
Change-Id: I5d663e546953af374175837551d23f484d568377
diff --git a/cmd/zip2zip/zip2zip.go b/cmd/zip2zip/zip2zip.go
index c4fb3d6..491267b 100644
--- a/cmd/zip2zip/zip2zip.go
+++ b/cmd/zip2zip/zip2zip.go
@@ -148,8 +148,13 @@
} else {
if pathtools.IsGlob(input) {
// If the input is a glob then the output is a directory.
- _, name := filepath.Split(file.Name)
- newName = filepath.Join(output, name)
+ rel, err := filepath.Rel(constantPartOfPattern(input), file.Name)
+ if err != nil {
+ return err
+ } else if strings.HasPrefix("../", rel) {
+ return fmt.Errorf("globbed path %q was not in %q", file.Name, constantPartOfPattern(input))
+ }
+ newName = filepath.Join(output, rel)
} else {
// Otherwise it is a file.
newName = output
@@ -277,3 +282,24 @@
}
return false, nil
}
+
+func constantPartOfPattern(pattern string) string {
+ ret := ""
+ for pattern != "" {
+ var first string
+ first, pattern = splitFirst(pattern)
+ if pathtools.IsGlob(first) {
+ return ret
+ }
+ ret = filepath.Join(ret, first)
+ }
+ return ret
+}
+
+func splitFirst(path string) (string, string) {
+ i := strings.IndexRune(path, filepath.Separator)
+ if i < 0 {
+ return path, ""
+ }
+ return path[:i], path[i+1:]
+}