From: Jeff King <peff@peff.net>
To: git@vger.kernel.org
Subject: [PATCH 07/12] remote.c: add branch_get_push
Date: Fri, 1 May 2015 18:53:31 -0400 [thread overview]
Message-ID: <20150501225331.GG1534@peff.net> (raw)
In-Reply-To: <20150501224414.GA25551@peff.net>
In a triangular workflow, the place you pull from and the
place you push to may be different. As we have
branch_get_upstream for the former, this patch adds
branch_get_push for the latter (and as the former implements
@{upstream}, so will this implement @{push} in a future
patch).
Note that the memory-handling for the return value bears
some explanation. Some code paths require allocating a new
string, and some let us return an existing string. We should
provide a consistent interface to the caller, so it knows
whether to free the result or not.
We could do so by xstrdup-ing any existing strings, and
having the caller always free. But that makes us
inconsistent with branch_get_upstream, so we would prefer to
simply take ownership of the resulting string. We do so by
storing it inside the "struct branch", just as we do with
the upstream refname (in that case we compute it when the
branch is created, but there's no reason not to just fill
it in lazily in this case).
Signed-off-by: Jeff King <peff@peff.net>
---
This patch is new in v2, but the logic is basically ripped from
sha1_name.c in v1.
remote.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
remote.h | 10 ++++++++
2 files changed, 95 insertions(+)
diff --git a/remote.c b/remote.c
index 146b94d..7f0fe28 100644
--- a/remote.c
+++ b/remote.c
@@ -1727,6 +1727,91 @@ const char *branch_get_upstream(struct branch *branch, struct strbuf *err)
return branch->merge[0]->dst;
}
+static const char *tracking_for_push_dest(struct remote *remote,
+ const char *refname,
+ struct strbuf *err)
+{
+ char *ret;
+
+ ret = apply_refspecs(remote->fetch, remote->fetch_refspec_nr, refname);
+ if (!ret)
+ return error_buf(err,
+ _("push destination '%s' on remote '%s' has no local tracking branch"),
+ refname, remote->name);
+ return ret;
+}
+
+static const char *branch_get_push_1(struct branch *branch, struct strbuf *err)
+{
+ struct remote *remote;
+
+ if (!branch)
+ return error_buf(err, _("HEAD does not point to a branch"));
+
+ remote = remote_get(pushremote_for_branch(branch, NULL));
+ if (!remote)
+ return error_buf(err,
+ _("branch '%s' has no remote for pushing"),
+ branch->name);
+
+ if (remote->push_refspec_nr) {
+ char *dst;
+ const char *ret;
+
+ dst = apply_refspecs(remote->push, remote->push_refspec_nr,
+ branch->refname);
+ if (!dst)
+ return error_buf(err,
+ _("push refspecs for '%s' do not include '%s'"),
+ remote->name, branch->name);
+
+ ret = tracking_for_push_dest(remote, dst, err);
+ free(dst);
+ return ret;
+ }
+
+ if (remote->mirror)
+ return tracking_for_push_dest(remote, branch->refname, err);
+
+ switch (push_default) {
+ case PUSH_DEFAULT_NOTHING:
+ return error_buf(err, _("push has no destination (push.default is 'nothing')"));
+
+ case PUSH_DEFAULT_MATCHING:
+ case PUSH_DEFAULT_CURRENT:
+ return tracking_for_push_dest(remote, branch->refname, err);
+
+ case PUSH_DEFAULT_UPSTREAM:
+ return branch_get_upstream(branch, err);
+
+ case PUSH_DEFAULT_UNSPECIFIED:
+ case PUSH_DEFAULT_SIMPLE:
+ {
+ const char *up, *cur;
+
+ up = branch_get_upstream(branch, err);
+ if (!up)
+ return NULL;
+ cur = tracking_for_push_dest(remote, branch->refname, err);
+ if (!cur)
+ return NULL;
+ if (strcmp(cur, up))
+ return error_buf(err,
+ _("cannot resolve 'simple' push to a single destination"));
+ return cur;
+ }
+ }
+
+ die("BUG: unhandled push situation");
+}
+
+const char *branch_get_push(struct branch *branch, struct strbuf *err)
+{
+ if (!branch->push_tracking_ref)
+ branch->push_tracking_ref = branch_get_push_1(branch, err);
+ return branch->push_tracking_ref;
+}
+
static int ignore_symref_update(const char *refname)
{
unsigned char sha1[20];
diff --git a/remote.h b/remote.h
index 03ca005..3326f2b 100644
--- a/remote.h
+++ b/remote.h
@@ -209,6 +209,8 @@ struct branch {
struct refspec **merge;
int merge_nr;
int merge_alloc;
+
+ const char *push_tracking_ref;
};
struct branch *branch_get(const char *name);
@@ -229,6 +231,14 @@ int branch_merge_matches(struct branch *, int n, const char *);
*/
const char *branch_get_upstream(struct branch *branch, struct strbuf *err);
+/**
+ * Return the tracking branch that corresponds to the ref we would push to
+ * given a bare `git push` while `branch` is checked out.
+ *
+ * The return value and `err` conventions match those of `branch_get_upstream`.
+ */
+const char *branch_get_push(struct branch *branch, struct strbuf *err);
+
/* Flags to match_refs. */
enum match_refs_flags {
MATCH_REFS_NONE = 0,
--
2.4.0.rc3.477.gc25258d
next prev parent reply other threads:[~2015-05-01 22:53 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-01 22:44 [PATCH v2 0/12] implement @{push} shorthand Jeff King
2015-05-01 22:44 ` [PATCH 01/12] remote.c: drop default_remote_name variable Jeff King
2015-05-01 22:45 ` [PATCH 02/12] remote.c: drop "remote" pointer from "struct branch" Jeff King
2015-05-03 3:34 ` Eric Sunshine
2015-05-05 19:31 ` Jeff King
2015-05-07 9:33 ` Jeff King
2015-05-01 22:45 ` [PATCH 03/12] remote.c: hoist branch.*.remote lookup out of remote_get_1 Jeff King
2015-05-01 22:46 ` [PATCH 04/12] remote.c: provide per-branch pushremote name Jeff King
2015-05-03 4:51 ` Eric Sunshine
2015-05-05 19:33 ` Jeff King
2015-05-05 19:48 ` Eric Sunshine
2015-05-07 9:38 ` Jeff King
2015-05-08 16:13 ` Eric Sunshine
2015-05-01 22:47 ` [PATCH 05/12] remote.c: introduce branch_get_upstream helper Jeff King
2015-05-01 22:52 ` [PATCH 06/12] remote.c: report specific errors from branch_get_upstream Jeff King
2015-05-01 22:53 ` Jeff King [this message]
2015-05-01 22:53 ` [PATCH 08/12] sha1_name: refactor upstream_mark Jeff King
2015-05-01 22:55 ` [PATCH 09/12] sha1_name: refactor interpret_upstream_mark Jeff King
2015-05-01 22:55 ` [PATCH 10/12] sha1_name: implement @{push} shorthand Jeff King
2015-05-01 22:55 ` [PATCH 11/12] for-each-ref: use skip_prefix instead of starts_with Jeff King
2015-05-01 22:56 ` [PATCH 12/12] for-each-ref: accept "%(push)" format Jeff King
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150501225331.GG1534@peff.net \
--to=peff@peff.net \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).