From 884b16c882863f1eb5144a4bf7d1739bdf99a271 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 13 Dec 2018 12:43:27 +0200 Subject: Factor git-status code from bdep-ci to git_status() --- bdep/ci.cxx | 125 ++++++++++++++---------------------------------------------- 1 file changed, 28 insertions(+), 97 deletions(-) (limited to 'bdep/ci.cxx') diff --git a/bdep/ci.cxx b/bdep/ci.cxx index 0ab6fad..83119c1 100644 --- a/bdep/ci.cxx +++ b/bdep/ci.cxx @@ -44,112 +44,43 @@ namespace bdep // // 4. Get the current commit id. // - // And aren't we in luck today: git-status --porcelain=2 (available since - // git 2.11.0) gives us all this information with a single invocation. - // string branch; string commit; { - string head; - string upstream; + git_repository_status s (git_status (prj)); - process pr; - bool io (false); - try - { - fdpipe pipe (fdopen_pipe ()); // Text mode seems appropriate. - - pr = start_git (semantic_version {2, 11, 0}, - prj, - 0 /* stdin */, - pipe /* stdout */, - 2 /* stderr */, - "status", - "--porcelain=2", - "--branch"); - - pipe.out.close (); - ifdstream is (move (pipe.in), fdstream_mode::skip, ifdstream::badbit); - - // Lines starting with '#' are headers with any other line indicating - // some kind of change. - // - // The headers we are interested in are: - // - // # branch.oid | (initial) Current commit. - // # branch.head | (detached) Current branch. - // # branch.upstream If upstream is set. - // # branch.ab + - If upstream is set and - // the commit is present. - // - // Note that if we are in the detached HEAD state, then we will only - // see the first two with branch.head being '(detached)'. - // - for (string l; !eof (getline (is, l)); ) - { - if (l[0] != '#') - fail << "project directory has uncommitted changes" << - info << "run 'git status' for details"; - - if (l.compare (2, 10, "branch.oid") == 0) - { - commit = string (l, 13); - - if (commit == "(initial)") - fail << "no commits in project repository" << - info << "run 'git status' for details"; - } - else if (l.compare (2, 11, "branch.head") == 0) - { - head = string (l, 14); - - if (head == "(detached)") - fail << "project directory is in the detached HEAD state" << - info << "run 'git status' for details"; - } - else if (l.compare (2, 15, "branch.upstream") == 0) - { - // This is normally in the / form, for example - // 'origin/master'. - // - upstream = string (l, 18); - size_t p (path::traits::rfind_separator (upstream)); - branch = p != string::npos ? string (upstream, p + 1) : upstream; - } - else if (l.compare (2, 9, "branch.ab") == 0) - { - // We definitely don't want to be ahead (upstream doesn't have - // this commit) but there doesn't seem be anything wrong with - // being behind. - // - if (l.compare (12, 3, "+0 ") != 0) - fail << "local branch '" << head << "' is ahead of '" - << upstream << "'" << - info << "run 'git push' to update"; - } - } - - is.close (); // Detect errors. - } - catch (const io_error&) - { - // Presumably the child process failed and issued diagnostics so let - // finish_git() try to deal with that. - // - io = true; - } + if (s.commit.empty ()) + fail << "no commits in project repository" << + info << "run 'git status' for details"; - finish_git (pr, io); + commit = move (s.commit); - // Make sure we've got everything we need. - // - if (commit.empty ()) - fail << "unable to obtain current commit" << + if (s.branch.empty ()) + fail << "project directory is in the detached HEAD state" << info << "run 'git status' for details"; - if (branch.empty ()) - fail << "no upstream branch set for local branch '" << head << "'" << + // Upstream is normally in the / form, for example + // 'origin/master'. + // + if (s.upstream.empty ()) + fail << "no upstream branch set for local branch '" + << s.branch << "'" << info << "run 'git push --set-upstream' to set"; + + size_t p (path::traits::rfind_separator (s.upstream)); + branch = p != string::npos ? string (s.upstream, p + 1) : s.upstream; + + if (s.staged || s.unstaged) + fail << "project directory has uncommitted changes" << + info << "run 'git status' for details"; + + // We definitely don't want to be ahead (upstream doesn't have this + // commit) but there doesn't seem be anything wrong with being behind. + // + if (s.ahead) + fail << "local branch '" << s.branch << "' is ahead of '" + << s.upstream << "'" << + info << "run 'git push' to update"; } // We treat the URL specified with --repository as a "base", that is, we -- cgit v1.1