blob: 90bcb2716873592864e2496951f913618521cb45 [file] [log] [blame]
Michael Haggerty7bd9bcf2015-11-09 14:34:01 +01001/*
2 * The backend-independent part of the reference module.
3 */
4
Daniel Barkalow95fc7512005-06-06 16:31:29 -04005#include "cache.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07006#include "config.h"
Michael Haggerty7d4558c2017-02-10 12:16:15 +01007#include "hashmap.h"
Michael Haggerty697cc8e2014-10-01 12:28:42 +02008#include "lockfile.h"
Michael Haggertyb05855b2017-04-16 08:41:26 +02009#include "iterator.h"
Junio C Hamano85023572006-12-19 14:34:12 -080010#include "refs.h"
Michael Haggerty4cb77002015-11-10 12:42:36 +010011#include "refs/refs-internal.h"
Patrick Steinhardt67541592020-06-19 08:56:14 +020012#include "run-command.h"
Ævar Arnfjörð Bjarmason5e3aba32021-09-26 21:03:26 +020013#include "hook.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -070014#include "object-store.h"
Junio C Hamanocf0adba2006-11-19 13:22:44 -080015#include "object.h"
16#include "tag.h"
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +070017#include "submodule.h"
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +070018#include "worktree.h"
Jeff Kingdbbcd442020-07-28 16:23:39 -040019#include "strvec.h"
Stefan Beller23a3f0c2018-04-11 17:21:09 -070020#include "repository.h"
Patrick Steinhardt67541592020-06-19 08:56:14 +020021#include "sigchain.h"
Ævar Arnfjörð Bjarmason88c7b4c2022-02-16 09:14:02 +010022#include "date.h"
Stefan Beller3581d792014-12-12 09:57:02 +010023
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020024/*
Ronnie Sahlberg3dce4442016-09-04 18:08:10 +020025 * List of all available backends
26 */
27static struct ref_storage_be *refs_backends = &refs_be_files;
28
29static struct ref_storage_be *find_ref_storage_backend(const char *name)
30{
31 struct ref_storage_be *be;
32 for (be = refs_backends; be; be = be->next)
33 if (!strcmp(be->name, name))
34 return be;
35 return NULL;
36}
37
Ronnie Sahlberg3dce4442016-09-04 18:08:10 +020038/*
David Turnerdde8a902014-06-03 23:38:10 -040039 * How to handle various characters in refnames:
40 * 0: An acceptable character for refs
Junio C Hamano5e650222014-07-28 10:41:53 -070041 * 1: End-of-component
42 * 2: ., look for a preceding . to reject .. in refs
43 * 3: {, look for a preceding @ to reject @{ in refs
Jacob Keller53a85552015-07-22 14:05:32 -070044 * 4: A bad character: ASCII control characters, and
Jacob Kellercd377f42015-07-22 14:05:33 -070045 * ":", "?", "[", "\", "^", "~", SP, or TAB
46 * 5: *, reject unless REFNAME_REFSPEC_PATTERN is set
David Turnerdde8a902014-06-03 23:38:10 -040047 */
48static unsigned char refname_disposition[256] = {
Junio C Hamano5e650222014-07-28 10:41:53 -070049 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
50 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
Jacob Kellercd377f42015-07-22 14:05:33 -070051 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 1,
Junio C Hamano5e650222014-07-28 10:41:53 -070052 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,
David Turnerdde8a902014-06-03 23:38:10 -040053 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Junio C Hamano5e650222014-07-28 10:41:53 -070054 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
David Turnerdde8a902014-06-03 23:38:10 -040057};
58
59/*
60 * Try to read one refname component from the front of refname.
61 * Return the length of the component found, or -1 if the component is
62 * not legal. It is legal if it is something reasonable to have under
63 * ".git/refs/"; We do not like it if:
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020064 *
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070065 * - it begins with ".", or
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020066 * - it has double dots "..", or
Jacob Keller53a85552015-07-22 14:05:32 -070067 * - it has ASCII control characters, or
Jacob Kellercd377f42015-07-22 14:05:33 -070068 * - it has ":", "?", "[", "\", "^", "~", SP, or TAB anywhere, or
69 * - it has "*" anywhere unless REFNAME_REFSPEC_PATTERN is set, or
Jacob Keller53a85552015-07-22 14:05:32 -070070 * - it ends with a "/", or
71 * - it ends with ".lock", or
72 * - it contains a "@{" portion
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070073 *
74 * When sanitized is not NULL, instead of rejecting the input refname
75 * as an error, try to come up with a usable replacement for the input
76 * refname in it.
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020077 */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070078static int check_refname_component(const char *refname, int *flags,
79 struct strbuf *sanitized)
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020080{
81 const char *cp;
82 char last = '\0';
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070083 size_t component_start = 0; /* garbage - not a reasonable initial value */
84
85 if (sanitized)
86 component_start = sanitized->len;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020087
88 for (cp = refname; ; cp++) {
David Turnerdde8a902014-06-03 23:38:10 -040089 int ch = *cp & 255;
90 unsigned char disp = refname_disposition[ch];
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070091
92 if (sanitized && disp != 1)
93 strbuf_addch(sanitized, ch);
94
David Turnerdde8a902014-06-03 23:38:10 -040095 switch (disp) {
Junio C Hamano5e650222014-07-28 10:41:53 -070096 case 1:
David Turnerdde8a902014-06-03 23:38:10 -040097 goto out;
Junio C Hamano5e650222014-07-28 10:41:53 -070098 case 2:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070099 if (last == '.') { /* Refname contains "..". */
100 if (sanitized)
101 /* collapse ".." to single "." */
102 strbuf_setlen(sanitized, sanitized->len - 1);
103 else
104 return -1;
105 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200106 break;
Junio C Hamano5e650222014-07-28 10:41:53 -0700107 case 3:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700108 if (last == '@') { /* Refname contains "@{". */
109 if (sanitized)
110 sanitized->buf[sanitized->len-1] = '-';
111 else
112 return -1;
113 }
David Turnerdde8a902014-06-03 23:38:10 -0400114 break;
Junio C Hamano5e650222014-07-28 10:41:53 -0700115 case 4:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700116 /* forbidden char */
117 if (sanitized)
118 sanitized->buf[sanitized->len-1] = '-';
119 else
120 return -1;
121 break;
Jacob Kellercd377f42015-07-22 14:05:33 -0700122 case 5:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700123 if (!(*flags & REFNAME_REFSPEC_PATTERN)) {
124 /* refspec can't be a pattern */
125 if (sanitized)
126 sanitized->buf[sanitized->len-1] = '-';
127 else
128 return -1;
129 }
Jacob Kellercd377f42015-07-22 14:05:33 -0700130
131 /*
132 * Unset the pattern flag so that we only accept
133 * a single asterisk for one side of refspec.
134 */
135 *flags &= ~ REFNAME_REFSPEC_PATTERN;
136 break;
David Turnerdde8a902014-06-03 23:38:10 -0400137 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200138 last = ch;
139 }
David Turnerdde8a902014-06-03 23:38:10 -0400140out:
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200141 if (cp == refname)
Michael Haggertydac529e2012-04-10 07:30:22 +0200142 return 0; /* Component has zero length. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700143
144 if (refname[0] == '.') { /* Component starts with '.'. */
145 if (sanitized)
146 sanitized->buf[component_start] = '-';
147 else
148 return -1;
149 }
Michael Haggerty7108ad22014-10-01 12:28:15 +0200150 if (cp - refname >= LOCK_SUFFIX_LEN &&
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700151 !memcmp(cp - LOCK_SUFFIX_LEN, LOCK_SUFFIX, LOCK_SUFFIX_LEN)) {
152 if (!sanitized)
153 return -1;
154 /* Refname ends with ".lock". */
155 while (strbuf_strip_suffix(sanitized, LOCK_SUFFIX)) {
156 /* try again in case we have .lock.lock */
157 }
158 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200159 return cp - refname;
160}
161
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700162static int check_or_sanitize_refname(const char *refname, int flags,
163 struct strbuf *sanitized)
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200164{
165 int component_len, component_count = 0;
166
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700167 if (!strcmp(refname, "@")) {
Felipe Contreras9ba89f42013-09-02 01:34:30 -0500168 /* Refname is a single character '@'. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700169 if (sanitized)
170 strbuf_addch(sanitized, '-');
171 else
172 return -1;
173 }
Felipe Contreras9ba89f42013-09-02 01:34:30 -0500174
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200175 while (1) {
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700176 if (sanitized && sanitized->len)
177 strbuf_complete(sanitized, '/');
178
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200179 /* We are at the start of a path component. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700180 component_len = check_refname_component(refname, &flags,
181 sanitized);
182 if (sanitized && component_len == 0)
183 ; /* OK, omit empty component */
184 else if (component_len <= 0)
Jacob Kellercd377f42015-07-22 14:05:33 -0700185 return -1;
186
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200187 component_count++;
188 if (refname[component_len] == '\0')
189 break;
190 /* Skip to next component. */
191 refname += component_len + 1;
192 }
193
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700194 if (refname[component_len - 1] == '.') {
195 /* Refname ends with '.'. */
196 if (sanitized)
197 ; /* omit ending dot */
198 else
199 return -1;
200 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200201 if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
202 return -1; /* Refname has only one component. */
203 return 0;
204}
205
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700206int check_refname_format(const char *refname, int flags)
207{
208 return check_or_sanitize_refname(refname, flags, NULL);
209}
210
211void sanitize_refname_component(const char *refname, struct strbuf *out)
212{
213 if (check_or_sanitize_refname(refname, REFNAME_ALLOW_ONELEVEL, out))
214 BUG("sanitizing refname '%s' check returned error", refname);
215}
216
Michael Haggerty4cb77002015-11-10 12:42:36 +0100217int refname_is_safe(const char *refname)
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700218{
Michael Haggerty39950fe2016-04-27 12:39:11 +0200219 const char *rest;
220
221 if (skip_prefix(refname, "refs/", &rest)) {
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700222 char *buf;
223 int result;
Michael Haggertye40f3552016-04-27 12:40:39 +0200224 size_t restlen = strlen(rest);
225
226 /* rest must not be empty, or start or end with "/" */
227 if (!restlen || *rest == '/' || rest[restlen - 1] == '/')
228 return 0;
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700229
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700230 /*
231 * Does the refname try to escape refs/?
232 * For example: refs/foo/../bar is safe but refs/foo/../../bar
233 * is not.
234 */
Michael Haggertye40f3552016-04-27 12:40:39 +0200235 buf = xmallocz(restlen);
236 result = !normalize_path_copy(buf, rest) && !strcmp(buf, rest);
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700237 free(buf);
238 return result;
239 }
Michael Haggerty35db25c2016-04-27 12:42:27 +0200240
241 do {
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700242 if (!isupper(*refname) && *refname != '_')
243 return 0;
244 refname++;
Michael Haggerty35db25c2016-04-27 12:42:27 +0200245 } while (*refname);
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700246 return 1;
247}
248
Michael Haggerty67be7c52017-06-23 09:01:37 +0200249/*
250 * Return true if refname, which has the specified oid and flags, can
251 * be resolved to an object in the database. If the referred-to object
252 * does not exist, emit a warning and return false.
253 */
254int ref_resolves_to_object(const char *refname,
Jonathan Tan9bc45a22021-10-08 14:08:15 -0700255 struct repository *repo,
Michael Haggerty67be7c52017-06-23 09:01:37 +0200256 const struct object_id *oid,
257 unsigned int flags)
258{
259 if (flags & REF_ISBROKEN)
260 return 0;
Jonathan Tan9bc45a22021-10-08 14:08:15 -0700261 if (!repo_has_object_file(repo, oid)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200262 error(_("%s does not point to a valid object!"), refname);
Michael Haggerty67be7c52017-06-23 09:01:37 +0200263 return 0;
264 }
265 return 1;
266}
267
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700268char *refs_resolve_refdup(struct ref_store *refs,
269 const char *refname, int resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000270 struct object_id *oid, int *flags)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700271{
272 const char *result;
273
274 result = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100275 oid, flags);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700276 return xstrdup_or_null(result);
277}
278
Michael Haggertyfb58c8d2015-06-22 16:03:05 +0200279char *resolve_refdup(const char *refname, int resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000280 struct object_id *oid, int *flags)
Nguyễn Thái Ngọc Duy96ec7b12011-12-13 21:17:48 +0700281{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700282 return refs_resolve_refdup(get_main_ref_store(the_repository),
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700283 refname, resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000284 oid, flags);
Nguyễn Thái Ngọc Duy96ec7b12011-12-13 21:17:48 +0700285}
286
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200287/* The argument to filter_refs */
288struct ref_filter {
289 const char *pattern;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000290 const char *prefix;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200291 each_ref_fn *fn;
292 void *cb_data;
293};
294
brian m. carlson34c290a2017-10-15 22:06:56 +0000295int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int *flags)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700296{
Ævar Arnfjörð Bjarmason76887df2021-10-16 11:39:14 +0200297 struct ref_store *refs = get_main_ref_store(the_repository);
298
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +0200299 if (refs_resolve_ref_unsafe(refs, refname, resolve_flags,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100300 oid, flags))
Ævar Arnfjörð Bjarmason76887df2021-10-16 11:39:14 +0200301 return 0;
302 return -1;
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700303}
304
brian m. carlson34c290a2017-10-15 22:06:56 +0000305int read_ref(const char *refname, struct object_id *oid)
Nguyễn Thái Ngọc Duyc6893322011-11-13 17:22:14 +0700306{
brian m. carlson34c290a2017-10-15 22:06:56 +0000307 return read_ref_full(refname, RESOLVE_REF_READING, oid, NULL);
Nguyễn Thái Ngọc Duyc6893322011-11-13 17:22:14 +0700308}
309
Han-Wen Nienhuys3f9f1ac2020-08-21 16:59:34 +0000310int refs_ref_exists(struct ref_store *refs, const char *refname)
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700311{
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +0200312 return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100313 NULL, NULL);
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700314}
315
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200316int ref_exists(const char *refname)
Junio C Hamanoef06b912006-11-18 22:13:33 -0800317{
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700318 return refs_ref_exists(get_main_ref_store(the_repository), refname);
Junio C Hamanoef06b912006-11-18 22:13:33 -0800319}
320
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000321static int filter_refs(const char *refname, const struct object_id *oid,
Michael Haggerty4e675d12015-05-25 18:39:21 +0000322 int flags, void *data)
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200323{
324 struct ref_filter *filter = (struct ref_filter *)data;
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000325
Ævar Arnfjörð Bjarmason55d34262017-06-22 21:38:08 +0000326 if (wildmatch(filter->pattern, refname, 0))
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200327 return 0;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000328 if (filter->prefix)
329 skip_prefix(refname, filter->prefix, &refname);
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000330 return filter->fn(refname, oid, flags, filter->cb_data);
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200331}
332
brian m. carlsonac2ed0d2017-10-15 22:07:10 +0000333enum peel_status peel_object(const struct object_id *name, struct object_id *oid)
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200334{
Jeff King45a187c2021-04-13 03:16:36 -0400335 struct object *o = lookup_unknown_object(the_repository, name);
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200336
337 if (o->type == OBJ_NONE) {
Stefan Beller0df8e962018-04-25 11:20:59 -0700338 int type = oid_object_info(the_repository, name, NULL);
Abhishek Kumar6da43d92020-06-17 14:44:08 +0530339 if (type < 0 || !object_as_type(o, type, 0))
Michael Haggerty68cf8702013-04-22 21:52:20 +0200340 return PEEL_INVALID;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200341 }
342
343 if (o->type != OBJ_TAG)
Michael Haggerty68cf8702013-04-22 21:52:20 +0200344 return PEEL_NON_TAG;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200345
346 o = deref_tag_noverify(o);
347 if (!o)
Michael Haggerty68cf8702013-04-22 21:52:20 +0200348 return PEEL_INVALID;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200349
brian m. carlsonac2ed0d2017-10-15 22:07:10 +0000350 oidcpy(oid, &o->oid);
Michael Haggerty68cf8702013-04-22 21:52:20 +0200351 return PEEL_PEELED;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200352}
353
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200354struct warn_if_dangling_data {
355 FILE *fp;
356 const char *refname;
Jens Lindströme6bea662014-05-23 12:30:25 +0200357 const struct string_list *refnames;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200358 const char *msg_fmt;
359};
360
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000361static int warn_if_dangling_symref(const char *refname, const struct object_id *oid,
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200362 int flags, void *cb_data)
363{
364 struct warn_if_dangling_data *d = cb_data;
365 const char *resolves_to;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200366
367 if (!(flags & REF_ISSYMREF))
368 return 0;
369
René Scharfe744c0402017-09-23 11:45:04 +0200370 resolves_to = resolve_ref_unsafe(refname, 0, NULL, NULL);
Jens Lindströme6bea662014-05-23 12:30:25 +0200371 if (!resolves_to
372 || (d->refname
373 ? strcmp(resolves_to, d->refname)
374 : !string_list_has_string(d->refnames, resolves_to))) {
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200375 return 0;
Jens Lindströme6bea662014-05-23 12:30:25 +0200376 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200377
378 fprintf(d->fp, d->msg_fmt, refname);
Junio C Hamano1be65ed2012-05-02 13:51:35 -0700379 fputc('\n', d->fp);
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200380 return 0;
381}
382
383void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
384{
385 struct warn_if_dangling_data data;
386
387 data.fp = fp;
388 data.refname = refname;
Jens Lindströme6bea662014-05-23 12:30:25 +0200389 data.refnames = NULL;
390 data.msg_fmt = msg_fmt;
391 for_each_rawref(warn_if_dangling_symref, &data);
392}
393
394void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)
395{
396 struct warn_if_dangling_data data;
397
398 data.fp = fp;
399 data.refname = NULL;
400 data.refnames = refnames;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200401 data.msg_fmt = msg_fmt;
402 for_each_rawref(warn_if_dangling_symref, &data);
403}
404
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700405int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
406{
407 return refs_for_each_ref_in(refs, "refs/tags/", fn, cb_data);
408}
409
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700410int for_each_tag_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400411{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700412 return refs_for_each_tag_ref(get_main_ref_store(the_repository), fn, cb_data);
Seana62be772006-05-13 21:43:00 -0400413}
414
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700415int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
416{
417 return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
Heiko Voigt9ef6aeb2010-07-07 15:39:12 +0200418}
419
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700420int for_each_branch_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400421{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700422 return refs_for_each_branch_ref(get_main_ref_store(the_repository), fn, cb_data);
Seana62be772006-05-13 21:43:00 -0400423}
424
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700425int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
426{
427 return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
Heiko Voigt9ef6aeb2010-07-07 15:39:12 +0200428}
429
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700430int for_each_remote_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400431{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700432 return refs_for_each_remote_ref(get_main_ref_store(the_repository), fn, cb_data);
Junio C Hamanof8948e22009-02-08 23:27:10 -0800433}
434
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700435int head_ref_namespaced(each_ref_fn fn, void *cb_data)
436{
437 struct strbuf buf = STRBUF_INIT;
438 int ret = 0;
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000439 struct object_id oid;
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700440 int flag;
441
442 strbuf_addf(&buf, "%sHEAD", get_git_namespace());
brian m. carlson34c290a2017-10-15 22:06:56 +0000443 if (!read_ref_full(buf.buf, RESOLVE_REF_READING, &oid, &flag))
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000444 ret = fn(buf.buf, &oid, flag, cb_data);
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700445 strbuf_release(&buf);
446
447 return ret;
448}
449
Rafael Ascensão65516f52017-11-21 21:33:41 +0000450void normalize_glob_ref(struct string_list_item *item, const char *prefix,
451 const char *pattern)
452{
453 struct strbuf normalized_pattern = STRBUF_INIT;
454
455 if (*pattern == '/')
456 BUG("pattern must not start with '/'");
457
458 if (prefix) {
459 strbuf_addstr(&normalized_pattern, prefix);
460 }
461 else if (!starts_with(pattern, "refs/"))
462 strbuf_addstr(&normalized_pattern, "refs/");
463 strbuf_addstr(&normalized_pattern, pattern);
464 strbuf_strip_suffix(&normalized_pattern, "/");
465
466 item->string = strbuf_detach(&normalized_pattern, NULL);
467 item->util = has_glob_specials(pattern) ? NULL : item->string;
468 strbuf_release(&normalized_pattern);
469}
470
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200471int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
472 const char *prefix, void *cb_data)
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200473{
474 struct strbuf real_pattern = STRBUF_INIT;
475 struct ref_filter filter;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200476 int ret;
477
Christian Couder59556542013-11-30 21:55:40 +0100478 if (!prefix && !starts_with(pattern, "refs/"))
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200479 strbuf_addstr(&real_pattern, "refs/");
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200480 else if (prefix)
481 strbuf_addstr(&real_pattern, prefix);
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200482 strbuf_addstr(&real_pattern, pattern);
483
Thomas Rast894a9d32010-03-12 18:04:26 +0100484 if (!has_glob_specials(pattern)) {
Junio C Hamano9517e6b2010-02-03 21:23:18 -0800485 /* Append implied '/' '*' if not present. */
Jeff King00b6c172015-09-24 17:08:35 -0400486 strbuf_complete(&real_pattern, '/');
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200487 /* No need to check for '*', there is none. */
488 strbuf_addch(&real_pattern, '*');
489 }
490
491 filter.pattern = real_pattern.buf;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000492 filter.prefix = prefix;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200493 filter.fn = fn;
494 filter.cb_data = cb_data;
495 ret = for_each_ref(filter_refs, &filter);
496
497 strbuf_release(&real_pattern);
498 return ret;
499}
500
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200501int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
502{
503 return for_each_glob_ref_in(fn, pattern, NULL, cb_data);
504}
505
Felipe Contreras4577e482009-05-14 00:22:04 +0300506const char *prettify_refname(const char *name)
Daniel Barkalowa9c37a72009-03-08 21:06:05 -0400507{
SZEDER Gábor3e5b36c2017-03-23 16:50:12 +0100508 if (skip_prefix(name, "refs/heads/", &name) ||
509 skip_prefix(name, "refs/tags/", &name) ||
510 skip_prefix(name, "refs/remotes/", &name))
511 ; /* nothing */
512 return name;
Daniel Barkalowa9c37a72009-03-08 21:06:05 -0400513}
514
Michael Haggerty54457fe2014-01-14 04:16:07 +0100515static const char *ref_rev_parse_rules[] = {
Steffen Prohaska79803322007-11-11 15:01:46 +0100516 "%.*s",
517 "refs/%.*s",
518 "refs/tags/%.*s",
519 "refs/heads/%.*s",
520 "refs/remotes/%.*s",
521 "refs/remotes/%.*s/HEAD",
522 NULL
523};
524
Junio C Hamano60650a42018-08-01 09:22:37 -0700525#define NUM_REV_PARSE_RULES (ARRAY_SIZE(ref_rev_parse_rules) - 1)
526
527/*
528 * Is it possible that the caller meant full_name with abbrev_name?
529 * If so return a non-zero value to signal "yes"; the magnitude of
530 * the returned value gives the precedence used for disambiguation.
531 *
532 * If abbrev_name cannot mean full_name, return 0.
533 */
Michael Haggerty54457fe2014-01-14 04:16:07 +0100534int refname_match(const char *abbrev_name, const char *full_name)
Steffen Prohaska79803322007-11-11 15:01:46 +0100535{
536 const char **p;
537 const int abbrev_name_len = strlen(abbrev_name);
Junio C Hamano60650a42018-08-01 09:22:37 -0700538 const int num_rules = NUM_REV_PARSE_RULES;
Steffen Prohaska79803322007-11-11 15:01:46 +0100539
Junio C Hamano60650a42018-08-01 09:22:37 -0700540 for (p = ref_rev_parse_rules; *p; p++)
541 if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name)))
542 return &ref_rev_parse_rules[num_rules] - p;
Steffen Prohaska79803322007-11-11 15:01:46 +0100543
544 return 0;
545}
546
Michael Haggerty19b68b12011-12-12 06:38:12 +0100547/*
Brandon Williamsb4be7412018-03-15 10:31:24 -0700548 * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add
549 * the results to 'prefixes'
550 */
Jeff Kingc972bf42020-07-28 16:25:12 -0400551void expand_ref_prefix(struct strvec *prefixes, const char *prefix)
Brandon Williamsb4be7412018-03-15 10:31:24 -0700552{
553 const char **p;
554 int len = strlen(prefix);
555
556 for (p = ref_rev_parse_rules; *p; p++)
Jeff Kingc972bf42020-07-28 16:25:12 -0400557 strvec_pushf(prefixes, *p, len, prefix);
Brandon Williamsb4be7412018-03-15 10:31:24 -0700558}
559
Johannes Schindelin675704c2020-12-11 11:36:57 +0000560static const char default_branch_name_advice[] = N_(
561"Using '%s' as the name for the initial branch. This default branch name\n"
562"is subject to change. To configure the initial branch name to use in all\n"
563"of your new repositories, which will suppress this warning, call:\n"
564"\n"
565"\tgit config --global init.defaultBranch <name>\n"
566"\n"
567"Names commonly chosen instead of 'master' are 'main', 'trunk' and\n"
568"'development'. The just-created branch can be renamed via this command:\n"
569"\n"
570"\tgit branch -m <name>\n"
571);
572
Johannes Schindelincc0f13c2020-12-11 11:36:56 +0000573char *repo_default_branch_name(struct repository *r, int quiet)
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000574{
575 const char *config_key = "init.defaultbranch";
576 const char *config_display_key = "init.defaultBranch";
577 char *ret = NULL, *full_ref;
Johannes Schindelin704fed92020-10-23 14:00:00 +0000578 const char *env = getenv("GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME");
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000579
Johannes Schindelin704fed92020-10-23 14:00:00 +0000580 if (env && *env)
581 ret = xstrdup(env);
582 else if (repo_config_get_string(r, config_key, &ret) < 0)
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000583 die(_("could not retrieve `%s`"), config_display_key);
584
Johannes Schindelin675704c2020-12-11 11:36:57 +0000585 if (!ret) {
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000586 ret = xstrdup("master");
Johannes Schindelin675704c2020-12-11 11:36:57 +0000587 if (!quiet)
588 advise(_(default_branch_name_advice), ret);
589 }
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000590
591 full_ref = xstrfmt("refs/heads/%s", ret);
592 if (check_refname_format(full_ref, 0))
593 die(_("invalid branch name: %s = %s"), config_display_key, ret);
594 free(full_ref);
595
596 return ret;
597}
598
Johannes Schindelincc0f13c2020-12-11 11:36:56 +0000599const char *git_default_branch_name(int quiet)
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000600{
601 static char *ret;
602
603 if (!ret)
Johannes Schindelincc0f13c2020-12-11 11:36:56 +0000604 ret = repo_default_branch_name(the_repository, quiet);
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000605
606 return ret;
607}
608
Brandon Williamsb4be7412018-03-15 10:31:24 -0700609/*
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700610 * *string and *len will only be substituted, and *string returned (for
611 * later free()ing) if the string passed in is a magic short-hand form
612 * to name a branch.
613 */
Nguyễn Thái Ngọc Duy8f56e9d2019-04-06 18:34:26 +0700614static char *substitute_branch_name(struct repository *r,
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700615 const char **string, int *len,
616 int nonfatal_dangling_mark)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700617{
618 struct strbuf buf = STRBUF_INIT;
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700619 struct interpret_branch_name_options options = {
620 .nonfatal_dangling_mark = nonfatal_dangling_mark
621 };
Jonathan Tana4f66a72020-09-01 15:28:07 -0700622 int ret = repo_interpret_branch_name(r, *string, *len, &buf, &options);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700623
624 if (ret == *len) {
625 size_t size;
626 *string = strbuf_detach(&buf, &size);
627 *len = size;
628 return (char *)*string;
629 }
630
631 return NULL;
632}
633
Nguyễn Thái Ngọc Duyd8984c52019-04-06 18:34:28 +0700634int repo_dwim_ref(struct repository *r, const char *str, int len,
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700635 struct object_id *oid, char **ref, int nonfatal_dangling_mark)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700636{
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700637 char *last_branch = substitute_branch_name(r, &str, &len,
638 nonfatal_dangling_mark);
Nguyễn Thái Ngọc Duyd8984c52019-04-06 18:34:28 +0700639 int refs_found = expand_ref(r, str, len, oid, ref);
Nguyễn Thái Ngọc Duy41da7112016-06-12 17:54:02 +0700640 free(last_branch);
641 return refs_found;
642}
643
Nguyễn Thái Ngọc Duy0b1dbf52019-04-06 18:34:27 +0700644int expand_ref(struct repository *repo, const char *str, int len,
645 struct object_id *oid, char **ref)
Nguyễn Thái Ngọc Duy41da7112016-06-12 17:54:02 +0700646{
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700647 const char **p, *r;
648 int refs_found = 0;
Jeff King6cd4a892017-03-28 15:46:33 -0400649 struct strbuf fullref = STRBUF_INIT;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700650
651 *ref = NULL;
652 for (p = ref_rev_parse_rules; *p; p++) {
brian m. carlsoncca5fa62017-10-15 22:06:57 +0000653 struct object_id oid_from_ref;
654 struct object_id *this_result;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700655 int flag;
Ævar Arnfjörð Bjarmason6582bd32021-10-16 11:39:24 +0200656 struct ref_store *refs = get_main_ref_store(repo);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700657
brian m. carlsoncca5fa62017-10-15 22:06:57 +0000658 this_result = refs_found ? &oid_from_ref : oid;
Jeff King6cd4a892017-03-28 15:46:33 -0400659 strbuf_reset(&fullref);
660 strbuf_addf(&fullref, *p, len, str);
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +0200661 r = refs_resolve_ref_unsafe(refs, fullref.buf,
Ævar Arnfjörð Bjarmason6582bd32021-10-16 11:39:24 +0200662 RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100663 this_result, &flag);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700664 if (r) {
665 if (!refs_found++)
666 *ref = xstrdup(r);
667 if (!warn_ambiguous_refs)
668 break;
Jeff King6cd4a892017-03-28 15:46:33 -0400669 } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200670 warning(_("ignoring dangling symref %s"), fullref.buf);
Jeff King6cd4a892017-03-28 15:46:33 -0400671 } else if ((flag & REF_ISBROKEN) && strchr(fullref.buf, '/')) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200672 warning(_("ignoring broken ref %s"), fullref.buf);
Junio C Hamano55956352011-10-19 13:55:49 -0700673 }
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700674 }
Jeff King6cd4a892017-03-28 15:46:33 -0400675 strbuf_release(&fullref);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700676 return refs_found;
677}
678
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700679int repo_dwim_log(struct repository *r, const char *str, int len,
680 struct object_id *oid, char **log)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700681{
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700682 struct ref_store *refs = get_main_ref_store(r);
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700683 char *last_branch = substitute_branch_name(r, &str, &len, 0);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700684 const char **p;
685 int logs_found = 0;
Jeff King6cd4a892017-03-28 15:46:33 -0400686 struct strbuf path = STRBUF_INIT;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700687
688 *log = NULL;
689 for (p = ref_rev_parse_rules; *p; p++) {
brian m. carlson334dc522017-10-15 22:06:59 +0000690 struct object_id hash;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700691 const char *ref, *it;
692
Jeff King6cd4a892017-03-28 15:46:33 -0400693 strbuf_reset(&path);
694 strbuf_addf(&path, *p, len, str);
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700695 ref = refs_resolve_ref_unsafe(refs, path.buf,
696 RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100697 oid ? &hash : NULL, NULL);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700698 if (!ref)
699 continue;
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700700 if (refs_reflog_exists(refs, path.buf))
Jeff King6cd4a892017-03-28 15:46:33 -0400701 it = path.buf;
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700702 else if (strcmp(ref, path.buf) &&
703 refs_reflog_exists(refs, ref))
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700704 it = ref;
705 else
706 continue;
707 if (!logs_found++) {
708 *log = xstrdup(it);
Ævar Arnfjörð Bjarmason6f45ec82021-08-23 13:36:08 +0200709 if (oid)
710 oidcpy(oid, &hash);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700711 }
712 if (!warn_ambiguous_refs)
713 break;
714 }
Jeff King6cd4a892017-03-28 15:46:33 -0400715 strbuf_release(&path);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700716 free(last_branch);
717 return logs_found;
718}
719
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700720int dwim_log(const char *str, int len, struct object_id *oid, char **log)
721{
722 return repo_dwim_log(the_repository, str, len, oid, log);
723}
724
David Turner266b1822015-07-31 02:06:18 -0400725static int is_per_worktree_ref(const char *refname)
726{
Han-Wen Nienhuys55dd8b92020-07-27 16:25:47 +0000727 return starts_with(refname, "refs/worktree/") ||
728 starts_with(refname, "refs/bisect/") ||
729 starts_with(refname, "refs/rewritten/");
David Turner266b1822015-07-31 02:06:18 -0400730}
731
732static int is_pseudoref_syntax(const char *refname)
733{
734 const char *c;
735
736 for (c = refname; *c; c++) {
737 if (!isupper(*c) && *c != '-' && *c != '_')
738 return 0;
739 }
740
741 return 1;
742}
743
Nguyễn Thái Ngọc Duy3a3b9d82018-10-21 10:08:54 +0200744static int is_main_pseudoref_syntax(const char *refname)
745{
746 return skip_prefix(refname, "main-worktree/", &refname) &&
747 *refname &&
748 is_pseudoref_syntax(refname);
749}
750
751static int is_other_pseudoref_syntax(const char *refname)
752{
753 if (!skip_prefix(refname, "worktrees/", &refname))
754 return 0;
755 refname = strchr(refname, '/');
756 if (!refname || !refname[1])
757 return 0;
758 return is_pseudoref_syntax(refname + 1);
759}
760
David Turner266b1822015-07-31 02:06:18 -0400761enum ref_type ref_type(const char *refname)
762{
763 if (is_per_worktree_ref(refname))
764 return REF_TYPE_PER_WORKTREE;
765 if (is_pseudoref_syntax(refname))
766 return REF_TYPE_PSEUDOREF;
Nguyễn Thái Ngọc Duy3a3b9d82018-10-21 10:08:54 +0200767 if (is_main_pseudoref_syntax(refname))
768 return REF_TYPE_MAIN_PSEUDOREF;
769 if (is_other_pseudoref_syntax(refname))
770 return REF_TYPE_OTHER_PSEUDOREF;
Nguyễn Thái Ngọc Duy5c79f742018-09-29 21:10:22 +0200771 return REF_TYPE_NORMAL;
David Turner266b1822015-07-31 02:06:18 -0400772}
773
Michael Haggerty4ff0f012017-08-21 13:51:34 +0200774long get_files_ref_lock_timeout_ms(void)
775{
776 static int configured = 0;
777
778 /* The default timeout is 100 ms: */
779 static int timeout_ms = 100;
780
781 if (!configured) {
782 git_config_get_int("core.filesreflocktimeout", &timeout_ms);
783 configured = 1;
784 }
785
786 return timeout_ms;
787}
788
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700789int refs_delete_ref(struct ref_store *refs, const char *msg,
790 const char *refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000791 const struct object_id *old_oid,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700792 unsigned int flags)
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700793{
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700794 struct ref_transaction *transaction;
795 struct strbuf err = STRBUF_INIT;
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700796
Junio C Hamanoc6da34a2022-04-13 15:51:33 -0700797 transaction = ref_store_transaction_begin(refs, &err);
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700798 if (!transaction ||
brian m. carlson89f3bbd2017-10-15 22:06:53 +0000799 ref_transaction_delete(transaction, refname, old_oid,
Kyle Meyer755b49a2017-02-20 20:10:32 -0500800 flags, msg, &err) ||
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -0700801 ref_transaction_commit(transaction, &err)) {
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700802 error("%s", err.buf);
803 ref_transaction_free(transaction);
804 strbuf_release(&err);
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700805 return 1;
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700806 }
807 ref_transaction_free(transaction);
808 strbuf_release(&err);
809 return 0;
Shawn Pearce4bd18c42006-05-17 05:55:02 -0400810}
811
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700812int delete_ref(const char *msg, const char *refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000813 const struct object_id *old_oid, unsigned int flags)
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700814{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700815 return refs_delete_ref(get_main_ref_store(the_repository), msg, refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000816 old_oid, flags);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700817}
818
Junio C Hamano523fa692020-07-10 17:19:53 +0000819static void copy_reflog_msg(struct strbuf *sb, const char *msg)
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700820{
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700821 char c;
822 int wasspace = 1;
823
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700824 while ((c = *msg++)) {
825 if (wasspace && isspace(c))
826 continue;
827 wasspace = isspace(c);
828 if (wasspace)
829 c = ' ';
Ben Peart80a6c202018-07-10 21:08:22 +0000830 strbuf_addch(sb, c);
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700831 }
Ben Peart80a6c202018-07-10 21:08:22 +0000832 strbuf_rtrim(sb);
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700833}
834
Junio C Hamano523fa692020-07-10 17:19:53 +0000835static char *normalize_reflog_message(const char *msg)
836{
837 struct strbuf sb = STRBUF_INIT;
838
839 if (msg && *msg)
840 copy_reflog_msg(&sb, msg);
841 return strbuf_detach(&sb, NULL);
842}
843
Michael Haggerty4cb77002015-11-10 12:42:36 +0100844int should_autocreate_reflog(const char *refname)
David Turner4e2bef52015-07-21 17:04:51 -0400845{
Cornelius Weig341fb282017-01-27 11:09:47 +0100846 switch (log_all_ref_updates) {
847 case LOG_REFS_ALWAYS:
848 return 1;
849 case LOG_REFS_NORMAL:
850 return starts_with(refname, "refs/heads/") ||
851 starts_with(refname, "refs/remotes/") ||
852 starts_with(refname, "refs/notes/") ||
853 !strcmp(refname, "HEAD");
854 default:
David Turner4e2bef52015-07-21 17:04:51 -0400855 return 0;
Cornelius Weig341fb282017-01-27 11:09:47 +0100856 }
David Turner4e2bef52015-07-21 17:04:51 -0400857}
858
Ronnie Sahlberge7e0f262014-07-15 16:02:38 -0700859int is_branch(const char *refname)
Linus Torvaldsc3b0dec2008-01-15 15:50:17 -0800860{
Christian Couder59556542013-11-30 21:55:40 +0100861 return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
Linus Torvaldsc3b0dec2008-01-15 15:50:17 -0800862}
863
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700864struct read_ref_at_cb {
865 const char *refname;
Johannes Schindelindddbad72017-04-26 21:29:31 +0200866 timestamp_t at_time;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700867 int cnt;
868 int reccnt;
brian m. carlson8eb36d92017-10-15 22:07:03 +0000869 struct object_id *oid;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700870 int found_it;
871
brian m. carlson8eb36d92017-10-15 22:07:03 +0000872 struct object_id ooid;
873 struct object_id noid;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700874 int tz;
Johannes Schindelindddbad72017-04-26 21:29:31 +0200875 timestamp_t date;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700876 char **msg;
Johannes Schindelindddbad72017-04-26 21:29:31 +0200877 timestamp_t *cutoff_time;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700878 int *cutoff_tz;
879 int *cutoff_cnt;
880};
881
Denton Liu95c2a712021-01-06 01:01:53 -0800882static void set_read_ref_cutoffs(struct read_ref_at_cb *cb,
883 timestamp_t timestamp, int tz, const char *message)
884{
885 if (cb->msg)
886 *cb->msg = xstrdup(message);
887 if (cb->cutoff_time)
888 *cb->cutoff_time = timestamp;
889 if (cb->cutoff_tz)
890 *cb->cutoff_tz = tz;
891 if (cb->cutoff_cnt)
892 *cb->cutoff_cnt = cb->reccnt;
893}
894
brian m. carlson9461d272017-02-21 23:47:32 +0000895static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
Johannes Schindelindddbad72017-04-26 21:29:31 +0200896 const char *email, timestamp_t timestamp, int tz,
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700897 const char *message, void *cb_data)
Junio C Hamano16d7cc92007-01-19 01:19:05 -0800898{
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700899 struct read_ref_at_cb *cb = cb_data;
Denton Liu6436a202021-01-07 02:36:59 -0800900 int reached_count;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700901
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700902 cb->tz = tz;
903 cb->date = timestamp;
904
Denton Liu6436a202021-01-07 02:36:59 -0800905 /*
906 * It is not possible for cb->cnt == 0 on the first iteration because
907 * that special case is handled in read_ref_at().
908 */
909 if (cb->cnt > 0)
910 cb->cnt--;
911 reached_count = cb->cnt == 0 && !is_null_oid(ooid);
912 if (timestamp <= cb->at_time || reached_count) {
Denton Liu95c2a712021-01-06 01:01:53 -0800913 set_read_ref_cutoffs(cb, timestamp, tz, message);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700914 /*
Michael Haggerty78fb4572017-11-05 09:42:09 +0100915 * we have not yet updated cb->[n|o]oid so they still
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700916 * hold the values for the previous record.
917 */
Denton Liu6436a202021-01-07 02:36:59 -0800918 if (!is_null_oid(&cb->ooid) && !oideq(&cb->ooid, noid))
919 warning(_("log for ref %s has gap after %s"),
Jeff Kinga5481a62015-06-25 12:55:02 -0400920 cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
Denton Liu6436a202021-01-07 02:36:59 -0800921 if (reached_count)
922 oidcpy(cb->oid, ooid);
923 else if (!is_null_oid(&cb->ooid) || cb->date == cb->at_time)
brian m. carlson8eb36d92017-10-15 22:07:03 +0000924 oidcpy(cb->oid, noid);
Jeff King9001dc22018-08-28 17:22:48 -0400925 else if (!oideq(noid, cb->oid))
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200926 warning(_("log for ref %s unexpectedly ended on %s"),
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700927 cb->refname, show_date(cb->date, cb->tz,
Jeff Kinga5481a62015-06-25 12:55:02 -0400928 DATE_MODE(RFC2822)));
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700929 cb->found_it = 1;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700930 }
Denton Liu95c2a712021-01-06 01:01:53 -0800931 cb->reccnt++;
brian m. carlson8eb36d92017-10-15 22:07:03 +0000932 oidcpy(&cb->ooid, ooid);
933 oidcpy(&cb->noid, noid);
Denton Liu6436a202021-01-07 02:36:59 -0800934 return cb->found_it;
935}
936
937static int read_ref_at_ent_newest(struct object_id *ooid, struct object_id *noid,
938 const char *email, timestamp_t timestamp,
939 int tz, const char *message, void *cb_data)
940{
941 struct read_ref_at_cb *cb = cb_data;
942
943 set_read_ref_cutoffs(cb, timestamp, tz, message);
944 oidcpy(cb->oid, noid);
945 /* We just want the first entry */
946 return 1;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700947}
948
brian m. carlson9461d272017-02-21 23:47:32 +0000949static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid,
Johannes Schindelindddbad72017-04-26 21:29:31 +0200950 const char *email, timestamp_t timestamp,
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700951 int tz, const char *message, void *cb_data)
952{
953 struct read_ref_at_cb *cb = cb_data;
954
Denton Liu95c2a712021-01-06 01:01:53 -0800955 set_read_ref_cutoffs(cb, timestamp, tz, message);
brian m. carlson8eb36d92017-10-15 22:07:03 +0000956 oidcpy(cb->oid, ooid);
957 if (is_null_oid(cb->oid))
958 oidcpy(cb->oid, noid);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700959 /* We just want the first entry */
960 return 1;
Junio C Hamano16d7cc92007-01-19 01:19:05 -0800961}
962
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +0700963int read_ref_at(struct ref_store *refs, const char *refname,
964 unsigned int flags, timestamp_t at_time, int cnt,
brian m. carlson8eb36d92017-10-15 22:07:03 +0000965 struct object_id *oid, char **msg,
Johannes Schindelindddbad72017-04-26 21:29:31 +0200966 timestamp_t *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
Shawn Pearced556fae2006-05-17 05:56:09 -0400967{
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700968 struct read_ref_at_cb cb;
Shawn Pearced556fae2006-05-17 05:56:09 -0400969
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700970 memset(&cb, 0, sizeof(cb));
971 cb.refname = refname;
972 cb.at_time = at_time;
973 cb.cnt = cnt;
974 cb.msg = msg;
975 cb.cutoff_time = cutoff_time;
976 cb.cutoff_tz = cutoff_tz;
977 cb.cutoff_cnt = cutoff_cnt;
brian m. carlson8eb36d92017-10-15 22:07:03 +0000978 cb.oid = oid;
Shawn Pearced556fae2006-05-17 05:56:09 -0400979
Denton Liu6436a202021-01-07 02:36:59 -0800980 if (cb.cnt == 0) {
981 refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent_newest, &cb);
982 return 0;
983 }
984
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +0700985 refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent, &cb);
Shawn Pearced556fae2006-05-17 05:56:09 -0400986
David Aguilarc41a87d2014-09-18 20:45:37 -0700987 if (!cb.reccnt) {
brian m. carlson321c89b2017-07-13 23:49:29 +0000988 if (flags & GET_OID_QUIETLY)
David Aguilarc41a87d2014-09-18 20:45:37 -0700989 exit(128);
990 else
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200991 die(_("log for %s is empty"), refname);
David Aguilarc41a87d2014-09-18 20:45:37 -0700992 }
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700993 if (cb.found_it)
994 return 0;
Junio C Hamano16d7cc92007-01-19 01:19:05 -0800995
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +0700996 refs_for_each_reflog_ent(refs, refname, read_ref_at_ent_oldest, &cb);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700997
Junio C Hamano16d7cc92007-01-19 01:19:05 -0800998 return 1;
Shawn Pearced556fae2006-05-17 05:56:09 -0400999}
Junio C Hamano2ff81662006-12-18 01:18:16 -08001000
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001001struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
1002 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001003{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001004 struct ref_transaction *tr;
Jonathan Nieder5a603b02014-08-28 16:42:37 -07001005 assert(err);
1006
René Scharfeca56dad2021-03-13 17:17:22 +01001007 CALLOC_ARRAY(tr, 1);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001008 tr->ref_store = refs;
1009 return tr;
1010}
1011
1012struct ref_transaction *ref_transaction_begin(struct strbuf *err)
1013{
Junio C Hamanoc6da34a2022-04-13 15:51:33 -07001014 return ref_store_transaction_begin(get_main_ref_store(the_repository), err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001015}
1016
Ronnie Sahlberg026bd1d2014-06-20 07:42:42 -07001017void ref_transaction_free(struct ref_transaction *transaction)
Michael Haggertycaa40462014-04-07 15:48:10 +02001018{
Michael Haggerty43a2dfd2017-05-22 16:17:37 +02001019 size_t i;
Michael Haggertycaa40462014-04-07 15:48:10 +02001020
Ronnie Sahlberg1b072552014-06-20 07:42:45 -07001021 if (!transaction)
1022 return;
1023
Michael Haggerty30173b82017-05-22 16:17:44 +02001024 switch (transaction->state) {
1025 case REF_TRANSACTION_OPEN:
1026 case REF_TRANSACTION_CLOSED:
1027 /* OK */
1028 break;
1029 case REF_TRANSACTION_PREPARED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02001030 BUG("free called on a prepared reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02001031 break;
1032 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02001033 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02001034 break;
1035 }
1036
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -07001037 for (i = 0; i < transaction->nr; i++) {
1038 free(transaction->updates[i]->msg);
Michael Haggerty88615912014-04-07 15:48:14 +02001039 free(transaction->updates[i]);
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -07001040 }
Michael Haggertycaa40462014-04-07 15:48:10 +02001041 free(transaction->updates);
1042 free(transaction);
1043}
1044
Michael Haggerty71564512016-04-25 11:39:54 +02001045struct ref_update *ref_transaction_add_update(
1046 struct ref_transaction *transaction,
1047 const char *refname, unsigned int flags,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001048 const struct object_id *new_oid,
1049 const struct object_id *old_oid,
Michael Haggerty71564512016-04-25 11:39:54 +02001050 const char *msg)
Michael Haggertycaa40462014-04-07 15:48:10 +02001051{
Jeff King96ffc062016-02-22 17:44:32 -05001052 struct ref_update *update;
Michael Haggerty71564512016-04-25 11:39:54 +02001053
1054 if (transaction->state != REF_TRANSACTION_OPEN)
Johannes Schindelin033abf92018-05-02 11:38:39 +02001055 BUG("update called for transaction that is not open");
Michael Haggerty71564512016-04-25 11:39:54 +02001056
Jeff King96ffc062016-02-22 17:44:32 -05001057 FLEX_ALLOC_STR(update, refname, refname);
Michael Haggertycaa40462014-04-07 15:48:10 +02001058 ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
1059 transaction->updates[transaction->nr++] = update;
Michael Haggerty71564512016-04-25 11:39:54 +02001060
1061 update->flags = flags;
1062
1063 if (flags & REF_HAVE_NEW)
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001064 oidcpy(&update->new_oid, new_oid);
Michael Haggerty71564512016-04-25 11:39:54 +02001065 if (flags & REF_HAVE_OLD)
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001066 oidcpy(&update->old_oid, old_oid);
Junio C Hamano523fa692020-07-10 17:19:53 +00001067 update->msg = normalize_reflog_message(msg);
Michael Haggertycaa40462014-04-07 15:48:10 +02001068 return update;
1069}
1070
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001071int ref_transaction_update(struct ref_transaction *transaction,
1072 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001073 const struct object_id *new_oid,
1074 const struct object_id *old_oid,
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001075 unsigned int flags, const char *msg,
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001076 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001077{
Jonathan Nieder5a603b02014-08-28 16:42:37 -07001078 assert(err);
1079
Han-Wen Nienhuys3c966c72021-12-07 13:38:18 +00001080 if (!(flags & REF_SKIP_REFNAME_VERIFICATION) &&
1081 ((new_oid && !is_null_oid(new_oid)) ?
1082 check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) :
1083 !refname_is_safe(refname))) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001084 strbuf_addf(err, _("refusing to update ref with bad name '%s'"),
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -07001085 refname);
1086 return -1;
1087 }
1088
Michael Haggertya9bbbce2017-11-05 09:42:03 +01001089 if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
1090 BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
Thomas Gummererc788c542017-09-12 23:59:21 +01001091
Jeff King49f1eb32021-11-19 16:28:30 -05001092 /*
1093 * Clear flags outside the allowed set; this should be a noop because
1094 * of the BUG() check above, but it works around a -Wnonnull warning
1095 * with some versions of "gcc -O3".
1096 */
1097 flags &= REF_TRANSACTION_UPDATE_ALLOWED_FLAGS;
1098
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001099 flags |= (new_oid ? REF_HAVE_NEW : 0) | (old_oid ? REF_HAVE_OLD : 0);
Michael Haggerty71564512016-04-25 11:39:54 +02001100
1101 ref_transaction_add_update(transaction, refname, flags,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001102 new_oid, old_oid, msg);
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001103 return 0;
Michael Haggertycaa40462014-04-07 15:48:10 +02001104}
1105
Ronnie Sahlbergb416af52014-04-16 15:26:44 -07001106int ref_transaction_create(struct ref_transaction *transaction,
1107 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001108 const struct object_id *new_oid,
Michael Haggertyfec14ec2015-02-17 18:00:13 +01001109 unsigned int flags, const char *msg,
Ronnie Sahlbergb416af52014-04-16 15:26:44 -07001110 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001111{
Derrick Stoleed097a232022-04-25 13:47:30 +00001112 if (!new_oid || is_null_oid(new_oid)) {
1113 strbuf_addf(err, "'%s' has a null OID", refname);
1114 return 1;
1115 }
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001116 return ref_transaction_update(transaction, refname, new_oid,
brian m. carlson14228442021-04-26 01:02:56 +00001117 null_oid(), flags, msg, err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001118}
1119
Ronnie Sahlberg8c8bdc02014-04-16 15:27:45 -07001120int ref_transaction_delete(struct ref_transaction *transaction,
1121 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001122 const struct object_id *old_oid,
Michael Haggertyfb5a6bb2015-02-17 18:00:16 +01001123 unsigned int flags, const char *msg,
Ronnie Sahlberg8c8bdc02014-04-16 15:27:45 -07001124 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001125{
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001126 if (old_oid && is_null_oid(old_oid))
Johannes Schindelin033abf92018-05-02 11:38:39 +02001127 BUG("delete called with old_oid set to zeros");
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001128 return ref_transaction_update(transaction, refname,
brian m. carlson14228442021-04-26 01:02:56 +00001129 null_oid(), old_oid,
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001130 flags, msg, err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001131}
1132
Michael Haggerty16180332015-02-17 18:00:21 +01001133int ref_transaction_verify(struct ref_transaction *transaction,
1134 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001135 const struct object_id *old_oid,
Michael Haggerty16180332015-02-17 18:00:21 +01001136 unsigned int flags,
1137 struct strbuf *err)
1138{
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001139 if (!old_oid)
Johannes Schindelin033abf92018-05-02 11:38:39 +02001140 BUG("verify called with old_oid set to NULL");
Michael Haggerty16180332015-02-17 18:00:21 +01001141 return ref_transaction_update(transaction, refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001142 NULL, old_oid,
Michael Haggerty16180332015-02-17 18:00:21 +01001143 flags, NULL, err);
1144}
1145
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001146int refs_update_ref(struct ref_store *refs, const char *msg,
brian m. carlsonae077772017-10-15 22:06:51 +00001147 const char *refname, const struct object_id *new_oid,
1148 const struct object_id *old_oid, unsigned int flags,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001149 enum action_on_err onerr)
Brad King4738a332013-09-04 11:22:40 -04001150{
David Turner74ec19d2015-07-31 02:06:19 -04001151 struct ref_transaction *t = NULL;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001152 struct strbuf err = STRBUF_INIT;
David Turner74ec19d2015-07-31 02:06:19 -04001153 int ret = 0;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001154
Junio C Hamanoc6da34a2022-04-13 15:51:33 -07001155 t = ref_store_transaction_begin(refs, &err);
Han-Wen Nienhuys09743412020-07-27 16:25:46 +00001156 if (!t ||
1157 ref_transaction_update(t, refname, new_oid, old_oid, flags, msg,
1158 &err) ||
1159 ref_transaction_commit(t, &err)) {
1160 ret = 1;
1161 ref_transaction_free(t);
David Turner74ec19d2015-07-31 02:06:19 -04001162 }
1163 if (ret) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001164 const char *str = _("update_ref failed for ref '%s': %s");
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001165
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001166 switch (onerr) {
1167 case UPDATE_REFS_MSG_ON_ERR:
1168 error(str, refname, err.buf);
1169 break;
1170 case UPDATE_REFS_DIE_ON_ERR:
1171 die(str, refname, err.buf);
1172 break;
1173 case UPDATE_REFS_QUIET_ON_ERR:
1174 break;
1175 }
1176 strbuf_release(&err);
Brad King4738a332013-09-04 11:22:40 -04001177 return 1;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001178 }
1179 strbuf_release(&err);
David Turner74ec19d2015-07-31 02:06:19 -04001180 if (t)
1181 ref_transaction_free(t);
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001182 return 0;
Brad King4738a332013-09-04 11:22:40 -04001183}
1184
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001185int update_ref(const char *msg, const char *refname,
brian m. carlsonae077772017-10-15 22:06:51 +00001186 const struct object_id *new_oid,
1187 const struct object_id *old_oid,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001188 unsigned int flags, enum action_on_err onerr)
1189{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001190 return refs_update_ref(get_main_ref_store(the_repository), msg, refname, new_oid,
brian m. carlsonae077772017-10-15 22:06:51 +00001191 old_oid, flags, onerr);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001192}
1193
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001194char *refs_shorten_unambiguous_ref(struct ref_store *refs,
1195 const char *refname, int strict)
Jeff King7c2b3022009-04-07 03:14:20 -04001196{
1197 int i;
1198 static char **scanf_fmts;
1199 static int nr_rules;
1200 char *short_name;
Jeff King6cd4a892017-03-28 15:46:33 -04001201 struct strbuf resolved_buf = STRBUF_INIT;
Jeff King7c2b3022009-04-07 03:14:20 -04001202
Jeff King7c2b3022009-04-07 03:14:20 -04001203 if (!nr_rules) {
Michael Haggerty43466632014-01-08 15:43:39 +01001204 /*
1205 * Pre-generate scanf formats from ref_rev_parse_rules[].
1206 * Generate a format suitable for scanf from a
1207 * ref_rev_parse_rules rule by interpolating "%s" at the
1208 * location of the "%.*s".
1209 */
Jeff King7c2b3022009-04-07 03:14:20 -04001210 size_t total_len = 0;
Michael Haggerty84d56332014-01-08 15:43:38 +01001211 size_t offset = 0;
Jeff King7c2b3022009-04-07 03:14:20 -04001212
1213 /* the rule list is NULL terminated, count them first */
Jeff Kinga4165852013-10-24 04:45:13 -04001214 for (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++)
Michael Haggerty7902fe02014-01-08 15:43:40 +01001215 /* -2 for strlen("%.*s") - strlen("%s"); +1 for NUL */
1216 total_len += strlen(ref_rev_parse_rules[nr_rules]) - 2 + 1;
Jeff King7c2b3022009-04-07 03:14:20 -04001217
René Scharfe50492f72016-07-30 20:18:31 +02001218 scanf_fmts = xmalloc(st_add(st_mult(sizeof(char *), nr_rules), total_len));
Jeff King7c2b3022009-04-07 03:14:20 -04001219
Michael Haggerty84d56332014-01-08 15:43:38 +01001220 offset = 0;
Jeff King7c2b3022009-04-07 03:14:20 -04001221 for (i = 0; i < nr_rules; i++) {
Michael Haggerty43466632014-01-08 15:43:39 +01001222 assert(offset < total_len);
Michael Haggerty84d56332014-01-08 15:43:38 +01001223 scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset;
Jeff Kingbf4baf12018-05-18 18:58:20 -07001224 offset += xsnprintf(scanf_fmts[i], total_len - offset,
1225 ref_rev_parse_rules[i], 2, "%s") + 1;
Jeff King7c2b3022009-04-07 03:14:20 -04001226 }
1227 }
1228
1229 /* bail out if there are no rules */
1230 if (!nr_rules)
Michael Haggertydfefa932011-12-12 06:38:09 +01001231 return xstrdup(refname);
Jeff King7c2b3022009-04-07 03:14:20 -04001232
Michael Haggertydfefa932011-12-12 06:38:09 +01001233 /* buffer for scanf result, at most refname must fit */
1234 short_name = xstrdup(refname);
Jeff King7c2b3022009-04-07 03:14:20 -04001235
1236 /* skip first rule, it will always match */
1237 for (i = nr_rules - 1; i > 0 ; --i) {
1238 int j;
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001239 int rules_to_fail = i;
Jeff King7c2b3022009-04-07 03:14:20 -04001240 int short_name_len;
1241
Michael Haggertydfefa932011-12-12 06:38:09 +01001242 if (1 != sscanf(refname, scanf_fmts[i], short_name))
Jeff King7c2b3022009-04-07 03:14:20 -04001243 continue;
1244
1245 short_name_len = strlen(short_name);
1246
1247 /*
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001248 * in strict mode, all (except the matched one) rules
1249 * must fail to resolve to a valid non-ambiguous ref
1250 */
1251 if (strict)
1252 rules_to_fail = nr_rules;
1253
1254 /*
Jeff King7c2b3022009-04-07 03:14:20 -04001255 * check if the short name resolves to a valid ref,
1256 * but use only rules prior to the matched one
1257 */
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001258 for (j = 0; j < rules_to_fail; j++) {
Jeff King7c2b3022009-04-07 03:14:20 -04001259 const char *rule = ref_rev_parse_rules[j];
Jeff King7c2b3022009-04-07 03:14:20 -04001260
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001261 /* skip matched rule */
1262 if (i == j)
1263 continue;
1264
Jeff King7c2b3022009-04-07 03:14:20 -04001265 /*
1266 * the short name is ambiguous, if it resolves
1267 * (with this previous rule) to a valid ref
1268 * read_ref() returns 0 on success
1269 */
Jeff King6cd4a892017-03-28 15:46:33 -04001270 strbuf_reset(&resolved_buf);
1271 strbuf_addf(&resolved_buf, rule,
1272 short_name_len, short_name);
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001273 if (refs_ref_exists(refs, resolved_buf.buf))
Jeff King7c2b3022009-04-07 03:14:20 -04001274 break;
1275 }
1276
1277 /*
1278 * short name is non-ambiguous if all previous rules
1279 * haven't resolved to a valid ref
1280 */
Jeff King6cd4a892017-03-28 15:46:33 -04001281 if (j == rules_to_fail) {
1282 strbuf_release(&resolved_buf);
Jeff King7c2b3022009-04-07 03:14:20 -04001283 return short_name;
Jeff King6cd4a892017-03-28 15:46:33 -04001284 }
Jeff King7c2b3022009-04-07 03:14:20 -04001285 }
1286
Jeff King6cd4a892017-03-28 15:46:33 -04001287 strbuf_release(&resolved_buf);
Jeff King7c2b3022009-04-07 03:14:20 -04001288 free(short_name);
Michael Haggertydfefa932011-12-12 06:38:09 +01001289 return xstrdup(refname);
Jeff King7c2b3022009-04-07 03:14:20 -04001290}
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001291
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001292char *shorten_unambiguous_ref(const char *refname, int strict)
1293{
1294 return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
1295 refname, strict);
1296}
1297
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001298static struct string_list *hide_refs;
1299
1300int parse_hide_refs_config(const char *var, const char *value, const char *section)
1301{
Jeff Kingad8c7cd2017-02-24 16:08:16 -05001302 const char *key;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001303 if (!strcmp("transfer.hiderefs", var) ||
Jeff Kingad8c7cd2017-02-24 16:08:16 -05001304 (!parse_config_key(var, section, NULL, NULL, &key) &&
1305 !strcmp(key, "hiderefs"))) {
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001306 char *ref;
1307 int len;
1308
1309 if (!value)
1310 return config_error_nonbool(var);
1311 ref = xstrdup(value);
1312 len = strlen(ref);
1313 while (len && ref[len - 1] == '/')
1314 ref[--len] = '\0';
1315 if (!hide_refs) {
René Scharfeca56dad2021-03-13 17:17:22 +01001316 CALLOC_ARRAY(hide_refs, 1);
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001317 hide_refs->strdup_strings = 1;
1318 }
1319 string_list_append(hide_refs, ref);
1320 }
1321 return 0;
1322}
1323
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001324int ref_is_hidden(const char *refname, const char *refname_full)
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001325{
Jeff King2bc31d12015-07-28 16:23:26 -04001326 int i;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001327
1328 if (!hide_refs)
1329 return 0;
Jeff King2bc31d12015-07-28 16:23:26 -04001330 for (i = hide_refs->nr - 1; i >= 0; i--) {
1331 const char *match = hide_refs->items[i].string;
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001332 const char *subject;
Jeff King2bc31d12015-07-28 16:23:26 -04001333 int neg = 0;
Christian Couder7a40a952017-07-22 06:39:12 +02001334 const char *p;
Jeff King2bc31d12015-07-28 16:23:26 -04001335
1336 if (*match == '!') {
1337 neg = 1;
1338 match++;
1339 }
1340
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001341 if (*match == '^') {
1342 subject = refname_full;
1343 match++;
1344 } else {
1345 subject = refname;
1346 }
1347
1348 /* refname can be NULL when namespaces are used. */
Christian Couder7a40a952017-07-22 06:39:12 +02001349 if (subject &&
1350 skip_prefix(subject, match, &p) &&
1351 (!*p || *p == '/'))
Jeff King2bc31d12015-07-28 16:23:26 -04001352 return !neg;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001353 }
1354 return 0;
1355}
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001356
David Turner08451222015-11-10 12:42:40 +01001357const char *find_descendant_ref(const char *dirname,
1358 const struct string_list *extras,
1359 const struct string_list *skip)
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001360{
David Turner08451222015-11-10 12:42:40 +01001361 int pos;
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001362
David Turner08451222015-11-10 12:42:40 +01001363 if (!extras)
1364 return NULL;
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001365
1366 /*
David Turner08451222015-11-10 12:42:40 +01001367 * Look at the place where dirname would be inserted into
1368 * extras. If there is an entry at that position that starts
1369 * with dirname (remember, dirname includes the trailing
1370 * slash) and is not in skip, then we have a conflict.
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001371 */
David Turner08451222015-11-10 12:42:40 +01001372 for (pos = string_list_find_insert_index(extras, dirname, 0);
1373 pos < extras->nr; pos++) {
1374 const char *extra_refname = extras->items[pos].string;
1375
1376 if (!starts_with(extra_refname, dirname))
1377 break;
1378
1379 if (!skip || !string_list_has_string(skip, extra_refname))
1380 return extra_refname;
Michael Haggerty4a32b2e2015-05-11 17:25:15 +02001381 }
David Turner08451222015-11-10 12:42:40 +01001382 return NULL;
1383}
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001384
Nguyễn Thái Ngọc Duy62f0b392017-08-23 19:36:55 +07001385int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turner2bf68ed2016-04-07 15:02:48 -04001386{
1387 struct object_id oid;
1388 int flag;
1389
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +02001390 if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001391 &oid, &flag))
David Turner2bf68ed2016-04-07 15:02:48 -04001392 return fn("HEAD", &oid, flag, cb_data);
1393
1394 return 0;
1395}
1396
1397int head_ref(each_ref_fn fn, void *cb_data)
1398{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001399 return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data);
David Turner2bf68ed2016-04-07 15:02:48 -04001400}
David Turner93770592016-04-07 15:02:49 -04001401
Michael Haggertye121b9c2017-03-20 17:33:08 +01001402struct ref_iterator *refs_ref_iterator_begin(
1403 struct ref_store *refs,
Jeff King9aab9522021-09-24 14:39:44 -04001404 const char *prefix, int trim,
1405 enum do_for_each_ref_flags flags)
Michael Haggertye121b9c2017-03-20 17:33:08 +01001406{
1407 struct ref_iterator *iter;
1408
Jeff King6d751be2021-09-24 14:42:38 -04001409 if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
Jeff King5d1f5b82021-09-24 14:46:37 -04001410 static int ref_paranoia = -1;
1411
Jeff King6d751be2021-09-24 14:42:38 -04001412 if (ref_paranoia < 0)
Jeff King968f12f2021-09-24 14:46:13 -04001413 ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 1);
Jeff King6d751be2021-09-24 14:42:38 -04001414 if (ref_paranoia) {
1415 flags |= DO_FOR_EACH_INCLUDE_BROKEN;
1416 flags |= DO_FOR_EACH_OMIT_DANGLING_SYMREFS;
1417 }
1418 }
Michael Haggerty0a0865b2017-05-22 16:17:52 +02001419
Michael Haggertye121b9c2017-03-20 17:33:08 +01001420 iter = refs->be->iterator_begin(refs, prefix, flags);
Michael Haggertyc7599712017-05-22 16:17:36 +02001421
1422 /*
1423 * `iterator_begin()` already takes care of prefix, but we
1424 * might need to do some trimming:
1425 */
1426 if (trim)
1427 iter = prefix_ref_iterator_begin(iter, "", trim);
Michael Haggertye121b9c2017-03-20 17:33:08 +01001428
Michael Haggerty8738a8a2017-09-13 19:15:55 +02001429 /* Sanity check for subclasses: */
1430 if (!iter->ordered)
1431 BUG("reference iterator is not ordered");
1432
Michael Haggertye121b9c2017-03-20 17:33:08 +01001433 return iter;
1434}
1435
Michael Haggerty4c4de892016-06-18 06:15:16 +02001436/*
1437 * Call fn for each reference in the specified submodule for which the
1438 * refname begins with prefix. If trim is non-zero, then trim that
1439 * many characters off the beginning of each refname before passing
1440 * the refname to fn. flags can be DO_FOR_EACH_INCLUDE_BROKEN to
1441 * include broken references in the iteration. If fn ever returns a
1442 * non-zero value, stop the iteration and return that value;
1443 * otherwise, return 0.
1444 */
Stefan Beller4a6067c2018-08-20 18:24:16 +00001445static int do_for_each_repo_ref(struct repository *r, const char *prefix,
1446 each_repo_ref_fn fn, int trim, int flags,
1447 void *cb_data)
Michael Haggerty4c4de892016-06-18 06:15:16 +02001448{
1449 struct ref_iterator *iter;
Stefan Beller4a6067c2018-08-20 18:24:16 +00001450 struct ref_store *refs = get_main_ref_store(r);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001451
Michael Haggerty00eebe32016-09-04 18:08:11 +02001452 if (!refs)
1453 return 0;
1454
Michael Haggertye121b9c2017-03-20 17:33:08 +01001455 iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001456
Stefan Beller4a6067c2018-08-20 18:24:16 +00001457 return do_for_each_repo_ref_iterator(r, iter, fn, cb_data);
1458}
1459
1460struct do_for_each_ref_help {
1461 each_ref_fn *fn;
1462 void *cb_data;
1463};
1464
1465static int do_for_each_ref_helper(struct repository *r,
1466 const char *refname,
1467 const struct object_id *oid,
1468 int flags,
1469 void *cb_data)
1470{
1471 struct do_for_each_ref_help *hp = cb_data;
1472
1473 return hp->fn(refname, oid, flags, hp->cb_data);
1474}
1475
1476static int do_for_each_ref(struct ref_store *refs, const char *prefix,
Jeff King9aab9522021-09-24 14:39:44 -04001477 each_ref_fn fn, int trim,
1478 enum do_for_each_ref_flags flags, void *cb_data)
Stefan Beller4a6067c2018-08-20 18:24:16 +00001479{
1480 struct ref_iterator *iter;
1481 struct do_for_each_ref_help hp = { fn, cb_data };
1482
1483 if (!refs)
1484 return 0;
1485
1486 iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
1487
1488 return do_for_each_repo_ref_iterator(the_repository, iter,
1489 do_for_each_ref_helper, &hp);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001490}
1491
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001492int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
1493{
1494 return do_for_each_ref(refs, "", fn, 0, 0, cb_data);
1495}
1496
David Turner93770592016-04-07 15:02:49 -04001497int for_each_ref(each_ref_fn fn, void *cb_data)
1498{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001499 return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data);
David Turner93770592016-04-07 15:02:49 -04001500}
1501
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001502int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
1503 each_ref_fn fn, void *cb_data)
1504{
1505 return do_for_each_ref(refs, prefix, fn, strlen(prefix), 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001506}
1507
1508int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
1509{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001510 return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data);
David Turner93770592016-04-07 15:02:49 -04001511}
1512
Jeff King67985e42021-09-24 14:48:48 -04001513int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001514{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001515 return do_for_each_ref(get_main_ref_store(the_repository),
Jeff King67985e42021-09-24 14:48:48 -04001516 prefix, fn, 0, 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001517}
1518
Nguyễn Thái Ngọc Duy073cf632017-08-23 19:36:56 +07001519int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
Jeff King67985e42021-09-24 14:48:48 -04001520 each_ref_fn fn, void *cb_data)
Michael Haggerty03df5672017-06-18 15:39:41 +02001521{
Jeff King67985e42021-09-24 14:48:48 -04001522 return do_for_each_ref(refs, prefix, fn, 0, 0, cb_data);
Michael Haggerty03df5672017-06-18 15:39:41 +02001523}
1524
Stefan Beller212e0f72018-08-20 18:24:19 +00001525int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001526{
Stefan Beller212e0f72018-08-20 18:24:19 +00001527 return do_for_each_repo_ref(r, git_replace_ref_base, fn,
1528 strlen(git_replace_ref_base),
1529 DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
David Turner93770592016-04-07 15:02:49 -04001530}
1531
1532int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
1533{
1534 struct strbuf buf = STRBUF_INIT;
1535 int ret;
1536 strbuf_addf(&buf, "%srefs/", get_git_namespace());
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001537 ret = do_for_each_ref(get_main_ref_store(the_repository),
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001538 buf.buf, fn, 0, 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001539 strbuf_release(&buf);
1540 return ret;
1541}
1542
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001543int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001544{
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001545 return do_for_each_ref(refs, "", fn, 0,
David Turner93770592016-04-07 15:02:49 -04001546 DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
1547}
David Turner2d0663b2016-04-07 15:03:10 -04001548
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001549int for_each_rawref(each_ref_fn fn, void *cb_data)
1550{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001551 return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001552}
1553
Taylor Blau16b19852021-01-20 11:04:21 -05001554static int qsort_strcmp(const void *va, const void *vb)
1555{
1556 const char *a = *(const char **)va;
1557 const char *b = *(const char **)vb;
1558
1559 return strcmp(a, b);
1560}
1561
1562static void find_longest_prefixes_1(struct string_list *out,
1563 struct strbuf *prefix,
1564 const char **patterns, size_t nr)
1565{
1566 size_t i;
1567
1568 for (i = 0; i < nr; i++) {
1569 char c = patterns[i][prefix->len];
1570 if (!c || is_glob_special(c)) {
1571 string_list_append(out, prefix->buf);
1572 return;
1573 }
1574 }
1575
1576 i = 0;
1577 while (i < nr) {
1578 size_t end;
1579
1580 /*
1581 * Set "end" to the index of the element _after_ the last one
1582 * in our group.
1583 */
1584 for (end = i + 1; end < nr; end++) {
1585 if (patterns[i][prefix->len] != patterns[end][prefix->len])
1586 break;
1587 }
1588
1589 strbuf_addch(prefix, patterns[i][prefix->len]);
1590 find_longest_prefixes_1(out, prefix, patterns + i, end - i);
1591 strbuf_setlen(prefix, prefix->len - 1);
1592
1593 i = end;
1594 }
1595}
1596
1597static void find_longest_prefixes(struct string_list *out,
1598 const char **patterns)
1599{
1600 struct strvec sorted = STRVEC_INIT;
1601 struct strbuf prefix = STRBUF_INIT;
1602
1603 strvec_pushv(&sorted, patterns);
1604 QSORT(sorted.v, sorted.nr, qsort_strcmp);
1605
1606 find_longest_prefixes_1(out, &prefix, sorted.v, sorted.nr);
1607
1608 strvec_clear(&sorted);
1609 strbuf_release(&prefix);
1610}
1611
1612int for_each_fullref_in_prefixes(const char *namespace,
1613 const char **patterns,
Jeff King67985e42021-09-24 14:48:48 -04001614 each_ref_fn fn, void *cb_data)
Taylor Blau16b19852021-01-20 11:04:21 -05001615{
1616 struct string_list prefixes = STRING_LIST_INIT_DUP;
1617 struct string_list_item *prefix;
1618 struct strbuf buf = STRBUF_INIT;
1619 int ret = 0, namespace_len;
1620
1621 find_longest_prefixes(&prefixes, patterns);
1622
1623 if (namespace)
1624 strbuf_addstr(&buf, namespace);
1625 namespace_len = buf.len;
1626
1627 for_each_string_list_item(prefix, &prefixes) {
1628 strbuf_addstr(&buf, prefix->string);
Jeff King67985e42021-09-24 14:48:48 -04001629 ret = for_each_fullref_in(buf.buf, fn, cb_data);
Taylor Blau16b19852021-01-20 11:04:21 -05001630 if (ret)
1631 break;
1632 strbuf_setlen(&buf, namespace_len);
1633 }
1634
1635 string_list_clear(&prefixes, 0);
1636 strbuf_release(&buf);
1637 return ret;
1638}
1639
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001640static int refs_read_special_head(struct ref_store *ref_store,
1641 const char *refname, struct object_id *oid,
Han-Wen Nienhuysdf3458e2021-10-16 11:39:10 +02001642 struct strbuf *referent, unsigned int *type,
1643 int *failure_errno)
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001644{
1645 struct strbuf full_path = STRBUF_INIT;
1646 struct strbuf content = STRBUF_INIT;
1647 int result = -1;
1648 strbuf_addf(&full_path, "%s/%s", ref_store->gitdir, refname);
1649
1650 if (strbuf_read_file(&content, full_path.buf, 0) < 0)
1651 goto done;
1652
Han-Wen Nienhuysdf3458e2021-10-16 11:39:10 +02001653 result = parse_loose_ref_contents(content.buf, oid, referent, type,
1654 failure_errno);
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001655
1656done:
1657 strbuf_release(&full_path);
1658 strbuf_release(&content);
1659 return result;
1660}
1661
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001662int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
1663 struct object_id *oid, struct strbuf *referent,
1664 unsigned int *type, int *failure_errno)
Michael Haggerty470be512017-03-20 17:33:07 +01001665{
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001666 assert(failure_errno);
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001667 if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) {
1668 return refs_read_special_head(ref_store, refname, oid, referent,
Han-Wen Nienhuysdf3458e2021-10-16 11:39:10 +02001669 type, failure_errno);
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001670 }
1671
1672 return ref_store->be->read_raw_ref(ref_store, refname, oid, referent,
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001673 type, failure_errno);
Michael Haggerty470be512017-03-20 17:33:07 +01001674}
1675
Patrick Steinhardtcd475b32022-03-01 10:33:46 +01001676int refs_read_symbolic_ref(struct ref_store *ref_store, const char *refname,
1677 struct strbuf *referent)
1678{
Ævar Arnfjörð Bjarmason5b875402022-03-17 18:27:19 +01001679 return ref_store->be->read_symbolic_ref(ref_store, refname, referent);
Patrick Steinhardtcd475b32022-03-01 10:33:46 +01001680}
1681
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001682const char *refs_resolve_ref_unsafe(struct ref_store *refs,
Michael Haggerty3c0cb0c2017-02-09 21:53:52 +01001683 const char *refname,
1684 int resolve_flags,
Ævar Arnfjörð Bjarmasonef181192021-10-16 11:39:08 +02001685 struct object_id *oid,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001686 int *flags)
David Turner2d0663b2016-04-07 15:03:10 -04001687{
1688 static struct strbuf sb_refname = STRBUF_INIT;
René Scharfe54fad662017-09-23 11:41:45 +02001689 struct object_id unused_oid;
David Turner2d0663b2016-04-07 15:03:10 -04001690 int unused_flags;
1691 int symref_count;
1692
brian m. carlson49e61472017-10-15 22:07:09 +00001693 if (!oid)
1694 oid = &unused_oid;
David Turner2d0663b2016-04-07 15:03:10 -04001695 if (!flags)
1696 flags = &unused_flags;
1697
1698 *flags = 0;
1699
1700 if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
1701 if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001702 !refname_is_safe(refname))
David Turner2d0663b2016-04-07 15:03:10 -04001703 return NULL;
David Turner2d0663b2016-04-07 15:03:10 -04001704
1705 /*
1706 * dwim_ref() uses REF_ISBROKEN to distinguish between
1707 * missing refs and refs that were present but invalid,
1708 * to complain about the latter to stderr.
1709 *
1710 * We don't know whether the ref exists, so don't set
1711 * REF_ISBROKEN yet.
1712 */
1713 *flags |= REF_BAD_NAME;
1714 }
1715
1716 for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
1717 unsigned int read_flags = 0;
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001718 int failure_errno;
David Turner2d0663b2016-04-07 15:03:10 -04001719
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001720 if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001721 &read_flags, &failure_errno)) {
David Turner2d0663b2016-04-07 15:03:10 -04001722 *flags |= read_flags;
Jeff Kinga1c1d812017-10-06 10:42:17 -04001723
1724 /* In reading mode, refs must eventually resolve */
1725 if (resolve_flags & RESOLVE_REF_READING)
David Turner2d0663b2016-04-07 15:03:10 -04001726 return NULL;
Jeff Kinga1c1d812017-10-06 10:42:17 -04001727
1728 /*
1729 * Otherwise a missing ref is OK. But the files backend
1730 * may show errors besides ENOENT if there are
1731 * similarly-named refs.
1732 */
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001733 if (failure_errno != ENOENT &&
1734 failure_errno != EISDIR &&
1735 failure_errno != ENOTDIR)
Jeff Kinga1c1d812017-10-06 10:42:17 -04001736 return NULL;
1737
brian m. carlson49e61472017-10-15 22:07:09 +00001738 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001739 if (*flags & REF_BAD_NAME)
1740 *flags |= REF_ISBROKEN;
1741 return refname;
1742 }
1743
1744 *flags |= read_flags;
1745
1746 if (!(read_flags & REF_ISSYMREF)) {
1747 if (*flags & REF_BAD_NAME) {
brian m. carlson49e61472017-10-15 22:07:09 +00001748 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001749 *flags |= REF_ISBROKEN;
1750 }
1751 return refname;
1752 }
1753
1754 refname = sb_refname.buf;
1755 if (resolve_flags & RESOLVE_REF_NO_RECURSE) {
brian m. carlson49e61472017-10-15 22:07:09 +00001756 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001757 return refname;
1758 }
1759 if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
1760 if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001761 !refname_is_safe(refname))
David Turner2d0663b2016-04-07 15:03:10 -04001762 return NULL;
David Turner2d0663b2016-04-07 15:03:10 -04001763
1764 *flags |= REF_ISBROKEN | REF_BAD_NAME;
1765 }
1766 }
1767
David Turner2d0663b2016-04-07 15:03:10 -04001768 return NULL;
1769}
Michael Haggerty00eebe32016-09-04 18:08:11 +02001770
David Turner6fb5acf2016-09-04 18:08:41 +02001771/* backend functions */
1772int refs_init_db(struct strbuf *err)
1773{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001774 struct ref_store *refs = get_main_ref_store(the_repository);
David Turner6fb5acf2016-09-04 18:08:41 +02001775
1776 return refs->be->init_db(refs, err);
1777}
1778
Michael Haggertybd40dcd2016-09-04 18:08:21 +02001779const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
brian m. carlson49e61472017-10-15 22:07:09 +00001780 struct object_id *oid, int *flags)
Michael Haggertybd40dcd2016-09-04 18:08:21 +02001781{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001782 return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001783 resolve_flags, oid, flags);
Michael Haggertybd40dcd2016-09-04 18:08:21 +02001784}
1785
Michael Haggertya8355bb2016-09-04 18:08:24 +02001786int resolve_gitlink_ref(const char *submodule, const char *refname,
brian m. carlsona98e6102017-10-15 22:07:07 +00001787 struct object_id *oid)
Michael Haggerty424dcc72016-09-04 18:08:22 +02001788{
Michael Haggerty424dcc72016-09-04 18:08:22 +02001789 struct ref_store *refs;
1790 int flags;
1791
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07001792 refs = get_submodule_ref_store(submodule);
Michael Haggerty48a84752016-09-04 18:08:23 +02001793
Michael Haggerty424dcc72016-09-04 18:08:22 +02001794 if (!refs)
1795 return -1;
1796
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001797 if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags) ||
1798 is_null_oid(oid))
Michael Haggerty424dcc72016-09-04 18:08:22 +02001799 return -1;
1800 return 0;
1801}
1802
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001803struct ref_store_hash_entry
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001804{
Eric Wonge2b50382019-10-06 23:30:43 +00001805 struct hashmap_entry ent;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001806
1807 struct ref_store *refs;
1808
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001809 /* NUL-terminated identifier of the ref store: */
1810 char name[FLEX_ARRAY];
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001811};
1812
Stefan Beller7663cdc2017-06-30 12:14:05 -07001813static int ref_store_hash_cmp(const void *unused_cmp_data,
Eric Wong939af162019-10-06 23:30:37 +00001814 const struct hashmap_entry *eptr,
1815 const struct hashmap_entry *entry_or_key,
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001816 const void *keydata)
1817{
Eric Wong939af162019-10-06 23:30:37 +00001818 const struct ref_store_hash_entry *e1, *e2;
1819 const char *name;
1820
1821 e1 = container_of(eptr, const struct ref_store_hash_entry, ent);
1822 e2 = container_of(entry_or_key, const struct ref_store_hash_entry, ent);
1823 name = keydata ? keydata : e2->name;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001824
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001825 return strcmp(e1->name, name);
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001826}
1827
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001828static struct ref_store_hash_entry *alloc_ref_store_hash_entry(
1829 const char *name, struct ref_store *refs)
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001830{
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001831 struct ref_store_hash_entry *entry;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001832
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001833 FLEX_ALLOC_STR(entry, name, name);
Eric Wongd22245a2019-10-06 23:30:27 +00001834 hashmap_entry_init(&entry->ent, strhash(name));
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001835 entry->refs = refs;
1836 return entry;
1837}
1838
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001839/* A hashmap of ref_stores, stored by submodule name: */
1840static struct hashmap submodule_ref_stores;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001841
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07001842/* A hashmap of ref_stores, stored by worktree id: */
1843static struct hashmap worktree_ref_stores;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001844
Michael Haggerty00eebe32016-09-04 18:08:11 +02001845/*
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001846 * Look up a ref store by name. If that ref_store hasn't been
1847 * registered yet, return NULL.
Michael Haggerty00eebe32016-09-04 18:08:11 +02001848 */
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001849static struct ref_store *lookup_ref_store_map(struct hashmap *map,
1850 const char *name)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001851{
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001852 struct ref_store_hash_entry *entry;
Eric Wongf23a4652019-10-06 23:30:36 +00001853 unsigned int hash;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001854
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001855 if (!map->tablesize)
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001856 /* It's initialized on demand in register_ref_store(). */
1857 return NULL;
Michael Haggerty620a66b2017-02-10 12:16:11 +01001858
Eric Wongf23a4652019-10-06 23:30:36 +00001859 hash = strhash(name);
1860 entry = hashmap_get_entry_from_hash(map, hash, name,
1861 struct ref_store_hash_entry, ent);
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001862 return entry ? entry->refs : NULL;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001863}
1864
Michael Haggertyc468da42017-02-10 12:16:12 +01001865/*
1866 * Create, record, and return a ref_store instance for the specified
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07001867 * gitdir.
Michael Haggertyc468da42017-02-10 12:16:12 +01001868 */
Jonathan Tan34224e12021-10-08 14:08:14 -07001869static struct ref_store *ref_store_init(struct repository *repo,
1870 const char *gitdir,
Nguyễn Thái Ngọc Duy9e7ec632017-03-26 09:42:32 +07001871 unsigned int flags)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001872{
1873 const char *be_name = "files";
1874 struct ref_storage_be *be = find_ref_storage_backend(be_name);
Michael Haggertyba88add2017-02-10 12:16:14 +01001875 struct ref_store *refs;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001876
1877 if (!be)
Johannes Schindelin033abf92018-05-02 11:38:39 +02001878 BUG("reference backend %s is unknown", be_name);
Michael Haggerty00eebe32016-09-04 18:08:11 +02001879
Jonathan Tan34224e12021-10-08 14:08:14 -07001880 refs = be->init(repo, gitdir, flags);
Michael Haggertyba88add2017-02-10 12:16:14 +01001881 return refs;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001882}
1883
Stefan Beller64a74162018-04-11 17:21:14 -07001884struct ref_store *get_main_ref_store(struct repository *r)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001885{
Jeff King02204612020-04-09 23:04:11 -04001886 if (r->refs_private)
1887 return r->refs_private;
Nguyễn Thái Ngọc Duy24c84072017-03-26 09:42:25 +07001888
Jeff King2dc417a2018-05-18 15:25:53 -07001889 if (!r->gitdir)
1890 BUG("attempting to get main_ref_store outside of repository");
1891
Jonathan Tan34224e12021-10-08 14:08:14 -07001892 r->refs_private = ref_store_init(r, r->gitdir, REF_STORE_ALL_CAPS);
Han-Wen Nienhuys4441f422020-09-09 10:15:08 +00001893 r->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private);
Jeff King02204612020-04-09 23:04:11 -04001894 return r->refs_private;
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07001895}
1896
1897/*
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001898 * Associate a ref store with a name. It is a fatal error to call this
1899 * function twice for the same name.
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07001900 */
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001901static void register_ref_store_map(struct hashmap *map,
1902 const char *type,
1903 struct ref_store *refs,
1904 const char *name)
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07001905{
Eric Wong26b455f2019-10-06 23:30:32 +00001906 struct ref_store_hash_entry *entry;
1907
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001908 if (!map->tablesize)
Stefan Beller7663cdc2017-06-30 12:14:05 -07001909 hashmap_init(map, ref_store_hash_cmp, NULL, 0);
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07001910
Eric Wong26b455f2019-10-06 23:30:32 +00001911 entry = alloc_ref_store_hash_entry(name, refs);
1912 if (hashmap_put(map, &entry->ent))
Johannes Schindelin033abf92018-05-02 11:38:39 +02001913 BUG("%s ref_store '%s' initialized twice", type, name);
Nguyễn Thái Ngọc Duy24c84072017-03-26 09:42:25 +07001914}
1915
Nguyễn Thái Ngọc Duy18d00022017-03-26 09:42:33 +07001916struct ref_store *get_submodule_ref_store(const char *submodule)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001917{
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07001918 struct strbuf submodule_sb = STRBUF_INIT;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001919 struct ref_store *refs;
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07001920 char *to_free = NULL;
1921 size_t len;
Jonathan Tan34224e12021-10-08 14:08:14 -07001922 struct repository *subrepo;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001923
Nguyễn Thái Ngọc Duy82a150f2017-08-23 19:37:03 +07001924 if (!submodule)
1925 return NULL;
1926
Nguyễn Thái Ngọc Duy873ea902017-08-23 19:37:04 +07001927 len = strlen(submodule);
1928 while (len && is_dir_sep(submodule[len - 1]))
1929 len--;
1930 if (!len)
1931 return NULL;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001932
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07001933 if (submodule[len])
1934 /* We need to strip off one or more trailing slashes */
1935 submodule = to_free = xmemdupz(submodule, len);
Michael Haggerty00eebe32016-09-04 18:08:11 +02001936
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001937 refs = lookup_ref_store_map(&submodule_ref_stores, submodule);
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07001938 if (refs)
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07001939 goto done;
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07001940
1941 strbuf_addstr(&submodule_sb, submodule);
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07001942 if (!is_nonbare_repository_dir(&submodule_sb))
1943 goto done;
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07001944
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07001945 if (submodule_to_gitdir(&submodule_sb, submodule))
1946 goto done;
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07001947
Jonathan Tan34224e12021-10-08 14:08:14 -07001948 subrepo = xmalloc(sizeof(*subrepo));
1949 /*
1950 * NEEDSWORK: Make get_submodule_ref_store() work with arbitrary
1951 * superprojects other than the_repository. This probably should be
1952 * done by making it take a struct repository * parameter instead of a
1953 * submodule path.
1954 */
1955 if (repo_submodule_init(subrepo, the_repository, submodule,
1956 null_oid())) {
1957 free(subrepo);
1958 goto done;
1959 }
1960 refs = ref_store_init(subrepo, submodule_sb.buf,
Nguyễn Thái Ngọc Duy9e7ec632017-03-26 09:42:32 +07001961 REF_STORE_READ | REF_STORE_ODB);
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001962 register_ref_store_map(&submodule_ref_stores, "submodule",
1963 refs, submodule);
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07001964
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07001965done:
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07001966 strbuf_release(&submodule_sb);
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07001967 free(to_free);
1968
Michael Haggerty00eebe32016-09-04 18:08:11 +02001969 return refs;
1970}
1971
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07001972struct ref_store *get_worktree_ref_store(const struct worktree *wt)
1973{
1974 struct ref_store *refs;
1975 const char *id;
1976
1977 if (wt->is_current)
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001978 return get_main_ref_store(the_repository);
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07001979
1980 id = wt->id ? wt->id : "/";
1981 refs = lookup_ref_store_map(&worktree_ref_stores, id);
1982 if (refs)
1983 return refs;
1984
1985 if (wt->id)
Jonathan Tan34224e12021-10-08 14:08:14 -07001986 refs = ref_store_init(the_repository,
1987 git_common_path("worktrees/%s", wt->id),
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07001988 REF_STORE_ALL_CAPS);
1989 else
Jonathan Tan34224e12021-10-08 14:08:14 -07001990 refs = ref_store_init(the_repository,
1991 get_git_common_dir(),
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07001992 REF_STORE_ALL_CAPS);
1993
1994 if (refs)
1995 register_ref_store_map(&worktree_ref_stores, "worktree",
1996 refs, id);
1997 return refs;
1998}
1999
Han-Wen Nienhuysf9f7fd32021-12-22 18:11:54 +00002000void base_ref_store_init(struct ref_store *refs, struct repository *repo,
2001 const char *path, const struct ref_storage_be *be)
Michael Haggerty00eebe32016-09-04 18:08:11 +02002002{
Michael Haggerty620a66b2017-02-10 12:16:11 +01002003 refs->be = be;
Han-Wen Nienhuysf9f7fd32021-12-22 18:11:54 +00002004 refs->repo = repo;
2005 refs->gitdir = xstrdup(path);
Michael Haggerty00eebe32016-09-04 18:08:11 +02002006}
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002007
2008/* backend functions */
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002009int refs_pack_refs(struct ref_store *refs, unsigned int flags)
Michael Haggerty82315272016-09-04 18:08:27 +02002010{
Michael Haggerty82315272016-09-04 18:08:27 +02002011 return refs->be->pack_refs(refs, flags);
2012}
2013
Jeff King36a31792021-01-20 14:44:43 -05002014int peel_iterated_oid(const struct object_id *base, struct object_id *peeled)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002015{
Jeff King36a31792021-01-20 14:44:43 -05002016 if (current_ref_iter &&
2017 (current_ref_iter->oid == base ||
2018 oideq(current_ref_iter->oid, base)))
2019 return ref_iterator_peel(current_ref_iter, peeled);
Michael Haggertyba1c0522017-09-25 10:00:14 +02002020
Han-Wen Nienhuys617480d2021-05-19 15:31:28 +00002021 return peel_object(base, peeled) ? -1 : 0;
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002022}
Michael Haggertybd427cf2016-09-04 18:08:29 +02002023
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002024int refs_create_symref(struct ref_store *refs,
2025 const char *ref_target,
2026 const char *refs_heads_master,
2027 const char *logmsg)
2028{
Junio C Hamano523fa692020-07-10 17:19:53 +00002029 char *msg;
2030 int retval;
2031
2032 msg = normalize_reflog_message(logmsg);
2033 retval = refs->be->create_symref(refs, ref_target, refs_heads_master,
2034 msg);
2035 free(msg);
2036 return retval;
Michael Haggertybd427cf2016-09-04 18:08:29 +02002037}
2038
Michael Haggerty284689b2016-09-04 18:08:28 +02002039int create_symref(const char *ref_target, const char *refs_heads_master,
2040 const char *logmsg)
2041{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002042 return refs_create_symref(get_main_ref_store(the_repository), ref_target,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002043 refs_heads_master, logmsg);
Michael Haggerty284689b2016-09-04 18:08:28 +02002044}
2045
Michael Haggerty2ced1052017-05-22 16:17:45 +02002046int ref_update_reject_duplicates(struct string_list *refnames,
2047 struct strbuf *err)
2048{
Michael Haggertya552e502017-05-22 16:17:46 +02002049 size_t i, n = refnames->nr;
Michael Haggerty2ced1052017-05-22 16:17:45 +02002050
2051 assert(err);
2052
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002053 for (i = 1; i < n; i++) {
2054 int cmp = strcmp(refnames->items[i - 1].string,
2055 refnames->items[i].string);
2056
2057 if (!cmp) {
Michael Haggerty2ced1052017-05-22 16:17:45 +02002058 strbuf_addf(err,
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002059 _("multiple updates for ref '%s' not allowed"),
Michael Haggerty2ced1052017-05-22 16:17:45 +02002060 refnames->items[i].string);
2061 return 1;
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002062 } else if (cmp > 0) {
Johannes Schindelin033abf92018-05-02 11:38:39 +02002063 BUG("ref_update_reject_duplicates() received unsorted list");
Michael Haggerty2ced1052017-05-22 16:17:45 +02002064 }
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002065 }
Michael Haggerty2ced1052017-05-22 16:17:45 +02002066 return 0;
2067}
2068
Patrick Steinhardt67541592020-06-19 08:56:14 +02002069static int run_transaction_hook(struct ref_transaction *transaction,
2070 const char *state)
2071{
2072 struct child_process proc = CHILD_PROCESS_INIT;
2073 struct strbuf buf = STRBUF_INIT;
Patrick Steinhardt0a0fbbe2020-08-25 12:35:24 +02002074 const char *hook;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002075 int ret = 0, i;
2076
Patrick Steinhardt0a0fbbe2020-08-25 12:35:24 +02002077 hook = find_hook("reference-transaction");
Patrick Steinhardt67541592020-06-19 08:56:14 +02002078 if (!hook)
Patrick Steinhardt67541592020-06-19 08:56:14 +02002079 return ret;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002080
Jeff Kingc972bf42020-07-28 16:25:12 -04002081 strvec_pushl(&proc.args, hook, state, NULL);
Patrick Steinhardt67541592020-06-19 08:56:14 +02002082 proc.in = -1;
2083 proc.stdout_to_stderr = 1;
2084 proc.trace2_hook_name = "reference-transaction";
2085
2086 ret = start_command(&proc);
2087 if (ret)
2088 return ret;
2089
2090 sigchain_push(SIGPIPE, SIG_IGN);
2091
2092 for (i = 0; i < transaction->nr; i++) {
2093 struct ref_update *update = transaction->updates[i];
2094
2095 strbuf_reset(&buf);
2096 strbuf_addf(&buf, "%s %s %s\n",
2097 oid_to_hex(&update->old_oid),
2098 oid_to_hex(&update->new_oid),
2099 update->refname);
2100
2101 if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
Ævar Arnfjörð Bjarmason4755d7d2021-10-16 11:39:25 +02002102 if (errno != EPIPE) {
2103 /* Don't leak errno outside this API */
2104 errno = 0;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002105 ret = -1;
Ævar Arnfjörð Bjarmason4755d7d2021-10-16 11:39:25 +02002106 }
Patrick Steinhardt67541592020-06-19 08:56:14 +02002107 break;
2108 }
2109 }
2110
2111 close(proc.in);
2112 sigchain_pop(SIGPIPE);
2113 strbuf_release(&buf);
2114
2115 ret |= finish_command(&proc);
2116 return ret;
2117}
2118
Michael Haggerty30173b82017-05-22 16:17:44 +02002119int ref_transaction_prepare(struct ref_transaction *transaction,
2120 struct strbuf *err)
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002121{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07002122 struct ref_store *refs = transaction->ref_store;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002123 int ret;
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002124
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002125 switch (transaction->state) {
2126 case REF_TRANSACTION_OPEN:
2127 /* Good. */
2128 break;
Michael Haggerty30173b82017-05-22 16:17:44 +02002129 case REF_TRANSACTION_PREPARED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002130 BUG("prepare called twice on reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002131 break;
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002132 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002133 BUG("prepare called on a closed reference transaction");
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002134 break;
2135 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002136 BUG("unexpected reference transaction state");
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002137 break;
2138 }
2139
Neeraj Singhecd81df2021-12-06 22:05:05 +00002140 if (refs->repo->objects->odb->disable_ref_updates) {
Jeff Kingd8f44812017-04-10 18:14:12 -04002141 strbuf_addstr(err,
2142 _("ref updates forbidden inside quarantine environment"));
2143 return -1;
2144 }
2145
Patrick Steinhardt67541592020-06-19 08:56:14 +02002146 ret = refs->be->transaction_prepare(refs, transaction, err);
2147 if (ret)
2148 return ret;
2149
2150 ret = run_transaction_hook(transaction, "prepared");
2151 if (ret) {
2152 ref_transaction_abort(transaction, err);
2153 die(_("ref updates aborted by hook"));
2154 }
2155
2156 return 0;
Michael Haggerty30173b82017-05-22 16:17:44 +02002157}
2158
2159int ref_transaction_abort(struct ref_transaction *transaction,
2160 struct strbuf *err)
2161{
2162 struct ref_store *refs = transaction->ref_store;
2163 int ret = 0;
2164
2165 switch (transaction->state) {
2166 case REF_TRANSACTION_OPEN:
2167 /* No need to abort explicitly. */
2168 break;
2169 case REF_TRANSACTION_PREPARED:
2170 ret = refs->be->transaction_abort(refs, transaction, err);
2171 break;
2172 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002173 BUG("abort called on a closed reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002174 break;
2175 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002176 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02002177 break;
2178 }
2179
Patrick Steinhardt67541592020-06-19 08:56:14 +02002180 run_transaction_hook(transaction, "aborted");
2181
Michael Haggerty30173b82017-05-22 16:17:44 +02002182 ref_transaction_free(transaction);
2183 return ret;
2184}
2185
2186int ref_transaction_commit(struct ref_transaction *transaction,
2187 struct strbuf *err)
2188{
2189 struct ref_store *refs = transaction->ref_store;
2190 int ret;
2191
2192 switch (transaction->state) {
2193 case REF_TRANSACTION_OPEN:
2194 /* Need to prepare first. */
2195 ret = ref_transaction_prepare(transaction, err);
2196 if (ret)
2197 return ret;
2198 break;
2199 case REF_TRANSACTION_PREPARED:
2200 /* Fall through to finish. */
2201 break;
2202 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002203 BUG("commit called on a closed reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002204 break;
2205 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002206 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02002207 break;
2208 }
2209
Patrick Steinhardt67541592020-06-19 08:56:14 +02002210 ret = refs->be->transaction_finish(refs, transaction, err);
2211 if (!ret)
2212 run_transaction_hook(transaction, "committed");
2213 return ret;
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002214}
Michael Haggerty62665822016-09-04 18:08:26 +02002215
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002216int refs_verify_refname_available(struct ref_store *refs,
2217 const char *refname,
Michael Haggertyb05855b2017-04-16 08:41:26 +02002218 const struct string_list *extras,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002219 const struct string_list *skip,
2220 struct strbuf *err)
Michael Haggerty62665822016-09-04 18:08:26 +02002221{
Michael Haggertyb05855b2017-04-16 08:41:26 +02002222 const char *slash;
2223 const char *extra_refname;
2224 struct strbuf dirname = STRBUF_INIT;
2225 struct strbuf referent = STRBUF_INIT;
2226 struct object_id oid;
2227 unsigned int type;
2228 struct ref_iterator *iter;
2229 int ok;
2230 int ret = -1;
2231
2232 /*
2233 * For the sake of comments in this function, suppose that
2234 * refname is "refs/foo/bar".
2235 */
2236
2237 assert(err);
2238
2239 strbuf_grow(&dirname, strlen(refname) + 1);
2240 for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02002241 /*
2242 * Just saying "Is a directory" when we e.g. can't
2243 * lock some multi-level ref isn't very informative,
2244 * the user won't be told *what* is a directory, so
2245 * let's not use strerror() below.
2246 */
2247 int ignore_errno;
Michael Haggertyb05855b2017-04-16 08:41:26 +02002248 /* Expand dirname to the new prefix, not including the trailing slash: */
2249 strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
2250
2251 /*
2252 * We are still at a leading dir of the refname (e.g.,
2253 * "refs/foo"; if there is a reference with that name,
2254 * it is a conflict, *unless* it is in skip.
2255 */
2256 if (skip && string_list_has_string(skip, dirname.buf))
2257 continue;
2258
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02002259 if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent,
2260 &type, &ignore_errno)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002261 strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002262 dirname.buf, refname);
2263 goto cleanup;
2264 }
2265
2266 if (extras && string_list_has_string(extras, dirname.buf)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002267 strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002268 refname, dirname.buf);
2269 goto cleanup;
2270 }
2271 }
2272
2273 /*
2274 * We are at the leaf of our refname (e.g., "refs/foo/bar").
2275 * There is no point in searching for a reference with that
2276 * name, because a refname isn't considered to conflict with
2277 * itself. But we still need to check for references whose
2278 * names are in the "refs/foo/bar/" namespace, because they
2279 * *do* conflict.
2280 */
2281 strbuf_addstr(&dirname, refname + dirname.len);
2282 strbuf_addch(&dirname, '/');
2283
2284 iter = refs_ref_iterator_begin(refs, dirname.buf, 0,
2285 DO_FOR_EACH_INCLUDE_BROKEN);
2286 while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
2287 if (skip &&
2288 string_list_has_string(skip, iter->refname))
2289 continue;
2290
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002291 strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002292 iter->refname, refname);
2293 ref_iterator_abort(iter);
2294 goto cleanup;
2295 }
2296
2297 if (ok != ITER_DONE)
Johannes Schindelin033abf92018-05-02 11:38:39 +02002298 BUG("error while iterating over references");
Michael Haggertyb05855b2017-04-16 08:41:26 +02002299
2300 extra_refname = find_descendant_ref(dirname.buf, extras, skip);
2301 if (extra_refname)
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002302 strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002303 refname, extra_refname);
2304 else
2305 ret = 0;
2306
2307cleanup:
2308 strbuf_release(&referent);
2309 strbuf_release(&dirname);
2310 return ret;
Michael Haggerty62665822016-09-04 18:08:26 +02002311}
David Turnere3688bd2016-09-04 18:08:38 +02002312
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002313int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turnere3688bd2016-09-04 18:08:38 +02002314{
David Turnere3688bd2016-09-04 18:08:38 +02002315 struct ref_iterator *iter;
Stefan Beller4a6067c2018-08-20 18:24:16 +00002316 struct do_for_each_ref_help hp = { fn, cb_data };
David Turnere3688bd2016-09-04 18:08:38 +02002317
2318 iter = refs->be->reflog_iterator_begin(refs);
2319
Stefan Beller4a6067c2018-08-20 18:24:16 +00002320 return do_for_each_repo_ref_iterator(the_repository, iter,
2321 do_for_each_ref_helper, &hp);
David Turnere3688bd2016-09-04 18:08:38 +02002322}
2323
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002324int for_each_reflog(each_ref_fn fn, void *cb_data)
2325{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002326 return refs_for_each_reflog(get_main_ref_store(the_repository), fn, cb_data);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002327}
2328
2329int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
2330 const char *refname,
2331 each_reflog_ent_fn fn,
2332 void *cb_data)
2333{
2334 return refs->be->for_each_reflog_ent_reverse(refs, refname,
2335 fn, cb_data);
2336}
2337
David Turnere3688bd2016-09-04 18:08:38 +02002338int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
2339 void *cb_data)
2340{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002341 return refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository),
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002342 refname, fn, cb_data);
2343}
David Turnere3688bd2016-09-04 18:08:38 +02002344
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002345int refs_for_each_reflog_ent(struct ref_store *refs, const char *refname,
2346 each_reflog_ent_fn fn, void *cb_data)
2347{
2348 return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002349}
2350
2351int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
2352 void *cb_data)
2353{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002354 return refs_for_each_reflog_ent(get_main_ref_store(the_repository), refname,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002355 fn, cb_data);
2356}
David Turnere3688bd2016-09-04 18:08:38 +02002357
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002358int refs_reflog_exists(struct ref_store *refs, const char *refname)
2359{
2360 return refs->be->reflog_exists(refs, refname);
David Turnere3688bd2016-09-04 18:08:38 +02002361}
2362
2363int reflog_exists(const char *refname)
2364{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002365 return refs_reflog_exists(get_main_ref_store(the_repository), refname);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002366}
David Turnere3688bd2016-09-04 18:08:38 +02002367
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002368int refs_create_reflog(struct ref_store *refs, const char *refname,
David Turnere3688bd2016-09-04 18:08:38 +02002369 struct strbuf *err)
2370{
Han-Wen Nienhuys7b089122021-11-22 14:19:08 +00002371 return refs->be->create_reflog(refs, refname, err);
2372}
2373
2374int safe_create_reflog(const char *refname, struct strbuf *err)
2375{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002376 return refs_create_reflog(get_main_ref_store(the_repository), refname,
Han-Wen Nienhuys7b089122021-11-22 14:19:08 +00002377 err);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002378}
David Turnere3688bd2016-09-04 18:08:38 +02002379
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002380int refs_delete_reflog(struct ref_store *refs, const char *refname)
2381{
2382 return refs->be->delete_reflog(refs, refname);
David Turnere3688bd2016-09-04 18:08:38 +02002383}
2384
2385int delete_reflog(const char *refname)
2386{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002387 return refs_delete_reflog(get_main_ref_store(the_repository), refname);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002388}
David Turnere3688bd2016-09-04 18:08:38 +02002389
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002390int refs_reflog_expire(struct ref_store *refs,
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002391 const char *refname,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002392 unsigned int flags,
2393 reflog_expiry_prepare_fn prepare_fn,
2394 reflog_expiry_should_prune_fn should_prune_fn,
2395 reflog_expiry_cleanup_fn cleanup_fn,
2396 void *policy_cb_data)
2397{
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002398 return refs->be->reflog_expire(refs, refname, flags,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002399 prepare_fn, should_prune_fn,
2400 cleanup_fn, policy_cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002401}
2402
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002403int reflog_expire(const char *refname,
David Turnere3688bd2016-09-04 18:08:38 +02002404 unsigned int flags,
2405 reflog_expiry_prepare_fn prepare_fn,
2406 reflog_expiry_should_prune_fn should_prune_fn,
2407 reflog_expiry_cleanup_fn cleanup_fn,
2408 void *policy_cb_data)
2409{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002410 return refs_reflog_expire(get_main_ref_store(the_repository),
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002411 refname, flags,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002412 prepare_fn, should_prune_fn,
2413 cleanup_fn, policy_cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002414}
David Turnerfc681462016-09-04 18:08:39 +02002415
2416int initial_ref_transaction_commit(struct ref_transaction *transaction,
2417 struct strbuf *err)
2418{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07002419 struct ref_store *refs = transaction->ref_store;
David Turnerfc681462016-09-04 18:08:39 +02002420
2421 return refs->be->initial_transaction_commit(refs, transaction, err);
2422}
David Turnera27dcf82016-09-04 18:08:40 +02002423
Patrick Steinhardt4f2ba2d2022-02-17 14:04:32 +01002424void ref_transaction_for_each_queued_update(struct ref_transaction *transaction,
2425 ref_transaction_for_each_queued_update_fn cb,
2426 void *cb_data)
2427{
2428 int i;
2429
2430 for (i = 0; i < transaction->nr; i++) {
2431 struct ref_update *update = transaction->updates[i];
2432
2433 cb(update->refname,
2434 (update->flags & REF_HAVE_OLD) ? &update->old_oid : NULL,
2435 (update->flags & REF_HAVE_NEW) ? &update->new_oid : NULL,
2436 cb_data);
2437 }
2438}
2439
Junio C Hamano523fa692020-07-10 17:19:53 +00002440int refs_delete_refs(struct ref_store *refs, const char *logmsg,
Michael Haggerty64da4192017-05-22 16:17:38 +02002441 struct string_list *refnames, unsigned int flags)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002442{
Junio C Hamano523fa692020-07-10 17:19:53 +00002443 char *msg;
2444 int retval;
2445
2446 msg = normalize_reflog_message(logmsg);
2447 retval = refs->be->delete_refs(refs, msg, refnames, flags);
2448 free(msg);
2449 return retval;
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002450}
2451
Michael Haggerty64da4192017-05-22 16:17:38 +02002452int delete_refs(const char *msg, struct string_list *refnames,
2453 unsigned int flags)
David Turnera27dcf82016-09-04 18:08:40 +02002454{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002455 return refs_delete_refs(get_main_ref_store(the_repository), msg, refnames, flags);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002456}
David Turnera27dcf82016-09-04 18:08:40 +02002457
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002458int refs_rename_ref(struct ref_store *refs, const char *oldref,
2459 const char *newref, const char *logmsg)
2460{
Junio C Hamano523fa692020-07-10 17:19:53 +00002461 char *msg;
2462 int retval;
2463
2464 msg = normalize_reflog_message(logmsg);
2465 retval = refs->be->rename_ref(refs, oldref, newref, msg);
2466 free(msg);
2467 return retval;
David Turnera27dcf82016-09-04 18:08:40 +02002468}
David Turner9b6b40d2016-09-04 18:08:42 +02002469
2470int rename_ref(const char *oldref, const char *newref, const char *logmsg)
2471{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002472 return refs_rename_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
David Turner9b6b40d2016-09-04 18:08:42 +02002473}
Sahil Dua52d59cc2017-06-18 23:19:16 +02002474
2475int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
2476 const char *newref, const char *logmsg)
2477{
Junio C Hamano523fa692020-07-10 17:19:53 +00002478 char *msg;
2479 int retval;
2480
2481 msg = normalize_reflog_message(logmsg);
2482 retval = refs->be->copy_ref(refs, oldref, newref, msg);
2483 free(msg);
2484 return retval;
Sahil Dua52d59cc2017-06-18 23:19:16 +02002485}
2486
2487int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)
2488{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002489 return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
Sahil Dua52d59cc2017-06-18 23:19:16 +02002490}