You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.3 KiB
86 lines
2.3 KiB
#include "git-compat-util.h" |
|
#include "gettext.h" |
|
#include "hex.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(struct repository *r, |
|
const char *refname, |
|
const struct object_id *oid, |
|
int flag UNUSED, |
|
void *cb_data UNUSED) |
|
{ |
|
/* 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(r->objects->replace_map, repl_obj)) |
|
die(_("duplicate replace ref: %s"), refname); |
|
|
|
return 0; |
|
} |
|
|
|
void prepare_replace_object(struct repository *r) |
|
{ |
|
if (r->objects->replace_map_initialized) |
|
return; |
|
|
|
pthread_mutex_lock(&r->objects->replace_mutex); |
|
if (r->objects->replace_map_initialized) { |
|
pthread_mutex_unlock(&r->objects->replace_mutex); |
|
return; |
|
} |
|
|
|
r->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); |
|
r->objects->replace_map_initialized = 1; |
|
|
|
pthread_mutex_unlock(&r->objects->replace_mutex); |
|
} |
|
|
|
/* 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 read_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)); |
|
}
|
|
|