blob: 7bd9aba6ee6c339e02c6fe25262a75a19bfc6e68 [file] [log] [blame]
Christian Couder68095572009-01-23 10:06:53 +01001#include "cache.h"
René Scharfef37b9bc2018-04-11 17:21:04 -07002#include "oidmap.h"
Stefan Bellerd88f9fd2018-04-11 17:21:05 -07003#include "object-store.h"
4#include "replace-object.h"
Christian Couder68095572009-01-23 10:06:53 +01005#include "refs.h"
Stefan Bellerd88f9fd2018-04-11 17:21:05 -07006#include "repository.h"
Stephen Boydc2e86ad2011-03-22 00:51:05 -07007#include "commit.h"
Christian Couder68095572009-01-23 10:06:53 +01008
Stefan Beller212e0f72018-08-20 18:24:19 +00009static int register_replace_ref(struct repository *r,
10 const char *refname,
Michael Haggerty00530832015-05-25 18:39:02 +000011 const struct object_id *oid,
Christian Couder68095572009-01-23 10:06:53 +010012 int flag, void *cb_data)
13{
14 /* Get sha1 from refname */
15 const char *slash = strrchr(refname, '/');
16 const char *hash = slash ? slash + 1 : refname;
17 struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));
18
René Scharfef37b9bc2018-04-11 17:21:04 -070019 if (get_oid_hex(hash, &repl_obj->original.oid)) {
Christian Couder68095572009-01-23 10:06:53 +010020 free(repl_obj);
Nguyễn Thái Ngọc Duyb73c6e32018-07-21 09:49:37 +020021 warning(_("bad replace ref name: %s"), refname);
Christian Couder68095572009-01-23 10:06:53 +010022 return 0;
23 }
24
25 /* Copy sha1 from the read ref */
brian m. carlson1731a1e2018-03-12 02:27:33 +000026 oidcpy(&repl_obj->replacement, oid);
Christian Couder68095572009-01-23 10:06:53 +010027
28 /* Register new object */
Stefan Beller212e0f72018-08-20 18:24:19 +000029 if (oidmap_put(r->objects->replace_map, repl_obj))
Nguyễn Thái Ngọc Duyb73c6e32018-07-21 09:49:37 +020030 die(_("duplicate replace ref: %s"), refname);
Christian Couder68095572009-01-23 10:06:53 +010031
32 return 0;
33}
34
Derrick Stoleed6538242018-08-20 18:24:27 +000035void prepare_replace_object(struct repository *r)
Christian Couder68095572009-01-23 10:06:53 +010036{
Matheus Tavaresb1fc9da2020-01-15 23:39:52 -030037 if (r->objects->replace_map_initialized)
Christian Couder68095572009-01-23 10:06:53 +010038 return;
39
Matheus Tavaresb1fc9da2020-01-15 23:39:52 -030040 pthread_mutex_lock(&r->objects->replace_mutex);
41 if (r->objects->replace_map_initialized) {
42 pthread_mutex_unlock(&r->objects->replace_mutex);
43 return;
44 }
45
Stefan Beller5982da92018-04-11 17:21:16 -070046 r->objects->replace_map =
Stefan Beller74fd0702018-05-09 16:40:59 -070047 xmalloc(sizeof(*r->objects->replace_map));
Stefan Beller5982da92018-04-11 17:21:16 -070048 oidmap_init(r->objects->replace_map, 0);
Stefan Bellerc1274492018-04-11 17:21:07 -070049
Stefan Beller5982da92018-04-11 17:21:16 -070050 for_each_replace_ref(r, register_replace_ref, NULL);
Matheus Tavaresb1fc9da2020-01-15 23:39:52 -030051 r->objects->replace_map_initialized = 1;
52
53 pthread_mutex_unlock(&r->objects->replace_mutex);
Christian Couder68095572009-01-23 10:06:53 +010054}
55
56/* We allow "recursive" replacement. Only within reason, though */
57#define MAXREPLACEDEPTH 5
58
Michael Haggerty1f91e792014-02-28 17:29:16 +010059/*
brian m. carlsonb383a132018-03-12 02:27:54 +000060 * If a replacement for object oid has been set up, return the
Michael Haggerty1f91e792014-02-28 17:29:16 +010061 * replacement object's name (replaced recursively, if necessary).
brian m. carlsonb383a132018-03-12 02:27:54 +000062 * The return value is either oid or a pointer to a
Michael Haggerty1f91e792014-02-28 17:29:16 +010063 * permanently-allocated value. This function always respects replace
Jeff King6ebd1ca2018-07-18 16:45:20 -040064 * references, regardless of the value of read_replace_refs.
Michael Haggerty1f91e792014-02-28 17:29:16 +010065 */
Stefan Beller56435572018-04-11 17:21:17 -070066const struct object_id *do_lookup_replace_object(struct repository *r,
67 const struct object_id *oid)
Christian Couder68095572009-01-23 10:06:53 +010068{
René Scharfef37b9bc2018-04-11 17:21:04 -070069 int depth = MAXREPLACEDEPTH;
brian m. carlsonb383a132018-03-12 02:27:54 +000070 const struct object_id *cur = oid;
Christian Couder68095572009-01-23 10:06:53 +010071
Stefan Beller56435572018-04-11 17:21:17 -070072 prepare_replace_object(r);
Christian Couder68095572009-01-23 10:06:53 +010073
74 /* Try to recursively replace the object */
René Scharfef37b9bc2018-04-11 17:21:04 -070075 while (depth-- > 0) {
Stefan Bellerd88f9fd2018-04-11 17:21:05 -070076 struct replace_object *repl_obj =
Stefan Beller56435572018-04-11 17:21:17 -070077 oidmap_get(r->objects->replace_map, cur);
René Scharfef37b9bc2018-04-11 17:21:04 -070078 if (!repl_obj)
79 return cur;
80 cur = &repl_obj->replacement;
81 }
Nguyễn Thái Ngọc Duyb73c6e32018-07-21 09:49:37 +020082 die(_("replace depth too high for object %s"), oid_to_hex(oid));
Christian Couder68095572009-01-23 10:06:53 +010083}