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