/* * Clears the cache. */ static void fscache_clear(void) { struct hashmap_iter iter; struct fsentry *fse; while ((fse = hashmap_iter_first(&map, &iter))) { fscache_remove(fse); fsentry_release(fse); } }
static void describe(const char *arg, int last_one) { unsigned char sha1[20]; struct commit *cmit, *gave_up_on = NULL; struct commit_list *list; struct commit_name *n; struct possible_tag all_matches[MAX_TAGS]; unsigned int match_cnt = 0, annotated_cnt = 0, cur_match; unsigned long seen_commits = 0; unsigned int unannotated_cnt = 0; if (get_sha1(arg, sha1)) die(_("Not a valid object name %s"), arg); cmit = lookup_commit_reference(sha1); if (!cmit) die(_("%s is not a valid '%s' object"), arg, commit_type); n = find_commit_name(cmit->object.oid.hash); if (n && (tags || all || n->prio == 2)) { /* * Exact match to an existing ref. */ display_name(n); if (longformat) show_suffix(0, n->tag ? n->tag->tagged->oid.hash : sha1); if (dirty) printf("%s", dirty); printf("\n"); return; } if (!max_candidates) die(_("no tag exactly matches '%s'"), oid_to_hex(&cmit->object.oid)); if (debug) fprintf(stderr, _("searching to describe %s\n"), arg); if (!have_util) { struct hashmap_iter iter; struct commit *c; struct commit_name *n = hashmap_iter_first(&names, &iter); for (; n; n = hashmap_iter_next(&iter)) { c = lookup_commit_reference_gently(n->peeled, 1); if (c) c->util = n; } have_util = 1; } list = NULL; cmit->object.flags = SEEN; commit_list_insert(cmit, &list); while (list) { struct commit *c = pop_commit(&list); struct commit_list *parents = c->parents; seen_commits++; n = c->util; if (n) { if (!tags && !all && n->prio < 2) { unannotated_cnt++; } else if (match_cnt < max_candidates) { struct possible_tag *t = &all_matches[match_cnt++]; t->name = n; t->depth = seen_commits - 1; t->flag_within = 1u << match_cnt; t->found_order = match_cnt; c->object.flags |= t->flag_within; if (n->prio == 2) annotated_cnt++; } else { gave_up_on = c; break; } } for (cur_match = 0; cur_match < match_cnt; cur_match++) { struct possible_tag *t = &all_matches[cur_match]; if (!(c->object.flags & t->flag_within)) t->depth++; } if (annotated_cnt && !list) { if (debug) fprintf(stderr, _("finished search at %s\n"), oid_to_hex(&c->object.oid)); break; } while (parents) { struct commit *p = parents->item; parse_commit(p); if (!(p->object.flags & SEEN)) commit_list_insert_by_date(p, &list); p->object.flags |= c->object.flags; parents = parents->next; if (first_parent) break; } } if (!match_cnt) { struct object_id *oid = &cmit->object.oid; if (always) { printf("%s", find_unique_abbrev(oid->hash, abbrev)); if (dirty) printf("%s", dirty); printf("\n"); return; } if (unannotated_cnt) die(_("No annotated tags can describe '%s'.\n" "However, there were unannotated tags: try --tags."), oid_to_hex(oid)); else die(_("No tags can describe '%s'.\n" "Try --always, or create some tags."), oid_to_hex(oid)); } QSORT(all_matches, match_cnt, compare_pt); if (gave_up_on) { commit_list_insert_by_date(gave_up_on, &list); seen_commits--; } seen_commits += finish_depth_computation(&list, &all_matches[0]); free_commit_list(list); if (debug) { for (cur_match = 0; cur_match < match_cnt; cur_match++) { struct possible_tag *t = &all_matches[cur_match]; fprintf(stderr, " %-11s %8d %s\n", prio_names[t->name->prio], t->depth, t->name->path); } fprintf(stderr, _("traversed %lu commits\n"), seen_commits); if (gave_up_on) { fprintf(stderr, _("more than %i tags found; listed %i most recent\n" "gave up search at %s\n"), max_candidates, max_candidates, oid_to_hex(&gave_up_on->object.oid)); } } display_name(all_matches[0].name); if (abbrev) show_suffix(all_matches[0].depth, cmit->object.oid.hash); if (dirty) printf("%s", dirty); printf("\n"); if (!last_one) clear_commit_marks(cmit, -1); }
/* This does a lookup of a submodule configuration by name or by path * (key) with on-demand reading of the appropriate .gitmodules from * revisions. */ static const struct submodule *config_from(struct submodule_cache *cache, const unsigned char *treeish_name, const char *key, enum lookup_type lookup_type) { struct strbuf rev = STRBUF_INIT; unsigned long config_size; char *config = NULL; unsigned char sha1[20]; enum object_type type; const struct submodule *submodule = NULL; struct parse_config_parameter parameter; /* * If any parameter except the cache is a NULL pointer just * return the first submodule. Can be used to check whether * there are any submodules parsed. */ if (!treeish_name || !key) { struct hashmap_iter iter; struct submodule_entry *entry; entry = hashmap_iter_first(&cache->for_name, &iter); if (!entry) return NULL; return entry->config; } if (!gitmodule_sha1_from_commit(treeish_name, sha1, &rev)) goto out; switch (lookup_type) { case lookup_name: submodule = cache_lookup_name(cache, sha1, key); break; case lookup_path: submodule = cache_lookup_path(cache, sha1, key); break; } if (submodule) goto out; config = read_sha1_file(sha1, &type, &config_size); if (!config || type != OBJ_BLOB) goto out; /* fill the submodule config into the cache */ parameter.cache = cache; parameter.treeish_name = treeish_name; parameter.gitmodules_sha1 = sha1; parameter.overwrite = 0; git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf, config, config_size, ¶meter); strbuf_release(&rev); free(config); switch (lookup_type) { case lookup_name: return cache_lookup_name(cache, sha1, key); case lookup_path: return cache_lookup_path(cache, sha1, key); default: return NULL; } out: strbuf_release(&rev); free(config); return submodule; }