blob: 55d2e0b2cb9e959443e98eb329fdf97eff9073a9 [file] [log] [blame]
Michael Haggerty7bd9bcf2015-11-09 14:34:01 +01001/*
2 * The backend-independent part of the reference module.
3 */
4
Elijah Newrene93fc5d2023-04-11 00:41:50 -07005#include "git-compat-util.h"
Elijah Newren6c6ddf92023-04-11 03:00:39 +00006#include "advice.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07007#include "config.h"
Elijah Newren32a8f512023-03-21 06:26:03 +00008#include "environment.h"
Michael Haggerty7d4558c2017-02-10 12:16:15 +01009#include "hashmap.h"
Elijah Newrenf394e092023-03-21 06:25:54 +000010#include "gettext.h"
Elijah Newren41771fa2023-02-24 00:09:27 +000011#include "hex.h"
Michael Haggerty697cc8e2014-10-01 12:28:42 +020012#include "lockfile.h"
Michael Haggertyb05855b2017-04-16 08:41:26 +020013#include "iterator.h"
Junio C Hamano85023572006-12-19 14:34:12 -080014#include "refs.h"
Michael Haggerty4cb77002015-11-10 12:42:36 +010015#include "refs/refs-internal.h"
Patrick Steinhardt67541592020-06-19 08:56:14 +020016#include "run-command.h"
Ævar Arnfjörð Bjarmason5e3aba32021-09-26 21:03:26 +020017#include "hook.h"
Elijah Newrendabab1d2023-04-11 00:41:49 -070018#include "object-name.h"
Elijah Newrena034e912023-05-16 06:34:06 +000019#include "object-store-ll.h"
Junio C Hamanocf0adba2006-11-19 13:22:44 -080020#include "object.h"
Elijah Newrenc3399322023-05-16 06:33:59 +000021#include "path.h"
Junio C Hamanocf0adba2006-11-19 13:22:44 -080022#include "tag.h"
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +070023#include "submodule.h"
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +070024#include "worktree.h"
Jeff Kingdbbcd442020-07-28 16:23:39 -040025#include "strvec.h"
Stefan Beller23a3f0c2018-04-11 17:21:09 -070026#include "repository.h"
Elijah Newrene38da482023-03-21 06:26:05 +000027#include "setup.h"
Patrick Steinhardt67541592020-06-19 08:56:14 +020028#include "sigchain.h"
Ævar Arnfjörð Bjarmason88c7b4c2022-02-16 09:14:02 +010029#include "date.h"
Derrick Stoleeb9342b32022-08-05 17:58:36 +000030#include "commit.h"
Elijah Newrendd77d582023-05-16 06:34:03 +000031#include "wildmatch.h"
Stefan Beller3581d792014-12-12 09:57:02 +010032
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020033/*
Ronnie Sahlberg3dce4442016-09-04 18:08:10 +020034 * List of all available backends
35 */
Patrick Steinhardt0fcc2852023-12-29 08:26:34 +010036static const struct ref_storage_be *refs_backends[] = {
37 [REF_STORAGE_FORMAT_FILES] = &refs_be_files,
Patrick Steinhardt57db2a02024-02-07 08:20:31 +010038 [REF_STORAGE_FORMAT_REFTABLE] = &refs_be_reftable,
Patrick Steinhardt0fcc2852023-12-29 08:26:34 +010039};
Ronnie Sahlberg3dce4442016-09-04 18:08:10 +020040
Patrick Steinhardt0fcc2852023-12-29 08:26:34 +010041static const struct ref_storage_be *find_ref_storage_backend(unsigned int ref_storage_format)
Ronnie Sahlberg3dce4442016-09-04 18:08:10 +020042{
Patrick Steinhardt0fcc2852023-12-29 08:26:34 +010043 if (ref_storage_format < ARRAY_SIZE(refs_backends))
44 return refs_backends[ref_storage_format];
Ronnie Sahlberg3dce4442016-09-04 18:08:10 +020045 return NULL;
46}
47
Patrick Steinhardt0fcc2852023-12-29 08:26:34 +010048unsigned int ref_storage_format_by_name(const char *name)
49{
50 for (unsigned int i = 0; i < ARRAY_SIZE(refs_backends); i++)
51 if (refs_backends[i] && !strcmp(refs_backends[i]->name, name))
52 return i;
53 return REF_STORAGE_FORMAT_UNKNOWN;
54}
55
56const char *ref_storage_format_to_name(unsigned int ref_storage_format)
57{
58 const struct ref_storage_be *be = find_ref_storage_backend(ref_storage_format);
59 if (!be)
60 return "unknown";
61 return be->name;
62}
63
Ronnie Sahlberg3dce4442016-09-04 18:08:10 +020064/*
David Turnerdde8a902014-06-03 23:38:10 -040065 * How to handle various characters in refnames:
66 * 0: An acceptable character for refs
Junio C Hamano5e650222014-07-28 10:41:53 -070067 * 1: End-of-component
68 * 2: ., look for a preceding . to reject .. in refs
69 * 3: {, look for a preceding @ to reject @{ in refs
Jacob Keller53a85552015-07-22 14:05:32 -070070 * 4: A bad character: ASCII control characters, and
Jacob Kellercd377f42015-07-22 14:05:33 -070071 * ":", "?", "[", "\", "^", "~", SP, or TAB
72 * 5: *, reject unless REFNAME_REFSPEC_PATTERN is set
David Turnerdde8a902014-06-03 23:38:10 -040073 */
74static unsigned char refname_disposition[256] = {
Junio C Hamano5e650222014-07-28 10:41:53 -070075 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
76 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
Jacob Kellercd377f42015-07-22 14:05:33 -070077 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 1,
Junio C Hamano5e650222014-07-28 10:41:53 -070078 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,
David Turnerdde8a902014-06-03 23:38:10 -040079 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Junio C Hamano5e650222014-07-28 10:41:53 -070080 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
David Turnerdde8a902014-06-03 23:38:10 -040083};
84
Derrick Stoleeb9342b32022-08-05 17:58:36 +000085struct ref_namespace_info ref_namespace[] = {
86 [NAMESPACE_HEAD] = {
87 .ref = "HEAD",
88 .decoration = DECORATION_REF_HEAD,
89 .exact = 1,
90 },
91 [NAMESPACE_BRANCHES] = {
92 .ref = "refs/heads/",
93 .decoration = DECORATION_REF_LOCAL,
94 },
95 [NAMESPACE_TAGS] = {
96 .ref = "refs/tags/",
97 .decoration = DECORATION_REF_TAG,
98 },
99 [NAMESPACE_REMOTE_REFS] = {
100 /*
101 * The default refspec for new remotes copies refs from
102 * refs/heads/ on the remote into refs/remotes/<remote>/.
103 * As such, "refs/remotes/" has special handling.
104 */
105 .ref = "refs/remotes/",
106 .decoration = DECORATION_REF_REMOTE,
107 },
108 [NAMESPACE_STASH] = {
109 /*
110 * The single ref "refs/stash" stores the latest stash.
111 * Older stashes can be found in the reflog.
112 */
113 .ref = "refs/stash",
114 .exact = 1,
115 .decoration = DECORATION_REF_STASH,
116 },
117 [NAMESPACE_REPLACE] = {
118 /*
119 * This namespace allows Git to act as if one object ID
120 * points to the content of another. Unlike the other
121 * ref namespaces, this one can be changed by the
122 * GIT_REPLACE_REF_BASE environment variable. This
123 * .namespace value will be overwritten in setup_git_env().
124 */
125 .ref = "refs/replace/",
126 .decoration = DECORATION_GRAFTED,
127 },
128 [NAMESPACE_NOTES] = {
129 /*
130 * The refs/notes/commit ref points to the tip of a
131 * parallel commit history that adds metadata to commits
132 * in the normal history. This ref can be overwritten
133 * by the core.notesRef config variable or the
134 * GIT_NOTES_REFS environment variable.
135 */
136 .ref = "refs/notes/commit",
137 .exact = 1,
138 },
139 [NAMESPACE_PREFETCH] = {
140 /*
141 * Prefetch refs are written by the background 'fetch'
142 * maintenance task. It allows faster foreground fetches
143 * by advertising these previously-downloaded tips without
144 * updating refs/remotes/ without user intervention.
145 */
146 .ref = "refs/prefetch/",
147 },
148 [NAMESPACE_REWRITTEN] = {
149 /*
150 * Rewritten refs are used by the 'label' command in the
151 * sequencer. These are particularly useful during an
152 * interactive rebase that uses the 'merge' command.
153 */
154 .ref = "refs/rewritten/",
155 },
156};
157
158void update_ref_namespace(enum ref_namespace namespace, char *ref)
159{
160 struct ref_namespace_info *info = &ref_namespace[namespace];
161 if (info->ref_updated)
162 free(info->ref);
163 info->ref = ref;
164 info->ref_updated = 1;
165}
166
David Turnerdde8a902014-06-03 23:38:10 -0400167/*
168 * Try to read one refname component from the front of refname.
169 * Return the length of the component found, or -1 if the component is
170 * not legal. It is legal if it is something reasonable to have under
171 * ".git/refs/"; We do not like it if:
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200172 *
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700173 * - it begins with ".", or
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200174 * - it has double dots "..", or
Jacob Keller53a85552015-07-22 14:05:32 -0700175 * - it has ASCII control characters, or
Jacob Kellercd377f42015-07-22 14:05:33 -0700176 * - it has ":", "?", "[", "\", "^", "~", SP, or TAB anywhere, or
177 * - it has "*" anywhere unless REFNAME_REFSPEC_PATTERN is set, or
Jacob Keller53a85552015-07-22 14:05:32 -0700178 * - it ends with a "/", or
179 * - it ends with ".lock", or
180 * - it contains a "@{" portion
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700181 *
182 * When sanitized is not NULL, instead of rejecting the input refname
183 * as an error, try to come up with a usable replacement for the input
184 * refname in it.
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200185 */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700186static int check_refname_component(const char *refname, int *flags,
187 struct strbuf *sanitized)
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200188{
189 const char *cp;
190 char last = '\0';
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700191 size_t component_start = 0; /* garbage - not a reasonable initial value */
192
193 if (sanitized)
194 component_start = sanitized->len;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200195
196 for (cp = refname; ; cp++) {
David Turnerdde8a902014-06-03 23:38:10 -0400197 int ch = *cp & 255;
198 unsigned char disp = refname_disposition[ch];
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700199
200 if (sanitized && disp != 1)
201 strbuf_addch(sanitized, ch);
202
David Turnerdde8a902014-06-03 23:38:10 -0400203 switch (disp) {
Junio C Hamano5e650222014-07-28 10:41:53 -0700204 case 1:
David Turnerdde8a902014-06-03 23:38:10 -0400205 goto out;
Junio C Hamano5e650222014-07-28 10:41:53 -0700206 case 2:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700207 if (last == '.') { /* Refname contains "..". */
208 if (sanitized)
209 /* collapse ".." to single "." */
210 strbuf_setlen(sanitized, sanitized->len - 1);
211 else
212 return -1;
213 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200214 break;
Junio C Hamano5e650222014-07-28 10:41:53 -0700215 case 3:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700216 if (last == '@') { /* Refname contains "@{". */
217 if (sanitized)
218 sanitized->buf[sanitized->len-1] = '-';
219 else
220 return -1;
221 }
David Turnerdde8a902014-06-03 23:38:10 -0400222 break;
Junio C Hamano5e650222014-07-28 10:41:53 -0700223 case 4:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700224 /* forbidden char */
225 if (sanitized)
226 sanitized->buf[sanitized->len-1] = '-';
227 else
228 return -1;
229 break;
Jacob Kellercd377f42015-07-22 14:05:33 -0700230 case 5:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700231 if (!(*flags & REFNAME_REFSPEC_PATTERN)) {
232 /* refspec can't be a pattern */
233 if (sanitized)
234 sanitized->buf[sanitized->len-1] = '-';
235 else
236 return -1;
237 }
Jacob Kellercd377f42015-07-22 14:05:33 -0700238
239 /*
240 * Unset the pattern flag so that we only accept
241 * a single asterisk for one side of refspec.
242 */
243 *flags &= ~ REFNAME_REFSPEC_PATTERN;
244 break;
David Turnerdde8a902014-06-03 23:38:10 -0400245 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200246 last = ch;
247 }
David Turnerdde8a902014-06-03 23:38:10 -0400248out:
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200249 if (cp == refname)
Michael Haggertydac529e2012-04-10 07:30:22 +0200250 return 0; /* Component has zero length. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700251
252 if (refname[0] == '.') { /* Component starts with '.'. */
253 if (sanitized)
254 sanitized->buf[component_start] = '-';
255 else
256 return -1;
257 }
Michael Haggerty7108ad22014-10-01 12:28:15 +0200258 if (cp - refname >= LOCK_SUFFIX_LEN &&
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700259 !memcmp(cp - LOCK_SUFFIX_LEN, LOCK_SUFFIX, LOCK_SUFFIX_LEN)) {
260 if (!sanitized)
261 return -1;
262 /* Refname ends with ".lock". */
263 while (strbuf_strip_suffix(sanitized, LOCK_SUFFIX)) {
264 /* try again in case we have .lock.lock */
265 }
266 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200267 return cp - refname;
268}
269
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700270static int check_or_sanitize_refname(const char *refname, int flags,
271 struct strbuf *sanitized)
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200272{
273 int component_len, component_count = 0;
274
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700275 if (!strcmp(refname, "@")) {
Felipe Contreras9ba89f42013-09-02 01:34:30 -0500276 /* Refname is a single character '@'. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700277 if (sanitized)
278 strbuf_addch(sanitized, '-');
279 else
280 return -1;
281 }
Felipe Contreras9ba89f42013-09-02 01:34:30 -0500282
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200283 while (1) {
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700284 if (sanitized && sanitized->len)
285 strbuf_complete(sanitized, '/');
286
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200287 /* We are at the start of a path component. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700288 component_len = check_refname_component(refname, &flags,
289 sanitized);
290 if (sanitized && component_len == 0)
291 ; /* OK, omit empty component */
292 else if (component_len <= 0)
Jacob Kellercd377f42015-07-22 14:05:33 -0700293 return -1;
294
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200295 component_count++;
296 if (refname[component_len] == '\0')
297 break;
298 /* Skip to next component. */
299 refname += component_len + 1;
300 }
301
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700302 if (refname[component_len - 1] == '.') {
303 /* Refname ends with '.'. */
304 if (sanitized)
305 ; /* omit ending dot */
306 else
307 return -1;
308 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200309 if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
310 return -1; /* Refname has only one component. */
311 return 0;
312}
313
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700314int check_refname_format(const char *refname, int flags)
315{
316 return check_or_sanitize_refname(refname, flags, NULL);
317}
318
319void sanitize_refname_component(const char *refname, struct strbuf *out)
320{
321 if (check_or_sanitize_refname(refname, REFNAME_ALLOW_ONELEVEL, out))
322 BUG("sanitizing refname '%s' check returned error", refname);
323}
324
Michael Haggerty4cb77002015-11-10 12:42:36 +0100325int refname_is_safe(const char *refname)
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700326{
Michael Haggerty39950fe2016-04-27 12:39:11 +0200327 const char *rest;
328
329 if (skip_prefix(refname, "refs/", &rest)) {
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700330 char *buf;
331 int result;
Michael Haggertye40f3552016-04-27 12:40:39 +0200332 size_t restlen = strlen(rest);
333
334 /* rest must not be empty, or start or end with "/" */
335 if (!restlen || *rest == '/' || rest[restlen - 1] == '/')
336 return 0;
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700337
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700338 /*
339 * Does the refname try to escape refs/?
340 * For example: refs/foo/../bar is safe but refs/foo/../../bar
341 * is not.
342 */
Michael Haggertye40f3552016-04-27 12:40:39 +0200343 buf = xmallocz(restlen);
344 result = !normalize_path_copy(buf, rest) && !strcmp(buf, rest);
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700345 free(buf);
346 return result;
347 }
Michael Haggerty35db25c2016-04-27 12:42:27 +0200348
349 do {
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700350 if (!isupper(*refname) && *refname != '_')
351 return 0;
352 refname++;
Michael Haggerty35db25c2016-04-27 12:42:27 +0200353 } while (*refname);
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700354 return 1;
355}
356
Michael Haggerty67be7c52017-06-23 09:01:37 +0200357/*
358 * Return true if refname, which has the specified oid and flags, can
359 * be resolved to an object in the database. If the referred-to object
360 * does not exist, emit a warning and return false.
361 */
362int ref_resolves_to_object(const char *refname,
Jonathan Tan9bc45a22021-10-08 14:08:15 -0700363 struct repository *repo,
Michael Haggerty67be7c52017-06-23 09:01:37 +0200364 const struct object_id *oid,
365 unsigned int flags)
366{
367 if (flags & REF_ISBROKEN)
368 return 0;
Jonathan Tan9bc45a22021-10-08 14:08:15 -0700369 if (!repo_has_object_file(repo, oid)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200370 error(_("%s does not point to a valid object!"), refname);
Michael Haggerty67be7c52017-06-23 09:01:37 +0200371 return 0;
372 }
373 return 1;
374}
375
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700376char *refs_resolve_refdup(struct ref_store *refs,
377 const char *refname, int resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000378 struct object_id *oid, int *flags)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700379{
380 const char *result;
381
382 result = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100383 oid, flags);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700384 return xstrdup_or_null(result);
385}
386
Michael Haggertyfb58c8d2015-06-22 16:03:05 +0200387char *resolve_refdup(const char *refname, int resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000388 struct object_id *oid, int *flags)
Nguyễn Thái Ngọc Duy96ec7b12011-12-13 21:17:48 +0700389{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700390 return refs_resolve_refdup(get_main_ref_store(the_repository),
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700391 refname, resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000392 oid, flags);
Nguyễn Thái Ngọc Duy96ec7b12011-12-13 21:17:48 +0700393}
394
Jeff Kingbf1377a2023-07-10 17:12:05 -0400395/* The argument to for_each_filter_refs */
396struct for_each_ref_filter {
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200397 const char *pattern;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000398 const char *prefix;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200399 each_ref_fn *fn;
400 void *cb_data;
401};
402
brian m. carlson34c290a2017-10-15 22:06:56 +0000403int 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 +0700404{
Ævar Arnfjörð Bjarmason76887df2021-10-16 11:39:14 +0200405 struct ref_store *refs = get_main_ref_store(the_repository);
406
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +0200407 if (refs_resolve_ref_unsafe(refs, refname, resolve_flags,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100408 oid, flags))
Ævar Arnfjörð Bjarmason76887df2021-10-16 11:39:14 +0200409 return 0;
410 return -1;
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700411}
412
brian m. carlson34c290a2017-10-15 22:06:56 +0000413int read_ref(const char *refname, struct object_id *oid)
Nguyễn Thái Ngọc Duyc6893322011-11-13 17:22:14 +0700414{
brian m. carlson34c290a2017-10-15 22:06:56 +0000415 return read_ref_full(refname, RESOLVE_REF_READING, oid, NULL);
Nguyễn Thái Ngọc Duyc6893322011-11-13 17:22:14 +0700416}
417
Han-Wen Nienhuys3f9f1ac2020-08-21 16:59:34 +0000418int refs_ref_exists(struct ref_store *refs, const char *refname)
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700419{
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +0200420 return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100421 NULL, NULL);
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700422}
423
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200424int ref_exists(const char *refname)
Junio C Hamanoef06b912006-11-18 22:13:33 -0800425{
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700426 return refs_ref_exists(get_main_ref_store(the_repository), refname);
Junio C Hamanoef06b912006-11-18 22:13:33 -0800427}
428
Jeff Kingbf1377a2023-07-10 17:12:05 -0400429static int for_each_filter_refs(const char *refname,
430 const struct object_id *oid,
431 int flags, void *data)
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200432{
Jeff Kingbf1377a2023-07-10 17:12:05 -0400433 struct for_each_ref_filter *filter = data;
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000434
Ævar Arnfjörð Bjarmason55d34262017-06-22 21:38:08 +0000435 if (wildmatch(filter->pattern, refname, 0))
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200436 return 0;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000437 if (filter->prefix)
438 skip_prefix(refname, filter->prefix, &refname);
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000439 return filter->fn(refname, oid, flags, filter->cb_data);
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200440}
441
brian m. carlsonac2ed0d2017-10-15 22:07:10 +0000442enum peel_status peel_object(const struct object_id *name, struct object_id *oid)
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200443{
Jeff King45a187c2021-04-13 03:16:36 -0400444 struct object *o = lookup_unknown_object(the_repository, name);
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200445
446 if (o->type == OBJ_NONE) {
Stefan Beller0df8e962018-04-25 11:20:59 -0700447 int type = oid_object_info(the_repository, name, NULL);
Abhishek Kumar6da43d92020-06-17 14:44:08 +0530448 if (type < 0 || !object_as_type(o, type, 0))
Michael Haggerty68cf8702013-04-22 21:52:20 +0200449 return PEEL_INVALID;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200450 }
451
452 if (o->type != OBJ_TAG)
Michael Haggerty68cf8702013-04-22 21:52:20 +0200453 return PEEL_NON_TAG;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200454
455 o = deref_tag_noverify(o);
456 if (!o)
Michael Haggerty68cf8702013-04-22 21:52:20 +0200457 return PEEL_INVALID;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200458
brian m. carlsonac2ed0d2017-10-15 22:07:10 +0000459 oidcpy(oid, &o->oid);
Michael Haggerty68cf8702013-04-22 21:52:20 +0200460 return PEEL_PEELED;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200461}
462
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200463struct warn_if_dangling_data {
464 FILE *fp;
465 const char *refname;
Jens Lindströme6bea662014-05-23 12:30:25 +0200466 const struct string_list *refnames;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200467 const char *msg_fmt;
468};
469
Jeff King63e14ee2022-08-19 06:08:32 -0400470static int warn_if_dangling_symref(const char *refname,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +0200471 const struct object_id *oid UNUSED,
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200472 int flags, void *cb_data)
473{
474 struct warn_if_dangling_data *d = cb_data;
475 const char *resolves_to;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200476
477 if (!(flags & REF_ISSYMREF))
478 return 0;
479
René Scharfe744c0402017-09-23 11:45:04 +0200480 resolves_to = resolve_ref_unsafe(refname, 0, NULL, NULL);
Jens Lindströme6bea662014-05-23 12:30:25 +0200481 if (!resolves_to
482 || (d->refname
483 ? strcmp(resolves_to, d->refname)
484 : !string_list_has_string(d->refnames, resolves_to))) {
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200485 return 0;
Jens Lindströme6bea662014-05-23 12:30:25 +0200486 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200487
488 fprintf(d->fp, d->msg_fmt, refname);
Junio C Hamano1be65ed2012-05-02 13:51:35 -0700489 fputc('\n', d->fp);
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200490 return 0;
491}
492
493void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
494{
495 struct warn_if_dangling_data data;
496
497 data.fp = fp;
498 data.refname = refname;
Jens Lindströme6bea662014-05-23 12:30:25 +0200499 data.refnames = NULL;
500 data.msg_fmt = msg_fmt;
501 for_each_rawref(warn_if_dangling_symref, &data);
502}
503
504void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)
505{
506 struct warn_if_dangling_data data;
507
508 data.fp = fp;
509 data.refname = NULL;
510 data.refnames = refnames;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200511 data.msg_fmt = msg_fmt;
512 for_each_rawref(warn_if_dangling_symref, &data);
513}
514
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700515int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
516{
517 return refs_for_each_ref_in(refs, "refs/tags/", fn, cb_data);
518}
519
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700520int for_each_tag_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400521{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700522 return refs_for_each_tag_ref(get_main_ref_store(the_repository), fn, cb_data);
Seana62be772006-05-13 21:43:00 -0400523}
524
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700525int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
526{
527 return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
Heiko Voigt9ef6aeb2010-07-07 15:39:12 +0200528}
529
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700530int for_each_branch_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400531{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700532 return refs_for_each_branch_ref(get_main_ref_store(the_repository), fn, cb_data);
Seana62be772006-05-13 21:43:00 -0400533}
534
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700535int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
536{
537 return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
Heiko Voigt9ef6aeb2010-07-07 15:39:12 +0200538}
539
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700540int for_each_remote_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400541{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700542 return refs_for_each_remote_ref(get_main_ref_store(the_repository), fn, cb_data);
Junio C Hamanof8948e22009-02-08 23:27:10 -0800543}
544
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700545int head_ref_namespaced(each_ref_fn fn, void *cb_data)
546{
547 struct strbuf buf = STRBUF_INIT;
548 int ret = 0;
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000549 struct object_id oid;
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700550 int flag;
551
552 strbuf_addf(&buf, "%sHEAD", get_git_namespace());
brian m. carlson34c290a2017-10-15 22:06:56 +0000553 if (!read_ref_full(buf.buf, RESOLVE_REF_READING, &oid, &flag))
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000554 ret = fn(buf.buf, &oid, flag, cb_data);
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700555 strbuf_release(&buf);
556
557 return ret;
558}
559
Rafael Ascensão65516f52017-11-21 21:33:41 +0000560void normalize_glob_ref(struct string_list_item *item, const char *prefix,
561 const char *pattern)
562{
563 struct strbuf normalized_pattern = STRBUF_INIT;
564
565 if (*pattern == '/')
566 BUG("pattern must not start with '/'");
567
Derrick Stoleeb877e612022-08-05 17:58:33 +0000568 if (prefix)
Rafael Ascensão65516f52017-11-21 21:33:41 +0000569 strbuf_addstr(&normalized_pattern, prefix);
Derrick Stoleeb877e612022-08-05 17:58:33 +0000570 else if (!starts_with(pattern, "refs/") &&
571 strcmp(pattern, "HEAD"))
Rafael Ascensão65516f52017-11-21 21:33:41 +0000572 strbuf_addstr(&normalized_pattern, "refs/");
Derrick Stoleeb877e612022-08-05 17:58:33 +0000573 /*
574 * NEEDSWORK: Special case other symrefs such as REBASE_HEAD,
575 * MERGE_HEAD, etc.
576 */
577
Rafael Ascensão65516f52017-11-21 21:33:41 +0000578 strbuf_addstr(&normalized_pattern, pattern);
579 strbuf_strip_suffix(&normalized_pattern, "/");
580
581 item->string = strbuf_detach(&normalized_pattern, NULL);
582 item->util = has_glob_specials(pattern) ? NULL : item->string;
583 strbuf_release(&normalized_pattern);
584}
585
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200586int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
587 const char *prefix, void *cb_data)
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200588{
589 struct strbuf real_pattern = STRBUF_INIT;
Jeff Kingbf1377a2023-07-10 17:12:05 -0400590 struct for_each_ref_filter filter;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200591 int ret;
592
Christian Couder59556542013-11-30 21:55:40 +0100593 if (!prefix && !starts_with(pattern, "refs/"))
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200594 strbuf_addstr(&real_pattern, "refs/");
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200595 else if (prefix)
596 strbuf_addstr(&real_pattern, prefix);
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200597 strbuf_addstr(&real_pattern, pattern);
598
Thomas Rast894a9d32010-03-12 18:04:26 +0100599 if (!has_glob_specials(pattern)) {
Junio C Hamano9517e6b2010-02-03 21:23:18 -0800600 /* Append implied '/' '*' if not present. */
Jeff King00b6c172015-09-24 17:08:35 -0400601 strbuf_complete(&real_pattern, '/');
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200602 /* No need to check for '*', there is none. */
603 strbuf_addch(&real_pattern, '*');
604 }
605
606 filter.pattern = real_pattern.buf;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000607 filter.prefix = prefix;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200608 filter.fn = fn;
609 filter.cb_data = cb_data;
Jeff Kingbf1377a2023-07-10 17:12:05 -0400610 ret = for_each_ref(for_each_filter_refs, &filter);
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200611
612 strbuf_release(&real_pattern);
613 return ret;
614}
615
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200616int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
617{
618 return for_each_glob_ref_in(fn, pattern, NULL, cb_data);
619}
620
Felipe Contreras4577e482009-05-14 00:22:04 +0300621const char *prettify_refname(const char *name)
Daniel Barkalowa9c37a72009-03-08 21:06:05 -0400622{
SZEDER Gábor3e5b36c2017-03-23 16:50:12 +0100623 if (skip_prefix(name, "refs/heads/", &name) ||
624 skip_prefix(name, "refs/tags/", &name) ||
625 skip_prefix(name, "refs/remotes/", &name))
626 ; /* nothing */
627 return name;
Daniel Barkalowa9c37a72009-03-08 21:06:05 -0400628}
629
Michael Haggerty54457fe2014-01-14 04:16:07 +0100630static const char *ref_rev_parse_rules[] = {
Steffen Prohaska79803322007-11-11 15:01:46 +0100631 "%.*s",
632 "refs/%.*s",
633 "refs/tags/%.*s",
634 "refs/heads/%.*s",
635 "refs/remotes/%.*s",
636 "refs/remotes/%.*s/HEAD",
637 NULL
638};
639
Junio C Hamano60650a42018-08-01 09:22:37 -0700640#define NUM_REV_PARSE_RULES (ARRAY_SIZE(ref_rev_parse_rules) - 1)
641
642/*
643 * Is it possible that the caller meant full_name with abbrev_name?
644 * If so return a non-zero value to signal "yes"; the magnitude of
645 * the returned value gives the precedence used for disambiguation.
646 *
647 * If abbrev_name cannot mean full_name, return 0.
648 */
Michael Haggerty54457fe2014-01-14 04:16:07 +0100649int refname_match(const char *abbrev_name, const char *full_name)
Steffen Prohaska79803322007-11-11 15:01:46 +0100650{
651 const char **p;
652 const int abbrev_name_len = strlen(abbrev_name);
Junio C Hamano60650a42018-08-01 09:22:37 -0700653 const int num_rules = NUM_REV_PARSE_RULES;
Steffen Prohaska79803322007-11-11 15:01:46 +0100654
Junio C Hamano60650a42018-08-01 09:22:37 -0700655 for (p = ref_rev_parse_rules; *p; p++)
656 if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name)))
657 return &ref_rev_parse_rules[num_rules] - p;
Steffen Prohaska79803322007-11-11 15:01:46 +0100658
659 return 0;
660}
661
Michael Haggerty19b68b12011-12-12 06:38:12 +0100662/*
Brandon Williamsb4be7412018-03-15 10:31:24 -0700663 * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add
664 * the results to 'prefixes'
665 */
Jeff Kingc972bf42020-07-28 16:25:12 -0400666void expand_ref_prefix(struct strvec *prefixes, const char *prefix)
Brandon Williamsb4be7412018-03-15 10:31:24 -0700667{
668 const char **p;
669 int len = strlen(prefix);
670
671 for (p = ref_rev_parse_rules; *p; p++)
Jeff Kingc972bf42020-07-28 16:25:12 -0400672 strvec_pushf(prefixes, *p, len, prefix);
Brandon Williamsb4be7412018-03-15 10:31:24 -0700673}
674
Johannes Schindelin675704c2020-12-11 11:36:57 +0000675static const char default_branch_name_advice[] = N_(
676"Using '%s' as the name for the initial branch. This default branch name\n"
677"is subject to change. To configure the initial branch name to use in all\n"
678"of your new repositories, which will suppress this warning, call:\n"
679"\n"
680"\tgit config --global init.defaultBranch <name>\n"
681"\n"
682"Names commonly chosen instead of 'master' are 'main', 'trunk' and\n"
683"'development'. The just-created branch can be renamed via this command:\n"
684"\n"
685"\tgit branch -m <name>\n"
686);
687
Johannes Schindelincc0f13c2020-12-11 11:36:56 +0000688char *repo_default_branch_name(struct repository *r, int quiet)
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000689{
690 const char *config_key = "init.defaultbranch";
691 const char *config_display_key = "init.defaultBranch";
692 char *ret = NULL, *full_ref;
Johannes Schindelin704fed92020-10-23 14:00:00 +0000693 const char *env = getenv("GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME");
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000694
Johannes Schindelin704fed92020-10-23 14:00:00 +0000695 if (env && *env)
696 ret = xstrdup(env);
697 else if (repo_config_get_string(r, config_key, &ret) < 0)
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000698 die(_("could not retrieve `%s`"), config_display_key);
699
Johannes Schindelin675704c2020-12-11 11:36:57 +0000700 if (!ret) {
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000701 ret = xstrdup("master");
Johannes Schindelin675704c2020-12-11 11:36:57 +0000702 if (!quiet)
703 advise(_(default_branch_name_advice), ret);
704 }
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000705
706 full_ref = xstrfmt("refs/heads/%s", ret);
707 if (check_refname_format(full_ref, 0))
708 die(_("invalid branch name: %s = %s"), config_display_key, ret);
709 free(full_ref);
710
711 return ret;
712}
713
Johannes Schindelincc0f13c2020-12-11 11:36:56 +0000714const char *git_default_branch_name(int quiet)
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000715{
716 static char *ret;
717
718 if (!ret)
Johannes Schindelincc0f13c2020-12-11 11:36:56 +0000719 ret = repo_default_branch_name(the_repository, quiet);
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000720
721 return ret;
722}
723
Brandon Williamsb4be7412018-03-15 10:31:24 -0700724/*
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700725 * *string and *len will only be substituted, and *string returned (for
726 * later free()ing) if the string passed in is a magic short-hand form
727 * to name a branch.
728 */
Nguyễn Thái Ngọc Duy8f56e9d2019-04-06 18:34:26 +0700729static char *substitute_branch_name(struct repository *r,
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700730 const char **string, int *len,
731 int nonfatal_dangling_mark)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700732{
733 struct strbuf buf = STRBUF_INIT;
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700734 struct interpret_branch_name_options options = {
735 .nonfatal_dangling_mark = nonfatal_dangling_mark
736 };
Jonathan Tana4f66a72020-09-01 15:28:07 -0700737 int ret = repo_interpret_branch_name(r, *string, *len, &buf, &options);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700738
739 if (ret == *len) {
740 size_t size;
741 *string = strbuf_detach(&buf, &size);
742 *len = size;
743 return (char *)*string;
744 }
745
746 return NULL;
747}
748
Nguyễn Thái Ngọc Duyd8984c52019-04-06 18:34:28 +0700749int repo_dwim_ref(struct repository *r, const char *str, int len,
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700750 struct object_id *oid, char **ref, int nonfatal_dangling_mark)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700751{
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700752 char *last_branch = substitute_branch_name(r, &str, &len,
753 nonfatal_dangling_mark);
Nguyễn Thái Ngọc Duyd8984c52019-04-06 18:34:28 +0700754 int refs_found = expand_ref(r, str, len, oid, ref);
Nguyễn Thái Ngọc Duy41da7112016-06-12 17:54:02 +0700755 free(last_branch);
756 return refs_found;
757}
758
Nguyễn Thái Ngọc Duy0b1dbf52019-04-06 18:34:27 +0700759int expand_ref(struct repository *repo, const char *str, int len,
760 struct object_id *oid, char **ref)
Nguyễn Thái Ngọc Duy41da7112016-06-12 17:54:02 +0700761{
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700762 const char **p, *r;
763 int refs_found = 0;
Jeff King6cd4a892017-03-28 15:46:33 -0400764 struct strbuf fullref = STRBUF_INIT;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700765
766 *ref = NULL;
767 for (p = ref_rev_parse_rules; *p; p++) {
brian m. carlsoncca5fa62017-10-15 22:06:57 +0000768 struct object_id oid_from_ref;
769 struct object_id *this_result;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700770 int flag;
Ævar Arnfjörð Bjarmason6582bd32021-10-16 11:39:24 +0200771 struct ref_store *refs = get_main_ref_store(repo);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700772
brian m. carlsoncca5fa62017-10-15 22:06:57 +0000773 this_result = refs_found ? &oid_from_ref : oid;
Jeff King6cd4a892017-03-28 15:46:33 -0400774 strbuf_reset(&fullref);
775 strbuf_addf(&fullref, *p, len, str);
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +0200776 r = refs_resolve_ref_unsafe(refs, fullref.buf,
Ævar Arnfjörð Bjarmason6582bd32021-10-16 11:39:24 +0200777 RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100778 this_result, &flag);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700779 if (r) {
780 if (!refs_found++)
781 *ref = xstrdup(r);
782 if (!warn_ambiguous_refs)
783 break;
Jeff King6cd4a892017-03-28 15:46:33 -0400784 } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200785 warning(_("ignoring dangling symref %s"), fullref.buf);
Jeff King6cd4a892017-03-28 15:46:33 -0400786 } else if ((flag & REF_ISBROKEN) && strchr(fullref.buf, '/')) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200787 warning(_("ignoring broken ref %s"), fullref.buf);
Junio C Hamano55956352011-10-19 13:55:49 -0700788 }
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700789 }
Jeff King6cd4a892017-03-28 15:46:33 -0400790 strbuf_release(&fullref);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700791 return refs_found;
792}
793
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700794int repo_dwim_log(struct repository *r, const char *str, int len,
795 struct object_id *oid, char **log)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700796{
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700797 struct ref_store *refs = get_main_ref_store(r);
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700798 char *last_branch = substitute_branch_name(r, &str, &len, 0);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700799 const char **p;
800 int logs_found = 0;
Jeff King6cd4a892017-03-28 15:46:33 -0400801 struct strbuf path = STRBUF_INIT;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700802
803 *log = NULL;
804 for (p = ref_rev_parse_rules; *p; p++) {
brian m. carlson334dc522017-10-15 22:06:59 +0000805 struct object_id hash;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700806 const char *ref, *it;
807
Jeff King6cd4a892017-03-28 15:46:33 -0400808 strbuf_reset(&path);
809 strbuf_addf(&path, *p, len, str);
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700810 ref = refs_resolve_ref_unsafe(refs, path.buf,
811 RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100812 oid ? &hash : NULL, NULL);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700813 if (!ref)
814 continue;
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700815 if (refs_reflog_exists(refs, path.buf))
Jeff King6cd4a892017-03-28 15:46:33 -0400816 it = path.buf;
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700817 else if (strcmp(ref, path.buf) &&
818 refs_reflog_exists(refs, ref))
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700819 it = ref;
820 else
821 continue;
822 if (!logs_found++) {
823 *log = xstrdup(it);
Ævar Arnfjörð Bjarmason6f45ec82021-08-23 13:36:08 +0200824 if (oid)
825 oidcpy(oid, &hash);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700826 }
827 if (!warn_ambiguous_refs)
828 break;
829 }
Jeff King6cd4a892017-03-28 15:46:33 -0400830 strbuf_release(&path);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700831 free(last_branch);
832 return logs_found;
833}
834
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700835int dwim_log(const char *str, int len, struct object_id *oid, char **log)
836{
837 return repo_dwim_log(the_repository, str, len, oid, log);
838}
839
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000840int is_per_worktree_ref(const char *refname)
David Turner266b1822015-07-31 02:06:18 -0400841{
Han-Wen Nienhuys55dd8b92020-07-27 16:25:47 +0000842 return starts_with(refname, "refs/worktree/") ||
843 starts_with(refname, "refs/bisect/") ||
844 starts_with(refname, "refs/rewritten/");
David Turner266b1822015-07-31 02:06:18 -0400845}
846
847static int is_pseudoref_syntax(const char *refname)
848{
849 const char *c;
850
851 for (c = refname; *c; c++) {
852 if (!isupper(*c) && *c != '-' && *c != '_')
853 return 0;
854 }
855
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000856 /*
857 * HEAD is not a pseudoref, but it certainly uses the
858 * pseudoref syntax.
859 */
David Turner266b1822015-07-31 02:06:18 -0400860 return 1;
861}
862
Karthik Nayak1eba2242024-02-23 11:01:08 +0100863int is_pseudoref(struct ref_store *refs, const char *refname)
864{
865 static const char *const irregular_pseudorefs[] = {
866 "AUTO_MERGE",
867 "BISECT_EXPECTED_REV",
868 "NOTES_MERGE_PARTIAL",
869 "NOTES_MERGE_REF",
870 "MERGE_AUTOSTASH",
871 };
872 struct object_id oid;
873 size_t i;
874
875 if (!is_pseudoref_syntax(refname))
876 return 0;
877
878 if (ends_with(refname, "_HEAD")) {
879 refs_resolve_ref_unsafe(refs, refname,
880 RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
881 &oid, NULL);
882 return !is_null_oid(&oid);
883 }
884
885 for (i = 0; i < ARRAY_SIZE(irregular_pseudorefs); i++)
886 if (!strcmp(refname, irregular_pseudorefs[i])) {
887 refs_resolve_ref_unsafe(refs, refname,
888 RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
889 &oid, NULL);
890 return !is_null_oid(&oid);
891 }
892
893 return 0;
894}
895
896int is_headref(struct ref_store *refs, const char *refname)
897{
898 if (!strcmp(refname, "HEAD"))
899 return refs_ref_exists(refs, refname);
900
901 return 0;
902}
903
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000904static int is_current_worktree_ref(const char *ref) {
905 return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref);
Nguyễn Thái Ngọc Duy3a3b9d82018-10-21 10:08:54 +0200906}
907
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000908enum ref_worktree_type parse_worktree_ref(const char *maybe_worktree_ref,
909 const char **worktree_name, int *worktree_name_length,
910 const char **bare_refname)
Nguyễn Thái Ngọc Duy3a3b9d82018-10-21 10:08:54 +0200911{
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000912 const char *name_dummy;
913 int name_length_dummy;
914 const char *ref_dummy;
Nguyễn Thái Ngọc Duy3a3b9d82018-10-21 10:08:54 +0200915
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000916 if (!worktree_name)
917 worktree_name = &name_dummy;
918 if (!worktree_name_length)
919 worktree_name_length = &name_length_dummy;
920 if (!bare_refname)
921 bare_refname = &ref_dummy;
922
923 if (skip_prefix(maybe_worktree_ref, "worktrees/", bare_refname)) {
924 const char *slash = strchr(*bare_refname, '/');
925
926 *worktree_name = *bare_refname;
927 if (!slash) {
928 *worktree_name_length = strlen(*worktree_name);
929
930 /* This is an error condition, and the caller tell because the bare_refname is "" */
931 *bare_refname = *worktree_name + *worktree_name_length;
932 return REF_WORKTREE_OTHER;
933 }
934
935 *worktree_name_length = slash - *bare_refname;
936 *bare_refname = slash + 1;
937
938 if (is_current_worktree_ref(*bare_refname))
939 return REF_WORKTREE_OTHER;
940 }
941
942 *worktree_name = NULL;
943 *worktree_name_length = 0;
944
945 if (skip_prefix(maybe_worktree_ref, "main-worktree/", bare_refname)
946 && is_current_worktree_ref(*bare_refname))
947 return REF_WORKTREE_MAIN;
948
949 *bare_refname = maybe_worktree_ref;
950 if (is_current_worktree_ref(maybe_worktree_ref))
951 return REF_WORKTREE_CURRENT;
952
953 return REF_WORKTREE_SHARED;
David Turner266b1822015-07-31 02:06:18 -0400954}
955
Michael Haggerty4ff0f012017-08-21 13:51:34 +0200956long get_files_ref_lock_timeout_ms(void)
957{
958 static int configured = 0;
959
960 /* The default timeout is 100 ms: */
961 static int timeout_ms = 100;
962
963 if (!configured) {
964 git_config_get_int("core.filesreflocktimeout", &timeout_ms);
965 configured = 1;
966 }
967
968 return timeout_ms;
969}
970
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700971int refs_delete_ref(struct ref_store *refs, const char *msg,
972 const char *refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000973 const struct object_id *old_oid,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700974 unsigned int flags)
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700975{
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700976 struct ref_transaction *transaction;
977 struct strbuf err = STRBUF_INIT;
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700978
Junio C Hamanoc6da34a2022-04-13 15:51:33 -0700979 transaction = ref_store_transaction_begin(refs, &err);
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700980 if (!transaction ||
brian m. carlson89f3bbd2017-10-15 22:06:53 +0000981 ref_transaction_delete(transaction, refname, old_oid,
Kyle Meyer755b49a2017-02-20 20:10:32 -0500982 flags, msg, &err) ||
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -0700983 ref_transaction_commit(transaction, &err)) {
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700984 error("%s", err.buf);
985 ref_transaction_free(transaction);
986 strbuf_release(&err);
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700987 return 1;
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700988 }
989 ref_transaction_free(transaction);
990 strbuf_release(&err);
991 return 0;
Shawn Pearce4bd18c42006-05-17 05:55:02 -0400992}
993
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700994int delete_ref(const char *msg, const char *refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000995 const struct object_id *old_oid, unsigned int flags)
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700996{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700997 return refs_delete_ref(get_main_ref_store(the_repository), msg, refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000998 old_oid, flags);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700999}
1000
Junio C Hamano523fa692020-07-10 17:19:53 +00001001static void copy_reflog_msg(struct strbuf *sb, const char *msg)
Junio C Hamano0ec29a42007-07-28 17:17:17 -07001002{
Junio C Hamano0ec29a42007-07-28 17:17:17 -07001003 char c;
1004 int wasspace = 1;
1005
Junio C Hamano0ec29a42007-07-28 17:17:17 -07001006 while ((c = *msg++)) {
1007 if (wasspace && isspace(c))
1008 continue;
1009 wasspace = isspace(c);
1010 if (wasspace)
1011 c = ' ';
Ben Peart80a6c202018-07-10 21:08:22 +00001012 strbuf_addch(sb, c);
Junio C Hamano0ec29a42007-07-28 17:17:17 -07001013 }
Ben Peart80a6c202018-07-10 21:08:22 +00001014 strbuf_rtrim(sb);
Junio C Hamano0ec29a42007-07-28 17:17:17 -07001015}
1016
Junio C Hamano523fa692020-07-10 17:19:53 +00001017static char *normalize_reflog_message(const char *msg)
1018{
1019 struct strbuf sb = STRBUF_INIT;
1020
1021 if (msg && *msg)
1022 copy_reflog_msg(&sb, msg);
1023 return strbuf_detach(&sb, NULL);
1024}
1025
Michael Haggerty4cb77002015-11-10 12:42:36 +01001026int should_autocreate_reflog(const char *refname)
David Turner4e2bef52015-07-21 17:04:51 -04001027{
Cornelius Weig341fb282017-01-27 11:09:47 +01001028 switch (log_all_ref_updates) {
1029 case LOG_REFS_ALWAYS:
1030 return 1;
1031 case LOG_REFS_NORMAL:
1032 return starts_with(refname, "refs/heads/") ||
1033 starts_with(refname, "refs/remotes/") ||
1034 starts_with(refname, "refs/notes/") ||
1035 !strcmp(refname, "HEAD");
1036 default:
David Turner4e2bef52015-07-21 17:04:51 -04001037 return 0;
Cornelius Weig341fb282017-01-27 11:09:47 +01001038 }
David Turner4e2bef52015-07-21 17:04:51 -04001039}
1040
Ronnie Sahlberge7e0f262014-07-15 16:02:38 -07001041int is_branch(const char *refname)
Linus Torvaldsc3b0dec2008-01-15 15:50:17 -08001042{
Christian Couder59556542013-11-30 21:55:40 +01001043 return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
Linus Torvaldsc3b0dec2008-01-15 15:50:17 -08001044}
1045
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001046struct read_ref_at_cb {
1047 const char *refname;
Johannes Schindelindddbad72017-04-26 21:29:31 +02001048 timestamp_t at_time;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001049 int cnt;
1050 int reccnt;
brian m. carlson8eb36d92017-10-15 22:07:03 +00001051 struct object_id *oid;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001052 int found_it;
1053
brian m. carlson8eb36d92017-10-15 22:07:03 +00001054 struct object_id ooid;
1055 struct object_id noid;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001056 int tz;
Johannes Schindelindddbad72017-04-26 21:29:31 +02001057 timestamp_t date;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001058 char **msg;
Johannes Schindelindddbad72017-04-26 21:29:31 +02001059 timestamp_t *cutoff_time;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001060 int *cutoff_tz;
1061 int *cutoff_cnt;
1062};
1063
Denton Liu95c2a712021-01-06 01:01:53 -08001064static void set_read_ref_cutoffs(struct read_ref_at_cb *cb,
1065 timestamp_t timestamp, int tz, const char *message)
1066{
1067 if (cb->msg)
1068 *cb->msg = xstrdup(message);
1069 if (cb->cutoff_time)
1070 *cb->cutoff_time = timestamp;
1071 if (cb->cutoff_tz)
1072 *cb->cutoff_tz = tz;
1073 if (cb->cutoff_cnt)
1074 *cb->cutoff_cnt = cb->reccnt;
1075}
1076
brian m. carlson9461d272017-02-21 23:47:32 +00001077static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02001078 const char *email UNUSED,
Jeff Kingc006e9f2022-08-19 06:08:35 -04001079 timestamp_t timestamp, int tz,
1080 const char *message, void *cb_data)
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001081{
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001082 struct read_ref_at_cb *cb = cb_data;
1083
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001084 cb->tz = tz;
1085 cb->date = timestamp;
1086
Jeff Kingaa72e732024-02-26 05:02:26 -05001087 if (timestamp <= cb->at_time || cb->cnt == 0) {
Denton Liu95c2a712021-01-06 01:01:53 -08001088 set_read_ref_cutoffs(cb, timestamp, tz, message);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001089 /*
Michael Haggerty78fb4572017-11-05 09:42:09 +01001090 * we have not yet updated cb->[n|o]oid so they still
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001091 * hold the values for the previous record.
1092 */
Jeff Kingaa72e732024-02-26 05:02:26 -05001093 if (!is_null_oid(&cb->ooid)) {
1094 oidcpy(cb->oid, noid);
1095 if (!oideq(&cb->ooid, noid))
1096 warning(_("log for ref %s has gap after %s"),
Jeff Kinga5481a62015-06-25 12:55:02 -04001097 cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
Jeff Kingaa72e732024-02-26 05:02:26 -05001098 }
1099 else if (cb->date == cb->at_time)
brian m. carlson8eb36d92017-10-15 22:07:03 +00001100 oidcpy(cb->oid, noid);
Jeff King9001dc22018-08-28 17:22:48 -04001101 else if (!oideq(noid, cb->oid))
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001102 warning(_("log for ref %s unexpectedly ended on %s"),
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001103 cb->refname, show_date(cb->date, cb->tz,
Jeff Kinga5481a62015-06-25 12:55:02 -04001104 DATE_MODE(RFC2822)));
Jeff Kingaa72e732024-02-26 05:02:26 -05001105 cb->reccnt++;
1106 oidcpy(&cb->ooid, ooid);
1107 oidcpy(&cb->noid, noid);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001108 cb->found_it = 1;
Jeff Kingaa72e732024-02-26 05:02:26 -05001109 return 1;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001110 }
Denton Liu95c2a712021-01-06 01:01:53 -08001111 cb->reccnt++;
brian m. carlson8eb36d92017-10-15 22:07:03 +00001112 oidcpy(&cb->ooid, ooid);
1113 oidcpy(&cb->noid, noid);
Jeff Kingaa72e732024-02-26 05:02:26 -05001114 if (cb->cnt > 0)
1115 cb->cnt--;
1116 return 0;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001117}
1118
brian m. carlson9461d272017-02-21 23:47:32 +00001119static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02001120 const char *email UNUSED,
Jeff Kingc006e9f2022-08-19 06:08:35 -04001121 timestamp_t timestamp, int tz,
1122 const char *message, void *cb_data)
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001123{
1124 struct read_ref_at_cb *cb = cb_data;
1125
Denton Liu95c2a712021-01-06 01:01:53 -08001126 set_read_ref_cutoffs(cb, timestamp, tz, message);
brian m. carlson8eb36d92017-10-15 22:07:03 +00001127 oidcpy(cb->oid, ooid);
Jeff King755e7462024-02-26 05:04:07 -05001128 if (cb->at_time && is_null_oid(cb->oid))
brian m. carlson8eb36d92017-10-15 22:07:03 +00001129 oidcpy(cb->oid, noid);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001130 /* We just want the first entry */
1131 return 1;
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001132}
1133
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +07001134int read_ref_at(struct ref_store *refs, const char *refname,
1135 unsigned int flags, timestamp_t at_time, int cnt,
brian m. carlson8eb36d92017-10-15 22:07:03 +00001136 struct object_id *oid, char **msg,
Johannes Schindelindddbad72017-04-26 21:29:31 +02001137 timestamp_t *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
Shawn Pearced556fae2006-05-17 05:56:09 -04001138{
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001139 struct read_ref_at_cb cb;
Shawn Pearced556fae2006-05-17 05:56:09 -04001140
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001141 memset(&cb, 0, sizeof(cb));
1142 cb.refname = refname;
1143 cb.at_time = at_time;
1144 cb.cnt = cnt;
1145 cb.msg = msg;
1146 cb.cutoff_time = cutoff_time;
1147 cb.cutoff_tz = cutoff_tz;
1148 cb.cutoff_cnt = cutoff_cnt;
brian m. carlson8eb36d92017-10-15 22:07:03 +00001149 cb.oid = oid;
Shawn Pearced556fae2006-05-17 05:56:09 -04001150
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +07001151 refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent, &cb);
Shawn Pearced556fae2006-05-17 05:56:09 -04001152
David Aguilarc41a87d2014-09-18 20:45:37 -07001153 if (!cb.reccnt) {
Jeff King5edd1262024-02-26 05:08:03 -05001154 if (cnt == 0) {
1155 /*
1156 * The caller asked for ref@{0}, and we had no entries.
1157 * It's a bit subtle, but in practice all callers have
1158 * prepped the "oid" field with the current value of
1159 * the ref, which is the most reasonable fallback.
1160 *
1161 * We'll put dummy values into the out-parameters (so
1162 * they're not just uninitialized garbage), and the
1163 * caller can take our return value as a hint that
1164 * we did not find any such reflog.
1165 */
1166 set_read_ref_cutoffs(&cb, 0, 0, "empty reflog");
1167 return 1;
1168 }
brian m. carlson321c89b2017-07-13 23:49:29 +00001169 if (flags & GET_OID_QUIETLY)
David Aguilarc41a87d2014-09-18 20:45:37 -07001170 exit(128);
1171 else
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001172 die(_("log for %s is empty"), refname);
David Aguilarc41a87d2014-09-18 20:45:37 -07001173 }
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001174 if (cb.found_it)
1175 return 0;
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001176
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +07001177 refs_for_each_reflog_ent(refs, refname, read_ref_at_ent_oldest, &cb);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001178
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001179 return 1;
Shawn Pearced556fae2006-05-17 05:56:09 -04001180}
Junio C Hamano2ff81662006-12-18 01:18:16 -08001181
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001182struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
1183 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001184{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001185 struct ref_transaction *tr;
Jonathan Nieder5a603b02014-08-28 16:42:37 -07001186 assert(err);
1187
René Scharfeca56dad2021-03-13 17:17:22 +01001188 CALLOC_ARRAY(tr, 1);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001189 tr->ref_store = refs;
1190 return tr;
1191}
1192
1193struct ref_transaction *ref_transaction_begin(struct strbuf *err)
1194{
Junio C Hamanoc6da34a2022-04-13 15:51:33 -07001195 return ref_store_transaction_begin(get_main_ref_store(the_repository), err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001196}
1197
Ronnie Sahlberg026bd1d2014-06-20 07:42:42 -07001198void ref_transaction_free(struct ref_transaction *transaction)
Michael Haggertycaa40462014-04-07 15:48:10 +02001199{
Michael Haggerty43a2dfd2017-05-22 16:17:37 +02001200 size_t i;
Michael Haggertycaa40462014-04-07 15:48:10 +02001201
Ronnie Sahlberg1b072552014-06-20 07:42:45 -07001202 if (!transaction)
1203 return;
1204
Michael Haggerty30173b82017-05-22 16:17:44 +02001205 switch (transaction->state) {
1206 case REF_TRANSACTION_OPEN:
1207 case REF_TRANSACTION_CLOSED:
1208 /* OK */
1209 break;
1210 case REF_TRANSACTION_PREPARED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02001211 BUG("free called on a prepared reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02001212 break;
1213 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02001214 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02001215 break;
1216 }
1217
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -07001218 for (i = 0; i < transaction->nr; i++) {
1219 free(transaction->updates[i]->msg);
Michael Haggerty88615912014-04-07 15:48:14 +02001220 free(transaction->updates[i]);
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -07001221 }
Michael Haggertycaa40462014-04-07 15:48:10 +02001222 free(transaction->updates);
1223 free(transaction);
1224}
1225
Michael Haggerty71564512016-04-25 11:39:54 +02001226struct ref_update *ref_transaction_add_update(
1227 struct ref_transaction *transaction,
1228 const char *refname, unsigned int flags,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001229 const struct object_id *new_oid,
1230 const struct object_id *old_oid,
Michael Haggerty71564512016-04-25 11:39:54 +02001231 const char *msg)
Michael Haggertycaa40462014-04-07 15:48:10 +02001232{
Jeff King96ffc062016-02-22 17:44:32 -05001233 struct ref_update *update;
Michael Haggerty71564512016-04-25 11:39:54 +02001234
1235 if (transaction->state != REF_TRANSACTION_OPEN)
Johannes Schindelin033abf92018-05-02 11:38:39 +02001236 BUG("update called for transaction that is not open");
Michael Haggerty71564512016-04-25 11:39:54 +02001237
Jeff King96ffc062016-02-22 17:44:32 -05001238 FLEX_ALLOC_STR(update, refname, refname);
Michael Haggertycaa40462014-04-07 15:48:10 +02001239 ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
1240 transaction->updates[transaction->nr++] = update;
Michael Haggerty71564512016-04-25 11:39:54 +02001241
1242 update->flags = flags;
1243
1244 if (flags & REF_HAVE_NEW)
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001245 oidcpy(&update->new_oid, new_oid);
Michael Haggerty71564512016-04-25 11:39:54 +02001246 if (flags & REF_HAVE_OLD)
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001247 oidcpy(&update->old_oid, old_oid);
Junio C Hamano523fa692020-07-10 17:19:53 +00001248 update->msg = normalize_reflog_message(msg);
Michael Haggertycaa40462014-04-07 15:48:10 +02001249 return update;
1250}
1251
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001252int ref_transaction_update(struct ref_transaction *transaction,
1253 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001254 const struct object_id *new_oid,
1255 const struct object_id *old_oid,
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001256 unsigned int flags, const char *msg,
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001257 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001258{
Jonathan Nieder5a603b02014-08-28 16:42:37 -07001259 assert(err);
1260
Han-Wen Nienhuys3c966c72021-12-07 13:38:18 +00001261 if (!(flags & REF_SKIP_REFNAME_VERIFICATION) &&
1262 ((new_oid && !is_null_oid(new_oid)) ?
1263 check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) :
1264 !refname_is_safe(refname))) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001265 strbuf_addf(err, _("refusing to update ref with bad name '%s'"),
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -07001266 refname);
1267 return -1;
1268 }
1269
Michael Haggertya9bbbce2017-11-05 09:42:03 +01001270 if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
1271 BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
Thomas Gummererc788c542017-09-12 23:59:21 +01001272
Jeff King49f1eb32021-11-19 16:28:30 -05001273 /*
1274 * Clear flags outside the allowed set; this should be a noop because
1275 * of the BUG() check above, but it works around a -Wnonnull warning
1276 * with some versions of "gcc -O3".
1277 */
1278 flags &= REF_TRANSACTION_UPDATE_ALLOWED_FLAGS;
1279
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001280 flags |= (new_oid ? REF_HAVE_NEW : 0) | (old_oid ? REF_HAVE_OLD : 0);
Michael Haggerty71564512016-04-25 11:39:54 +02001281
1282 ref_transaction_add_update(transaction, refname, flags,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001283 new_oid, old_oid, msg);
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001284 return 0;
Michael Haggertycaa40462014-04-07 15:48:10 +02001285}
1286
Ronnie Sahlbergb416af52014-04-16 15:26:44 -07001287int ref_transaction_create(struct ref_transaction *transaction,
1288 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001289 const struct object_id *new_oid,
Michael Haggertyfec14ec2015-02-17 18:00:13 +01001290 unsigned int flags, const char *msg,
Ronnie Sahlbergb416af52014-04-16 15:26:44 -07001291 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001292{
Derrick Stoleed097a232022-04-25 13:47:30 +00001293 if (!new_oid || is_null_oid(new_oid)) {
1294 strbuf_addf(err, "'%s' has a null OID", refname);
1295 return 1;
1296 }
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001297 return ref_transaction_update(transaction, refname, new_oid,
brian m. carlson14228442021-04-26 01:02:56 +00001298 null_oid(), flags, msg, err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001299}
1300
Ronnie Sahlberg8c8bdc02014-04-16 15:27:45 -07001301int ref_transaction_delete(struct ref_transaction *transaction,
1302 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001303 const struct object_id *old_oid,
Michael Haggertyfb5a6bb2015-02-17 18:00:16 +01001304 unsigned int flags, const char *msg,
Ronnie Sahlberg8c8bdc02014-04-16 15:27:45 -07001305 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001306{
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001307 if (old_oid && is_null_oid(old_oid))
Johannes Schindelin033abf92018-05-02 11:38:39 +02001308 BUG("delete called with old_oid set to zeros");
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001309 return ref_transaction_update(transaction, refname,
brian m. carlson14228442021-04-26 01:02:56 +00001310 null_oid(), old_oid,
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001311 flags, msg, err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001312}
1313
Michael Haggerty16180332015-02-17 18:00:21 +01001314int ref_transaction_verify(struct ref_transaction *transaction,
1315 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001316 const struct object_id *old_oid,
Michael Haggerty16180332015-02-17 18:00:21 +01001317 unsigned int flags,
1318 struct strbuf *err)
1319{
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001320 if (!old_oid)
Johannes Schindelin033abf92018-05-02 11:38:39 +02001321 BUG("verify called with old_oid set to NULL");
Michael Haggerty16180332015-02-17 18:00:21 +01001322 return ref_transaction_update(transaction, refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001323 NULL, old_oid,
Michael Haggerty16180332015-02-17 18:00:21 +01001324 flags, NULL, err);
1325}
1326
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001327int refs_update_ref(struct ref_store *refs, const char *msg,
brian m. carlsonae077772017-10-15 22:06:51 +00001328 const char *refname, const struct object_id *new_oid,
1329 const struct object_id *old_oid, unsigned int flags,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001330 enum action_on_err onerr)
Brad King4738a332013-09-04 11:22:40 -04001331{
David Turner74ec19d2015-07-31 02:06:19 -04001332 struct ref_transaction *t = NULL;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001333 struct strbuf err = STRBUF_INIT;
David Turner74ec19d2015-07-31 02:06:19 -04001334 int ret = 0;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001335
Junio C Hamanoc6da34a2022-04-13 15:51:33 -07001336 t = ref_store_transaction_begin(refs, &err);
Han-Wen Nienhuys09743412020-07-27 16:25:46 +00001337 if (!t ||
1338 ref_transaction_update(t, refname, new_oid, old_oid, flags, msg,
1339 &err) ||
1340 ref_transaction_commit(t, &err)) {
1341 ret = 1;
1342 ref_transaction_free(t);
David Turner74ec19d2015-07-31 02:06:19 -04001343 }
1344 if (ret) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001345 const char *str = _("update_ref failed for ref '%s': %s");
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001346
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001347 switch (onerr) {
1348 case UPDATE_REFS_MSG_ON_ERR:
1349 error(str, refname, err.buf);
1350 break;
1351 case UPDATE_REFS_DIE_ON_ERR:
1352 die(str, refname, err.buf);
1353 break;
1354 case UPDATE_REFS_QUIET_ON_ERR:
1355 break;
1356 }
1357 strbuf_release(&err);
Brad King4738a332013-09-04 11:22:40 -04001358 return 1;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001359 }
1360 strbuf_release(&err);
David Turner74ec19d2015-07-31 02:06:19 -04001361 if (t)
1362 ref_transaction_free(t);
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001363 return 0;
Brad King4738a332013-09-04 11:22:40 -04001364}
1365
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001366int update_ref(const char *msg, const char *refname,
brian m. carlsonae077772017-10-15 22:06:51 +00001367 const struct object_id *new_oid,
1368 const struct object_id *old_oid,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001369 unsigned int flags, enum action_on_err onerr)
1370{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001371 return refs_update_ref(get_main_ref_store(the_repository), msg, refname, new_oid,
brian m. carlsonae077772017-10-15 22:06:51 +00001372 old_oid, flags, onerr);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001373}
1374
Jeff King613bef52023-02-15 10:16:21 -05001375/*
1376 * Check that the string refname matches a rule of the form
1377 * "{prefix}%.*s{suffix}". So "foo/bar/baz" would match the rule
1378 * "foo/%.*s/baz", and return the string "bar".
1379 */
1380static const char *match_parse_rule(const char *refname, const char *rule,
1381 size_t *len)
1382{
1383 /*
1384 * Check that rule matches refname up to the first percent in the rule.
1385 * We can bail immediately if not, but otherwise we leave "rule" at the
1386 * %-placeholder, and "refname" at the start of the potential matched
1387 * name.
1388 */
1389 while (*rule != '%') {
1390 if (!*rule)
1391 BUG("rev-parse rule did not have percent");
1392 if (*refname++ != *rule++)
1393 return NULL;
1394 }
1395
1396 /*
1397 * Check that our "%" is the expected placeholder. This assumes there
1398 * are no other percents (placeholder or quoted) in the string, but
1399 * that is sufficient for our rev-parse rules.
1400 */
1401 if (!skip_prefix(rule, "%.*s", &rule))
1402 return NULL;
1403
1404 /*
1405 * And now check that our suffix (if any) matches.
1406 */
1407 if (!strip_suffix(refname, rule, len))
1408 return NULL;
1409
1410 return refname; /* len set by strip_suffix() */
1411}
1412
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001413char *refs_shorten_unambiguous_ref(struct ref_store *refs,
1414 const char *refname, int strict)
Jeff King7c2b3022009-04-07 03:14:20 -04001415{
1416 int i;
Jeff King6cd4a892017-03-28 15:46:33 -04001417 struct strbuf resolved_buf = STRBUF_INIT;
Jeff King7c2b3022009-04-07 03:14:20 -04001418
Jeff King7c2b3022009-04-07 03:14:20 -04001419 /* skip first rule, it will always match */
Jeff King8f416f62023-02-15 10:16:18 -05001420 for (i = NUM_REV_PARSE_RULES - 1; i > 0 ; --i) {
Jeff King7c2b3022009-04-07 03:14:20 -04001421 int j;
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001422 int rules_to_fail = i;
Jeff King613bef52023-02-15 10:16:21 -05001423 const char *short_name;
Jeff Kingdd5e4d32023-02-15 10:16:14 -05001424 size_t short_name_len;
Jeff King7c2b3022009-04-07 03:14:20 -04001425
Jeff King613bef52023-02-15 10:16:21 -05001426 short_name = match_parse_rule(refname, ref_rev_parse_rules[i],
1427 &short_name_len);
1428 if (!short_name)
Jeff King7c2b3022009-04-07 03:14:20 -04001429 continue;
1430
Jeff King7c2b3022009-04-07 03:14:20 -04001431 /*
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001432 * in strict mode, all (except the matched one) rules
1433 * must fail to resolve to a valid non-ambiguous ref
1434 */
1435 if (strict)
Jeff King8f416f62023-02-15 10:16:18 -05001436 rules_to_fail = NUM_REV_PARSE_RULES;
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001437
1438 /*
Jeff King7c2b3022009-04-07 03:14:20 -04001439 * check if the short name resolves to a valid ref,
1440 * but use only rules prior to the matched one
1441 */
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001442 for (j = 0; j < rules_to_fail; j++) {
Jeff King7c2b3022009-04-07 03:14:20 -04001443 const char *rule = ref_rev_parse_rules[j];
Jeff King7c2b3022009-04-07 03:14:20 -04001444
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001445 /* skip matched rule */
1446 if (i == j)
1447 continue;
1448
Jeff King7c2b3022009-04-07 03:14:20 -04001449 /*
1450 * the short name is ambiguous, if it resolves
1451 * (with this previous rule) to a valid ref
1452 * read_ref() returns 0 on success
1453 */
Jeff King6cd4a892017-03-28 15:46:33 -04001454 strbuf_reset(&resolved_buf);
1455 strbuf_addf(&resolved_buf, rule,
Jeff Kingdd5e4d32023-02-15 10:16:14 -05001456 cast_size_t_to_int(short_name_len),
1457 short_name);
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001458 if (refs_ref_exists(refs, resolved_buf.buf))
Jeff King7c2b3022009-04-07 03:14:20 -04001459 break;
1460 }
1461
1462 /*
1463 * short name is non-ambiguous if all previous rules
1464 * haven't resolved to a valid ref
1465 */
Jeff King6cd4a892017-03-28 15:46:33 -04001466 if (j == rules_to_fail) {
1467 strbuf_release(&resolved_buf);
Jeff King613bef52023-02-15 10:16:21 -05001468 return xmemdupz(short_name, short_name_len);
Jeff King6cd4a892017-03-28 15:46:33 -04001469 }
Jeff King7c2b3022009-04-07 03:14:20 -04001470 }
1471
Jeff King6cd4a892017-03-28 15:46:33 -04001472 strbuf_release(&resolved_buf);
Michael Haggertydfefa932011-12-12 06:38:09 +01001473 return xstrdup(refname);
Jeff King7c2b3022009-04-07 03:14:20 -04001474}
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001475
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001476char *shorten_unambiguous_ref(const char *refname, int strict)
1477{
1478 return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
1479 refname, strict);
1480}
1481
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001482int parse_hide_refs_config(const char *var, const char *value, const char *section,
Taylor Blauc45841f2023-07-10 17:12:33 -04001483 struct strvec *hide_refs)
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001484{
Jeff Kingad8c7cd2017-02-24 16:08:16 -05001485 const char *key;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001486 if (!strcmp("transfer.hiderefs", var) ||
Jeff Kingad8c7cd2017-02-24 16:08:16 -05001487 (!parse_config_key(var, section, NULL, NULL, &key) &&
1488 !strcmp(key, "hiderefs"))) {
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001489 char *ref;
1490 int len;
1491
1492 if (!value)
1493 return config_error_nonbool(var);
Taylor Blauc45841f2023-07-10 17:12:33 -04001494
1495 /* drop const to remove trailing '/' characters */
1496 ref = (char *)strvec_push(hide_refs, value);
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001497 len = strlen(ref);
1498 while (len && ref[len - 1] == '/')
1499 ref[--len] = '\0';
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001500 }
1501 return 0;
1502}
1503
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001504int ref_is_hidden(const char *refname, const char *refname_full,
Taylor Blauc45841f2023-07-10 17:12:33 -04001505 const struct strvec *hide_refs)
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001506{
Jeff King2bc31d12015-07-28 16:23:26 -04001507 int i;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001508
Jeff King2bc31d12015-07-28 16:23:26 -04001509 for (i = hide_refs->nr - 1; i >= 0; i--) {
Taylor Blauc45841f2023-07-10 17:12:33 -04001510 const char *match = hide_refs->v[i];
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001511 const char *subject;
Jeff King2bc31d12015-07-28 16:23:26 -04001512 int neg = 0;
Christian Couder7a40a952017-07-22 06:39:12 +02001513 const char *p;
Jeff King2bc31d12015-07-28 16:23:26 -04001514
1515 if (*match == '!') {
1516 neg = 1;
1517 match++;
1518 }
1519
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001520 if (*match == '^') {
1521 subject = refname_full;
1522 match++;
1523 } else {
1524 subject = refname;
1525 }
1526
1527 /* refname can be NULL when namespaces are used. */
Christian Couder7a40a952017-07-22 06:39:12 +02001528 if (subject &&
1529 skip_prefix(subject, match, &p) &&
1530 (!*p || *p == '/'))
Jeff King2bc31d12015-07-28 16:23:26 -04001531 return !neg;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001532 }
1533 return 0;
1534}
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001535
Taylor Blau15af64d2023-07-10 17:12:39 -04001536const char **hidden_refs_to_excludes(const struct strvec *hide_refs)
1537{
1538 const char **pattern;
1539 for (pattern = hide_refs->v; *pattern; pattern++) {
1540 /*
1541 * We can't feed any excludes from hidden refs config
1542 * sections, since later rules may override previous
1543 * ones. For example, with rules "refs/foo" and
1544 * "!refs/foo/bar", we should show "refs/foo/bar" (and
1545 * everything underneath it), but the earlier exclusion
1546 * would cause us to skip all of "refs/foo". We
1547 * likewise don't implement the namespace stripping
1548 * required for '^' rules.
1549 *
1550 * Both are possible to do, but complicated, so avoid
1551 * populating the jump list at all if we see either of
1552 * these patterns.
1553 */
1554 if (**pattern == '!' || **pattern == '^')
1555 return NULL;
1556 }
1557 return hide_refs->v;
1558}
1559
David Turner08451222015-11-10 12:42:40 +01001560const char *find_descendant_ref(const char *dirname,
1561 const struct string_list *extras,
1562 const struct string_list *skip)
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001563{
David Turner08451222015-11-10 12:42:40 +01001564 int pos;
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001565
David Turner08451222015-11-10 12:42:40 +01001566 if (!extras)
1567 return NULL;
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001568
1569 /*
David Turner08451222015-11-10 12:42:40 +01001570 * Look at the place where dirname would be inserted into
1571 * extras. If there is an entry at that position that starts
1572 * with dirname (remember, dirname includes the trailing
1573 * slash) and is not in skip, then we have a conflict.
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001574 */
David Turner08451222015-11-10 12:42:40 +01001575 for (pos = string_list_find_insert_index(extras, dirname, 0);
1576 pos < extras->nr; pos++) {
1577 const char *extra_refname = extras->items[pos].string;
1578
1579 if (!starts_with(extra_refname, dirname))
1580 break;
1581
1582 if (!skip || !string_list_has_string(skip, extra_refname))
1583 return extra_refname;
Michael Haggerty4a32b2e2015-05-11 17:25:15 +02001584 }
David Turner08451222015-11-10 12:42:40 +01001585 return NULL;
1586}
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001587
Nguyễn Thái Ngọc Duy62f0b392017-08-23 19:36:55 +07001588int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turner2bf68ed2016-04-07 15:02:48 -04001589{
1590 struct object_id oid;
1591 int flag;
1592
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +02001593 if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001594 &oid, &flag))
David Turner2bf68ed2016-04-07 15:02:48 -04001595 return fn("HEAD", &oid, flag, cb_data);
1596
1597 return 0;
1598}
1599
1600int head_ref(each_ref_fn fn, void *cb_data)
1601{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001602 return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data);
David Turner2bf68ed2016-04-07 15:02:48 -04001603}
David Turner93770592016-04-07 15:02:49 -04001604
Michael Haggertye121b9c2017-03-20 17:33:08 +01001605struct ref_iterator *refs_ref_iterator_begin(
1606 struct ref_store *refs,
Taylor Blaub269ac52023-07-10 17:12:22 -04001607 const char *prefix,
1608 const char **exclude_patterns,
1609 int trim,
Jeff King9aab9522021-09-24 14:39:44 -04001610 enum do_for_each_ref_flags flags)
Michael Haggertye121b9c2017-03-20 17:33:08 +01001611{
1612 struct ref_iterator *iter;
1613
Jeff King6d751be2021-09-24 14:42:38 -04001614 if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
Jeff King5d1f5b82021-09-24 14:46:37 -04001615 static int ref_paranoia = -1;
1616
Jeff King6d751be2021-09-24 14:42:38 -04001617 if (ref_paranoia < 0)
Jeff King968f12f2021-09-24 14:46:13 -04001618 ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 1);
Jeff King6d751be2021-09-24 14:42:38 -04001619 if (ref_paranoia) {
1620 flags |= DO_FOR_EACH_INCLUDE_BROKEN;
1621 flags |= DO_FOR_EACH_OMIT_DANGLING_SYMREFS;
1622 }
1623 }
Michael Haggerty0a0865b2017-05-22 16:17:52 +02001624
Taylor Blaub269ac52023-07-10 17:12:22 -04001625 iter = refs->be->iterator_begin(refs, prefix, exclude_patterns, flags);
Michael Haggertyc7599712017-05-22 16:17:36 +02001626 /*
1627 * `iterator_begin()` already takes care of prefix, but we
1628 * might need to do some trimming:
1629 */
1630 if (trim)
1631 iter = prefix_ref_iterator_begin(iter, "", trim);
Michael Haggertye121b9c2017-03-20 17:33:08 +01001632
1633 return iter;
1634}
1635
Michael Haggerty4c4de892016-06-18 06:15:16 +02001636/*
1637 * Call fn for each reference in the specified submodule for which the
1638 * refname begins with prefix. If trim is non-zero, then trim that
1639 * many characters off the beginning of each refname before passing
1640 * the refname to fn. flags can be DO_FOR_EACH_INCLUDE_BROKEN to
1641 * include broken references in the iteration. If fn ever returns a
1642 * non-zero value, stop the iteration and return that value;
1643 * otherwise, return 0.
1644 */
Stefan Beller4a6067c2018-08-20 18:24:16 +00001645static int do_for_each_repo_ref(struct repository *r, const char *prefix,
1646 each_repo_ref_fn fn, int trim, int flags,
1647 void *cb_data)
Michael Haggerty4c4de892016-06-18 06:15:16 +02001648{
1649 struct ref_iterator *iter;
Stefan Beller4a6067c2018-08-20 18:24:16 +00001650 struct ref_store *refs = get_main_ref_store(r);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001651
Michael Haggerty00eebe32016-09-04 18:08:11 +02001652 if (!refs)
1653 return 0;
1654
Taylor Blaub269ac52023-07-10 17:12:22 -04001655 iter = refs_ref_iterator_begin(refs, prefix, NULL, trim, flags);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001656
Stefan Beller4a6067c2018-08-20 18:24:16 +00001657 return do_for_each_repo_ref_iterator(r, iter, fn, cb_data);
1658}
1659
1660struct do_for_each_ref_help {
1661 each_ref_fn *fn;
1662 void *cb_data;
1663};
1664
Jeff King1779dee2023-07-03 02:44:02 -04001665static int do_for_each_ref_helper(struct repository *r UNUSED,
Stefan Beller4a6067c2018-08-20 18:24:16 +00001666 const char *refname,
1667 const struct object_id *oid,
1668 int flags,
1669 void *cb_data)
1670{
1671 struct do_for_each_ref_help *hp = cb_data;
1672
1673 return hp->fn(refname, oid, flags, hp->cb_data);
1674}
1675
1676static int do_for_each_ref(struct ref_store *refs, const char *prefix,
Taylor Blaub269ac52023-07-10 17:12:22 -04001677 const char **exclude_patterns,
Jeff King9aab9522021-09-24 14:39:44 -04001678 each_ref_fn fn, int trim,
1679 enum do_for_each_ref_flags flags, void *cb_data)
Stefan Beller4a6067c2018-08-20 18:24:16 +00001680{
1681 struct ref_iterator *iter;
1682 struct do_for_each_ref_help hp = { fn, cb_data };
1683
1684 if (!refs)
1685 return 0;
1686
Taylor Blaub269ac52023-07-10 17:12:22 -04001687 iter = refs_ref_iterator_begin(refs, prefix, exclude_patterns, trim,
1688 flags);
Stefan Beller4a6067c2018-08-20 18:24:16 +00001689
1690 return do_for_each_repo_ref_iterator(the_repository, iter,
1691 do_for_each_ref_helper, &hp);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001692}
1693
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001694int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
1695{
Taylor Blaub269ac52023-07-10 17:12:22 -04001696 return do_for_each_ref(refs, "", NULL, fn, 0, 0, cb_data);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001697}
1698
David Turner93770592016-04-07 15:02:49 -04001699int for_each_ref(each_ref_fn fn, void *cb_data)
1700{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001701 return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data);
David Turner93770592016-04-07 15:02:49 -04001702}
1703
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001704int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
1705 each_ref_fn fn, void *cb_data)
1706{
Taylor Blaub269ac52023-07-10 17:12:22 -04001707 return do_for_each_ref(refs, prefix, NULL, fn, strlen(prefix), 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001708}
1709
1710int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
1711{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001712 return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data);
David Turner93770592016-04-07 15:02:49 -04001713}
1714
Jeff King67985e42021-09-24 14:48:48 -04001715int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001716{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001717 return do_for_each_ref(get_main_ref_store(the_repository),
Taylor Blaub269ac52023-07-10 17:12:22 -04001718 prefix, NULL, fn, 0, 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001719}
1720
Nguyễn Thái Ngọc Duy073cf632017-08-23 19:36:56 +07001721int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
Taylor Blaub269ac52023-07-10 17:12:22 -04001722 const char **exclude_patterns,
Jeff King67985e42021-09-24 14:48:48 -04001723 each_ref_fn fn, void *cb_data)
Michael Haggerty03df5672017-06-18 15:39:41 +02001724{
Taylor Blaub269ac52023-07-10 17:12:22 -04001725 return do_for_each_ref(refs, prefix, exclude_patterns, fn, 0, 0, cb_data);
Michael Haggerty03df5672017-06-18 15:39:41 +02001726}
1727
Stefan Beller212e0f72018-08-20 18:24:19 +00001728int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001729{
Derrick Stolee97e61e02022-08-05 17:58:37 +00001730 const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
Stefan Beller212e0f72018-08-20 18:24:19 +00001731 return do_for_each_repo_ref(r, git_replace_ref_base, fn,
1732 strlen(git_replace_ref_base),
1733 DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
David Turner93770592016-04-07 15:02:49 -04001734}
1735
Taylor Blaue6bf24d2023-07-10 17:12:36 -04001736int for_each_namespaced_ref(const char **exclude_patterns,
1737 each_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001738{
1739 struct strbuf buf = STRBUF_INIT;
1740 int ret;
1741 strbuf_addf(&buf, "%srefs/", get_git_namespace());
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001742 ret = do_for_each_ref(get_main_ref_store(the_repository),
Taylor Blaue6bf24d2023-07-10 17:12:36 -04001743 buf.buf, exclude_patterns, fn, 0, 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001744 strbuf_release(&buf);
1745 return ret;
1746}
1747
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001748int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001749{
Taylor Blaub269ac52023-07-10 17:12:22 -04001750 return do_for_each_ref(refs, "", NULL, fn, 0,
David Turner93770592016-04-07 15:02:49 -04001751 DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
1752}
David Turner2d0663b2016-04-07 15:03:10 -04001753
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001754int for_each_rawref(each_ref_fn fn, void *cb_data)
1755{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001756 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 +07001757}
1758
Karthik Nayakd0f00c12024-02-23 11:01:10 +01001759int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn,
1760 void *cb_data)
1761{
1762 return do_for_each_ref(refs, "", NULL, fn, 0,
1763 DO_FOR_EACH_INCLUDE_ROOT_REFS, cb_data);
1764}
1765
Taylor Blau16b19852021-01-20 11:04:21 -05001766static int qsort_strcmp(const void *va, const void *vb)
1767{
1768 const char *a = *(const char **)va;
1769 const char *b = *(const char **)vb;
1770
1771 return strcmp(a, b);
1772}
1773
1774static void find_longest_prefixes_1(struct string_list *out,
1775 struct strbuf *prefix,
1776 const char **patterns, size_t nr)
1777{
1778 size_t i;
1779
1780 for (i = 0; i < nr; i++) {
1781 char c = patterns[i][prefix->len];
1782 if (!c || is_glob_special(c)) {
1783 string_list_append(out, prefix->buf);
1784 return;
1785 }
1786 }
1787
1788 i = 0;
1789 while (i < nr) {
1790 size_t end;
1791
1792 /*
1793 * Set "end" to the index of the element _after_ the last one
1794 * in our group.
1795 */
1796 for (end = i + 1; end < nr; end++) {
1797 if (patterns[i][prefix->len] != patterns[end][prefix->len])
1798 break;
1799 }
1800
1801 strbuf_addch(prefix, patterns[i][prefix->len]);
1802 find_longest_prefixes_1(out, prefix, patterns + i, end - i);
1803 strbuf_setlen(prefix, prefix->len - 1);
1804
1805 i = end;
1806 }
1807}
1808
1809static void find_longest_prefixes(struct string_list *out,
1810 const char **patterns)
1811{
1812 struct strvec sorted = STRVEC_INIT;
1813 struct strbuf prefix = STRBUF_INIT;
1814
1815 strvec_pushv(&sorted, patterns);
1816 QSORT(sorted.v, sorted.nr, qsort_strcmp);
1817
1818 find_longest_prefixes_1(out, &prefix, sorted.v, sorted.nr);
1819
1820 strvec_clear(&sorted);
1821 strbuf_release(&prefix);
1822}
1823
Jeff King91e2ab12022-12-13 06:11:10 -05001824int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
1825 const char *namespace,
1826 const char **patterns,
Taylor Blaub269ac52023-07-10 17:12:22 -04001827 const char **exclude_patterns,
Jeff King91e2ab12022-12-13 06:11:10 -05001828 each_ref_fn fn, void *cb_data)
Taylor Blau16b19852021-01-20 11:04:21 -05001829{
1830 struct string_list prefixes = STRING_LIST_INIT_DUP;
1831 struct string_list_item *prefix;
1832 struct strbuf buf = STRBUF_INIT;
1833 int ret = 0, namespace_len;
1834
1835 find_longest_prefixes(&prefixes, patterns);
1836
1837 if (namespace)
1838 strbuf_addstr(&buf, namespace);
1839 namespace_len = buf.len;
1840
1841 for_each_string_list_item(prefix, &prefixes) {
1842 strbuf_addstr(&buf, prefix->string);
Taylor Blaub269ac52023-07-10 17:12:22 -04001843 ret = refs_for_each_fullref_in(ref_store, buf.buf,
1844 exclude_patterns, fn, cb_data);
Taylor Blau16b19852021-01-20 11:04:21 -05001845 if (ret)
1846 break;
1847 strbuf_setlen(&buf, namespace_len);
1848 }
1849
1850 string_list_clear(&prefixes, 0);
1851 strbuf_release(&buf);
1852 return ret;
1853}
1854
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001855static int refs_read_special_head(struct ref_store *ref_store,
1856 const char *refname, struct object_id *oid,
Han-Wen Nienhuysdf3458e2021-10-16 11:39:10 +02001857 struct strbuf *referent, unsigned int *type,
1858 int *failure_errno)
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001859{
1860 struct strbuf full_path = STRBUF_INIT;
1861 struct strbuf content = STRBUF_INIT;
1862 int result = -1;
1863 strbuf_addf(&full_path, "%s/%s", ref_store->gitdir, refname);
1864
Patrick Steinhardt668cdc02023-12-14 14:37:02 +01001865 if (strbuf_read_file(&content, full_path.buf, 0) < 0) {
1866 *failure_errno = errno;
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001867 goto done;
Patrick Steinhardt668cdc02023-12-14 14:37:02 +01001868 }
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001869
Han-Wen Nienhuysdf3458e2021-10-16 11:39:10 +02001870 result = parse_loose_ref_contents(content.buf, oid, referent, type,
1871 failure_errno);
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001872
1873done:
1874 strbuf_release(&full_path);
1875 strbuf_release(&content);
1876 return result;
1877}
1878
Patrick Steinhardt70c70de2023-12-14 14:37:06 +01001879static int is_special_ref(const char *refname)
1880{
1881 /*
Patrick Steinhardt2cd33f42024-01-19 11:40:24 +01001882 * Special references are refs that have different semantics compared
1883 * to "normal" refs. These refs can thus not be stored in the ref
1884 * backend, but must always be accessed via the filesystem. The
1885 * following refs are special:
Patrick Steinhardt70c70de2023-12-14 14:37:06 +01001886 *
1887 * - FETCH_HEAD may contain multiple object IDs, and each one of them
1888 * carries additional metadata like where it came from.
1889 *
1890 * - MERGE_HEAD may contain multiple object IDs when merging multiple
1891 * heads.
1892 *
Patrick Steinhardt2cd33f42024-01-19 11:40:24 +01001893 * Reading, writing or deleting references must consistently go either
1894 * through the filesystem (special refs) or through the reference
1895 * backend (normal ones).
Patrick Steinhardt70c70de2023-12-14 14:37:06 +01001896 */
1897 static const char * const special_refs[] = {
Patrick Steinhardt70c70de2023-12-14 14:37:06 +01001898 "FETCH_HEAD",
Patrick Steinhardt70c70de2023-12-14 14:37:06 +01001899 "MERGE_HEAD",
1900 };
1901 size_t i;
1902
1903 for (i = 0; i < ARRAY_SIZE(special_refs); i++)
1904 if (!strcmp(refname, special_refs[i]))
1905 return 1;
1906
1907 return 0;
1908}
1909
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001910int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
1911 struct object_id *oid, struct strbuf *referent,
1912 unsigned int *type, int *failure_errno)
Michael Haggerty470be512017-03-20 17:33:07 +01001913{
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001914 assert(failure_errno);
Patrick Steinhardt70c70de2023-12-14 14:37:06 +01001915 if (is_special_ref(refname))
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001916 return refs_read_special_head(ref_store, refname, oid, referent,
Han-Wen Nienhuysdf3458e2021-10-16 11:39:10 +02001917 type, failure_errno);
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001918
1919 return ref_store->be->read_raw_ref(ref_store, refname, oid, referent,
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001920 type, failure_errno);
Michael Haggerty470be512017-03-20 17:33:07 +01001921}
1922
Patrick Steinhardtcd475b32022-03-01 10:33:46 +01001923int refs_read_symbolic_ref(struct ref_store *ref_store, const char *refname,
1924 struct strbuf *referent)
1925{
Ævar Arnfjörð Bjarmason5b875402022-03-17 18:27:19 +01001926 return ref_store->be->read_symbolic_ref(ref_store, refname, referent);
Patrick Steinhardtcd475b32022-03-01 10:33:46 +01001927}
1928
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001929const char *refs_resolve_ref_unsafe(struct ref_store *refs,
Michael Haggerty3c0cb0c2017-02-09 21:53:52 +01001930 const char *refname,
1931 int resolve_flags,
Ævar Arnfjörð Bjarmasonef181192021-10-16 11:39:08 +02001932 struct object_id *oid,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001933 int *flags)
David Turner2d0663b2016-04-07 15:03:10 -04001934{
1935 static struct strbuf sb_refname = STRBUF_INIT;
René Scharfe54fad662017-09-23 11:41:45 +02001936 struct object_id unused_oid;
David Turner2d0663b2016-04-07 15:03:10 -04001937 int unused_flags;
1938 int symref_count;
1939
brian m. carlson49e61472017-10-15 22:07:09 +00001940 if (!oid)
1941 oid = &unused_oid;
David Turner2d0663b2016-04-07 15:03:10 -04001942 if (!flags)
1943 flags = &unused_flags;
1944
1945 *flags = 0;
1946
1947 if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
1948 if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001949 !refname_is_safe(refname))
David Turner2d0663b2016-04-07 15:03:10 -04001950 return NULL;
David Turner2d0663b2016-04-07 15:03:10 -04001951
1952 /*
Ævar Arnfjörð Bjarmasonc7c33f52023-03-28 15:58:57 +02001953 * repo_dwim_ref() uses REF_ISBROKEN to distinguish between
David Turner2d0663b2016-04-07 15:03:10 -04001954 * missing refs and refs that were present but invalid,
1955 * to complain about the latter to stderr.
1956 *
1957 * We don't know whether the ref exists, so don't set
1958 * REF_ISBROKEN yet.
1959 */
1960 *flags |= REF_BAD_NAME;
1961 }
1962
1963 for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
1964 unsigned int read_flags = 0;
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001965 int failure_errno;
David Turner2d0663b2016-04-07 15:03:10 -04001966
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001967 if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001968 &read_flags, &failure_errno)) {
David Turner2d0663b2016-04-07 15:03:10 -04001969 *flags |= read_flags;
Jeff Kinga1c1d812017-10-06 10:42:17 -04001970
1971 /* In reading mode, refs must eventually resolve */
1972 if (resolve_flags & RESOLVE_REF_READING)
David Turner2d0663b2016-04-07 15:03:10 -04001973 return NULL;
Jeff Kinga1c1d812017-10-06 10:42:17 -04001974
1975 /*
1976 * Otherwise a missing ref is OK. But the files backend
1977 * may show errors besides ENOENT if there are
1978 * similarly-named refs.
1979 */
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001980 if (failure_errno != ENOENT &&
1981 failure_errno != EISDIR &&
1982 failure_errno != ENOTDIR)
Jeff Kinga1c1d812017-10-06 10:42:17 -04001983 return NULL;
1984
brian m. carlson49e61472017-10-15 22:07:09 +00001985 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001986 if (*flags & REF_BAD_NAME)
1987 *flags |= REF_ISBROKEN;
1988 return refname;
1989 }
1990
1991 *flags |= read_flags;
1992
1993 if (!(read_flags & REF_ISSYMREF)) {
1994 if (*flags & REF_BAD_NAME) {
brian m. carlson49e61472017-10-15 22:07:09 +00001995 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001996 *flags |= REF_ISBROKEN;
1997 }
1998 return refname;
1999 }
2000
2001 refname = sb_refname.buf;
2002 if (resolve_flags & RESOLVE_REF_NO_RECURSE) {
brian m. carlson49e61472017-10-15 22:07:09 +00002003 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04002004 return refname;
2005 }
2006 if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
2007 if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01002008 !refname_is_safe(refname))
David Turner2d0663b2016-04-07 15:03:10 -04002009 return NULL;
David Turner2d0663b2016-04-07 15:03:10 -04002010
2011 *flags |= REF_ISBROKEN | REF_BAD_NAME;
2012 }
2013 }
2014
David Turner2d0663b2016-04-07 15:03:10 -04002015 return NULL;
2016}
Michael Haggerty00eebe32016-09-04 18:08:11 +02002017
David Turner6fb5acf2016-09-04 18:08:41 +02002018/* backend functions */
Patrick Steinhardt2e573d62024-01-08 11:05:26 +01002019int refs_init_db(struct ref_store *refs, int flags, struct strbuf *err)
David Turner6fb5acf2016-09-04 18:08:41 +02002020{
Patrick Steinhardt2e573d62024-01-08 11:05:26 +01002021 return refs->be->init_db(refs, flags, err);
David Turner6fb5acf2016-09-04 18:08:41 +02002022}
2023
Michael Haggertybd40dcd2016-09-04 18:08:21 +02002024const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
brian m. carlson49e61472017-10-15 22:07:09 +00002025 struct object_id *oid, int *flags)
Michael Haggertybd40dcd2016-09-04 18:08:21 +02002026{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002027 return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01002028 resolve_flags, oid, flags);
Michael Haggertybd40dcd2016-09-04 18:08:21 +02002029}
2030
Michael Haggertya8355bb2016-09-04 18:08:24 +02002031int resolve_gitlink_ref(const char *submodule, const char *refname,
brian m. carlsona98e6102017-10-15 22:07:07 +00002032 struct object_id *oid)
Michael Haggerty424dcc72016-09-04 18:08:22 +02002033{
Michael Haggerty424dcc72016-09-04 18:08:22 +02002034 struct ref_store *refs;
2035 int flags;
2036
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07002037 refs = get_submodule_ref_store(submodule);
Michael Haggerty48a84752016-09-04 18:08:23 +02002038
Michael Haggerty424dcc72016-09-04 18:08:22 +02002039 if (!refs)
2040 return -1;
2041
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01002042 if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags) ||
2043 is_null_oid(oid))
Michael Haggerty424dcc72016-09-04 18:08:22 +02002044 return -1;
2045 return 0;
2046}
2047
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002048struct ref_store_hash_entry
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002049{
Eric Wonge2b50382019-10-06 23:30:43 +00002050 struct hashmap_entry ent;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002051
2052 struct ref_store *refs;
2053
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002054 /* NUL-terminated identifier of the ref store: */
2055 char name[FLEX_ARRAY];
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002056};
2057
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02002058static int ref_store_hash_cmp(const void *cmp_data UNUSED,
Eric Wong939af162019-10-06 23:30:37 +00002059 const struct hashmap_entry *eptr,
2060 const struct hashmap_entry *entry_or_key,
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002061 const void *keydata)
2062{
Eric Wong939af162019-10-06 23:30:37 +00002063 const struct ref_store_hash_entry *e1, *e2;
2064 const char *name;
2065
2066 e1 = container_of(eptr, const struct ref_store_hash_entry, ent);
2067 e2 = container_of(entry_or_key, const struct ref_store_hash_entry, ent);
2068 name = keydata ? keydata : e2->name;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002069
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002070 return strcmp(e1->name, name);
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002071}
2072
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002073static struct ref_store_hash_entry *alloc_ref_store_hash_entry(
2074 const char *name, struct ref_store *refs)
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002075{
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002076 struct ref_store_hash_entry *entry;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002077
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002078 FLEX_ALLOC_STR(entry, name, name);
Eric Wongd22245a2019-10-06 23:30:27 +00002079 hashmap_entry_init(&entry->ent, strhash(name));
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002080 entry->refs = refs;
2081 return entry;
2082}
2083
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002084/* A hashmap of ref_stores, stored by submodule name: */
2085static struct hashmap submodule_ref_stores;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002086
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07002087/* A hashmap of ref_stores, stored by worktree id: */
2088static struct hashmap worktree_ref_stores;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002089
Michael Haggerty00eebe32016-09-04 18:08:11 +02002090/*
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002091 * Look up a ref store by name. If that ref_store hasn't been
2092 * registered yet, return NULL.
Michael Haggerty00eebe32016-09-04 18:08:11 +02002093 */
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002094static struct ref_store *lookup_ref_store_map(struct hashmap *map,
2095 const char *name)
Michael Haggerty00eebe32016-09-04 18:08:11 +02002096{
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002097 struct ref_store_hash_entry *entry;
Eric Wongf23a4652019-10-06 23:30:36 +00002098 unsigned int hash;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002099
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002100 if (!map->tablesize)
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002101 /* It's initialized on demand in register_ref_store(). */
2102 return NULL;
Michael Haggerty620a66b2017-02-10 12:16:11 +01002103
Eric Wongf23a4652019-10-06 23:30:36 +00002104 hash = strhash(name);
2105 entry = hashmap_get_entry_from_hash(map, hash, name,
2106 struct ref_store_hash_entry, ent);
Michael Haggerty7d4558c2017-02-10 12:16:15 +01002107 return entry ? entry->refs : NULL;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002108}
2109
Michael Haggertyc468da42017-02-10 12:16:12 +01002110/*
2111 * Create, record, and return a ref_store instance for the specified
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07002112 * gitdir.
Michael Haggertyc468da42017-02-10 12:16:12 +01002113 */
Jonathan Tan34224e12021-10-08 14:08:14 -07002114static struct ref_store *ref_store_init(struct repository *repo,
2115 const char *gitdir,
Nguyễn Thái Ngọc Duy9e7ec632017-03-26 09:42:32 +07002116 unsigned int flags)
Michael Haggerty00eebe32016-09-04 18:08:11 +02002117{
Patrick Steinhardt173761e2023-12-29 08:26:39 +01002118 const struct ref_storage_be *be;
Michael Haggertyba88add2017-02-10 12:16:14 +01002119 struct ref_store *refs;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002120
Patrick Steinhardt173761e2023-12-29 08:26:39 +01002121 be = find_ref_storage_backend(repo->ref_storage_format);
Michael Haggerty00eebe32016-09-04 18:08:11 +02002122 if (!be)
Patrick Steinhardt0fcc2852023-12-29 08:26:34 +01002123 BUG("reference backend is unknown");
Michael Haggerty00eebe32016-09-04 18:08:11 +02002124
Jonathan Tan34224e12021-10-08 14:08:14 -07002125 refs = be->init(repo, gitdir, flags);
Michael Haggertyba88add2017-02-10 12:16:14 +01002126 return refs;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002127}
2128
Stefan Beller64a74162018-04-11 17:21:14 -07002129struct ref_store *get_main_ref_store(struct repository *r)
Michael Haggerty00eebe32016-09-04 18:08:11 +02002130{
Jeff King02204612020-04-09 23:04:11 -04002131 if (r->refs_private)
2132 return r->refs_private;
Nguyễn Thái Ngọc Duy24c84072017-03-26 09:42:25 +07002133
Jeff King2dc417a2018-05-18 15:25:53 -07002134 if (!r->gitdir)
2135 BUG("attempting to get main_ref_store outside of repository");
2136
Jonathan Tan34224e12021-10-08 14:08:14 -07002137 r->refs_private = ref_store_init(r, r->gitdir, REF_STORE_ALL_CAPS);
Han-Wen Nienhuys4441f422020-09-09 10:15:08 +00002138 r->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private);
Jeff King02204612020-04-09 23:04:11 -04002139 return r->refs_private;
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07002140}
2141
2142/*
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002143 * Associate a ref store with a name. It is a fatal error to call this
2144 * function twice for the same name.
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07002145 */
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002146static void register_ref_store_map(struct hashmap *map,
2147 const char *type,
2148 struct ref_store *refs,
2149 const char *name)
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07002150{
Eric Wong26b455f2019-10-06 23:30:32 +00002151 struct ref_store_hash_entry *entry;
2152
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002153 if (!map->tablesize)
Stefan Beller7663cdc2017-06-30 12:14:05 -07002154 hashmap_init(map, ref_store_hash_cmp, NULL, 0);
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07002155
Eric Wong26b455f2019-10-06 23:30:32 +00002156 entry = alloc_ref_store_hash_entry(name, refs);
2157 if (hashmap_put(map, &entry->ent))
Johannes Schindelin033abf92018-05-02 11:38:39 +02002158 BUG("%s ref_store '%s' initialized twice", type, name);
Nguyễn Thái Ngọc Duy24c84072017-03-26 09:42:25 +07002159}
2160
Nguyễn Thái Ngọc Duy18d00022017-03-26 09:42:33 +07002161struct ref_store *get_submodule_ref_store(const char *submodule)
Michael Haggerty00eebe32016-09-04 18:08:11 +02002162{
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07002163 struct strbuf submodule_sb = STRBUF_INIT;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002164 struct ref_store *refs;
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07002165 char *to_free = NULL;
2166 size_t len;
Jonathan Tan34224e12021-10-08 14:08:14 -07002167 struct repository *subrepo;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002168
Nguyễn Thái Ngọc Duy82a150f2017-08-23 19:37:03 +07002169 if (!submodule)
2170 return NULL;
2171
Nguyễn Thái Ngọc Duy873ea902017-08-23 19:37:04 +07002172 len = strlen(submodule);
2173 while (len && is_dir_sep(submodule[len - 1]))
2174 len--;
2175 if (!len)
2176 return NULL;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002177
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07002178 if (submodule[len])
2179 /* We need to strip off one or more trailing slashes */
2180 submodule = to_free = xmemdupz(submodule, len);
Michael Haggerty00eebe32016-09-04 18:08:11 +02002181
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002182 refs = lookup_ref_store_map(&submodule_ref_stores, submodule);
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07002183 if (refs)
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07002184 goto done;
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07002185
2186 strbuf_addstr(&submodule_sb, submodule);
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07002187 if (!is_nonbare_repository_dir(&submodule_sb))
2188 goto done;
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07002189
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07002190 if (submodule_to_gitdir(&submodule_sb, submodule))
2191 goto done;
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07002192
Jonathan Tan34224e12021-10-08 14:08:14 -07002193 subrepo = xmalloc(sizeof(*subrepo));
2194 /*
2195 * NEEDSWORK: Make get_submodule_ref_store() work with arbitrary
2196 * superprojects other than the_repository. This probably should be
2197 * done by making it take a struct repository * parameter instead of a
2198 * submodule path.
2199 */
2200 if (repo_submodule_init(subrepo, the_repository, submodule,
2201 null_oid())) {
2202 free(subrepo);
2203 goto done;
2204 }
2205 refs = ref_store_init(subrepo, submodule_sb.buf,
Nguyễn Thái Ngọc Duy9e7ec632017-03-26 09:42:32 +07002206 REF_STORE_READ | REF_STORE_ODB);
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002207 register_ref_store_map(&submodule_ref_stores, "submodule",
2208 refs, submodule);
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07002209
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07002210done:
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07002211 strbuf_release(&submodule_sb);
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07002212 free(to_free);
2213
Michael Haggerty00eebe32016-09-04 18:08:11 +02002214 return refs;
2215}
2216
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07002217struct ref_store *get_worktree_ref_store(const struct worktree *wt)
2218{
2219 struct ref_store *refs;
2220 const char *id;
2221
2222 if (wt->is_current)
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002223 return get_main_ref_store(the_repository);
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07002224
2225 id = wt->id ? wt->id : "/";
2226 refs = lookup_ref_store_map(&worktree_ref_stores, id);
2227 if (refs)
2228 return refs;
2229
2230 if (wt->id)
Jonathan Tan34224e12021-10-08 14:08:14 -07002231 refs = ref_store_init(the_repository,
2232 git_common_path("worktrees/%s", wt->id),
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07002233 REF_STORE_ALL_CAPS);
2234 else
Jonathan Tan34224e12021-10-08 14:08:14 -07002235 refs = ref_store_init(the_repository,
2236 get_git_common_dir(),
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07002237 REF_STORE_ALL_CAPS);
2238
2239 if (refs)
2240 register_ref_store_map(&worktree_ref_stores, "worktree",
2241 refs, id);
2242 return refs;
2243}
2244
Han-Wen Nienhuysf9f7fd32021-12-22 18:11:54 +00002245void base_ref_store_init(struct ref_store *refs, struct repository *repo,
2246 const char *path, const struct ref_storage_be *be)
Michael Haggerty00eebe32016-09-04 18:08:11 +02002247{
Michael Haggerty620a66b2017-02-10 12:16:11 +01002248 refs->be = be;
Han-Wen Nienhuysf9f7fd32021-12-22 18:11:54 +00002249 refs->repo = repo;
2250 refs->gitdir = xstrdup(path);
Michael Haggerty00eebe32016-09-04 18:08:11 +02002251}
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002252
2253/* backend functions */
John Cai826ae792023-05-12 21:34:41 +00002254int refs_pack_refs(struct ref_store *refs, struct pack_refs_opts *opts)
Michael Haggerty82315272016-09-04 18:08:27 +02002255{
John Cai826ae792023-05-12 21:34:41 +00002256 return refs->be->pack_refs(refs, opts);
Michael Haggerty82315272016-09-04 18:08:27 +02002257}
2258
Jeff King36a31792021-01-20 14:44:43 -05002259int peel_iterated_oid(const struct object_id *base, struct object_id *peeled)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002260{
Jeff King36a31792021-01-20 14:44:43 -05002261 if (current_ref_iter &&
2262 (current_ref_iter->oid == base ||
2263 oideq(current_ref_iter->oid, base)))
2264 return ref_iterator_peel(current_ref_iter, peeled);
Michael Haggertyba1c0522017-09-25 10:00:14 +02002265
Han-Wen Nienhuys617480d2021-05-19 15:31:28 +00002266 return peel_object(base, peeled) ? -1 : 0;
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002267}
Michael Haggertybd427cf2016-09-04 18:08:29 +02002268
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002269int refs_create_symref(struct ref_store *refs,
2270 const char *ref_target,
2271 const char *refs_heads_master,
2272 const char *logmsg)
2273{
Junio C Hamano523fa692020-07-10 17:19:53 +00002274 char *msg;
2275 int retval;
2276
2277 msg = normalize_reflog_message(logmsg);
2278 retval = refs->be->create_symref(refs, ref_target, refs_heads_master,
2279 msg);
2280 free(msg);
2281 return retval;
Michael Haggertybd427cf2016-09-04 18:08:29 +02002282}
2283
Michael Haggerty284689b2016-09-04 18:08:28 +02002284int create_symref(const char *ref_target, const char *refs_heads_master,
2285 const char *logmsg)
2286{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002287 return refs_create_symref(get_main_ref_store(the_repository), ref_target,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002288 refs_heads_master, logmsg);
Michael Haggerty284689b2016-09-04 18:08:28 +02002289}
2290
Michael Haggerty2ced1052017-05-22 16:17:45 +02002291int ref_update_reject_duplicates(struct string_list *refnames,
2292 struct strbuf *err)
2293{
Michael Haggertya552e502017-05-22 16:17:46 +02002294 size_t i, n = refnames->nr;
Michael Haggerty2ced1052017-05-22 16:17:45 +02002295
2296 assert(err);
2297
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002298 for (i = 1; i < n; i++) {
2299 int cmp = strcmp(refnames->items[i - 1].string,
2300 refnames->items[i].string);
2301
2302 if (!cmp) {
Michael Haggerty2ced1052017-05-22 16:17:45 +02002303 strbuf_addf(err,
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002304 _("multiple updates for ref '%s' not allowed"),
Michael Haggerty2ced1052017-05-22 16:17:45 +02002305 refnames->items[i].string);
2306 return 1;
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002307 } else if (cmp > 0) {
Johannes Schindelin033abf92018-05-02 11:38:39 +02002308 BUG("ref_update_reject_duplicates() received unsorted list");
Michael Haggerty2ced1052017-05-22 16:17:45 +02002309 }
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002310 }
Michael Haggerty2ced1052017-05-22 16:17:45 +02002311 return 0;
2312}
2313
Patrick Steinhardt67541592020-06-19 08:56:14 +02002314static int run_transaction_hook(struct ref_transaction *transaction,
2315 const char *state)
2316{
2317 struct child_process proc = CHILD_PROCESS_INIT;
2318 struct strbuf buf = STRBUF_INIT;
Patrick Steinhardt0a0fbbe2020-08-25 12:35:24 +02002319 const char *hook;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002320 int ret = 0, i;
2321
Patrick Steinhardt0a0fbbe2020-08-25 12:35:24 +02002322 hook = find_hook("reference-transaction");
Patrick Steinhardt67541592020-06-19 08:56:14 +02002323 if (!hook)
Patrick Steinhardt67541592020-06-19 08:56:14 +02002324 return ret;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002325
Jeff Kingc972bf42020-07-28 16:25:12 -04002326 strvec_pushl(&proc.args, hook, state, NULL);
Patrick Steinhardt67541592020-06-19 08:56:14 +02002327 proc.in = -1;
2328 proc.stdout_to_stderr = 1;
2329 proc.trace2_hook_name = "reference-transaction";
2330
2331 ret = start_command(&proc);
2332 if (ret)
2333 return ret;
2334
2335 sigchain_push(SIGPIPE, SIG_IGN);
2336
2337 for (i = 0; i < transaction->nr; i++) {
2338 struct ref_update *update = transaction->updates[i];
2339
2340 strbuf_reset(&buf);
2341 strbuf_addf(&buf, "%s %s %s\n",
2342 oid_to_hex(&update->old_oid),
2343 oid_to_hex(&update->new_oid),
2344 update->refname);
2345
2346 if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
Ævar Arnfjörð Bjarmason4755d7d2021-10-16 11:39:25 +02002347 if (errno != EPIPE) {
2348 /* Don't leak errno outside this API */
2349 errno = 0;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002350 ret = -1;
Ævar Arnfjörð Bjarmason4755d7d2021-10-16 11:39:25 +02002351 }
Patrick Steinhardt67541592020-06-19 08:56:14 +02002352 break;
2353 }
2354 }
2355
2356 close(proc.in);
2357 sigchain_pop(SIGPIPE);
2358 strbuf_release(&buf);
2359
2360 ret |= finish_command(&proc);
2361 return ret;
2362}
2363
Michael Haggerty30173b82017-05-22 16:17:44 +02002364int ref_transaction_prepare(struct ref_transaction *transaction,
2365 struct strbuf *err)
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002366{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07002367 struct ref_store *refs = transaction->ref_store;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002368 int ret;
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002369
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002370 switch (transaction->state) {
2371 case REF_TRANSACTION_OPEN:
2372 /* Good. */
2373 break;
Michael Haggerty30173b82017-05-22 16:17:44 +02002374 case REF_TRANSACTION_PREPARED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002375 BUG("prepare called twice on reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002376 break;
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002377 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002378 BUG("prepare called on a closed reference transaction");
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002379 break;
2380 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002381 BUG("unexpected reference transaction state");
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002382 break;
2383 }
2384
Neeraj Singhecd81df2021-12-06 22:05:05 +00002385 if (refs->repo->objects->odb->disable_ref_updates) {
Jeff Kingd8f44812017-04-10 18:14:12 -04002386 strbuf_addstr(err,
2387 _("ref updates forbidden inside quarantine environment"));
2388 return -1;
2389 }
2390
Patrick Steinhardt67541592020-06-19 08:56:14 +02002391 ret = refs->be->transaction_prepare(refs, transaction, err);
2392 if (ret)
2393 return ret;
2394
2395 ret = run_transaction_hook(transaction, "prepared");
2396 if (ret) {
2397 ref_transaction_abort(transaction, err);
2398 die(_("ref updates aborted by hook"));
2399 }
2400
2401 return 0;
Michael Haggerty30173b82017-05-22 16:17:44 +02002402}
2403
2404int ref_transaction_abort(struct ref_transaction *transaction,
2405 struct strbuf *err)
2406{
2407 struct ref_store *refs = transaction->ref_store;
2408 int ret = 0;
2409
2410 switch (transaction->state) {
2411 case REF_TRANSACTION_OPEN:
2412 /* No need to abort explicitly. */
2413 break;
2414 case REF_TRANSACTION_PREPARED:
2415 ret = refs->be->transaction_abort(refs, transaction, err);
2416 break;
2417 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002418 BUG("abort called on a closed reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002419 break;
2420 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002421 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02002422 break;
2423 }
2424
Patrick Steinhardt67541592020-06-19 08:56:14 +02002425 run_transaction_hook(transaction, "aborted");
2426
Michael Haggerty30173b82017-05-22 16:17:44 +02002427 ref_transaction_free(transaction);
2428 return ret;
2429}
2430
2431int ref_transaction_commit(struct ref_transaction *transaction,
2432 struct strbuf *err)
2433{
2434 struct ref_store *refs = transaction->ref_store;
2435 int ret;
2436
2437 switch (transaction->state) {
2438 case REF_TRANSACTION_OPEN:
2439 /* Need to prepare first. */
2440 ret = ref_transaction_prepare(transaction, err);
2441 if (ret)
2442 return ret;
2443 break;
2444 case REF_TRANSACTION_PREPARED:
2445 /* Fall through to finish. */
2446 break;
2447 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002448 BUG("commit called on a closed reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002449 break;
2450 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002451 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02002452 break;
2453 }
2454
Patrick Steinhardt67541592020-06-19 08:56:14 +02002455 ret = refs->be->transaction_finish(refs, transaction, err);
2456 if (!ret)
2457 run_transaction_hook(transaction, "committed");
2458 return ret;
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002459}
Michael Haggerty62665822016-09-04 18:08:26 +02002460
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002461int refs_verify_refname_available(struct ref_store *refs,
2462 const char *refname,
Michael Haggertyb05855b2017-04-16 08:41:26 +02002463 const struct string_list *extras,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002464 const struct string_list *skip,
2465 struct strbuf *err)
Michael Haggerty62665822016-09-04 18:08:26 +02002466{
Michael Haggertyb05855b2017-04-16 08:41:26 +02002467 const char *slash;
2468 const char *extra_refname;
2469 struct strbuf dirname = STRBUF_INIT;
2470 struct strbuf referent = STRBUF_INIT;
2471 struct object_id oid;
2472 unsigned int type;
2473 struct ref_iterator *iter;
2474 int ok;
2475 int ret = -1;
2476
2477 /*
2478 * For the sake of comments in this function, suppose that
2479 * refname is "refs/foo/bar".
2480 */
2481
2482 assert(err);
2483
2484 strbuf_grow(&dirname, strlen(refname) + 1);
2485 for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02002486 /*
2487 * Just saying "Is a directory" when we e.g. can't
2488 * lock some multi-level ref isn't very informative,
2489 * the user won't be told *what* is a directory, so
2490 * let's not use strerror() below.
2491 */
2492 int ignore_errno;
Michael Haggertyb05855b2017-04-16 08:41:26 +02002493 /* Expand dirname to the new prefix, not including the trailing slash: */
2494 strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
2495
2496 /*
2497 * We are still at a leading dir of the refname (e.g.,
2498 * "refs/foo"; if there is a reference with that name,
2499 * it is a conflict, *unless* it is in skip.
2500 */
2501 if (skip && string_list_has_string(skip, dirname.buf))
2502 continue;
2503
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02002504 if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent,
2505 &type, &ignore_errno)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002506 strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002507 dirname.buf, refname);
2508 goto cleanup;
2509 }
2510
2511 if (extras && string_list_has_string(extras, dirname.buf)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002512 strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002513 refname, dirname.buf);
2514 goto cleanup;
2515 }
2516 }
2517
2518 /*
2519 * We are at the leaf of our refname (e.g., "refs/foo/bar").
2520 * There is no point in searching for a reference with that
2521 * name, because a refname isn't considered to conflict with
2522 * itself. But we still need to check for references whose
2523 * names are in the "refs/foo/bar/" namespace, because they
2524 * *do* conflict.
2525 */
2526 strbuf_addstr(&dirname, refname + dirname.len);
2527 strbuf_addch(&dirname, '/');
2528
Taylor Blaub269ac52023-07-10 17:12:22 -04002529 iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0,
Michael Haggertyb05855b2017-04-16 08:41:26 +02002530 DO_FOR_EACH_INCLUDE_BROKEN);
2531 while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
2532 if (skip &&
2533 string_list_has_string(skip, iter->refname))
2534 continue;
2535
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002536 strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002537 iter->refname, refname);
2538 ref_iterator_abort(iter);
2539 goto cleanup;
2540 }
2541
2542 if (ok != ITER_DONE)
Johannes Schindelin033abf92018-05-02 11:38:39 +02002543 BUG("error while iterating over references");
Michael Haggertyb05855b2017-04-16 08:41:26 +02002544
2545 extra_refname = find_descendant_ref(dirname.buf, extras, skip);
2546 if (extra_refname)
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002547 strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002548 refname, extra_refname);
2549 else
2550 ret = 0;
2551
2552cleanup:
2553 strbuf_release(&referent);
2554 strbuf_release(&dirname);
2555 return ret;
Michael Haggerty62665822016-09-04 18:08:26 +02002556}
David Turnere3688bd2016-09-04 18:08:38 +02002557
Patrick Steinhardt31f89832024-02-21 13:37:39 +01002558struct do_for_each_reflog_help {
2559 each_reflog_fn *fn;
2560 void *cb_data;
2561};
2562
2563static int do_for_each_reflog_helper(struct repository *r UNUSED,
2564 const char *refname,
2565 const struct object_id *oid UNUSED,
2566 int flags,
2567 void *cb_data)
2568{
2569 struct do_for_each_reflog_help *hp = cb_data;
2570 return hp->fn(refname, hp->cb_data);
2571}
2572
2573int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_data)
David Turnere3688bd2016-09-04 18:08:38 +02002574{
David Turnere3688bd2016-09-04 18:08:38 +02002575 struct ref_iterator *iter;
Patrick Steinhardt31f89832024-02-21 13:37:39 +01002576 struct do_for_each_reflog_help hp = { fn, cb_data };
David Turnere3688bd2016-09-04 18:08:38 +02002577
2578 iter = refs->be->reflog_iterator_begin(refs);
2579
Stefan Beller4a6067c2018-08-20 18:24:16 +00002580 return do_for_each_repo_ref_iterator(the_repository, iter,
Patrick Steinhardt31f89832024-02-21 13:37:39 +01002581 do_for_each_reflog_helper, &hp);
David Turnere3688bd2016-09-04 18:08:38 +02002582}
2583
Patrick Steinhardt31f89832024-02-21 13:37:39 +01002584int for_each_reflog(each_reflog_fn fn, void *cb_data)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002585{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002586 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 +07002587}
2588
2589int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
2590 const char *refname,
2591 each_reflog_ent_fn fn,
2592 void *cb_data)
2593{
2594 return refs->be->for_each_reflog_ent_reverse(refs, refname,
2595 fn, cb_data);
2596}
2597
David Turnere3688bd2016-09-04 18:08:38 +02002598int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
2599 void *cb_data)
2600{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002601 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 +07002602 refname, fn, cb_data);
2603}
David Turnere3688bd2016-09-04 18:08:38 +02002604
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002605int refs_for_each_reflog_ent(struct ref_store *refs, const char *refname,
2606 each_reflog_ent_fn fn, void *cb_data)
2607{
2608 return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002609}
2610
2611int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
2612 void *cb_data)
2613{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002614 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 +07002615 fn, cb_data);
2616}
David Turnere3688bd2016-09-04 18:08:38 +02002617
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002618int refs_reflog_exists(struct ref_store *refs, const char *refname)
2619{
2620 return refs->be->reflog_exists(refs, refname);
David Turnere3688bd2016-09-04 18:08:38 +02002621}
2622
2623int reflog_exists(const char *refname)
2624{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002625 return refs_reflog_exists(get_main_ref_store(the_repository), refname);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002626}
David Turnere3688bd2016-09-04 18:08:38 +02002627
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002628int refs_create_reflog(struct ref_store *refs, const char *refname,
David Turnere3688bd2016-09-04 18:08:38 +02002629 struct strbuf *err)
2630{
Han-Wen Nienhuys7b089122021-11-22 14:19:08 +00002631 return refs->be->create_reflog(refs, refname, err);
2632}
2633
2634int safe_create_reflog(const char *refname, struct strbuf *err)
2635{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002636 return refs_create_reflog(get_main_ref_store(the_repository), refname,
Han-Wen Nienhuys7b089122021-11-22 14:19:08 +00002637 err);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002638}
David Turnere3688bd2016-09-04 18:08:38 +02002639
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002640int refs_delete_reflog(struct ref_store *refs, const char *refname)
2641{
2642 return refs->be->delete_reflog(refs, refname);
David Turnere3688bd2016-09-04 18:08:38 +02002643}
2644
2645int delete_reflog(const char *refname)
2646{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002647 return refs_delete_reflog(get_main_ref_store(the_repository), refname);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002648}
David Turnere3688bd2016-09-04 18:08:38 +02002649
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002650int refs_reflog_expire(struct ref_store *refs,
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002651 const char *refname,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002652 unsigned int flags,
2653 reflog_expiry_prepare_fn prepare_fn,
2654 reflog_expiry_should_prune_fn should_prune_fn,
2655 reflog_expiry_cleanup_fn cleanup_fn,
2656 void *policy_cb_data)
2657{
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002658 return refs->be->reflog_expire(refs, refname, flags,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002659 prepare_fn, should_prune_fn,
2660 cleanup_fn, policy_cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002661}
2662
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002663int reflog_expire(const char *refname,
David Turnere3688bd2016-09-04 18:08:38 +02002664 unsigned int flags,
2665 reflog_expiry_prepare_fn prepare_fn,
2666 reflog_expiry_should_prune_fn should_prune_fn,
2667 reflog_expiry_cleanup_fn cleanup_fn,
2668 void *policy_cb_data)
2669{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002670 return refs_reflog_expire(get_main_ref_store(the_repository),
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002671 refname, flags,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002672 prepare_fn, should_prune_fn,
2673 cleanup_fn, policy_cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002674}
David Turnerfc681462016-09-04 18:08:39 +02002675
2676int initial_ref_transaction_commit(struct ref_transaction *transaction,
2677 struct strbuf *err)
2678{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07002679 struct ref_store *refs = transaction->ref_store;
David Turnerfc681462016-09-04 18:08:39 +02002680
2681 return refs->be->initial_transaction_commit(refs, transaction, err);
2682}
David Turnera27dcf82016-09-04 18:08:40 +02002683
Patrick Steinhardt4f2ba2d2022-02-17 14:04:32 +01002684void ref_transaction_for_each_queued_update(struct ref_transaction *transaction,
2685 ref_transaction_for_each_queued_update_fn cb,
2686 void *cb_data)
2687{
2688 int i;
2689
2690 for (i = 0; i < transaction->nr; i++) {
2691 struct ref_update *update = transaction->updates[i];
2692
2693 cb(update->refname,
2694 (update->flags & REF_HAVE_OLD) ? &update->old_oid : NULL,
2695 (update->flags & REF_HAVE_NEW) ? &update->new_oid : NULL,
2696 cb_data);
2697 }
2698}
2699
Junio C Hamano523fa692020-07-10 17:19:53 +00002700int refs_delete_refs(struct ref_store *refs, const char *logmsg,
Michael Haggerty64da4192017-05-22 16:17:38 +02002701 struct string_list *refnames, unsigned int flags)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002702{
Patrick Steinhardtd6f8e722023-11-14 09:58:46 +01002703 struct ref_transaction *transaction;
2704 struct strbuf err = STRBUF_INIT;
2705 struct string_list_item *item;
2706 int ret = 0, failures = 0;
Junio C Hamano523fa692020-07-10 17:19:53 +00002707 char *msg;
Patrick Steinhardtd6f8e722023-11-14 09:58:46 +01002708
2709 if (!refnames->nr)
2710 return 0;
Junio C Hamano523fa692020-07-10 17:19:53 +00002711
2712 msg = normalize_reflog_message(logmsg);
Patrick Steinhardtd6f8e722023-11-14 09:58:46 +01002713
2714 /*
2715 * Since we don't check the references' old_oids, the
2716 * individual updates can't fail, so we can pack all of the
2717 * updates into a single transaction.
2718 */
2719 transaction = ref_store_transaction_begin(refs, &err);
2720 if (!transaction) {
2721 ret = error("%s", err.buf);
2722 goto out;
2723 }
2724
2725 for_each_string_list_item(item, refnames) {
2726 ret = ref_transaction_delete(transaction, item->string,
2727 NULL, flags, msg, &err);
2728 if (ret) {
2729 warning(_("could not delete reference %s: %s"),
2730 item->string, err.buf);
2731 strbuf_reset(&err);
2732 failures = 1;
2733 }
2734 }
2735
2736 ret = ref_transaction_commit(transaction, &err);
2737 if (ret) {
2738 if (refnames->nr == 1)
2739 error(_("could not delete reference %s: %s"),
2740 refnames->items[0].string, err.buf);
2741 else
2742 error(_("could not delete references: %s"), err.buf);
2743 }
2744
2745out:
2746 if (!ret && failures)
2747 ret = -1;
2748 ref_transaction_free(transaction);
2749 strbuf_release(&err);
Junio C Hamano523fa692020-07-10 17:19:53 +00002750 free(msg);
Patrick Steinhardtd6f8e722023-11-14 09:58:46 +01002751 return ret;
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002752}
2753
Michael Haggerty64da4192017-05-22 16:17:38 +02002754int delete_refs(const char *msg, struct string_list *refnames,
2755 unsigned int flags)
David Turnera27dcf82016-09-04 18:08:40 +02002756{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002757 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 +07002758}
David Turnera27dcf82016-09-04 18:08:40 +02002759
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002760int refs_rename_ref(struct ref_store *refs, const char *oldref,
2761 const char *newref, const char *logmsg)
2762{
Junio C Hamano523fa692020-07-10 17:19:53 +00002763 char *msg;
2764 int retval;
2765
2766 msg = normalize_reflog_message(logmsg);
2767 retval = refs->be->rename_ref(refs, oldref, newref, msg);
2768 free(msg);
2769 return retval;
David Turnera27dcf82016-09-04 18:08:40 +02002770}
David Turner9b6b40d2016-09-04 18:08:42 +02002771
2772int rename_ref(const char *oldref, const char *newref, const char *logmsg)
2773{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002774 return refs_rename_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
David Turner9b6b40d2016-09-04 18:08:42 +02002775}
Sahil Dua52d59cc2017-06-18 23:19:16 +02002776
2777int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
2778 const char *newref, const char *logmsg)
2779{
Junio C Hamano523fa692020-07-10 17:19:53 +00002780 char *msg;
2781 int retval;
2782
2783 msg = normalize_reflog_message(logmsg);
2784 retval = refs->be->copy_ref(refs, oldref, newref, msg);
2785 free(msg);
2786 return retval;
Sahil Dua52d59cc2017-06-18 23:19:16 +02002787}
2788
2789int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)
2790{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002791 return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
Sahil Dua52d59cc2017-06-18 23:19:16 +02002792}