The code was sorting files in the archives entirely by path string,
but that's not what fs.WalkDir would do. In a directory with
subdirectory foo/bar and file foo/bar.go, foo/bar gets visited
first, so foo/bar/baz appears before foo/bar.go, even though
"foo/bar/baz" > "foo/bar.go".
This CL replaces the string comparison with a path-aware
comparison that places foo/bar/baz before foo/bar.go,
so that if the tar file is extracted and then repacked using
fs.WalkDir, the files will remain in the same order.
This will make it easier to compare the pristine distpack-produced
tgz for darwin against the rebuilt tgz with signed binaries.
Before:
% tar tzvf /tmp/cmddist.tgz | grep -C1 runtime/cgo.go
-rw-r--r-- 0 0 0 11122 Jul 13 15:00 go/src/runtime/callers_test.go
-rw-r--r-- 0 0 0 2416 Jul 13 15:00 go/src/runtime/cgo.go
-rw-r--r-- 0 0 0 2795 Jul 13 15:00 go/src/runtime/cgo/abi_amd64.h
After:
% tar tzvf pkg/distpack/go1.21rsc.src.tar.gz | grep -C1 runtime/cgo.go
-rw-r--r-- 0 0 0 1848 Dec 31 1969 go/src/runtime/cgo/signal_ios_arm64.s
-rw-r--r-- 0 0 0 2416 Dec 31 1969 go/src/runtime/cgo.go
-rw-r--r-- 0 0 0 2479 Dec 31 1969 go/src/runtime/cgo_mmap.go
For #24904.
For #61513.
Change-Id: Ib7374bc0d6324377f81c561bef57fd87b2111b98
Reviewed-on: https://go-review.googlesource.com/c/go/+/511977
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
})
}
+func nameLess(x, y string) bool {
+ for i := 0; i < len(x) && i < len(y); i++ {
+ if x[i] != y[i] {
+ // foo/bar/baz before foo/bar.go, because foo/bar is before foo/bar.go
+ if x[i] == '/' {
+ return true
+ }
+ if y[i] == '/' {
+ return false
+ }
+ return x[i] < y[i]
+ }
+ }
+ return len(x) < len(y)
+}
+
// Sort sorts the files in the archive.
// It is only necessary to call Sort after calling Add or RenameGoMod.
-// ArchiveDir returns a sorted archive, and the other methods
+// NewArchive returns a sorted archive, and the other methods
// preserve the sorting of the archive.
func (a *Archive) Sort() {
sort.Slice(a.Files, func(i, j int) bool {
- return a.Files[i].Name < a.Files[j].Name
+ return nameLess(a.Files[i].Name, a.Files[j].Name)
})
}