Make an archive's digest independent of the umask of the account that packs it (issue 1589)

This commit is contained in:
2026-10-21 09:49:13 +00:00
parent d7e6074d97
commit ef154705b9
2 changed files with 20 additions and 2 deletions
@@ -99,7 +99,12 @@ func (m *Module) pinnedArchive(ctx context.Context, workspace, module string, ar
if err != nil {
return nil, err
}
if err := os.WriteFile(filepath.Join(laid, art.File), body, 0o644); err != nil {
kept := filepath.Join(laid, art.File)
if err := os.WriteFile(kept, body, 0o644); err != nil {
return nil, err
}
// The mode is the archive's, never the account's umask: the digest is the same on every build node.
if err := os.Chmod(kept, 0o644); err != nil {
return nil, err
}
} else if err := unpackUpstream(file, laid, art.Within); err != nil {
@@ -274,6 +279,10 @@ func untar(stream io.Reader, into, within string) error {
if err != nil {
return err
}
if err := out.Chmod(mode); err != nil {
out.Close()
return err
}
if _, err := io.Copy(out, io.LimitReader(reader, header.Size)); err != nil {
out.Close()
return err
@@ -43,7 +43,16 @@ func copyTree(t *testing.T, from, to string) {
if err != nil {
return err
}
return os.WriteFile(target, body, info.Mode().Perm())
// The modes a checkout gives depend on the umask of whoever checked it out; the fixture's are its executable bit
// alone, as git records it, so the digest does not depend on the machine the test runs on.
mode := os.FileMode(0o644)
if info.Mode().Perm()&0o100 != 0 {
mode = 0o755
}
if err := os.WriteFile(target, body, mode); err != nil {
return err
}
return os.Chmod(target, mode)
})
if err != nil {
t.Fatal(err)