diff --git a/zip/cmd/main.go b/zip/cmd/main.go index def76aa62..a2ccc2011 100644 --- a/zip/cmd/main.go +++ b/zip/cmd/main.go @@ -78,6 +78,15 @@ func (rspFiles) Set(s string) error { return nil } +type explicitFile struct{} + +func (explicitFile) String() string { return `""` } + +func (explicitFile) Set(s string) error { + fileArgsBuilder.ExplicitPathInZip(s) + return nil +} + type dir struct{} func (dir) String() string { return `""` } @@ -173,6 +182,7 @@ func main() { flags.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression") flags.Var(&relativeRoot{}, "C", "path to use as relative root of files in following -f, -l, or -D arguments") flags.Var(&junkPaths{}, "j", "junk paths, zip files without directory names") + flags.Var(&explicitFile{}, "e", "filename to use in the zip file for the next -f argument") flags.Parse(expandedArgs[1:]) diff --git a/zip/zip.go b/zip/zip.go index 6f1a8adaf..5e1a10462 100644 --- a/zip/zip.go +++ b/zip/zip.go @@ -80,6 +80,7 @@ type pathMapping struct { type FileArg struct { PathPrefixInZip, SourcePrefixToStrip string + ExplicitPathInZip string SourceFiles []string JunkPaths bool GlobDir string @@ -124,6 +125,10 @@ func (b *FileArgsBuilder) File(name string) *FileArgsBuilder { arg := b.state arg.SourceFiles = []string{name} b.fileArgs = append(b.fileArgs, arg) + + if b.state.ExplicitPathInZip != "" { + b.state.ExplicitPathInZip = "" + } return b } @@ -189,6 +194,12 @@ func (b *FileArgsBuilder) RspFile(name string) *FileArgsBuilder { return b } +// ExplicitPathInZip sets the path in the zip file for the next File call. +func (b *FileArgsBuilder) ExplicitPathInZip(s string) *FileArgsBuilder { + b.state.ExplicitPathInZip = s + return b +} + func (b *FileArgsBuilder) Error() error { if b == nil { return nil @@ -425,7 +436,9 @@ func fillPathPairs(fa FileArg, src string, pathMappings *[]pathMapping, var dest string - if fa.JunkPaths { + if fa.ExplicitPathInZip != "" { + dest = fa.ExplicitPathInZip + } else if fa.JunkPaths { dest = filepath.Base(src) } else { var err error diff --git a/zip/zip_test.go b/zip/zip_test.go index e7fdea839..c64c3f499 100644 --- a/zip/zip_test.go +++ b/zip/zip_test.go @@ -454,6 +454,60 @@ func TestZip(t *testing.T) { fhWithSHA256("c", fileC, zip.Deflate, sha256FileC), }, }, + { + name: "explicit path", + args: fileArgsBuilder(). + ExplicitPathInZip("foo"). + File("a/a/a"). + File("a/a/b"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("foo", fileA, zip.Deflate), + fh("a/a/b", fileB, zip.Deflate), + }, + }, + { + name: "explicit path with prefix", + args: fileArgsBuilder(). + PathPrefixInZip("prefix"). + ExplicitPathInZip("foo"). + File("a/a/a"). + File("a/a/b"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("prefix/foo", fileA, zip.Deflate), + fh("prefix/a/a/b", fileB, zip.Deflate), + }, + }, + { + name: "explicit path with glob", + args: fileArgsBuilder(). + ExplicitPathInZip("foo"). + File("a/a/a*"). + File("a/a/b"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("foo", fileA, zip.Deflate), + fh("a/a/b", fileB, zip.Deflate), + }, + }, + { + name: "explicit path with junk paths", + args: fileArgsBuilder(). + JunkPaths(true). + ExplicitPathInZip("foo/bar"). + File("a/a/a*"). + File("a/a/b"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("foo/bar", fileA, zip.Deflate), + fh("b", fileB, zip.Deflate), + }, + }, // errors { @@ -490,6 +544,22 @@ func TestZip(t *testing.T) { File("d/a/a"), err: ConflictingFileError{}, }, + { + name: "error explicit path conflicting", + args: fileArgsBuilder(). + ExplicitPathInZip("foo"). + File("a/a/a"). + ExplicitPathInZip("foo"). + File("a/a/b"), + err: ConflictingFileError{}, + }, + { + name: "error explicit path conflicting glob", + args: fileArgsBuilder(). + ExplicitPathInZip("foo"). + File("a/a/*"), + err: ConflictingFileError{}, + }, } for _, test := range testCases {