Skip to content
Snippets Groups Projects
Commit 94bbd989 authored by Jelle van der Waa's avatar Jelle van der Waa :construction:
Browse files

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.
parent cf473bcf
No related branches found
No related tags found
No related merge requests found
Pipeline #104901 passed
......@@ -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 @@ def check(self, test):
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 @@ def load(self):
"fail": 0
}
self.args = ""
self.env = {}
self.retcode = 0
self.db = {
"local": pmdb.pmdb("local", self.root)
......@@ -298,7 +299,7 @@ def run(self, pacman):
# 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))
......
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")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment