git
/
replace-object.c
115 строк · 2.9 Кб
1#include "git-compat-util.h"2#include "gettext.h"3#include "hex.h"4#include "oidmap.h"5#include "object-store-ll.h"6#include "replace-object.h"7#include "refs.h"8#include "repository.h"9#include "commit.h"10
11static int register_replace_ref(const char *refname,12const char *referent UNUSED,13const struct object_id *oid,14int flag UNUSED,15void *cb_data)16{
17struct repository *r = cb_data;18
19/* Get sha1 from refname */20const char *slash = strrchr(refname, '/');21const char *hash = slash ? slash + 1 : refname;22struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));23
24if (get_oid_hex_algop(hash, &repl_obj->original.oid, r->hash_algo)) {25free(repl_obj);26warning(_("bad replace ref name: %s"), refname);27return 0;28}29
30/* Copy sha1 from the read ref */31oidcpy(&repl_obj->replacement, oid);32
33/* Register new object */34if (oidmap_put(r->objects->replace_map, repl_obj))35die(_("duplicate replace ref: %s"), refname);36
37return 0;38}
39
40void prepare_replace_object(struct repository *r)41{
42if (r->objects->replace_map_initialized)43return;44
45pthread_mutex_lock(&r->objects->replace_mutex);46if (r->objects->replace_map_initialized) {47pthread_mutex_unlock(&r->objects->replace_mutex);48return;49}50
51r->objects->replace_map =52xmalloc(sizeof(*r->objects->replace_map));53oidmap_init(r->objects->replace_map, 0);54
55refs_for_each_replace_ref(get_main_ref_store(r),56register_replace_ref, r);57r->objects->replace_map_initialized = 1;58
59pthread_mutex_unlock(&r->objects->replace_mutex);60}
61
62/* We allow "recursive" replacement. Only within reason, though */
63#define MAXREPLACEDEPTH 564
65/*
66* If a replacement for object oid has been set up, return the
67* replacement object's name (replaced recursively, if necessary).
68* The return value is either oid or a pointer to a
69* permanently-allocated value. This function always respects replace
70* references, regardless of the value of r->settings.read_replace_refs.
71*/
72const struct object_id *do_lookup_replace_object(struct repository *r,73const struct object_id *oid)74{
75int depth = MAXREPLACEDEPTH;76const struct object_id *cur = oid;77
78prepare_replace_object(r);79
80/* Try to recursively replace the object */81while (depth-- > 0) {82struct replace_object *repl_obj =83oidmap_get(r->objects->replace_map, cur);84if (!repl_obj)85return cur;86cur = &repl_obj->replacement;87}88die(_("replace depth too high for object %s"), oid_to_hex(oid));89}
90
91/*
92* This indicator determines whether replace references should be
93* respected process-wide, regardless of which repository is being
94* using at the time.
95*/
96static int read_replace_refs = 1;97
98void disable_replace_refs(void)99{
100read_replace_refs = 0;101}
102
103int replace_refs_enabled(struct repository *r)104{
105if (!read_replace_refs)106return 0;107
108if (r->gitdir) {109prepare_repo_settings(r);110return r->settings.read_replace_refs;111}112
113/* repository has no objects or refs. */114return 0;115}
116