From e825566a0c22b5e26af2f7f5eb3541b95ae41040 Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Thu, 15 Feb 2024 09:57:35 +0100 Subject: [PATCH 1/3] Add option to set mtime of files in rpms to SOURCE_DATE_EPOCH. For backwards compatibility the option clamp / limit the maximum mtime is retained. Setting it ouright avoids problems with an incorrectly older clock. It also avoids problems with build scrips that incorrectly change file mtimes when SOURCE_DATE_EPOCH_MTIME is in use. mtimes are required to increase with new versions and releases of an rpm with the same name, as rsync without --checksum and similar tools would get confused if the content changes without newer mtime. If SOURCE_DATE_EPOCH_MTIME is set use it instead for file modification time stamps. It is supposed to be newer. This can be used if we might want to compare if the file content remains the same when a build dependency changes while a build script embeds SOURCE_DATE_EPOCH in the file content. This can be used to support automatic rebuilds. Normally automatic rebuilds work, but together with reproducible builds an undesirable situation may occur. If a build e.g. embeds SOURCE_DATE_EPOCH in the output, then the output changes every time such a rebuild happens, which can be very often. This is to be avoided as updating packages without necessity is too expensive. --- build/files.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/build/files.c b/build/files.c index 5ae20c689..ebb2aa0cd 100644 --- a/build/files.c +++ b/build/files.c @@ -1001,14 +1001,34 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) uint32_t defaultalgo = RPM_HASH_MD5, digestalgo; rpm_loff_t totalFileSize = 0; Header h = pkg->header; /* just a shortcut */ + int set_mtime = 0; time_t source_date_epoch = 0; char *srcdate = getenv("SOURCE_DATE_EPOCH"); + char *msrcdate = getenv("SOURCE_DATE_EPOCH_MTIME"); - /* Limit the maximum date to SOURCE_DATE_EPOCH if defined - * similar to the tar --clamp-mtime option + /* If SOURCE_DATE_EPOCH_MTIME is set use it for file modification time + * stamps, it is supposed to be newer. This can be used if we might want to + * compare if the file content remains the same when a build dependency + * changes while a build script embeds SOURCE_DATE_EPOCH in the file + * content. mtimes are required to increase with new versions and releases + * of an rpm with the same name, as rsync without --checksum and similar + * tools would get confused if the content changes without newer mtime. */ + if (msrcdate != NULL) { + srcdate = msrcdate; + } + + /* Set the file mtime to SOURCE_DATE_EPOCH it if requested to make the + * resulting rpm reproducible. * https://reproducible-builds.org/specs/source-date-epoch/ + * + * For backwards compatibility clamp / limit the maximum mtime if requested + * similar the tar --clamp-mtime option. Setting it ouright avoids problems + * with an incorrectly older clock. It also avoids problems with build + * scrips that incorrectly change file mtimes when SOURCE_DATE_EPOCH_MTIME + * is in use. */ - if (srcdate && rpmExpandNumeric("%{?clamp_mtime_to_source_date_epoch}")) { + if (srcdate && (rpmExpandNumeric("%{?clamp_mtime_to_source_date_epoch}") + || rpmExpandNumeric("%{?set_mtime_to_source_date_epoch}"))) { char *endptr; errno = 0; source_date_epoch = strtol(srcdate, &endptr, 10); @@ -1016,6 +1036,9 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) rpmlog(RPMLOG_ERR, _("unable to parse %s=%s\n"), "SOURCE_DATE_EPOCH", srcdate); fl->processingFailed = 1; } + if (rpmExpandNumeric("%{?set_mtime_to_source_date_epoch}")) { + set_mtime = 1; + } } /* @@ -1160,8 +1183,8 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) totalFileSize += flp->fl_size; } } - - if (source_date_epoch && flp->fl_mtime > source_date_epoch) { + + if (source_date_epoch && (flp->fl_mtime > source_date_epoch || set_mtime)) { flp->fl_mtime = source_date_epoch; } /* -- 2.45.2