mirror of
https://github.com/git/git.git
synced 2024-12-11 19:03:50 +08:00
8378c9d27b
The function `for_each_replace_ref()` is a bit of an oddball across the refs interfaces as it accepts a pointer to the repository instead of a pointer to the ref store. The only reason for us to accept a repository is so that we can eventually pass it back to the callback function that the caller has provided. This is somewhat arbitrary though, as callers that need the repository can instead make it accessible via the callback payload. Refactor the function to instead accept the ref store and adjust callers accordingly. This allows us to get rid of some of the boilerplate that we had to carry to pass along the repository and brings us in line with the other functions that iterate through refs. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
115 lines
2.8 KiB
C
115 lines
2.8 KiB
C
#include "git-compat-util.h"
|
|
#include "gettext.h"
|
|
#include "hex.h"
|
|
#include "oidmap.h"
|
|
#include "object-store-ll.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 UNUSED,
|
|
void *cb_data)
|
|
{
|
|
struct repository *r = 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(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);
|
|
|
|
refs_for_each_replace_ref(get_main_ref_store(r),
|
|
register_replace_ref, r);
|
|
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 r->settings.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));
|
|
}
|
|
|
|
/*
|
|
* This indicator determines whether replace references should be
|
|
* respected process-wide, regardless of which repository is being
|
|
* using at the time.
|
|
*/
|
|
static int read_replace_refs = 1;
|
|
|
|
void disable_replace_refs(void)
|
|
{
|
|
read_replace_refs = 0;
|
|
}
|
|
|
|
int replace_refs_enabled(struct repository *r)
|
|
{
|
|
if (!read_replace_refs)
|
|
return 0;
|
|
|
|
if (r->gitdir) {
|
|
prepare_repo_settings(r);
|
|
return r->settings.read_replace_refs;
|
|
}
|
|
|
|
/* repository has no objects or refs. */
|
|
return 0;
|
|
}
|