blob: d2a98e1c21f4e9e0be61070aeec48446b0335efc [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"
Elijah Newren36bf1952023-02-24 00:09:24 +00007#include "alloc.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07008#include "config.h"
Elijah Newren32a8f512023-03-21 06:26:03 +00009#include "environment.h"
Michael Haggerty7d4558c2017-02-10 12:16:15 +010010#include "hashmap.h"
Elijah Newrenf394e092023-03-21 06:25:54 +000011#include "gettext.h"
Elijah Newren41771fa2023-02-24 00:09:27 +000012#include "hex.h"
Michael Haggerty697cc8e2014-10-01 12:28:42 +020013#include "lockfile.h"
Michael Haggertyb05855b2017-04-16 08:41:26 +020014#include "iterator.h"
Junio C Hamano85023572006-12-19 14:34:12 -080015#include "refs.h"
Michael Haggerty4cb77002015-11-10 12:42:36 +010016#include "refs/refs-internal.h"
Patrick Steinhardt67541592020-06-19 08:56:14 +020017#include "run-command.h"
Ævar Arnfjörð Bjarmason5e3aba32021-09-26 21:03:26 +020018#include "hook.h"
Elijah Newrendabab1d2023-04-11 00:41:49 -070019#include "object-name.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -070020#include "object-store.h"
Junio C Hamanocf0adba2006-11-19 13:22:44 -080021#include "object.h"
22#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 Newrend5ebb502023-03-21 06:26:01 +000031#include "wrapper.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 */
36static struct ref_storage_be *refs_backends = &refs_be_files;
37
38static struct ref_storage_be *find_ref_storage_backend(const char *name)
39{
40 struct ref_storage_be *be;
41 for (be = refs_backends; be; be = be->next)
42 if (!strcmp(be->name, name))
43 return be;
44 return NULL;
45}
46
Ronnie Sahlberg3dce4442016-09-04 18:08:10 +020047/*
David Turnerdde8a902014-06-03 23:38:10 -040048 * How to handle various characters in refnames:
49 * 0: An acceptable character for refs
Junio C Hamano5e650222014-07-28 10:41:53 -070050 * 1: End-of-component
51 * 2: ., look for a preceding . to reject .. in refs
52 * 3: {, look for a preceding @ to reject @{ in refs
Jacob Keller53a85552015-07-22 14:05:32 -070053 * 4: A bad character: ASCII control characters, and
Jacob Kellercd377f42015-07-22 14:05:33 -070054 * ":", "?", "[", "\", "^", "~", SP, or TAB
55 * 5: *, reject unless REFNAME_REFSPEC_PATTERN is set
David Turnerdde8a902014-06-03 23:38:10 -040056 */
57static unsigned char refname_disposition[256] = {
Junio C Hamano5e650222014-07-28 10:41:53 -070058 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
59 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
Jacob Kellercd377f42015-07-22 14:05:33 -070060 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 1,
Junio C Hamano5e650222014-07-28 10:41:53 -070061 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,
David Turnerdde8a902014-06-03 23:38:10 -040062 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Junio C Hamano5e650222014-07-28 10:41:53 -070063 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
64 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
David Turnerdde8a902014-06-03 23:38:10 -040066};
67
Derrick Stoleeb9342b32022-08-05 17:58:36 +000068struct ref_namespace_info ref_namespace[] = {
69 [NAMESPACE_HEAD] = {
70 .ref = "HEAD",
71 .decoration = DECORATION_REF_HEAD,
72 .exact = 1,
73 },
74 [NAMESPACE_BRANCHES] = {
75 .ref = "refs/heads/",
76 .decoration = DECORATION_REF_LOCAL,
77 },
78 [NAMESPACE_TAGS] = {
79 .ref = "refs/tags/",
80 .decoration = DECORATION_REF_TAG,
81 },
82 [NAMESPACE_REMOTE_REFS] = {
83 /*
84 * The default refspec for new remotes copies refs from
85 * refs/heads/ on the remote into refs/remotes/<remote>/.
86 * As such, "refs/remotes/" has special handling.
87 */
88 .ref = "refs/remotes/",
89 .decoration = DECORATION_REF_REMOTE,
90 },
91 [NAMESPACE_STASH] = {
92 /*
93 * The single ref "refs/stash" stores the latest stash.
94 * Older stashes can be found in the reflog.
95 */
96 .ref = "refs/stash",
97 .exact = 1,
98 .decoration = DECORATION_REF_STASH,
99 },
100 [NAMESPACE_REPLACE] = {
101 /*
102 * This namespace allows Git to act as if one object ID
103 * points to the content of another. Unlike the other
104 * ref namespaces, this one can be changed by the
105 * GIT_REPLACE_REF_BASE environment variable. This
106 * .namespace value will be overwritten in setup_git_env().
107 */
108 .ref = "refs/replace/",
109 .decoration = DECORATION_GRAFTED,
110 },
111 [NAMESPACE_NOTES] = {
112 /*
113 * The refs/notes/commit ref points to the tip of a
114 * parallel commit history that adds metadata to commits
115 * in the normal history. This ref can be overwritten
116 * by the core.notesRef config variable or the
117 * GIT_NOTES_REFS environment variable.
118 */
119 .ref = "refs/notes/commit",
120 .exact = 1,
121 },
122 [NAMESPACE_PREFETCH] = {
123 /*
124 * Prefetch refs are written by the background 'fetch'
125 * maintenance task. It allows faster foreground fetches
126 * by advertising these previously-downloaded tips without
127 * updating refs/remotes/ without user intervention.
128 */
129 .ref = "refs/prefetch/",
130 },
131 [NAMESPACE_REWRITTEN] = {
132 /*
133 * Rewritten refs are used by the 'label' command in the
134 * sequencer. These are particularly useful during an
135 * interactive rebase that uses the 'merge' command.
136 */
137 .ref = "refs/rewritten/",
138 },
139};
140
141void update_ref_namespace(enum ref_namespace namespace, char *ref)
142{
143 struct ref_namespace_info *info = &ref_namespace[namespace];
144 if (info->ref_updated)
145 free(info->ref);
146 info->ref = ref;
147 info->ref_updated = 1;
148}
149
David Turnerdde8a902014-06-03 23:38:10 -0400150/*
151 * Try to read one refname component from the front of refname.
152 * Return the length of the component found, or -1 if the component is
153 * not legal. It is legal if it is something reasonable to have under
154 * ".git/refs/"; We do not like it if:
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200155 *
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700156 * - it begins with ".", or
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200157 * - it has double dots "..", or
Jacob Keller53a85552015-07-22 14:05:32 -0700158 * - it has ASCII control characters, or
Jacob Kellercd377f42015-07-22 14:05:33 -0700159 * - it has ":", "?", "[", "\", "^", "~", SP, or TAB anywhere, or
160 * - it has "*" anywhere unless REFNAME_REFSPEC_PATTERN is set, or
Jacob Keller53a85552015-07-22 14:05:32 -0700161 * - it ends with a "/", or
162 * - it ends with ".lock", or
163 * - it contains a "@{" portion
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700164 *
165 * When sanitized is not NULL, instead of rejecting the input refname
166 * as an error, try to come up with a usable replacement for the input
167 * refname in it.
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200168 */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700169static int check_refname_component(const char *refname, int *flags,
170 struct strbuf *sanitized)
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200171{
172 const char *cp;
173 char last = '\0';
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700174 size_t component_start = 0; /* garbage - not a reasonable initial value */
175
176 if (sanitized)
177 component_start = sanitized->len;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200178
179 for (cp = refname; ; cp++) {
David Turnerdde8a902014-06-03 23:38:10 -0400180 int ch = *cp & 255;
181 unsigned char disp = refname_disposition[ch];
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700182
183 if (sanitized && disp != 1)
184 strbuf_addch(sanitized, ch);
185
David Turnerdde8a902014-06-03 23:38:10 -0400186 switch (disp) {
Junio C Hamano5e650222014-07-28 10:41:53 -0700187 case 1:
David Turnerdde8a902014-06-03 23:38:10 -0400188 goto out;
Junio C Hamano5e650222014-07-28 10:41:53 -0700189 case 2:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700190 if (last == '.') { /* Refname contains "..". */
191 if (sanitized)
192 /* collapse ".." to single "." */
193 strbuf_setlen(sanitized, sanitized->len - 1);
194 else
195 return -1;
196 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200197 break;
Junio C Hamano5e650222014-07-28 10:41:53 -0700198 case 3:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700199 if (last == '@') { /* Refname contains "@{". */
200 if (sanitized)
201 sanitized->buf[sanitized->len-1] = '-';
202 else
203 return -1;
204 }
David Turnerdde8a902014-06-03 23:38:10 -0400205 break;
Junio C Hamano5e650222014-07-28 10:41:53 -0700206 case 4:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700207 /* forbidden char */
208 if (sanitized)
209 sanitized->buf[sanitized->len-1] = '-';
210 else
211 return -1;
212 break;
Jacob Kellercd377f42015-07-22 14:05:33 -0700213 case 5:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700214 if (!(*flags & REFNAME_REFSPEC_PATTERN)) {
215 /* refspec can't be a pattern */
216 if (sanitized)
217 sanitized->buf[sanitized->len-1] = '-';
218 else
219 return -1;
220 }
Jacob Kellercd377f42015-07-22 14:05:33 -0700221
222 /*
223 * Unset the pattern flag so that we only accept
224 * a single asterisk for one side of refspec.
225 */
226 *flags &= ~ REFNAME_REFSPEC_PATTERN;
227 break;
David Turnerdde8a902014-06-03 23:38:10 -0400228 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200229 last = ch;
230 }
David Turnerdde8a902014-06-03 23:38:10 -0400231out:
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200232 if (cp == refname)
Michael Haggertydac529e2012-04-10 07:30:22 +0200233 return 0; /* Component has zero length. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700234
235 if (refname[0] == '.') { /* Component starts with '.'. */
236 if (sanitized)
237 sanitized->buf[component_start] = '-';
238 else
239 return -1;
240 }
Michael Haggerty7108ad22014-10-01 12:28:15 +0200241 if (cp - refname >= LOCK_SUFFIX_LEN &&
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700242 !memcmp(cp - LOCK_SUFFIX_LEN, LOCK_SUFFIX, LOCK_SUFFIX_LEN)) {
243 if (!sanitized)
244 return -1;
245 /* Refname ends with ".lock". */
246 while (strbuf_strip_suffix(sanitized, LOCK_SUFFIX)) {
247 /* try again in case we have .lock.lock */
248 }
249 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200250 return cp - refname;
251}
252
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700253static int check_or_sanitize_refname(const char *refname, int flags,
254 struct strbuf *sanitized)
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200255{
256 int component_len, component_count = 0;
257
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700258 if (!strcmp(refname, "@")) {
Felipe Contreras9ba89f42013-09-02 01:34:30 -0500259 /* Refname is a single character '@'. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700260 if (sanitized)
261 strbuf_addch(sanitized, '-');
262 else
263 return -1;
264 }
Felipe Contreras9ba89f42013-09-02 01:34:30 -0500265
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200266 while (1) {
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700267 if (sanitized && sanitized->len)
268 strbuf_complete(sanitized, '/');
269
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200270 /* We are at the start of a path component. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700271 component_len = check_refname_component(refname, &flags,
272 sanitized);
273 if (sanitized && component_len == 0)
274 ; /* OK, omit empty component */
275 else if (component_len <= 0)
Jacob Kellercd377f42015-07-22 14:05:33 -0700276 return -1;
277
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200278 component_count++;
279 if (refname[component_len] == '\0')
280 break;
281 /* Skip to next component. */
282 refname += component_len + 1;
283 }
284
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700285 if (refname[component_len - 1] == '.') {
286 /* Refname ends with '.'. */
287 if (sanitized)
288 ; /* omit ending dot */
289 else
290 return -1;
291 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200292 if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
293 return -1; /* Refname has only one component. */
294 return 0;
295}
296
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700297int check_refname_format(const char *refname, int flags)
298{
299 return check_or_sanitize_refname(refname, flags, NULL);
300}
301
302void sanitize_refname_component(const char *refname, struct strbuf *out)
303{
304 if (check_or_sanitize_refname(refname, REFNAME_ALLOW_ONELEVEL, out))
305 BUG("sanitizing refname '%s' check returned error", refname);
306}
307
Michael Haggerty4cb77002015-11-10 12:42:36 +0100308int refname_is_safe(const char *refname)
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700309{
Michael Haggerty39950fe2016-04-27 12:39:11 +0200310 const char *rest;
311
312 if (skip_prefix(refname, "refs/", &rest)) {
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700313 char *buf;
314 int result;
Michael Haggertye40f3552016-04-27 12:40:39 +0200315 size_t restlen = strlen(rest);
316
317 /* rest must not be empty, or start or end with "/" */
318 if (!restlen || *rest == '/' || rest[restlen - 1] == '/')
319 return 0;
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700320
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700321 /*
322 * Does the refname try to escape refs/?
323 * For example: refs/foo/../bar is safe but refs/foo/../../bar
324 * is not.
325 */
Michael Haggertye40f3552016-04-27 12:40:39 +0200326 buf = xmallocz(restlen);
327 result = !normalize_path_copy(buf, rest) && !strcmp(buf, rest);
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700328 free(buf);
329 return result;
330 }
Michael Haggerty35db25c2016-04-27 12:42:27 +0200331
332 do {
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700333 if (!isupper(*refname) && *refname != '_')
334 return 0;
335 refname++;
Michael Haggerty35db25c2016-04-27 12:42:27 +0200336 } while (*refname);
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700337 return 1;
338}
339
Michael Haggerty67be7c52017-06-23 09:01:37 +0200340/*
341 * Return true if refname, which has the specified oid and flags, can
342 * be resolved to an object in the database. If the referred-to object
343 * does not exist, emit a warning and return false.
344 */
345int ref_resolves_to_object(const char *refname,
Jonathan Tan9bc45a22021-10-08 14:08:15 -0700346 struct repository *repo,
Michael Haggerty67be7c52017-06-23 09:01:37 +0200347 const struct object_id *oid,
348 unsigned int flags)
349{
350 if (flags & REF_ISBROKEN)
351 return 0;
Jonathan Tan9bc45a22021-10-08 14:08:15 -0700352 if (!repo_has_object_file(repo, oid)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200353 error(_("%s does not point to a valid object!"), refname);
Michael Haggerty67be7c52017-06-23 09:01:37 +0200354 return 0;
355 }
356 return 1;
357}
358
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700359char *refs_resolve_refdup(struct ref_store *refs,
360 const char *refname, int resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000361 struct object_id *oid, int *flags)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700362{
363 const char *result;
364
365 result = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100366 oid, flags);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700367 return xstrdup_or_null(result);
368}
369
Michael Haggertyfb58c8d2015-06-22 16:03:05 +0200370char *resolve_refdup(const char *refname, int resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000371 struct object_id *oid, int *flags)
Nguyễn Thái Ngọc Duy96ec7b12011-12-13 21:17:48 +0700372{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700373 return refs_resolve_refdup(get_main_ref_store(the_repository),
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700374 refname, resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000375 oid, flags);
Nguyễn Thái Ngọc Duy96ec7b12011-12-13 21:17:48 +0700376}
377
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200378/* The argument to filter_refs */
379struct ref_filter {
380 const char *pattern;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000381 const char *prefix;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200382 each_ref_fn *fn;
383 void *cb_data;
384};
385
brian m. carlson34c290a2017-10-15 22:06:56 +0000386int 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 +0700387{
Ævar Arnfjörð Bjarmason76887df2021-10-16 11:39:14 +0200388 struct ref_store *refs = get_main_ref_store(the_repository);
389
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +0200390 if (refs_resolve_ref_unsafe(refs, refname, resolve_flags,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100391 oid, flags))
Ævar Arnfjörð Bjarmason76887df2021-10-16 11:39:14 +0200392 return 0;
393 return -1;
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700394}
395
brian m. carlson34c290a2017-10-15 22:06:56 +0000396int read_ref(const char *refname, struct object_id *oid)
Nguyễn Thái Ngọc Duyc6893322011-11-13 17:22:14 +0700397{
brian m. carlson34c290a2017-10-15 22:06:56 +0000398 return read_ref_full(refname, RESOLVE_REF_READING, oid, NULL);
Nguyễn Thái Ngọc Duyc6893322011-11-13 17:22:14 +0700399}
400
Han-Wen Nienhuys3f9f1ac2020-08-21 16:59:34 +0000401int refs_ref_exists(struct ref_store *refs, const char *refname)
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700402{
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +0200403 return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100404 NULL, NULL);
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700405}
406
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200407int ref_exists(const char *refname)
Junio C Hamanoef06b912006-11-18 22:13:33 -0800408{
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700409 return refs_ref_exists(get_main_ref_store(the_repository), refname);
Junio C Hamanoef06b912006-11-18 22:13:33 -0800410}
411
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000412static int filter_refs(const char *refname, const struct object_id *oid,
Michael Haggerty4e675d12015-05-25 18:39:21 +0000413 int flags, void *data)
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200414{
415 struct ref_filter *filter = (struct ref_filter *)data;
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000416
Ævar Arnfjörð Bjarmason55d34262017-06-22 21:38:08 +0000417 if (wildmatch(filter->pattern, refname, 0))
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200418 return 0;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000419 if (filter->prefix)
420 skip_prefix(refname, filter->prefix, &refname);
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000421 return filter->fn(refname, oid, flags, filter->cb_data);
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200422}
423
brian m. carlsonac2ed0d2017-10-15 22:07:10 +0000424enum peel_status peel_object(const struct object_id *name, struct object_id *oid)
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200425{
Jeff King45a187c2021-04-13 03:16:36 -0400426 struct object *o = lookup_unknown_object(the_repository, name);
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200427
428 if (o->type == OBJ_NONE) {
Stefan Beller0df8e962018-04-25 11:20:59 -0700429 int type = oid_object_info(the_repository, name, NULL);
Abhishek Kumar6da43d92020-06-17 14:44:08 +0530430 if (type < 0 || !object_as_type(o, type, 0))
Michael Haggerty68cf8702013-04-22 21:52:20 +0200431 return PEEL_INVALID;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200432 }
433
434 if (o->type != OBJ_TAG)
Michael Haggerty68cf8702013-04-22 21:52:20 +0200435 return PEEL_NON_TAG;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200436
437 o = deref_tag_noverify(o);
438 if (!o)
Michael Haggerty68cf8702013-04-22 21:52:20 +0200439 return PEEL_INVALID;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200440
brian m. carlsonac2ed0d2017-10-15 22:07:10 +0000441 oidcpy(oid, &o->oid);
Michael Haggerty68cf8702013-04-22 21:52:20 +0200442 return PEEL_PEELED;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200443}
444
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200445struct warn_if_dangling_data {
446 FILE *fp;
447 const char *refname;
Jens Lindströme6bea662014-05-23 12:30:25 +0200448 const struct string_list *refnames;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200449 const char *msg_fmt;
450};
451
Jeff King63e14ee2022-08-19 06:08:32 -0400452static int warn_if_dangling_symref(const char *refname,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +0200453 const struct object_id *oid UNUSED,
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200454 int flags, void *cb_data)
455{
456 struct warn_if_dangling_data *d = cb_data;
457 const char *resolves_to;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200458
459 if (!(flags & REF_ISSYMREF))
460 return 0;
461
René Scharfe744c0402017-09-23 11:45:04 +0200462 resolves_to = resolve_ref_unsafe(refname, 0, NULL, NULL);
Jens Lindströme6bea662014-05-23 12:30:25 +0200463 if (!resolves_to
464 || (d->refname
465 ? strcmp(resolves_to, d->refname)
466 : !string_list_has_string(d->refnames, resolves_to))) {
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200467 return 0;
Jens Lindströme6bea662014-05-23 12:30:25 +0200468 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200469
470 fprintf(d->fp, d->msg_fmt, refname);
Junio C Hamano1be65ed2012-05-02 13:51:35 -0700471 fputc('\n', d->fp);
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200472 return 0;
473}
474
475void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
476{
477 struct warn_if_dangling_data data;
478
479 data.fp = fp;
480 data.refname = refname;
Jens Lindströme6bea662014-05-23 12:30:25 +0200481 data.refnames = NULL;
482 data.msg_fmt = msg_fmt;
483 for_each_rawref(warn_if_dangling_symref, &data);
484}
485
486void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)
487{
488 struct warn_if_dangling_data data;
489
490 data.fp = fp;
491 data.refname = NULL;
492 data.refnames = refnames;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200493 data.msg_fmt = msg_fmt;
494 for_each_rawref(warn_if_dangling_symref, &data);
495}
496
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700497int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
498{
499 return refs_for_each_ref_in(refs, "refs/tags/", fn, cb_data);
500}
501
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700502int for_each_tag_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400503{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700504 return refs_for_each_tag_ref(get_main_ref_store(the_repository), fn, cb_data);
Seana62be772006-05-13 21:43:00 -0400505}
506
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700507int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
508{
509 return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
Heiko Voigt9ef6aeb2010-07-07 15:39:12 +0200510}
511
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700512int for_each_branch_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400513{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700514 return refs_for_each_branch_ref(get_main_ref_store(the_repository), fn, cb_data);
Seana62be772006-05-13 21:43:00 -0400515}
516
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700517int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
518{
519 return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
Heiko Voigt9ef6aeb2010-07-07 15:39:12 +0200520}
521
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700522int for_each_remote_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400523{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700524 return refs_for_each_remote_ref(get_main_ref_store(the_repository), fn, cb_data);
Junio C Hamanof8948e22009-02-08 23:27:10 -0800525}
526
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700527int head_ref_namespaced(each_ref_fn fn, void *cb_data)
528{
529 struct strbuf buf = STRBUF_INIT;
530 int ret = 0;
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000531 struct object_id oid;
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700532 int flag;
533
534 strbuf_addf(&buf, "%sHEAD", get_git_namespace());
brian m. carlson34c290a2017-10-15 22:06:56 +0000535 if (!read_ref_full(buf.buf, RESOLVE_REF_READING, &oid, &flag))
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000536 ret = fn(buf.buf, &oid, flag, cb_data);
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700537 strbuf_release(&buf);
538
539 return ret;
540}
541
Rafael Ascensão65516f52017-11-21 21:33:41 +0000542void normalize_glob_ref(struct string_list_item *item, const char *prefix,
543 const char *pattern)
544{
545 struct strbuf normalized_pattern = STRBUF_INIT;
546
547 if (*pattern == '/')
548 BUG("pattern must not start with '/'");
549
Derrick Stoleeb877e612022-08-05 17:58:33 +0000550 if (prefix)
Rafael Ascensão65516f52017-11-21 21:33:41 +0000551 strbuf_addstr(&normalized_pattern, prefix);
Derrick Stoleeb877e612022-08-05 17:58:33 +0000552 else if (!starts_with(pattern, "refs/") &&
553 strcmp(pattern, "HEAD"))
Rafael Ascensão65516f52017-11-21 21:33:41 +0000554 strbuf_addstr(&normalized_pattern, "refs/");
Derrick Stoleeb877e612022-08-05 17:58:33 +0000555 /*
556 * NEEDSWORK: Special case other symrefs such as REBASE_HEAD,
557 * MERGE_HEAD, etc.
558 */
559
Rafael Ascensão65516f52017-11-21 21:33:41 +0000560 strbuf_addstr(&normalized_pattern, pattern);
561 strbuf_strip_suffix(&normalized_pattern, "/");
562
563 item->string = strbuf_detach(&normalized_pattern, NULL);
564 item->util = has_glob_specials(pattern) ? NULL : item->string;
565 strbuf_release(&normalized_pattern);
566}
567
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200568int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
569 const char *prefix, void *cb_data)
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200570{
571 struct strbuf real_pattern = STRBUF_INIT;
572 struct ref_filter filter;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200573 int ret;
574
Christian Couder59556542013-11-30 21:55:40 +0100575 if (!prefix && !starts_with(pattern, "refs/"))
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200576 strbuf_addstr(&real_pattern, "refs/");
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200577 else if (prefix)
578 strbuf_addstr(&real_pattern, prefix);
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200579 strbuf_addstr(&real_pattern, pattern);
580
Thomas Rast894a9d32010-03-12 18:04:26 +0100581 if (!has_glob_specials(pattern)) {
Junio C Hamano9517e6b2010-02-03 21:23:18 -0800582 /* Append implied '/' '*' if not present. */
Jeff King00b6c172015-09-24 17:08:35 -0400583 strbuf_complete(&real_pattern, '/');
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200584 /* No need to check for '*', there is none. */
585 strbuf_addch(&real_pattern, '*');
586 }
587
588 filter.pattern = real_pattern.buf;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000589 filter.prefix = prefix;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200590 filter.fn = fn;
591 filter.cb_data = cb_data;
592 ret = for_each_ref(filter_refs, &filter);
593
594 strbuf_release(&real_pattern);
595 return ret;
596}
597
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200598int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
599{
600 return for_each_glob_ref_in(fn, pattern, NULL, cb_data);
601}
602
Felipe Contreras4577e482009-05-14 00:22:04 +0300603const char *prettify_refname(const char *name)
Daniel Barkalowa9c37a72009-03-08 21:06:05 -0400604{
SZEDER Gábor3e5b36c2017-03-23 16:50:12 +0100605 if (skip_prefix(name, "refs/heads/", &name) ||
606 skip_prefix(name, "refs/tags/", &name) ||
607 skip_prefix(name, "refs/remotes/", &name))
608 ; /* nothing */
609 return name;
Daniel Barkalowa9c37a72009-03-08 21:06:05 -0400610}
611
Michael Haggerty54457fe2014-01-14 04:16:07 +0100612static const char *ref_rev_parse_rules[] = {
Steffen Prohaska79803322007-11-11 15:01:46 +0100613 "%.*s",
614 "refs/%.*s",
615 "refs/tags/%.*s",
616 "refs/heads/%.*s",
617 "refs/remotes/%.*s",
618 "refs/remotes/%.*s/HEAD",
619 NULL
620};
621
Junio C Hamano60650a42018-08-01 09:22:37 -0700622#define NUM_REV_PARSE_RULES (ARRAY_SIZE(ref_rev_parse_rules) - 1)
623
624/*
625 * Is it possible that the caller meant full_name with abbrev_name?
626 * If so return a non-zero value to signal "yes"; the magnitude of
627 * the returned value gives the precedence used for disambiguation.
628 *
629 * If abbrev_name cannot mean full_name, return 0.
630 */
Michael Haggerty54457fe2014-01-14 04:16:07 +0100631int refname_match(const char *abbrev_name, const char *full_name)
Steffen Prohaska79803322007-11-11 15:01:46 +0100632{
633 const char **p;
634 const int abbrev_name_len = strlen(abbrev_name);
Junio C Hamano60650a42018-08-01 09:22:37 -0700635 const int num_rules = NUM_REV_PARSE_RULES;
Steffen Prohaska79803322007-11-11 15:01:46 +0100636
Junio C Hamano60650a42018-08-01 09:22:37 -0700637 for (p = ref_rev_parse_rules; *p; p++)
638 if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name)))
639 return &ref_rev_parse_rules[num_rules] - p;
Steffen Prohaska79803322007-11-11 15:01:46 +0100640
641 return 0;
642}
643
Michael Haggerty19b68b12011-12-12 06:38:12 +0100644/*
Brandon Williamsb4be7412018-03-15 10:31:24 -0700645 * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add
646 * the results to 'prefixes'
647 */
Jeff Kingc972bf42020-07-28 16:25:12 -0400648void expand_ref_prefix(struct strvec *prefixes, const char *prefix)
Brandon Williamsb4be7412018-03-15 10:31:24 -0700649{
650 const char **p;
651 int len = strlen(prefix);
652
653 for (p = ref_rev_parse_rules; *p; p++)
Jeff Kingc972bf42020-07-28 16:25:12 -0400654 strvec_pushf(prefixes, *p, len, prefix);
Brandon Williamsb4be7412018-03-15 10:31:24 -0700655}
656
Johannes Schindelin675704c2020-12-11 11:36:57 +0000657static const char default_branch_name_advice[] = N_(
658"Using '%s' as the name for the initial branch. This default branch name\n"
659"is subject to change. To configure the initial branch name to use in all\n"
660"of your new repositories, which will suppress this warning, call:\n"
661"\n"
662"\tgit config --global init.defaultBranch <name>\n"
663"\n"
664"Names commonly chosen instead of 'master' are 'main', 'trunk' and\n"
665"'development'. The just-created branch can be renamed via this command:\n"
666"\n"
667"\tgit branch -m <name>\n"
668);
669
Johannes Schindelincc0f13c2020-12-11 11:36:56 +0000670char *repo_default_branch_name(struct repository *r, int quiet)
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000671{
672 const char *config_key = "init.defaultbranch";
673 const char *config_display_key = "init.defaultBranch";
674 char *ret = NULL, *full_ref;
Johannes Schindelin704fed92020-10-23 14:00:00 +0000675 const char *env = getenv("GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME");
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000676
Johannes Schindelin704fed92020-10-23 14:00:00 +0000677 if (env && *env)
678 ret = xstrdup(env);
679 else if (repo_config_get_string(r, config_key, &ret) < 0)
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000680 die(_("could not retrieve `%s`"), config_display_key);
681
Johannes Schindelin675704c2020-12-11 11:36:57 +0000682 if (!ret) {
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000683 ret = xstrdup("master");
Johannes Schindelin675704c2020-12-11 11:36:57 +0000684 if (!quiet)
685 advise(_(default_branch_name_advice), ret);
686 }
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000687
688 full_ref = xstrfmt("refs/heads/%s", ret);
689 if (check_refname_format(full_ref, 0))
690 die(_("invalid branch name: %s = %s"), config_display_key, ret);
691 free(full_ref);
692
693 return ret;
694}
695
Johannes Schindelincc0f13c2020-12-11 11:36:56 +0000696const char *git_default_branch_name(int quiet)
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000697{
698 static char *ret;
699
700 if (!ret)
Johannes Schindelincc0f13c2020-12-11 11:36:56 +0000701 ret = repo_default_branch_name(the_repository, quiet);
Don Goodman-Wilson8747ebb2020-06-24 14:46:33 +0000702
703 return ret;
704}
705
Brandon Williamsb4be7412018-03-15 10:31:24 -0700706/*
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700707 * *string and *len will only be substituted, and *string returned (for
708 * later free()ing) if the string passed in is a magic short-hand form
709 * to name a branch.
710 */
Nguyễn Thái Ngọc Duy8f56e9d2019-04-06 18:34:26 +0700711static char *substitute_branch_name(struct repository *r,
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700712 const char **string, int *len,
713 int nonfatal_dangling_mark)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700714{
715 struct strbuf buf = STRBUF_INIT;
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700716 struct interpret_branch_name_options options = {
717 .nonfatal_dangling_mark = nonfatal_dangling_mark
718 };
Jonathan Tana4f66a72020-09-01 15:28:07 -0700719 int ret = repo_interpret_branch_name(r, *string, *len, &buf, &options);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700720
721 if (ret == *len) {
722 size_t size;
723 *string = strbuf_detach(&buf, &size);
724 *len = size;
725 return (char *)*string;
726 }
727
728 return NULL;
729}
730
Nguyễn Thái Ngọc Duyd8984c52019-04-06 18:34:28 +0700731int repo_dwim_ref(struct repository *r, const char *str, int len,
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700732 struct object_id *oid, char **ref, int nonfatal_dangling_mark)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700733{
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700734 char *last_branch = substitute_branch_name(r, &str, &len,
735 nonfatal_dangling_mark);
Nguyễn Thái Ngọc Duyd8984c52019-04-06 18:34:28 +0700736 int refs_found = expand_ref(r, str, len, oid, ref);
Nguyễn Thái Ngọc Duy41da7112016-06-12 17:54:02 +0700737 free(last_branch);
738 return refs_found;
739}
740
Nguyễn Thái Ngọc Duy0b1dbf52019-04-06 18:34:27 +0700741int expand_ref(struct repository *repo, const char *str, int len,
742 struct object_id *oid, char **ref)
Nguyễn Thái Ngọc Duy41da7112016-06-12 17:54:02 +0700743{
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700744 const char **p, *r;
745 int refs_found = 0;
Jeff King6cd4a892017-03-28 15:46:33 -0400746 struct strbuf fullref = STRBUF_INIT;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700747
748 *ref = NULL;
749 for (p = ref_rev_parse_rules; *p; p++) {
brian m. carlsoncca5fa62017-10-15 22:06:57 +0000750 struct object_id oid_from_ref;
751 struct object_id *this_result;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700752 int flag;
Ævar Arnfjörð Bjarmason6582bd32021-10-16 11:39:24 +0200753 struct ref_store *refs = get_main_ref_store(repo);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700754
brian m. carlsoncca5fa62017-10-15 22:06:57 +0000755 this_result = refs_found ? &oid_from_ref : oid;
Jeff King6cd4a892017-03-28 15:46:33 -0400756 strbuf_reset(&fullref);
757 strbuf_addf(&fullref, *p, len, str);
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +0200758 r = refs_resolve_ref_unsafe(refs, fullref.buf,
Ævar Arnfjörð Bjarmason6582bd32021-10-16 11:39:24 +0200759 RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100760 this_result, &flag);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700761 if (r) {
762 if (!refs_found++)
763 *ref = xstrdup(r);
764 if (!warn_ambiguous_refs)
765 break;
Jeff King6cd4a892017-03-28 15:46:33 -0400766 } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200767 warning(_("ignoring dangling symref %s"), fullref.buf);
Jeff King6cd4a892017-03-28 15:46:33 -0400768 } else if ((flag & REF_ISBROKEN) && strchr(fullref.buf, '/')) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200769 warning(_("ignoring broken ref %s"), fullref.buf);
Junio C Hamano55956352011-10-19 13:55:49 -0700770 }
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700771 }
Jeff King6cd4a892017-03-28 15:46:33 -0400772 strbuf_release(&fullref);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700773 return refs_found;
774}
775
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700776int repo_dwim_log(struct repository *r, const char *str, int len,
777 struct object_id *oid, char **log)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700778{
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700779 struct ref_store *refs = get_main_ref_store(r);
Jonathan Tanf24c30e2020-09-01 15:28:09 -0700780 char *last_branch = substitute_branch_name(r, &str, &len, 0);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700781 const char **p;
782 int logs_found = 0;
Jeff King6cd4a892017-03-28 15:46:33 -0400783 struct strbuf path = STRBUF_INIT;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700784
785 *log = NULL;
786 for (p = ref_rev_parse_rules; *p; p++) {
brian m. carlson334dc522017-10-15 22:06:59 +0000787 struct object_id hash;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700788 const char *ref, *it;
789
Jeff King6cd4a892017-03-28 15:46:33 -0400790 strbuf_reset(&path);
791 strbuf_addf(&path, *p, len, str);
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700792 ref = refs_resolve_ref_unsafe(refs, path.buf,
793 RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100794 oid ? &hash : NULL, NULL);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700795 if (!ref)
796 continue;
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700797 if (refs_reflog_exists(refs, path.buf))
Jeff King6cd4a892017-03-28 15:46:33 -0400798 it = path.buf;
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700799 else if (strcmp(ref, path.buf) &&
800 refs_reflog_exists(refs, ref))
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700801 it = ref;
802 else
803 continue;
804 if (!logs_found++) {
805 *log = xstrdup(it);
Ævar Arnfjörð Bjarmason6f45ec82021-08-23 13:36:08 +0200806 if (oid)
807 oidcpy(oid, &hash);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700808 }
809 if (!warn_ambiguous_refs)
810 break;
811 }
Jeff King6cd4a892017-03-28 15:46:33 -0400812 strbuf_release(&path);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700813 free(last_branch);
814 return logs_found;
815}
816
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700817int dwim_log(const char *str, int len, struct object_id *oid, char **log)
818{
819 return repo_dwim_log(the_repository, str, len, oid, log);
820}
821
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000822int is_per_worktree_ref(const char *refname)
David Turner266b1822015-07-31 02:06:18 -0400823{
Han-Wen Nienhuys55dd8b92020-07-27 16:25:47 +0000824 return starts_with(refname, "refs/worktree/") ||
825 starts_with(refname, "refs/bisect/") ||
826 starts_with(refname, "refs/rewritten/");
David Turner266b1822015-07-31 02:06:18 -0400827}
828
829static int is_pseudoref_syntax(const char *refname)
830{
831 const char *c;
832
833 for (c = refname; *c; c++) {
834 if (!isupper(*c) && *c != '-' && *c != '_')
835 return 0;
836 }
837
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000838 /*
839 * HEAD is not a pseudoref, but it certainly uses the
840 * pseudoref syntax.
841 */
David Turner266b1822015-07-31 02:06:18 -0400842 return 1;
843}
844
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000845static int is_current_worktree_ref(const char *ref) {
846 return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref);
Nguyễn Thái Ngọc Duy3a3b9d82018-10-21 10:08:54 +0200847}
848
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000849enum ref_worktree_type parse_worktree_ref(const char *maybe_worktree_ref,
850 const char **worktree_name, int *worktree_name_length,
851 const char **bare_refname)
Nguyễn Thái Ngọc Duy3a3b9d82018-10-21 10:08:54 +0200852{
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000853 const char *name_dummy;
854 int name_length_dummy;
855 const char *ref_dummy;
Nguyễn Thái Ngọc Duy3a3b9d82018-10-21 10:08:54 +0200856
Han-Wen Nienhuys71e54732022-09-19 16:34:50 +0000857 if (!worktree_name)
858 worktree_name = &name_dummy;
859 if (!worktree_name_length)
860 worktree_name_length = &name_length_dummy;
861 if (!bare_refname)
862 bare_refname = &ref_dummy;
863
864 if (skip_prefix(maybe_worktree_ref, "worktrees/", bare_refname)) {
865 const char *slash = strchr(*bare_refname, '/');
866
867 *worktree_name = *bare_refname;
868 if (!slash) {
869 *worktree_name_length = strlen(*worktree_name);
870
871 /* This is an error condition, and the caller tell because the bare_refname is "" */
872 *bare_refname = *worktree_name + *worktree_name_length;
873 return REF_WORKTREE_OTHER;
874 }
875
876 *worktree_name_length = slash - *bare_refname;
877 *bare_refname = slash + 1;
878
879 if (is_current_worktree_ref(*bare_refname))
880 return REF_WORKTREE_OTHER;
881 }
882
883 *worktree_name = NULL;
884 *worktree_name_length = 0;
885
886 if (skip_prefix(maybe_worktree_ref, "main-worktree/", bare_refname)
887 && is_current_worktree_ref(*bare_refname))
888 return REF_WORKTREE_MAIN;
889
890 *bare_refname = maybe_worktree_ref;
891 if (is_current_worktree_ref(maybe_worktree_ref))
892 return REF_WORKTREE_CURRENT;
893
894 return REF_WORKTREE_SHARED;
David Turner266b1822015-07-31 02:06:18 -0400895}
896
Michael Haggerty4ff0f012017-08-21 13:51:34 +0200897long get_files_ref_lock_timeout_ms(void)
898{
899 static int configured = 0;
900
901 /* The default timeout is 100 ms: */
902 static int timeout_ms = 100;
903
904 if (!configured) {
905 git_config_get_int("core.filesreflocktimeout", &timeout_ms);
906 configured = 1;
907 }
908
909 return timeout_ms;
910}
911
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700912int refs_delete_ref(struct ref_store *refs, const char *msg,
913 const char *refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000914 const struct object_id *old_oid,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700915 unsigned int flags)
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700916{
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700917 struct ref_transaction *transaction;
918 struct strbuf err = STRBUF_INIT;
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700919
Junio C Hamanoc6da34a2022-04-13 15:51:33 -0700920 transaction = ref_store_transaction_begin(refs, &err);
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700921 if (!transaction ||
brian m. carlson89f3bbd2017-10-15 22:06:53 +0000922 ref_transaction_delete(transaction, refname, old_oid,
Kyle Meyer755b49a2017-02-20 20:10:32 -0500923 flags, msg, &err) ||
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -0700924 ref_transaction_commit(transaction, &err)) {
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700925 error("%s", err.buf);
926 ref_transaction_free(transaction);
927 strbuf_release(&err);
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700928 return 1;
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700929 }
930 ref_transaction_free(transaction);
931 strbuf_release(&err);
932 return 0;
Shawn Pearce4bd18c42006-05-17 05:55:02 -0400933}
934
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700935int delete_ref(const char *msg, const char *refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000936 const struct object_id *old_oid, unsigned int flags)
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700937{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700938 return refs_delete_ref(get_main_ref_store(the_repository), msg, refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000939 old_oid, flags);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700940}
941
Junio C Hamano523fa692020-07-10 17:19:53 +0000942static void copy_reflog_msg(struct strbuf *sb, const char *msg)
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700943{
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700944 char c;
945 int wasspace = 1;
946
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700947 while ((c = *msg++)) {
948 if (wasspace && isspace(c))
949 continue;
950 wasspace = isspace(c);
951 if (wasspace)
952 c = ' ';
Ben Peart80a6c202018-07-10 21:08:22 +0000953 strbuf_addch(sb, c);
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700954 }
Ben Peart80a6c202018-07-10 21:08:22 +0000955 strbuf_rtrim(sb);
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700956}
957
Junio C Hamano523fa692020-07-10 17:19:53 +0000958static char *normalize_reflog_message(const char *msg)
959{
960 struct strbuf sb = STRBUF_INIT;
961
962 if (msg && *msg)
963 copy_reflog_msg(&sb, msg);
964 return strbuf_detach(&sb, NULL);
965}
966
Michael Haggerty4cb77002015-11-10 12:42:36 +0100967int should_autocreate_reflog(const char *refname)
David Turner4e2bef52015-07-21 17:04:51 -0400968{
Cornelius Weig341fb282017-01-27 11:09:47 +0100969 switch (log_all_ref_updates) {
970 case LOG_REFS_ALWAYS:
971 return 1;
972 case LOG_REFS_NORMAL:
973 return starts_with(refname, "refs/heads/") ||
974 starts_with(refname, "refs/remotes/") ||
975 starts_with(refname, "refs/notes/") ||
976 !strcmp(refname, "HEAD");
977 default:
David Turner4e2bef52015-07-21 17:04:51 -0400978 return 0;
Cornelius Weig341fb282017-01-27 11:09:47 +0100979 }
David Turner4e2bef52015-07-21 17:04:51 -0400980}
981
Ronnie Sahlberge7e0f262014-07-15 16:02:38 -0700982int is_branch(const char *refname)
Linus Torvaldsc3b0dec2008-01-15 15:50:17 -0800983{
Christian Couder59556542013-11-30 21:55:40 +0100984 return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
Linus Torvaldsc3b0dec2008-01-15 15:50:17 -0800985}
986
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700987struct read_ref_at_cb {
988 const char *refname;
Johannes Schindelindddbad72017-04-26 21:29:31 +0200989 timestamp_t at_time;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700990 int cnt;
991 int reccnt;
brian m. carlson8eb36d92017-10-15 22:07:03 +0000992 struct object_id *oid;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700993 int found_it;
994
brian m. carlson8eb36d92017-10-15 22:07:03 +0000995 struct object_id ooid;
996 struct object_id noid;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700997 int tz;
Johannes Schindelindddbad72017-04-26 21:29:31 +0200998 timestamp_t date;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700999 char **msg;
Johannes Schindelindddbad72017-04-26 21:29:31 +02001000 timestamp_t *cutoff_time;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001001 int *cutoff_tz;
1002 int *cutoff_cnt;
1003};
1004
Denton Liu95c2a712021-01-06 01:01:53 -08001005static void set_read_ref_cutoffs(struct read_ref_at_cb *cb,
1006 timestamp_t timestamp, int tz, const char *message)
1007{
1008 if (cb->msg)
1009 *cb->msg = xstrdup(message);
1010 if (cb->cutoff_time)
1011 *cb->cutoff_time = timestamp;
1012 if (cb->cutoff_tz)
1013 *cb->cutoff_tz = tz;
1014 if (cb->cutoff_cnt)
1015 *cb->cutoff_cnt = cb->reccnt;
1016}
1017
brian m. carlson9461d272017-02-21 23:47:32 +00001018static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02001019 const char *email UNUSED,
Jeff Kingc006e9f2022-08-19 06:08:35 -04001020 timestamp_t timestamp, int tz,
1021 const char *message, void *cb_data)
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001022{
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001023 struct read_ref_at_cb *cb = cb_data;
Denton Liu6436a202021-01-07 02:36:59 -08001024 int reached_count;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001025
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001026 cb->tz = tz;
1027 cb->date = timestamp;
1028
Denton Liu6436a202021-01-07 02:36:59 -08001029 /*
1030 * It is not possible for cb->cnt == 0 on the first iteration because
1031 * that special case is handled in read_ref_at().
1032 */
1033 if (cb->cnt > 0)
1034 cb->cnt--;
1035 reached_count = cb->cnt == 0 && !is_null_oid(ooid);
1036 if (timestamp <= cb->at_time || reached_count) {
Denton Liu95c2a712021-01-06 01:01:53 -08001037 set_read_ref_cutoffs(cb, timestamp, tz, message);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001038 /*
Michael Haggerty78fb4572017-11-05 09:42:09 +01001039 * we have not yet updated cb->[n|o]oid so they still
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001040 * hold the values for the previous record.
1041 */
Denton Liu6436a202021-01-07 02:36:59 -08001042 if (!is_null_oid(&cb->ooid) && !oideq(&cb->ooid, noid))
1043 warning(_("log for ref %s has gap after %s"),
Jeff Kinga5481a62015-06-25 12:55:02 -04001044 cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
Denton Liu6436a202021-01-07 02:36:59 -08001045 if (reached_count)
1046 oidcpy(cb->oid, ooid);
1047 else if (!is_null_oid(&cb->ooid) || cb->date == cb->at_time)
brian m. carlson8eb36d92017-10-15 22:07:03 +00001048 oidcpy(cb->oid, noid);
Jeff King9001dc22018-08-28 17:22:48 -04001049 else if (!oideq(noid, cb->oid))
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001050 warning(_("log for ref %s unexpectedly ended on %s"),
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001051 cb->refname, show_date(cb->date, cb->tz,
Jeff Kinga5481a62015-06-25 12:55:02 -04001052 DATE_MODE(RFC2822)));
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001053 cb->found_it = 1;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001054 }
Denton Liu95c2a712021-01-06 01:01:53 -08001055 cb->reccnt++;
brian m. carlson8eb36d92017-10-15 22:07:03 +00001056 oidcpy(&cb->ooid, ooid);
1057 oidcpy(&cb->noid, noid);
Denton Liu6436a202021-01-07 02:36:59 -08001058 return cb->found_it;
1059}
1060
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02001061static int read_ref_at_ent_newest(struct object_id *ooid UNUSED,
Jeff King63e14ee2022-08-19 06:08:32 -04001062 struct object_id *noid,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02001063 const char *email UNUSED,
Jeff King63e14ee2022-08-19 06:08:32 -04001064 timestamp_t timestamp, int tz,
1065 const char *message, void *cb_data)
Denton Liu6436a202021-01-07 02:36:59 -08001066{
1067 struct read_ref_at_cb *cb = cb_data;
1068
1069 set_read_ref_cutoffs(cb, timestamp, tz, message);
1070 oidcpy(cb->oid, noid);
1071 /* We just want the first entry */
1072 return 1;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001073}
1074
brian m. carlson9461d272017-02-21 23:47:32 +00001075static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02001076 const char *email UNUSED,
Jeff Kingc006e9f2022-08-19 06:08:35 -04001077 timestamp_t timestamp, int tz,
1078 const char *message, void *cb_data)
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001079{
1080 struct read_ref_at_cb *cb = cb_data;
1081
Denton Liu95c2a712021-01-06 01:01:53 -08001082 set_read_ref_cutoffs(cb, timestamp, tz, message);
brian m. carlson8eb36d92017-10-15 22:07:03 +00001083 oidcpy(cb->oid, ooid);
1084 if (is_null_oid(cb->oid))
1085 oidcpy(cb->oid, noid);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001086 /* We just want the first entry */
1087 return 1;
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001088}
1089
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +07001090int read_ref_at(struct ref_store *refs, const char *refname,
1091 unsigned int flags, timestamp_t at_time, int cnt,
brian m. carlson8eb36d92017-10-15 22:07:03 +00001092 struct object_id *oid, char **msg,
Johannes Schindelindddbad72017-04-26 21:29:31 +02001093 timestamp_t *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
Shawn Pearced556fae2006-05-17 05:56:09 -04001094{
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001095 struct read_ref_at_cb cb;
Shawn Pearced556fae2006-05-17 05:56:09 -04001096
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001097 memset(&cb, 0, sizeof(cb));
1098 cb.refname = refname;
1099 cb.at_time = at_time;
1100 cb.cnt = cnt;
1101 cb.msg = msg;
1102 cb.cutoff_time = cutoff_time;
1103 cb.cutoff_tz = cutoff_tz;
1104 cb.cutoff_cnt = cutoff_cnt;
brian m. carlson8eb36d92017-10-15 22:07:03 +00001105 cb.oid = oid;
Shawn Pearced556fae2006-05-17 05:56:09 -04001106
Denton Liu6436a202021-01-07 02:36:59 -08001107 if (cb.cnt == 0) {
1108 refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent_newest, &cb);
1109 return 0;
1110 }
1111
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +07001112 refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent, &cb);
Shawn Pearced556fae2006-05-17 05:56:09 -04001113
David Aguilarc41a87d2014-09-18 20:45:37 -07001114 if (!cb.reccnt) {
brian m. carlson321c89b2017-07-13 23:49:29 +00001115 if (flags & GET_OID_QUIETLY)
David Aguilarc41a87d2014-09-18 20:45:37 -07001116 exit(128);
1117 else
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001118 die(_("log for %s is empty"), refname);
David Aguilarc41a87d2014-09-18 20:45:37 -07001119 }
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001120 if (cb.found_it)
1121 return 0;
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001122
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +07001123 refs_for_each_reflog_ent(refs, refname, read_ref_at_ent_oldest, &cb);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001124
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001125 return 1;
Shawn Pearced556fae2006-05-17 05:56:09 -04001126}
Junio C Hamano2ff81662006-12-18 01:18:16 -08001127
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001128struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
1129 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001130{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001131 struct ref_transaction *tr;
Jonathan Nieder5a603b02014-08-28 16:42:37 -07001132 assert(err);
1133
René Scharfeca56dad2021-03-13 17:17:22 +01001134 CALLOC_ARRAY(tr, 1);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001135 tr->ref_store = refs;
1136 return tr;
1137}
1138
1139struct ref_transaction *ref_transaction_begin(struct strbuf *err)
1140{
Junio C Hamanoc6da34a2022-04-13 15:51:33 -07001141 return ref_store_transaction_begin(get_main_ref_store(the_repository), err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001142}
1143
Ronnie Sahlberg026bd1d2014-06-20 07:42:42 -07001144void ref_transaction_free(struct ref_transaction *transaction)
Michael Haggertycaa40462014-04-07 15:48:10 +02001145{
Michael Haggerty43a2dfd2017-05-22 16:17:37 +02001146 size_t i;
Michael Haggertycaa40462014-04-07 15:48:10 +02001147
Ronnie Sahlberg1b072552014-06-20 07:42:45 -07001148 if (!transaction)
1149 return;
1150
Michael Haggerty30173b82017-05-22 16:17:44 +02001151 switch (transaction->state) {
1152 case REF_TRANSACTION_OPEN:
1153 case REF_TRANSACTION_CLOSED:
1154 /* OK */
1155 break;
1156 case REF_TRANSACTION_PREPARED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02001157 BUG("free called on a prepared reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02001158 break;
1159 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02001160 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02001161 break;
1162 }
1163
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -07001164 for (i = 0; i < transaction->nr; i++) {
1165 free(transaction->updates[i]->msg);
Michael Haggerty88615912014-04-07 15:48:14 +02001166 free(transaction->updates[i]);
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -07001167 }
Michael Haggertycaa40462014-04-07 15:48:10 +02001168 free(transaction->updates);
1169 free(transaction);
1170}
1171
Michael Haggerty71564512016-04-25 11:39:54 +02001172struct ref_update *ref_transaction_add_update(
1173 struct ref_transaction *transaction,
1174 const char *refname, unsigned int flags,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001175 const struct object_id *new_oid,
1176 const struct object_id *old_oid,
Michael Haggerty71564512016-04-25 11:39:54 +02001177 const char *msg)
Michael Haggertycaa40462014-04-07 15:48:10 +02001178{
Jeff King96ffc062016-02-22 17:44:32 -05001179 struct ref_update *update;
Michael Haggerty71564512016-04-25 11:39:54 +02001180
1181 if (transaction->state != REF_TRANSACTION_OPEN)
Johannes Schindelin033abf92018-05-02 11:38:39 +02001182 BUG("update called for transaction that is not open");
Michael Haggerty71564512016-04-25 11:39:54 +02001183
Jeff King96ffc062016-02-22 17:44:32 -05001184 FLEX_ALLOC_STR(update, refname, refname);
Michael Haggertycaa40462014-04-07 15:48:10 +02001185 ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
1186 transaction->updates[transaction->nr++] = update;
Michael Haggerty71564512016-04-25 11:39:54 +02001187
1188 update->flags = flags;
1189
1190 if (flags & REF_HAVE_NEW)
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001191 oidcpy(&update->new_oid, new_oid);
Michael Haggerty71564512016-04-25 11:39:54 +02001192 if (flags & REF_HAVE_OLD)
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001193 oidcpy(&update->old_oid, old_oid);
Junio C Hamano523fa692020-07-10 17:19:53 +00001194 update->msg = normalize_reflog_message(msg);
Michael Haggertycaa40462014-04-07 15:48:10 +02001195 return update;
1196}
1197
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001198int ref_transaction_update(struct ref_transaction *transaction,
1199 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001200 const struct object_id *new_oid,
1201 const struct object_id *old_oid,
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001202 unsigned int flags, const char *msg,
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001203 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001204{
Jonathan Nieder5a603b02014-08-28 16:42:37 -07001205 assert(err);
1206
Han-Wen Nienhuys3c966c72021-12-07 13:38:18 +00001207 if (!(flags & REF_SKIP_REFNAME_VERIFICATION) &&
1208 ((new_oid && !is_null_oid(new_oid)) ?
1209 check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) :
1210 !refname_is_safe(refname))) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001211 strbuf_addf(err, _("refusing to update ref with bad name '%s'"),
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -07001212 refname);
1213 return -1;
1214 }
1215
Michael Haggertya9bbbce2017-11-05 09:42:03 +01001216 if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
1217 BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
Thomas Gummererc788c542017-09-12 23:59:21 +01001218
Jeff King49f1eb32021-11-19 16:28:30 -05001219 /*
1220 * Clear flags outside the allowed set; this should be a noop because
1221 * of the BUG() check above, but it works around a -Wnonnull warning
1222 * with some versions of "gcc -O3".
1223 */
1224 flags &= REF_TRANSACTION_UPDATE_ALLOWED_FLAGS;
1225
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001226 flags |= (new_oid ? REF_HAVE_NEW : 0) | (old_oid ? REF_HAVE_OLD : 0);
Michael Haggerty71564512016-04-25 11:39:54 +02001227
1228 ref_transaction_add_update(transaction, refname, flags,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001229 new_oid, old_oid, msg);
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001230 return 0;
Michael Haggertycaa40462014-04-07 15:48:10 +02001231}
1232
Ronnie Sahlbergb416af52014-04-16 15:26:44 -07001233int ref_transaction_create(struct ref_transaction *transaction,
1234 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001235 const struct object_id *new_oid,
Michael Haggertyfec14ec2015-02-17 18:00:13 +01001236 unsigned int flags, const char *msg,
Ronnie Sahlbergb416af52014-04-16 15:26:44 -07001237 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001238{
Derrick Stoleed097a232022-04-25 13:47:30 +00001239 if (!new_oid || is_null_oid(new_oid)) {
1240 strbuf_addf(err, "'%s' has a null OID", refname);
1241 return 1;
1242 }
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001243 return ref_transaction_update(transaction, refname, new_oid,
brian m. carlson14228442021-04-26 01:02:56 +00001244 null_oid(), flags, msg, err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001245}
1246
Ronnie Sahlberg8c8bdc02014-04-16 15:27:45 -07001247int ref_transaction_delete(struct ref_transaction *transaction,
1248 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001249 const struct object_id *old_oid,
Michael Haggertyfb5a6bb2015-02-17 18:00:16 +01001250 unsigned int flags, const char *msg,
Ronnie Sahlberg8c8bdc02014-04-16 15:27:45 -07001251 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001252{
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001253 if (old_oid && is_null_oid(old_oid))
Johannes Schindelin033abf92018-05-02 11:38:39 +02001254 BUG("delete called with old_oid set to zeros");
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001255 return ref_transaction_update(transaction, refname,
brian m. carlson14228442021-04-26 01:02:56 +00001256 null_oid(), old_oid,
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001257 flags, msg, err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001258}
1259
Michael Haggerty16180332015-02-17 18:00:21 +01001260int ref_transaction_verify(struct ref_transaction *transaction,
1261 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001262 const struct object_id *old_oid,
Michael Haggerty16180332015-02-17 18:00:21 +01001263 unsigned int flags,
1264 struct strbuf *err)
1265{
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001266 if (!old_oid)
Johannes Schindelin033abf92018-05-02 11:38:39 +02001267 BUG("verify called with old_oid set to NULL");
Michael Haggerty16180332015-02-17 18:00:21 +01001268 return ref_transaction_update(transaction, refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001269 NULL, old_oid,
Michael Haggerty16180332015-02-17 18:00:21 +01001270 flags, NULL, err);
1271}
1272
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001273int refs_update_ref(struct ref_store *refs, const char *msg,
brian m. carlsonae077772017-10-15 22:06:51 +00001274 const char *refname, const struct object_id *new_oid,
1275 const struct object_id *old_oid, unsigned int flags,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001276 enum action_on_err onerr)
Brad King4738a332013-09-04 11:22:40 -04001277{
David Turner74ec19d2015-07-31 02:06:19 -04001278 struct ref_transaction *t = NULL;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001279 struct strbuf err = STRBUF_INIT;
David Turner74ec19d2015-07-31 02:06:19 -04001280 int ret = 0;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001281
Junio C Hamanoc6da34a2022-04-13 15:51:33 -07001282 t = ref_store_transaction_begin(refs, &err);
Han-Wen Nienhuys09743412020-07-27 16:25:46 +00001283 if (!t ||
1284 ref_transaction_update(t, refname, new_oid, old_oid, flags, msg,
1285 &err) ||
1286 ref_transaction_commit(t, &err)) {
1287 ret = 1;
1288 ref_transaction_free(t);
David Turner74ec19d2015-07-31 02:06:19 -04001289 }
1290 if (ret) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001291 const char *str = _("update_ref failed for ref '%s': %s");
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001292
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001293 switch (onerr) {
1294 case UPDATE_REFS_MSG_ON_ERR:
1295 error(str, refname, err.buf);
1296 break;
1297 case UPDATE_REFS_DIE_ON_ERR:
1298 die(str, refname, err.buf);
1299 break;
1300 case UPDATE_REFS_QUIET_ON_ERR:
1301 break;
1302 }
1303 strbuf_release(&err);
Brad King4738a332013-09-04 11:22:40 -04001304 return 1;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001305 }
1306 strbuf_release(&err);
David Turner74ec19d2015-07-31 02:06:19 -04001307 if (t)
1308 ref_transaction_free(t);
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001309 return 0;
Brad King4738a332013-09-04 11:22:40 -04001310}
1311
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001312int update_ref(const char *msg, const char *refname,
brian m. carlsonae077772017-10-15 22:06:51 +00001313 const struct object_id *new_oid,
1314 const struct object_id *old_oid,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001315 unsigned int flags, enum action_on_err onerr)
1316{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001317 return refs_update_ref(get_main_ref_store(the_repository), msg, refname, new_oid,
brian m. carlsonae077772017-10-15 22:06:51 +00001318 old_oid, flags, onerr);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001319}
1320
Jeff King613bef52023-02-15 10:16:21 -05001321/*
1322 * Check that the string refname matches a rule of the form
1323 * "{prefix}%.*s{suffix}". So "foo/bar/baz" would match the rule
1324 * "foo/%.*s/baz", and return the string "bar".
1325 */
1326static const char *match_parse_rule(const char *refname, const char *rule,
1327 size_t *len)
1328{
1329 /*
1330 * Check that rule matches refname up to the first percent in the rule.
1331 * We can bail immediately if not, but otherwise we leave "rule" at the
1332 * %-placeholder, and "refname" at the start of the potential matched
1333 * name.
1334 */
1335 while (*rule != '%') {
1336 if (!*rule)
1337 BUG("rev-parse rule did not have percent");
1338 if (*refname++ != *rule++)
1339 return NULL;
1340 }
1341
1342 /*
1343 * Check that our "%" is the expected placeholder. This assumes there
1344 * are no other percents (placeholder or quoted) in the string, but
1345 * that is sufficient for our rev-parse rules.
1346 */
1347 if (!skip_prefix(rule, "%.*s", &rule))
1348 return NULL;
1349
1350 /*
1351 * And now check that our suffix (if any) matches.
1352 */
1353 if (!strip_suffix(refname, rule, len))
1354 return NULL;
1355
1356 return refname; /* len set by strip_suffix() */
1357}
1358
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001359char *refs_shorten_unambiguous_ref(struct ref_store *refs,
1360 const char *refname, int strict)
Jeff King7c2b3022009-04-07 03:14:20 -04001361{
1362 int i;
Jeff King6cd4a892017-03-28 15:46:33 -04001363 struct strbuf resolved_buf = STRBUF_INIT;
Jeff King7c2b3022009-04-07 03:14:20 -04001364
Jeff King7c2b3022009-04-07 03:14:20 -04001365 /* skip first rule, it will always match */
Jeff King8f416f62023-02-15 10:16:18 -05001366 for (i = NUM_REV_PARSE_RULES - 1; i > 0 ; --i) {
Jeff King7c2b3022009-04-07 03:14:20 -04001367 int j;
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001368 int rules_to_fail = i;
Jeff King613bef52023-02-15 10:16:21 -05001369 const char *short_name;
Jeff Kingdd5e4d32023-02-15 10:16:14 -05001370 size_t short_name_len;
Jeff King7c2b3022009-04-07 03:14:20 -04001371
Jeff King613bef52023-02-15 10:16:21 -05001372 short_name = match_parse_rule(refname, ref_rev_parse_rules[i],
1373 &short_name_len);
1374 if (!short_name)
Jeff King7c2b3022009-04-07 03:14:20 -04001375 continue;
1376
Jeff King7c2b3022009-04-07 03:14:20 -04001377 /*
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001378 * in strict mode, all (except the matched one) rules
1379 * must fail to resolve to a valid non-ambiguous ref
1380 */
1381 if (strict)
Jeff King8f416f62023-02-15 10:16:18 -05001382 rules_to_fail = NUM_REV_PARSE_RULES;
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001383
1384 /*
Jeff King7c2b3022009-04-07 03:14:20 -04001385 * check if the short name resolves to a valid ref,
1386 * but use only rules prior to the matched one
1387 */
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001388 for (j = 0; j < rules_to_fail; j++) {
Jeff King7c2b3022009-04-07 03:14:20 -04001389 const char *rule = ref_rev_parse_rules[j];
Jeff King7c2b3022009-04-07 03:14:20 -04001390
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001391 /* skip matched rule */
1392 if (i == j)
1393 continue;
1394
Jeff King7c2b3022009-04-07 03:14:20 -04001395 /*
1396 * the short name is ambiguous, if it resolves
1397 * (with this previous rule) to a valid ref
1398 * read_ref() returns 0 on success
1399 */
Jeff King6cd4a892017-03-28 15:46:33 -04001400 strbuf_reset(&resolved_buf);
1401 strbuf_addf(&resolved_buf, rule,
Jeff Kingdd5e4d32023-02-15 10:16:14 -05001402 cast_size_t_to_int(short_name_len),
1403 short_name);
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001404 if (refs_ref_exists(refs, resolved_buf.buf))
Jeff King7c2b3022009-04-07 03:14:20 -04001405 break;
1406 }
1407
1408 /*
1409 * short name is non-ambiguous if all previous rules
1410 * haven't resolved to a valid ref
1411 */
Jeff King6cd4a892017-03-28 15:46:33 -04001412 if (j == rules_to_fail) {
1413 strbuf_release(&resolved_buf);
Jeff King613bef52023-02-15 10:16:21 -05001414 return xmemdupz(short_name, short_name_len);
Jeff King6cd4a892017-03-28 15:46:33 -04001415 }
Jeff King7c2b3022009-04-07 03:14:20 -04001416 }
1417
Jeff King6cd4a892017-03-28 15:46:33 -04001418 strbuf_release(&resolved_buf);
Michael Haggertydfefa932011-12-12 06:38:09 +01001419 return xstrdup(refname);
Jeff King7c2b3022009-04-07 03:14:20 -04001420}
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001421
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001422char *shorten_unambiguous_ref(const char *refname, int strict)
1423{
1424 return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
1425 refname, strict);
1426}
1427
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001428int parse_hide_refs_config(const char *var, const char *value, const char *section,
1429 struct string_list *hide_refs)
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001430{
Jeff Kingad8c7cd2017-02-24 16:08:16 -05001431 const char *key;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001432 if (!strcmp("transfer.hiderefs", var) ||
Jeff Kingad8c7cd2017-02-24 16:08:16 -05001433 (!parse_config_key(var, section, NULL, NULL, &key) &&
1434 !strcmp(key, "hiderefs"))) {
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001435 char *ref;
1436 int len;
1437
1438 if (!value)
1439 return config_error_nonbool(var);
1440 ref = xstrdup(value);
1441 len = strlen(ref);
1442 while (len && ref[len - 1] == '/')
1443 ref[--len] = '\0';
Patrick Steinhardt5eeb9aa2022-11-17 06:46:39 +01001444 string_list_append_nodup(hide_refs, ref);
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001445 }
1446 return 0;
1447}
1448
Patrick Steinhardt9b67eb62022-11-17 06:46:43 +01001449int ref_is_hidden(const char *refname, const char *refname_full,
1450 const struct string_list *hide_refs)
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001451{
Jeff King2bc31d12015-07-28 16:23:26 -04001452 int i;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001453
Jeff King2bc31d12015-07-28 16:23:26 -04001454 for (i = hide_refs->nr - 1; i >= 0; i--) {
1455 const char *match = hide_refs->items[i].string;
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001456 const char *subject;
Jeff King2bc31d12015-07-28 16:23:26 -04001457 int neg = 0;
Christian Couder7a40a952017-07-22 06:39:12 +02001458 const char *p;
Jeff King2bc31d12015-07-28 16:23:26 -04001459
1460 if (*match == '!') {
1461 neg = 1;
1462 match++;
1463 }
1464
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001465 if (*match == '^') {
1466 subject = refname_full;
1467 match++;
1468 } else {
1469 subject = refname;
1470 }
1471
1472 /* refname can be NULL when namespaces are used. */
Christian Couder7a40a952017-07-22 06:39:12 +02001473 if (subject &&
1474 skip_prefix(subject, match, &p) &&
1475 (!*p || *p == '/'))
Jeff King2bc31d12015-07-28 16:23:26 -04001476 return !neg;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001477 }
1478 return 0;
1479}
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001480
David Turner08451222015-11-10 12:42:40 +01001481const char *find_descendant_ref(const char *dirname,
1482 const struct string_list *extras,
1483 const struct string_list *skip)
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001484{
David Turner08451222015-11-10 12:42:40 +01001485 int pos;
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001486
David Turner08451222015-11-10 12:42:40 +01001487 if (!extras)
1488 return NULL;
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001489
1490 /*
David Turner08451222015-11-10 12:42:40 +01001491 * Look at the place where dirname would be inserted into
1492 * extras. If there is an entry at that position that starts
1493 * with dirname (remember, dirname includes the trailing
1494 * slash) and is not in skip, then we have a conflict.
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001495 */
David Turner08451222015-11-10 12:42:40 +01001496 for (pos = string_list_find_insert_index(extras, dirname, 0);
1497 pos < extras->nr; pos++) {
1498 const char *extra_refname = extras->items[pos].string;
1499
1500 if (!starts_with(extra_refname, dirname))
1501 break;
1502
1503 if (!skip || !string_list_has_string(skip, extra_refname))
1504 return extra_refname;
Michael Haggerty4a32b2e2015-05-11 17:25:15 +02001505 }
David Turner08451222015-11-10 12:42:40 +01001506 return NULL;
1507}
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001508
Nguyễn Thái Ngọc Duy62f0b392017-08-23 19:36:55 +07001509int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turner2bf68ed2016-04-07 15:02:48 -04001510{
1511 struct object_id oid;
1512 int flag;
1513
Ævar Arnfjörð Bjarmasonf1da24c2021-10-16 11:39:27 +02001514 if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001515 &oid, &flag))
David Turner2bf68ed2016-04-07 15:02:48 -04001516 return fn("HEAD", &oid, flag, cb_data);
1517
1518 return 0;
1519}
1520
1521int head_ref(each_ref_fn fn, void *cb_data)
1522{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001523 return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data);
David Turner2bf68ed2016-04-07 15:02:48 -04001524}
David Turner93770592016-04-07 15:02:49 -04001525
Michael Haggertye121b9c2017-03-20 17:33:08 +01001526struct ref_iterator *refs_ref_iterator_begin(
1527 struct ref_store *refs,
Jeff King9aab9522021-09-24 14:39:44 -04001528 const char *prefix, int trim,
1529 enum do_for_each_ref_flags flags)
Michael Haggertye121b9c2017-03-20 17:33:08 +01001530{
1531 struct ref_iterator *iter;
1532
Jeff King6d751be2021-09-24 14:42:38 -04001533 if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
Jeff King5d1f5b82021-09-24 14:46:37 -04001534 static int ref_paranoia = -1;
1535
Jeff King6d751be2021-09-24 14:42:38 -04001536 if (ref_paranoia < 0)
Jeff King968f12f2021-09-24 14:46:13 -04001537 ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 1);
Jeff King6d751be2021-09-24 14:42:38 -04001538 if (ref_paranoia) {
1539 flags |= DO_FOR_EACH_INCLUDE_BROKEN;
1540 flags |= DO_FOR_EACH_OMIT_DANGLING_SYMREFS;
1541 }
1542 }
Michael Haggerty0a0865b2017-05-22 16:17:52 +02001543
Michael Haggertye121b9c2017-03-20 17:33:08 +01001544 iter = refs->be->iterator_begin(refs, prefix, flags);
Michael Haggertyc7599712017-05-22 16:17:36 +02001545
1546 /*
1547 * `iterator_begin()` already takes care of prefix, but we
1548 * might need to do some trimming:
1549 */
1550 if (trim)
1551 iter = prefix_ref_iterator_begin(iter, "", trim);
Michael Haggertye121b9c2017-03-20 17:33:08 +01001552
Michael Haggerty8738a8a2017-09-13 19:15:55 +02001553 /* Sanity check for subclasses: */
1554 if (!iter->ordered)
1555 BUG("reference iterator is not ordered");
1556
Michael Haggertye121b9c2017-03-20 17:33:08 +01001557 return iter;
1558}
1559
Michael Haggerty4c4de892016-06-18 06:15:16 +02001560/*
1561 * Call fn for each reference in the specified submodule for which the
1562 * refname begins with prefix. If trim is non-zero, then trim that
1563 * many characters off the beginning of each refname before passing
1564 * the refname to fn. flags can be DO_FOR_EACH_INCLUDE_BROKEN to
1565 * include broken references in the iteration. If fn ever returns a
1566 * non-zero value, stop the iteration and return that value;
1567 * otherwise, return 0.
1568 */
Stefan Beller4a6067c2018-08-20 18:24:16 +00001569static int do_for_each_repo_ref(struct repository *r, const char *prefix,
1570 each_repo_ref_fn fn, int trim, int flags,
1571 void *cb_data)
Michael Haggerty4c4de892016-06-18 06:15:16 +02001572{
1573 struct ref_iterator *iter;
Stefan Beller4a6067c2018-08-20 18:24:16 +00001574 struct ref_store *refs = get_main_ref_store(r);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001575
Michael Haggerty00eebe32016-09-04 18:08:11 +02001576 if (!refs)
1577 return 0;
1578
Michael Haggertye121b9c2017-03-20 17:33:08 +01001579 iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001580
Stefan Beller4a6067c2018-08-20 18:24:16 +00001581 return do_for_each_repo_ref_iterator(r, iter, fn, cb_data);
1582}
1583
1584struct do_for_each_ref_help {
1585 each_ref_fn *fn;
1586 void *cb_data;
1587};
1588
1589static int do_for_each_ref_helper(struct repository *r,
1590 const char *refname,
1591 const struct object_id *oid,
1592 int flags,
1593 void *cb_data)
1594{
1595 struct do_for_each_ref_help *hp = cb_data;
1596
1597 return hp->fn(refname, oid, flags, hp->cb_data);
1598}
1599
1600static int do_for_each_ref(struct ref_store *refs, const char *prefix,
Jeff King9aab9522021-09-24 14:39:44 -04001601 each_ref_fn fn, int trim,
1602 enum do_for_each_ref_flags flags, void *cb_data)
Stefan Beller4a6067c2018-08-20 18:24:16 +00001603{
1604 struct ref_iterator *iter;
1605 struct do_for_each_ref_help hp = { fn, cb_data };
1606
1607 if (!refs)
1608 return 0;
1609
1610 iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
1611
1612 return do_for_each_repo_ref_iterator(the_repository, iter,
1613 do_for_each_ref_helper, &hp);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001614}
1615
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001616int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
1617{
1618 return do_for_each_ref(refs, "", fn, 0, 0, cb_data);
1619}
1620
David Turner93770592016-04-07 15:02:49 -04001621int for_each_ref(each_ref_fn fn, void *cb_data)
1622{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001623 return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data);
David Turner93770592016-04-07 15:02:49 -04001624}
1625
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001626int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
1627 each_ref_fn fn, void *cb_data)
1628{
1629 return do_for_each_ref(refs, prefix, fn, strlen(prefix), 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001630}
1631
1632int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
1633{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001634 return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data);
David Turner93770592016-04-07 15:02:49 -04001635}
1636
Jeff King67985e42021-09-24 14:48:48 -04001637int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001638{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001639 return do_for_each_ref(get_main_ref_store(the_repository),
Jeff King67985e42021-09-24 14:48:48 -04001640 prefix, fn, 0, 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001641}
1642
Nguyễn Thái Ngọc Duy073cf632017-08-23 19:36:56 +07001643int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
Jeff King67985e42021-09-24 14:48:48 -04001644 each_ref_fn fn, void *cb_data)
Michael Haggerty03df5672017-06-18 15:39:41 +02001645{
Jeff King67985e42021-09-24 14:48:48 -04001646 return do_for_each_ref(refs, prefix, fn, 0, 0, cb_data);
Michael Haggerty03df5672017-06-18 15:39:41 +02001647}
1648
Stefan Beller212e0f72018-08-20 18:24:19 +00001649int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001650{
Derrick Stolee97e61e02022-08-05 17:58:37 +00001651 const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
Stefan Beller212e0f72018-08-20 18:24:19 +00001652 return do_for_each_repo_ref(r, git_replace_ref_base, fn,
1653 strlen(git_replace_ref_base),
1654 DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
David Turner93770592016-04-07 15:02:49 -04001655}
1656
1657int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
1658{
1659 struct strbuf buf = STRBUF_INIT;
1660 int ret;
1661 strbuf_addf(&buf, "%srefs/", get_git_namespace());
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001662 ret = do_for_each_ref(get_main_ref_store(the_repository),
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001663 buf.buf, fn, 0, 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001664 strbuf_release(&buf);
1665 return ret;
1666}
1667
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001668int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001669{
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001670 return do_for_each_ref(refs, "", fn, 0,
David Turner93770592016-04-07 15:02:49 -04001671 DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
1672}
David Turner2d0663b2016-04-07 15:03:10 -04001673
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001674int for_each_rawref(each_ref_fn fn, void *cb_data)
1675{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001676 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 +07001677}
1678
Taylor Blau16b19852021-01-20 11:04:21 -05001679static int qsort_strcmp(const void *va, const void *vb)
1680{
1681 const char *a = *(const char **)va;
1682 const char *b = *(const char **)vb;
1683
1684 return strcmp(a, b);
1685}
1686
1687static void find_longest_prefixes_1(struct string_list *out,
1688 struct strbuf *prefix,
1689 const char **patterns, size_t nr)
1690{
1691 size_t i;
1692
1693 for (i = 0; i < nr; i++) {
1694 char c = patterns[i][prefix->len];
1695 if (!c || is_glob_special(c)) {
1696 string_list_append(out, prefix->buf);
1697 return;
1698 }
1699 }
1700
1701 i = 0;
1702 while (i < nr) {
1703 size_t end;
1704
1705 /*
1706 * Set "end" to the index of the element _after_ the last one
1707 * in our group.
1708 */
1709 for (end = i + 1; end < nr; end++) {
1710 if (patterns[i][prefix->len] != patterns[end][prefix->len])
1711 break;
1712 }
1713
1714 strbuf_addch(prefix, patterns[i][prefix->len]);
1715 find_longest_prefixes_1(out, prefix, patterns + i, end - i);
1716 strbuf_setlen(prefix, prefix->len - 1);
1717
1718 i = end;
1719 }
1720}
1721
1722static void find_longest_prefixes(struct string_list *out,
1723 const char **patterns)
1724{
1725 struct strvec sorted = STRVEC_INIT;
1726 struct strbuf prefix = STRBUF_INIT;
1727
1728 strvec_pushv(&sorted, patterns);
1729 QSORT(sorted.v, sorted.nr, qsort_strcmp);
1730
1731 find_longest_prefixes_1(out, &prefix, sorted.v, sorted.nr);
1732
1733 strvec_clear(&sorted);
1734 strbuf_release(&prefix);
1735}
1736
Jeff King91e2ab12022-12-13 06:11:10 -05001737int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
1738 const char *namespace,
1739 const char **patterns,
1740 each_ref_fn fn, void *cb_data)
Taylor Blau16b19852021-01-20 11:04:21 -05001741{
1742 struct string_list prefixes = STRING_LIST_INIT_DUP;
1743 struct string_list_item *prefix;
1744 struct strbuf buf = STRBUF_INIT;
1745 int ret = 0, namespace_len;
1746
1747 find_longest_prefixes(&prefixes, patterns);
1748
1749 if (namespace)
1750 strbuf_addstr(&buf, namespace);
1751 namespace_len = buf.len;
1752
1753 for_each_string_list_item(prefix, &prefixes) {
1754 strbuf_addstr(&buf, prefix->string);
Jeff King91e2ab12022-12-13 06:11:10 -05001755 ret = refs_for_each_fullref_in(ref_store, buf.buf, fn, cb_data);
Taylor Blau16b19852021-01-20 11:04:21 -05001756 if (ret)
1757 break;
1758 strbuf_setlen(&buf, namespace_len);
1759 }
1760
1761 string_list_clear(&prefixes, 0);
1762 strbuf_release(&buf);
1763 return ret;
1764}
1765
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001766static int refs_read_special_head(struct ref_store *ref_store,
1767 const char *refname, struct object_id *oid,
Han-Wen Nienhuysdf3458e2021-10-16 11:39:10 +02001768 struct strbuf *referent, unsigned int *type,
1769 int *failure_errno)
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001770{
1771 struct strbuf full_path = STRBUF_INIT;
1772 struct strbuf content = STRBUF_INIT;
1773 int result = -1;
1774 strbuf_addf(&full_path, "%s/%s", ref_store->gitdir, refname);
1775
1776 if (strbuf_read_file(&content, full_path.buf, 0) < 0)
1777 goto done;
1778
Han-Wen Nienhuysdf3458e2021-10-16 11:39:10 +02001779 result = parse_loose_ref_contents(content.buf, oid, referent, type,
1780 failure_errno);
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001781
1782done:
1783 strbuf_release(&full_path);
1784 strbuf_release(&content);
1785 return result;
1786}
1787
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001788int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
1789 struct object_id *oid, struct strbuf *referent,
1790 unsigned int *type, int *failure_errno)
Michael Haggerty470be512017-03-20 17:33:07 +01001791{
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001792 assert(failure_errno);
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001793 if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) {
1794 return refs_read_special_head(ref_store, refname, oid, referent,
Han-Wen Nienhuysdf3458e2021-10-16 11:39:10 +02001795 type, failure_errno);
Han-Wen Nienhuyse8115302020-08-19 14:27:58 +00001796 }
1797
1798 return ref_store->be->read_raw_ref(ref_store, refname, oid, referent,
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001799 type, failure_errno);
Michael Haggerty470be512017-03-20 17:33:07 +01001800}
1801
Patrick Steinhardtcd475b32022-03-01 10:33:46 +01001802int refs_read_symbolic_ref(struct ref_store *ref_store, const char *refname,
1803 struct strbuf *referent)
1804{
Ævar Arnfjörð Bjarmason5b875402022-03-17 18:27:19 +01001805 return ref_store->be->read_symbolic_ref(ref_store, refname, referent);
Patrick Steinhardtcd475b32022-03-01 10:33:46 +01001806}
1807
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001808const char *refs_resolve_ref_unsafe(struct ref_store *refs,
Michael Haggerty3c0cb0c2017-02-09 21:53:52 +01001809 const char *refname,
1810 int resolve_flags,
Ævar Arnfjörð Bjarmasonef181192021-10-16 11:39:08 +02001811 struct object_id *oid,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001812 int *flags)
David Turner2d0663b2016-04-07 15:03:10 -04001813{
1814 static struct strbuf sb_refname = STRBUF_INIT;
René Scharfe54fad662017-09-23 11:41:45 +02001815 struct object_id unused_oid;
David Turner2d0663b2016-04-07 15:03:10 -04001816 int unused_flags;
1817 int symref_count;
1818
brian m. carlson49e61472017-10-15 22:07:09 +00001819 if (!oid)
1820 oid = &unused_oid;
David Turner2d0663b2016-04-07 15:03:10 -04001821 if (!flags)
1822 flags = &unused_flags;
1823
1824 *flags = 0;
1825
1826 if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
1827 if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001828 !refname_is_safe(refname))
David Turner2d0663b2016-04-07 15:03:10 -04001829 return NULL;
David Turner2d0663b2016-04-07 15:03:10 -04001830
1831 /*
Ævar Arnfjörð Bjarmasonc7c33f52023-03-28 15:58:57 +02001832 * repo_dwim_ref() uses REF_ISBROKEN to distinguish between
David Turner2d0663b2016-04-07 15:03:10 -04001833 * missing refs and refs that were present but invalid,
1834 * to complain about the latter to stderr.
1835 *
1836 * We don't know whether the ref exists, so don't set
1837 * REF_ISBROKEN yet.
1838 */
1839 *flags |= REF_BAD_NAME;
1840 }
1841
1842 for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
1843 unsigned int read_flags = 0;
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001844 int failure_errno;
David Turner2d0663b2016-04-07 15:03:10 -04001845
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02001846 if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001847 &read_flags, &failure_errno)) {
David Turner2d0663b2016-04-07 15:03:10 -04001848 *flags |= read_flags;
Jeff Kinga1c1d812017-10-06 10:42:17 -04001849
1850 /* In reading mode, refs must eventually resolve */
1851 if (resolve_flags & RESOLVE_REF_READING)
David Turner2d0663b2016-04-07 15:03:10 -04001852 return NULL;
Jeff Kinga1c1d812017-10-06 10:42:17 -04001853
1854 /*
1855 * Otherwise a missing ref is OK. But the files backend
1856 * may show errors besides ENOENT if there are
1857 * similarly-named refs.
1858 */
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001859 if (failure_errno != ENOENT &&
1860 failure_errno != EISDIR &&
1861 failure_errno != ENOTDIR)
Jeff Kinga1c1d812017-10-06 10:42:17 -04001862 return NULL;
1863
brian m. carlson49e61472017-10-15 22:07:09 +00001864 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001865 if (*flags & REF_BAD_NAME)
1866 *flags |= REF_ISBROKEN;
1867 return refname;
1868 }
1869
1870 *flags |= read_flags;
1871
1872 if (!(read_flags & REF_ISSYMREF)) {
1873 if (*flags & REF_BAD_NAME) {
brian m. carlson49e61472017-10-15 22:07:09 +00001874 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001875 *flags |= REF_ISBROKEN;
1876 }
1877 return refname;
1878 }
1879
1880 refname = sb_refname.buf;
1881 if (resolve_flags & RESOLVE_REF_NO_RECURSE) {
brian m. carlson49e61472017-10-15 22:07:09 +00001882 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001883 return refname;
1884 }
1885 if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
1886 if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001887 !refname_is_safe(refname))
David Turner2d0663b2016-04-07 15:03:10 -04001888 return NULL;
David Turner2d0663b2016-04-07 15:03:10 -04001889
1890 *flags |= REF_ISBROKEN | REF_BAD_NAME;
1891 }
1892 }
1893
David Turner2d0663b2016-04-07 15:03:10 -04001894 return NULL;
1895}
Michael Haggerty00eebe32016-09-04 18:08:11 +02001896
David Turner6fb5acf2016-09-04 18:08:41 +02001897/* backend functions */
1898int refs_init_db(struct strbuf *err)
1899{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001900 struct ref_store *refs = get_main_ref_store(the_repository);
David Turner6fb5acf2016-09-04 18:08:41 +02001901
1902 return refs->be->init_db(refs, err);
1903}
1904
Michael Haggertybd40dcd2016-09-04 18:08:21 +02001905const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
brian m. carlson49e61472017-10-15 22:07:09 +00001906 struct object_id *oid, int *flags)
Michael Haggertybd40dcd2016-09-04 18:08:21 +02001907{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001908 return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname,
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001909 resolve_flags, oid, flags);
Michael Haggertybd40dcd2016-09-04 18:08:21 +02001910}
1911
Michael Haggertya8355bb2016-09-04 18:08:24 +02001912int resolve_gitlink_ref(const char *submodule, const char *refname,
brian m. carlsona98e6102017-10-15 22:07:07 +00001913 struct object_id *oid)
Michael Haggerty424dcc72016-09-04 18:08:22 +02001914{
Michael Haggerty424dcc72016-09-04 18:08:22 +02001915 struct ref_store *refs;
1916 int flags;
1917
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07001918 refs = get_submodule_ref_store(submodule);
Michael Haggerty48a84752016-09-04 18:08:23 +02001919
Michael Haggerty424dcc72016-09-04 18:08:22 +02001920 if (!refs)
1921 return -1;
1922
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +01001923 if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags) ||
1924 is_null_oid(oid))
Michael Haggerty424dcc72016-09-04 18:08:22 +02001925 return -1;
1926 return 0;
1927}
1928
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001929struct ref_store_hash_entry
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001930{
Eric Wonge2b50382019-10-06 23:30:43 +00001931 struct hashmap_entry ent;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001932
1933 struct ref_store *refs;
1934
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001935 /* NUL-terminated identifier of the ref store: */
1936 char name[FLEX_ARRAY];
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001937};
1938
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02001939static int ref_store_hash_cmp(const void *cmp_data UNUSED,
Eric Wong939af162019-10-06 23:30:37 +00001940 const struct hashmap_entry *eptr,
1941 const struct hashmap_entry *entry_or_key,
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001942 const void *keydata)
1943{
Eric Wong939af162019-10-06 23:30:37 +00001944 const struct ref_store_hash_entry *e1, *e2;
1945 const char *name;
1946
1947 e1 = container_of(eptr, const struct ref_store_hash_entry, ent);
1948 e2 = container_of(entry_or_key, const struct ref_store_hash_entry, ent);
1949 name = keydata ? keydata : e2->name;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001950
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001951 return strcmp(e1->name, name);
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001952}
1953
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001954static struct ref_store_hash_entry *alloc_ref_store_hash_entry(
1955 const char *name, struct ref_store *refs)
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001956{
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001957 struct ref_store_hash_entry *entry;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001958
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001959 FLEX_ALLOC_STR(entry, name, name);
Eric Wongd22245a2019-10-06 23:30:27 +00001960 hashmap_entry_init(&entry->ent, strhash(name));
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001961 entry->refs = refs;
1962 return entry;
1963}
1964
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001965/* A hashmap of ref_stores, stored by submodule name: */
1966static struct hashmap submodule_ref_stores;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001967
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07001968/* A hashmap of ref_stores, stored by worktree id: */
1969static struct hashmap worktree_ref_stores;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001970
Michael Haggerty00eebe32016-09-04 18:08:11 +02001971/*
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001972 * Look up a ref store by name. If that ref_store hasn't been
1973 * registered yet, return NULL.
Michael Haggerty00eebe32016-09-04 18:08:11 +02001974 */
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001975static struct ref_store *lookup_ref_store_map(struct hashmap *map,
1976 const char *name)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001977{
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001978 struct ref_store_hash_entry *entry;
Eric Wongf23a4652019-10-06 23:30:36 +00001979 unsigned int hash;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001980
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001981 if (!map->tablesize)
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001982 /* It's initialized on demand in register_ref_store(). */
1983 return NULL;
Michael Haggerty620a66b2017-02-10 12:16:11 +01001984
Eric Wongf23a4652019-10-06 23:30:36 +00001985 hash = strhash(name);
1986 entry = hashmap_get_entry_from_hash(map, hash, name,
1987 struct ref_store_hash_entry, ent);
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001988 return entry ? entry->refs : NULL;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001989}
1990
Michael Haggertyc468da42017-02-10 12:16:12 +01001991/*
1992 * Create, record, and return a ref_store instance for the specified
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07001993 * gitdir.
Michael Haggertyc468da42017-02-10 12:16:12 +01001994 */
Jonathan Tan34224e12021-10-08 14:08:14 -07001995static struct ref_store *ref_store_init(struct repository *repo,
1996 const char *gitdir,
Nguyễn Thái Ngọc Duy9e7ec632017-03-26 09:42:32 +07001997 unsigned int flags)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001998{
1999 const char *be_name = "files";
2000 struct ref_storage_be *be = find_ref_storage_backend(be_name);
Michael Haggertyba88add2017-02-10 12:16:14 +01002001 struct ref_store *refs;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002002
2003 if (!be)
Johannes Schindelin033abf92018-05-02 11:38:39 +02002004 BUG("reference backend %s is unknown", be_name);
Michael Haggerty00eebe32016-09-04 18:08:11 +02002005
Jonathan Tan34224e12021-10-08 14:08:14 -07002006 refs = be->init(repo, gitdir, flags);
Michael Haggertyba88add2017-02-10 12:16:14 +01002007 return refs;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002008}
2009
Stefan Beller64a74162018-04-11 17:21:14 -07002010struct ref_store *get_main_ref_store(struct repository *r)
Michael Haggerty00eebe32016-09-04 18:08:11 +02002011{
Jeff King02204612020-04-09 23:04:11 -04002012 if (r->refs_private)
2013 return r->refs_private;
Nguyễn Thái Ngọc Duy24c84072017-03-26 09:42:25 +07002014
Jeff King2dc417a2018-05-18 15:25:53 -07002015 if (!r->gitdir)
2016 BUG("attempting to get main_ref_store outside of repository");
2017
Jonathan Tan34224e12021-10-08 14:08:14 -07002018 r->refs_private = ref_store_init(r, r->gitdir, REF_STORE_ALL_CAPS);
Han-Wen Nienhuys4441f422020-09-09 10:15:08 +00002019 r->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private);
Jeff King02204612020-04-09 23:04:11 -04002020 return r->refs_private;
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07002021}
2022
2023/*
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002024 * Associate a ref store with a name. It is a fatal error to call this
2025 * function twice for the same name.
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07002026 */
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002027static void register_ref_store_map(struct hashmap *map,
2028 const char *type,
2029 struct ref_store *refs,
2030 const char *name)
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07002031{
Eric Wong26b455f2019-10-06 23:30:32 +00002032 struct ref_store_hash_entry *entry;
2033
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002034 if (!map->tablesize)
Stefan Beller7663cdc2017-06-30 12:14:05 -07002035 hashmap_init(map, ref_store_hash_cmp, NULL, 0);
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07002036
Eric Wong26b455f2019-10-06 23:30:32 +00002037 entry = alloc_ref_store_hash_entry(name, refs);
2038 if (hashmap_put(map, &entry->ent))
Johannes Schindelin033abf92018-05-02 11:38:39 +02002039 BUG("%s ref_store '%s' initialized twice", type, name);
Nguyễn Thái Ngọc Duy24c84072017-03-26 09:42:25 +07002040}
2041
Nguyễn Thái Ngọc Duy18d00022017-03-26 09:42:33 +07002042struct ref_store *get_submodule_ref_store(const char *submodule)
Michael Haggerty00eebe32016-09-04 18:08:11 +02002043{
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07002044 struct strbuf submodule_sb = STRBUF_INIT;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002045 struct ref_store *refs;
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07002046 char *to_free = NULL;
2047 size_t len;
Jonathan Tan34224e12021-10-08 14:08:14 -07002048 struct repository *subrepo;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002049
Nguyễn Thái Ngọc Duy82a150f2017-08-23 19:37:03 +07002050 if (!submodule)
2051 return NULL;
2052
Nguyễn Thái Ngọc Duy873ea902017-08-23 19:37:04 +07002053 len = strlen(submodule);
2054 while (len && is_dir_sep(submodule[len - 1]))
2055 len--;
2056 if (!len)
2057 return NULL;
Michael Haggerty00eebe32016-09-04 18:08:11 +02002058
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07002059 if (submodule[len])
2060 /* We need to strip off one or more trailing slashes */
2061 submodule = to_free = xmemdupz(submodule, len);
Michael Haggerty00eebe32016-09-04 18:08:11 +02002062
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002063 refs = lookup_ref_store_map(&submodule_ref_stores, submodule);
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07002064 if (refs)
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07002065 goto done;
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07002066
2067 strbuf_addstr(&submodule_sb, submodule);
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07002068 if (!is_nonbare_repository_dir(&submodule_sb))
2069 goto done;
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07002070
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07002071 if (submodule_to_gitdir(&submodule_sb, submodule))
2072 goto done;
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07002073
Jonathan Tan34224e12021-10-08 14:08:14 -07002074 subrepo = xmalloc(sizeof(*subrepo));
2075 /*
2076 * NEEDSWORK: Make get_submodule_ref_store() work with arbitrary
2077 * superprojects other than the_repository. This probably should be
2078 * done by making it take a struct repository * parameter instead of a
2079 * submodule path.
2080 */
2081 if (repo_submodule_init(subrepo, the_repository, submodule,
2082 null_oid())) {
2083 free(subrepo);
2084 goto done;
2085 }
2086 refs = ref_store_init(subrepo, submodule_sb.buf,
Nguyễn Thái Ngọc Duy9e7ec632017-03-26 09:42:32 +07002087 REF_STORE_READ | REF_STORE_ODB);
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07002088 register_ref_store_map(&submodule_ref_stores, "submodule",
2089 refs, submodule);
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07002090
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07002091done:
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07002092 strbuf_release(&submodule_sb);
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07002093 free(to_free);
2094
Michael Haggerty00eebe32016-09-04 18:08:11 +02002095 return refs;
2096}
2097
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07002098struct ref_store *get_worktree_ref_store(const struct worktree *wt)
2099{
2100 struct ref_store *refs;
2101 const char *id;
2102
2103 if (wt->is_current)
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002104 return get_main_ref_store(the_repository);
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07002105
2106 id = wt->id ? wt->id : "/";
2107 refs = lookup_ref_store_map(&worktree_ref_stores, id);
2108 if (refs)
2109 return refs;
2110
2111 if (wt->id)
Jonathan Tan34224e12021-10-08 14:08:14 -07002112 refs = ref_store_init(the_repository,
2113 git_common_path("worktrees/%s", wt->id),
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07002114 REF_STORE_ALL_CAPS);
2115 else
Jonathan Tan34224e12021-10-08 14:08:14 -07002116 refs = ref_store_init(the_repository,
2117 get_git_common_dir(),
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07002118 REF_STORE_ALL_CAPS);
2119
2120 if (refs)
2121 register_ref_store_map(&worktree_ref_stores, "worktree",
2122 refs, id);
2123 return refs;
2124}
2125
Han-Wen Nienhuysf9f7fd32021-12-22 18:11:54 +00002126void base_ref_store_init(struct ref_store *refs, struct repository *repo,
2127 const char *path, const struct ref_storage_be *be)
Michael Haggerty00eebe32016-09-04 18:08:11 +02002128{
Michael Haggerty620a66b2017-02-10 12:16:11 +01002129 refs->be = be;
Han-Wen Nienhuysf9f7fd32021-12-22 18:11:54 +00002130 refs->repo = repo;
2131 refs->gitdir = xstrdup(path);
Michael Haggerty00eebe32016-09-04 18:08:11 +02002132}
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002133
2134/* backend functions */
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002135int refs_pack_refs(struct ref_store *refs, unsigned int flags)
Michael Haggerty82315272016-09-04 18:08:27 +02002136{
Michael Haggerty82315272016-09-04 18:08:27 +02002137 return refs->be->pack_refs(refs, flags);
2138}
2139
Jeff King36a31792021-01-20 14:44:43 -05002140int peel_iterated_oid(const struct object_id *base, struct object_id *peeled)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002141{
Jeff King36a31792021-01-20 14:44:43 -05002142 if (current_ref_iter &&
2143 (current_ref_iter->oid == base ||
2144 oideq(current_ref_iter->oid, base)))
2145 return ref_iterator_peel(current_ref_iter, peeled);
Michael Haggertyba1c0522017-09-25 10:00:14 +02002146
Han-Wen Nienhuys617480d2021-05-19 15:31:28 +00002147 return peel_object(base, peeled) ? -1 : 0;
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002148}
Michael Haggertybd427cf2016-09-04 18:08:29 +02002149
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002150int refs_create_symref(struct ref_store *refs,
2151 const char *ref_target,
2152 const char *refs_heads_master,
2153 const char *logmsg)
2154{
Junio C Hamano523fa692020-07-10 17:19:53 +00002155 char *msg;
2156 int retval;
2157
2158 msg = normalize_reflog_message(logmsg);
2159 retval = refs->be->create_symref(refs, ref_target, refs_heads_master,
2160 msg);
2161 free(msg);
2162 return retval;
Michael Haggertybd427cf2016-09-04 18:08:29 +02002163}
2164
Michael Haggerty284689b2016-09-04 18:08:28 +02002165int create_symref(const char *ref_target, const char *refs_heads_master,
2166 const char *logmsg)
2167{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002168 return refs_create_symref(get_main_ref_store(the_repository), ref_target,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002169 refs_heads_master, logmsg);
Michael Haggerty284689b2016-09-04 18:08:28 +02002170}
2171
Michael Haggerty2ced1052017-05-22 16:17:45 +02002172int ref_update_reject_duplicates(struct string_list *refnames,
2173 struct strbuf *err)
2174{
Michael Haggertya552e502017-05-22 16:17:46 +02002175 size_t i, n = refnames->nr;
Michael Haggerty2ced1052017-05-22 16:17:45 +02002176
2177 assert(err);
2178
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002179 for (i = 1; i < n; i++) {
2180 int cmp = strcmp(refnames->items[i - 1].string,
2181 refnames->items[i].string);
2182
2183 if (!cmp) {
Michael Haggerty2ced1052017-05-22 16:17:45 +02002184 strbuf_addf(err,
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002185 _("multiple updates for ref '%s' not allowed"),
Michael Haggerty2ced1052017-05-22 16:17:45 +02002186 refnames->items[i].string);
2187 return 1;
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002188 } else if (cmp > 0) {
Johannes Schindelin033abf92018-05-02 11:38:39 +02002189 BUG("ref_update_reject_duplicates() received unsorted list");
Michael Haggerty2ced1052017-05-22 16:17:45 +02002190 }
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002191 }
Michael Haggerty2ced1052017-05-22 16:17:45 +02002192 return 0;
2193}
2194
Patrick Steinhardt67541592020-06-19 08:56:14 +02002195static int run_transaction_hook(struct ref_transaction *transaction,
2196 const char *state)
2197{
2198 struct child_process proc = CHILD_PROCESS_INIT;
2199 struct strbuf buf = STRBUF_INIT;
Patrick Steinhardt0a0fbbe2020-08-25 12:35:24 +02002200 const char *hook;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002201 int ret = 0, i;
2202
Patrick Steinhardt0a0fbbe2020-08-25 12:35:24 +02002203 hook = find_hook("reference-transaction");
Patrick Steinhardt67541592020-06-19 08:56:14 +02002204 if (!hook)
Patrick Steinhardt67541592020-06-19 08:56:14 +02002205 return ret;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002206
Jeff Kingc972bf42020-07-28 16:25:12 -04002207 strvec_pushl(&proc.args, hook, state, NULL);
Patrick Steinhardt67541592020-06-19 08:56:14 +02002208 proc.in = -1;
2209 proc.stdout_to_stderr = 1;
2210 proc.trace2_hook_name = "reference-transaction";
2211
2212 ret = start_command(&proc);
2213 if (ret)
2214 return ret;
2215
2216 sigchain_push(SIGPIPE, SIG_IGN);
2217
2218 for (i = 0; i < transaction->nr; i++) {
2219 struct ref_update *update = transaction->updates[i];
2220
2221 strbuf_reset(&buf);
2222 strbuf_addf(&buf, "%s %s %s\n",
2223 oid_to_hex(&update->old_oid),
2224 oid_to_hex(&update->new_oid),
2225 update->refname);
2226
2227 if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
Ævar Arnfjörð Bjarmason4755d7d2021-10-16 11:39:25 +02002228 if (errno != EPIPE) {
2229 /* Don't leak errno outside this API */
2230 errno = 0;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002231 ret = -1;
Ævar Arnfjörð Bjarmason4755d7d2021-10-16 11:39:25 +02002232 }
Patrick Steinhardt67541592020-06-19 08:56:14 +02002233 break;
2234 }
2235 }
2236
2237 close(proc.in);
2238 sigchain_pop(SIGPIPE);
2239 strbuf_release(&buf);
2240
2241 ret |= finish_command(&proc);
2242 return ret;
2243}
2244
Michael Haggerty30173b82017-05-22 16:17:44 +02002245int ref_transaction_prepare(struct ref_transaction *transaction,
2246 struct strbuf *err)
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002247{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07002248 struct ref_store *refs = transaction->ref_store;
Patrick Steinhardt67541592020-06-19 08:56:14 +02002249 int ret;
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002250
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002251 switch (transaction->state) {
2252 case REF_TRANSACTION_OPEN:
2253 /* Good. */
2254 break;
Michael Haggerty30173b82017-05-22 16:17:44 +02002255 case REF_TRANSACTION_PREPARED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002256 BUG("prepare called twice on reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002257 break;
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002258 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002259 BUG("prepare called on a closed reference transaction");
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002260 break;
2261 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002262 BUG("unexpected reference transaction state");
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002263 break;
2264 }
2265
Neeraj Singhecd81df2021-12-06 22:05:05 +00002266 if (refs->repo->objects->odb->disable_ref_updates) {
Jeff Kingd8f44812017-04-10 18:14:12 -04002267 strbuf_addstr(err,
2268 _("ref updates forbidden inside quarantine environment"));
2269 return -1;
2270 }
2271
Patrick Steinhardt67541592020-06-19 08:56:14 +02002272 ret = refs->be->transaction_prepare(refs, transaction, err);
2273 if (ret)
2274 return ret;
2275
2276 ret = run_transaction_hook(transaction, "prepared");
2277 if (ret) {
2278 ref_transaction_abort(transaction, err);
2279 die(_("ref updates aborted by hook"));
2280 }
2281
2282 return 0;
Michael Haggerty30173b82017-05-22 16:17:44 +02002283}
2284
2285int ref_transaction_abort(struct ref_transaction *transaction,
2286 struct strbuf *err)
2287{
2288 struct ref_store *refs = transaction->ref_store;
2289 int ret = 0;
2290
2291 switch (transaction->state) {
2292 case REF_TRANSACTION_OPEN:
2293 /* No need to abort explicitly. */
2294 break;
2295 case REF_TRANSACTION_PREPARED:
2296 ret = refs->be->transaction_abort(refs, transaction, err);
2297 break;
2298 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002299 BUG("abort called on a closed reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002300 break;
2301 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002302 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02002303 break;
2304 }
2305
Patrick Steinhardt67541592020-06-19 08:56:14 +02002306 run_transaction_hook(transaction, "aborted");
2307
Michael Haggerty30173b82017-05-22 16:17:44 +02002308 ref_transaction_free(transaction);
2309 return ret;
2310}
2311
2312int ref_transaction_commit(struct ref_transaction *transaction,
2313 struct strbuf *err)
2314{
2315 struct ref_store *refs = transaction->ref_store;
2316 int ret;
2317
2318 switch (transaction->state) {
2319 case REF_TRANSACTION_OPEN:
2320 /* Need to prepare first. */
2321 ret = ref_transaction_prepare(transaction, err);
2322 if (ret)
2323 return ret;
2324 break;
2325 case REF_TRANSACTION_PREPARED:
2326 /* Fall through to finish. */
2327 break;
2328 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002329 BUG("commit called on a closed reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002330 break;
2331 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002332 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02002333 break;
2334 }
2335
Patrick Steinhardt67541592020-06-19 08:56:14 +02002336 ret = refs->be->transaction_finish(refs, transaction, err);
2337 if (!ret)
2338 run_transaction_hook(transaction, "committed");
2339 return ret;
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02002340}
Michael Haggerty62665822016-09-04 18:08:26 +02002341
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002342int refs_verify_refname_available(struct ref_store *refs,
2343 const char *refname,
Michael Haggertyb05855b2017-04-16 08:41:26 +02002344 const struct string_list *extras,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002345 const struct string_list *skip,
2346 struct strbuf *err)
Michael Haggerty62665822016-09-04 18:08:26 +02002347{
Michael Haggertyb05855b2017-04-16 08:41:26 +02002348 const char *slash;
2349 const char *extra_refname;
2350 struct strbuf dirname = STRBUF_INIT;
2351 struct strbuf referent = STRBUF_INIT;
2352 struct object_id oid;
2353 unsigned int type;
2354 struct ref_iterator *iter;
2355 int ok;
2356 int ret = -1;
2357
2358 /*
2359 * For the sake of comments in this function, suppose that
2360 * refname is "refs/foo/bar".
2361 */
2362
2363 assert(err);
2364
2365 strbuf_grow(&dirname, strlen(refname) + 1);
2366 for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02002367 /*
2368 * Just saying "Is a directory" when we e.g. can't
2369 * lock some multi-level ref isn't very informative,
2370 * the user won't be told *what* is a directory, so
2371 * let's not use strerror() below.
2372 */
2373 int ignore_errno;
Michael Haggertyb05855b2017-04-16 08:41:26 +02002374 /* Expand dirname to the new prefix, not including the trailing slash: */
2375 strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
2376
2377 /*
2378 * We are still at a leading dir of the refname (e.g.,
2379 * "refs/foo"; if there is a reference with that name,
2380 * it is a conflict, *unless* it is in skip.
2381 */
2382 if (skip && string_list_has_string(skip, dirname.buf))
2383 continue;
2384
Han-Wen Nienhuys8b72fea2021-10-16 11:39:09 +02002385 if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent,
2386 &type, &ignore_errno)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002387 strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002388 dirname.buf, refname);
2389 goto cleanup;
2390 }
2391
2392 if (extras && string_list_has_string(extras, dirname.buf)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002393 strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002394 refname, dirname.buf);
2395 goto cleanup;
2396 }
2397 }
2398
2399 /*
2400 * We are at the leaf of our refname (e.g., "refs/foo/bar").
2401 * There is no point in searching for a reference with that
2402 * name, because a refname isn't considered to conflict with
2403 * itself. But we still need to check for references whose
2404 * names are in the "refs/foo/bar/" namespace, because they
2405 * *do* conflict.
2406 */
2407 strbuf_addstr(&dirname, refname + dirname.len);
2408 strbuf_addch(&dirname, '/');
2409
2410 iter = refs_ref_iterator_begin(refs, dirname.buf, 0,
2411 DO_FOR_EACH_INCLUDE_BROKEN);
2412 while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
2413 if (skip &&
2414 string_list_has_string(skip, iter->refname))
2415 continue;
2416
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002417 strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002418 iter->refname, refname);
2419 ref_iterator_abort(iter);
2420 goto cleanup;
2421 }
2422
2423 if (ok != ITER_DONE)
Johannes Schindelin033abf92018-05-02 11:38:39 +02002424 BUG("error while iterating over references");
Michael Haggertyb05855b2017-04-16 08:41:26 +02002425
2426 extra_refname = find_descendant_ref(dirname.buf, extras, skip);
2427 if (extra_refname)
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002428 strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002429 refname, extra_refname);
2430 else
2431 ret = 0;
2432
2433cleanup:
2434 strbuf_release(&referent);
2435 strbuf_release(&dirname);
2436 return ret;
Michael Haggerty62665822016-09-04 18:08:26 +02002437}
David Turnere3688bd2016-09-04 18:08:38 +02002438
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002439int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turnere3688bd2016-09-04 18:08:38 +02002440{
David Turnere3688bd2016-09-04 18:08:38 +02002441 struct ref_iterator *iter;
Stefan Beller4a6067c2018-08-20 18:24:16 +00002442 struct do_for_each_ref_help hp = { fn, cb_data };
David Turnere3688bd2016-09-04 18:08:38 +02002443
2444 iter = refs->be->reflog_iterator_begin(refs);
2445
Stefan Beller4a6067c2018-08-20 18:24:16 +00002446 return do_for_each_repo_ref_iterator(the_repository, iter,
2447 do_for_each_ref_helper, &hp);
David Turnere3688bd2016-09-04 18:08:38 +02002448}
2449
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002450int for_each_reflog(each_ref_fn fn, void *cb_data)
2451{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002452 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 +07002453}
2454
2455int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
2456 const char *refname,
2457 each_reflog_ent_fn fn,
2458 void *cb_data)
2459{
2460 return refs->be->for_each_reflog_ent_reverse(refs, refname,
2461 fn, cb_data);
2462}
2463
David Turnere3688bd2016-09-04 18:08:38 +02002464int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
2465 void *cb_data)
2466{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002467 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 +07002468 refname, fn, cb_data);
2469}
David Turnere3688bd2016-09-04 18:08:38 +02002470
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002471int refs_for_each_reflog_ent(struct ref_store *refs, const char *refname,
2472 each_reflog_ent_fn fn, void *cb_data)
2473{
2474 return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002475}
2476
2477int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
2478 void *cb_data)
2479{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002480 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 +07002481 fn, cb_data);
2482}
David Turnere3688bd2016-09-04 18:08:38 +02002483
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002484int refs_reflog_exists(struct ref_store *refs, const char *refname)
2485{
2486 return refs->be->reflog_exists(refs, refname);
David Turnere3688bd2016-09-04 18:08:38 +02002487}
2488
2489int reflog_exists(const char *refname)
2490{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002491 return refs_reflog_exists(get_main_ref_store(the_repository), refname);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002492}
David Turnere3688bd2016-09-04 18:08:38 +02002493
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002494int refs_create_reflog(struct ref_store *refs, const char *refname,
David Turnere3688bd2016-09-04 18:08:38 +02002495 struct strbuf *err)
2496{
Han-Wen Nienhuys7b089122021-11-22 14:19:08 +00002497 return refs->be->create_reflog(refs, refname, err);
2498}
2499
2500int safe_create_reflog(const char *refname, struct strbuf *err)
2501{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002502 return refs_create_reflog(get_main_ref_store(the_repository), refname,
Han-Wen Nienhuys7b089122021-11-22 14:19:08 +00002503 err);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002504}
David Turnere3688bd2016-09-04 18:08:38 +02002505
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002506int refs_delete_reflog(struct ref_store *refs, const char *refname)
2507{
2508 return refs->be->delete_reflog(refs, refname);
David Turnere3688bd2016-09-04 18:08:38 +02002509}
2510
2511int delete_reflog(const char *refname)
2512{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002513 return refs_delete_reflog(get_main_ref_store(the_repository), refname);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002514}
David Turnere3688bd2016-09-04 18:08:38 +02002515
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002516int refs_reflog_expire(struct ref_store *refs,
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002517 const char *refname,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002518 unsigned int flags,
2519 reflog_expiry_prepare_fn prepare_fn,
2520 reflog_expiry_should_prune_fn should_prune_fn,
2521 reflog_expiry_cleanup_fn cleanup_fn,
2522 void *policy_cb_data)
2523{
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002524 return refs->be->reflog_expire(refs, refname, flags,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002525 prepare_fn, should_prune_fn,
2526 cleanup_fn, policy_cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002527}
2528
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002529int reflog_expire(const char *refname,
David Turnere3688bd2016-09-04 18:08:38 +02002530 unsigned int flags,
2531 reflog_expiry_prepare_fn prepare_fn,
2532 reflog_expiry_should_prune_fn should_prune_fn,
2533 reflog_expiry_cleanup_fn cleanup_fn,
2534 void *policy_cb_data)
2535{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002536 return refs_reflog_expire(get_main_ref_store(the_repository),
Ævar Arnfjörð Bjarmasoncc40b5c2021-08-23 13:36:11 +02002537 refname, flags,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002538 prepare_fn, should_prune_fn,
2539 cleanup_fn, policy_cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002540}
David Turnerfc681462016-09-04 18:08:39 +02002541
2542int initial_ref_transaction_commit(struct ref_transaction *transaction,
2543 struct strbuf *err)
2544{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07002545 struct ref_store *refs = transaction->ref_store;
David Turnerfc681462016-09-04 18:08:39 +02002546
2547 return refs->be->initial_transaction_commit(refs, transaction, err);
2548}
David Turnera27dcf82016-09-04 18:08:40 +02002549
Patrick Steinhardt4f2ba2d2022-02-17 14:04:32 +01002550void ref_transaction_for_each_queued_update(struct ref_transaction *transaction,
2551 ref_transaction_for_each_queued_update_fn cb,
2552 void *cb_data)
2553{
2554 int i;
2555
2556 for (i = 0; i < transaction->nr; i++) {
2557 struct ref_update *update = transaction->updates[i];
2558
2559 cb(update->refname,
2560 (update->flags & REF_HAVE_OLD) ? &update->old_oid : NULL,
2561 (update->flags & REF_HAVE_NEW) ? &update->new_oid : NULL,
2562 cb_data);
2563 }
2564}
2565
Junio C Hamano523fa692020-07-10 17:19:53 +00002566int refs_delete_refs(struct ref_store *refs, const char *logmsg,
Michael Haggerty64da4192017-05-22 16:17:38 +02002567 struct string_list *refnames, unsigned int flags)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002568{
Junio C Hamano523fa692020-07-10 17:19:53 +00002569 char *msg;
2570 int retval;
2571
2572 msg = normalize_reflog_message(logmsg);
2573 retval = refs->be->delete_refs(refs, msg, refnames, flags);
2574 free(msg);
2575 return retval;
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002576}
2577
Michael Haggerty64da4192017-05-22 16:17:38 +02002578int delete_refs(const char *msg, struct string_list *refnames,
2579 unsigned int flags)
David Turnera27dcf82016-09-04 18:08:40 +02002580{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002581 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 +07002582}
David Turnera27dcf82016-09-04 18:08:40 +02002583
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002584int refs_rename_ref(struct ref_store *refs, const char *oldref,
2585 const char *newref, const char *logmsg)
2586{
Junio C Hamano523fa692020-07-10 17:19:53 +00002587 char *msg;
2588 int retval;
2589
2590 msg = normalize_reflog_message(logmsg);
2591 retval = refs->be->rename_ref(refs, oldref, newref, msg);
2592 free(msg);
2593 return retval;
David Turnera27dcf82016-09-04 18:08:40 +02002594}
David Turner9b6b40d2016-09-04 18:08:42 +02002595
2596int rename_ref(const char *oldref, const char *newref, const char *logmsg)
2597{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002598 return refs_rename_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
David Turner9b6b40d2016-09-04 18:08:42 +02002599}
Sahil Dua52d59cc2017-06-18 23:19:16 +02002600
2601int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
2602 const char *newref, const char *logmsg)
2603{
Junio C Hamano523fa692020-07-10 17:19:53 +00002604 char *msg;
2605 int retval;
2606
2607 msg = normalize_reflog_message(logmsg);
2608 retval = refs->be->copy_ref(refs, oldref, newref, msg);
2609 free(msg);
2610 return retval;
Sahil Dua52d59cc2017-06-18 23:19:16 +02002611}
2612
2613int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)
2614{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002615 return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
Sahil Dua52d59cc2017-06-18 23:19:16 +02002616}