unsigned candidate_ok:1;
unsigned disambiguate_fn_used:1;
unsigned ambiguous:1;
+ unsigned always_call_fn:1;
};
static void update_candidates(struct disambiguate_state *ds, const unsigned char *current)
{
+ if (ds->always_call_fn) {
+ ds->ambiguous = ds->fn(current, ds->cb_data) ? 1 : 0;
+ return;
+ }
if (!ds->candidate_exists) {
/* this is the first candidate */
hashcpy(ds->candidate, current);
return kind == OBJ_BLOB;
}
-static int get_short_sha1(const char *name, int len, unsigned char *sha1,
- unsigned flags)
+static int prepare_prefixes(const char *name, int len,
+ unsigned char *bin_pfx,
+ char *hex_pfx)
{
- int i, status;
- char hex_pfx[40];
- unsigned char bin_pfx[20];
- struct disambiguate_state ds;
- int quietly = !!(flags & GET_SHA1_QUIETLY);
+ int i;
- if (len < MINIMUM_ABBREV || len > 40)
- return -1;
hashclr(bin_pfx);
memset(hex_pfx, 'x', 40);
for (i = 0; i < len ;i++) {
val <<= 4;
bin_pfx[i >> 1] |= val;
}
+ return 0;
+}
+
+static int get_short_sha1(const char *name, int len, unsigned char *sha1,
+ unsigned flags)
+{
+ int status;
+ char hex_pfx[40];
+ unsigned char bin_pfx[20];
+ struct disambiguate_state ds;
+ int quietly = !!(flags & GET_SHA1_QUIETLY);
+
+ if (len < MINIMUM_ABBREV || len > 40)
+ return -1;
+ if (prepare_prefixes(name, len, bin_pfx, hex_pfx) < 0)
+ return -1;
prepare_alt_odb();
return status;
}
+
+int for_each_abbrev(const char *prefix, each_abbrev_fn fn, void *cb_data)
+{
+ char hex_pfx[40];
+ unsigned char bin_pfx[20];
+ struct disambiguate_state ds;
+ int len = strlen(prefix);
+
+ if (len < MINIMUM_ABBREV || len > 40)
+ return -1;
+ if (prepare_prefixes(prefix, len, bin_pfx, hex_pfx) < 0)
+ return -1;
+
+ prepare_alt_odb();
+
+ memset(&ds, 0, sizeof(ds));
+ ds.always_call_fn = 1;
+ ds.cb_data = cb_data;
+ ds.fn = fn;
+
+ find_short_object_filename(len, hex_pfx, &ds);
+ find_short_packed_object(len, bin_pfx, &ds);
+ return ds.ambiguous;
+}
+
const char *find_unique_abbrev(const unsigned char *sha1, int len)
{
int status, exists;
len = cp + tmp_len - name;
cp = xstrndup(name, cp - name);
upstream = branch_get(*cp ? cp : NULL);
- if (!upstream
- || !upstream->merge
- || !upstream->merge[0]->dst)
- return error("No upstream branch found for '%s'", cp);
+ /*
+ * Upstream can be NULL only if cp refers to HEAD and HEAD
+ * points to something different than a branch.
+ */
+ if (!upstream)
+ return error(_("HEAD does not point to a branch"));
+ if (!upstream->merge || !upstream->merge[0]->dst) {
+ if (!ref_exists(upstream->refname))
+ return error(_("No such branch: '%s'"), cp);
+ if (!upstream->merge)
+ return error(_("No upstream configured for branch '%s'"),
+ upstream->name);
+ return error(
+ _("Upstream branch '%s' not stored as a remote-tracking branch"),
+ upstream->merge[0]->src);
+ }
free(cp);
cp = shorten_unambiguous_ref(upstream->merge[0]->dst, 0);
strbuf_reset(buf);
if (new_filename)
filename = new_filename;
ret = get_tree_entry(tree_sha1, filename, sha1, &oc->mode);
- if (only_to_die) {
+ if (ret && only_to_die) {
diagnose_invalid_sha1_path(prefix, filename,
tree_sha1, object_name);
free(object_name);