From 18d1f2f4ad48629dfa76fd49b614ee044c2a6b539251f7db164effb2db099294 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 9 Mar 2017 08:40:16 +0000 Subject: [PATCH] Accepting request 476984 from home:bmwiedemann:branches:Base:System rebased - Add upstream patches 0001-set-SOURCE_DATE_EPOCH-from-changelog.patch 0002-Extend-changelog-to-support-full-timestamps-903.patch 0003-Allow-SOURCE_DATE_EPOCH-to-override-file-timestamps.patch 0004-Allow-SOURCE_DATE_EPOCH-to-override-RPMTAG_BUILDTIME.patch in order to allow for building bit-identical rpms as described in https://github.com/rpm-software-management/rpm/pull/144 OBS-URL: https://build.opensuse.org/request/show/476984 OBS-URL: https://build.opensuse.org/package/show/Base:System/rpm?expand=0&rev=384 --- ...set-SOURCE_DATE_EPOCH-from-changelog.patch | 62 ++++++ ...gelog-to-support-full-timestamps-903.patch | 191 ++++++++++++++++++ ...TE_EPOCH-to-override-file-timestamps.patch | 82 ++++++++ ...E_EPOCH-to-override-RPMTAG_BUILDTIME.patch | 50 +++++ rpm.changes | 10 + rpm.spec | 10 +- 6 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 0001-set-SOURCE_DATE_EPOCH-from-changelog.patch create mode 100644 0002-Extend-changelog-to-support-full-timestamps-903.patch create mode 100644 0003-Allow-SOURCE_DATE_EPOCH-to-override-file-timestamps.patch create mode 100644 0004-Allow-SOURCE_DATE_EPOCH-to-override-RPMTAG_BUILDTIME.patch diff --git a/0001-set-SOURCE_DATE_EPOCH-from-changelog.patch b/0001-set-SOURCE_DATE_EPOCH-from-changelog.patch new file mode 100644 index 0000000..870d8ec --- /dev/null +++ b/0001-set-SOURCE_DATE_EPOCH-from-changelog.patch @@ -0,0 +1,62 @@ +From 42906a9c5da4c89128ed8ffb619f8ef1fa2d9b93 Mon Sep 17 00:00:00 2001 +From: "Bernhard M. Wiedemann" +Date: Fri, 27 Jan 2017 13:01:57 +0100 +Subject: [PATCH 1/4] set SOURCE_DATE_EPOCH from changelog + +if requested by macro +to allow for more reproducible builds of packages. + +See https://reproducible-builds.org/ for why this is good +and https://reproducible-builds.org/specs/source-date-epoch/ +for the definition of this variable. + +(cherry picked from commit 0e87aed1785d0531c40b23889f8338744f6abb3a) +--- + build/build.c | 15 +++++++++++++++ + macros.in | 4 ++++ + 2 files changed, 19 insertions(+) + +diff --git a/build/build.c b/build/build.c +index 04b039c..89b04ce 100644 +--- build/build.c ++++ build/build.c +@@ -209,6 +209,21 @@ static rpmRC buildSpec(BTA_t buildArgs, rpmSpec spec, int what) + int test = (what & RPMBUILD_NOBUILD); + char *cookie = buildArgs->cookie ? xstrdup(buildArgs->cookie) : NULL; + ++ if (rpmExpandNumeric("%{?source_date_epoch_from_changelog}") && ++ getenv("SOURCE_DATE_EPOCH") == NULL) { ++ /* Use date of first (== latest) changelog entry */ ++ Header h = spec->packages->header; ++ struct rpmtd_s td; ++ if (headerGet(h, RPMTAG_CHANGELOGTIME, &td, (HEADERGET_MINMEM|HEADERGET_RAW))) { ++ char sdestr[22]; ++ snprintf(sdestr, sizeof(sdestr), "%lli", ++ (long long) rpmtdGetNumber(&td)); ++ rpmlog(RPMLOG_NOTICE, _("setting %s=%s\n"), "SOURCE_DATE_EPOCH", sdestr); ++ setenv("SOURCE_DATE_EPOCH", sdestr, 0); ++ rpmtdFreeData(&td); ++ } ++ } ++ + /* XXX TODO: rootDir is only relevant during build, eliminate from spec */ + spec->rootDir = buildArgs->rootdir; + if (!spec->recursing && spec->BACount) { +diff --git a/macros.in b/macros.in +index fd57f2e..85f172a 100644 +--- macros.in ++++ macros.in +@@ -210,6 +210,10 @@ package or when debugging this package.\ + # Any older entry is not packaged in binary packages. + %_changelog_trimtime 0 + ++# If true, set the SOURCE_DATE_EPOCH environment variable ++# to the timestamp of the topmost changelog entry ++%source_date_epoch_from_changelog 0 ++ + # The directory where newly built binary packages will be written. + %_rpmdir %{_topdir}/RPMS + +-- +2.10.2 + diff --git a/0002-Extend-changelog-to-support-full-timestamps-903.patch b/0002-Extend-changelog-to-support-full-timestamps-903.patch new file mode 100644 index 0000000..8914d04 --- /dev/null +++ b/0002-Extend-changelog-to-support-full-timestamps-903.patch @@ -0,0 +1,191 @@ +From b74958824c7e0d7c12550ba22d9b31da040d2cd4 Mon Sep 17 00:00:00 2001 +From: Pavlina +Date: Thu, 6 Oct 2016 08:59:47 +0200 +Subject: [PATCH 2/4] Extend %changelog to support full timestamps (#903) + +The newly accepted date format is + +Mon Jan 6 09:02:22 CEST 2016 + +(like output of "date" command). Original format "Mon Jun 6 2016" is still supported. + +(cherry picked from commit 57f94a582602f0353cdb17a02dc12c4461d4f32d) +--- + build/parseChangelog.c | 106 +++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 89 insertions(+), 17 deletions(-) + +diff --git a/build/parseChangelog.c b/build/parseChangelog.c +index ff301b9..82fd096 100644 +--- build/parseChangelog.c ++++ build/parseChangelog.c +@@ -32,17 +32,20 @@ static int sameDate(const struct tm *ot, const struct tm *nt) + + /** + * Parse date string to seconds. ++ * accepted date formats are "Mon Jun 6 2016" (original one) ++ * and "Thu Oct 6 06:48:39 CEST 2016" (extended one) + * @param datestr date string (e.g. 'Wed Jan 1 1997') + * @retval secs secs since the unix epoch + * @return 0 on success, -1 on error + */ +-static int dateToTimet(const char * datestr, time_t * secs) ++static int dateToTimet(const char * datestr, time_t * secs, int * date_words) + { + int rc = -1; /* assume failure */ + struct tm time, ntime; + const char * const * idx; + char *p, *pe, *q, *date, *tz; +- ++ char tz_name[10]; /* name of timezone (if extended format is used) */ ++ + static const char * const days[] = + { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL }; + static const char * const months[] = +@@ -80,26 +83,93 @@ static int dateToTimet(const char * datestr, time_t * secs) + if (*p == '\0') goto exit; + pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0'; + +- /* make this noon so the day is always right (as we make this UTC) */ +- time.tm_hour = 12; +- + time.tm_mday = strtol(p, &q, 10); + if (!(q && *q == '\0')) goto exit; + if (time.tm_mday < 0 || time.tm_mday > lengths[time.tm_mon]) goto exit; + +- /* year */ +- p = pe; SKIPSPACE(p); +- if (*p == '\0') goto exit; +- pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe = '\0'; ++ /* first part of year entry (original format) / time entry (extended format)*/ ++ p = pe; ++ SKIPSPACE(p); ++ if (*p == '\0') ++ goto exit; ++ ++ /* in the original format here is year record (e.g. 1999), ++ * in the extended one here is time stamp (e.g. 10:22:30). ++ * Choose the format ++ */ ++ if ((p[1]==':') || ((p[1]!='\0') && ((p[2]==':')))) { ++ /* it can be extended format */ ++ *date_words = 6; ++ ++ /* second part of time entry */ ++ /* hours */ ++ time.tm_hour = strtol(p, &q, 10); ++ if ( (time.tm_hour < 0) || (time.tm_hour > 23) ) ++ goto exit; ++ if (*q!=':') ++ goto exit; ++ p = ++q; ++ /* minutes */ ++ time.tm_min = strtol(p, &q, 10); ++ if ( (time.tm_min < 0) || (time.tm_min > 59) ) ++ goto exit; ++ if (*q != ':') ++ goto exit; ++ p = ++q; ++ /* time - seconds */ ++ time.tm_sec = strtol(p, &q, 10); ++ if ( (time.tm_sec < 0) || (time.tm_sec > 59) ) ++ goto exit; ++ p = q; ++ ++ /* time zone name */ ++ SKIPSPACE(p); ++ if (*p == '\0') ++ goto exit; ++ pe = p; ++ SKIPNONSPACE(pe); ++ if (*pe != '\0') ++ *pe++ = '\0'; ++ if (((int)(pe-p) + 1) > 9 ) ++ goto exit; ++ strncpy(tz_name, p, (int)(pe-p)); ++ tz_name[(int)(pe-p)] = '\0'; ++ ++ /* first part of year entry */ ++ p = pe; ++ SKIPSPACE(p); ++ if (*p == '\0') ++ goto exit; ++ } else { ++ *date_words = 4; ++ /* the original format */ ++ /* make this noon so the day is always right (as we make this UTC) */ ++ time.tm_hour = 12; ++ } ++ ++ /* year - second part */ ++ pe = p; ++ SKIPNONSPACE(pe); ++ if (*pe != '\0') ++ *pe = '\0'; + time.tm_year = strtol(p, &q, 10); + if (!(q && *q == '\0')) goto exit; + if (time.tm_year < 1990 || time.tm_year >= 3000) goto exit; + time.tm_year -= 1900; + +- /* chnagelog date is always in UTC */ ++ /* change time zone and compute calendar time representation */ + tz = getenv("TZ"); +- if (tz) tz = xstrdup(tz); +- setenv("TZ", "UTC", 1); ++ if (tz) ++ tz = xstrdup(tz); ++ if (*date_words == 6) { ++ /* changelog date is in read time zone */ ++ tz = getenv("TZ"); ++ if (tz) tz = xstrdup(tz); ++ setenv("TZ", tz_name, 1); ++ } else { ++ /* changelog date is always in UTC */ ++ setenv("TZ", "UTC", 1); ++ } + ntime = time; /* struct assignment */ + *secs = mktime(&ntime); + unsetenv("TZ"); +@@ -107,6 +177,7 @@ static int dateToTimet(const char * datestr, time_t * secs) + setenv("TZ", tz, 1); + free(tz); + } ++ + if (*secs == -1) goto exit; + + /* XXX Turn this into a hard error in a release or two */ +@@ -135,6 +206,7 @@ static rpmRC addChangelog(Header h, ARGV_const_t sb) + time_t lastTime = 0; + time_t trimtime = rpmExpandNumeric("%{?_changelog_trimtime}"); + char *date, *name, *text, *next; ++ int date_words; /* number of words in date string */ + + s = sp = argvJoin(sb, ""); + +@@ -160,12 +232,8 @@ static rpmRC addChangelog(Header h, ARGV_const_t sb) + /* 4 fields of date */ + date++; + s = date; +- for (i = 0; i < 4; i++) { +- SKIPSPACE(s); +- SKIPNONSPACE(s); +- } + SKIPSPACE(date); +- if (dateToTimet(date, &time)) { ++ if (dateToTimet(date, &time, &date_words)) { + rpmlog(RPMLOG_ERR, _("bad date in %%changelog: %s\n"), date); + goto exit; + } +@@ -174,6 +242,10 @@ static rpmRC addChangelog(Header h, ARGV_const_t sb) + _("%%changelog not in descending chronological order\n")); + goto exit; + } ++ for (i = 0; i < date_words; i++) { ++ SKIPSPACE(s); ++ SKIPNONSPACE(s); ++ } + lastTime = time; + + /* skip space to the name */ +-- +2.10.2 + diff --git a/0003-Allow-SOURCE_DATE_EPOCH-to-override-file-timestamps.patch b/0003-Allow-SOURCE_DATE_EPOCH-to-override-file-timestamps.patch new file mode 100644 index 0000000..54a5dd8 --- /dev/null +++ b/0003-Allow-SOURCE_DATE_EPOCH-to-override-file-timestamps.patch @@ -0,0 +1,82 @@ +From f2aa612c5a2a99e1186853a3d00d43607bdc6aa2 Mon Sep 17 00:00:00 2001 +From: "Bernhard M. Wiedemann" +Date: Sun, 13 Mar 2016 10:20:47 +0100 +Subject: [PATCH 3/4] Allow SOURCE_DATE_EPOCH to override file timestamps + +Limit the maximum date to SOURCE_DATE_EPOCH or use origtime if not defined +similar to the tar --clamp-mtime option + +based on a patch by Nicolas Vigier + +(cherry picked from commit 8d84878ee05b2e63858af3a5a49d98e9e2933b1b) +--- + build/files.c | 22 ++++++++++++++++++++++ + macros.in | 5 +++++ + 2 files changed, 27 insertions(+) + +diff --git build/files.c build/files.c +index b76ce04..48b03e9 100644 +--- build/files.c ++++ build/files.c +@@ -9,6 +9,7 @@ + #define MYALLPERMS 07777 + + #include ++#include + #include + #if WITH_CAP + #include +@@ -939,6 +940,24 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) + uint32_t defaultalgo = PGPHASHALGO_MD5, digestalgo; + rpm_loff_t totalFileSize = 0; + Header h = pkg->header; /* just a shortcut */ ++ int override_date = 0; ++ time_t source_date_epoch; ++ char *srcdate = getenv("SOURCE_DATE_EPOCH"); ++ ++ /* Limit the maximum date to SOURCE_DATE_EPOCH if defined ++ * similar to the tar --clamp-mtime option ++ * https://reproducible-builds.org/specs/source-date-epoch/ ++ */ ++ if (srcdate && rpmExpandNumeric("%{?clamp_mtime_to_source_date_epoch}")) { ++ char *endptr; ++ errno = 0; ++ source_date_epoch = strtol(srcdate, &endptr, 10); ++ if (srcdate == endptr || *endptr || errno != 0) { ++ rpmlog(RPMLOG_ERR, _("unable to parse %s=%s\n"), "SOURCE_DATE_EPOCH", srcdate); ++ exit(28); ++ } ++ override_date = 1; ++ } + + /* + * See if non-md5 file digest algorithm is requested. If not +@@ -1070,6 +1089,9 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) + } + } + ++ if (override_date && flp->fl_mtime > source_date_epoch) { ++ flp->fl_mtime = source_date_epoch; ++ } + /* + * For items whose size varies between systems, always explicitly + * cast to the header type before inserting. +diff --git macros.in macros.in +index 85f172a..e0d7b7f 100644 +--- macros.in ++++ macros.in +@@ -214,6 +214,11 @@ package or when debugging this package.\ + # to the timestamp of the topmost changelog entry + %source_date_epoch_from_changelog 0 + ++# If true, make sure that timestamps in built rpms ++# are not later than the value of SOURCE_DATE_EPOCH. ++# Is ignored when SOURCE_DATE_EPOCH is not set. ++%clamp_mtime_to_source_date_epoch 0 ++ + # The directory where newly built binary packages will be written. + %_rpmdir %{_topdir}/RPMS + +-- +2.10.2 + diff --git a/0004-Allow-SOURCE_DATE_EPOCH-to-override-RPMTAG_BUILDTIME.patch b/0004-Allow-SOURCE_DATE_EPOCH-to-override-RPMTAG_BUILDTIME.patch new file mode 100644 index 0000000..04529a4 --- /dev/null +++ b/0004-Allow-SOURCE_DATE_EPOCH-to-override-RPMTAG_BUILDTIME.patch @@ -0,0 +1,50 @@ +From 686ff4634d69999740c93eea761b09c3fb17c2f6 Mon Sep 17 00:00:00 2001 +From: Nicolas Vigier +Date: Thu, 3 Dec 2015 12:57:22 +0100 +Subject: [PATCH 4/4] Allow SOURCE_DATE_EPOCH to override RPMTAG_BUILDTIME + +SOURCE_DATE_EPOCH environment variable is a distribution-agnostic +standard for build systems to exchange a timestamp. + +SOURCE_DATE_EPOCH specification is available at: +https://reproducible-builds.org/specs/source-date-epoch + +Signed-off-by: Dhiru Kholia +(cherry picked from commit b8a54d6a1e9bb6140b6b47e23dc707e4b967537e) +--- + build/pack.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git build/pack.c build/pack.c +index 094419e..8305b42 100644 +--- build/pack.c ++++ build/pack.c +@@ -154,9 +154,23 @@ exit: + static rpm_time_t * getBuildTime(void) + { + static rpm_time_t buildTime[1]; ++ char *srcdate; ++ time_t epoch; ++ char *endptr; ++ ++ if (buildTime[0] == 0) { ++ srcdate = getenv("SOURCE_DATE_EPOCH"); ++ if (srcdate) { ++ errno = 0; ++ epoch = strtol(srcdate, &endptr, 10); ++ if (srcdate == endptr || *endptr || errno != 0) ++ rpmlog(RPMLOG_ERR, _("unable to parse SOURCE_DATE_EPOCH\n")); ++ else ++ buildTime[0] = (int32_t) epoch; ++ } else ++ buildTime[0] = (int32_t) time(NULL); ++ } + +- if (buildTime[0] == 0) +- buildTime[0] = (int32_t) time(NULL); + return buildTime; + } + +-- +2.10.2 + diff --git a/rpm.changes b/rpm.changes index d7fef1e..14f6798 100644 --- a/rpm.changes +++ b/rpm.changes @@ -10,6 +10,16 @@ Mon Feb 27 13:24:26 UTC 2017 - rguenther@suse.com - Fix debugedit-canon-fix.diff to handle directory table size shrinking by 1 byte correctly. +------------------------------------------------------------------- +Wed Feb 22 12:54:05 UTC 2017 - bwiedemann@suse.com + +- Add upstream patches 0001-set-SOURCE_DATE_EPOCH-from-changelog.patch + 0002-Extend-changelog-to-support-full-timestamps-903.patch + 0003-Allow-SOURCE_DATE_EPOCH-to-override-file-timestamps.patch + 0004-Allow-SOURCE_DATE_EPOCH-to-override-RPMTAG_BUILDTIME.patch + in order to allow for building bit-identical rpms as described in + https://github.com/rpm-software-management/rpm/pull/144 + ------------------------------------------------------------------- Mon Feb 20 14:17:26 CET 2017 - mls@suse.de diff --git a/rpm.spec b/rpm.spec index 6c67efa..3e12211 100644 --- a/rpm.spec +++ b/rpm.spec @@ -125,6 +125,14 @@ Patch76: python3-abi-kind.diff Patch77: langnoc.diff Patch78: headerchk2.diff Patch79: helperenv.diff +# PATCH-FEATURE-UPSTREAM 4.14 0e87aed1785d0531c40b23889f8338744f6abb3a +Patch80: 0001-set-SOURCE_DATE_EPOCH-from-changelog.patch +# PATCH-FEATURE-UPSTREAM 4.14 57f94a582602f0353cdb17a02dc12c4461d4f32d +Patch81: 0002-Extend-changelog-to-support-full-timestamps-903.patch +# PATCH-FEATURE-UPSTREAM 4.14 8d84878ee05b2e63858af3a5a49d98e9e2933b1b +Patch82: 0003-Allow-SOURCE_DATE_EPOCH-to-override-file-timestamps.patch +# PATCH-FEATURE-UPSTREAM 4.14 b8a54d6a1e9bb6140b6b47e23dc707e4b967537e +Patch83: 0004-Allow-SOURCE_DATE_EPOCH-to-override-RPMTAG_BUILDTIME.patch Patch85: brp-compress-no-img.patch Patch92: find-lang-python.patch Patch93: weakdepscompat.diff @@ -227,7 +235,7 @@ rm -f rpmdb/db.h %patch -P 50 -P 51 -P 52 -P 53 -P 54 -P 55 -P 56 -P 57 -P 58 %patch -P 60 -P 61 -P 65 -P 66 -P 67 -P 68 -P 69 %patch -P 70 -P 71 -P 73 -P 74 -P 75 -P 76 -P 77 -P 78 -P 79 -%patch -P 85 +%patch -P 80 -P 81 -P 82 -P 83 -P 85 %patch -P 92 -P 93 -P 94 -P 96 -P 98 -P 99 %patch -P 100 -P 101 -P 102