From: Junio C Hamano Date: Wed, 3 Apr 2013 16:34:53 +0000 (-0700) Subject: Merge branch 'jc/sha1-name-object-peeler' X-Git-Tag: v1.8.3-rc0~118 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/1b7b22bfd0fb1fe62cf9d40e2b1de031cc48771d?hp=-c Merge branch 'jc/sha1-name-object-peeler' There was no good way to ask "I have a random string that came from outside world. I want to turn it into a 40-hex object name while making sure such an object exists". A new peeling suffix ^{object} can be used for that purpose, together with "rev-parse --verify". * jc/sha1-name-object-peeler: peel_onion(): teach $foo^{object} peeler peel_onion: disambiguate to favor tree-ish when we know we want a tree-ish --- 1b7b22bfd0fb1fe62cf9d40e2b1de031cc48771d diff --combined Documentation/revisions.txt index 314e25da73,e82a4db61c..1707d451b6 --- a/Documentation/revisions.txt +++ b/Documentation/revisions.txt @@@ -23,7 -23,7 +23,7 @@@ blobs contained in a commit A symbolic ref name. E.g. 'master' typically means the commit object referenced by 'refs/heads/master'. If you happen to have both 'heads/master' and 'tags/master', you can - explicitly say 'heads/master' to tell git which one you mean. + explicitly say 'heads/master' to tell Git which one you mean. When ambiguous, a '' is disambiguated by taking the first match in the following rules: @@@ -116,6 -116,11 +116,11 @@@ some output processing may assume ref n object of that type is found or the object cannot be dereferenced anymore (in which case, barf). '{caret}0' is a short-hand for '{caret}\{commit\}'. + + + 'rev{caret}\{object\}' can be used to make sure 'rev' names an + object that exists, without requiring 'rev' to be a tag, and + without dereferencing 'rev'; because a tag is already an object, + it does not have to be dereferenced even once to get to an object. '{caret}\{\}', e.g. 'v0.99.8{caret}\{\}':: A suffix '{caret}' followed by an empty brace pair diff --combined sha1_name.c index 2fbda48e02,85b6e75741..3820f28ae7 --- a/sha1_name.c +++ b/sha1_name.c @@@ -594,7 -594,7 +594,7 @@@ struct object *peel_to_type(const char while (1) { if (!o || (!o->parsed && !parse_object(o->sha1))) return NULL; - if (o->type == expected_type) + if (expected_type == OBJ_ANY || o->type == expected_type) return o; if (o->type == OBJ_TAG) o = ((struct tag*) o)->tagged; @@@ -645,6 -645,8 +645,8 @@@ static int peel_onion(const char *name expected_type = OBJ_TREE; else if (!strncmp(blob_type, sp, 4) && sp[4] == '}') expected_type = OBJ_BLOB; + else if (!prefixcmp(sp, "object}")) + expected_type = OBJ_ANY; else if (sp[0] == '}') expected_type = OBJ_NONE; else if (sp[0] == '/') @@@ -654,6 -656,8 +656,8 @@@ if (expected_type == OBJ_COMMIT) lookup_flags = GET_SHA1_COMMITTISH; + else if (expected_type == OBJ_TREE) + lookup_flags = GET_SHA1_TREEISH; if (get_sha1_1(name, sp - name - 2, outer, lookup_flags)) return -1; @@@ -856,8 -860,8 +860,8 @@@ static int get_sha1_oneline(const char } struct grab_nth_branch_switch_cbdata { - long cnt, alloc; - struct strbuf *buf; + int remaining; + struct strbuf buf; }; static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1, @@@ -867,6 -871,7 +871,6 @@@ struct grab_nth_branch_switch_cbdata *cb = cb_data; const char *match = NULL, *target = NULL; size_t len; - int nth; if (!prefixcmp(message, "checkout: moving from ")) { match = message + strlen("checkout: moving from "); @@@ -875,12 -880,11 +879,12 @@@ if (!match || !target) return 0; - - len = target - match; - nth = cb->cnt++ % cb->alloc; - strbuf_reset(&cb->buf[nth]); - strbuf_add(&cb->buf[nth], match, len); + if (--(cb->remaining) == 0) { + len = target - match; + strbuf_reset(&cb->buf); + strbuf_add(&cb->buf, match, len); + return 1; /* we are done */ + } return 0; } @@@ -891,7 -895,7 +895,7 @@@ static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf) { long nth; - int i, retval; + int retval; struct grab_nth_branch_switch_cbdata cb; const char *brace; char *num_end; @@@ -901,22 -905,34 +905,22 @@@ brace = strchr(name, '}'); if (!brace) return -1; - nth = strtol(name+3, &num_end, 10); + nth = strtol(name + 3, &num_end, 10); if (num_end != brace) return -1; if (nth <= 0) return -1; - cb.alloc = nth; - cb.buf = xmalloc(nth * sizeof(struct strbuf)); - for (i = 0; i < nth; i++) - strbuf_init(&cb.buf[i], 20); - cb.cnt = 0; + cb.remaining = nth; + strbuf_init(&cb.buf, 20); + retval = 0; - for_each_recent_reflog_ent("HEAD", grab_nth_branch_switch, 40960, &cb); - if (cb.cnt < nth) { - cb.cnt = 0; - for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb); - } - if (cb.cnt < nth) - goto release_return; - i = cb.cnt % nth; - strbuf_reset(buf); - strbuf_add(buf, cb.buf[i].buf, cb.buf[i].len); - retval = brace-name+1; - -release_return: - for (i = 0; i < nth; i++) - strbuf_release(&cb.buf[i]); - free(cb.buf); + if (0 < for_each_reflog_ent_reverse("HEAD", grab_nth_branch_switch, &cb)) { + strbuf_reset(buf); + strbuf_add(buf, cb.buf.buf, cb.buf.len); + retval = brace - name + 1; + } + strbuf_release(&cb.buf); return retval; }