From 698bbc675764f3aec648aa242a99e89859065454 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 25 Jan 2019 11:42:02 +0200 Subject: Add --show-push option to bdep-release --- bdep/release.cli | 7 +++ bdep/release.cxx | 128 ++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 111 insertions(+), 24 deletions(-) (limited to 'bdep') diff --git a/bdep/release.cli b/bdep/release.cli index c90ec29..12210d1 100644 --- a/bdep/release.cli +++ b/bdep/release.cli @@ -99,6 +99,13 @@ namespace bdep "Push the committed changes and tags to the remote." } + bool --show-push + { + "Print the push command instead of executing it. This allows examining + the committed changes and tags before pushing them to the remote. Note + that the command is printed to \cb{stdout}." + } + bool --no-open { "Don't open the next development cycle. Opening can be performed later diff --git a/bdep/release.cxx b/bdep/release.cxx index 22f2d91..232df64 100644 --- a/bdep/release.cxx +++ b/bdep/release.cxx @@ -4,6 +4,8 @@ #include +#include // cout + #include // manifest_name_value #include @@ -483,10 +485,12 @@ namespace bdep verify ("--no-open", o.no_open ()); // Releasing only (see above). // There is no sense to push without committing the version change first. + // Meaningful for all modes. // gopt = nullptr; - verify ("--push", o.push ()); // Meaningful for all modes. - verify ("--no-commit", o.no_commit ()); // See above for modes. + verify ("--push", o.push ()); + verify ("--show-push", o.show_push ()); + verify ("--no-commit", o.no_commit ()); // Not for tagging (see above). } // Fully parse package manifest verifying it is valid and returning the @@ -656,7 +660,12 @@ namespace bdep const package& pkg (prj.packages.front ()); // Exemplar package. bool commit (!o.no_commit () && (pkg.release_version || prj.open_version)); - bool push (o.push ()); + + // true - push, false - show push, nullopt - none of the above + // + optional push; + if (o.push () || o.show_push ()) + push = o.push (); if (push && st.upstream.empty ()) fail << "no upstream branch set for local branch '" << st.branch << "'"; @@ -694,6 +703,9 @@ namespace bdep dr << " push: " << (push ? st.upstream.c_str () : "no"); + if (push && !*push) + dr << " (show)"; + dr.flush (); if (!yn_prompt ("continue? [y/n]")) @@ -860,6 +872,40 @@ namespace bdep // replace the tag in the remote repository. Thus, we specify the // repository and refspecs explicitly. // + // Upstream is normally in the / form, for example + // 'origin/master'. + // + string remote; + string brspec; + { + size_t p (path::traits::rfind_separator (st.upstream)); + + if (p == string::npos) + fail << "unable to extract remote from '" << st.upstream << "'"; + + remote = string (st.upstream, 0, p); + + // Push the branch if the mode is other than tagging (and so the + // version change is committed) or the local branch is ahead (probably + // due to the previous command run without --push). + // + if (!o.tag () || st.ahead) + { + // Since we may print the push command, let's tidy it up a bit by + // reducing : to just if the source and destination + // branches are the same. + // + brspec = st.branch; + + string b (st.upstream, p + 1); + if (b != st.branch) + { + brspec += ':'; + brspec += b; + } + } + } + string tagspec; if (prj.tag) @@ -873,35 +919,69 @@ namespace bdep tagspec += *prj.tag; } - // Upstream is normally in the / form, for example - // 'origin/master'. + // There should always be something to push, since we are either tagging + // or committing the version change (or both). // - string remote; - string brspec; + assert (!brspec.empty () || !tagspec.empty ()); + + if (*push) { - size_t p (path::traits::rfind_separator (st.upstream)); + if (verb && !o.no_progress ()) + { + diag_record dr (text); + dr << "pushing"; - if (p == string::npos) - fail << "unable to extract remote from '" << st.upstream << "'"; + if (!brspec.empty ()) + dr << " branch " << st.branch; - remote = string (st.upstream, 0, p); - brspec = st.branch + ':' + string (st.upstream, p + 1); - } + if (prj.tag) + { + if (!brspec.empty ()) + dr << ','; - if (verb && !o.no_progress ()) - { - diag_record dr (text); - dr << "pushing branch " << st.branch; + dr << " tag " << *prj.tag; + } + } - if (prj.tag) - dr << ", tag " << *prj.tag; + git_push (o, + prj.path, + remote, + !brspec.empty () ? brspec.c_str () : nullptr, + !tagspec.empty () ? tagspec.c_str () : nullptr); } + else + { + // While normally the command will be run by the user, it's possible + // this will be scripted in some way and the script may want to + // extract the push command to run later. So, for generality and + // consistency with other similar situations, we print the command + // to stdout. + // + cout << "git "; - git_push (o, - prj.path, - remote, - brspec, - !tagspec.empty () ? tagspec.c_str () : nullptr); + // Check if CWD is the project root and add -C if it's not. + // + if (prj.path != path::current_directory()) + { + // Quote the directory if it contains spaces. + // + const string& s (prj.path.string ()); + const string& d (s.find (' ') == string::npos ? s : '"' + s + '"'); + cout << "-C " << d << ' '; + } + + // Note: none of the remote, branch, or tag may contain spaces. + // + cout << "push " << remote; + + if (!brspec.empty ()) + cout << ' ' << brspec; + + if (!tagspec.empty ()) + cout << ' ' << tagspec; + + cout << endl; + } } return 0; -- cgit v1.1