@@ -57,7 +57,7 @@ func (f FileInfo) Stat() (fs.FileInfo, error) { return f.FileInfo, nil }
57
57
// archive recursively, rooted at the named directory. They should use the
58
58
// platform's path separator (backslash on Windows; slash on everything else).
59
59
// For convenience, map keys that end in a separator ('/', or '\' on Windows)
60
- // will enumerate contents only without adding the folder itself to the archive.
60
+ // will enumerate contents only, without adding the folder itself to the archive.
61
61
//
62
62
// Map values should typically use slash ('/') as the separator regardless of
63
63
// the platform, as most archive formats standardize on that rune as the
@@ -153,11 +153,24 @@ func nameOnDiskToNameInArchive(nameOnDisk, rootOnDisk, rootInArchive string) str
153
153
// one function is easier to reason about and test. I suspect the performance
154
154
// penalty is insignificant.
155
155
if strings .HasSuffix (rootOnDisk , string (filepath .Separator )) {
156
+ // "map keys that end in a separator will enumerate contents only,
157
+ // without adding the folder itself to the archive."
156
158
rootInArchive = trimTopDir (rootInArchive )
157
159
} else if rootInArchive == "" {
160
+ // "map values that are empty string are interpreted as the base name
161
+ // of the file (sans path) in the root of the archive"
158
162
rootInArchive = filepath .Base (rootOnDisk )
159
163
}
164
+ if rootInArchive == "." {
165
+ // an in-archive root of "." is an escape hatch for the above rule
166
+ // where an empty in-archive root means to use the base name of the
167
+ // file; if the user does not want this, they can specify a "." to
168
+ // still put it in the root of the archive
169
+ rootInArchive = ""
170
+ }
160
171
if strings .HasSuffix (rootInArchive , "/" ) {
172
+ // "map values that end in a slash will use the base name of the file in
173
+ // that folder of the archive."
161
174
rootInArchive += filepath .Base (rootOnDisk )
162
175
}
163
176
truncPath := strings .TrimPrefix (nameOnDisk , rootOnDisk )
@@ -167,27 +180,22 @@ func nameOnDiskToNameInArchive(nameOnDisk, rootOnDisk, rootInArchive string) str
167
180
// trimTopDir strips the top or first directory from the path.
168
181
// It expects a forward-slashed path.
169
182
//
170
- // For example , "a/b/c" => "b/c".
183
+ // Examples: "a/b/c" => "b/c" , "/ a/b/c" => "b/c"
171
184
func trimTopDir (dir string ) string {
172
- if len (dir ) > 0 && dir [0 ] == '/' {
173
- dir = dir [1 :]
174
- }
175
- if pos := strings .Index (dir , "/" ); pos >= 0 {
176
- return dir [pos + 1 :]
177
- }
178
- return dir
185
+ return strings .TrimPrefix (dir , topDir (dir )+ "/" )
179
186
}
180
187
181
188
// topDir returns the top or first directory in the path.
182
189
// It expects a forward-slashed path.
183
190
//
184
- // For example , "a/b/c" => "a".
191
+ // Examples: "a/b/c" => "a" , "/ a/b/c" => "/a"
185
192
func topDir (dir string ) string {
193
+ var start int
186
194
if len (dir ) > 0 && dir [0 ] == '/' {
187
- dir = dir [ 1 :]
195
+ start = 1
188
196
}
189
- if pos := strings .Index (dir , "/" ); pos >= 0 {
190
- return dir [:pos ]
197
+ if pos := strings .Index (dir [ start :] , "/" ); pos >= 0 {
198
+ return dir [:pos + start ]
191
199
}
192
200
return dir
193
201
}
0 commit comments