From 834876c5fb13dfaa102000e816e9052af139048c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 8 Jan 2021 10:24:42 +0200 Subject: Initial attempt (gzip -n and preserve post-processed manifest timestamp) 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). --- libbuild2/dist/module.hxx | 4 ++++ libbuild2/dist/operation.cxx | 21 ++++++++++++--------- libbuild2/version/init.cxx | 19 ++++++++++++++++++- 3 files changed, 34 insertions(+), 10 deletions(-) (limited to 'libbuild2') 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 (); } -- cgit v1.1