aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-01-08 10:24:42 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2021-01-08 10:24:42 +0200
commit834876c5fb13dfaa102000e816e9052af139048c (patch)
treeb07b7670ce555ad50415d811885ea46ae89a533f
parenta8017ff4b661305a71fe98813d0118b6c3876c52 (diff)
Initial attempt (gzip -n and preserve post-processed manifest timestamp)reproducible-dist
Turns our this is not enough since tar saves timestamps (as well as owner information, file order, etc) including for directories and getting rid of that in a portable way is not going to be easy. Looks like the most plausible way would be to switch to embedded libarchive (provided it's possible to achieve everything we need).
-rw-r--r--libbuild2/dist/module.hxx4
-rw-r--r--libbuild2/dist/operation.cxx21
-rw-r--r--libbuild2/version/init.cxx19
3 files changed, 34 insertions, 10 deletions
diff --git a/libbuild2/dist/module.hxx b/libbuild2/dist/module.hxx
index 314dc96..e1af9fc 100644
--- a/libbuild2/dist/module.hxx
+++ b/libbuild2/dist/module.hxx
@@ -59,6 +59,10 @@ namespace build2
// Note also that in the bootstrap distribution mode only callbacks
// registered during bootstrap will be called.
//
+ // If the callback is doing some sort of post-processing, then you may
+ // want to consider preserving the timestamps of the files being
+ // modified in order produce the same archive for the same distribution.
+ //
using callback_func = void (const path&, const scope&, void*);
void
diff --git a/libbuild2/dist/operation.cxx b/libbuild2/dist/operation.cxx
index 2fa953d..402f34b 100644
--- a/libbuild2/dist/operation.cxx
+++ b/libbuild2/dist/operation.cxx
@@ -719,13 +719,16 @@ namespace build2
// On Windows we use libarchive's bsdtar with auto-compression (tar
// itself and quite a few compressors are MSYS executables).
//
- const char* l (nullptr); // Compression level (option).
+ // For gzip we also suppress the timestamp with -n to produce the
+ // same archive for the same distribution.
+ //
+ const char* o (nullptr); // Option (compression level, etc).
#ifdef _WIN32
const char* tar = "bsdtar";
if (e == "tar.gz")
- l = "--options=compression-level=9";
+ o = "--options=compression-level=9,!timestamp";
#else
const char* tar = "tar";
@@ -739,9 +742,9 @@ namespace build2
//
const char* c (nullptr);
- if (e == "tar.gz") { c = "gzip"; l = "-9"; }
- else if (e == "tar.xz") { c = "xz"; }
- else if (e == "tar.bz2") { c = "bzip2"; }
+ if (e == "tar.gz") { c = "gzip"; o = "-9n"; }
+ else if (e == "tar.xz") { c = "xz"; }
+ else if (e == "tar.bz2") { c = "bzip2"; }
if (c != nullptr)
{
@@ -753,8 +756,8 @@ namespace build2
i = args.size ();
args.push_back (c);
- if (l != nullptr)
- args.push_back (l);
+ if (o != nullptr)
+ args.push_back (o);
args.push_back (nullptr);
args.push_back (nullptr); // Pipe end.
@@ -784,8 +787,8 @@ namespace build2
"--format", "ustar",
"-a"};
- if (l != nullptr)
- args.push_back (l);
+ if (o != nullptr)
+ args.push_back (o);
args.push_back ("-cf");
args.push_back (ap.string ().c_str ());
diff --git a/libbuild2/version/init.cxx b/libbuild2/version/init.cxx
index ced9c68..88f1080 100644
--- a/libbuild2/version/init.cxx
+++ b/libbuild2/version/init.cxx
@@ -374,7 +374,24 @@ namespace build2
path::temp_path ("manifest"),
m.version));
- mvfile (t.path, f, verb_never);
+
+
+ // Copy the original timestamps in order produce the same archive for
+ // the same distribution.
+ //
+ try
+ {
+ entry_time et (file_time (f));
+
+ mvfile (t.path, f, verb_never);
+
+ file_time (f, et);
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to get/set timestamp for " << f << ": " << e;
+ }
+
t.cancel ();
}