diff options
author | Russ Cox <rsc@golang.org> | 2023-08-09 23:47:27 -0400 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2023-08-11 17:56:21 +0000 |
commit | 93989514795d8145344262124dde8bce089ff33e (patch) | |
tree | 81ebe32a8a1a2b7bdda7c30fb4f2b36ed6270444 | |
parent | 75d8be5fb4cbc1a539a99557cef93dcdef997bf5 (diff) | |
download | go-93989514795d8145344262124dde8bce089ff33e.tar.gz go-93989514795d8145344262124dde8bce089ff33e.zip |
[release-branch.go1.21] cmd/distpack: include directory entries in tar files
Various tools expect tar files to contain entries for directories.
I dropped them when writing cmd/distpack because they're not
strictly necessary and omitting them saves space, but it also
turns out to break some things, so add them back.
We will backport this to release-branch.go1.21 so that Go 1.21.1
will include the directory entries. We can't do anything about
Go 1.21.0 retroactively.
% tar tzvf go1.22rsc1.src.tar.gz | sed 10q
drwxr-xr-x 0 0 0 0 Aug 10 10:07 go/
-rw-r--r-- 0 0 0 1337 Aug 10 10:07 go/CONTRIBUTING.md
-rw-r--r-- 0 0 0 1479 Aug 10 10:07 go/LICENSE
-rw-r--r-- 0 0 0 1303 Aug 10 10:07 go/PATENTS
-rw-r--r-- 0 0 0 1455 Aug 10 10:07 go/README.md
-rw-r--r-- 0 0 0 419 Aug 10 10:07 go/SECURITY.md
-rw-r--r-- 0 0 0 42 Aug 10 10:07 go/VERSION
drwxr-xr-x 0 0 0 0 Aug 10 10:07 go/api/
-rw-r--r-- 0 0 0 1142 Aug 10 10:07 go/api/README
-rw-r--r-- 0 0 0 35424 Aug 10 10:07 go/api/except.txt
% tar tzvf go1.22rsc1.darwin-amd64.tar.gz | sed 10q
drwxr-xr-x 0 0 0 0 Aug 10 10:07 go/
-rw-r--r-- 0 0 0 1337 Aug 10 10:07 go/CONTRIBUTING.md
-rw-r--r-- 0 0 0 1479 Aug 10 10:07 go/LICENSE
-rw-r--r-- 0 0 0 1303 Aug 10 10:07 go/PATENTS
-rw-r--r-- 0 0 0 1455 Aug 10 10:07 go/README.md
-rw-r--r-- 0 0 0 419 Aug 10 10:07 go/SECURITY.md
-rw-r--r-- 0 0 0 42 Aug 10 10:07 go/VERSION
drwxr-xr-x 0 0 0 0 Aug 10 10:07 go/api/
-rw-r--r-- 0 0 0 1142 Aug 10 10:07 go/api/README
-rw-r--r-- 0 0 0 35424 Aug 10 10:07 go/api/except.txt
%
Fixes #61862.
Fixes #61927.
Change-Id: Iecd9ba893015295e88715b031b79a104236b9ced
Reviewed-on: https://go-review.googlesource.com/c/go/+/518335
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/518835
Auto-Submit: Russ Cox <rsc@golang.org>
-rw-r--r-- | src/cmd/distpack/archive.go | 2 | ||||
-rw-r--r-- | src/cmd/distpack/pack.go | 39 |
2 files changed, 40 insertions, 1 deletions
diff --git a/src/cmd/distpack/archive.go b/src/cmd/distpack/archive.go index f731b3792f..24ed077610 100644 --- a/src/cmd/distpack/archive.go +++ b/src/cmd/distpack/archive.go @@ -44,7 +44,7 @@ type fileInfo struct { func (i fileInfo) Name() string { return path.Base(i.f.Name) } func (i fileInfo) ModTime() time.Time { return i.f.Time } func (i fileInfo) Mode() fs.FileMode { return i.f.Mode } -func (i fileInfo) IsDir() bool { return false } +func (i fileInfo) IsDir() bool { return i.f.Mode&fs.ModeDir != 0 } func (i fileInfo) Size() int64 { return i.f.Size } func (i fileInfo) Sys() any { return nil } diff --git a/src/cmd/distpack/pack.go b/src/cmd/distpack/pack.go index e8b5255e63..cf507edb4d 100644 --- a/src/cmd/distpack/pack.go +++ b/src/cmd/distpack/pack.go @@ -329,8 +329,47 @@ func writeTgz(name string, a *Archive) { zw := check(gzip.NewWriterLevel(out, gzip.BestCompression)) tw := tar.NewWriter(zw) + + // Find the mode and mtime to use for directory entries, + // based on the mode and mtime of the first file we see. + // We know that modes and mtimes are uniform across the archive. + var dirMode fs.FileMode + var mtime time.Time + for _, f := range a.Files { + dirMode = fs.ModeDir | f.Mode | (f.Mode&0444)>>2 // copy r bits down to x bits + mtime = f.Time + break + } + + // mkdirAll ensures that the tar file contains directory + // entries for dir and all its parents. Some programs reading + // these tar files expect that. See go.dev/issue/61862. + haveDir := map[string]bool{".": true} + var mkdirAll func(string) + mkdirAll = func(dir string) { + if dir == "/" { + panic("mkdirAll /") + } + if haveDir[dir] { + return + } + haveDir[dir] = true + mkdirAll(path.Dir(dir)) + df := &File{ + Name: dir + "/", + Time: mtime, + Mode: dirMode, + } + h := check(tar.FileInfoHeader(df.Info(), "")) + h.Name = dir + "/" + if err := tw.WriteHeader(h); err != nil { + panic(err) + } + } + for _, f = range a.Files { h := check(tar.FileInfoHeader(f.Info(), "")) + mkdirAll(path.Dir(f.Name)) h.Name = f.Name if err := tw.WriteHeader(h); err != nil { panic(err) |