Coverage Report

Created: 2026-01-09 07:10

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