aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bdep/ci.cxx39
-rw-r--r--bdep/release.cxx28
2 files changed, 54 insertions, 13 deletions
diff --git a/bdep/ci.cxx b/bdep/ci.cxx
index 2f07957..b7fe2cf 100644
--- a/bdep/ci.cxx
+++ b/bdep/ci.cxx
@@ -22,6 +22,11 @@ namespace bdep
{
using bpkg::repository_location;
+ // Note: the git_status() function, that we use, requires git 2.11.0 or
+ // higher.
+ //
+ static const semantic_version git_ver {2, 11, 0};
+
static const url default_server (
#ifdef BDEP_STAGE
"https://ci.stage.build2.org"
@@ -67,15 +72,35 @@ namespace bdep
info << "run 'git status' for details";
// Upstream is normally in the <remote>/<branch> form, for example
- // 'origin/master'.
+ // 'origin/master'. Note, however, that we cannot unambiguously split it
+ // into the remote and branch names (see release.cxx for details).
//
- if (s.upstream.empty ())
- fail << "no upstream branch set for local branch '"
- << s.branch << "'" <<
- info << "run 'git push --set-upstream' to set";
+ {
+ if (s.upstream.empty ())
+ fail << "no upstream branch set for local branch '"
+ << s.branch << "'" <<
+ info << "run 'git push --set-upstream' to set";
+
+ optional<string> rem (git_line (git_ver,
+ prj,
+ false /* ignore_error */,
+ "config",
+ "branch." + s.branch + ".remote"));
+
+ if (!rem)
+ fail << "unable to obtain remote for '" << s.branch << "'";
+
+ // For good measure verify that the remote name is a prefix for the
+ // upstream branch.
+ //
+ size_t n (rem->size ());
+ if (s.upstream.compare (0, n, *rem) != 0 ||
+ !path::traits_type::is_separator (s.upstream[n]))
+ fail << "remote '" << *rem << "' is not a prefix for upstream "
+ << "branch '" << s.upstream << "'";
- size_t p (path::traits_type::rfind_separator (s.upstream));
- branch = p != string::npos ? string (s.upstream, p + 1) : s.upstream;
+ branch.assign (s.upstream, n + 1);
+ }
// Note: not forcible (for now). While the use case is valid, the
// current and committed package versions are likely to differ (in
diff --git a/bdep/release.cxx b/bdep/release.cxx
index 2532242..66b4a30 100644
--- a/bdep/release.cxx
+++ b/bdep/release.cxx
@@ -1189,17 +1189,24 @@ namespace bdep
// the repository and refspecs explicitly.
//
// Upstream is normally in the <remote>/<branch> form, for example
- // 'origin/master'.
+ // 'origin/master'. Note, however, that if any of these names contains
+ // '/', then the split is ambiguous. Thus, we retrieve the remote name
+ // via git-config and use it to also deduce the remote branch name from
+ // the upstream branch.
//
string remote;
string brspec;
{
- size_t p (path::traits_type::rfind_separator (st.upstream));
+ optional<string> rem (git_line (git_ver,
+ prj.path,
+ false /* ignore_error */,
+ "config",
+ "branch." + st.branch + ".remote"));
- if (p == string::npos)
- fail << "unable to extract remote from '" << st.upstream << "'";
+ if (!rem)
+ fail << "unable to obtain remote for '" << st.branch << "'";
- remote = string (st.upstream, 0, p);
+ remote = move (*rem);
// Push the branch if the mode is other than tagging (and so the
// version change is committed) or the local branch is ahead (probably
@@ -1213,7 +1220,16 @@ namespace bdep
//
brspec = st.branch;
- string b (st.upstream, p + 1);
+ // For good measure verify that the remote name is a prefix for the
+ // upstream branch.
+ //
+ size_t n (remote.size ());
+ if (st.upstream.compare (0, n, remote) != 0 ||
+ !path::traits_type::is_separator (st.upstream[n]))
+ fail << "remote '" << remote << "' is not a prefix for upstream "
+ << "branch '" << st.upstream << "'";
+
+ string b (st.upstream, n + 1);
if (b != st.branch)
{
brspec += ':';