summaryrefslogtreecommitdiff
path: root/builtin/push.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2013-12-27 22:57:50 (GMT)
committerJunio C Hamano <gitster@pobox.com>2013-12-27 22:57:50 (GMT)
commit7cdebd8a2039cb3ec717b880709ea6dfd824e3c4 (patch)
treef07fff24eb335bc59849625af60378a869f766a8 /builtin/push.c
parent7794a680e63a2a11b73cb1194653662f2769a792 (diff)
parentfc9261ca611080b1dae76b86b3bf5f36d592042f (diff)
downloadgit-7cdebd8a2039cb3ec717b880709ea6dfd824e3c4.zip
git-7cdebd8a2039cb3ec717b880709ea6dfd824e3c4.tar.gz
git-7cdebd8a2039cb3ec717b880709ea6dfd824e3c4.tar.bz2
Merge branch 'jc/push-refmap'
Make "git push origin master" update the same ref that would be updated by our 'master' when "git push origin" (no refspecs) is run while the 'master' branch is checked out, which makes "git push" more symmetric to "git fetch" and more usable for the triangular workflow. * jc/push-refmap: push: also use "upstream" mapping when pushing a single ref push: use remote.$name.push as a refmap builtin/push.c: use strbuf instead of manual allocation
Diffstat (limited to 'builtin/push.c')
-rw-r--r--builtin/push.c84
1 files changed, 62 insertions, 22 deletions
diff --git a/builtin/push.c b/builtin/push.c
index a73982a..0e50ddb 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -35,35 +35,75 @@ static void add_refspec(const char *ref)
refspec[refspec_nr-1] = ref;
}
-static void set_refspecs(const char **refs, int nr)
+static const char *map_refspec(const char *ref,
+ struct remote *remote, struct ref *local_refs)
{
+ struct ref *matched = NULL;
+
+ /* Does "ref" uniquely name our ref? */
+ if (count_refspec_match(ref, local_refs, &matched) != 1)
+ return ref;
+
+ if (remote->push) {
+ struct refspec query;
+ memset(&query, 0, sizeof(struct refspec));
+ query.src = matched->name;
+ if (!query_refspecs(remote->push, remote->push_refspec_nr, &query) &&
+ query.dst) {
+ struct strbuf buf = STRBUF_INIT;
+ strbuf_addf(&buf, "%s%s:%s",
+ query.force ? "+" : "",
+ query.src, query.dst);
+ return strbuf_detach(&buf, NULL);
+ }
+ }
+
+ if (push_default == PUSH_DEFAULT_UPSTREAM &&
+ !prefixcmp(matched->name, "refs/heads/")) {
+ struct branch *branch = branch_get(matched->name + 11);
+ if (branch->merge_nr == 1 && branch->merge[0]->src) {
+ struct strbuf buf = STRBUF_INIT;
+ strbuf_addf(&buf, "%s:%s",
+ ref, branch->merge[0]->src);
+ return strbuf_detach(&buf, NULL);
+ }
+ }
+
+ return ref;
+}
+
+static void set_refspecs(const char **refs, int nr, const char *repo)
+{
+ struct remote *remote = NULL;
+ struct ref *local_refs = NULL;
int i;
+
for (i = 0; i < nr; i++) {
const char *ref = refs[i];
if (!strcmp("tag", ref)) {
- char *tag;
- int len;
+ struct strbuf tagref = STRBUF_INIT;
if (nr <= ++i)
die(_("tag shorthand without <tag>"));
- len = strlen(refs[i]) + 11;
- if (deleterefs) {
- tag = xmalloc(len+1);
- strcpy(tag, ":refs/tags/");
- } else {
- tag = xmalloc(len);
- strcpy(tag, "refs/tags/");
+ ref = refs[i];
+ if (deleterefs)
+ strbuf_addf(&tagref, ":refs/tags/%s", ref);
+ else
+ strbuf_addf(&tagref, "refs/tags/%s", ref);
+ ref = strbuf_detach(&tagref, NULL);
+ } else if (deleterefs) {
+ struct strbuf delref = STRBUF_INIT;
+ if (strchr(ref, ':'))
+ die(_("--delete only accepts plain target ref names"));
+ strbuf_addf(&delref, ":%s", ref);
+ ref = strbuf_detach(&delref, NULL);
+ } else if (!strchr(ref, ':')) {
+ if (!remote) {
+ /* lazily grab remote and local_refs */
+ remote = remote_get(repo);
+ local_refs = get_local_heads();
}
- strcat(tag, refs[i]);
- ref = tag;
- } else if (deleterefs && !strchr(ref, ':')) {
- char *delref;
- int len = strlen(ref)+1;
- delref = xmalloc(len+1);
- strcpy(delref, ":");
- strcat(delref, ref);
- ref = delref;
- } else if (deleterefs)
- die(_("--delete only accepts plain target ref names"));
+ ref = map_refspec(ref, remote, local_refs);
+ }
add_refspec(ref);
}
}
@@ -501,7 +541,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
if (argc > 0) {
repo = argv[0];
- set_refspecs(argv + 1, argc - 1);
+ set_refspecs(argv + 1, argc - 1, repo);
}
rc = do_push(repo, flags);