diff --git a/arch/arch.go b/arch/arch.go index d2485744..a35d021d 100644 --- a/arch/arch.go +++ b/arch/arch.go @@ -17,6 +17,7 @@ import ( "github.com/goreleaser/nfpm/v2" "github.com/goreleaser/nfpm/v2/files" "github.com/goreleaser/nfpm/v2/internal/maps" + "github.com/goreleaser/nfpm/v2/internal/modtime" "github.com/klauspost/compress/zstd" "github.com/klauspost/pgzip" ) @@ -152,7 +153,7 @@ func (ArchLinux) Package(info *nfpm.Info, w io.Writer) error { // .PKGINFO must be the first entry in .MTREE entries = append([]MtreeEntry{*pkginfoEntry}, entries...) - err = createMtree(tw, entries, info.MTime) + err = createMtree(tw, entries, modtime.Get(info.MTime)) if err != nil { return fmt.Errorf("create mtree: %w", err) } @@ -310,7 +311,7 @@ func createPkginfo(info *nfpm.Info, tw *tar.Writer, totalSize int64) (*MtreeEntr return nil, err } - builddate := strconv.FormatInt(info.MTime.Unix(), 10) + builddate := strconv.FormatInt(modtime.Get(info.MTime).Unix(), 10) totalSizeStr := strconv.FormatInt(totalSize, 10) err = writeKVPairs(buf, map[string]string{ @@ -374,7 +375,7 @@ func createPkginfo(info *nfpm.Info, tw *tar.Writer, totalSize int64) (*MtreeEntr Mode: 0o644, Name: ".PKGINFO", Size: int64(size), - ModTime: info.MTime, + ModTime: modtime.Get(info.MTime), }) if err != nil { return nil, err @@ -392,7 +393,7 @@ func createPkginfo(info *nfpm.Info, tw *tar.Writer, totalSize int64) (*MtreeEntr return &MtreeEntry{ Destination: ".PKGINFO", - Time: info.MTime.Unix(), + Time: modtime.Get(info.MTime).Unix(), Mode: 0o644, Size: int64(size), Type: files.TypeFile, @@ -558,7 +559,7 @@ func createScripts(info *nfpm.Info, tw *tar.Writer) error { Mode: 0o644, Name: ".INSTALL", Size: int64(buf.Len()), - ModTime: info.MTime, + ModTime: modtime.Get(info.MTime), }) if err != nil { return err diff --git a/deb/deb.go b/deb/deb.go index 66f4a13e..be50cf7e 100644 --- a/deb/deb.go +++ b/deb/deb.go @@ -23,6 +23,7 @@ import ( "github.com/goreleaser/nfpm/v2/deprecation" "github.com/goreleaser/nfpm/v2/files" "github.com/goreleaser/nfpm/v2/internal/maps" + "github.com/goreleaser/nfpm/v2/internal/modtime" "github.com/goreleaser/nfpm/v2/internal/sign" "github.com/klauspost/compress/zstd" "github.com/ulikunitz/xz" @@ -126,15 +127,17 @@ func (d *Deb) Package(info *nfpm.Info, deb io.Writer) (err error) { // nolint: f return fmt.Errorf("cannot write ar header to deb file: %w", err) } - if err := addArFile(w, "debian-binary", debianBinary, info.MTime); err != nil { + mtime := modtime.Get(info.MTime) + + if err := addArFile(w, "debian-binary", debianBinary, mtime); err != nil { return fmt.Errorf("cannot pack debian-binary: %w", err) } - if err := addArFile(w, "control.tar.gz", controlTarGz, info.MTime); err != nil { + if err := addArFile(w, "control.tar.gz", controlTarGz, mtime); err != nil { return fmt.Errorf("cannot add control.tar.gz to deb: %w", err) } - if err := addArFile(w, dataTarballName, dataTarball, info.MTime); err != nil { + if err := addArFile(w, dataTarballName, dataTarball, mtime); err != nil { return fmt.Errorf("cannot add data.tar.gz to deb: %w", err) } @@ -144,7 +147,7 @@ func (d *Deb) Package(info *nfpm.Info, deb io.Writer) (err error) { // nolint: f return err } - if err := addArFile(w, "_gpg"+sigType, sig, info.MTime); err != nil { + if err := addArFile(w, "_gpg"+sigType, sig, mtime); err != nil { return &nfpm.ErrSigningFailure{ Err: fmt.Errorf("add signature to ar file: %w", err), } @@ -256,7 +259,7 @@ func newDpkgSigFileLine(name string, fileContent []byte) dpkgSigFileLine { func readDpkgSigData(info *nfpm.Info, debianBinary, controlTarGz, dataTarball []byte) (io.Reader, error) { data := dpkgSigData{ Signer: info.Deb.Signature.Signer, - Date: info.MTime, + Date: modtime.Get(info.MTime), Role: info.Deb.Signature.Type, Files: []dpkgSigFileLine{ newDpkgSigFileLine("debian-binary", debianBinary), @@ -392,14 +395,14 @@ func createFilesInsideDataTar(info *nfpm.Info, tw *tar.Writer) (md5buf bytes.Buf Format: tar.FormatGNU, Uname: file.FileInfo.Owner, Gname: file.FileInfo.Group, - ModTime: time.Unix(0, 0), + ModTime: modtime.Get(info.MTime), }) case files.TypeSymlink: err = newItemInsideTar(tw, []byte{}, &tar.Header{ Name: files.AsExplicitRelativePath(file.Destination), Linkname: file.Source, Typeflag: tar.TypeSymlink, - ModTime: time.Unix(0, 0), + ModTime: modtime.Get(info.MTime), Format: tar.FormatGNU, }) case files.TypeDebChangelog: @@ -511,7 +514,7 @@ func createChangelogInsideDataTar( return 0, err } - if err = newFileInsideTar(tarw, fileName, changelogData, info.MTime); err != nil { + if err = newFileInsideTar(tarw, fileName, changelogData, modtime.Get(info.MTime)); err != nil { return 0, err } @@ -555,18 +558,19 @@ func createControl(instSize int64, md5sums []byte, info *nfpm.Info) (controlTarG return nil, err } - if err := newFileInsideTar(out, "./control", body.Bytes(), info.MTime); err != nil { + mtime := modtime.Get(info.MTime) + if err := newFileInsideTar(out, "./control", body.Bytes(), mtime); err != nil { return nil, err } - if err := newFileInsideTar(out, "./md5sums", md5sums, info.MTime); err != nil { + if err := newFileInsideTar(out, "./md5sums", md5sums, mtime); err != nil { return nil, err } - if err := newFileInsideTar(out, "./conffiles", conffiles(info), info.MTime); err != nil { + if err := newFileInsideTar(out, "./conffiles", conffiles(info), mtime); err != nil { return nil, err } if triggers := createTriggers(info); len(triggers) > 0 { - if err := newFileInsideTar(out, "./triggers", triggers, info.MTime); err != nil { + if err := newFileInsideTar(out, "./triggers", triggers, mtime); err != nil { return nil, err } } @@ -612,13 +616,7 @@ func createControl(instSize int64, md5sums []byte, info *nfpm.Info) (controlTarG if dets.fileName == "" { continue } - if err := newFilePathInsideTar( - out, - dets.fileName, - filename, - dets.mode, - info.MTime, - ); err != nil { + if err := newFilePathInsideTar(out, dets.fileName, filename, dets.mode, mtime); err != nil { return nil, err } } diff --git a/internal/modtime/mtime.go b/internal/modtime/mtime.go new file mode 100644 index 00000000..a00ce3c7 --- /dev/null +++ b/internal/modtime/mtime.go @@ -0,0 +1,28 @@ +package modtime + +import ( + "os" + "strconv" + "time" +) + +func FromEnv() time.Time { + epoch := os.Getenv("SOURCE_DATE_EPOCH") + if epoch == "" { + return time.Time{} + } + sde, err := strconv.ParseInt(epoch, 10, 64) + if err != nil { + return time.Time{} + } + return time.Unix(sde, 0).UTC() +} + +func Get(times ...time.Time) time.Time { + for _, t := range times { + if !t.IsZero() { + return t + } + } + return time.Now() +} diff --git a/nfpm.go b/nfpm.go index b7c6bf3c..06e30d44 100644 --- a/nfpm.go +++ b/nfpm.go @@ -8,7 +8,6 @@ import ( "io" "io/fs" "os" - "strconv" "strings" "sync" "time" @@ -18,6 +17,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/goreleaser/chglog" "github.com/goreleaser/nfpm/v2/files" + "github.com/goreleaser/nfpm/v2/internal/modtime" "gopkg.in/yaml.v3" ) @@ -537,7 +537,7 @@ func WithDefaults(info *Info) *Info { info.Umask = 0o02 } if info.MTime.IsZero() { - info.MTime = getSourceDateEpoch() + info.MTime = modtime.FromEnv() } switch info.VersionSchema { case "none": @@ -552,19 +552,6 @@ func WithDefaults(info *Info) *Info { return info } -func getSourceDateEpoch() time.Time { - now := time.Now().UTC() - epoch := os.Getenv("SOURCE_DATE_EPOCH") - if epoch == "" { - return now - } - sde, err := strconv.ParseInt(epoch, 10, 64) - if err != nil { - return now - } - return time.Unix(sde, 0).UTC() -} - // ErrSigningFailure is returned whenever something went wrong during // the package signing process. The underlying error can be unwrapped // and could be crypto-related or something that occurred while adding diff --git a/rpm/rpm.go b/rpm/rpm.go index b07cf156..f533f549 100644 --- a/rpm/rpm.go +++ b/rpm/rpm.go @@ -15,6 +15,7 @@ import ( "github.com/goreleaser/chglog" "github.com/goreleaser/nfpm/v2" "github.com/goreleaser/nfpm/v2/files" + "github.com/goreleaser/nfpm/v2/internal/modtime" "github.com/goreleaser/nfpm/v2/internal/sign" ) @@ -256,7 +257,7 @@ func buildRPMMeta(info *nfpm.Info) (*rpmpack.RPMMetaData, error) { Suggests: suggests, Conflicts: conflicts, Compressor: info.RPM.Compression, - BuildTime: info.MTime, + BuildTime: modtime.Get(info.MTime), BuildHost: hostname, }, nil } @@ -344,7 +345,9 @@ func addScriptFiles(info *nfpm.Info, rpm *rpmpack.RPM) error { return nil } +// TODO: pass mtime down in all content types func createFilesInsideRPM(info *nfpm.Info, rpm *rpmpack.RPM) (err error) { + mtime := modtime.Get(info.MTime) for _, content := range info.Contents { if content.Packager != "" && content.Packager != packagerName { continue @@ -372,7 +375,7 @@ func createFilesInsideRPM(info *nfpm.Info, rpm *rpmpack.RPM) (err error) { case files.TypeSymlink: file = asRPMSymlink(content) case files.TypeDir: - file = asRPMDirectory(content, info.MTime) + file = asRPMDirectory(content, mtime) case files.TypeImplicitDir: // we don't need to add imlicit directories to RPMs continue