a757a5ebf2e506d4770f7ba60226b6dc09bc3dcd
   1#include "cache.h"
   2#include "oidmap.h"
   3#include "refs.h"
   4#include "commit.h"
   5
   6struct replace_object {
   7        struct oidmap_entry original;
   8        struct object_id replacement;
   9};
  10
  11static struct oidmap replace_map = OIDMAP_INIT;
  12
  13static int register_replace_ref(const char *refname,
  14                                const struct object_id *oid,
  15                                int flag, void *cb_data)
  16{
  17        /* Get sha1 from refname */
  18        const char *slash = strrchr(refname, '/');
  19        const char *hash = slash ? slash + 1 : refname;
  20        struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));
  21
  22        if (get_oid_hex(hash, &repl_obj->original.oid)) {
  23                free(repl_obj);
  24                warning("bad replace ref name: %s", refname);
  25                return 0;
  26        }
  27
  28        /* Copy sha1 from the read ref */
  29        oidcpy(&repl_obj->replacement, oid);
  30
  31        /* Register new object */
  32        if (oidmap_put(&replace_map, repl_obj))
  33                die("duplicate replace ref: %s", refname);
  34
  35        return 0;
  36}
  37
  38static void prepare_replace_object(void)
  39{
  40        static int replace_object_prepared;
  41
  42        if (replace_object_prepared)
  43                return;
  44
  45        for_each_replace_ref(register_replace_ref, NULL);
  46        replace_object_prepared = 1;
  47        if (!replace_map.map.tablesize)
  48                check_replace_refs = 0;
  49}
  50
  51/* We allow "recursive" replacement. Only within reason, though */
  52#define MAXREPLACEDEPTH 5
  53
  54/*
  55 * If a replacement for object oid has been set up, return the
  56 * replacement object's name (replaced recursively, if necessary).
  57 * The return value is either oid or a pointer to a
  58 * permanently-allocated value.  This function always respects replace
  59 * references, regardless of the value of check_replace_refs.
  60 */
  61const struct object_id *do_lookup_replace_object(const struct object_id *oid)
  62{
  63        int depth = MAXREPLACEDEPTH;
  64        const struct object_id *cur = oid;
  65
  66        prepare_replace_object();
  67
  68        /* Try to recursively replace the object */
  69        while (depth-- > 0) {
  70                struct replace_object *repl_obj = oidmap_get(&replace_map, cur);
  71                if (!repl_obj)
  72                        return cur;
  73                cur = &repl_obj->replacement;
  74        }
  75        die("replace depth too high for object %s", oid_to_hex(oid));
  76}