From 10ec1ac16b5ec2577b94e8311e48ee3c7db9fb78 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 20 Mar 2018 14:01:38 +0200 Subject: Come up with better version for uncommitted snapshots Instead of leaving it as .z we now take the date of the previous commit and increment it by a second. The main benefit of doing it this way is that once committed, the new version does not "jump back" behind .z. --- build2/version/init.cxx | 20 +++++++++------- build2/version/module.hxx | 10 ++++++-- build2/version/snapshot-git.cxx | 51 ++++++++++++++++++++++++++++++----------- build2/version/snapshot.hxx | 1 + 4 files changed, 59 insertions(+), 23 deletions(-) (limited to 'build2/version') diff --git a/build2/version/init.cxx b/build2/version/init.cxx index 7b8bd01..f793c98 100644 --- a/build2/version/init.cxx +++ b/build2/version/init.cxx @@ -163,9 +163,9 @@ namespace build2 } // If this is the latest snapshot (i.e., the -a.1.z kind), then load the - // snapshot sn and id (e.g., commit date and id from git). If there is - // uncommitted stuff, then leave it as .z. + // snapshot number and id (e.g., commit date and id from git). // + bool committed (true); if (v.snapshot () && v.snapshot_sn == standard_version::latest_sn) { snapshot ss (extract_snapshot (rs)); @@ -174,7 +174,10 @@ namespace build2 { v.snapshot_sn = ss.sn; v.snapshot_id = move (ss.id); + committed = ss.committed; } + else + committed = false; } // Set all the version.* variables. @@ -215,16 +218,17 @@ namespace build2 set ("version.pre_release_string", v.string_pre_release ()); set ("version.pre_release_number", uint64_t (v.pre_release ())); - set ("version.snapshot", v.snapshot ()); // bool - set ("version.snapshot_sn", v.snapshot_sn); // uint64 - set ("version.snapshot_id", v.snapshot_id); // string - set ("version.snapshot_string", v.string_snapshot ()); + set ("version.snapshot", v.snapshot ()); // bool + set ("version.snapshot_sn", v.snapshot_sn); // uint64 + set ("version.snapshot_id", v.snapshot_id); // string + set ("version.snapshot_string", v.string_snapshot ()); + set ("version.snapshot_committed", committed); // bool set ("version.revision", uint64_t (v.revision)); // Create the module. // - mod.reset (new module (move (v), move (ds))); + mod.reset (new module (move (v), committed, move (ds))); return true; // Init first (dist.package, etc). } @@ -331,7 +335,7 @@ namespace build2 // Complain if this is an uncommitted snapshot. // - if (v.snapshot_sn == standard_version::latest_sn) + if (v.snapshot () && !m.committed) fail << "distribution of uncommitted project " << rs.src_path (); // The plan is simple, re-serialize the manifest into a temporary file diff --git a/build2/version/module.hxx b/build2/version/module.hxx index 190d8d7..a5a667a 100644 --- a/build2/version/module.hxx +++ b/build2/version/module.hxx @@ -25,13 +25,19 @@ namespace build2 static const string name; butl::standard_version version; + bool committed; // Whether this is a committed snapshot. + dependency_constraints dependencies; const variable* in_symbol = nullptr; // in.symbol const variable* in_substitution = nullptr; // in.substitution - module (butl::standard_version v, dependency_constraints d) - : version (move (v)), dependencies (move (d)) {} + module (butl::standard_version v, + bool c, + dependency_constraints d) + : version (move (v)), + committed (c), + dependencies (move (d)) {} }; } } diff --git a/build2/version/snapshot-git.cxx b/build2/version/snapshot-git.cxx index b85b47e..751686e 100644 --- a/build2/version/snapshot-git.cxx +++ b/build2/version/snapshot-git.cxx @@ -31,9 +31,9 @@ namespace build2 // { const char* args[] {"git", "-C", d, "status", "--porcelain", nullptr}; - - if (!run (3, args, [](string& s) {return move (s);}).empty ()) - return r; + r.committed = run (3 /* verbosity */, + args, + [](string& s) {return move (s);}).empty (); } // Now extract the commit id and date. One might think that would be @@ -45,7 +45,18 @@ namespace build2 // // Where is the size of and is the output of: // - // git cat-file commit ... + // git cat-file commit HEAD + // + // There is also one annoying special case: new repository without any + // commits. In this case the above command will fail (with diagnostics + // and non-zero exit code) because there is no HEAD. Of course, it can + // also fail for other reason (like broken repository) which would be + // hard to distinguish. Note, however, that we just ran git status and + // it would have most likely failed if this were the case. So here we + // (reluctantly) assume that the only reason git cat-file fails is if + // there is no HEAD (that we equal with the "new repository" condition + // which is, strictly speaking, might not be the case either). So we + // suppress any diagnostics, and handle non-zero exit code. // string data; @@ -53,14 +64,16 @@ namespace build2 "git", "-C", d, "cat-file", "commit", "HEAD", nullptr}; process pr (run_start (3 /* verbosity */, args, - 0 /* stdin */, - -1 /* stdout */)); + 0 /* stdin */, + -1 /* stdout */, + false /* error */)); + string l; try { ifdstream is (move (pr.in_ofd), ifdstream::badbit); - for (string l; !eof (getline (is, l)); ) + while (!eof (getline (is, l))) { data += l; data += '\n'; // We assume there is always a newline. @@ -128,16 +141,28 @@ namespace build2 // that. } - run_finish (args, pr); + if (!run_finish (args, pr, false /* error */, l)) + { + // Presumably new repository without HEAD. Return uncommitted snapshot + // with UNIX epoch as timestamp. + // + r.sn = 19700101000000ULL; + r.committed = false; + return r; + } if (r.sn == 0) fail << "unable to extract git commit id/date for " << src_root; - sha1 cs; - cs.append ("commit " + to_string (data.size ())); // Includes '\0'. - cs.append (data.c_str (), data.size ()); - - r.id.assign (cs.string (), 12); // 12-characters abbreviated commit id. + if (r.committed) + { + sha1 cs; + cs.append ("commit " + to_string (data.size ())); // Includes '\0'. + cs.append (data.c_str (), data.size ()); + r.id.assign (cs.string (), 12); // 12-characters abbreviated commit id. + } + else + r.sn++; // Add a second. return r; } diff --git a/build2/version/snapshot.hxx b/build2/version/snapshot.hxx index b7e6dd7..15f4b59 100644 --- a/build2/version/snapshot.hxx +++ b/build2/version/snapshot.hxx @@ -18,6 +18,7 @@ namespace build2 { uint64_t sn = 0; string id; + bool committed = false; bool empty () const {return sn == 0;} -- cgit v1.1