blob: 1ab0bb54d3d73bfe17f0eab4cd02d760bb9a7d01 [file] [log] [blame]
Michael Haggerty7bd9bcf2015-11-09 14:34:01 +01001/*
2 * The backend-independent part of the reference module.
3 */
4
Daniel Barkalow95fc7512005-06-06 16:31:29 -04005#include "cache.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07006#include "config.h"
Michael Haggerty7d4558c2017-02-10 12:16:15 +01007#include "hashmap.h"
Michael Haggerty697cc8e2014-10-01 12:28:42 +02008#include "lockfile.h"
Michael Haggertyb05855b2017-04-16 08:41:26 +02009#include "iterator.h"
Junio C Hamano85023572006-12-19 14:34:12 -080010#include "refs.h"
Michael Haggerty4cb77002015-11-10 12:42:36 +010011#include "refs/refs-internal.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -070012#include "object-store.h"
Junio C Hamanocf0adba2006-11-19 13:22:44 -080013#include "object.h"
14#include "tag.h"
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +070015#include "submodule.h"
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +070016#include "worktree.h"
Brandon Williamsb4be7412018-03-15 10:31:24 -070017#include "argv-array.h"
Stefan Beller23a3f0c2018-04-11 17:21:09 -070018#include "repository.h"
Stefan Beller3581d792014-12-12 09:57:02 +010019
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020020/*
Ronnie Sahlberg3dce4442016-09-04 18:08:10 +020021 * List of all available backends
22 */
23static struct ref_storage_be *refs_backends = &refs_be_files;
24
25static struct ref_storage_be *find_ref_storage_backend(const char *name)
26{
27 struct ref_storage_be *be;
28 for (be = refs_backends; be; be = be->next)
29 if (!strcmp(be->name, name))
30 return be;
31 return NULL;
32}
33
34int ref_storage_backend_exists(const char *name)
35{
36 return find_ref_storage_backend(name) != NULL;
37}
38
39/*
David Turnerdde8a902014-06-03 23:38:10 -040040 * How to handle various characters in refnames:
41 * 0: An acceptable character for refs
Junio C Hamano5e650222014-07-28 10:41:53 -070042 * 1: End-of-component
43 * 2: ., look for a preceding . to reject .. in refs
44 * 3: {, look for a preceding @ to reject @{ in refs
Jacob Keller53a85552015-07-22 14:05:32 -070045 * 4: A bad character: ASCII control characters, and
Jacob Kellercd377f42015-07-22 14:05:33 -070046 * ":", "?", "[", "\", "^", "~", SP, or TAB
47 * 5: *, reject unless REFNAME_REFSPEC_PATTERN is set
David Turnerdde8a902014-06-03 23:38:10 -040048 */
49static unsigned char refname_disposition[256] = {
Junio C Hamano5e650222014-07-28 10:41:53 -070050 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
51 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
Jacob Kellercd377f42015-07-22 14:05:33 -070052 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 1,
Junio C Hamano5e650222014-07-28 10:41:53 -070053 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,
David Turnerdde8a902014-06-03 23:38:10 -040054 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Junio C Hamano5e650222014-07-28 10:41:53 -070055 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
David Turnerdde8a902014-06-03 23:38:10 -040058};
59
60/*
61 * Try to read one refname component from the front of refname.
62 * Return the length of the component found, or -1 if the component is
63 * not legal. It is legal if it is something reasonable to have under
64 * ".git/refs/"; We do not like it if:
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020065 *
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070066 * - it begins with ".", or
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020067 * - it has double dots "..", or
Jacob Keller53a85552015-07-22 14:05:32 -070068 * - it has ASCII control characters, or
Jacob Kellercd377f42015-07-22 14:05:33 -070069 * - it has ":", "?", "[", "\", "^", "~", SP, or TAB anywhere, or
70 * - it has "*" anywhere unless REFNAME_REFSPEC_PATTERN is set, or
Jacob Keller53a85552015-07-22 14:05:32 -070071 * - it ends with a "/", or
72 * - it ends with ".lock", or
73 * - it contains a "@{" portion
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070074 *
75 * When sanitized is not NULL, instead of rejecting the input refname
76 * as an error, try to come up with a usable replacement for the input
77 * refname in it.
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020078 */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070079static int check_refname_component(const char *refname, int *flags,
80 struct strbuf *sanitized)
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020081{
82 const char *cp;
83 char last = '\0';
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070084 size_t component_start = 0; /* garbage - not a reasonable initial value */
85
86 if (sanitized)
87 component_start = sanitized->len;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +020088
89 for (cp = refname; ; cp++) {
David Turnerdde8a902014-06-03 23:38:10 -040090 int ch = *cp & 255;
91 unsigned char disp = refname_disposition[ch];
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +070092
93 if (sanitized && disp != 1)
94 strbuf_addch(sanitized, ch);
95
David Turnerdde8a902014-06-03 23:38:10 -040096 switch (disp) {
Junio C Hamano5e650222014-07-28 10:41:53 -070097 case 1:
David Turnerdde8a902014-06-03 23:38:10 -040098 goto out;
Junio C Hamano5e650222014-07-28 10:41:53 -070099 case 2:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700100 if (last == '.') { /* Refname contains "..". */
101 if (sanitized)
102 /* collapse ".." to single "." */
103 strbuf_setlen(sanitized, sanitized->len - 1);
104 else
105 return -1;
106 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200107 break;
Junio C Hamano5e650222014-07-28 10:41:53 -0700108 case 3:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700109 if (last == '@') { /* Refname contains "@{". */
110 if (sanitized)
111 sanitized->buf[sanitized->len-1] = '-';
112 else
113 return -1;
114 }
David Turnerdde8a902014-06-03 23:38:10 -0400115 break;
Junio C Hamano5e650222014-07-28 10:41:53 -0700116 case 4:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700117 /* forbidden char */
118 if (sanitized)
119 sanitized->buf[sanitized->len-1] = '-';
120 else
121 return -1;
122 break;
Jacob Kellercd377f42015-07-22 14:05:33 -0700123 case 5:
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700124 if (!(*flags & REFNAME_REFSPEC_PATTERN)) {
125 /* refspec can't be a pattern */
126 if (sanitized)
127 sanitized->buf[sanitized->len-1] = '-';
128 else
129 return -1;
130 }
Jacob Kellercd377f42015-07-22 14:05:33 -0700131
132 /*
133 * Unset the pattern flag so that we only accept
134 * a single asterisk for one side of refspec.
135 */
136 *flags &= ~ REFNAME_REFSPEC_PATTERN;
137 break;
David Turnerdde8a902014-06-03 23:38:10 -0400138 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200139 last = ch;
140 }
David Turnerdde8a902014-06-03 23:38:10 -0400141out:
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200142 if (cp == refname)
Michael Haggertydac529e2012-04-10 07:30:22 +0200143 return 0; /* Component has zero length. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700144
145 if (refname[0] == '.') { /* Component starts with '.'. */
146 if (sanitized)
147 sanitized->buf[component_start] = '-';
148 else
149 return -1;
150 }
Michael Haggerty7108ad22014-10-01 12:28:15 +0200151 if (cp - refname >= LOCK_SUFFIX_LEN &&
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700152 !memcmp(cp - LOCK_SUFFIX_LEN, LOCK_SUFFIX, LOCK_SUFFIX_LEN)) {
153 if (!sanitized)
154 return -1;
155 /* Refname ends with ".lock". */
156 while (strbuf_strip_suffix(sanitized, LOCK_SUFFIX)) {
157 /* try again in case we have .lock.lock */
158 }
159 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200160 return cp - refname;
161}
162
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700163static int check_or_sanitize_refname(const char *refname, int flags,
164 struct strbuf *sanitized)
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200165{
166 int component_len, component_count = 0;
167
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700168 if (!strcmp(refname, "@")) {
Felipe Contreras9ba89f42013-09-02 01:34:30 -0500169 /* Refname is a single character '@'. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700170 if (sanitized)
171 strbuf_addch(sanitized, '-');
172 else
173 return -1;
174 }
Felipe Contreras9ba89f42013-09-02 01:34:30 -0500175
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200176 while (1) {
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700177 if (sanitized && sanitized->len)
178 strbuf_complete(sanitized, '/');
179
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200180 /* We are at the start of a path component. */
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700181 component_len = check_refname_component(refname, &flags,
182 sanitized);
183 if (sanitized && component_len == 0)
184 ; /* OK, omit empty component */
185 else if (component_len <= 0)
Jacob Kellercd377f42015-07-22 14:05:33 -0700186 return -1;
187
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200188 component_count++;
189 if (refname[component_len] == '\0')
190 break;
191 /* Skip to next component. */
192 refname += component_len + 1;
193 }
194
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700195 if (refname[component_len - 1] == '.') {
196 /* Refname ends with '.'. */
197 if (sanitized)
198 ; /* omit ending dot */
199 else
200 return -1;
201 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200202 if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
203 return -1; /* Refname has only one component. */
204 return 0;
205}
206
Nguyễn Thái Ngọc Duy1de16ae2019-03-08 16:28:34 +0700207int check_refname_format(const char *refname, int flags)
208{
209 return check_or_sanitize_refname(refname, flags, NULL);
210}
211
212void sanitize_refname_component(const char *refname, struct strbuf *out)
213{
214 if (check_or_sanitize_refname(refname, REFNAME_ALLOW_ONELEVEL, out))
215 BUG("sanitizing refname '%s' check returned error", refname);
216}
217
Michael Haggerty4cb77002015-11-10 12:42:36 +0100218int refname_is_safe(const char *refname)
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700219{
Michael Haggerty39950fe2016-04-27 12:39:11 +0200220 const char *rest;
221
222 if (skip_prefix(refname, "refs/", &rest)) {
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700223 char *buf;
224 int result;
Michael Haggertye40f3552016-04-27 12:40:39 +0200225 size_t restlen = strlen(rest);
226
227 /* rest must not be empty, or start or end with "/" */
228 if (!restlen || *rest == '/' || rest[restlen - 1] == '/')
229 return 0;
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700230
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700231 /*
232 * Does the refname try to escape refs/?
233 * For example: refs/foo/../bar is safe but refs/foo/../../bar
234 * is not.
235 */
Michael Haggertye40f3552016-04-27 12:40:39 +0200236 buf = xmallocz(restlen);
237 result = !normalize_path_copy(buf, rest) && !strcmp(buf, rest);
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700238 free(buf);
239 return result;
240 }
Michael Haggerty35db25c2016-04-27 12:42:27 +0200241
242 do {
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700243 if (!isupper(*refname) && *refname != '_')
244 return 0;
245 refname++;
Michael Haggerty35db25c2016-04-27 12:42:27 +0200246 } while (*refname);
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -0700247 return 1;
248}
249
Michael Haggerty67be7c52017-06-23 09:01:37 +0200250/*
251 * Return true if refname, which has the specified oid and flags, can
252 * be resolved to an object in the database. If the referred-to object
253 * does not exist, emit a warning and return false.
254 */
255int ref_resolves_to_object(const char *refname,
256 const struct object_id *oid,
257 unsigned int flags)
258{
259 if (flags & REF_ISBROKEN)
260 return 0;
Jeff King98374a02019-01-07 03:37:54 -0500261 if (!has_object_file(oid)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200262 error(_("%s does not point to a valid object!"), refname);
Michael Haggerty67be7c52017-06-23 09:01:37 +0200263 return 0;
264 }
265 return 1;
266}
267
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700268char *refs_resolve_refdup(struct ref_store *refs,
269 const char *refname, int resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000270 struct object_id *oid, int *flags)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700271{
272 const char *result;
273
274 result = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
brian m. carlson49e61472017-10-15 22:07:09 +0000275 oid, flags);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700276 return xstrdup_or_null(result);
277}
278
Michael Haggertyfb58c8d2015-06-22 16:03:05 +0200279char *resolve_refdup(const char *refname, int resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000280 struct object_id *oid, int *flags)
Nguyễn Thái Ngọc Duy96ec7b12011-12-13 21:17:48 +0700281{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700282 return refs_resolve_refdup(get_main_ref_store(the_repository),
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700283 refname, resolve_flags,
brian m. carlson0f2dc722017-10-15 22:06:55 +0000284 oid, flags);
Nguyễn Thái Ngọc Duy96ec7b12011-12-13 21:17:48 +0700285}
286
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200287/* The argument to filter_refs */
288struct ref_filter {
289 const char *pattern;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000290 const char *prefix;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200291 each_ref_fn *fn;
292 void *cb_data;
293};
294
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700295int refs_read_ref_full(struct ref_store *refs, const char *refname,
brian m. carlson34c290a2017-10-15 22:06:56 +0000296 int resolve_flags, struct object_id *oid, int *flags)
Linus Torvalds8a65ff72005-07-02 20:23:36 -0700297{
brian m. carlson49e61472017-10-15 22:07:09 +0000298 if (refs_resolve_ref_unsafe(refs, refname, resolve_flags, oid, flags))
Junio C Hamanoa876ed82005-09-30 14:08:25 -0700299 return 0;
300 return -1;
Linus Torvalds8a65ff72005-07-02 20:23:36 -0700301}
302
brian m. carlson34c290a2017-10-15 22:06:56 +0000303int 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 +0700304{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700305 return refs_read_ref_full(get_main_ref_store(the_repository), refname,
brian m. carlson34c290a2017-10-15 22:06:56 +0000306 resolve_flags, oid, flags);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700307}
308
brian m. carlson34c290a2017-10-15 22:06:56 +0000309int read_ref(const char *refname, struct object_id *oid)
Nguyễn Thái Ngọc Duyc6893322011-11-13 17:22:14 +0700310{
brian m. carlson34c290a2017-10-15 22:06:56 +0000311 return read_ref_full(refname, RESOLVE_REF_READING, oid, NULL);
Nguyễn Thái Ngọc Duyc6893322011-11-13 17:22:14 +0700312}
313
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700314static int refs_ref_exists(struct ref_store *refs, const char *refname)
315{
316 return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING, NULL, NULL);
317}
318
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200319int ref_exists(const char *refname)
Junio C Hamanoef06b912006-11-18 22:13:33 -0800320{
Nguyễn Thái Ngọc Duyb3cd33d2019-04-06 18:34:24 +0700321 return refs_ref_exists(get_main_ref_store(the_repository), refname);
Junio C Hamanoef06b912006-11-18 22:13:33 -0800322}
323
Rafael Ascensão65516f52017-11-21 21:33:41 +0000324static int match_ref_pattern(const char *refname,
325 const struct string_list_item *item)
326{
327 int matched = 0;
328 if (item->util == NULL) {
329 if (!wildmatch(item->string, refname, 0))
330 matched = 1;
331 } else {
332 const char *rest;
333 if (skip_prefix(refname, item->string, &rest) &&
334 (!*rest || *rest == '/'))
335 matched = 1;
336 }
337 return matched;
338}
339
340int ref_filter_match(const char *refname,
341 const struct string_list *include_patterns,
342 const struct string_list *exclude_patterns)
343{
344 struct string_list_item *item;
345
346 if (exclude_patterns && exclude_patterns->nr) {
347 for_each_string_list_item(item, exclude_patterns) {
348 if (match_ref_pattern(refname, item))
349 return 0;
350 }
351 }
352
353 if (include_patterns && include_patterns->nr) {
354 int found = 0;
355 for_each_string_list_item(item, include_patterns) {
356 if (match_ref_pattern(refname, item)) {
357 found = 1;
358 break;
359 }
360 }
361
362 if (!found)
363 return 0;
364 }
365 return 1;
366}
367
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000368static int filter_refs(const char *refname, const struct object_id *oid,
Michael Haggerty4e675d12015-05-25 18:39:21 +0000369 int flags, void *data)
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200370{
371 struct ref_filter *filter = (struct ref_filter *)data;
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000372
Ævar Arnfjörð Bjarmason55d34262017-06-22 21:38:08 +0000373 if (wildmatch(filter->pattern, refname, 0))
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200374 return 0;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000375 if (filter->prefix)
376 skip_prefix(refname, filter->prefix, &refname);
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000377 return filter->fn(refname, oid, flags, filter->cb_data);
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200378}
379
brian m. carlsonac2ed0d2017-10-15 22:07:10 +0000380enum peel_status peel_object(const struct object_id *name, struct object_id *oid)
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200381{
Jeff King0ebbcf72019-06-20 03:41:10 -0400382 struct object *o = lookup_unknown_object(name);
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200383
384 if (o->type == OBJ_NONE) {
Stefan Beller0df8e962018-04-25 11:20:59 -0700385 int type = oid_object_info(the_repository, name, NULL);
Stefan Beller1268dfa2018-06-28 18:21:54 -0700386 if (type < 0 || !object_as_type(the_repository, o, type, 0))
Michael Haggerty68cf8702013-04-22 21:52:20 +0200387 return PEEL_INVALID;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200388 }
389
390 if (o->type != OBJ_TAG)
Michael Haggerty68cf8702013-04-22 21:52:20 +0200391 return PEEL_NON_TAG;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200392
393 o = deref_tag_noverify(o);
394 if (!o)
Michael Haggerty68cf8702013-04-22 21:52:20 +0200395 return PEEL_INVALID;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200396
brian m. carlsonac2ed0d2017-10-15 22:07:10 +0000397 oidcpy(oid, &o->oid);
Michael Haggerty68cf8702013-04-22 21:52:20 +0200398 return PEEL_PEELED;
Michael Haggertycb2ae1c2013-04-22 21:52:19 +0200399}
400
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200401struct warn_if_dangling_data {
402 FILE *fp;
403 const char *refname;
Jens Lindströme6bea662014-05-23 12:30:25 +0200404 const struct string_list *refnames;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200405 const char *msg_fmt;
406};
407
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000408static int warn_if_dangling_symref(const char *refname, const struct object_id *oid,
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200409 int flags, void *cb_data)
410{
411 struct warn_if_dangling_data *d = cb_data;
412 const char *resolves_to;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200413
414 if (!(flags & REF_ISSYMREF))
415 return 0;
416
René Scharfe744c0402017-09-23 11:45:04 +0200417 resolves_to = resolve_ref_unsafe(refname, 0, NULL, NULL);
Jens Lindströme6bea662014-05-23 12:30:25 +0200418 if (!resolves_to
419 || (d->refname
420 ? strcmp(resolves_to, d->refname)
421 : !string_list_has_string(d->refnames, resolves_to))) {
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200422 return 0;
Jens Lindströme6bea662014-05-23 12:30:25 +0200423 }
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200424
425 fprintf(d->fp, d->msg_fmt, refname);
Junio C Hamano1be65ed2012-05-02 13:51:35 -0700426 fputc('\n', d->fp);
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200427 return 0;
428}
429
430void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
431{
432 struct warn_if_dangling_data data;
433
434 data.fp = fp;
435 data.refname = refname;
Jens Lindströme6bea662014-05-23 12:30:25 +0200436 data.refnames = NULL;
437 data.msg_fmt = msg_fmt;
438 for_each_rawref(warn_if_dangling_symref, &data);
439}
440
441void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)
442{
443 struct warn_if_dangling_data data;
444
445 data.fp = fp;
446 data.refname = NULL;
447 data.refnames = refnames;
Michael Haggertybc5fd6d2012-04-10 07:30:13 +0200448 data.msg_fmt = msg_fmt;
449 for_each_rawref(warn_if_dangling_symref, &data);
450}
451
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700452int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
453{
454 return refs_for_each_ref_in(refs, "refs/tags/", fn, cb_data);
455}
456
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700457int for_each_tag_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400458{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700459 return refs_for_each_tag_ref(get_main_ref_store(the_repository), fn, cb_data);
Seana62be772006-05-13 21:43:00 -0400460}
461
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700462int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
463{
464 return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
Heiko Voigt9ef6aeb2010-07-07 15:39:12 +0200465}
466
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700467int for_each_branch_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400468{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700469 return refs_for_each_branch_ref(get_main_ref_store(the_repository), fn, cb_data);
Seana62be772006-05-13 21:43:00 -0400470}
471
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +0700472int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
473{
474 return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
Heiko Voigt9ef6aeb2010-07-07 15:39:12 +0200475}
476
Junio C Hamanocb5d7092006-09-20 21:47:42 -0700477int for_each_remote_ref(each_ref_fn fn, void *cb_data)
Seana62be772006-05-13 21:43:00 -0400478{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700479 return refs_for_each_remote_ref(get_main_ref_store(the_repository), fn, cb_data);
Junio C Hamanof8948e22009-02-08 23:27:10 -0800480}
481
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700482int head_ref_namespaced(each_ref_fn fn, void *cb_data)
483{
484 struct strbuf buf = STRBUF_INIT;
485 int ret = 0;
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000486 struct object_id oid;
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700487 int flag;
488
489 strbuf_addf(&buf, "%sHEAD", get_git_namespace());
brian m. carlson34c290a2017-10-15 22:06:56 +0000490 if (!read_ref_full(buf.buf, RESOLVE_REF_READING, &oid, &flag))
Michael Haggerty2b2a5be2015-05-25 18:38:28 +0000491 ret = fn(buf.buf, &oid, flag, cb_data);
Josh Tripletta1bea2c2011-07-05 10:54:44 -0700492 strbuf_release(&buf);
493
494 return ret;
495}
496
Rafael Ascensão65516f52017-11-21 21:33:41 +0000497void normalize_glob_ref(struct string_list_item *item, const char *prefix,
498 const char *pattern)
499{
500 struct strbuf normalized_pattern = STRBUF_INIT;
501
502 if (*pattern == '/')
503 BUG("pattern must not start with '/'");
504
505 if (prefix) {
506 strbuf_addstr(&normalized_pattern, prefix);
507 }
508 else if (!starts_with(pattern, "refs/"))
509 strbuf_addstr(&normalized_pattern, "refs/");
510 strbuf_addstr(&normalized_pattern, pattern);
511 strbuf_strip_suffix(&normalized_pattern, "/");
512
513 item->string = strbuf_detach(&normalized_pattern, NULL);
514 item->util = has_glob_specials(pattern) ? NULL : item->string;
515 strbuf_release(&normalized_pattern);
516}
517
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200518int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
519 const char *prefix, void *cb_data)
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200520{
521 struct strbuf real_pattern = STRBUF_INIT;
522 struct ref_filter filter;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200523 int ret;
524
Christian Couder59556542013-11-30 21:55:40 +0100525 if (!prefix && !starts_with(pattern, "refs/"))
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200526 strbuf_addstr(&real_pattern, "refs/");
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200527 else if (prefix)
528 strbuf_addstr(&real_pattern, prefix);
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200529 strbuf_addstr(&real_pattern, pattern);
530
Thomas Rast894a9d32010-03-12 18:04:26 +0100531 if (!has_glob_specials(pattern)) {
Junio C Hamano9517e6b2010-02-03 21:23:18 -0800532 /* Append implied '/' '*' if not present. */
Jeff King00b6c172015-09-24 17:08:35 -0400533 strbuf_complete(&real_pattern, '/');
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200534 /* No need to check for '*', there is none. */
535 strbuf_addch(&real_pattern, '*');
536 }
537
538 filter.pattern = real_pattern.buf;
Rafael Ascensão9ab9b5d2018-11-12 13:25:44 +0000539 filter.prefix = prefix;
Ilari Liusvaarad08bae72010-01-20 11:48:25 +0200540 filter.fn = fn;
541 filter.cb_data = cb_data;
542 ret = for_each_ref(filter_refs, &filter);
543
544 strbuf_release(&real_pattern);
545 return ret;
546}
547
Ilari Liusvaarab09fe972010-01-20 11:48:26 +0200548int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
549{
550 return for_each_glob_ref_in(fn, pattern, NULL, cb_data);
551}
552
Felipe Contreras4577e482009-05-14 00:22:04 +0300553const char *prettify_refname(const char *name)
Daniel Barkalowa9c37a72009-03-08 21:06:05 -0400554{
SZEDER Gábor3e5b36c2017-03-23 16:50:12 +0100555 if (skip_prefix(name, "refs/heads/", &name) ||
556 skip_prefix(name, "refs/tags/", &name) ||
557 skip_prefix(name, "refs/remotes/", &name))
558 ; /* nothing */
559 return name;
Daniel Barkalowa9c37a72009-03-08 21:06:05 -0400560}
561
Michael Haggerty54457fe2014-01-14 04:16:07 +0100562static const char *ref_rev_parse_rules[] = {
Steffen Prohaska79803322007-11-11 15:01:46 +0100563 "%.*s",
564 "refs/%.*s",
565 "refs/tags/%.*s",
566 "refs/heads/%.*s",
567 "refs/remotes/%.*s",
568 "refs/remotes/%.*s/HEAD",
569 NULL
570};
571
Junio C Hamano60650a42018-08-01 09:22:37 -0700572#define NUM_REV_PARSE_RULES (ARRAY_SIZE(ref_rev_parse_rules) - 1)
573
574/*
575 * Is it possible that the caller meant full_name with abbrev_name?
576 * If so return a non-zero value to signal "yes"; the magnitude of
577 * the returned value gives the precedence used for disambiguation.
578 *
579 * If abbrev_name cannot mean full_name, return 0.
580 */
Michael Haggerty54457fe2014-01-14 04:16:07 +0100581int refname_match(const char *abbrev_name, const char *full_name)
Steffen Prohaska79803322007-11-11 15:01:46 +0100582{
583 const char **p;
584 const int abbrev_name_len = strlen(abbrev_name);
Junio C Hamano60650a42018-08-01 09:22:37 -0700585 const int num_rules = NUM_REV_PARSE_RULES;
Steffen Prohaska79803322007-11-11 15:01:46 +0100586
Junio C Hamano60650a42018-08-01 09:22:37 -0700587 for (p = ref_rev_parse_rules; *p; p++)
588 if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name)))
589 return &ref_rev_parse_rules[num_rules] - p;
Steffen Prohaska79803322007-11-11 15:01:46 +0100590
591 return 0;
592}
593
Michael Haggerty19b68b12011-12-12 06:38:12 +0100594/*
Brandon Williamsb4be7412018-03-15 10:31:24 -0700595 * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add
596 * the results to 'prefixes'
597 */
598void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
599{
600 const char **p;
601 int len = strlen(prefix);
602
603 for (p = ref_rev_parse_rules; *p; p++)
604 argv_array_pushf(prefixes, *p, len, prefix);
605}
606
607/*
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700608 * *string and *len will only be substituted, and *string returned (for
609 * later free()ing) if the string passed in is a magic short-hand form
610 * to name a branch.
611 */
Nguyễn Thái Ngọc Duy8f56e9d2019-04-06 18:34:26 +0700612static char *substitute_branch_name(struct repository *r,
613 const char **string, int *len)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700614{
615 struct strbuf buf = STRBUF_INIT;
Nguyễn Thái Ngọc Duy8f56e9d2019-04-06 18:34:26 +0700616 int ret = repo_interpret_branch_name(r, *string, *len, &buf, 0);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700617
618 if (ret == *len) {
619 size_t size;
620 *string = strbuf_detach(&buf, &size);
621 *len = size;
622 return (char *)*string;
623 }
624
625 return NULL;
626}
627
Nguyễn Thái Ngọc Duyd8984c52019-04-06 18:34:28 +0700628int repo_dwim_ref(struct repository *r, const char *str, int len,
629 struct object_id *oid, char **ref)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700630{
Nguyễn Thái Ngọc Duyd8984c52019-04-06 18:34:28 +0700631 char *last_branch = substitute_branch_name(r, &str, &len);
632 int refs_found = expand_ref(r, str, len, oid, ref);
Nguyễn Thái Ngọc Duy41da7112016-06-12 17:54:02 +0700633 free(last_branch);
634 return refs_found;
635}
636
Nguyễn Thái Ngọc Duyd8984c52019-04-06 18:34:28 +0700637int dwim_ref(const char *str, int len, struct object_id *oid, char **ref)
638{
639 return repo_dwim_ref(the_repository, str, len, oid, ref);
640}
641
Nguyễn Thái Ngọc Duy0b1dbf52019-04-06 18:34:27 +0700642int expand_ref(struct repository *repo, const char *str, int len,
643 struct object_id *oid, char **ref)
Nguyễn Thái Ngọc Duy41da7112016-06-12 17:54:02 +0700644{
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700645 const char **p, *r;
646 int refs_found = 0;
Jeff King6cd4a892017-03-28 15:46:33 -0400647 struct strbuf fullref = STRBUF_INIT;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700648
649 *ref = NULL;
650 for (p = ref_rev_parse_rules; *p; p++) {
brian m. carlsoncca5fa62017-10-15 22:06:57 +0000651 struct object_id oid_from_ref;
652 struct object_id *this_result;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700653 int flag;
654
brian m. carlsoncca5fa62017-10-15 22:06:57 +0000655 this_result = refs_found ? &oid_from_ref : oid;
Jeff King6cd4a892017-03-28 15:46:33 -0400656 strbuf_reset(&fullref);
657 strbuf_addf(&fullref, *p, len, str);
Nguyễn Thái Ngọc Duy0b1dbf52019-04-06 18:34:27 +0700658 r = refs_resolve_ref_unsafe(get_main_ref_store(repo),
659 fullref.buf, RESOLVE_REF_READING,
660 this_result, &flag);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700661 if (r) {
662 if (!refs_found++)
663 *ref = xstrdup(r);
664 if (!warn_ambiguous_refs)
665 break;
Jeff King6cd4a892017-03-28 15:46:33 -0400666 } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200667 warning(_("ignoring dangling symref %s"), fullref.buf);
Jeff King6cd4a892017-03-28 15:46:33 -0400668 } else if ((flag & REF_ISBROKEN) && strchr(fullref.buf, '/')) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200669 warning(_("ignoring broken ref %s"), fullref.buf);
Junio C Hamano55956352011-10-19 13:55:49 -0700670 }
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700671 }
Jeff King6cd4a892017-03-28 15:46:33 -0400672 strbuf_release(&fullref);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700673 return refs_found;
674}
675
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700676int repo_dwim_log(struct repository *r, const char *str, int len,
677 struct object_id *oid, char **log)
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700678{
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700679 struct ref_store *refs = get_main_ref_store(r);
680 char *last_branch = substitute_branch_name(r, &str, &len);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700681 const char **p;
682 int logs_found = 0;
Jeff King6cd4a892017-03-28 15:46:33 -0400683 struct strbuf path = STRBUF_INIT;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700684
685 *log = NULL;
686 for (p = ref_rev_parse_rules; *p; p++) {
brian m. carlson334dc522017-10-15 22:06:59 +0000687 struct object_id hash;
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700688 const char *ref, *it;
689
Jeff King6cd4a892017-03-28 15:46:33 -0400690 strbuf_reset(&path);
691 strbuf_addf(&path, *p, len, str);
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700692 ref = refs_resolve_ref_unsafe(refs, path.buf,
693 RESOLVE_REF_READING,
694 &hash, NULL);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700695 if (!ref)
696 continue;
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700697 if (refs_reflog_exists(refs, path.buf))
Jeff King6cd4a892017-03-28 15:46:33 -0400698 it = path.buf;
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700699 else if (strcmp(ref, path.buf) &&
700 refs_reflog_exists(refs, ref))
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700701 it = ref;
702 else
703 continue;
704 if (!logs_found++) {
705 *log = xstrdup(it);
brian m. carlson334dc522017-10-15 22:06:59 +0000706 oidcpy(oid, &hash);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700707 }
708 if (!warn_ambiguous_refs)
709 break;
710 }
Jeff King6cd4a892017-03-28 15:46:33 -0400711 strbuf_release(&path);
Junio C Hamanoff74f7f2011-10-12 10:35:38 -0700712 free(last_branch);
713 return logs_found;
714}
715
Nguyễn Thái Ngọc Duy56700902019-04-06 18:34:29 +0700716int dwim_log(const char *str, int len, struct object_id *oid, char **log)
717{
718 return repo_dwim_log(the_repository, str, len, oid, log);
719}
720
David Turner266b1822015-07-31 02:06:18 -0400721static int is_per_worktree_ref(const char *refname)
722{
David Turnerce414b32015-08-31 22:13:11 -0400723 return !strcmp(refname, "HEAD") ||
Nguyễn Thái Ngọc Duy8aff1a92018-09-29 21:10:23 +0200724 starts_with(refname, "refs/worktree/") ||
Johannes Schindelina9be29c2018-04-25 14:29:16 +0200725 starts_with(refname, "refs/bisect/") ||
726 starts_with(refname, "refs/rewritten/");
David Turner266b1822015-07-31 02:06:18 -0400727}
728
729static int is_pseudoref_syntax(const char *refname)
730{
731 const char *c;
732
733 for (c = refname; *c; c++) {
734 if (!isupper(*c) && *c != '-' && *c != '_')
735 return 0;
736 }
737
738 return 1;
739}
740
Nguyễn Thái Ngọc Duy3a3b9d82018-10-21 10:08:54 +0200741static int is_main_pseudoref_syntax(const char *refname)
742{
743 return skip_prefix(refname, "main-worktree/", &refname) &&
744 *refname &&
745 is_pseudoref_syntax(refname);
746}
747
748static int is_other_pseudoref_syntax(const char *refname)
749{
750 if (!skip_prefix(refname, "worktrees/", &refname))
751 return 0;
752 refname = strchr(refname, '/');
753 if (!refname || !refname[1])
754 return 0;
755 return is_pseudoref_syntax(refname + 1);
756}
757
David Turner266b1822015-07-31 02:06:18 -0400758enum ref_type ref_type(const char *refname)
759{
760 if (is_per_worktree_ref(refname))
761 return REF_TYPE_PER_WORKTREE;
762 if (is_pseudoref_syntax(refname))
763 return REF_TYPE_PSEUDOREF;
Nguyễn Thái Ngọc Duy3a3b9d82018-10-21 10:08:54 +0200764 if (is_main_pseudoref_syntax(refname))
765 return REF_TYPE_MAIN_PSEUDOREF;
766 if (is_other_pseudoref_syntax(refname))
767 return REF_TYPE_OTHER_PSEUDOREF;
Nguyễn Thái Ngọc Duy5c79f742018-09-29 21:10:22 +0200768 return REF_TYPE_NORMAL;
David Turner266b1822015-07-31 02:06:18 -0400769}
770
Michael Haggerty4ff0f012017-08-21 13:51:34 +0200771long get_files_ref_lock_timeout_ms(void)
772{
773 static int configured = 0;
774
775 /* The default timeout is 100 ms: */
776 static int timeout_ms = 100;
777
778 if (!configured) {
779 git_config_get_int("core.filesreflocktimeout", &timeout_ms);
780 configured = 1;
781 }
782
783 return timeout_ms;
784}
785
brian m. carlsonae077772017-10-15 22:06:51 +0000786static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
787 const struct object_id *old_oid, struct strbuf *err)
David Turner74ec19d2015-07-31 02:06:19 -0400788{
789 const char *filename;
790 int fd;
Martin Ågren01084512018-05-09 22:55:36 +0200791 struct lock_file lock = LOCK_INIT;
David Turner74ec19d2015-07-31 02:06:19 -0400792 struct strbuf buf = STRBUF_INIT;
793 int ret = -1;
794
brian m. carlson6ee18212017-10-15 22:06:52 +0000795 if (!oid)
796 return 0;
797
brian m. carlsonae077772017-10-15 22:06:51 +0000798 strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
David Turner74ec19d2015-07-31 02:06:19 -0400799
800 filename = git_path("%s", pseudoref);
Martin Ågren01084512018-05-09 22:55:36 +0200801 fd = hold_lock_file_for_update_timeout(&lock, filename, 0,
Michael Haggerty4ff0f012017-08-21 13:51:34 +0200802 get_files_ref_lock_timeout_ms());
David Turner74ec19d2015-07-31 02:06:19 -0400803 if (fd < 0) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200804 strbuf_addf(err, _("could not open '%s' for writing: %s"),
David Turner74ec19d2015-07-31 02:06:19 -0400805 filename, strerror(errno));
Rene Scharfeaeb014f2017-08-30 19:58:12 +0200806 goto done;
David Turner74ec19d2015-07-31 02:06:19 -0400807 }
808
brian m. carlsonae077772017-10-15 22:06:51 +0000809 if (old_oid) {
810 struct object_id actual_old_oid;
David Turner2c3aed12015-07-15 18:05:28 -0400811
Martin Ågrendb0210d2018-05-10 21:29:56 +0200812 if (read_ref(pseudoref, &actual_old_oid)) {
813 if (!is_null_oid(old_oid)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200814 strbuf_addf(err, _("could not read ref '%s'"),
Martin Ågrendb0210d2018-05-10 21:29:56 +0200815 pseudoref);
816 rollback_lock_file(&lock);
817 goto done;
818 }
819 } else if (is_null_oid(old_oid)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200820 strbuf_addf(err, _("ref '%s' already exists"),
Martin Ågrendb0210d2018-05-10 21:29:56 +0200821 pseudoref);
822 rollback_lock_file(&lock);
823 goto done;
Jeff King9001dc22018-08-28 17:22:48 -0400824 } else if (!oideq(&actual_old_oid, old_oid)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200825 strbuf_addf(err, _("unexpected object ID when writing '%s'"),
Martin Ågrenc0bdd652018-05-10 21:29:54 +0200826 pseudoref);
David Turner74ec19d2015-07-31 02:06:19 -0400827 rollback_lock_file(&lock);
828 goto done;
829 }
830 }
831
Jeff King06f46f22017-09-13 13:16:03 -0400832 if (write_in_full(fd, buf.buf, buf.len) < 0) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200833 strbuf_addf(err, _("could not write to '%s'"), filename);
David Turner74ec19d2015-07-31 02:06:19 -0400834 rollback_lock_file(&lock);
835 goto done;
836 }
837
838 commit_lock_file(&lock);
839 ret = 0;
840done:
841 strbuf_release(&buf);
842 return ret;
843}
844
brian m. carlson2616a5e2017-10-15 22:06:50 +0000845static int delete_pseudoref(const char *pseudoref, const struct object_id *old_oid)
David Turner74ec19d2015-07-31 02:06:19 -0400846{
David Turner74ec19d2015-07-31 02:06:19 -0400847 const char *filename;
848
849 filename = git_path("%s", pseudoref);
850
brian m. carlson2616a5e2017-10-15 22:06:50 +0000851 if (old_oid && !is_null_oid(old_oid)) {
Martin Ågren3c6fad42018-05-09 22:55:37 +0200852 struct lock_file lock = LOCK_INIT;
David Turner74ec19d2015-07-31 02:06:19 -0400853 int fd;
brian m. carlson2616a5e2017-10-15 22:06:50 +0000854 struct object_id actual_old_oid;
David Turner74ec19d2015-07-31 02:06:19 -0400855
Michael Haggerty4ff0f012017-08-21 13:51:34 +0200856 fd = hold_lock_file_for_update_timeout(
Martin Ågren3c6fad42018-05-09 22:55:37 +0200857 &lock, filename, 0,
Michael Haggerty4ff0f012017-08-21 13:51:34 +0200858 get_files_ref_lock_timeout_ms());
Martin Ågren3c6fad42018-05-09 22:55:37 +0200859 if (fd < 0) {
860 error_errno(_("could not open '%s' for writing"),
861 filename);
862 return -1;
863 }
brian m. carlson34c290a2017-10-15 22:06:56 +0000864 if (read_ref(pseudoref, &actual_old_oid))
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200865 die(_("could not read ref '%s'"), pseudoref);
Jeff King9001dc22018-08-28 17:22:48 -0400866 if (!oideq(&actual_old_oid, old_oid)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200867 error(_("unexpected object ID when deleting '%s'"),
Martin Ågrenc0bdd652018-05-10 21:29:54 +0200868 pseudoref);
David Turner74ec19d2015-07-31 02:06:19 -0400869 rollback_lock_file(&lock);
870 return -1;
871 }
872
873 unlink(filename);
874 rollback_lock_file(&lock);
875 } else {
876 unlink(filename);
877 }
878
879 return 0;
880}
881
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700882int refs_delete_ref(struct ref_store *refs, const char *msg,
883 const char *refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000884 const struct object_id *old_oid,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700885 unsigned int flags)
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700886{
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700887 struct ref_transaction *transaction;
888 struct strbuf err = STRBUF_INIT;
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700889
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700890 if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700891 assert(refs == get_main_ref_store(the_repository));
brian m. carlson2616a5e2017-10-15 22:06:50 +0000892 return delete_pseudoref(refname, old_oid);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700893 }
David Turner74ec19d2015-07-31 02:06:19 -0400894
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700895 transaction = ref_store_transaction_begin(refs, &err);
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700896 if (!transaction ||
brian m. carlson89f3bbd2017-10-15 22:06:53 +0000897 ref_transaction_delete(transaction, refname, old_oid,
Kyle Meyer755b49a2017-02-20 20:10:32 -0500898 flags, msg, &err) ||
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -0700899 ref_transaction_commit(transaction, &err)) {
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700900 error("%s", err.buf);
901 ref_transaction_free(transaction);
902 strbuf_release(&err);
Junio C Hamanoc0277d12006-09-30 15:02:00 -0700903 return 1;
Ronnie Sahlberg7521cc42014-04-30 09:22:45 -0700904 }
905 ref_transaction_free(transaction);
906 strbuf_release(&err);
907 return 0;
Shawn Pearce4bd18c42006-05-17 05:55:02 -0400908}
909
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700910int delete_ref(const char *msg, const char *refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000911 const struct object_id *old_oid, unsigned int flags)
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700912{
Stefan Beller23a3f0c2018-04-11 17:21:09 -0700913 return refs_delete_ref(get_main_ref_store(the_repository), msg, refname,
brian m. carlson2616a5e2017-10-15 22:06:50 +0000914 old_oid, flags);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +0700915}
916
Ben Peart80a6c202018-07-10 21:08:22 +0000917void copy_reflog_msg(struct strbuf *sb, const char *msg)
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700918{
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700919 char c;
920 int wasspace = 1;
921
Ben Peart80a6c202018-07-10 21:08:22 +0000922 strbuf_addch(sb, '\t');
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700923 while ((c = *msg++)) {
924 if (wasspace && isspace(c))
925 continue;
926 wasspace = isspace(c);
927 if (wasspace)
928 c = ' ';
Ben Peart80a6c202018-07-10 21:08:22 +0000929 strbuf_addch(sb, c);
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700930 }
Ben Peart80a6c202018-07-10 21:08:22 +0000931 strbuf_rtrim(sb);
Junio C Hamano0ec29a42007-07-28 17:17:17 -0700932}
933
Michael Haggerty4cb77002015-11-10 12:42:36 +0100934int should_autocreate_reflog(const char *refname)
David Turner4e2bef52015-07-21 17:04:51 -0400935{
Cornelius Weig341fb282017-01-27 11:09:47 +0100936 switch (log_all_ref_updates) {
937 case LOG_REFS_ALWAYS:
938 return 1;
939 case LOG_REFS_NORMAL:
940 return starts_with(refname, "refs/heads/") ||
941 starts_with(refname, "refs/remotes/") ||
942 starts_with(refname, "refs/notes/") ||
943 !strcmp(refname, "HEAD");
944 default:
David Turner4e2bef52015-07-21 17:04:51 -0400945 return 0;
Cornelius Weig341fb282017-01-27 11:09:47 +0100946 }
David Turner4e2bef52015-07-21 17:04:51 -0400947}
948
Ronnie Sahlberge7e0f262014-07-15 16:02:38 -0700949int is_branch(const char *refname)
Linus Torvaldsc3b0dec2008-01-15 15:50:17 -0800950{
Christian Couder59556542013-11-30 21:55:40 +0100951 return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
Linus Torvaldsc3b0dec2008-01-15 15:50:17 -0800952}
953
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700954struct read_ref_at_cb {
955 const char *refname;
Johannes Schindelindddbad72017-04-26 21:29:31 +0200956 timestamp_t at_time;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700957 int cnt;
958 int reccnt;
brian m. carlson8eb36d92017-10-15 22:07:03 +0000959 struct object_id *oid;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700960 int found_it;
961
brian m. carlson8eb36d92017-10-15 22:07:03 +0000962 struct object_id ooid;
963 struct object_id noid;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700964 int tz;
Johannes Schindelindddbad72017-04-26 21:29:31 +0200965 timestamp_t date;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700966 char **msg;
Johannes Schindelindddbad72017-04-26 21:29:31 +0200967 timestamp_t *cutoff_time;
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700968 int *cutoff_tz;
969 int *cutoff_cnt;
970};
971
brian m. carlson9461d272017-02-21 23:47:32 +0000972static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
Johannes Schindelindddbad72017-04-26 21:29:31 +0200973 const char *email, timestamp_t timestamp, int tz,
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700974 const char *message, void *cb_data)
Junio C Hamano16d7cc92007-01-19 01:19:05 -0800975{
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700976 struct read_ref_at_cb *cb = cb_data;
977
978 cb->reccnt++;
979 cb->tz = tz;
980 cb->date = timestamp;
981
982 if (timestamp <= cb->at_time || cb->cnt == 0) {
983 if (cb->msg)
984 *cb->msg = xstrdup(message);
985 if (cb->cutoff_time)
986 *cb->cutoff_time = timestamp;
987 if (cb->cutoff_tz)
988 *cb->cutoff_tz = tz;
989 if (cb->cutoff_cnt)
990 *cb->cutoff_cnt = cb->reccnt - 1;
991 /*
Michael Haggerty78fb4572017-11-05 09:42:09 +0100992 * we have not yet updated cb->[n|o]oid so they still
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -0700993 * hold the values for the previous record.
994 */
brian m. carlson8eb36d92017-10-15 22:07:03 +0000995 if (!is_null_oid(&cb->ooid)) {
996 oidcpy(cb->oid, noid);
Jeff King9001dc22018-08-28 17:22:48 -0400997 if (!oideq(&cb->ooid, noid))
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +0200998 warning(_("log for ref %s has gap after %s"),
Jeff Kinga5481a62015-06-25 12:55:02 -0400999 cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001000 }
1001 else if (cb->date == cb->at_time)
brian m. carlson8eb36d92017-10-15 22:07:03 +00001002 oidcpy(cb->oid, noid);
Jeff King9001dc22018-08-28 17:22:48 -04001003 else if (!oideq(noid, cb->oid))
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001004 warning(_("log for ref %s unexpectedly ended on %s"),
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001005 cb->refname, show_date(cb->date, cb->tz,
Jeff Kinga5481a62015-06-25 12:55:02 -04001006 DATE_MODE(RFC2822)));
brian m. carlson8eb36d92017-10-15 22:07:03 +00001007 oidcpy(&cb->ooid, ooid);
1008 oidcpy(&cb->noid, noid);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001009 cb->found_it = 1;
1010 return 1;
1011 }
brian m. carlson8eb36d92017-10-15 22:07:03 +00001012 oidcpy(&cb->ooid, ooid);
1013 oidcpy(&cb->noid, noid);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001014 if (cb->cnt > 0)
1015 cb->cnt--;
1016 return 0;
1017}
1018
brian m. carlson9461d272017-02-21 23:47:32 +00001019static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid,
Johannes Schindelindddbad72017-04-26 21:29:31 +02001020 const char *email, timestamp_t timestamp,
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001021 int tz, const char *message, void *cb_data)
1022{
1023 struct read_ref_at_cb *cb = cb_data;
1024
1025 if (cb->msg)
1026 *cb->msg = xstrdup(message);
1027 if (cb->cutoff_time)
1028 *cb->cutoff_time = timestamp;
1029 if (cb->cutoff_tz)
1030 *cb->cutoff_tz = tz;
1031 if (cb->cutoff_cnt)
1032 *cb->cutoff_cnt = cb->reccnt;
brian m. carlson8eb36d92017-10-15 22:07:03 +00001033 oidcpy(cb->oid, ooid);
1034 if (is_null_oid(cb->oid))
1035 oidcpy(cb->oid, noid);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001036 /* We just want the first entry */
1037 return 1;
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001038}
1039
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +07001040int read_ref_at(struct ref_store *refs, const char *refname,
1041 unsigned int flags, timestamp_t at_time, int cnt,
brian m. carlson8eb36d92017-10-15 22:07:03 +00001042 struct object_id *oid, char **msg,
Johannes Schindelindddbad72017-04-26 21:29:31 +02001043 timestamp_t *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
Shawn Pearced556fae2006-05-17 05:56:09 -04001044{
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001045 struct read_ref_at_cb cb;
Shawn Pearced556fae2006-05-17 05:56:09 -04001046
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001047 memset(&cb, 0, sizeof(cb));
1048 cb.refname = refname;
1049 cb.at_time = at_time;
1050 cb.cnt = cnt;
1051 cb.msg = msg;
1052 cb.cutoff_time = cutoff_time;
1053 cb.cutoff_tz = cutoff_tz;
1054 cb.cutoff_cnt = cutoff_cnt;
brian m. carlson8eb36d92017-10-15 22:07:03 +00001055 cb.oid = oid;
Shawn Pearced556fae2006-05-17 05:56:09 -04001056
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +07001057 refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent, &cb);
Shawn Pearced556fae2006-05-17 05:56:09 -04001058
David Aguilarc41a87d2014-09-18 20:45:37 -07001059 if (!cb.reccnt) {
brian m. carlson321c89b2017-07-13 23:49:29 +00001060 if (flags & GET_OID_QUIETLY)
David Aguilarc41a87d2014-09-18 20:45:37 -07001061 exit(128);
1062 else
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001063 die(_("log for %s is empty"), refname);
David Aguilarc41a87d2014-09-18 20:45:37 -07001064 }
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001065 if (cb.found_it)
1066 return 0;
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001067
Nguyễn Thái Ngọc Duy7fdff472019-04-06 18:34:30 +07001068 refs_for_each_reflog_ent(refs, refname, read_ref_at_ent_oldest, &cb);
Ronnie Sahlberg4207ed22014-06-03 09:09:59 -07001069
Junio C Hamano16d7cc92007-01-19 01:19:05 -08001070 return 1;
Shawn Pearced556fae2006-05-17 05:56:09 -04001071}
Junio C Hamano2ff81662006-12-18 01:18:16 -08001072
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001073struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
1074 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001075{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001076 struct ref_transaction *tr;
Jonathan Nieder5a603b02014-08-28 16:42:37 -07001077 assert(err);
1078
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001079 tr = xcalloc(1, sizeof(struct ref_transaction));
1080 tr->ref_store = refs;
1081 return tr;
1082}
1083
1084struct ref_transaction *ref_transaction_begin(struct strbuf *err)
1085{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001086 return ref_store_transaction_begin(get_main_ref_store(the_repository), err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001087}
1088
Ronnie Sahlberg026bd1d2014-06-20 07:42:42 -07001089void ref_transaction_free(struct ref_transaction *transaction)
Michael Haggertycaa40462014-04-07 15:48:10 +02001090{
Michael Haggerty43a2dfd2017-05-22 16:17:37 +02001091 size_t i;
Michael Haggertycaa40462014-04-07 15:48:10 +02001092
Ronnie Sahlberg1b072552014-06-20 07:42:45 -07001093 if (!transaction)
1094 return;
1095
Michael Haggerty30173b82017-05-22 16:17:44 +02001096 switch (transaction->state) {
1097 case REF_TRANSACTION_OPEN:
1098 case REF_TRANSACTION_CLOSED:
1099 /* OK */
1100 break;
1101 case REF_TRANSACTION_PREPARED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02001102 BUG("free called on a prepared reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02001103 break;
1104 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02001105 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02001106 break;
1107 }
1108
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -07001109 for (i = 0; i < transaction->nr; i++) {
1110 free(transaction->updates[i]->msg);
Michael Haggerty88615912014-04-07 15:48:14 +02001111 free(transaction->updates[i]);
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -07001112 }
Michael Haggertycaa40462014-04-07 15:48:10 +02001113 free(transaction->updates);
1114 free(transaction);
1115}
1116
Michael Haggerty71564512016-04-25 11:39:54 +02001117struct ref_update *ref_transaction_add_update(
1118 struct ref_transaction *transaction,
1119 const char *refname, unsigned int flags,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001120 const struct object_id *new_oid,
1121 const struct object_id *old_oid,
Michael Haggerty71564512016-04-25 11:39:54 +02001122 const char *msg)
Michael Haggertycaa40462014-04-07 15:48:10 +02001123{
Jeff King96ffc062016-02-22 17:44:32 -05001124 struct ref_update *update;
Michael Haggerty71564512016-04-25 11:39:54 +02001125
1126 if (transaction->state != REF_TRANSACTION_OPEN)
Johannes Schindelin033abf92018-05-02 11:38:39 +02001127 BUG("update called for transaction that is not open");
Michael Haggerty71564512016-04-25 11:39:54 +02001128
Jeff King96ffc062016-02-22 17:44:32 -05001129 FLEX_ALLOC_STR(update, refname, refname);
Michael Haggertycaa40462014-04-07 15:48:10 +02001130 ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
1131 transaction->updates[transaction->nr++] = update;
Michael Haggerty71564512016-04-25 11:39:54 +02001132
1133 update->flags = flags;
1134
1135 if (flags & REF_HAVE_NEW)
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001136 oidcpy(&update->new_oid, new_oid);
Michael Haggerty71564512016-04-25 11:39:54 +02001137 if (flags & REF_HAVE_OLD)
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001138 oidcpy(&update->old_oid, old_oid);
Junio C Hamano13092a92016-10-12 11:20:23 -07001139 update->msg = xstrdup_or_null(msg);
Michael Haggertycaa40462014-04-07 15:48:10 +02001140 return update;
1141}
1142
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001143int ref_transaction_update(struct ref_transaction *transaction,
1144 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001145 const struct object_id *new_oid,
1146 const struct object_id *old_oid,
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001147 unsigned int flags, const char *msg,
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001148 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001149{
Jonathan Nieder5a603b02014-08-28 16:42:37 -07001150 assert(err);
1151
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001152 if ((new_oid && !is_null_oid(new_oid)) ?
Michael Haggerty8a679de2016-04-27 15:54:45 +02001153 check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) :
1154 !refname_is_safe(refname)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001155 strbuf_addf(err, _("refusing to update ref with bad name '%s'"),
Ronnie Sahlbergd0f810f2014-09-03 11:45:43 -07001156 refname);
1157 return -1;
1158 }
1159
Michael Haggertya9bbbce2017-11-05 09:42:03 +01001160 if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
1161 BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
Thomas Gummererc788c542017-09-12 23:59:21 +01001162
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001163 flags |= (new_oid ? REF_HAVE_NEW : 0) | (old_oid ? REF_HAVE_OLD : 0);
Michael Haggerty71564512016-04-25 11:39:54 +02001164
1165 ref_transaction_add_update(transaction, refname, flags,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001166 new_oid, old_oid, msg);
Ronnie Sahlberg8e348002014-06-20 07:43:00 -07001167 return 0;
Michael Haggertycaa40462014-04-07 15:48:10 +02001168}
1169
Ronnie Sahlbergb416af52014-04-16 15:26:44 -07001170int ref_transaction_create(struct ref_transaction *transaction,
1171 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001172 const struct object_id *new_oid,
Michael Haggertyfec14ec2015-02-17 18:00:13 +01001173 unsigned int flags, const char *msg,
Ronnie Sahlbergb416af52014-04-16 15:26:44 -07001174 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001175{
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001176 if (!new_oid || is_null_oid(new_oid))
Johannes Schindelin033abf92018-05-02 11:38:39 +02001177 BUG("create called without valid new_oid");
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001178 return ref_transaction_update(transaction, refname, new_oid,
1179 &null_oid, flags, msg, err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001180}
1181
Ronnie Sahlberg8c8bdc02014-04-16 15:27:45 -07001182int ref_transaction_delete(struct ref_transaction *transaction,
1183 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001184 const struct object_id *old_oid,
Michael Haggertyfb5a6bb2015-02-17 18:00:16 +01001185 unsigned int flags, const char *msg,
Ronnie Sahlberg8c8bdc02014-04-16 15:27:45 -07001186 struct strbuf *err)
Michael Haggertycaa40462014-04-07 15:48:10 +02001187{
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001188 if (old_oid && is_null_oid(old_oid))
Johannes Schindelin033abf92018-05-02 11:38:39 +02001189 BUG("delete called with old_oid set to zeros");
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001190 return ref_transaction_update(transaction, refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001191 &null_oid, old_oid,
Michael Haggerty1d147bd2015-02-17 18:00:15 +01001192 flags, msg, err);
Michael Haggertycaa40462014-04-07 15:48:10 +02001193}
1194
Michael Haggerty16180332015-02-17 18:00:21 +01001195int ref_transaction_verify(struct ref_transaction *transaction,
1196 const char *refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001197 const struct object_id *old_oid,
Michael Haggerty16180332015-02-17 18:00:21 +01001198 unsigned int flags,
1199 struct strbuf *err)
1200{
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001201 if (!old_oid)
Johannes Schindelin033abf92018-05-02 11:38:39 +02001202 BUG("verify called with old_oid set to NULL");
Michael Haggerty16180332015-02-17 18:00:21 +01001203 return ref_transaction_update(transaction, refname,
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001204 NULL, old_oid,
Michael Haggerty16180332015-02-17 18:00:21 +01001205 flags, NULL, err);
1206}
1207
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001208int refs_update_ref(struct ref_store *refs, const char *msg,
brian m. carlsonae077772017-10-15 22:06:51 +00001209 const char *refname, const struct object_id *new_oid,
1210 const struct object_id *old_oid, unsigned int flags,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001211 enum action_on_err onerr)
Brad King4738a332013-09-04 11:22:40 -04001212{
David Turner74ec19d2015-07-31 02:06:19 -04001213 struct ref_transaction *t = NULL;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001214 struct strbuf err = STRBUF_INIT;
David Turner74ec19d2015-07-31 02:06:19 -04001215 int ret = 0;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001216
David Turner74ec19d2015-07-31 02:06:19 -04001217 if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001218 assert(refs == get_main_ref_store(the_repository));
brian m. carlsonae077772017-10-15 22:06:51 +00001219 ret = write_pseudoref(refname, new_oid, old_oid, &err);
David Turner74ec19d2015-07-31 02:06:19 -04001220 } else {
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001221 t = ref_store_transaction_begin(refs, &err);
David Turner74ec19d2015-07-31 02:06:19 -04001222 if (!t ||
brian m. carlson89f3bbd2017-10-15 22:06:53 +00001223 ref_transaction_update(t, refname, new_oid, old_oid,
David Turner74ec19d2015-07-31 02:06:19 -04001224 flags, msg, &err) ||
1225 ref_transaction_commit(t, &err)) {
1226 ret = 1;
1227 ref_transaction_free(t);
1228 }
1229 }
1230 if (ret) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02001231 const char *str = _("update_ref failed for ref '%s': %s");
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001232
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001233 switch (onerr) {
1234 case UPDATE_REFS_MSG_ON_ERR:
1235 error(str, refname, err.buf);
1236 break;
1237 case UPDATE_REFS_DIE_ON_ERR:
1238 die(str, refname, err.buf);
1239 break;
1240 case UPDATE_REFS_QUIET_ON_ERR:
1241 break;
1242 }
1243 strbuf_release(&err);
Brad King4738a332013-09-04 11:22:40 -04001244 return 1;
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001245 }
1246 strbuf_release(&err);
David Turner74ec19d2015-07-31 02:06:19 -04001247 if (t)
1248 ref_transaction_free(t);
Ronnie Sahlbergb4d75ac2014-04-24 16:36:55 -07001249 return 0;
Brad King4738a332013-09-04 11:22:40 -04001250}
1251
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001252int update_ref(const char *msg, const char *refname,
brian m. carlsonae077772017-10-15 22:06:51 +00001253 const struct object_id *new_oid,
1254 const struct object_id *old_oid,
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001255 unsigned int flags, enum action_on_err onerr)
1256{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001257 return refs_update_ref(get_main_ref_store(the_repository), msg, refname, new_oid,
brian m. carlsonae077772017-10-15 22:06:51 +00001258 old_oid, flags, onerr);
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07001259}
1260
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001261char *refs_shorten_unambiguous_ref(struct ref_store *refs,
1262 const char *refname, int strict)
Jeff King7c2b3022009-04-07 03:14:20 -04001263{
1264 int i;
1265 static char **scanf_fmts;
1266 static int nr_rules;
1267 char *short_name;
Jeff King6cd4a892017-03-28 15:46:33 -04001268 struct strbuf resolved_buf = STRBUF_INIT;
Jeff King7c2b3022009-04-07 03:14:20 -04001269
Jeff King7c2b3022009-04-07 03:14:20 -04001270 if (!nr_rules) {
Michael Haggerty43466632014-01-08 15:43:39 +01001271 /*
1272 * Pre-generate scanf formats from ref_rev_parse_rules[].
1273 * Generate a format suitable for scanf from a
1274 * ref_rev_parse_rules rule by interpolating "%s" at the
1275 * location of the "%.*s".
1276 */
Jeff King7c2b3022009-04-07 03:14:20 -04001277 size_t total_len = 0;
Michael Haggerty84d56332014-01-08 15:43:38 +01001278 size_t offset = 0;
Jeff King7c2b3022009-04-07 03:14:20 -04001279
1280 /* the rule list is NULL terminated, count them first */
Jeff Kinga4165852013-10-24 04:45:13 -04001281 for (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++)
Michael Haggerty7902fe02014-01-08 15:43:40 +01001282 /* -2 for strlen("%.*s") - strlen("%s"); +1 for NUL */
1283 total_len += strlen(ref_rev_parse_rules[nr_rules]) - 2 + 1;
Jeff King7c2b3022009-04-07 03:14:20 -04001284
René Scharfe50492f72016-07-30 20:18:31 +02001285 scanf_fmts = xmalloc(st_add(st_mult(sizeof(char *), nr_rules), total_len));
Jeff King7c2b3022009-04-07 03:14:20 -04001286
Michael Haggerty84d56332014-01-08 15:43:38 +01001287 offset = 0;
Jeff King7c2b3022009-04-07 03:14:20 -04001288 for (i = 0; i < nr_rules; i++) {
Michael Haggerty43466632014-01-08 15:43:39 +01001289 assert(offset < total_len);
Michael Haggerty84d56332014-01-08 15:43:38 +01001290 scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset;
Jeff Kingbf4baf12018-05-18 18:58:20 -07001291 offset += xsnprintf(scanf_fmts[i], total_len - offset,
1292 ref_rev_parse_rules[i], 2, "%s") + 1;
Jeff King7c2b3022009-04-07 03:14:20 -04001293 }
1294 }
1295
1296 /* bail out if there are no rules */
1297 if (!nr_rules)
Michael Haggertydfefa932011-12-12 06:38:09 +01001298 return xstrdup(refname);
Jeff King7c2b3022009-04-07 03:14:20 -04001299
Michael Haggertydfefa932011-12-12 06:38:09 +01001300 /* buffer for scanf result, at most refname must fit */
1301 short_name = xstrdup(refname);
Jeff King7c2b3022009-04-07 03:14:20 -04001302
1303 /* skip first rule, it will always match */
1304 for (i = nr_rules - 1; i > 0 ; --i) {
1305 int j;
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001306 int rules_to_fail = i;
Jeff King7c2b3022009-04-07 03:14:20 -04001307 int short_name_len;
1308
Michael Haggertydfefa932011-12-12 06:38:09 +01001309 if (1 != sscanf(refname, scanf_fmts[i], short_name))
Jeff King7c2b3022009-04-07 03:14:20 -04001310 continue;
1311
1312 short_name_len = strlen(short_name);
1313
1314 /*
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001315 * in strict mode, all (except the matched one) rules
1316 * must fail to resolve to a valid non-ambiguous ref
1317 */
1318 if (strict)
1319 rules_to_fail = nr_rules;
1320
1321 /*
Jeff King7c2b3022009-04-07 03:14:20 -04001322 * check if the short name resolves to a valid ref,
1323 * but use only rules prior to the matched one
1324 */
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001325 for (j = 0; j < rules_to_fail; j++) {
Jeff King7c2b3022009-04-07 03:14:20 -04001326 const char *rule = ref_rev_parse_rules[j];
Jeff King7c2b3022009-04-07 03:14:20 -04001327
Bert Wesarg6e7b3302009-04-13 12:25:46 +02001328 /* skip matched rule */
1329 if (i == j)
1330 continue;
1331
Jeff King7c2b3022009-04-07 03:14:20 -04001332 /*
1333 * the short name is ambiguous, if it resolves
1334 * (with this previous rule) to a valid ref
1335 * read_ref() returns 0 on success
1336 */
Jeff King6cd4a892017-03-28 15:46:33 -04001337 strbuf_reset(&resolved_buf);
1338 strbuf_addf(&resolved_buf, rule,
1339 short_name_len, short_name);
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001340 if (refs_ref_exists(refs, resolved_buf.buf))
Jeff King7c2b3022009-04-07 03:14:20 -04001341 break;
1342 }
1343
1344 /*
1345 * short name is non-ambiguous if all previous rules
1346 * haven't resolved to a valid ref
1347 */
Jeff King6cd4a892017-03-28 15:46:33 -04001348 if (j == rules_to_fail) {
1349 strbuf_release(&resolved_buf);
Jeff King7c2b3022009-04-07 03:14:20 -04001350 return short_name;
Jeff King6cd4a892017-03-28 15:46:33 -04001351 }
Jeff King7c2b3022009-04-07 03:14:20 -04001352 }
1353
Jeff King6cd4a892017-03-28 15:46:33 -04001354 strbuf_release(&resolved_buf);
Jeff King7c2b3022009-04-07 03:14:20 -04001355 free(short_name);
Michael Haggertydfefa932011-12-12 06:38:09 +01001356 return xstrdup(refname);
Jeff King7c2b3022009-04-07 03:14:20 -04001357}
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001358
Nguyễn Thái Ngọc Duy546edf32019-04-06 18:34:25 +07001359char *shorten_unambiguous_ref(const char *refname, int strict)
1360{
1361 return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
1362 refname, strict);
1363}
1364
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001365static struct string_list *hide_refs;
1366
1367int parse_hide_refs_config(const char *var, const char *value, const char *section)
1368{
Jeff Kingad8c7cd2017-02-24 16:08:16 -05001369 const char *key;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001370 if (!strcmp("transfer.hiderefs", var) ||
Jeff Kingad8c7cd2017-02-24 16:08:16 -05001371 (!parse_config_key(var, section, NULL, NULL, &key) &&
1372 !strcmp(key, "hiderefs"))) {
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001373 char *ref;
1374 int len;
1375
1376 if (!value)
1377 return config_error_nonbool(var);
1378 ref = xstrdup(value);
1379 len = strlen(ref);
1380 while (len && ref[len - 1] == '/')
1381 ref[--len] = '\0';
1382 if (!hide_refs) {
1383 hide_refs = xcalloc(1, sizeof(*hide_refs));
1384 hide_refs->strdup_strings = 1;
1385 }
1386 string_list_append(hide_refs, ref);
1387 }
1388 return 0;
1389}
1390
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001391int ref_is_hidden(const char *refname, const char *refname_full)
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001392{
Jeff King2bc31d12015-07-28 16:23:26 -04001393 int i;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001394
1395 if (!hide_refs)
1396 return 0;
Jeff King2bc31d12015-07-28 16:23:26 -04001397 for (i = hide_refs->nr - 1; i >= 0; i--) {
1398 const char *match = hide_refs->items[i].string;
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001399 const char *subject;
Jeff King2bc31d12015-07-28 16:23:26 -04001400 int neg = 0;
Christian Couder7a40a952017-07-22 06:39:12 +02001401 const char *p;
Jeff King2bc31d12015-07-28 16:23:26 -04001402
1403 if (*match == '!') {
1404 neg = 1;
1405 match++;
1406 }
1407
Lukas Fleischer78a766a2015-11-03 08:58:16 +01001408 if (*match == '^') {
1409 subject = refname_full;
1410 match++;
1411 } else {
1412 subject = refname;
1413 }
1414
1415 /* refname can be NULL when namespaces are used. */
Christian Couder7a40a952017-07-22 06:39:12 +02001416 if (subject &&
1417 skip_prefix(subject, match, &p) &&
1418 (!*p || *p == '/'))
Jeff King2bc31d12015-07-28 16:23:26 -04001419 return !neg;
Junio C Hamanodaebaa72013-01-18 16:08:30 -08001420 }
1421 return 0;
1422}
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001423
David Turner08451222015-11-10 12:42:40 +01001424const char *find_descendant_ref(const char *dirname,
1425 const struct string_list *extras,
1426 const struct string_list *skip)
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001427{
David Turner08451222015-11-10 12:42:40 +01001428 int pos;
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001429
David Turner08451222015-11-10 12:42:40 +01001430 if (!extras)
1431 return NULL;
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001432
1433 /*
David Turner08451222015-11-10 12:42:40 +01001434 * Look at the place where dirname would be inserted into
1435 * extras. If there is an entry at that position that starts
1436 * with dirname (remember, dirname includes the trailing
1437 * slash) and is not in skip, then we have a conflict.
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001438 */
David Turner08451222015-11-10 12:42:40 +01001439 for (pos = string_list_find_insert_index(extras, dirname, 0);
1440 pos < extras->nr; pos++) {
1441 const char *extra_refname = extras->items[pos].string;
1442
1443 if (!starts_with(extra_refname, dirname))
1444 break;
1445
1446 if (!skip || !string_list_has_string(skip, extra_refname))
1447 return extra_refname;
Michael Haggerty4a32b2e2015-05-11 17:25:15 +02001448 }
David Turner08451222015-11-10 12:42:40 +01001449 return NULL;
1450}
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001451
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001452int refs_rename_ref_available(struct ref_store *refs,
1453 const char *old_refname,
1454 const char *new_refname)
David Turner08451222015-11-10 12:42:40 +01001455{
1456 struct string_list skip = STRING_LIST_INIT_NODUP;
1457 struct strbuf err = STRBUF_INIT;
David Turnerff3a2992016-09-04 18:08:08 +02001458 int ok;
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001459
David Turnerff3a2992016-09-04 18:08:08 +02001460 string_list_insert(&skip, old_refname);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001461 ok = !refs_verify_refname_available(refs, new_refname,
1462 NULL, &skip, &err);
David Turnerff3a2992016-09-04 18:08:08 +02001463 if (!ok)
David Turner08451222015-11-10 12:42:40 +01001464 error("%s", err.buf);
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001465
David Turner08451222015-11-10 12:42:40 +01001466 string_list_clear(&skip, 0);
1467 strbuf_release(&err);
David Turnerff3a2992016-09-04 18:08:08 +02001468 return ok;
Michael Haggertyfa5b1832014-12-12 09:56:59 +01001469}
David Turner2bf68ed2016-04-07 15:02:48 -04001470
Nguyễn Thái Ngọc Duy62f0b392017-08-23 19:36:55 +07001471int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turner2bf68ed2016-04-07 15:02:48 -04001472{
1473 struct object_id oid;
1474 int flag;
1475
Nguyễn Thái Ngọc Duy62f0b392017-08-23 19:36:55 +07001476 if (!refs_read_ref_full(refs, "HEAD", RESOLVE_REF_READING,
brian m. carlson34c290a2017-10-15 22:06:56 +00001477 &oid, &flag))
David Turner2bf68ed2016-04-07 15:02:48 -04001478 return fn("HEAD", &oid, flag, cb_data);
1479
1480 return 0;
1481}
1482
1483int head_ref(each_ref_fn fn, void *cb_data)
1484{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001485 return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data);
David Turner2bf68ed2016-04-07 15:02:48 -04001486}
David Turner93770592016-04-07 15:02:49 -04001487
Michael Haggertye121b9c2017-03-20 17:33:08 +01001488struct ref_iterator *refs_ref_iterator_begin(
1489 struct ref_store *refs,
1490 const char *prefix, int trim, int flags)
1491{
1492 struct ref_iterator *iter;
1493
Michael Haggerty0a0865b2017-05-22 16:17:52 +02001494 if (ref_paranoia < 0)
1495 ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 0);
1496 if (ref_paranoia)
1497 flags |= DO_FOR_EACH_INCLUDE_BROKEN;
1498
Michael Haggertye121b9c2017-03-20 17:33:08 +01001499 iter = refs->be->iterator_begin(refs, prefix, flags);
Michael Haggertyc7599712017-05-22 16:17:36 +02001500
1501 /*
1502 * `iterator_begin()` already takes care of prefix, but we
1503 * might need to do some trimming:
1504 */
1505 if (trim)
1506 iter = prefix_ref_iterator_begin(iter, "", trim);
Michael Haggertye121b9c2017-03-20 17:33:08 +01001507
Michael Haggerty8738a8a2017-09-13 19:15:55 +02001508 /* Sanity check for subclasses: */
1509 if (!iter->ordered)
1510 BUG("reference iterator is not ordered");
1511
Michael Haggertye121b9c2017-03-20 17:33:08 +01001512 return iter;
1513}
1514
Michael Haggerty4c4de892016-06-18 06:15:16 +02001515/*
1516 * Call fn for each reference in the specified submodule for which the
1517 * refname begins with prefix. If trim is non-zero, then trim that
1518 * many characters off the beginning of each refname before passing
1519 * the refname to fn. flags can be DO_FOR_EACH_INCLUDE_BROKEN to
1520 * include broken references in the iteration. If fn ever returns a
1521 * non-zero value, stop the iteration and return that value;
1522 * otherwise, return 0.
1523 */
Stefan Beller4a6067c2018-08-20 18:24:16 +00001524static int do_for_each_repo_ref(struct repository *r, const char *prefix,
1525 each_repo_ref_fn fn, int trim, int flags,
1526 void *cb_data)
Michael Haggerty4c4de892016-06-18 06:15:16 +02001527{
1528 struct ref_iterator *iter;
Stefan Beller4a6067c2018-08-20 18:24:16 +00001529 struct ref_store *refs = get_main_ref_store(r);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001530
Michael Haggerty00eebe32016-09-04 18:08:11 +02001531 if (!refs)
1532 return 0;
1533
Michael Haggertye121b9c2017-03-20 17:33:08 +01001534 iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001535
Stefan Beller4a6067c2018-08-20 18:24:16 +00001536 return do_for_each_repo_ref_iterator(r, iter, fn, cb_data);
1537}
1538
1539struct do_for_each_ref_help {
1540 each_ref_fn *fn;
1541 void *cb_data;
1542};
1543
1544static int do_for_each_ref_helper(struct repository *r,
1545 const char *refname,
1546 const struct object_id *oid,
1547 int flags,
1548 void *cb_data)
1549{
1550 struct do_for_each_ref_help *hp = cb_data;
1551
1552 return hp->fn(refname, oid, flags, hp->cb_data);
1553}
1554
1555static int do_for_each_ref(struct ref_store *refs, const char *prefix,
1556 each_ref_fn fn, int trim, int flags, void *cb_data)
1557{
1558 struct ref_iterator *iter;
1559 struct do_for_each_ref_help hp = { fn, cb_data };
1560
1561 if (!refs)
1562 return 0;
1563
1564 iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
1565
1566 return do_for_each_repo_ref_iterator(the_repository, iter,
1567 do_for_each_ref_helper, &hp);
Michael Haggerty4c4de892016-06-18 06:15:16 +02001568}
1569
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001570int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
1571{
1572 return do_for_each_ref(refs, "", fn, 0, 0, cb_data);
1573}
1574
David Turner93770592016-04-07 15:02:49 -04001575int for_each_ref(each_ref_fn fn, void *cb_data)
1576{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001577 return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data);
David Turner93770592016-04-07 15:02:49 -04001578}
1579
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001580int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
1581 each_ref_fn fn, void *cb_data)
1582{
1583 return do_for_each_ref(refs, prefix, fn, strlen(prefix), 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001584}
1585
1586int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
1587{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001588 return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data);
David Turner93770592016-04-07 15:02:49 -04001589}
1590
1591int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsigned int broken)
1592{
1593 unsigned int flag = 0;
1594
1595 if (broken)
1596 flag = DO_FOR_EACH_INCLUDE_BROKEN;
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001597 return do_for_each_ref(get_main_ref_store(the_repository),
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001598 prefix, fn, 0, flag, cb_data);
David Turner93770592016-04-07 15:02:49 -04001599}
1600
Nguyễn Thái Ngọc Duy073cf632017-08-23 19:36:56 +07001601int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
1602 each_ref_fn fn, void *cb_data,
1603 unsigned int broken)
Michael Haggerty03df5672017-06-18 15:39:41 +02001604{
1605 unsigned int flag = 0;
1606
1607 if (broken)
1608 flag = DO_FOR_EACH_INCLUDE_BROKEN;
Nguyễn Thái Ngọc Duy073cf632017-08-23 19:36:56 +07001609 return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data);
Michael Haggerty03df5672017-06-18 15:39:41 +02001610}
1611
Stefan Beller212e0f72018-08-20 18:24:19 +00001612int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001613{
Stefan Beller212e0f72018-08-20 18:24:19 +00001614 return do_for_each_repo_ref(r, git_replace_ref_base, fn,
1615 strlen(git_replace_ref_base),
1616 DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
David Turner93770592016-04-07 15:02:49 -04001617}
1618
1619int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
1620{
1621 struct strbuf buf = STRBUF_INIT;
1622 int ret;
1623 strbuf_addf(&buf, "%srefs/", get_git_namespace());
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001624 ret = do_for_each_ref(get_main_ref_store(the_repository),
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001625 buf.buf, fn, 0, 0, cb_data);
David Turner93770592016-04-07 15:02:49 -04001626 strbuf_release(&buf);
1627 return ret;
1628}
1629
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001630int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turner93770592016-04-07 15:02:49 -04001631{
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001632 return do_for_each_ref(refs, "", fn, 0,
David Turner93770592016-04-07 15:02:49 -04001633 DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
1634}
David Turner2d0663b2016-04-07 15:03:10 -04001635
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001636int for_each_rawref(each_ref_fn fn, void *cb_data)
1637{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001638 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 +07001639}
1640
Michael Haggerty470be512017-03-20 17:33:07 +01001641int refs_read_raw_ref(struct ref_store *ref_store,
brian m. carlson99afe912017-10-15 22:07:11 +00001642 const char *refname, struct object_id *oid,
Michael Haggerty470be512017-03-20 17:33:07 +01001643 struct strbuf *referent, unsigned int *type)
1644{
brian m. carlson99afe912017-10-15 22:07:11 +00001645 return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, type);
Michael Haggerty470be512017-03-20 17:33:07 +01001646}
1647
David Turner2d0663b2016-04-07 15:03:10 -04001648/* This function needs to return a meaningful errno on failure */
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001649const char *refs_resolve_ref_unsafe(struct ref_store *refs,
Michael Haggerty3c0cb0c2017-02-09 21:53:52 +01001650 const char *refname,
1651 int resolve_flags,
brian m. carlson49e61472017-10-15 22:07:09 +00001652 struct object_id *oid, int *flags)
David Turner2d0663b2016-04-07 15:03:10 -04001653{
1654 static struct strbuf sb_refname = STRBUF_INIT;
René Scharfe54fad662017-09-23 11:41:45 +02001655 struct object_id unused_oid;
David Turner2d0663b2016-04-07 15:03:10 -04001656 int unused_flags;
1657 int symref_count;
1658
brian m. carlson49e61472017-10-15 22:07:09 +00001659 if (!oid)
1660 oid = &unused_oid;
David Turner2d0663b2016-04-07 15:03:10 -04001661 if (!flags)
1662 flags = &unused_flags;
1663
1664 *flags = 0;
1665
1666 if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
1667 if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
1668 !refname_is_safe(refname)) {
1669 errno = EINVAL;
1670 return NULL;
1671 }
1672
1673 /*
1674 * dwim_ref() uses REF_ISBROKEN to distinguish between
1675 * missing refs and refs that were present but invalid,
1676 * to complain about the latter to stderr.
1677 *
1678 * We don't know whether the ref exists, so don't set
1679 * REF_ISBROKEN yet.
1680 */
1681 *flags |= REF_BAD_NAME;
1682 }
1683
1684 for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
1685 unsigned int read_flags = 0;
1686
Michael Haggerty470be512017-03-20 17:33:07 +01001687 if (refs_read_raw_ref(refs, refname,
brian m. carlson99afe912017-10-15 22:07:11 +00001688 oid, &sb_refname, &read_flags)) {
David Turner2d0663b2016-04-07 15:03:10 -04001689 *flags |= read_flags;
Jeff Kinga1c1d812017-10-06 10:42:17 -04001690
1691 /* In reading mode, refs must eventually resolve */
1692 if (resolve_flags & RESOLVE_REF_READING)
David Turner2d0663b2016-04-07 15:03:10 -04001693 return NULL;
Jeff Kinga1c1d812017-10-06 10:42:17 -04001694
1695 /*
1696 * Otherwise a missing ref is OK. But the files backend
1697 * may show errors besides ENOENT if there are
1698 * similarly-named refs.
1699 */
1700 if (errno != ENOENT &&
1701 errno != EISDIR &&
1702 errno != ENOTDIR)
1703 return NULL;
1704
brian m. carlson49e61472017-10-15 22:07:09 +00001705 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001706 if (*flags & REF_BAD_NAME)
1707 *flags |= REF_ISBROKEN;
1708 return refname;
1709 }
1710
1711 *flags |= read_flags;
1712
1713 if (!(read_flags & REF_ISSYMREF)) {
1714 if (*flags & REF_BAD_NAME) {
brian m. carlson49e61472017-10-15 22:07:09 +00001715 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001716 *flags |= REF_ISBROKEN;
1717 }
1718 return refname;
1719 }
1720
1721 refname = sb_refname.buf;
1722 if (resolve_flags & RESOLVE_REF_NO_RECURSE) {
brian m. carlson49e61472017-10-15 22:07:09 +00001723 oidclr(oid);
David Turner2d0663b2016-04-07 15:03:10 -04001724 return refname;
1725 }
1726 if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
1727 if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
1728 !refname_is_safe(refname)) {
1729 errno = EINVAL;
1730 return NULL;
1731 }
1732
1733 *flags |= REF_ISBROKEN | REF_BAD_NAME;
1734 }
1735 }
1736
1737 errno = ELOOP;
1738 return NULL;
1739}
Michael Haggerty00eebe32016-09-04 18:08:11 +02001740
David Turner6fb5acf2016-09-04 18:08:41 +02001741/* backend functions */
1742int refs_init_db(struct strbuf *err)
1743{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001744 struct ref_store *refs = get_main_ref_store(the_repository);
David Turner6fb5acf2016-09-04 18:08:41 +02001745
1746 return refs->be->init_db(refs, err);
1747}
1748
Michael Haggertybd40dcd2016-09-04 18:08:21 +02001749const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
brian m. carlson49e61472017-10-15 22:07:09 +00001750 struct object_id *oid, int *flags)
Michael Haggertybd40dcd2016-09-04 18:08:21 +02001751{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001752 return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname,
brian m. carlson49e61472017-10-15 22:07:09 +00001753 resolve_flags, oid, flags);
Michael Haggertybd40dcd2016-09-04 18:08:21 +02001754}
1755
Michael Haggertya8355bb2016-09-04 18:08:24 +02001756int resolve_gitlink_ref(const char *submodule, const char *refname,
brian m. carlsona98e6102017-10-15 22:07:07 +00001757 struct object_id *oid)
Michael Haggerty424dcc72016-09-04 18:08:22 +02001758{
Michael Haggerty424dcc72016-09-04 18:08:22 +02001759 struct ref_store *refs;
1760 int flags;
1761
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07001762 refs = get_submodule_ref_store(submodule);
Michael Haggerty48a84752016-09-04 18:08:23 +02001763
Michael Haggerty424dcc72016-09-04 18:08:22 +02001764 if (!refs)
1765 return -1;
1766
brian m. carlson49e61472017-10-15 22:07:09 +00001767 if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags) ||
brian m. carlsona98e6102017-10-15 22:07:07 +00001768 is_null_oid(oid))
Michael Haggerty424dcc72016-09-04 18:08:22 +02001769 return -1;
1770 return 0;
1771}
1772
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001773struct ref_store_hash_entry
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001774{
Eric Wonge2b50382019-10-06 23:30:43 +00001775 struct hashmap_entry ent;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001776
1777 struct ref_store *refs;
1778
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001779 /* NUL-terminated identifier of the ref store: */
1780 char name[FLEX_ARRAY];
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001781};
1782
Stefan Beller7663cdc2017-06-30 12:14:05 -07001783static int ref_store_hash_cmp(const void *unused_cmp_data,
Eric Wong939af162019-10-06 23:30:37 +00001784 const struct hashmap_entry *eptr,
1785 const struct hashmap_entry *entry_or_key,
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001786 const void *keydata)
1787{
Eric Wong939af162019-10-06 23:30:37 +00001788 const struct ref_store_hash_entry *e1, *e2;
1789 const char *name;
1790
1791 e1 = container_of(eptr, const struct ref_store_hash_entry, ent);
1792 e2 = container_of(entry_or_key, const struct ref_store_hash_entry, ent);
1793 name = keydata ? keydata : e2->name;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001794
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001795 return strcmp(e1->name, name);
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001796}
1797
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001798static struct ref_store_hash_entry *alloc_ref_store_hash_entry(
1799 const char *name, struct ref_store *refs)
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001800{
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001801 struct ref_store_hash_entry *entry;
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001802
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001803 FLEX_ALLOC_STR(entry, name, name);
Eric Wongd22245a2019-10-06 23:30:27 +00001804 hashmap_entry_init(&entry->ent, strhash(name));
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001805 entry->refs = refs;
1806 return entry;
1807}
1808
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001809/* A hashmap of ref_stores, stored by submodule name: */
1810static struct hashmap submodule_ref_stores;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001811
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07001812/* A hashmap of ref_stores, stored by worktree id: */
1813static struct hashmap worktree_ref_stores;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001814
Michael Haggerty00eebe32016-09-04 18:08:11 +02001815/*
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001816 * Look up a ref store by name. If that ref_store hasn't been
1817 * registered yet, return NULL.
Michael Haggerty00eebe32016-09-04 18:08:11 +02001818 */
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001819static struct ref_store *lookup_ref_store_map(struct hashmap *map,
1820 const char *name)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001821{
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001822 struct ref_store_hash_entry *entry;
Eric Wongf23a4652019-10-06 23:30:36 +00001823 unsigned int hash;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001824
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001825 if (!map->tablesize)
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001826 /* It's initialized on demand in register_ref_store(). */
1827 return NULL;
Michael Haggerty620a66b2017-02-10 12:16:11 +01001828
Eric Wongf23a4652019-10-06 23:30:36 +00001829 hash = strhash(name);
1830 entry = hashmap_get_entry_from_hash(map, hash, name,
1831 struct ref_store_hash_entry, ent);
Michael Haggerty7d4558c2017-02-10 12:16:15 +01001832 return entry ? entry->refs : NULL;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001833}
1834
Michael Haggertyc468da42017-02-10 12:16:12 +01001835/*
1836 * Create, record, and return a ref_store instance for the specified
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07001837 * gitdir.
Michael Haggertyc468da42017-02-10 12:16:12 +01001838 */
Nguyễn Thái Ngọc Duy9e7ec632017-03-26 09:42:32 +07001839static struct ref_store *ref_store_init(const char *gitdir,
1840 unsigned int flags)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001841{
1842 const char *be_name = "files";
1843 struct ref_storage_be *be = find_ref_storage_backend(be_name);
Michael Haggertyba88add2017-02-10 12:16:14 +01001844 struct ref_store *refs;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001845
1846 if (!be)
Johannes Schindelin033abf92018-05-02 11:38:39 +02001847 BUG("reference backend %s is unknown", be_name);
Michael Haggerty00eebe32016-09-04 18:08:11 +02001848
Nguyễn Thái Ngọc Duy9e7ec632017-03-26 09:42:32 +07001849 refs = be->init(gitdir, flags);
Michael Haggertyba88add2017-02-10 12:16:14 +01001850 return refs;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001851}
1852
Stefan Beller64a74162018-04-11 17:21:14 -07001853struct ref_store *get_main_ref_store(struct repository *r)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001854{
Stefan Beller64a74162018-04-11 17:21:14 -07001855 if (r->refs)
1856 return r->refs;
Nguyễn Thái Ngọc Duy24c84072017-03-26 09:42:25 +07001857
Jeff King2dc417a2018-05-18 15:25:53 -07001858 if (!r->gitdir)
1859 BUG("attempting to get main_ref_store outside of repository");
1860
Stefan Beller64a74162018-04-11 17:21:14 -07001861 r->refs = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS);
1862 return r->refs;
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07001863}
1864
1865/*
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001866 * Associate a ref store with a name. It is a fatal error to call this
1867 * function twice for the same name.
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07001868 */
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001869static void register_ref_store_map(struct hashmap *map,
1870 const char *type,
1871 struct ref_store *refs,
1872 const char *name)
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07001873{
Eric Wong26b455f2019-10-06 23:30:32 +00001874 struct ref_store_hash_entry *entry;
1875
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001876 if (!map->tablesize)
Stefan Beller7663cdc2017-06-30 12:14:05 -07001877 hashmap_init(map, ref_store_hash_cmp, NULL, 0);
Nguyễn Thái Ngọc Duy378dc912017-03-26 09:42:28 +07001878
Eric Wong26b455f2019-10-06 23:30:32 +00001879 entry = alloc_ref_store_hash_entry(name, refs);
1880 if (hashmap_put(map, &entry->ent))
Johannes Schindelin033abf92018-05-02 11:38:39 +02001881 BUG("%s ref_store '%s' initialized twice", type, name);
Nguyễn Thái Ngọc Duy24c84072017-03-26 09:42:25 +07001882}
1883
Nguyễn Thái Ngọc Duy18d00022017-03-26 09:42:33 +07001884struct ref_store *get_submodule_ref_store(const char *submodule)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001885{
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07001886 struct strbuf submodule_sb = STRBUF_INIT;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001887 struct ref_store *refs;
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07001888 char *to_free = NULL;
1889 size_t len;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001890
Nguyễn Thái Ngọc Duy82a150f2017-08-23 19:37:03 +07001891 if (!submodule)
1892 return NULL;
1893
Nguyễn Thái Ngọc Duy873ea902017-08-23 19:37:04 +07001894 len = strlen(submodule);
1895 while (len && is_dir_sep(submodule[len - 1]))
1896 len--;
1897 if (!len)
1898 return NULL;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001899
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07001900 if (submodule[len])
1901 /* We need to strip off one or more trailing slashes */
1902 submodule = to_free = xmemdupz(submodule, len);
Michael Haggerty00eebe32016-09-04 18:08:11 +02001903
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001904 refs = lookup_ref_store_map(&submodule_ref_stores, submodule);
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07001905 if (refs)
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07001906 goto done;
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07001907
1908 strbuf_addstr(&submodule_sb, submodule);
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07001909 if (!is_nonbare_repository_dir(&submodule_sb))
1910 goto done;
Nguyễn Thái Ngọc Duy126c9e02017-03-26 09:42:27 +07001911
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07001912 if (submodule_to_gitdir(&submodule_sb, submodule))
1913 goto done;
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07001914
Nguyễn Thái Ngọc Duy9e7ec632017-03-26 09:42:32 +07001915 /* assume that add_submodule_odb() has been called */
1916 refs = ref_store_init(submodule_sb.buf,
1917 REF_STORE_READ | REF_STORE_ODB);
Nguyễn Thái Ngọc Duy0c064d92017-04-04 17:21:20 +07001918 register_ref_store_map(&submodule_ref_stores, "submodule",
1919 refs, submodule);
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07001920
Nguyễn Thái Ngọc Duy2c616c12017-08-23 19:36:53 +07001921done:
Nguyễn Thái Ngọc Duy5d0bc902017-03-26 09:42:31 +07001922 strbuf_release(&submodule_sb);
Nguyễn Thái Ngọc Duy29babbe2017-08-23 19:36:54 +07001923 free(to_free);
1924
Michael Haggerty00eebe32016-09-04 18:08:11 +02001925 return refs;
1926}
1927
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07001928struct ref_store *get_worktree_ref_store(const struct worktree *wt)
1929{
1930 struct ref_store *refs;
1931 const char *id;
1932
1933 if (wt->is_current)
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001934 return get_main_ref_store(the_repository);
Nguyễn Thái Ngọc Duy17eff962017-04-24 17:01:22 +07001935
1936 id = wt->id ? wt->id : "/";
1937 refs = lookup_ref_store_map(&worktree_ref_stores, id);
1938 if (refs)
1939 return refs;
1940
1941 if (wt->id)
1942 refs = ref_store_init(git_common_path("worktrees/%s", wt->id),
1943 REF_STORE_ALL_CAPS);
1944 else
1945 refs = ref_store_init(get_git_common_dir(),
1946 REF_STORE_ALL_CAPS);
1947
1948 if (refs)
1949 register_ref_store_map(&worktree_ref_stores, "worktree",
1950 refs, id);
1951 return refs;
1952}
1953
Michael Haggerty620a66b2017-02-10 12:16:11 +01001954void base_ref_store_init(struct ref_store *refs,
Michael Haggertyfbfd0a22017-02-10 12:16:17 +01001955 const struct ref_storage_be *be)
Michael Haggerty00eebe32016-09-04 18:08:11 +02001956{
Michael Haggerty620a66b2017-02-10 12:16:11 +01001957 refs->be = be;
Michael Haggerty00eebe32016-09-04 18:08:11 +02001958}
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02001959
1960/* backend functions */
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001961int refs_pack_refs(struct ref_store *refs, unsigned int flags)
Michael Haggerty82315272016-09-04 18:08:27 +02001962{
Michael Haggerty82315272016-09-04 18:08:27 +02001963 return refs->be->pack_refs(refs, flags);
1964}
1965
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001966int refs_peel_ref(struct ref_store *refs, const char *refname,
brian m. carlsonb420d902017-10-15 22:07:02 +00001967 struct object_id *oid)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001968{
Michael Haggertyba1c0522017-09-25 10:00:14 +02001969 int flag;
brian m. carlson34c290a2017-10-15 22:06:56 +00001970 struct object_id base;
Michael Haggertyba1c0522017-09-25 10:00:14 +02001971
1972 if (current_ref_iter && current_ref_iter->refname == refname) {
1973 struct object_id peeled;
1974
1975 if (ref_iterator_peel(current_ref_iter, &peeled))
1976 return -1;
brian m. carlsonb420d902017-10-15 22:07:02 +00001977 oidcpy(oid, &peeled);
Michael Haggertyba1c0522017-09-25 10:00:14 +02001978 return 0;
1979 }
1980
1981 if (refs_read_ref_full(refs, refname,
brian m. carlson34c290a2017-10-15 22:06:56 +00001982 RESOLVE_REF_READING, &base, &flag))
Michael Haggertyba1c0522017-09-25 10:00:14 +02001983 return -1;
1984
brian m. carlsonac2ed0d2017-10-15 22:07:10 +00001985 return peel_object(&base, oid);
Ronnie Sahlberg127b42a2016-09-04 18:08:16 +02001986}
1987
brian m. carlsonb420d902017-10-15 22:07:02 +00001988int peel_ref(const char *refname, struct object_id *oid)
Michael Haggertybd427cf2016-09-04 18:08:29 +02001989{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07001990 return refs_peel_ref(get_main_ref_store(the_repository), refname, oid);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001991}
Michael Haggertybd427cf2016-09-04 18:08:29 +02001992
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07001993int refs_create_symref(struct ref_store *refs,
1994 const char *ref_target,
1995 const char *refs_heads_master,
1996 const char *logmsg)
1997{
1998 return refs->be->create_symref(refs, ref_target,
1999 refs_heads_master,
2000 logmsg);
Michael Haggertybd427cf2016-09-04 18:08:29 +02002001}
2002
Michael Haggerty284689b2016-09-04 18:08:28 +02002003int create_symref(const char *ref_target, const char *refs_heads_master,
2004 const char *logmsg)
2005{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002006 return refs_create_symref(get_main_ref_store(the_repository), ref_target,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002007 refs_heads_master, logmsg);
Michael Haggerty284689b2016-09-04 18:08:28 +02002008}
2009
Michael Haggerty2ced1052017-05-22 16:17:45 +02002010int ref_update_reject_duplicates(struct string_list *refnames,
2011 struct strbuf *err)
2012{
Michael Haggertya552e502017-05-22 16:17:46 +02002013 size_t i, n = refnames->nr;
Michael Haggerty2ced1052017-05-22 16:17:45 +02002014
2015 assert(err);
2016
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002017 for (i = 1; i < n; i++) {
2018 int cmp = strcmp(refnames->items[i - 1].string,
2019 refnames->items[i].string);
2020
2021 if (!cmp) {
Michael Haggerty2ced1052017-05-22 16:17:45 +02002022 strbuf_addf(err,
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002023 _("multiple updates for ref '%s' not allowed"),
Michael Haggerty2ced1052017-05-22 16:17:45 +02002024 refnames->items[i].string);
2025 return 1;
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002026 } else if (cmp > 0) {
Johannes Schindelin033abf92018-05-02 11:38:39 +02002027 BUG("ref_update_reject_duplicates() received unsorted list");
Michael Haggerty2ced1052017-05-22 16:17:45 +02002028 }
Michael Haggerty8556f8d2017-05-22 16:17:47 +02002029 }
Michael Haggerty2ced1052017-05-22 16:17:45 +02002030 return 0;
2031}
2032
Michael Haggerty30173b82017-05-22 16:17:44 +02002033int ref_transaction_prepare(struct ref_transaction *transaction,
2034 struct strbuf *err)
Daniel Barkalow95fc7512005-06-06 16:31:29 -04002035{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07002036 struct ref_store *refs = transaction->ref_store;
Daniel Barkalow95fc7512005-06-06 16:31:29 -04002037
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002038 switch (transaction->state) {
2039 case REF_TRANSACTION_OPEN:
2040 /* Good. */
2041 break;
Michael Haggerty30173b82017-05-22 16:17:44 +02002042 case REF_TRANSACTION_PREPARED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002043 BUG("prepare called twice on reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002044 break;
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002045 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002046 BUG("prepare called on a closed reference transaction");
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002047 break;
2048 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002049 BUG("unexpected reference transaction state");
Michael Haggerty8d4240d2017-05-22 16:17:43 +02002050 break;
2051 }
2052
Jeff Kingd8f44812017-04-10 18:14:12 -04002053 if (getenv(GIT_QUARANTINE_ENVIRONMENT)) {
2054 strbuf_addstr(err,
2055 _("ref updates forbidden inside quarantine environment"));
2056 return -1;
2057 }
2058
Michael Haggerty30173b82017-05-22 16:17:44 +02002059 return refs->be->transaction_prepare(refs, transaction, err);
2060}
2061
2062int ref_transaction_abort(struct ref_transaction *transaction,
2063 struct strbuf *err)
2064{
2065 struct ref_store *refs = transaction->ref_store;
2066 int ret = 0;
2067
2068 switch (transaction->state) {
2069 case REF_TRANSACTION_OPEN:
2070 /* No need to abort explicitly. */
2071 break;
2072 case REF_TRANSACTION_PREPARED:
2073 ret = refs->be->transaction_abort(refs, transaction, err);
2074 break;
2075 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002076 BUG("abort called on a closed reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002077 break;
2078 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002079 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02002080 break;
2081 }
2082
2083 ref_transaction_free(transaction);
2084 return ret;
2085}
2086
2087int ref_transaction_commit(struct ref_transaction *transaction,
2088 struct strbuf *err)
2089{
2090 struct ref_store *refs = transaction->ref_store;
2091 int ret;
2092
2093 switch (transaction->state) {
2094 case REF_TRANSACTION_OPEN:
2095 /* Need to prepare first. */
2096 ret = ref_transaction_prepare(transaction, err);
2097 if (ret)
2098 return ret;
2099 break;
2100 case REF_TRANSACTION_PREPARED:
2101 /* Fall through to finish. */
2102 break;
2103 case REF_TRANSACTION_CLOSED:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002104 BUG("commit called on a closed reference transaction");
Michael Haggerty30173b82017-05-22 16:17:44 +02002105 break;
2106 default:
Johannes Schindelin033abf92018-05-02 11:38:39 +02002107 BUG("unexpected reference transaction state");
Michael Haggerty30173b82017-05-22 16:17:44 +02002108 break;
2109 }
2110
2111 return refs->be->transaction_finish(refs, transaction, err);
Daniel Barkalow95fc7512005-06-06 16:31:29 -04002112}
Michael Haggerty62665822016-09-04 18:08:26 +02002113
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002114int refs_verify_refname_available(struct ref_store *refs,
2115 const char *refname,
Michael Haggertyb05855b2017-04-16 08:41:26 +02002116 const struct string_list *extras,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002117 const struct string_list *skip,
2118 struct strbuf *err)
Michael Haggerty62665822016-09-04 18:08:26 +02002119{
Michael Haggertyb05855b2017-04-16 08:41:26 +02002120 const char *slash;
2121 const char *extra_refname;
2122 struct strbuf dirname = STRBUF_INIT;
2123 struct strbuf referent = STRBUF_INIT;
2124 struct object_id oid;
2125 unsigned int type;
2126 struct ref_iterator *iter;
2127 int ok;
2128 int ret = -1;
2129
2130 /*
2131 * For the sake of comments in this function, suppose that
2132 * refname is "refs/foo/bar".
2133 */
2134
2135 assert(err);
2136
2137 strbuf_grow(&dirname, strlen(refname) + 1);
2138 for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
2139 /* Expand dirname to the new prefix, not including the trailing slash: */
2140 strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
2141
2142 /*
2143 * We are still at a leading dir of the refname (e.g.,
2144 * "refs/foo"; if there is a reference with that name,
2145 * it is a conflict, *unless* it is in skip.
2146 */
2147 if (skip && string_list_has_string(skip, dirname.buf))
2148 continue;
2149
brian m. carlson99afe912017-10-15 22:07:11 +00002150 if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, &type)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002151 strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002152 dirname.buf, refname);
2153 goto cleanup;
2154 }
2155
2156 if (extras && string_list_has_string(extras, dirname.buf)) {
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002157 strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002158 refname, dirname.buf);
2159 goto cleanup;
2160 }
2161 }
2162
2163 /*
2164 * We are at the leaf of our refname (e.g., "refs/foo/bar").
2165 * There is no point in searching for a reference with that
2166 * name, because a refname isn't considered to conflict with
2167 * itself. But we still need to check for references whose
2168 * names are in the "refs/foo/bar/" namespace, because they
2169 * *do* conflict.
2170 */
2171 strbuf_addstr(&dirname, refname + dirname.len);
2172 strbuf_addch(&dirname, '/');
2173
2174 iter = refs_ref_iterator_begin(refs, dirname.buf, 0,
2175 DO_FOR_EACH_INCLUDE_BROKEN);
2176 while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
2177 if (skip &&
2178 string_list_has_string(skip, iter->refname))
2179 continue;
2180
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002181 strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002182 iter->refname, refname);
2183 ref_iterator_abort(iter);
2184 goto cleanup;
2185 }
2186
2187 if (ok != ITER_DONE)
Johannes Schindelin033abf92018-05-02 11:38:39 +02002188 BUG("error while iterating over references");
Michael Haggertyb05855b2017-04-16 08:41:26 +02002189
2190 extra_refname = find_descendant_ref(dirname.buf, extras, skip);
2191 if (extra_refname)
Nguyễn Thái Ngọc Duy661558f2018-07-21 09:49:35 +02002192 strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
Michael Haggertyb05855b2017-04-16 08:41:26 +02002193 refname, extra_refname);
2194 else
2195 ret = 0;
2196
2197cleanup:
2198 strbuf_release(&referent);
2199 strbuf_release(&dirname);
2200 return ret;
Michael Haggerty62665822016-09-04 18:08:26 +02002201}
David Turnere3688bd2016-09-04 18:08:38 +02002202
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002203int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
David Turnere3688bd2016-09-04 18:08:38 +02002204{
David Turnere3688bd2016-09-04 18:08:38 +02002205 struct ref_iterator *iter;
Stefan Beller4a6067c2018-08-20 18:24:16 +00002206 struct do_for_each_ref_help hp = { fn, cb_data };
David Turnere3688bd2016-09-04 18:08:38 +02002207
2208 iter = refs->be->reflog_iterator_begin(refs);
2209
Stefan Beller4a6067c2018-08-20 18:24:16 +00002210 return do_for_each_repo_ref_iterator(the_repository, iter,
2211 do_for_each_ref_helper, &hp);
David Turnere3688bd2016-09-04 18:08:38 +02002212}
2213
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002214int for_each_reflog(each_ref_fn fn, void *cb_data)
2215{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002216 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 +07002217}
2218
2219int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
2220 const char *refname,
2221 each_reflog_ent_fn fn,
2222 void *cb_data)
2223{
2224 return refs->be->for_each_reflog_ent_reverse(refs, refname,
2225 fn, cb_data);
2226}
2227
David Turnere3688bd2016-09-04 18:08:38 +02002228int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
2229 void *cb_data)
2230{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002231 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 +07002232 refname, fn, cb_data);
2233}
David Turnere3688bd2016-09-04 18:08:38 +02002234
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002235int refs_for_each_reflog_ent(struct ref_store *refs, const char *refname,
2236 each_reflog_ent_fn fn, void *cb_data)
2237{
2238 return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002239}
2240
2241int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
2242 void *cb_data)
2243{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002244 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 +07002245 fn, cb_data);
2246}
David Turnere3688bd2016-09-04 18:08:38 +02002247
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002248int refs_reflog_exists(struct ref_store *refs, const char *refname)
2249{
2250 return refs->be->reflog_exists(refs, refname);
David Turnere3688bd2016-09-04 18:08:38 +02002251}
2252
2253int reflog_exists(const char *refname)
2254{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002255 return refs_reflog_exists(get_main_ref_store(the_repository), refname);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002256}
David Turnere3688bd2016-09-04 18:08:38 +02002257
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002258int refs_create_reflog(struct ref_store *refs, const char *refname,
2259 int force_create, struct strbuf *err)
2260{
2261 return refs->be->create_reflog(refs, refname, force_create, err);
David Turnere3688bd2016-09-04 18:08:38 +02002262}
2263
2264int safe_create_reflog(const char *refname, int force_create,
2265 struct strbuf *err)
2266{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002267 return refs_create_reflog(get_main_ref_store(the_repository), refname,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002268 force_create, err);
2269}
David Turnere3688bd2016-09-04 18:08:38 +02002270
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002271int refs_delete_reflog(struct ref_store *refs, const char *refname)
2272{
2273 return refs->be->delete_reflog(refs, refname);
David Turnere3688bd2016-09-04 18:08:38 +02002274}
2275
2276int delete_reflog(const char *refname)
2277{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002278 return refs_delete_reflog(get_main_ref_store(the_repository), refname);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002279}
David Turnere3688bd2016-09-04 18:08:38 +02002280
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002281int refs_reflog_expire(struct ref_store *refs,
brian m. carlson0155f712017-10-15 22:07:04 +00002282 const char *refname, const struct object_id *oid,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002283 unsigned int flags,
2284 reflog_expiry_prepare_fn prepare_fn,
2285 reflog_expiry_should_prune_fn should_prune_fn,
2286 reflog_expiry_cleanup_fn cleanup_fn,
2287 void *policy_cb_data)
2288{
brian m. carlson0155f712017-10-15 22:07:04 +00002289 return refs->be->reflog_expire(refs, refname, oid, flags,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002290 prepare_fn, should_prune_fn,
2291 cleanup_fn, policy_cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002292}
2293
brian m. carlson0155f712017-10-15 22:07:04 +00002294int reflog_expire(const char *refname, const struct object_id *oid,
David Turnere3688bd2016-09-04 18:08:38 +02002295 unsigned int flags,
2296 reflog_expiry_prepare_fn prepare_fn,
2297 reflog_expiry_should_prune_fn should_prune_fn,
2298 reflog_expiry_cleanup_fn cleanup_fn,
2299 void *policy_cb_data)
2300{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002301 return refs_reflog_expire(get_main_ref_store(the_repository),
brian m. carlson0155f712017-10-15 22:07:04 +00002302 refname, oid, flags,
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002303 prepare_fn, should_prune_fn,
2304 cleanup_fn, policy_cb_data);
David Turnere3688bd2016-09-04 18:08:38 +02002305}
David Turnerfc681462016-09-04 18:08:39 +02002306
2307int initial_ref_transaction_commit(struct ref_transaction *transaction,
2308 struct strbuf *err)
2309{
Nguyễn Thái Ngọc Duyc0fe4e82017-03-26 09:42:35 +07002310 struct ref_store *refs = transaction->ref_store;
David Turnerfc681462016-09-04 18:08:39 +02002311
2312 return refs->be->initial_transaction_commit(refs, transaction, err);
2313}
David Turnera27dcf82016-09-04 18:08:40 +02002314
Michael Haggerty64da4192017-05-22 16:17:38 +02002315int refs_delete_refs(struct ref_store *refs, const char *msg,
2316 struct string_list *refnames, unsigned int flags)
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002317{
Michael Haggerty64da4192017-05-22 16:17:38 +02002318 return refs->be->delete_refs(refs, msg, refnames, flags);
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002319}
2320
Michael Haggerty64da4192017-05-22 16:17:38 +02002321int delete_refs(const char *msg, struct string_list *refnames,
2322 unsigned int flags)
David Turnera27dcf82016-09-04 18:08:40 +02002323{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002324 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 +07002325}
David Turnera27dcf82016-09-04 18:08:40 +02002326
Nguyễn Thái Ngọc Duy7d2df052017-03-26 09:42:34 +07002327int refs_rename_ref(struct ref_store *refs, const char *oldref,
2328 const char *newref, const char *logmsg)
2329{
2330 return refs->be->rename_ref(refs, oldref, newref, logmsg);
David Turnera27dcf82016-09-04 18:08:40 +02002331}
David Turner9b6b40d2016-09-04 18:08:42 +02002332
2333int rename_ref(const char *oldref, const char *newref, const char *logmsg)
2334{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002335 return refs_rename_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
David Turner9b6b40d2016-09-04 18:08:42 +02002336}
Sahil Dua52d59cc2017-06-18 23:19:16 +02002337
2338int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
2339 const char *newref, const char *logmsg)
2340{
2341 return refs->be->copy_ref(refs, oldref, newref, logmsg);
2342}
2343
2344int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)
2345{
Stefan Beller23a3f0c2018-04-11 17:21:09 -07002346 return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
Sahil Dua52d59cc2017-06-18 23:19:16 +02002347}