diff options
Diffstat (limited to 'object-name.c')
| -rw-r--r-- | object-name.c | 145 |
1 files changed, 108 insertions, 37 deletions
diff --git a/object-name.c b/object-name.c index 88d1313028..11aa0e6afc 100644 --- a/object-name.c +++ b/object-name.c @@ -19,7 +19,7 @@ #include "oidtree.h" #include "packfile.h" #include "pretty.h" -#include "object-store-ll.h" +#include "object-file.h" #include "read-cache-ll.h" #include "repo-settings.h" #include "repository.h" @@ -28,6 +28,7 @@ #include "commit-reach.h" #include "date.h" #include "object-file-convert.h" +#include "prio-queue.h" static int get_oid_oneline(struct repository *r, const char *, struct object_id *, const struct commit_list *); @@ -112,10 +113,10 @@ static enum cb_next match_prefix(const struct object_id *oid, void *arg) static void find_short_object_filename(struct disambiguate_state *ds) { - struct object_directory *odb; + struct odb_source *source; - for (odb = ds->repo->objects->odb; odb && !ds->ambiguous; odb = odb->next) - oidtree_each(odb_loose_cache(odb, &ds->bin_pfx), + for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) + oidtree_each(odb_loose_cache(source, &ds->bin_pfx), &ds->bin_pfx, ds->len, match_prefix, ds); } @@ -198,16 +199,20 @@ static void unique_in_pack(struct packed_git *p, static void find_short_packed_object(struct disambiguate_state *ds) { - struct multi_pack_index *m; + struct odb_source *source; struct packed_git *p; /* Skip, unless oids from the storage hash algorithm are wanted */ if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo)) return; - for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous; - m = m->next) - unique_in_midx(m, ds); + odb_prepare_alternates(ds->repo->objects); + for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) { + struct multi_pack_index *m = get_multi_pack_index(source); + if (m) + unique_in_midx(m, ds); + } + for (p = get_packed_git(ds->repo); p && !ds->ambiguous; p = p->next) unique_in_pack(p, ds); @@ -251,7 +256,7 @@ static int disambiguate_commit_only(struct repository *r, const struct object_id *oid, void *cb_data UNUSED) { - int kind = oid_object_info(r, oid, NULL); + int kind = odb_read_object_info(r->objects, oid, NULL); return kind == OBJ_COMMIT; } @@ -262,7 +267,7 @@ static int disambiguate_committish_only(struct repository *r, struct object *obj; int kind; - kind = oid_object_info(r, oid, NULL); + kind = odb_read_object_info(r->objects, oid, NULL); if (kind == OBJ_COMMIT) return 1; if (kind != OBJ_TAG) @@ -279,7 +284,7 @@ static int disambiguate_tree_only(struct repository *r, const struct object_id *oid, void *cb_data UNUSED) { - int kind = oid_object_info(r, oid, NULL); + int kind = odb_read_object_info(r->objects, oid, NULL); return kind == OBJ_TREE; } @@ -290,7 +295,7 @@ static int disambiguate_treeish_only(struct repository *r, struct object *obj; int kind; - kind = oid_object_info(r, oid, NULL); + kind = odb_read_object_info(r->objects, oid, NULL); if (kind == OBJ_TREE || kind == OBJ_COMMIT) return 1; if (kind != OBJ_TAG) @@ -307,7 +312,7 @@ static int disambiguate_blob_only(struct repository *r, const struct object_id *oid, void *cb_data UNUSED) { - int kind = oid_object_info(r, oid, NULL); + int kind = odb_read_object_info(r->objects, oid, NULL); return kind == OBJ_BLOB; } @@ -376,7 +381,7 @@ static int init_object_disambiguation(struct repository *r, ds->hex_pfx[len] = '\0'; ds->repo = r; ds->bin_pfx.algo = algo ? hash_algo_by_ptr(algo) : GIT_HASH_UNKNOWN; - prepare_alt_odb(r); + odb_prepare_alternates(r->objects); return 0; } @@ -399,7 +404,7 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) return 0; hash = repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV); - type = oid_object_info(ds->repo, oid, NULL); + type = odb_read_object_info(ds->repo->objects, oid, NULL); if (type < 0) { /* @@ -514,8 +519,8 @@ static int sort_ambiguous(const void *va, const void *vb, void *ctx) { struct repository *sort_ambiguous_repo = ctx; const struct object_id *a = va, *b = vb; - int a_type = oid_object_info(sort_ambiguous_repo, a, NULL); - int b_type = oid_object_info(sort_ambiguous_repo, b, NULL); + int a_type = odb_read_object_info(sort_ambiguous_repo->objects, a, NULL); + int b_type = odb_read_object_info(sort_ambiguous_repo->objects, b, NULL); int a_type_sort; int b_type_sort; @@ -792,11 +797,15 @@ static void find_abbrev_len_for_pack(struct packed_git *p, static void find_abbrev_len_packed(struct min_abbrev_data *mad) { - struct multi_pack_index *m; struct packed_git *p; - for (m = get_multi_pack_index(mad->repo); m; m = m->next) - find_abbrev_len_for_midx(m, mad); + odb_prepare_alternates(mad->repo->objects); + for (struct odb_source *source = mad->repo->objects->sources; source; source = source->next) { + struct multi_pack_index *m = get_multi_pack_index(source); + if (m) + find_abbrev_len_for_midx(m, mad); + } + for (p = get_packed_git(mad->repo); p; p = p->next) find_abbrev_len_for_pack(p, mad); } @@ -961,7 +970,9 @@ static int get_oid_basic(struct repository *r, const char *str, int len, int fatal = !(flags & GET_OID_QUIETLY); if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) { - if (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) { + if (!(flags & GET_OID_SKIP_AMBIGUITY_CHECK) && + repo_settings_get_warn_ambiguous_refs(r) && + warn_on_object_refname_ambiguity) { refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0); if (refs_found > 0) { warning(warn_msg, len, str); @@ -1079,13 +1090,17 @@ static int get_oid_basic(struct repository *r, const char *str, int len, * still fill in the oid with the "old" value, * which we can use. */ - } else { + } else if (!(flags & GET_OID_GENTLY)) { if (flags & GET_OID_QUIETLY) { exit(128); } die(_("log for '%.*s' only has %d entries"), len, str, co_cnt); } + if (flags & GET_OID_GENTLY) { + free(real_ref); + return -1; + } } } @@ -1272,6 +1287,58 @@ static int peel_onion(struct repository *r, const char *name, int len, return 0; } +/* + * Documentation/revisions.adoc says: + * '<describeOutput>', e.g. 'v1.7.4.2-679-g3bee7fb':: + * Output from `git describe`; i.e. a closest tag, optionally + * followed by a dash and a number of commits, followed by a dash, a + * 'g', and an abbreviated object name. + * + * which means that the stuff before '-g${HASH}' needs to be a valid + * refname, a dash, and a non-negative integer. This function verifies + * that. + * + * In particular, we do not want to treat + * branchname:path/to/file/named/i-gaffed + * as a request for commit affed. + * + * More generally, we should probably not treat + * 'refs/heads/./../.../ ~^:/?*[////\\\&}/busted.lock-g050e0ef6ead' + * as a request for object 050e0ef6ead either. + * + * We are called with name[len] == '-' and name[len+1] == 'g', i.e. + * we are verifying ${REFNAME}-{INTEGER} part of the name. + */ +static int ref_and_count_parts_valid(const char *name, int len) +{ + struct strbuf sb; + const char *cp; + int flags = REFNAME_ALLOW_ONELEVEL; + int ret = 1; + + /* Ensure we have at least one digit */ + if (!isxdigit(name[len-1])) + return 0; + + /* Skip over digits backwards until we get to the dash */ + for (cp = name + len - 2; name < cp; cp--) { + if (*cp == '-') + break; + if (!isxdigit(*cp)) + return 0; + } + /* Ensure we found the leading dash */ + if (*cp != '-') + return 0; + + len = cp - name; + strbuf_init(&sb, len); + strbuf_add(&sb, name, len); + ret = !check_refname_format(sb.buf, flags); + strbuf_release(&sb); + return ret; +} + static int get_describe_name(struct repository *r, const char *name, int len, struct object_id *oid) @@ -1285,7 +1352,8 @@ static int get_describe_name(struct repository *r, /* We must be looking at g in "SOMETHING-g" * for it to be describe output. */ - if (ch == 'g' && cp[-1] == '-') { + if (ch == 'g' && cp[-1] == '-' && + ref_and_count_parts_valid(name, cp - 1 - name)) { cp++; len -= cp - name; return get_short_oid(r, @@ -1402,7 +1470,7 @@ static int get_oid_oneline(struct repository *r, const char *prefix, struct object_id *oid, const struct commit_list *list) { - struct commit_list *copy = NULL, **copy_tail = © + struct prio_queue copy = { compare_commits_by_commit_date }; const struct commit_list *l; int found = 0; int negative = 0; @@ -1424,9 +1492,9 @@ static int get_oid_oneline(struct repository *r, for (l = list; l; l = l->next) { l->item->object.flags |= ONELINE_SEEN; - copy_tail = &commit_list_insert(l->item, copy_tail)->next; + prio_queue_put(©, l->item); } - while (copy) { + while (copy.nr) { const char *p, *buf; struct commit *commit; int matches; @@ -1448,7 +1516,7 @@ static int get_oid_oneline(struct repository *r, regfree(®ex); for (l = list; l; l = l->next) clear_commit_marks(l->item, ONELINE_SEEN); - free_commit_list(copy); + clear_prio_queue(©); return found ? 0 : -1; } @@ -1741,18 +1809,20 @@ void object_context_release(struct object_context *ctx) strbuf_release(&ctx->symlink_path); } -/* - * This is like "get_oid_basic()", except it allows "object ID expressions", - * notably "xyz^" for "parent of xyz" - */ -int repo_get_oid(struct repository *r, const char *name, struct object_id *oid) +int repo_get_oid_with_flags(struct repository *r, const char *name, + struct object_id *oid, unsigned flags) { struct object_context unused; - int ret = get_oid_with_context(r, name, 0, oid, &unused); + int ret = get_oid_with_context(r, name, flags, oid, &unused); object_context_release(&unused); return ret; } +int repo_get_oid(struct repository *r, const char *name, struct object_id *oid) +{ + return repo_get_oid_with_flags(r, name, oid, 0); +} + /* * This returns a non-zero value if the string (built using printf * format and the given arguments) is not a valid object. @@ -2000,7 +2070,6 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo, cb.list = &list; refs_for_each_ref(get_main_ref_store(repo), handle_one_ref, &cb); refs_head_ref(get_main_ref_store(repo), handle_one_ref, &cb); - commit_list_sort_by_date(&list); ret = get_oid_oneline(repo, name + 2, oid, list); free_commit_list(list); @@ -2052,12 +2121,14 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo, return -1; } for (cp = name, bracket_depth = 0; *cp; cp++) { - if (*cp == '{') + if (strchr("@^", *cp) && cp[1] == '{') { + cp++; bracket_depth++; - else if (bracket_depth && *cp == '}') + } else if (bracket_depth && *cp == '}') { bracket_depth--; - else if (!bracket_depth && *cp == ':') + } else if (!bracket_depth && *cp == ':') { break; + } } if (*cp == ':') { struct object_id tree_oid; |
