return remote_for_branch(branch, explicit);
}
+const char *remote_ref_for_branch(struct branch *branch, int for_push,
+ int *explicit)
+{
+ if (branch) {
+ if (!for_push) {
+ if (branch->merge_nr) {
+ if (explicit)
+ *explicit = 1;
+ return branch->merge_name[0];
+ }
+ } else {
+ const char *dst, *remote_name =
+ pushremote_for_branch(branch, NULL);
+ struct remote *remote = remote_get(remote_name);
+
+ if (remote && remote->push_refspec_nr &&
+ (dst = apply_refspecs(remote->push,
+ remote->push_refspec_nr,
+ branch->refname))) {
+ if (explicit)
+ *explicit = 1;
+ return dst;
+ }
+ }
+ }
+ if (explicit)
+ *explicit = 0;
+ return "";
+}
+
static struct remote *remote_get_1(const char *name,
const char *(*get_default)(struct branch *, int *))
{
strcmp(ret->remote_name, "."))
continue;
if (dwim_ref(ret->merge_name[i], strlen(ret->merge_name[i]),
- oid.hash, &ref) == 1)
+ &oid, &ref) == 1)
ret->merge[i]->dst = ref;
else
ret->merge[i]->dst = xstrdup(ret->merge_name[i]);
}
/*
- * Compare a branch with its upstream, and save their differences (number
- * of commits) in *num_ours and *num_theirs. The name of the upstream branch
- * (or NULL if no upstream is defined) is returned via *upstream_name, if it
- * is not itself NULL.
+ * Lookup the upstream branch for the given branch and if present, optionally
+ * compute the commit ahead/behind values for the pair.
+ *
+ * If abf is AHEAD_BEHIND_FULL, compute the full ahead/behind and return the
+ * counts in *num_ours and *num_theirs. If abf is AHEAD_BEHIND_QUICK, skip
+ * the (potentially expensive) a/b computation (*num_ours and *num_theirs are
+ * set to zero).
+ *
+ * The name of the upstream branch (or NULL if no upstream is defined) is
+ * returned via *upstream_name, if it is not itself NULL.
*
* Returns -1 if num_ours and num_theirs could not be filled in (e.g., no
- * upstream defined, or ref does not exist), 0 otherwise.
+ * upstream defined, or ref does not exist). Returns 0 if the commits are
+ * identical. Returns 1 if commits are different.
*/
int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
- const char **upstream_name)
+ const char **upstream_name, enum ahead_behind_flags abf)
{
struct object_id oid;
struct commit *ours, *theirs;
return -1;
/* Cannot stat if what we used to build on no longer exists */
- if (read_ref(base, oid.hash))
+ if (read_ref(base, &oid))
return -1;
theirs = lookup_commit_reference(&oid);
if (!theirs)
return -1;
- if (read_ref(branch->refname, oid.hash))
+ if (read_ref(branch->refname, &oid))
return -1;
ours = lookup_commit_reference(&oid);
if (!ours)
return -1;
+ *num_theirs = *num_ours = 0;
+
/* are we the same? */
- if (theirs == ours) {
- *num_theirs = *num_ours = 0;
+ if (theirs == ours)
return 0;
- }
+ if (abf == AHEAD_BEHIND_QUICK)
+ return 1;
+ if (abf != AHEAD_BEHIND_FULL)
+ BUG("stat_tracking_info: invalid abf '%d'", abf);
/* Run "rev-list --left-right ours...theirs" internally... */
argv_array_push(&argv, ""); /* ignored */
die("revision walk setup failed");
/* ... and count the commits on each side. */
- *num_ours = 0;
- *num_theirs = 0;
while (1) {
struct commit *c = get_revision(&revs);
if (!c)
clear_commit_marks(theirs, ALL_REV_FLAGS);
argv_array_clear(&argv);
- return 0;
+ return 1;
}
/*
char *base;
int upstream_is_gone = 0;
- if (stat_tracking_info(branch, &ours, &theirs, &full_base) < 0) {
+ if (stat_tracking_info(branch, &ours, &theirs, &full_base,
+ AHEAD_BEHIND_FULL) < 0) {
if (!full_base)
return 0;
upstream_is_gone = 1;
dst = apply_refspecs(remote->fetch, remote->fetch_refspec_nr, refname);
if (!dst)
return -1; /* no tracking ref for refname at remote */
- if (read_ref(dst, oid->hash))
+ if (read_ref(dst, oid))
return -1; /* we know what the tracking ref is but we cannot read it */
return 0;
}