Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 714614ce authored by Colin Cross's avatar Colin Cross
Browse files

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
parent c29e55d4
Loading
Loading
Loading
Loading
+28 −2
Original line number Diff line number Diff line
@@ -148,8 +148,13 @@ func zip2zip(reader *zip.Reader, writer *zip.Writer, sortOutput, sortJava, setTi
				} 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 @@ func (m *multiFlag) Match(s string) (bool, error) {
	}
	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:]
}
+96 −0
Original line number Diff line number Diff line
@@ -352,6 +352,60 @@ var testCases = []struct {
			"a/b",
		},
	},
	{
		name: "recursive glob",

		inputFiles: []string{
			"a/a/a",
			"a/a/b",
		},
		args: []string{"a/**/*:b"},
		outputFiles: []string{
			"b/a/a",
			"b/a/b",
		},
	},
	{
		name: "glob",

		inputFiles: []string{
			"a/a/a",
			"a/a/b",
			"a/b",
			"a/c",
		},
		args: []string{"a/*:b"},
		outputFiles: []string{
			"b/b",
			"b/c",
		},
	},
	{
		name: "top level glob",

		inputFiles: []string{
			"a",
			"b",
		},
		args: []string{"*:b"},
		outputFiles: []string{
			"b/a",
			"b/b",
		},
	},
	{
		name: "multilple glob",

		inputFiles: []string{
			"a/a/a",
			"a/a/b",
		},
		args: []string{"a/*/*:b"},
		outputFiles: []string{
			"b/a/a",
			"b/a/b",
		},
	},
}

func errorString(e error) string {
@@ -416,3 +470,45 @@ func TestZip2Zip(t *testing.T) {
		})
	}
}

func TestConstantPartOfPattern(t *testing.T) {
	testCases := []struct{ in, out string }{
		{
			in:  "",
			out: "",
		},
		{
			in:  "a",
			out: "a",
		},
		{
			in:  "*",
			out: "",
		},
		{
			in:  "a/a",
			out: "a/a",
		},
		{
			in:  "a/*",
			out: "a",
		},
		{
			in:  "a/*/a",
			out: "a",
		},
		{
			in:  "a/**/*",
			out: "a",
		},
	}

	for _, test := range testCases {
		t.Run(test.in, func(t *testing.T) {
			got := constantPartOfPattern(test.in)
			if got != test.out {
				t.Errorf("want %q, got %q", test.out, got)
			}
		})
	}
}