From 3afa5daabd6245be0c03b6e666f93835e32d7f7c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 21 Jul 2023 13:31:10 -0400 Subject: [PATCH] cmd/distpack: sort files in standard walk order 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 Reviewed-by: Heschi Kreinick Run-TryBot: Russ Cox TryBot-Result: Gopher Robot --- src/cmd/distpack/archive.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/cmd/distpack/archive.go b/src/cmd/distpack/archive.go index f731b3792f..8245381f90 100644 --- a/src/cmd/distpack/archive.go +++ b/src/cmd/distpack/archive.go @@ -91,13 +91,29 @@ func (a *Archive) Add(name, src string, info fs.FileInfo) { }) } +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) }) }