Skip to content

Commit

Permalink
archive: use 1970-01-01 as the whiteout timestamp
Browse files Browse the repository at this point in the history
The whiteout timestamps are no longer set to the source date epoch.
The source date epoch still applies to non-whiteout files.

Discussion happened in moby/buildkit PR 3560.

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
  • Loading branch information
AkihiroSuda committed Jun 30, 2023
1 parent a542a57 commit 5dedb6d
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 19 deletions.
5 changes: 4 additions & 1 deletion api/services/diff/v1/diff.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion api/services/diff/v1/diff.proto
Expand Up @@ -74,8 +74,11 @@ message DiffRequest {
// on content store commit.
map<string, string> labels = 5;

// SourceDateEpoch specifies the timestamp used for whiteouts to provide control for reproducibility.
// SourceDateEpoch specifies the timestamp used to provide control for reproducibility.
// See also https://reproducible-builds.org/docs/source-date-epoch/ .
//
// Since containerd v2.0, the whiteout timestamps are set to zero (1970-01-01),
// not to the source date epoch.
google.protobuf.Timestamp source_date_epoch = 6;
}

Expand Down
24 changes: 9 additions & 15 deletions archive/tar.go
Expand Up @@ -103,9 +103,9 @@ func WriteDiff(ctx context.Context, w io.Writer, a, b string, opts ...WriteDiffO
func writeDiffNaive(ctx context.Context, w io.Writer, a, b string, o WriteDiffOptions) error {
var opts []ChangeWriterOpt
if o.SourceDateEpoch != nil {
opts = append(opts,
WithModTimeUpperBound(*o.SourceDateEpoch),
WithWhiteoutTime(*o.SourceDateEpoch))
opts = append(opts, WithModTimeUpperBound(*o.SourceDateEpoch))
// Since containerd v2.0, the whiteout timestamps are set to zero (1970-01-01),
// not to the source date epoch
}
cw := NewChangeWriter(w, b, opts...)
err := fs.Changes(ctx, a, b, cw.HandleChange)
Expand Down Expand Up @@ -505,7 +505,6 @@ type ChangeWriter struct {
tw *tar.Writer
source string
modTimeUpperBound *time.Time
whiteoutT time.Time
inodeSrc map[uint64]string
inodeRefs map[uint64][]string
addedDirs map[string]struct{}
Expand All @@ -521,21 +520,13 @@ func WithModTimeUpperBound(tm time.Time) ChangeWriterOpt {
}
}

// WithWhiteoutTime sets the whiteout timestamp.
func WithWhiteoutTime(tm time.Time) ChangeWriterOpt {
return func(cw *ChangeWriter) {
cw.whiteoutT = tm
}
}

// NewChangeWriter returns ChangeWriter that writes tar stream of the source directory
// to the privided writer. Change information (add/modify/delete/unmodified) for each
// file needs to be passed through HandleChange method.
func NewChangeWriter(w io.Writer, source string, opts ...ChangeWriterOpt) *ChangeWriter {
cw := &ChangeWriter{
tw: tar.NewWriter(w),
source: source,
whiteoutT: time.Now(), // can be overridden with WithWhiteoutTime(time.Time) ChangeWriterOpt .
inodeSrc: map[uint64]string{},
inodeRefs: map[uint64][]string{},
addedDirs: map[string]struct{}{},
Expand All @@ -557,13 +548,16 @@ func (cw *ChangeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e
whiteOutDir := filepath.Dir(p)
whiteOutBase := filepath.Base(p)
whiteOut := filepath.Join(whiteOutDir, whiteoutPrefix+whiteOutBase)
// Since containerd v2.0, the whiteout timestamps are set to zero (1970-01-01),
// not to the source date epoch.
whiteOutT := time.Unix(0, 0).UTC()
hdr := &tar.Header{
Typeflag: tar.TypeReg,
Name: whiteOut[1:],
Size: 0,
ModTime: cw.whiteoutT,
AccessTime: cw.whiteoutT,
ChangeTime: cw.whiteoutT,
ModTime: whiteOutT,
AccessTime: whiteOutT,
ChangeTime: whiteOutT,
}
if err := cw.includeParents(hdr); err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion archive/tar_test.go
Expand Up @@ -1176,7 +1176,7 @@ func TestSourceDateEpoch(t *testing.T) {

opts := []WriteDiffOpt{WithSourceDateEpoch(&sourceDateEpoch)}
validators := []tarEntryValidator{
composeValidators(whiteoutEntry("f1"), requireModTime(sourceDateEpoch)),
composeValidators(whiteoutEntry("f1"), requireModTime(time.Unix(0, 0).UTC())), // not sourceDateEpoch
composeValidators(fileEntry("f2", []byte("content2"), 0644), requireModTime(past)),
composeValidators(fileEntry("f3", []byte("content3"), 0644), requireModTime(sourceDateEpoch)),
}
Expand Down
5 changes: 4 additions & 1 deletion diff/diff.go
Expand Up @@ -125,8 +125,11 @@ func WithPayloads(payloads map[string]typeurl.Any) ApplyOpt {
}
}

// WithSourceDateEpoch specifies the timestamp used for whiteouts to provide control for reproducibility.
// WithSourceDateEpoch specifies the timestamp used to provide control for reproducibility.
// See also https://reproducible-builds.org/docs/source-date-epoch/ .
//
// Since containerd v2.0, the whiteout timestamps are set to zero (1970-01-01),
// not to the source date epoch.
func WithSourceDateEpoch(tm *time.Time) Opt {
return func(c *Config) error {
c.SourceDateEpoch = tm
Expand Down

0 comments on commit 5dedb6d

Please sign in to comment.