diff --git a/api/services/diff/v1/diff.pb.go b/api/services/diff/v1/diff.pb.go index 54df8b56d..4552734ab 100644 --- a/api/services/diff/v1/diff.pb.go +++ b/api/services/diff/v1/diff.pb.go @@ -172,8 +172,11 @@ type DiffRequest struct { // Labels are the labels to apply to the generated content // on content store commit. Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // 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. SourceDateEpoch *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=source_date_epoch,json=sourceDateEpoch,proto3" json:"source_date_epoch,omitempty"` } diff --git a/api/services/diff/v1/diff.proto b/api/services/diff/v1/diff.proto index 7191a562e..17a26211c 100644 --- a/api/services/diff/v1/diff.proto +++ b/api/services/diff/v1/diff.proto @@ -74,8 +74,11 @@ message DiffRequest { // on content store commit. map 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; } diff --git a/archive/tar.go b/archive/tar.go index 28b623dcf..a807f8205 100644 --- a/archive/tar.go +++ b/archive/tar.go @@ -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) @@ -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{} @@ -521,13 +520,6 @@ 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. @@ -535,7 +527,6 @@ func NewChangeWriter(w io.Writer, source string, opts ...ChangeWriterOpt) *Chang 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{}{}, @@ -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 diff --git a/archive/tar_test.go b/archive/tar_test.go index 1ced02531..d1bc839bc 100644 --- a/archive/tar_test.go +++ b/archive/tar_test.go @@ -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)), } diff --git a/diff/diff.go b/diff/diff.go index 56c7e6694..40e63f798 100644 --- a/diff/diff.go +++ b/diff/diff.go @@ -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