lib: support reproducible install date
When building an Arch Linux image the install date would vary when trying to reproduce it. Similar to building packages, respect `SOURCE_DATE_EPOCH` when installing packages.
This commit is contained in:
parent
cf473bcfbd
commit
94bbd989df
6 changed files with 57 additions and 2 deletions
|
@ -412,6 +412,43 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
|
|||
return errors;
|
||||
}
|
||||
|
||||
static time_t get_install_time(void)
|
||||
{
|
||||
|
||||
time_t now;
|
||||
char *source_date_epoch;
|
||||
unsigned long long epoch;
|
||||
char *endptr;
|
||||
|
||||
source_date_epoch = getenv("SOURCE_DATE_EPOCH");
|
||||
if (source_date_epoch) {
|
||||
errno = 0;
|
||||
epoch = strtoull(source_date_epoch, &endptr, 10);
|
||||
if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
|
||||
|| (errno != 0 && epoch == 0)) {
|
||||
fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (endptr == source_date_epoch) {
|
||||
fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n", endptr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (*endptr != '\0') {
|
||||
fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n", endptr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (epoch > ULONG_MAX) {
|
||||
fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to %lu but was found to be: %llu \n", ULONG_MAX, epoch);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
now = epoch;
|
||||
} else {
|
||||
now = time(NULL);
|
||||
}
|
||||
|
||||
return now;
|
||||
}
|
||||
|
||||
static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
|
||||
size_t pkg_current, size_t pkg_count)
|
||||
{
|
||||
|
@ -591,7 +628,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
|
|||
}
|
||||
|
||||
/* make an install date (in UTC) */
|
||||
newpkg->installdate = time(NULL);
|
||||
newpkg->installdate = get_install_time();
|
||||
|
||||
_alpm_log(handle, ALPM_LOG_DEBUG, "updating database\n");
|
||||
_alpm_log(handle, ALPM_LOG_DEBUG, "adding database entry '%s'\n", newpkg->name);
|
||||
|
|
|
@ -294,6 +294,7 @@ Possible rules are:
|
|||
PKG_REASON=name|intvalue
|
||||
PKG_FILES=name|filename
|
||||
PKG_BACKUP=name|backupname
|
||||
PKG_INSTALLDATE=name|epoch
|
||||
|
||||
Example:
|
||||
PKG_DEPENDS=ncurses|glibc
|
||||
|
|
|
@ -278,6 +278,7 @@ pacman_tests = [
|
|||
'tests/sync992.py',
|
||||
'tests/sync993.py',
|
||||
'tests/sync999.py',
|
||||
'tests/source_date_epoch_install.py',
|
||||
'tests/trans001.py',
|
||||
'tests/type001.py',
|
||||
'tests/unresolvable001.py',
|
||||
|
|
|
@ -108,6 +108,9 @@ class pmrule(object):
|
|||
if f.startswith(value + "\t"):
|
||||
success = 1
|
||||
break;
|
||||
elif case == "INSTALLDATE":
|
||||
if newpkg.installdate != value:
|
||||
success = 0
|
||||
else:
|
||||
tap.diag("PKG rule '%s' not found" % case)
|
||||
success = -1
|
||||
|
|
|
@ -92,6 +92,7 @@ class pmtest(object):
|
|||
"fail": 0
|
||||
}
|
||||
self.args = ""
|
||||
self.env = {}
|
||||
self.retcode = 0
|
||||
self.db = {
|
||||
"local": pmdb.pmdb("local", self.root)
|
||||
|
@ -298,7 +299,7 @@ class pmtest(object):
|
|||
# archives are made available more easily.
|
||||
time_start = time.time()
|
||||
self.retcode = subprocess.call(cmd, stdout=output, stderr=output,
|
||||
cwd=os.path.join(self.root, util.TMPDIR), env={'LC_ALL': 'C'})
|
||||
cwd=os.path.join(self.root, util.TMPDIR), env={'LC_ALL': 'C', **self.env})
|
||||
time_end = time.time()
|
||||
vprint("\ttime elapsed: %.2fs" % (time_end - time_start))
|
||||
|
||||
|
|
12
test/pacman/tests/source_date_epoch_install.py
Normal file
12
test/pacman/tests/source_date_epoch_install.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
self.description = "Check that installing a package retains INSTALL DATE with SOURCE_DATE_EPOCH"
|
||||
|
||||
p = pmpkg("pkg1")
|
||||
p.files = ["foo/file1",
|
||||
"foo/file2"]
|
||||
self.addpkg(p)
|
||||
|
||||
self.args = "-U %s" % p.filename()
|
||||
self.env = {"SOURCE_DATE_EPOCH": "1662046009"}
|
||||
|
||||
self.addrule("PACMAN_RETCODE=0")
|
||||
self.addrule("PKG_INSTALLDATE=pkg1|1662046009")
|
Loading…
Add table
Reference in a new issue