diff options
Diffstat (limited to 'remote.c')
-rw-r--r-- | remote.c | 134 |
1 files changed, 128 insertions, 6 deletions
@@ -1,6 +1,9 @@ #include "cache.h" #include "remote.h" #include "refs.h" +#include "commit.h" +#include "diff.h" +#include "revision.h" static struct refspec s_tag_refspec = { 0, @@ -295,6 +298,17 @@ static void read_branches_file(struct remote *remote) } add_url_alias(remote, p); add_fetch_refspec(remote, strbuf_detach(&branch, 0)); + /* + * Cogito compatible push: push current HEAD to remote #branch + * (master if missing) + */ + strbuf_init(&branch, 0); + strbuf_addstr(&branch, "HEAD"); + if (frag) + strbuf_addf(&branch, ":refs/heads/%s", frag); + else + strbuf_addstr(&branch, ":refs/heads/master"); + add_push_refspec(remote, strbuf_detach(&branch, 0)); remote->fetch_tags = 1; /* always auto-follow */ } @@ -339,13 +353,14 @@ static int handle_config(const char *key, const char *value, void *cb) if (prefixcmp(key, "remote.")) return 0; name = key + 7; + if (*name == '/') { + warning("Config remote shorthand cannot begin with '/': %s", + name); + return 0; + } subkey = strrchr(name, '.'); if (!subkey) return error("Config with no key for remote %s", name); - if (*subkey == '/') { - warning("Config remote shorthand cannot begin with '/': %s", name); - return 0; - } remote = make_remote(name, subkey - name); if (!strcmp(subkey, ".mirror")) remote->mirror = git_config_bool(key, value); @@ -576,8 +591,7 @@ int valid_fetch_refspec(const char *fetch_refspec_str) struct refspec *refspec; refspec = parse_refspec_internal(1, fetch_refspec, 1, 1); - if (refspec) - free(refspec); + free(refspec); return !!refspec; } @@ -1238,3 +1252,111 @@ int resolve_remote_symref(struct ref *ref, struct ref *list) } return 1; } + +/* + * Return true if there is anything to report, otherwise false. + */ +int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs) +{ + unsigned char sha1[20]; + struct commit *ours, *theirs; + char symmetric[84]; + struct rev_info revs; + const char *rev_argv[10], *base; + int rev_argc; + + /* + * Nothing to report unless we are marked to build on top of + * somebody else. + */ + if (!branch || + !branch->merge || !branch->merge[0] || !branch->merge[0]->dst) + return 0; + + /* + * If what we used to build on no longer exists, there is + * nothing to report. + */ + base = branch->merge[0]->dst; + if (!resolve_ref(base, sha1, 1, NULL)) + return 0; + theirs = lookup_commit(sha1); + if (!theirs) + return 0; + + if (!resolve_ref(branch->refname, sha1, 1, NULL)) + return 0; + ours = lookup_commit(sha1); + if (!ours) + return 0; + + /* are we the same? */ + if (theirs == ours) + return 0; + + /* Run "rev-list --left-right ours...theirs" internally... */ + rev_argc = 0; + rev_argv[rev_argc++] = NULL; + rev_argv[rev_argc++] = "--left-right"; + rev_argv[rev_argc++] = symmetric; + rev_argv[rev_argc++] = "--"; + rev_argv[rev_argc] = NULL; + + strcpy(symmetric, sha1_to_hex(ours->object.sha1)); + strcpy(symmetric + 40, "..."); + strcpy(symmetric + 43, sha1_to_hex(theirs->object.sha1)); + + init_revisions(&revs, NULL); + setup_revisions(rev_argc, rev_argv, &revs, NULL); + prepare_revision_walk(&revs); + + /* ... and count the commits on each side. */ + *num_ours = 0; + *num_theirs = 0; + while (1) { + struct commit *c = get_revision(&revs); + if (!c) + break; + if (c->object.flags & SYMMETRIC_LEFT) + (*num_ours)++; + else + (*num_theirs)++; + } + + /* clear object flags smudged by the above traversal */ + clear_commit_marks(ours, ALL_REV_FLAGS); + clear_commit_marks(theirs, ALL_REV_FLAGS); + return 1; +} + +/* + * Return true when there is anything to report, otherwise false. + */ +int format_tracking_info(struct branch *branch, struct strbuf *sb) +{ + int num_ours, num_theirs; + const char *base; + + if (!stat_tracking_info(branch, &num_ours, &num_theirs)) + return 0; + + base = branch->merge[0]->dst; + if (!prefixcmp(base, "refs/remotes/")) { + base += strlen("refs/remotes/"); + } + if (!num_theirs) + strbuf_addf(sb, "Your branch is ahead of '%s' " + "by %d commit%s.\n", + base, num_ours, (num_ours == 1) ? "" : "s"); + else if (!num_ours) + strbuf_addf(sb, "Your branch is behind '%s' " + "by %d commit%s, " + "and can be fast-forwarded.\n", + base, num_theirs, (num_theirs == 1) ? "" : "s"); + else + strbuf_addf(sb, "Your branch and '%s' have diverged,\n" + "and have %d and %d different commit(s) each, " + "respectively.\n", + base, num_ours, num_theirs); + return 1; +} |