blob: 523215589de9221b0823aab9edbb06389ca52825 [file] [log] [blame]
Elijah Newren4f6728d2023-03-21 06:25:56 +00001#include "git-compat-util.h"
Elijah Newrenf394e092023-03-21 06:25:54 +00002#include "gettext.h"
Elijah Newren41771fa2023-02-24 00:09:27 +00003#include "hex.h"
René Scharfef37b9bc2018-04-11 17:21:04 -07004#include "oidmap.h"
Elijah Newrena034e912023-05-16 06:34:06 +00005#include "object-store-ll.h"
Stefan Bellerd88f9fd2018-04-11 17:21:05 -07006#include "replace-object.h"
Christian Couder68095572009-01-23 10:06:53 +01007#include "refs.h"
Stefan Bellerd88f9fd2018-04-11 17:21:05 -07008#include "repository.h"
Stephen Boydc2e86ad2011-03-22 00:51:05 -07009#include "commit.h"
Christian Couder68095572009-01-23 10:06:53 +010010
Stefan Beller212e0f72018-08-20 18:24:19 +000011static int register_replace_ref(struct repository *r,
12 const char *refname,
Michael Haggerty00530832015-05-25 18:39:02 +000013 const struct object_id *oid,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +020014 int flag UNUSED,
15 void *cb_data UNUSED)
Christian Couder68095572009-01-23 10:06:53 +010016{
17 /* Get sha1 from refname */
18 const char *slash = strrchr(refname, '/');
19 const char *hash = slash ? slash + 1 : refname;
20 struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));
21
René Scharfef37b9bc2018-04-11 17:21:04 -070022 if (get_oid_hex(hash, &repl_obj->original.oid)) {
Christian Couder68095572009-01-23 10:06:53 +010023 free(repl_obj);
Nguyễn Thái Ngọc Duyb73c6e32018-07-21 09:49:37 +020024 warning(_("bad replace ref name: %s"), refname);
Christian Couder68095572009-01-23 10:06:53 +010025 return 0;
26 }
27
28 /* Copy sha1 from the read ref */
brian m. carlson1731a1e2018-03-12 02:27:33 +000029 oidcpy(&repl_obj->replacement, oid);
Christian Couder68095572009-01-23 10:06:53 +010030
31 /* Register new object */
Stefan Beller212e0f72018-08-20 18:24:19 +000032 if (oidmap_put(r->objects->replace_map, repl_obj))
Nguyễn Thái Ngọc Duyb73c6e32018-07-21 09:49:37 +020033 die(_("duplicate replace ref: %s"), refname);
Christian Couder68095572009-01-23 10:06:53 +010034
35 return 0;
36}
37
Derrick Stoleed6538242018-08-20 18:24:27 +000038void prepare_replace_object(struct repository *r)
Christian Couder68095572009-01-23 10:06:53 +010039{
Matheus Tavaresb1fc9da2020-01-15 23:39:52 -030040 if (r->objects->replace_map_initialized)
Christian Couder68095572009-01-23 10:06:53 +010041 return;
42
Matheus Tavaresb1fc9da2020-01-15 23:39:52 -030043 pthread_mutex_lock(&r->objects->replace_mutex);
44 if (r->objects->replace_map_initialized) {
45 pthread_mutex_unlock(&r->objects->replace_mutex);
46 return;
47 }
48
Stefan Beller5982da92018-04-11 17:21:16 -070049 r->objects->replace_map =
Stefan Beller74fd0702018-05-09 16:40:59 -070050 xmalloc(sizeof(*r->objects->replace_map));
Stefan Beller5982da92018-04-11 17:21:16 -070051 oidmap_init(r->objects->replace_map, 0);
Stefan Bellerc1274492018-04-11 17:21:07 -070052
Stefan Beller5982da92018-04-11 17:21:16 -070053 for_each_replace_ref(r, register_replace_ref, NULL);
Matheus Tavaresb1fc9da2020-01-15 23:39:52 -030054 r->objects->replace_map_initialized = 1;
55
56 pthread_mutex_unlock(&r->objects->replace_mutex);
Christian Couder68095572009-01-23 10:06:53 +010057}
58
59/* We allow "recursive" replacement. Only within reason, though */
60#define MAXREPLACEDEPTH 5
61
Michael Haggerty1f91e792014-02-28 17:29:16 +010062/*
brian m. carlsonb383a132018-03-12 02:27:54 +000063 * If a replacement for object oid has been set up, return the
Michael Haggerty1f91e792014-02-28 17:29:16 +010064 * replacement object's name (replaced recursively, if necessary).
brian m. carlsonb383a132018-03-12 02:27:54 +000065 * The return value is either oid or a pointer to a
Michael Haggerty1f91e792014-02-28 17:29:16 +010066 * permanently-allocated value. This function always respects replace
Derrick Stolee9c7d1b02023-06-06 13:24:37 +000067 * references, regardless of the value of r->settings.read_replace_refs.
Michael Haggerty1f91e792014-02-28 17:29:16 +010068 */
Stefan Beller56435572018-04-11 17:21:17 -070069const struct object_id *do_lookup_replace_object(struct repository *r,
70 const struct object_id *oid)
Christian Couder68095572009-01-23 10:06:53 +010071{
René Scharfef37b9bc2018-04-11 17:21:04 -070072 int depth = MAXREPLACEDEPTH;
brian m. carlsonb383a132018-03-12 02:27:54 +000073 const struct object_id *cur = oid;
Christian Couder68095572009-01-23 10:06:53 +010074
Stefan Beller56435572018-04-11 17:21:17 -070075 prepare_replace_object(r);
Christian Couder68095572009-01-23 10:06:53 +010076
77 /* Try to recursively replace the object */
René Scharfef37b9bc2018-04-11 17:21:04 -070078 while (depth-- > 0) {
Stefan Bellerd88f9fd2018-04-11 17:21:05 -070079 struct replace_object *repl_obj =
Stefan Beller56435572018-04-11 17:21:17 -070080 oidmap_get(r->objects->replace_map, cur);
René Scharfef37b9bc2018-04-11 17:21:04 -070081 if (!repl_obj)
82 return cur;
83 cur = &repl_obj->replacement;
84 }
Nguyễn Thái Ngọc Duyb73c6e32018-07-21 09:49:37 +020085 die(_("replace depth too high for object %s"), oid_to_hex(oid));
Christian Couder68095572009-01-23 10:06:53 +010086}
Derrick Stoleed24eda42023-06-06 13:24:35 +000087
Derrick Stolee9c7d1b02023-06-06 13:24:37 +000088/*
89 * This indicator determines whether replace references should be
90 * respected process-wide, regardless of which repository is being
91 * using at the time.
92 */
93static int read_replace_refs = 1;
94
Derrick Stoleed24eda42023-06-06 13:24:35 +000095void disable_replace_refs(void)
96{
97 read_replace_refs = 0;
98}
Derrick Stoleef1178382023-06-06 13:24:36 +000099
100int replace_refs_enabled(struct repository *r)
101{
Derrick Stolee9c7d1b02023-06-06 13:24:37 +0000102 if (!read_replace_refs)
103 return 0;
104
105 if (r->gitdir) {
106 prepare_repo_settings(r);
107 return r->settings.read_replace_refs;
108 }
109
110 /* repository has no objects or refs. */
111 return 0;
Derrick Stoleef1178382023-06-06 13:24:36 +0000112}