diff options
Diffstat (limited to 'libbuild2/version/snapshot-git.cxx')
-rw-r--r-- | libbuild2/version/snapshot-git.cxx | 63 |
1 files changed, 39 insertions, 24 deletions
diff --git a/libbuild2/version/snapshot-git.cxx b/libbuild2/version/snapshot-git.cxx index 28d96ac..ab0224a 100644 --- a/libbuild2/version/snapshot-git.cxx +++ b/libbuild2/version/snapshot-git.cxx @@ -3,7 +3,7 @@ #include <ctime> // time_t -#include <libbutl/sha1.mxx> +#include <libbutl/sha1.hxx> #include <libbuild2/version/snapshot.hxx> @@ -14,11 +14,20 @@ namespace build2 { namespace version { + // We have to run git twice to extract the information we need and doing + // it repetitively is quite expensive, especially for larger repositories. + // So we cache it, which helps multi-package repositories. + // + static global_cache<snapshot, dir_path> cache; + snapshot - extract_snapshot_git (const dir_path& src_root) + extract_snapshot_git (context& ctx, dir_path rep_root) { + if (const snapshot* r = cache.find (rep_root)) + return *r; + snapshot r; - const char* d (src_root.string ().c_str ()); + const char* d (rep_root.string ().c_str ()); // On startup git prepends the PATH environment variable value with the // computed directory path where its sub-programs are supposedly located @@ -73,7 +82,11 @@ namespace build2 args[args_i + 1] = "--porcelain"; args[args_i + 2] = nullptr; + // @@ PERF: redo with custom stream reading code (then could also + // get rid of context). + // r.committed = run<string> ( + ctx, 3 /* verbosity */, pp, args, @@ -99,7 +112,8 @@ namespace build2 // (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. + // suppress any diagnostics, and handle non-zero exit code (and so no + // diagnostics buffering is needed, plus we are in the load phase). // string data; @@ -108,12 +122,12 @@ namespace build2 args[args_i + 2] = "HEAD"; args[args_i + 3] = nullptr; - process pr (run_start (3 /* verbosity */, + process pr (run_start (3 /* verbosity */, pp, args, - 0 /* stdin */, - -1 /* stdout */, - false /* error */)); + 0 /* stdin */, + -1 /* stdout */, + 1 /* stderr (to stdout) */)); string l; try @@ -192,30 +206,31 @@ namespace build2 // that. } - if (!run_finish_code (args, pr, l)) + if (run_finish_code (args, pr, l, 2 /* verbosity */)) + { + if (r.sn == 0) + fail << "unable to extract git commit id/date for " << rep_root; + + 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-char abbreviated commit id. + } + else + r.sn++; // Add a second. + } + else { // 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; - - 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; + return cache.insert (move (rep_root), move (r)); } } } |