From: Junio C Hamano Date: Wed, 23 May 2018 05:38:09 +0000 (+0900) Subject: Merge branch 'sb/object-store-replace' X-Git-Tag: v2.18.0-rc0~71 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/a2cec42213c55dd3ff9febb51612e3f1cab37b12?ds=inline;hp=-c Merge branch 'sb/object-store-replace' Hotfix. * sb/object-store-replace: get_main_ref_store: BUG() when outside a repository object.c: clear replace map before freeing it replace-object.c: remove the_repository from prepare_replace_object object.c: free replace map in raw_object_store_clear --- a2cec42213c55dd3ff9febb51612e3f1cab37b12 diff --combined refs.c index 64aadd14c9,4a44e44b6a..2e4a42f459 --- a/refs.c +++ b/refs.c @@@ -13,7 -13,6 +13,7 @@@ #include "tag.h" #include "submodule.h" #include "worktree.h" +#include "argv-array.h" #include "repository.h" /* @@@ -503,19 -502,6 +503,19 @@@ int refname_match(const char *abbrev_na return 0; } +/* + * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add + * the results to 'prefixes' + */ +void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) +{ + const char **p; + int len = strlen(prefix); + + for (p = ref_rev_parse_rules; *p; p++) + argv_array_pushf(prefixes, *p, len, prefix); +} + /* * *string and *len will only be substituted, and *string returned (for * later free()ing) if the string passed in is a magic short-hand form @@@ -1668,6 -1654,9 +1668,9 @@@ struct ref_store *get_main_ref_store(st if (r->refs) return r->refs; + if (!r->gitdir) + BUG("attempting to get main_ref_store outside of repository"); + r->refs = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS); return r->refs; } diff --combined replace-object.c index 246b98cd4f,0000000000..801b5c1678 mode 100644,000000..100644 --- a/replace-object.c +++ b/replace-object.c @@@ -1,73 -1,0 +1,73 @@@ +#include "cache.h" +#include "oidmap.h" +#include "object-store.h" +#include "replace-object.h" +#include "refs.h" +#include "repository.h" +#include "commit.h" + +static int register_replace_ref(const char *refname, + const struct object_id *oid, + int flag, void *cb_data) +{ + /* Get sha1 from refname */ + const char *slash = strrchr(refname, '/'); + const char *hash = slash ? slash + 1 : refname; + struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj)); + + if (get_oid_hex(hash, &repl_obj->original.oid)) { + free(repl_obj); + warning("bad replace ref name: %s", refname); + return 0; + } + + /* Copy sha1 from the read ref */ + oidcpy(&repl_obj->replacement, oid); + + /* Register new object */ + if (oidmap_put(the_repository->objects->replace_map, repl_obj)) + die("duplicate replace ref: %s", refname); + + return 0; +} + +static void prepare_replace_object(struct repository *r) +{ + if (r->objects->replace_map) + return; + + r->objects->replace_map = - xmalloc(sizeof(*the_repository->objects->replace_map)); ++ xmalloc(sizeof(*r->objects->replace_map)); + oidmap_init(r->objects->replace_map, 0); + + for_each_replace_ref(r, register_replace_ref, NULL); +} + +/* We allow "recursive" replacement. Only within reason, though */ +#define MAXREPLACEDEPTH 5 + +/* + * If a replacement for object oid has been set up, return the + * replacement object's name (replaced recursively, if necessary). + * The return value is either oid or a pointer to a + * permanently-allocated value. This function always respects replace + * references, regardless of the value of check_replace_refs. + */ +const struct object_id *do_lookup_replace_object(struct repository *r, + const struct object_id *oid) +{ + int depth = MAXREPLACEDEPTH; + const struct object_id *cur = oid; + + prepare_replace_object(r); + + /* Try to recursively replace the object */ + while (depth-- > 0) { + struct replace_object *repl_obj = + oidmap_get(r->objects->replace_map, cur); + if (!repl_obj) + return cur; + cur = &repl_obj->replacement; + } + die("replace depth too high for object %s", oid_to_hex(oid)); +}