packed-backend: new module for handling packed references
Now that the interface between `files_ref_store` and `packed_ref_store` is relatively narrow, move the latter into a new module, "refs/packed-backend.h" and "refs/packed-backend.c". It still doesn't quite implement the `ref_store` interface, but it will soon. This commit moves code around and adjusts its visibility, but doesn't change anything. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Michael Haggerty committed
Jun 23, 2017 at 09:01 UTC
67be7c5a593da8905added96723448d28b4a1812
6 files changed
+685
-639
Makefile
+1
@@ -817,6 +817,7 @@ LIB_OBJS += reflog-walk.o
817
LIB_OBJS += refs.o
818
LIB_OBJS += refs/files-backend.o
819
LIB_OBJS += refs/iterator.o
820
+LIB_OBJS += refs/packed-backend.o
821
LIB_OBJS += refs/ref-cache.o
822
LIB_OBJS += ref-filter.o
823
LIB_OBJS += remote.o
refs.c
+18
@@ -173,6 +173,24 @@ int refname_is_safe(const char *refname)
173
return 1;
174
}
175
176
+/*
177
+ * Return true if refname, which has the specified oid and flags, can
178
+ * be resolved to an object in the database. If the referred-to object
179
+ * does not exist, emit a warning and return false.
180
+ */
181
+int ref_resolves_to_object(const char *refname,
182
+ const struct object_id *oid,
183
+ unsigned int flags)
184
+{
185
+ if (flags & REF_ISBROKEN)
186
+ return 0;
187
+ if (!has_sha1_file(oid->hash)) {
188
+ error("%s does not point to a valid object!", refname);
189
+ return 0;
190
+ }
191
+ return 1;
192
+}
193
+
194
char *refs_resolve_refdup(struct ref_store *refs,
195
const char *refname, int resolve_flags,
196
unsigned char *sha1, int *flags)
refs/files-backend.c
+1
-639
@@ -2,6 +2,7 @@
2
#include "../refs.h"
3
#include "refs-internal.h"
4
#include "ref-cache.h"
5
+#include "packed-backend.h"
6
#include "../iterator.h"
7
#include "../dir-iterator.h"
8
#include "../lockfile.h"
@@ -14,85 +15,6 @@ struct ref_lock {
15
struct object_id old_oid;
16
};
17
17
-/*
18
- * Return true if refname, which has the specified oid and flags, can
19
- * be resolved to an object in the database. If the referred-to object
20
- * does not exist, emit a warning and return false.
21
- */
22
-static int ref_resolves_to_object(const char *refname,
23
- const struct object_id *oid,
24
- unsigned int flags)
25
-{
26
- if (flags & REF_ISBROKEN)
27
- return 0;
28
- if (!has_sha1_file(oid->hash)) {
29
- error("%s does not point to a valid object!", refname);
30
- return 0;
31
- }
32
- return 1;
33
-}
34
-
35
-struct packed_ref_cache {
36
- struct ref_cache *cache;
37
-
38
- /*
39
- * Count of references to the data structure in this instance,
40
- * including the pointer from files_ref_store::packed if any.
41
- * The data will not be freed as long as the reference count
42
- * is nonzero.
43
- */
44
- unsigned int referrers;
45
-
46
- /* The metadata from when this packed-refs cache was read */
47
- struct stat_validity validity;
48
-};
49
-
50
-/*
51
- * A container for `packed-refs`-related data. It is not (yet) a
52
- * `ref_store`.
53
- */
54
-struct packed_ref_store {
55
- unsigned int store_flags;
56
-
57
- /* The path of the "packed-refs" file: */
58
- char *path;
59
-
60
- /*
61
- * A cache of the values read from the `packed-refs` file, if
62
- * it might still be current; otherwise, NULL.
63
- */
64
- struct packed_ref_cache *cache;
65
-
66
- /*
67
- * Lock used for the "packed-refs" file. Note that this (and
68
- * thus the enclosing `packed_ref_store`) must not be freed.
69
- */
70
- struct lock_file lock;
71
-};
72
-
73
-static struct packed_ref_store *packed_ref_store_create(
74
- const char *path, unsigned int store_flags)
75
-{
76
- struct packed_ref_store *refs = xcalloc(1, sizeof(*refs));
77
-
78
- refs->store_flags = store_flags;
79
- refs->path = xstrdup(path);
80
- return refs;
81
-}
82
-
83
-/*
84
- * Die if refs is not the main ref store. caller is used in any
85
- * necessary error messages.
86
- */
87
-static void packed_assert_main_repository(struct packed_ref_store *refs,
88
- const char *caller)
89
-{
90
- if (refs->store_flags & REF_STORE_MAIN)
91
- return;
92
-
93
- die("BUG: operation %s only allowed for main ref store", caller);
94
-}
95
-
18
/*
19
* Future: need to be in "struct repository"
20
* when doing a full libification.
@@ -109,42 +31,6 @@ struct files_ref_store {
31
struct packed_ref_store *packed_ref_store;
32
};
33
112
-/*
113
- * Increment the reference count of *packed_refs.
114
- */
115
-static void acquire_packed_ref_cache(struct packed_ref_cache *packed_refs)
116
-{
117
- packed_refs->referrers++;
118
-}
119
-
120
-/*
121
- * Decrease the reference count of *packed_refs. If it goes to zero,
122
- * free *packed_refs and return true; otherwise return false.
123
- */
124
-static int release_packed_ref_cache(struct packed_ref_cache *packed_refs)
125
-{
126
- if (!--packed_refs->referrers) {
127
- free_ref_cache(packed_refs->cache);
128
- stat_validity_clear(&packed_refs->validity);
129
- free(packed_refs);
130
- return 1;
131
- } else {
132
- return 0;
133
- }
134
-}
135
-
136
-static void clear_packed_ref_cache(struct packed_ref_store *refs)
137
-{
138
- if (refs->cache) {
139
- struct packed_ref_cache *cache = refs->cache;
140
-
141
- if (is_lock_file_locked(&refs->lock))
142
- die("BUG: packed-ref cache cleared while locked");
143
- refs->cache = NULL;
144
- release_packed_ref_cache(cache);
145
- }
146
-}
147
-
34
static void clear_loose_ref_cache(struct files_ref_store *refs)
35
{
36
if (refs->loose) {
@@ -215,151 +101,6 @@ static struct files_ref_store *files_downcast(struct ref_store *ref_store,
101
return refs;
102
}
103
218
-/* The length of a peeled reference line in packed-refs, including EOL: */
219
-#define PEELED_LINE_LENGTH 42
220
-
221
-/*
222
- * The packed-refs header line that we write out. Perhaps other
223
- * traits will be added later. The trailing space is required.
224
- */
225
-static const char PACKED_REFS_HEADER[] =
226
- "# pack-refs with: peeled fully-peeled \n";
227
-
228
-/*
229
- * Parse one line from a packed-refs file. Write the SHA1 to sha1.
230
- * Return a pointer to the refname within the line (null-terminated),
231
- * or NULL if there was a problem.
232
- */
233
-static const char *parse_ref_line(struct strbuf *line, struct object_id *oid)
234
-{
235
- const char *ref;
236
-
237
- if (parse_oid_hex(line->buf, oid, &ref) < 0)
238
- return NULL;
239
- if (!isspace(*ref++))
240
- return NULL;
241
-
242
- if (isspace(*ref))
243
- return NULL;
244
-
245
- if (line->buf[line->len - 1] != '\n')
246
- return NULL;
247
- line->buf[--line->len] = 0;
248
-
249
- return ref;
250
-}
251
-
252
-/*
253
- * Read from `packed_refs_file` into a newly-allocated
254
- * `packed_ref_cache` and return it. The return value will already
255
- * have its reference count incremented.
256
- *
257
- * A comment line of the form "# pack-refs with: " may contain zero or
258
- * more traits. We interpret the traits as follows:
259
- *
260
- * No traits:
261
- *
262
- * Probably no references are peeled. But if the file contains a
263
- * peeled value for a reference, we will use it.
264
- *
265
- * peeled:
266
- *
267
- * References under "refs/tags/", if they *can* be peeled, *are*
268
- * peeled in this file. References outside of "refs/tags/" are
269
- * probably not peeled even if they could have been, but if we find
270
- * a peeled value for such a reference we will use it.
271
- *
272
- * fully-peeled:
273
- *
274
- * All references in the file that can be peeled are peeled.
275
- * Inversely (and this is more important), any references in the
276
- * file for which no peeled value is recorded is not peelable. This
277
- * trait should typically be written alongside "peeled" for
278
- * compatibility with older clients, but we do not require it
279
- * (i.e., "peeled" is a no-op if "fully-peeled" is set).
280
- */
281
-static struct packed_ref_cache *read_packed_refs(const char *packed_refs_file)
282
-{
283
- FILE *f;
284
- struct packed_ref_cache *packed_refs = xcalloc(1, sizeof(*packed_refs));
285
- struct ref_entry *last = NULL;
286
- struct strbuf line = STRBUF_INIT;
287
- enum { PEELED_NONE, PEELED_TAGS, PEELED_FULLY } peeled = PEELED_NONE;
288
- struct ref_dir *dir;
289
-
290
- acquire_packed_ref_cache(packed_refs);
291
- packed_refs->cache = create_ref_cache(NULL, NULL);
292
- packed_refs->cache->root->flag &= ~REF_INCOMPLETE;
293
-
294
- f = fopen(packed_refs_file, "r");
295
- if (!f) {
296
- if (errno == ENOENT) {
297
- /*
298
- * This is OK; it just means that no
299
- * "packed-refs" file has been written yet,
300
- * which is equivalent to it being empty.
301
- */
302
- return packed_refs;
303
- } else {
304
- die_errno("couldn't read %s", packed_refs_file);
305
- }
306
- }
307
-
308
- stat_validity_update(&packed_refs->validity, fileno(f));
309
-
310
- dir = get_ref_dir(packed_refs->cache->root);
311
- while (strbuf_getwholeline(&line, f, '\n') != EOF) {
312
- struct object_id oid;
313
- const char *refname;
314
- const char *traits;
315
-
316
- if (skip_prefix(line.buf, "# pack-refs with:", &traits)) {
317
- if (strstr(traits, " fully-peeled "))
318
- peeled = PEELED_FULLY;
319
- else if (strstr(traits, " peeled "))
320
- peeled = PEELED_TAGS;
321
- /* perhaps other traits later as well */
322
- continue;
323
- }
324
-
325
- refname = parse_ref_line(&line, &oid);
326
- if (refname) {
327
- int flag = REF_ISPACKED;
328
-
329
- if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
330
- if (!refname_is_safe(refname))
331
- die("packed refname is dangerous: %s", refname);
332
- oidclr(&oid);
333
- flag |= REF_BAD_NAME | REF_ISBROKEN;
334
- }
335
- last = create_ref_entry(refname, &oid, flag);
336
- if (peeled == PEELED_FULLY ||
337
- (peeled == PEELED_TAGS && starts_with(refname, "refs/tags/")))
338
- last->flag |= REF_KNOWS_PEELED;
339
- add_ref_entry(dir, last);
340
- continue;
341
- }
342
- if (last &&
343
- line.buf[0] == '^' &&
344
- line.len == PEELED_LINE_LENGTH &&
345
- line.buf[PEELED_LINE_LENGTH - 1] == '\n' &&
346
- !get_oid_hex(line.buf + 1, &oid)) {
347
- oidcpy(&last->u.value.peeled, &oid);
348
- /*
349
- * Regardless of what the file header said,
350
- * we definitely know the value of *this*
351
- * reference:
352
- */
353
- last->flag |= REF_KNOWS_PEELED;
354
- }
355
- }
356
-
357
- fclose(f);
358
- strbuf_release(&line);
359
-
360
- return packed_refs;
361
-}
362
-
104
static void files_reflog_path(struct files_ref_store *refs,
105
struct strbuf *sb,
106
const char *refname)
@@ -405,77 +146,6 @@ static void files_ref_path(struct files_ref_store *refs,
146
}
147
}
148
408
-/*
409
- * Check that the packed refs cache (if any) still reflects the
410
- * contents of the file. If not, clear the cache.
411
- */
412
-static void validate_packed_ref_cache(struct packed_ref_store *refs)
413
-{
414
- if (refs->cache &&
415
- !stat_validity_check(&refs->cache->validity, refs->path))
416
- clear_packed_ref_cache(refs);
417
-}
418
-
419
-/*
420
- * Get the packed_ref_cache for the specified packed_ref_store,
421
- * creating and populating it if it hasn't been read before or if the
422
- * file has been changed (according to its `validity` field) since it
423
- * was last read. On the other hand, if we hold the lock, then assume
424
- * that the file hasn't been changed out from under us, so skip the
425
- * extra `stat()` call in `stat_validity_check()`.
426
- */
427
-static struct packed_ref_cache *get_packed_ref_cache(struct packed_ref_store *refs)
428
-{
429
- if (!is_lock_file_locked(&refs->lock))
430
- validate_packed_ref_cache(refs);
431
-
432
- if (!refs->cache)
433
- refs->cache = read_packed_refs(refs->path);
434
-
435
- return refs->cache;
436
-}
437
-
438
-static struct ref_dir *get_packed_ref_dir(struct packed_ref_cache *packed_ref_cache)
439
-{
440
- return get_ref_dir(packed_ref_cache->cache->root);
441
-}
442
-
443
-static struct ref_dir *get_packed_refs(struct packed_ref_store *refs)
444
-{
445
- return get_packed_ref_dir(get_packed_ref_cache(refs));
446
-}
447
-
448
-/*
449
- * Add or overwrite a reference in the in-memory packed reference
450
- * cache. This may only be called while the packed-refs file is locked
451
- * (see lock_packed_refs()). To actually write the packed-refs file,
452
- * call commit_packed_refs().
453
- */
454
-static void add_packed_ref(struct packed_ref_store *refs,
455
- const char *refname, const struct object_id *oid)
456
-{
457
- struct ref_dir *packed_refs;
458
- struct ref_entry *packed_entry;
459
-
460
- if (!is_lock_file_locked(&refs->lock))
461
- die("BUG: packed refs not locked");
462
-
463
- if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))
464
- die("Reference has invalid format: '%s'", refname);
465
-
466
- packed_refs = get_packed_refs(refs);
467
- packed_entry = find_ref_entry(packed_refs, refname);
468
- if (packed_entry) {
469
- /* Overwrite the existing entry: */
470
- oidcpy(&packed_entry->u.value.oid, oid);
471
- packed_entry->flag = REF_ISPACKED;
472
- oidclr(&packed_entry->u.value.peeled);
473
- } else {
474
- packed_entry = create_ref_entry(refname, oid, REF_ISPACKED);
475
- add_ref_entry(packed_refs, packed_entry);
476
- }
477
-}
478
-
149
/*
150
* Read the loose references from the namespace dirname into dir
151
* (without recursing). dirname must end with '/'. dir must be the
@@ -598,35 +268,6 @@ static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs)
268
return refs->loose;
269
}
270
601
-/*
602
- * Return the ref_entry for the given refname from the packed
603
- * references. If it does not exist, return NULL.
604
- */
605
-static struct ref_entry *get_packed_ref(struct packed_ref_store *refs,
606
- const char *refname)
607
-{
608
- return find_ref_entry(get_packed_refs(refs), refname);
609
-}
610
-
611
-static int packed_read_raw_ref(struct packed_ref_store *refs,
612
- const char *refname, unsigned char *sha1,
613
- struct strbuf *referent, unsigned int *type)
614
-{
615
- struct ref_entry *entry;
616
-
617
- *type = 0;
618
-
619
- entry = get_packed_ref(refs, refname);
620
- if (!entry) {
621
- errno = ENOENT;
622
- return -1;
623
- }
624
-
625
- hashcpy(sha1, entry->u.value.oid.hash);
626
- *type = REF_ISPACKED;
627
- return 0;
628
-}
629
-
271
static int files_read_raw_ref(struct ref_store *ref_store,
272
const char *refname, unsigned char *sha1,
273
struct strbuf *referent, unsigned int *type)
@@ -1011,18 +652,6 @@ out:
652
return ret;
653
}
654
1014
-static int packed_peel_ref(struct packed_ref_store *refs,
1015
- const char *refname, unsigned char *sha1)
1016
-{
1017
- struct ref_entry *r = get_packed_ref(refs, refname);
1018
-
1019
- if (!r || peel_entry(r, 0))
1020
- return -1;
1021
-
1022
- hashcpy(sha1, r->u.value.peeled.hash);
1023
- return 0;
1024
-}
1025
-
655
static int files_peel_ref(struct ref_store *ref_store,
656
const char *refname, unsigned char *sha1)
657
{
@@ -1060,99 +689,6 @@ static int files_peel_ref(struct ref_store *ref_store,
689
return peel_object(base, sha1);
690
}
691
1063
-struct packed_ref_iterator {
1064
- struct ref_iterator base;
1065
-
1066
- struct packed_ref_cache *cache;
1067
- struct ref_iterator *iter0;
1068
- unsigned int flags;
1069
-};
1070
-
1071
-static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
1072
-{
1073
- struct packed_ref_iterator *iter =
1074
- (struct packed_ref_iterator *)ref_iterator;
1075
- int ok;
1076
-
1077
- while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
1078
- if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
1079
- ref_type(iter->iter0->refname) != REF_TYPE_PER_WORKTREE)
1080
- continue;
1081
-
1082
- if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
1083
- !ref_resolves_to_object(iter->iter0->refname,
1084
- iter->iter0->oid,
1085
- iter->iter0->flags))
1086
- continue;
1087
-
1088
- iter->base.refname = iter->iter0->refname;
1089
- iter->base.oid = iter->iter0->oid;
1090
- iter->base.flags = iter->iter0->flags;
1091
- return ITER_OK;
1092
- }
1093
-
1094
- iter->iter0 = NULL;
1095
- if (ref_iterator_abort(ref_iterator) != ITER_DONE)
1096
- ok = ITER_ERROR;
1097
-
1098
- return ok;
1099
-}
1100
-
1101
-static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
1102
- struct object_id *peeled)
1103
-{
1104
- struct packed_ref_iterator *iter =
1105
- (struct packed_ref_iterator *)ref_iterator;
1106
-
1107
- return ref_iterator_peel(iter->iter0, peeled);
1108
-}
1109
-
1110
-static int packed_ref_iterator_abort(struct ref_iterator *ref_iterator)
1111
-{
1112
- struct packed_ref_iterator *iter =
1113
- (struct packed_ref_iterator *)ref_iterator;
1114
- int ok = ITER_DONE;
1115
-
1116
- if (iter->iter0)
1117
- ok = ref_iterator_abort(iter->iter0);
1118
-
1119
- release_packed_ref_cache(iter->cache);
1120
- base_ref_iterator_free(ref_iterator);
1121
- return ok;
1122
-}
1123
-
1124
-static struct ref_iterator_vtable packed_ref_iterator_vtable = {
1125
- packed_ref_iterator_advance,
1126
- packed_ref_iterator_peel,
1127
- packed_ref_iterator_abort
1128
-};
1129
-
1130
-static struct ref_iterator *packed_ref_iterator_begin(
1131
- struct packed_ref_store *refs,
1132
- const char *prefix, unsigned int flags)
1133
-{
1134
- struct packed_ref_iterator *iter;
1135
- struct ref_iterator *ref_iterator;
1136
-
1137
- iter = xcalloc(1, sizeof(*iter));
1138
- ref_iterator = &iter->base;
1139
- base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable);
1140
-
1141
- /*
1142
- * Note that get_packed_ref_cache() internally checks whether
1143
- * the packed-ref cache is up to date with what is on disk,
1144
- * and re-reads it if not.
1145
- */
1146
-
1147
- iter->cache = get_packed_ref_cache(refs);
1148
- acquire_packed_ref_cache(iter->cache);
1149
- iter->iter0 = cache_ref_iterator_begin(iter->cache->cache, prefix, 0);
1150
-
1151
- iter->flags = flags;
1152
-
1153
- return ref_iterator;
1154
-}
1155
-
692
struct files_ref_iterator {
693
struct ref_iterator base;
694
@@ -1434,124 +970,6 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
970
return lock;
971
}
972
1437
-/*
1438
- * Write an entry to the packed-refs file for the specified refname.
1439
- * If peeled is non-NULL, write it as the entry's peeled value.
1440
- */
1441
-static void write_packed_entry(FILE *fh, const char *refname,
1442
- const unsigned char *sha1,
1443
- const unsigned char *peeled)
1444
-{
1445
- fprintf_or_die(fh, "%s %s\n", sha1_to_hex(sha1), refname);
1446
- if (peeled)
1447
- fprintf_or_die(fh, "^%s\n", sha1_to_hex(peeled));
1448
-}
1449
-
1450
-/*
1451
- * Lock the packed-refs file for writing. Flags is passed to
1452
- * hold_lock_file_for_update(). Return 0 on success. On errors, set
1453
- * errno appropriately and return a nonzero value.
1454
- */
1455
-static int lock_packed_refs(struct packed_ref_store *refs, int flags)
1456
-{
1457
- static int timeout_configured = 0;
1458
- static int timeout_value = 1000;
1459
- struct packed_ref_cache *packed_ref_cache;
1460
-
1461
- packed_assert_main_repository(refs, "lock_packed_refs");
1462
-
1463
- if (!timeout_configured) {
1464
- git_config_get_int("core.packedrefstimeout", &timeout_value);
1465
- timeout_configured = 1;
1466
- }
1467
-
1468
- if (hold_lock_file_for_update_timeout(
1469
- &refs->lock,
1470
- refs->path,
1471
- flags, timeout_value) < 0)
1472
- return -1;
1473
-
1474
- /*
1475
- * Now that we hold the `packed-refs` lock, make sure that our
1476
- * cache matches the current version of the file. Normally
1477
- * `get_packed_ref_cache()` does that for us, but that
1478
- * function assumes that when the file is locked, any existing
1479
- * cache is still valid. We've just locked the file, but it
1480
- * might have changed the moment *before* we locked it.
1481
- */
1482
- validate_packed_ref_cache(refs);
1483
-
1484
- packed_ref_cache = get_packed_ref_cache(refs);
1485
- /* Increment the reference count to prevent it from being freed: */
1486
- acquire_packed_ref_cache(packed_ref_cache);
1487
- return 0;
1488
-}
1489
-
1490
-/*
1491
- * Write the current version of the packed refs cache from memory to
1492
- * disk. The packed-refs file must already be locked for writing (see
1493
- * lock_packed_refs()). Return zero on success. On errors, set errno
1494
- * and return a nonzero value
1495
- */
1496
-static int commit_packed_refs(struct packed_ref_store *refs)
1497
-{
1498
- struct packed_ref_cache *packed_ref_cache =
1499
- get_packed_ref_cache(refs);
1500
- int ok, error = 0;
1501
- int save_errno = 0;
1502
- FILE *out;
1503
- struct ref_iterator *iter;
1504
-
1505
- packed_assert_main_repository(refs, "commit_packed_refs");
1506
-
1507
- if (!is_lock_file_locked(&refs->lock))
1508
- die("BUG: packed-refs not locked");
1509
-
1510
- out = fdopen_lock_file(&refs->lock, "w");
1511
- if (!out)
1512
- die_errno("unable to fdopen packed-refs descriptor");
1513
-
1514
- fprintf_or_die(out, "%s", PACKED_REFS_HEADER);
1515
-
1516
- iter = cache_ref_iterator_begin(packed_ref_cache->cache, NULL, 0);
1517
- while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
1518
- struct object_id peeled;
1519
- int peel_error = ref_iterator_peel(iter, &peeled);
1520
-
1521
- write_packed_entry(out, iter->refname, iter->oid->hash,
1522
- peel_error ? NULL : peeled.hash);
1523
- }
1524
-
1525
- if (ok != ITER_DONE)
1526
- die("error while iterating over references");
1527
-
1528
- if (commit_lock_file(&refs->lock)) {
1529
- save_errno = errno;
1530
- error = -1;
1531
- }
1532
- release_packed_ref_cache(packed_ref_cache);
1533
- errno = save_errno;
1534
- return error;
1535
-}
1536
-
1537
-/*
1538
- * Rollback the lockfile for the packed-refs file, and discard the
1539
- * in-memory packed reference cache. (The packed-refs file will be
1540
- * read anew if it is needed again after this function is called.)
1541
- */
1542
-static void rollback_packed_refs(struct packed_ref_store *refs)
1543
-{
1544
- struct packed_ref_cache *packed_ref_cache = get_packed_ref_cache(refs);
1545
-
1546
- packed_assert_main_repository(refs, "rollback_packed_refs");
1547
-
1548
- if (!is_lock_file_locked(&refs->lock))
1549
- die("BUG: packed-refs not locked");
1550
- rollback_lock_file(&refs->lock);
1551
- release_packed_ref_cache(packed_ref_cache);
1552
- clear_packed_ref_cache(refs);
1553
-}
1554
-
973
struct ref_to_prune {
974
struct ref_to_prune *next;
975
unsigned char sha1[20];
@@ -1717,62 +1135,6 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
1135
return 0;
1136
}
1137
1720
-/*
1721
- * Rewrite the packed-refs file, omitting any refs listed in
1722
- * 'refnames'. On error, leave packed-refs unchanged, write an error
1723
- * message to 'err', and return a nonzero value.
1724
- *
1725
- * The refs in 'refnames' needn't be sorted. `err` must not be NULL.
1726
- */
1727
-static int repack_without_refs(struct packed_ref_store *refs,
1728
- struct string_list *refnames, struct strbuf *err)
1729
-{
1730
- struct ref_dir *packed;
1731
- struct string_list_item *refname;
1732
- int ret, needs_repacking = 0, removed = 0;
1733
-
1734
- packed_assert_main_repository(refs, "repack_without_refs");
1735
- assert(err);
1736
-
1737
- /* Look for a packed ref */
1738
- for_each_string_list_item(refname, refnames) {
1739
- if (get_packed_ref(refs, refname->string)) {
1740
- needs_repacking = 1;
1741
- break;
1742
- }
1743
- }
1744
-
1745
- /* Avoid locking if we have nothing to do */
1746
- if (!needs_repacking)
1747
- return 0; /* no refname exists in packed refs */
1748
-
1749
- if (lock_packed_refs(refs, 0)) {
1750
- unable_to_lock_message(refs->path, errno, err);
1751
- return -1;
1752
- }
1753
- packed = get_packed_refs(refs);
1754
-
1755
- /* Remove refnames from the cache */
1756
- for_each_string_list_item(refname, refnames)
1757
- if (remove_entry_from_dir(packed, refname->string) != -1)
1758
- removed = 1;
1759
- if (!removed) {
1760
- /*
1761
- * All packed entries disappeared while we were
1762
- * acquiring the lock.
1763
- */
1764
- rollback_packed_refs(refs);
1765
- return 0;
1766
- }
1767
-
1768
- /* Write what remains */
1769
- ret = commit_packed_refs(refs);
1770
- if (ret)
1771
- strbuf_addf(err, "unable to overwrite old ref-pack file: %s",
1772
- strerror(errno));
1773
- return ret;
1774
-}
1775
-
1138
static int files_delete_refs(struct ref_store *ref_store, const char *msg,
1139
struct string_list *refnames, unsigned int flags)
1140
{
refs/packed-backend.c
new
+623
@@ -0,0 +1,623 @@
1
+#include "../cache.h"
2
+#include "../refs.h"
3
+#include "refs-internal.h"
4
+#include "ref-cache.h"
5
+#include "packed-backend.h"
6
+#include "../iterator.h"
7
+#include "../lockfile.h"
8
+
9
+struct packed_ref_cache {
10
+ struct ref_cache *cache;
11
+
12
+ /*
13
+ * Count of references to the data structure in this instance,
14
+ * including the pointer from files_ref_store::packed if any.
15
+ * The data will not be freed as long as the reference count
16
+ * is nonzero.
17
+ */
18
+ unsigned int referrers;
19
+
20
+ /* The metadata from when this packed-refs cache was read */
21
+ struct stat_validity validity;
22
+};
23
+
24
+/*
25
+ * Increment the reference count of *packed_refs.
26
+ */
27
+static void acquire_packed_ref_cache(struct packed_ref_cache *packed_refs)
28
+{
29
+ packed_refs->referrers++;
30
+}
31
+
32
+/*
33
+ * Decrease the reference count of *packed_refs. If it goes to zero,
34
+ * free *packed_refs and return true; otherwise return false.
35
+ */
36
+static int release_packed_ref_cache(struct packed_ref_cache *packed_refs)
37
+{
38
+ if (!--packed_refs->referrers) {
39
+ free_ref_cache(packed_refs->cache);
40
+ stat_validity_clear(&packed_refs->validity);
41
+ free(packed_refs);
42
+ return 1;
43
+ } else {
44
+ return 0;
45
+ }
46
+}
47
+
48
+/*
49
+ * A container for `packed-refs`-related data. It is not (yet) a
50
+ * `ref_store`.
51
+ */
52
+struct packed_ref_store {
53
+ unsigned int store_flags;
54
+
55
+ /* The path of the "packed-refs" file: */
56
+ char *path;
57
+
58
+ /*
59
+ * A cache of the values read from the `packed-refs` file, if
60
+ * it might still be current; otherwise, NULL.
61
+ */
62
+ struct packed_ref_cache *cache;
63
+
64
+ /*
65
+ * Lock used for the "packed-refs" file. Note that this (and
66
+ * thus the enclosing `packed_ref_store`) must not be freed.
67
+ */
68
+ struct lock_file lock;
69
+};
70
+
71
+struct packed_ref_store *packed_ref_store_create(
72
+ const char *path, unsigned int store_flags)
73
+{
74
+ struct packed_ref_store *refs = xcalloc(1, sizeof(*refs));
75
+
76
+ refs->store_flags = store_flags;
77
+ refs->path = xstrdup(path);
78
+ return refs;
79
+}
80
+
81
+/*
82
+ * Die if refs is not the main ref store. caller is used in any
83
+ * necessary error messages.
84
+ */
85
+static void packed_assert_main_repository(struct packed_ref_store *refs,
86
+ const char *caller)
87
+{
88
+ if (refs->store_flags & REF_STORE_MAIN)
89
+ return;
90
+
91
+ die("BUG: operation %s only allowed for main ref store", caller);
92
+}
93
+
94
+static void clear_packed_ref_cache(struct packed_ref_store *refs)
95
+{
96
+ if (refs->cache) {
97
+ struct packed_ref_cache *cache = refs->cache;
98
+
99
+ if (is_lock_file_locked(&refs->lock))
100
+ die("BUG: packed-ref cache cleared while locked");
101
+ refs->cache = NULL;
102
+ release_packed_ref_cache(cache);
103
+ }
104
+}
105
+
106
+/* The length of a peeled reference line in packed-refs, including EOL: */
107
+#define PEELED_LINE_LENGTH 42
108
+
109
+/*
110
+ * Parse one line from a packed-refs file. Write the SHA1 to sha1.
111
+ * Return a pointer to the refname within the line (null-terminated),
112
+ * or NULL if there was a problem.
113
+ */
114
+static const char *parse_ref_line(struct strbuf *line, struct object_id *oid)
115
+{
116
+ const char *ref;
117
+
118
+ if (parse_oid_hex(line->buf, oid, &ref) < 0)
119
+ return NULL;
120
+ if (!isspace(*ref++))
121
+ return NULL;
122
+
123
+ if (isspace(*ref))
124
+ return NULL;
125
+
126
+ if (line->buf[line->len - 1] != '\n')
127
+ return NULL;
128
+ line->buf[--line->len] = 0;
129
+
130
+ return ref;
131
+}
132
+
133
+/*
134
+ * Read from `packed_refs_file` into a newly-allocated
135
+ * `packed_ref_cache` and return it. The return value will already
136
+ * have its reference count incremented.
137
+ *
138
+ * A comment line of the form "# pack-refs with: " may contain zero or
139
+ * more traits. We interpret the traits as follows:
140
+ *
141
+ * No traits:
142
+ *
143
+ * Probably no references are peeled. But if the file contains a
144
+ * peeled value for a reference, we will use it.
145
+ *
146
+ * peeled:
147
+ *
148
+ * References under "refs/tags/", if they *can* be peeled, *are*
149
+ * peeled in this file. References outside of "refs/tags/" are
150
+ * probably not peeled even if they could have been, but if we find
151
+ * a peeled value for such a reference we will use it.
152
+ *
153
+ * fully-peeled:
154
+ *
155
+ * All references in the file that can be peeled are peeled.
156
+ * Inversely (and this is more important), any references in the
157
+ * file for which no peeled value is recorded is not peelable. This
158
+ * trait should typically be written alongside "peeled" for
159
+ * compatibility with older clients, but we do not require it
160
+ * (i.e., "peeled" is a no-op if "fully-peeled" is set).
161
+ */
162
+static struct packed_ref_cache *read_packed_refs(const char *packed_refs_file)
163
+{
164
+ FILE *f;
165
+ struct packed_ref_cache *packed_refs = xcalloc(1, sizeof(*packed_refs));
166
+ struct ref_entry *last = NULL;
167
+ struct strbuf line = STRBUF_INIT;
168
+ enum { PEELED_NONE, PEELED_TAGS, PEELED_FULLY } peeled = PEELED_NONE;
169
+ struct ref_dir *dir;
170
+
171
+ acquire_packed_ref_cache(packed_refs);
172
+ packed_refs->cache = create_ref_cache(NULL, NULL);
173
+ packed_refs->cache->root->flag &= ~REF_INCOMPLETE;
174
+
175
+ f = fopen(packed_refs_file, "r");
176
+ if (!f) {
177
+ if (errno == ENOENT) {
178
+ /*
179
+ * This is OK; it just means that no
180
+ * "packed-refs" file has been written yet,
181
+ * which is equivalent to it being empty.
182
+ */
183
+ return packed_refs;
184
+ } else {
185
+ die_errno("couldn't read %s", packed_refs_file);
186
+ }
187
+ }
188
+
189
+ stat_validity_update(&packed_refs->validity, fileno(f));
190
+
191
+ dir = get_ref_dir(packed_refs->cache->root);
192
+ while (strbuf_getwholeline(&line, f, '\n') != EOF) {
193
+ struct object_id oid;
194
+ const char *refname;
195
+ const char *traits;
196
+
197
+ if (skip_prefix(line.buf, "# pack-refs with:", &traits)) {
198
+ if (strstr(traits, " fully-peeled "))
199
+ peeled = PEELED_FULLY;
200
+ else if (strstr(traits, " peeled "))
201
+ peeled = PEELED_TAGS;
202
+ /* perhaps other traits later as well */
203
+ continue;
204
+ }
205
+
206
+ refname = parse_ref_line(&line, &oid);
207
+ if (refname) {
208
+ int flag = REF_ISPACKED;
209
+
210
+ if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
211
+ if (!refname_is_safe(refname))
212
+ die("packed refname is dangerous: %s", refname);
213
+ oidclr(&oid);
214
+ flag |= REF_BAD_NAME | REF_ISBROKEN;
215
+ }
216
+ last = create_ref_entry(refname, &oid, flag);
217
+ if (peeled == PEELED_FULLY ||
218
+ (peeled == PEELED_TAGS && starts_with(refname, "refs/tags/")))
219
+ last->flag |= REF_KNOWS_PEELED;
220
+ add_ref_entry(dir, last);
221
+ continue;
222
+ }
223
+ if (last &&
224
+ line.buf[0] == '^' &&
225
+ line.len == PEELED_LINE_LENGTH &&
226
+ line.buf[PEELED_LINE_LENGTH - 1] == '\n' &&
227
+ !get_oid_hex(line.buf + 1, &oid)) {
228
+ oidcpy(&last->u.value.peeled, &oid);
229
+ /*
230
+ * Regardless of what the file header said,
231
+ * we definitely know the value of *this*
232
+ * reference:
233
+ */
234
+ last->flag |= REF_KNOWS_PEELED;
235
+ }
236
+ }
237
+
238
+ fclose(f);
239
+ strbuf_release(&line);
240
+
241
+ return packed_refs;
242
+}
243
+
244
+/*
245
+ * Check that the packed refs cache (if any) still reflects the
246
+ * contents of the file. If not, clear the cache.
247
+ */
248
+static void validate_packed_ref_cache(struct packed_ref_store *refs)
249
+{
250
+ if (refs->cache &&
251
+ !stat_validity_check(&refs->cache->validity, refs->path))
252
+ clear_packed_ref_cache(refs);
253
+}
254
+
255
+/*
256
+ * Get the packed_ref_cache for the specified packed_ref_store,
257
+ * creating and populating it if it hasn't been read before or if the
258
+ * file has been changed (according to its `validity` field) since it
259
+ * was last read. On the other hand, if we hold the lock, then assume
260
+ * that the file hasn't been changed out from under us, so skip the
261
+ * extra `stat()` call in `stat_validity_check()`.
262
+ */
263
+static struct packed_ref_cache *get_packed_ref_cache(struct packed_ref_store *refs)
264
+{
265
+ if (!is_lock_file_locked(&refs->lock))
266
+ validate_packed_ref_cache(refs);
267
+
268
+ if (!refs->cache)
269
+ refs->cache = read_packed_refs(refs->path);
270
+
271
+ return refs->cache;
272
+}
273
+
274
+static struct ref_dir *get_packed_ref_dir(struct packed_ref_cache *packed_ref_cache)
275
+{
276
+ return get_ref_dir(packed_ref_cache->cache->root);
277
+}
278
+
279
+static struct ref_dir *get_packed_refs(struct packed_ref_store *refs)
280
+{
281
+ return get_packed_ref_dir(get_packed_ref_cache(refs));
282
+}
283
+
284
+/*
285
+ * Add or overwrite a reference in the in-memory packed reference
286
+ * cache. This may only be called while the packed-refs file is locked
287
+ * (see lock_packed_refs()). To actually write the packed-refs file,
288
+ * call commit_packed_refs().
289
+ */
290
+void add_packed_ref(struct packed_ref_store *refs,
291
+ const char *refname, const struct object_id *oid)
292
+{
293
+ struct ref_dir *packed_refs;
294
+ struct ref_entry *packed_entry;
295
+
296
+ if (!is_lock_file_locked(&refs->lock))
297
+ die("BUG: packed refs not locked");
298
+
299
+ if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))
300
+ die("Reference has invalid format: '%s'", refname);
301
+
302
+ packed_refs = get_packed_refs(refs);
303
+ packed_entry = find_ref_entry(packed_refs, refname);
304
+ if (packed_entry) {
305
+ /* Overwrite the existing entry: */
306
+ oidcpy(&packed_entry->u.value.oid, oid);
307
+ packed_entry->flag = REF_ISPACKED;
308
+ oidclr(&packed_entry->u.value.peeled);
309
+ } else {
310
+ packed_entry = create_ref_entry(refname, oid, REF_ISPACKED);
311
+ add_ref_entry(packed_refs, packed_entry);
312
+ }
313
+}
314
+
315
+/*
316
+ * Return the ref_entry for the given refname from the packed
317
+ * references. If it does not exist, return NULL.
318
+ */
319
+static struct ref_entry *get_packed_ref(struct packed_ref_store *refs,
320
+ const char *refname)
321
+{
322
+ return find_ref_entry(get_packed_refs(refs), refname);
323
+}
324
+
325
+int packed_read_raw_ref(struct packed_ref_store *refs,
326
+ const char *refname, unsigned char *sha1,
327
+ struct strbuf *referent, unsigned int *type)
328
+{
329
+ struct ref_entry *entry;
330
+
331
+ *type = 0;
332
+
333
+ entry = get_packed_ref(refs, refname);
334
+ if (!entry) {
335
+ errno = ENOENT;
336
+ return -1;
337
+ }
338
+
339
+ hashcpy(sha1, entry->u.value.oid.hash);
340
+ *type = REF_ISPACKED;
341
+ return 0;
342
+}
343
+
344
+int packed_peel_ref(struct packed_ref_store *refs,
345
+ const char *refname, unsigned char *sha1)
346
+{
347
+ struct ref_entry *r = get_packed_ref(refs, refname);
348
+
349
+ if (!r || peel_entry(r, 0))
350
+ return -1;
351
+
352
+ hashcpy(sha1, r->u.value.peeled.hash);
353
+ return 0;
354
+}
355
+
356
+struct packed_ref_iterator {
357
+ struct ref_iterator base;
358
+
359
+ struct packed_ref_cache *cache;
360
+ struct ref_iterator *iter0;
361
+ unsigned int flags;
362
+};
363
+
364
+static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
365
+{
366
+ struct packed_ref_iterator *iter =
367
+ (struct packed_ref_iterator *)ref_iterator;
368
+ int ok;
369
+
370
+ while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
371
+ if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
372
+ ref_type(iter->iter0->refname) != REF_TYPE_PER_WORKTREE)
373
+ continue;
374
+
375
+ if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
376
+ !ref_resolves_to_object(iter->iter0->refname,
377
+ iter->iter0->oid,
378
+ iter->iter0->flags))
379
+ continue;
380
+
381
+ iter->base.refname = iter->iter0->refname;
382
+ iter->base.oid = iter->iter0->oid;
383
+ iter->base.flags = iter->iter0->flags;
384
+ return ITER_OK;
385
+ }
386
+
387
+ iter->iter0 = NULL;
388
+ if (ref_iterator_abort(ref_iterator) != ITER_DONE)
389
+ ok = ITER_ERROR;
390
+
391
+ return ok;
392
+}
393
+
394
+static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
395
+ struct object_id *peeled)
396
+{
397
+ struct packed_ref_iterator *iter =
398
+ (struct packed_ref_iterator *)ref_iterator;
399
+
400
+ return ref_iterator_peel(iter->iter0, peeled);
401
+}
402
+
403
+static int packed_ref_iterator_abort(struct ref_iterator *ref_iterator)
404
+{
405
+ struct packed_ref_iterator *iter =
406
+ (struct packed_ref_iterator *)ref_iterator;
407
+ int ok = ITER_DONE;
408
+
409
+ if (iter->iter0)
410
+ ok = ref_iterator_abort(iter->iter0);
411
+
412
+ release_packed_ref_cache(iter->cache);
413
+ base_ref_iterator_free(ref_iterator);
414
+ return ok;
415
+}
416
+
417
+static struct ref_iterator_vtable packed_ref_iterator_vtable = {
418
+ packed_ref_iterator_advance,
419
+ packed_ref_iterator_peel,
420
+ packed_ref_iterator_abort
421
+};
422
+
423
+struct ref_iterator *packed_ref_iterator_begin(
424
+ struct packed_ref_store *refs,
425
+ const char *prefix, unsigned int flags)
426
+{
427
+ struct packed_ref_iterator *iter;
428
+ struct ref_iterator *ref_iterator;
429
+
430
+ iter = xcalloc(1, sizeof(*iter));
431
+ ref_iterator = &iter->base;
432
+ base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable);
433
+
434
+ /*
435
+ * Note that get_packed_ref_cache() internally checks whether
436
+ * the packed-ref cache is up to date with what is on disk,
437
+ * and re-reads it if not.
438
+ */
439
+
440
+ iter->cache = get_packed_ref_cache(refs);
441
+ acquire_packed_ref_cache(iter->cache);
442
+ iter->iter0 = cache_ref_iterator_begin(iter->cache->cache, prefix, 0);
443
+
444
+ iter->flags = flags;
445
+
446
+ return ref_iterator;
447
+}
448
+
449
+/*
450
+ * Write an entry to the packed-refs file for the specified refname.
451
+ * If peeled is non-NULL, write it as the entry's peeled value.
452
+ */
453
+static void write_packed_entry(FILE *fh, const char *refname,
454
+ const unsigned char *sha1,
455
+ const unsigned char *peeled)
456
+{
457
+ fprintf_or_die(fh, "%s %s\n", sha1_to_hex(sha1), refname);
458
+ if (peeled)
459
+ fprintf_or_die(fh, "^%s\n", sha1_to_hex(peeled));
460
+}
461
+
462
+int lock_packed_refs(struct packed_ref_store *refs, int flags)
463
+{
464
+ static int timeout_configured = 0;
465
+ static int timeout_value = 1000;
466
+ struct packed_ref_cache *packed_ref_cache;
467
+
468
+ packed_assert_main_repository(refs, "lock_packed_refs");
469
+
470
+ if (!timeout_configured) {
471
+ git_config_get_int("core.packedrefstimeout", &timeout_value);
472
+ timeout_configured = 1;
473
+ }
474
+
475
+ if (hold_lock_file_for_update_timeout(
476
+ &refs->lock,
477
+ refs->path,
478
+ flags, timeout_value) < 0)
479
+ return -1;
480
+
481
+ /*
482
+ * Now that we hold the `packed-refs` lock, make sure that our
483
+ * cache matches the current version of the file. Normally
484
+ * `get_packed_ref_cache()` does that for us, but that
485
+ * function assumes that when the file is locked, any existing
486
+ * cache is still valid. We've just locked the file, but it
487
+ * might have changed the moment *before* we locked it.
488
+ */
489
+ validate_packed_ref_cache(refs);
490
+
491
+ packed_ref_cache = get_packed_ref_cache(refs);
492
+ /* Increment the reference count to prevent it from being freed: */
493
+ acquire_packed_ref_cache(packed_ref_cache);
494
+ return 0;
495
+}
496
+
497
+/*
498
+ * The packed-refs header line that we write out. Perhaps other
499
+ * traits will be added later. The trailing space is required.
500
+ */
501
+static const char PACKED_REFS_HEADER[] =
502
+ "# pack-refs with: peeled fully-peeled \n";
503
+
504
+/*
505
+ * Write the current version of the packed refs cache from memory to
506
+ * disk. The packed-refs file must already be locked for writing (see
507
+ * lock_packed_refs()). Return zero on success. On errors, set errno
508
+ * and return a nonzero value.
509
+ */
510
+int commit_packed_refs(struct packed_ref_store *refs)
511
+{
512
+ struct packed_ref_cache *packed_ref_cache =
513
+ get_packed_ref_cache(refs);
514
+ int ok, error = 0;
515
+ int save_errno = 0;
516
+ FILE *out;
517
+ struct ref_iterator *iter;
518
+
519
+ packed_assert_main_repository(refs, "commit_packed_refs");
520
+
521
+ if (!is_lock_file_locked(&refs->lock))
522
+ die("BUG: packed-refs not locked");
523
+
524
+ out = fdopen_lock_file(&refs->lock, "w");
525
+ if (!out)
526
+ die_errno("unable to fdopen packed-refs descriptor");
527
+
528
+ fprintf_or_die(out, "%s", PACKED_REFS_HEADER);
529
+
530
+ iter = cache_ref_iterator_begin(packed_ref_cache->cache, NULL, 0);
531
+ while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
532
+ struct object_id peeled;
533
+ int peel_error = ref_iterator_peel(iter, &peeled);
534
+
535
+ write_packed_entry(out, iter->refname, iter->oid->hash,
536
+ peel_error ? NULL : peeled.hash);
537
+ }
538
+
539
+ if (ok != ITER_DONE)
540
+ die("error while iterating over references");
541
+
542
+ if (commit_lock_file(&refs->lock)) {
543
+ save_errno = errno;
544
+ error = -1;
545
+ }
546
+ release_packed_ref_cache(packed_ref_cache);
547
+ errno = save_errno;
548
+ return error;
549
+}
550
+
551
+/*
552
+ * Rollback the lockfile for the packed-refs file, and discard the
553
+ * in-memory packed reference cache. (The packed-refs file will be
554
+ * read anew if it is needed again after this function is called.)
555
+ */
556
+static void rollback_packed_refs(struct packed_ref_store *refs)
557
+{
558
+ struct packed_ref_cache *packed_ref_cache = get_packed_ref_cache(refs);
559
+
560
+ packed_assert_main_repository(refs, "rollback_packed_refs");
561
+
562
+ if (!is_lock_file_locked(&refs->lock))
563
+ die("BUG: packed-refs not locked");
564
+ rollback_lock_file(&refs->lock);
565
+ release_packed_ref_cache(packed_ref_cache);
566
+ clear_packed_ref_cache(refs);
567
+}
568
+
569
+/*
570
+ * Rewrite the packed-refs file, omitting any refs listed in
571
+ * 'refnames'. On error, leave packed-refs unchanged, write an error
572
+ * message to 'err', and return a nonzero value.
573
+ *
574
+ * The refs in 'refnames' needn't be sorted. `err` must not be NULL.
575
+ */
576
+int repack_without_refs(struct packed_ref_store *refs,
577
+ struct string_list *refnames, struct strbuf *err)
578
+{
579
+ struct ref_dir *packed;
580
+ struct string_list_item *refname;
581
+ int ret, needs_repacking = 0, removed = 0;
582
+
583
+ packed_assert_main_repository(refs, "repack_without_refs");
584
+ assert(err);
585
+
586
+ /* Look for a packed ref */
587
+ for_each_string_list_item(refname, refnames) {
588
+ if (get_packed_ref(refs, refname->string)) {
589
+ needs_repacking = 1;
590
+ break;
591
+ }
592
+ }
593
+
594
+ /* Avoid locking if we have nothing to do */
595
+ if (!needs_repacking)
596
+ return 0; /* no refname exists in packed refs */
597
+
598
+ if (lock_packed_refs(refs, 0)) {
599
+ unable_to_lock_message(refs->path, errno, err);
600
+ return -1;
601
+ }
602
+ packed = get_packed_refs(refs);
603
+
604
+ /* Remove refnames from the cache */
605
+ for_each_string_list_item(refname, refnames)
606
+ if (remove_entry_from_dir(packed, refname->string) != -1)
607
+ removed = 1;
608
+ if (!removed) {
609
+ /*
610
+ * All packed entries disappeared while we were
611
+ * acquiring the lock.
612
+ */
613
+ rollback_packed_refs(refs);
614
+ return 0;
615
+ }
616
+
617
+ /* Write what remains */
618
+ ret = commit_packed_refs(refs);
619
+ if (ret)
620
+ strbuf_addf(err, "unable to overwrite old ref-pack file: %s",
621
+ strerror(errno));
622
+ return ret;
623
+}
refs/packed-backend.h
new
+33
@@ -0,0 +1,33 @@
1
+#ifndef REFS_PACKED_BACKEND_H
2
+#define REFS_PACKED_BACKEND_H
3
+
4
+struct packed_ref_store *packed_ref_store_create(
5
+ const char *path, unsigned int store_flags);
6
+
7
+int packed_read_raw_ref(struct packed_ref_store *refs,
8
+ const char *refname, unsigned char *sha1,
9
+ struct strbuf *referent, unsigned int *type);
10
+
11
+int packed_peel_ref(struct packed_ref_store *refs,
12
+ const char *refname, unsigned char *sha1);
13
+
14
+struct ref_iterator *packed_ref_iterator_begin(
15
+ struct packed_ref_store *refs,
16
+ const char *prefix, unsigned int flags);
17
+
18
+/*
19
+ * Lock the packed-refs file for writing. Flags is passed to
20
+ * hold_lock_file_for_update(). Return 0 on success. On errors, set
21
+ * errno appropriately and return a nonzero value.
22
+ */
23
+int lock_packed_refs(struct packed_ref_store *refs, int flags);
24
+
25
+void add_packed_ref(struct packed_ref_store *refs,
26
+ const char *refname, const struct object_id *oid);
27
+
28
+int commit_packed_refs(struct packed_ref_store *refs);
29
+
30
+int repack_without_refs(struct packed_ref_store *refs,
31
+ struct string_list *refnames, struct strbuf *err);
32
+
33
+#endif /* REFS_PACKED_BACKEND_H */
refs/refs-internal.h
+9
@@ -77,6 +77,15 @@
77
*/
78
int refname_is_safe(const char *refname);
79
80
+/*
81
+ * Helper function: return true if refname, which has the specified
82
+ * oid and flags, can be resolved to an object in the database. If the
83
+ * referred-to object does not exist, emit a warning and return false.
84
+ */
85
+int ref_resolves_to_object(const char *refname,
86
+ const struct object_id *oid,
87
+ unsigned int flags);
88
+
89
enum peel_status {
90
/* object was peeled successfully: */
91
PEEL_PEELED = 0,