aboutsummaryrefslogtreecommitdiffstats
path: root/refs
diff options
context:
space:
mode:
Diffstat (limited to 'refs')
-rw-r--r--refs/debug.c40
-rw-r--r--refs/files-backend.c156
-rw-r--r--refs/iterator.c73
-rw-r--r--refs/packed-backend.c77
-rw-r--r--refs/ref-cache.c20
-rw-r--r--refs/refs-internal.h31
-rw-r--r--refs/reftable-backend.c170
7 files changed, 266 insertions, 301 deletions
diff --git a/refs/debug.c b/refs/debug.c
index da300efaf3..54f409c249 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -1,7 +1,6 @@
#include "git-compat-util.h"
#include "hex.h"
#include "refs-internal.h"
-#include "string-list.h"
#include "trace.h"
static struct trace_key trace_refs = TRACE_KEY_INIT(REFS);
@@ -48,6 +47,14 @@ static int debug_create_on_disk(struct ref_store *refs, int flags, struct strbuf
return res;
}
+static int debug_remove_on_disk(struct ref_store *refs, struct strbuf *err)
+{
+ struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
+ int res = drefs->refs->be->remove_on_disk(drefs->refs, err);
+ trace_printf_key(&trace_refs, "remove_on_disk: %d\n", res);
+ return res;
+}
+
static int debug_transaction_prepare(struct ref_store *refs,
struct ref_transaction *transaction,
struct strbuf *err)
@@ -117,11 +124,11 @@ static int debug_transaction_abort(struct ref_store *refs,
return res;
}
-static int debug_pack_refs(struct ref_store *ref_store, struct pack_refs_opts *opts)
+static int debug_optimize(struct ref_store *ref_store, struct refs_optimize_opts *opts)
{
struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
- int res = drefs->refs->be->pack_refs(drefs->refs, opts);
- trace_printf_key(&trace_refs, "pack_refs: %d\n", res);
+ int res = drefs->refs->be->optimize(drefs->refs, opts);
+ trace_printf_key(&trace_refs, "optimize: %d\n", res);
return res;
}
@@ -161,11 +168,9 @@ static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator)
trace_printf_key(&trace_refs, "iterator_advance: (%d)\n", res);
else
trace_printf_key(&trace_refs, "iterator_advance: %s (0)\n",
- diter->iter->refname);
+ diter->iter->ref.name);
- diter->base.refname = diter->iter->refname;
- diter->base.oid = diter->iter->oid;
- diter->base.flags = diter->iter->flags;
+ diter->base.ref = diter->iter->ref;
return res;
}
@@ -180,16 +185,6 @@ static int debug_ref_iterator_seek(struct ref_iterator *ref_iterator,
return res;
}
-static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct debug_ref_iterator *diter =
- (struct debug_ref_iterator *)ref_iterator;
- int res = diter->iter->vtable->peel(diter->iter, peeled);
- trace_printf_key(&trace_refs, "iterator_peel: %s: %d\n", diter->iter->refname, res);
- return res;
-}
-
static void debug_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct debug_ref_iterator *diter =
@@ -201,7 +196,6 @@ static void debug_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable debug_ref_iterator_vtable = {
.advance = debug_ref_iterator_advance,
.seek = debug_ref_iterator_seek,
- .peel = debug_ref_iterator_peel,
.release = debug_ref_iterator_release,
};
@@ -277,7 +271,8 @@ struct debug_reflog {
void *cb_data;
};
-static int debug_print_reflog_ent(struct object_id *old_oid,
+static int debug_print_reflog_ent(const char *refname,
+ struct object_id *old_oid,
struct object_id *new_oid,
const char *committer, timestamp_t timestamp,
int tz, const char *msg, void *cb_data)
@@ -292,7 +287,7 @@ static int debug_print_reflog_ent(struct object_id *old_oid,
if (new_oid)
oid_to_hex_r(n, new_oid);
- ret = dbg->fn(old_oid, new_oid, committer, timestamp, tz, msg,
+ ret = dbg->fn(refname, old_oid, new_oid, committer, timestamp, tz, msg,
dbg->cb_data);
trace_printf_key(&trace_refs,
"reflog_ent %s (ret %d): %s -> %s, %s %ld \"%.*s\"\n",
@@ -432,6 +427,7 @@ struct ref_storage_be refs_be_debug = {
.init = NULL,
.release = debug_release,
.create_on_disk = debug_create_on_disk,
+ .remove_on_disk = debug_remove_on_disk,
/*
* None of these should be NULL. If the "files" backend (in
@@ -443,7 +439,7 @@ struct ref_storage_be refs_be_debug = {
.transaction_finish = debug_transaction_finish,
.transaction_abort = debug_transaction_abort,
- .pack_refs = debug_pack_refs,
+ .optimize = debug_optimize,
.rename_ref = debug_rename_ref,
.copy_ref = debug_copy_ref,
diff --git a/refs/files-backend.c b/refs/files-backend.c
index b2de84fa69..a1e70b1c10 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -20,7 +20,6 @@
#include "../dir-iterator.h"
#include "../lockfile.h"
#include "../object.h"
-#include "../object-file.h"
#include "../path.h"
#include "../dir.h"
#include "../chdir-notify.h"
@@ -962,26 +961,23 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
- parse_worktree_ref(iter->iter0->refname, NULL, NULL,
+ parse_worktree_ref(iter->iter0->ref.name, NULL, NULL,
NULL) != REF_WORKTREE_CURRENT)
continue;
if ((iter->flags & DO_FOR_EACH_OMIT_DANGLING_SYMREFS) &&
- (iter->iter0->flags & REF_ISSYMREF) &&
- (iter->iter0->flags & REF_ISBROKEN))
+ (iter->iter0->ref.flags & REF_ISSYMREF) &&
+ (iter->iter0->ref.flags & REF_ISBROKEN))
continue;
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
- !ref_resolves_to_object(iter->iter0->refname,
+ !ref_resolves_to_object(iter->iter0->ref.name,
iter->repo,
- iter->iter0->oid,
- iter->iter0->flags))
+ iter->iter0->ref.oid,
+ iter->iter0->ref.flags))
continue;
- iter->base.refname = iter->iter0->refname;
- iter->base.oid = iter->iter0->oid;
- iter->base.flags = iter->iter0->flags;
- iter->base.referent = iter->iter0->referent;
+ iter->base.ref = iter->iter0->ref;
return ITER_OK;
}
@@ -997,15 +993,6 @@ static int files_ref_iterator_seek(struct ref_iterator *ref_iterator,
return ref_iterator_seek(iter->iter0, refname, flags);
}
-static int files_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct files_ref_iterator *iter =
- (struct files_ref_iterator *)ref_iterator;
-
- return ref_iterator_peel(iter->iter0, peeled);
-}
-
static void files_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct files_ref_iterator *iter =
@@ -1016,7 +1003,6 @@ static void files_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable files_ref_iterator_vtable = {
.advance = files_ref_iterator_advance,
.seek = files_ref_iterator_seek,
- .peel = files_ref_iterator_peel,
.release = files_ref_iterator_release,
};
@@ -1368,37 +1354,36 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune **refs_
* Return true if the specified reference should be packed.
*/
static int should_pack_ref(struct files_ref_store *refs,
- const char *refname,
- const struct object_id *oid, unsigned int ref_flags,
- struct pack_refs_opts *opts)
+ const struct reference *ref,
+ struct refs_optimize_opts *opts)
{
struct string_list_item *item;
/* Do not pack per-worktree refs: */
- if (parse_worktree_ref(refname, NULL, NULL, NULL) !=
+ if (parse_worktree_ref(ref->name, NULL, NULL, NULL) !=
REF_WORKTREE_SHARED)
return 0;
/* Do not pack symbolic refs: */
- if (ref_flags & REF_ISSYMREF)
+ if (ref->flags & REF_ISSYMREF)
return 0;
/* Do not pack broken refs: */
- if (!ref_resolves_to_object(refname, refs->base.repo, oid, ref_flags))
+ if (!ref_resolves_to_object(ref->name, refs->base.repo, ref->oid, ref->flags))
return 0;
- if (ref_excluded(opts->exclusions, refname))
+ if (ref_excluded(opts->exclusions, ref->name))
return 0;
for_each_string_list_item(item, opts->includes)
- if (!wildmatch(item->string, refname, 0))
+ if (!wildmatch(item->string, ref->name, 0))
return 1;
return 0;
}
static int should_pack_refs(struct files_ref_store *refs,
- struct pack_refs_opts *opts)
+ struct refs_optimize_opts *opts)
{
struct ref_iterator *iter;
size_t packed_size;
@@ -1406,7 +1391,7 @@ static int should_pack_refs(struct files_ref_store *refs,
size_t limit;
int ret;
- if (!(opts->flags & PACK_REFS_AUTO))
+ if (!(opts->flags & REFS_OPTIMIZE_AUTO))
return 1;
ret = packed_refs_size(refs->packed_ref_store, &packed_size);
@@ -1444,8 +1429,7 @@ static int should_pack_refs(struct files_ref_store *refs,
iter = cache_ref_iterator_begin(get_loose_ref_cache(refs, 0), NULL,
refs->base.repo, 0);
while ((ret = ref_iterator_advance(iter)) == ITER_OK) {
- if (should_pack_ref(refs, iter->refname, iter->oid,
- iter->flags, opts))
+ if (should_pack_ref(refs, &iter->ref, opts))
refcount++;
if (refcount >= limit) {
ref_iterator_free(iter);
@@ -1460,8 +1444,8 @@ static int should_pack_refs(struct files_ref_store *refs,
return 0;
}
-static int files_pack_refs(struct ref_store *ref_store,
- struct pack_refs_opts *opts)
+static int files_optimize(struct ref_store *ref_store,
+ struct refs_optimize_opts *opts)
{
struct files_ref_store *refs =
files_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB,
@@ -1490,24 +1474,24 @@ static int files_pack_refs(struct ref_store *ref_store,
* in the packed ref cache. If the reference should be
* pruned, also add it to refs_to_prune.
*/
- if (!should_pack_ref(refs, iter->refname, iter->oid, iter->flags, opts))
+ if (!should_pack_ref(refs, &iter->ref, opts))
continue;
/*
* Add a reference creation for this reference to the
* packed-refs transaction:
*/
- if (ref_transaction_update(transaction, iter->refname,
- iter->oid, NULL, NULL, NULL,
+ if (ref_transaction_update(transaction, iter->ref.name,
+ iter->ref.oid, NULL, NULL, NULL,
REF_NO_DEREF, NULL, &err))
die("failure preparing to create packed reference %s: %s",
- iter->refname, err.buf);
+ iter->ref.name, err.buf);
/* Schedule the loose reference for pruning if requested. */
- if ((opts->flags & PACK_REFS_PRUNE)) {
+ if ((opts->flags & REFS_OPTIMIZE_PRUNE)) {
struct ref_to_prune *n;
- FLEX_ALLOC_STR(n, name, iter->refname);
- oidcpy(&n->oid, iter->oid);
+ FLEX_ALLOC_STR(n, name, iter->ref.name);
+ oidcpy(&n->oid, iter->ref.oid);
n->next = refs_to_prune;
refs_to_prune = n;
}
@@ -2105,20 +2089,35 @@ static int commit_ref_update(struct files_ref_store *refs,
return 0;
}
-#ifdef NO_SYMLINK_HEAD
+#if defined(NO_SYMLINK_HEAD) || defined(WITH_BREAKING_CHANGES)
#define create_ref_symlink(a, b) (-1)
#else
static int create_ref_symlink(struct ref_lock *lock, const char *target)
{
+ static int warn_once = 1;
+ char *ref_path;
int ret = -1;
- char *ref_path = get_locked_file_path(&lock->lk);
+ ref_path = get_locked_file_path(&lock->lk);
unlink(ref_path);
ret = symlink(target, ref_path);
free(ref_path);
if (ret)
fprintf(stderr, "no symlink - falling back to symbolic ref\n");
+
+ if (warn_once)
+ warning(_("'core.preferSymlinkRefs=true' is nominated for removal.\n"
+ "hint: The use of symbolic links for symbolic refs is deprecated\n"
+ "hint: and will be removed in Git 3.0. The configuration that\n"
+ "hint: tells Git to use them is thus going away. You can unset\n"
+ "hint: it with:\n"
+ "hint:\n"
+ "hint:\tgit config unset core.preferSymlinkRefs\n"
+ "hint:\n"
+ "hint: Git will then use the textual symref format instead."));
+ warn_once = 0;
+
return ret;
}
#endif
@@ -2170,7 +2169,9 @@ static int files_delete_reflog(struct ref_store *ref_store,
return ret;
}
-static int show_one_reflog_ent(struct files_ref_store *refs, struct strbuf *sb,
+static int show_one_reflog_ent(struct files_ref_store *refs,
+ const char *refname,
+ struct strbuf *sb,
each_reflog_ent_fn fn, void *cb_data)
{
struct object_id ooid, noid;
@@ -2197,7 +2198,7 @@ static int show_one_reflog_ent(struct files_ref_store *refs, struct strbuf *sb,
message += 6;
else
message += 7;
- return fn(&ooid, &noid, p, timestamp, tz, message, cb_data);
+ return fn(refname, &ooid, &noid, p, timestamp, tz, message, cb_data);
}
static char *find_beginning_of_line(char *bob, char *scan)
@@ -2281,7 +2282,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,
strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1));
scanp = bp;
endp = bp + 1;
- ret = show_one_reflog_ent(refs, &sb, fn, cb_data);
+ ret = show_one_reflog_ent(refs, refname, &sb, fn, cb_data);
strbuf_reset(&sb);
if (ret)
break;
@@ -2293,7 +2294,7 @@ static int files_for_each_reflog_ent_reverse(struct ref_store *ref_store,
* Process it, and we can end the loop.
*/
strbuf_splice(&sb, 0, 0, buf, endp - buf);
- ret = show_one_reflog_ent(refs, &sb, fn, cb_data);
+ ret = show_one_reflog_ent(refs, refname, &sb, fn, cb_data);
strbuf_reset(&sb);
break;
}
@@ -2343,7 +2344,7 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store,
return -1;
while (!ret && !strbuf_getwholeline(&sb, logfp, '\n'))
- ret = show_one_reflog_ent(refs, &sb, fn, cb_data);
+ ret = show_one_reflog_ent(refs, refname, &sb, fn, cb_data);
fclose(logfp);
strbuf_release(&sb);
return ret;
@@ -2369,7 +2370,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
REFNAME_ALLOW_ONELEVEL))
continue;
- iter->base.refname = diter->relative_path;
+ iter->base.ref.name = diter->relative_path;
return ITER_OK;
}
@@ -2383,12 +2384,6 @@ static int files_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
BUG("ref_iterator_seek() called for reflog_iterator");
}
-static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
- struct object_id *peeled UNUSED)
-{
- BUG("ref_iterator_peel() called for reflog_iterator");
-}
-
static void files_reflog_iterator_release(struct ref_iterator *ref_iterator)
{
struct files_reflog_iterator *iter =
@@ -2399,7 +2394,6 @@ static void files_reflog_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable files_reflog_iterator_vtable = {
.advance = files_reflog_iterator_advance,
.seek = files_reflog_iterator_seek,
- .peel = files_reflog_iterator_peel,
.release = files_reflog_iterator_release,
};
@@ -2568,13 +2562,37 @@ static enum ref_transaction_error split_symref_update(struct ref_update *update,
*/
static enum ref_transaction_error check_old_oid(struct ref_update *update,
struct object_id *oid,
+ struct strbuf *referent,
struct strbuf *err)
{
if (update->flags & REF_LOG_ONLY ||
- !(update->flags & REF_HAVE_OLD) ||
- oideq(oid, &update->old_oid))
+ !(update->flags & REF_HAVE_OLD))
return 0;
+ if (oideq(oid, &update->old_oid)) {
+ /*
+ * Normally matching the expected old oid is enough. Either we
+ * found the ref at the expected state, or we are creating and
+ * expect the null oid (and likewise found nothing).
+ *
+ * But there is one exception for the null oid: if we found a
+ * symref pointing to nothing we'll also get the null oid. In
+ * regular recursive mode, that's good (we'll write to what the
+ * symref points to, which doesn't exist). But in no-deref
+ * mode, it means we'll clobber the symref, even though the
+ * caller asked for this to be a creation event. So flag
+ * that case to preserve the dangling symref.
+ */
+ if ((update->flags & REF_NO_DEREF) && referent->len &&
+ is_null_oid(oid)) {
+ strbuf_addf(err, "cannot lock ref '%s': "
+ "dangling symref already exists",
+ ref_update_original_update_refname(update));
+ return REF_TRANSACTION_ERROR_CREATE_EXISTS;
+ }
+ return 0;
+ }
+
if (is_null_oid(&update->old_oid)) {
strbuf_addf(err, "cannot lock ref '%s': "
"reference already exists",
@@ -2713,7 +2731,8 @@ static enum ref_transaction_error lock_ref_for_update(struct files_ref_store *re
if (update->old_target)
ret = ref_update_check_old_target(referent.buf, update, err);
else
- ret = check_old_oid(update, &lock->old_oid, err);
+ ret = check_old_oid(update, &lock->old_oid,
+ &referent, err);
if (ret)
goto out;
} else {
@@ -2745,7 +2764,8 @@ static enum ref_transaction_error lock_ref_for_update(struct files_ref_store *re
ret = REF_TRANSACTION_ERROR_EXPECTED_SYMREF;
goto out;
} else {
- ret = check_old_oid(update, &lock->old_oid, err);
+ ret = check_old_oid(update, &lock->old_oid,
+ &referent, err);
if (ret) {
goto out;
}
@@ -3114,14 +3134,11 @@ static int parse_and_write_reflog(struct files_ref_store *refs,
return 0;
}
-static int ref_present(const char *refname, const char *referent UNUSED,
- const struct object_id *oid UNUSED,
- int flags UNUSED,
- void *cb_data)
+static int ref_present(const struct reference *ref, void *cb_data)
{
struct string_list *affected_refnames = cb_data;
- return string_list_has_string(affected_refnames, refname);
+ return string_list_has_string(affected_refnames, ref->name);
}
static int files_transaction_finish_initial(struct files_ref_store *refs,
@@ -3420,7 +3437,8 @@ struct expire_reflog_cb {
dry_run:1;
};
-static int expire_reflog_ent(struct object_id *ooid, struct object_id *noid,
+static int expire_reflog_ent(const char *refname UNUSED,
+ struct object_id *ooid, struct object_id *noid,
const char *email, timestamp_t timestamp, int tz,
const char *message, void *cb_data)
{
@@ -3938,8 +3956,6 @@ static int files_fsck_refs(struct ref_store *ref_store,
NULL,
};
- if (o->verbose)
- fprintf_ln(stderr, _("Checking references consistency"));
return files_fsck_refs_dir(ref_store, o, "refs", wt, fsck_refs_fn);
}
@@ -3965,7 +3981,7 @@ struct ref_storage_be refs_be_files = {
.transaction_finish = files_transaction_finish,
.transaction_abort = files_transaction_abort,
- .pack_refs = files_pack_refs,
+ .optimize = files_optimize,
.rename_ref = files_rename_ref,
.copy_ref = files_copy_ref,
diff --git a/refs/iterator.c b/refs/iterator.c
index 17ef841d8a..d79aa5ec82 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -21,12 +21,6 @@ int ref_iterator_seek(struct ref_iterator *ref_iterator, const char *refname,
return ref_iterator->vtable->seek(ref_iterator, refname, flags);
}
-int ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- return ref_iterator->vtable->peel(ref_iterator, peeled);
-}
-
void ref_iterator_free(struct ref_iterator *ref_iterator)
{
if (ref_iterator) {
@@ -41,10 +35,7 @@ void base_ref_iterator_init(struct ref_iterator *iter,
struct ref_iterator_vtable *vtable)
{
iter->vtable = vtable;
- iter->refname = NULL;
- iter->referent = NULL;
- iter->oid = NULL;
- iter->flags = 0;
+ memset(&iter->ref, 0, sizeof(iter->ref));
}
struct empty_ref_iterator {
@@ -63,12 +54,6 @@ static int empty_ref_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
return 0;
}
-static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
- struct object_id *peeled UNUSED)
-{
- BUG("peel called for empty iterator");
-}
-
static void empty_ref_iterator_release(struct ref_iterator *ref_iterator UNUSED)
{
}
@@ -76,7 +61,6 @@ static void empty_ref_iterator_release(struct ref_iterator *ref_iterator UNUSED)
static struct ref_iterator_vtable empty_ref_iterator_vtable = {
.advance = empty_ref_iterator_advance,
.seek = empty_ref_iterator_seek,
- .peel = empty_ref_iterator_peel,
.release = empty_ref_iterator_release,
};
@@ -127,8 +111,8 @@ enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree,
* latter.
*/
if (iter_worktree) {
- int cmp = strcmp(iter_worktree->refname,
- iter_common->refname);
+ int cmp = strcmp(iter_worktree->ref.name,
+ iter_common->ref.name);
if (cmp < 0)
return ITER_SELECT_0;
else if (!cmp)
@@ -139,7 +123,7 @@ enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree,
* We now know that the lexicographically-next ref is a common
* ref. When the common ref is a shared one we return it.
*/
- if (parse_worktree_ref(iter_common->refname, NULL, NULL,
+ if (parse_worktree_ref(iter_common->ref.name, NULL, NULL,
NULL) == REF_WORKTREE_SHARED)
return ITER_SELECT_1;
@@ -212,10 +196,7 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
}
if (selection & ITER_YIELD_CURRENT) {
- iter->base.referent = (*iter->current)->referent;
- iter->base.refname = (*iter->current)->refname;
- iter->base.oid = (*iter->current)->oid;
- iter->base.flags = (*iter->current)->flags;
+ iter->base.ref = (*iter->current)->ref;
return ITER_OK;
}
}
@@ -246,18 +227,6 @@ static int merge_ref_iterator_seek(struct ref_iterator *ref_iterator,
return 0;
}
-static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct merge_ref_iterator *iter =
- (struct merge_ref_iterator *)ref_iterator;
-
- if (!iter->current) {
- BUG("peel called before advance for merge iterator");
- }
- return ref_iterator_peel(*iter->current, peeled);
-}
-
static void merge_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct merge_ref_iterator *iter =
@@ -269,7 +238,6 @@ static void merge_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable merge_ref_iterator_vtable = {
.advance = merge_ref_iterator_advance,
.seek = merge_ref_iterator_seek,
- .peel = merge_ref_iterator_peel,
.release = merge_ref_iterator_release,
};
@@ -313,7 +281,7 @@ static enum iterator_selection overlay_iterator_select(
else if (!front)
return ITER_SELECT_1;
- cmp = strcmp(front->refname, back->refname);
+ cmp = strcmp(front->ref.name, back->ref.name);
if (cmp < 0)
return ITER_SELECT_0;
@@ -371,7 +339,7 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
int ok;
while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
- int cmp = compare_prefix(iter->iter0->refname, iter->prefix);
+ int cmp = compare_prefix(iter->iter0->ref.name, iter->prefix);
if (cmp < 0)
continue;
/*
@@ -382,6 +350,8 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
if (cmp > 0)
return ITER_DONE;
+ iter->base.ref = iter->iter0->ref;
+
if (iter->trim) {
/*
* It is nonsense to trim off characters that
@@ -392,15 +362,11 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
* one character left in the refname after
* trimming, report it as a bug:
*/
- if (strlen(iter->iter0->refname) <= iter->trim)
+ if (strlen(iter->base.ref.name) <= iter->trim)
BUG("attempt to trim too many characters");
- iter->base.refname = iter->iter0->refname + iter->trim;
- } else {
- iter->base.refname = iter->iter0->refname;
+ iter->base.ref.name += iter->trim;
}
- iter->base.oid = iter->iter0->oid;
- iter->base.flags = iter->iter0->flags;
return ITER_OK;
}
@@ -420,15 +386,6 @@ static int prefix_ref_iterator_seek(struct ref_iterator *ref_iterator,
return ref_iterator_seek(iter->iter0, refname, flags);
}
-static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct prefix_ref_iterator *iter =
- (struct prefix_ref_iterator *)ref_iterator;
-
- return ref_iterator_peel(iter->iter0, peeled);
-}
-
static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct prefix_ref_iterator *iter =
@@ -440,7 +397,6 @@ static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable prefix_ref_iterator_vtable = {
.advance = prefix_ref_iterator_advance,
.seek = prefix_ref_iterator_seek,
- .peel = prefix_ref_iterator_peel,
.release = prefix_ref_iterator_release,
};
@@ -466,23 +422,18 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
return ref_iterator;
}
-struct ref_iterator *current_ref_iter = NULL;
-
int do_for_each_ref_iterator(struct ref_iterator *iter,
each_ref_fn fn, void *cb_data)
{
int retval = 0, ok;
- struct ref_iterator *old_ref_iter = current_ref_iter;
- current_ref_iter = iter;
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
- retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data);
+ retval = fn(&iter->ref, cb_data);
if (retval)
goto out;
}
out:
- current_ref_iter = old_ref_iter;
if (ok == ITER_ERROR)
retval = -1;
ref_iterator_free(iter);
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index a8c22a0a7f..10062fd8b6 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -882,6 +882,7 @@ static int next_record(struct packed_ref_iterator *iter)
{
const char *p, *eol;
+ memset(&iter->base.ref, 0, sizeof(iter->base.ref));
strbuf_reset(&iter->refname_buf);
/*
@@ -908,7 +909,7 @@ static int next_record(struct packed_ref_iterator *iter)
if (iter->pos == iter->eof)
return ITER_DONE;
- iter->base.flags = REF_ISPACKED;
+ iter->base.ref.flags = REF_ISPACKED;
p = iter->pos;
if (iter->eof - p < snapshot_hexsz(iter->snapshot) + 2 ||
@@ -916,6 +917,7 @@ static int next_record(struct packed_ref_iterator *iter)
!isspace(*p++))
die_invalid_line(iter->snapshot->refs->path,
iter->pos, iter->eof - iter->pos);
+ iter->base.ref.oid = &iter->oid;
eol = memchr(p, '\n', iter->eof - p);
if (!eol)
@@ -923,22 +925,22 @@ static int next_record(struct packed_ref_iterator *iter)
iter->pos, iter->eof - iter->pos);
strbuf_add(&iter->refname_buf, p, eol - p);
- iter->base.refname = iter->refname_buf.buf;
+ iter->base.ref.name = iter->refname_buf.buf;
if (refname_contains_nul(&iter->refname_buf))
- die("packed refname contains embedded NULL: %s", iter->base.refname);
+ die("packed refname contains embedded NULL: %s", iter->base.ref.name);
- if (check_refname_format(iter->base.refname, REFNAME_ALLOW_ONELEVEL)) {
- if (!refname_is_safe(iter->base.refname))
+ if (check_refname_format(iter->base.ref.name, REFNAME_ALLOW_ONELEVEL)) {
+ if (!refname_is_safe(iter->base.ref.name))
die("packed refname is dangerous: %s",
- iter->base.refname);
+ iter->base.ref.name);
oidclr(&iter->oid, iter->repo->hash_algo);
- iter->base.flags |= REF_BAD_NAME | REF_ISBROKEN;
+ iter->base.ref.flags |= REF_BAD_NAME | REF_ISBROKEN;
}
if (iter->snapshot->peeled == PEELED_FULLY ||
(iter->snapshot->peeled == PEELED_TAGS &&
- starts_with(iter->base.refname, "refs/tags/")))
- iter->base.flags |= REF_KNOWS_PEELED;
+ starts_with(iter->base.ref.name, "refs/tags/")))
+ iter->base.ref.flags |= REF_KNOWS_PEELED;
iter->pos = eol + 1;
@@ -956,11 +958,12 @@ static int next_record(struct packed_ref_iterator *iter)
* definitely know the value of *this* reference. But
* we suppress it if the reference is broken:
*/
- if ((iter->base.flags & REF_ISBROKEN)) {
+ if ((iter->base.ref.flags & REF_ISBROKEN)) {
oidclr(&iter->peeled, iter->repo->hash_algo);
- iter->base.flags &= ~REF_KNOWS_PEELED;
+ iter->base.ref.flags &= ~REF_KNOWS_PEELED;
} else {
- iter->base.flags |= REF_KNOWS_PEELED;
+ iter->base.ref.flags |= REF_KNOWS_PEELED;
+ iter->base.ref.peeled_oid = &iter->peeled;
}
} else {
oidclr(&iter->peeled, iter->repo->hash_algo);
@@ -976,15 +979,15 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
int ok;
while ((ok = next_record(iter)) == ITER_OK) {
- const char *refname = iter->base.refname;
+ const char *refname = iter->base.ref.name;
const char *prefix = iter->prefix;
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
- !is_per_worktree_ref(iter->base.refname))
+ !is_per_worktree_ref(iter->base.ref.name))
continue;
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
- !ref_resolves_to_object(iter->base.refname, iter->repo,
+ !ref_resolves_to_object(iter->base.ref.name, iter->repo,
&iter->oid, iter->flags))
continue;
@@ -1027,22 +1030,6 @@ static int packed_ref_iterator_seek(struct ref_iterator *ref_iterator,
return 0;
}
-static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct packed_ref_iterator *iter =
- (struct packed_ref_iterator *)ref_iterator;
-
- if ((iter->base.flags & REF_KNOWS_PEELED)) {
- oidcpy(peeled, &iter->peeled);
- return is_null_oid(&iter->peeled) ? -1 : 0;
- } else if ((iter->base.flags & (REF_ISBROKEN | REF_ISSYMREF))) {
- return -1;
- } else {
- return peel_object(iter->repo, &iter->oid, peeled) ? -1 : 0;
- }
-}
-
static void packed_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct packed_ref_iterator *iter =
@@ -1056,7 +1043,6 @@ static void packed_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable packed_ref_iterator_vtable = {
.advance = packed_ref_iterator_advance,
.seek = packed_ref_iterator_seek,
- .peel = packed_ref_iterator_peel,
.release = packed_ref_iterator_release,
};
@@ -1194,7 +1180,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
iter->snapshot = snapshot;
acquire_snapshot(snapshot);
strbuf_init(&iter->refname_buf, 0);
- iter->base.oid = &iter->oid;
iter->repo = ref_store->repo;
iter->flags = flags;
@@ -1436,7 +1421,7 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
if (!iter)
cmp = +1;
else
- cmp = strcmp(iter->refname, update->refname);
+ cmp = strcmp(iter->ref.name, update->refname);
}
if (!cmp) {
@@ -1459,11 +1444,11 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
}
goto error;
- } else if (!oideq(&update->old_oid, iter->oid)) {
+ } else if (!oideq(&update->old_oid, iter->ref.oid)) {
strbuf_addf(err, "cannot update ref '%s': "
"is at %s but expected %s",
update->refname,
- oid_to_hex(iter->oid),
+ oid_to_hex(iter->ref.oid),
oid_to_hex(&update->old_oid));
ret = REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE;
@@ -1523,13 +1508,8 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
if (cmp < 0) {
/* Pass the old reference through. */
-
- struct object_id peeled;
- int peel_error = ref_iterator_peel(iter, &peeled);
-
- if (write_packed_entry(out, iter->refname,
- iter->oid,
- peel_error ? NULL : &peeled))
+ if (write_packed_entry(out, iter->ref.name,
+ iter->ref.oid, iter->ref.peeled_oid))
goto write_error;
if ((ok = ref_iterator_advance(iter)) != ITER_OK) {
@@ -1547,9 +1527,8 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
i++;
} else {
struct object_id peeled;
- int peel_error = peel_object(refs->base.repo,
- &update->new_oid,
- &peeled);
+ int peel_error = peel_object(refs->base.repo, &update->new_oid,
+ &peeled, PEEL_OBJECT_VERIFY_OBJECT_TYPE);
if (write_packed_entry(out, update->refname,
&update->new_oid,
@@ -1794,8 +1773,8 @@ cleanup:
return ret;
}
-static int packed_pack_refs(struct ref_store *ref_store UNUSED,
- struct pack_refs_opts *pack_opts UNUSED)
+static int packed_optimize(struct ref_store *ref_store UNUSED,
+ struct refs_optimize_opts *opts UNUSED)
{
/*
* Packed refs are already packed. It might be that loose refs
@@ -2150,7 +2129,7 @@ struct ref_storage_be refs_be_packed = {
.transaction_finish = packed_transaction_finish,
.transaction_abort = packed_transaction_abort,
- .pack_refs = packed_pack_refs,
+ .optimize = packed_optimize,
.rename_ref = NULL,
.copy_ref = NULL,
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index c180e0aad7..ffef01a597 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -425,10 +425,11 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
level->prefix_state = entry_prefix_state;
level->index = -1;
} else {
- iter->base.refname = entry->name;
- iter->base.referent = entry->u.value.referent;
- iter->base.oid = &entry->u.value.oid;
- iter->base.flags = entry->flag;
+ memset(&iter->base.ref, 0, sizeof(iter->base.ref));
+ iter->base.ref.name = entry->name;
+ iter->base.ref.target = entry->u.value.referent;
+ iter->base.ref.oid = &entry->u.value.oid;
+ iter->base.ref.flags = entry->flag;
return ITER_OK;
}
}
@@ -539,20 +540,12 @@ static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator,
*/
break;
}
- } while (slash);
+ } while (slash && dir->nr);
}
return 0;
}
-static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct cache_ref_iterator *iter =
- (struct cache_ref_iterator *)ref_iterator;
- return peel_object(iter->repo, ref_iterator->oid, peeled) ? -1 : 0;
-}
-
static void cache_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct cache_ref_iterator *iter =
@@ -564,7 +557,6 @@ static void cache_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable cache_ref_iterator_vtable = {
.advance = cache_ref_iterator_advance,
.seek = cache_ref_iterator_seek,
- .peel = cache_ref_iterator_peel,
.release = cache_ref_iterator_release,
};
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 54c2079c12..dee42f231d 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -249,10 +249,7 @@ const char *find_descendant_ref(const char *dirname,
*/
struct ref_iterator {
struct ref_iterator_vtable *vtable;
- const char *refname;
- const char *referent;
- const struct object_id *oid;
- unsigned int flags;
+ struct reference ref;
};
/*
@@ -361,12 +358,6 @@ typedef int ref_iterator_seek_fn(struct ref_iterator *ref_iterator,
const char *refname, unsigned int flags);
/*
- * Peels the current ref, returning 0 for success or -1 for failure.
- */
-typedef int ref_iterator_peel_fn(struct ref_iterator *ref_iterator,
- struct object_id *peeled);
-
-/*
* Implementations of this function should free any resources specific
* to the derived class.
*/
@@ -375,23 +366,9 @@ typedef void ref_iterator_release_fn(struct ref_iterator *ref_iterator);
struct ref_iterator_vtable {
ref_iterator_advance_fn *advance;
ref_iterator_seek_fn *seek;
- ref_iterator_peel_fn *peel;
ref_iterator_release_fn *release;
};
-/*
- * current_ref_iter is a performance hack: when iterating over
- * references using the for_each_ref*() functions, current_ref_iter is
- * set to the reference iterator before calling the callback function.
- * If the callback function calls peel_ref(), then peel_ref() first
- * checks whether the reference to be peeled is the one referred to by
- * the iterator (it usually is) and if so, asks the iterator for the
- * peeled version of the reference if it is available. This avoids a
- * refname lookup in a common case. current_ref_iter is set to NULL
- * when the iteration is over.
- */
-extern struct ref_iterator *current_ref_iter;
-
struct ref_store;
/* refs backends */
@@ -445,8 +422,8 @@ typedef int ref_transaction_commit_fn(struct ref_store *refs,
struct ref_transaction *transaction,
struct strbuf *err);
-typedef int pack_refs_fn(struct ref_store *ref_store,
- struct pack_refs_opts *opts);
+typedef int optimize_fn(struct ref_store *ref_store,
+ struct refs_optimize_opts *opts);
typedef int rename_ref_fn(struct ref_store *ref_store,
const char *oldref, const char *newref,
const char *logmsg);
@@ -571,7 +548,7 @@ struct ref_storage_be {
ref_transaction_finish_fn *transaction_finish;
ref_transaction_abort_fn *transaction_abort;
- pack_refs_fn *pack_refs;
+ optimize_fn *optimize;
rename_ref_fn *rename_ref;
copy_ref_fn *copy_ref;
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index c0440b4bd0..c23c45f3bf 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -6,20 +6,21 @@
#include "../config.h"
#include "../dir.h"
#include "../environment.h"
+#include "../fsck.h"
#include "../gettext.h"
#include "../hash.h"
#include "../hex.h"
#include "../iterator.h"
#include "../ident.h"
-#include "../lockfile.h"
#include "../object.h"
#include "../path.h"
#include "../refs.h"
#include "../reftable/reftable-basics.h"
-#include "../reftable/reftable-stack.h"
-#include "../reftable/reftable-record.h"
#include "../reftable/reftable-error.h"
+#include "../reftable/reftable-fsck.h"
#include "../reftable/reftable-iterator.h"
+#include "../reftable/reftable-record.h"
+#include "../reftable/reftable-stack.h"
#include "../repo-settings.h"
#include "../setup.h"
#include "../strmap.h"
@@ -546,6 +547,7 @@ struct reftable_ref_iterator {
struct reftable_iterator iter;
struct reftable_ref_record ref;
struct object_id oid;
+ struct object_id peeled_oid;
char *prefix;
size_t prefix_len;
@@ -670,6 +672,8 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
case REFTABLE_REF_VAL2:
oidread(&iter->oid, iter->ref.value.val2.value,
refs->base.repo->hash_algo);
+ oidread(&iter->peeled_oid, iter->ref.value.val2.target_value,
+ refs->base.repo->hash_algo);
break;
case REFTABLE_REF_SYMREF:
referent = refs_resolve_ref_unsafe(&iter->refs->base,
@@ -703,10 +707,13 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
&iter->oid, flags))
continue;
- iter->base.refname = iter->ref.refname;
- iter->base.referent = referent;
- iter->base.oid = &iter->oid;
- iter->base.flags = flags;
+ memset(&iter->base.ref, 0, sizeof(iter->base.ref));
+ iter->base.ref.name = iter->ref.refname;
+ iter->base.ref.target = referent;
+ iter->base.ref.oid = &iter->oid;
+ if (iter->ref.value_type == REFTABLE_REF_VAL2)
+ iter->base.ref.peeled_oid = &iter->peeled_oid;
+ iter->base.ref.flags = flags;
break;
}
@@ -737,21 +744,6 @@ static int reftable_ref_iterator_seek(struct ref_iterator *ref_iterator,
return iter->err;
}
-static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct reftable_ref_iterator *iter =
- (struct reftable_ref_iterator *)ref_iterator;
-
- if (iter->ref.value_type == REFTABLE_REF_VAL2) {
- oidread(peeled, iter->ref.value.val2.target_value,
- iter->refs->base.repo->hash_algo);
- return 0;
- }
-
- return -1;
-}
-
static void reftable_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct reftable_ref_iterator *iter =
@@ -769,7 +761,6 @@ static void reftable_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable reftable_ref_iterator_vtable = {
.advance = reftable_ref_iterator_advance,
.seek = reftable_ref_iterator_seek,
- .peel = reftable_ref_iterator_peel,
.release = reftable_ref_iterator_release,
};
@@ -827,7 +818,7 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
iter = xcalloc(1, sizeof(*iter));
base_ref_iterator_init(&iter->base, &reftable_ref_iterator_vtable);
- iter->base.oid = &iter->oid;
+ iter->base.ref.oid = &iter->oid;
iter->flags = flags;
iter->refs = refs;
iter->exclude_patterns = filter_exclude_patterns(exclude_patterns);
@@ -1012,10 +1003,6 @@ static int prepare_transaction_update(struct write_transaction_table_arg **out,
if (!arg) {
struct reftable_addition *addition;
- ret = reftable_stack_reload(be->stack);
- if (ret)
- return ret;
-
ret = reftable_stack_new_addition(&addition, be->stack,
REFTABLE_STACK_NEW_ADDITION_RELOAD);
if (ret) {
@@ -1278,9 +1265,33 @@ static enum ref_transaction_error prepare_single_update(struct reftable_ref_stor
ret = ref_update_check_old_target(referent->buf, u, err);
if (ret)
return ret;
- } else if ((u->flags & (REF_LOG_ONLY | REF_HAVE_OLD)) == REF_HAVE_OLD &&
- !oideq(&current_oid, &u->old_oid)) {
- if (is_null_oid(&u->old_oid)) {
+ } else if ((u->flags & (REF_LOG_ONLY | REF_HAVE_OLD)) == REF_HAVE_OLD) {
+ if (oideq(&current_oid, &u->old_oid)) {
+ /*
+ * Normally matching the expected old oid is enough. Either we
+ * found the ref at the expected state, or we are creating and
+ * expect the null oid (and likewise found nothing).
+ *
+ * But there is one exception for the null oid: if we found a
+ * symref pointing to nothing we'll also get the null oid. In
+ * regular recursive mode, that's good (we'll write to what the
+ * symref points to, which doesn't exist). But in no-deref
+ * mode, it means we'll clobber the symref, even though the
+ * caller asked for this to be a creation event. So flag
+ * that case to preserve the dangling symref.
+ *
+ * Everything else is OK and we can fall through to the
+ * end of the conditional chain.
+ */
+ if ((u->flags & REF_NO_DEREF) &&
+ referent->len &&
+ is_null_oid(&u->old_oid)) {
+ strbuf_addf(err, _("cannot lock ref '%s': "
+ "dangling symref already exists"),
+ ref_update_original_update_refname(u));
+ return REF_TRANSACTION_ERROR_CREATE_EXISTS;
+ }
+ } else if (is_null_oid(&u->old_oid)) {
strbuf_addf(err, _("cannot lock ref '%s': "
"reference already exists"),
ref_update_original_update_refname(u));
@@ -1621,7 +1632,8 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
ref.refname = (char *)u->refname;
ref.update_index = ts;
- peel_error = peel_object(arg->refs->base.repo, &u->new_oid, &peeled);
+ peel_error = peel_object(arg->refs->base.repo, &u->new_oid, &peeled,
+ PEEL_OBJECT_VERIFY_OBJECT_TYPE);
if (!peel_error) {
ref.value_type = REFTABLE_REF_VAL2;
memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
@@ -1688,11 +1700,11 @@ done:
return ret;
}
-static int reftable_be_pack_refs(struct ref_store *ref_store,
- struct pack_refs_opts *opts)
+static int reftable_be_optimize(struct ref_store *ref_store,
+ struct refs_optimize_opts *opts)
{
struct reftable_ref_store *refs =
- reftable_be_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB, "pack_refs");
+ reftable_be_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB, "optimize_refs");
struct reftable_stack *stack;
int ret;
@@ -1703,7 +1715,7 @@ static int reftable_be_pack_refs(struct ref_store *ref_store,
if (!stack)
stack = refs->main_backend.stack;
- if (opts->flags & PACK_REFS_AUTO)
+ if (opts->flags & REFS_OPTIMIZE_AUTO)
ret = reftable_stack_auto_compact(stack);
else
ret = reftable_stack_compact_all(stack, NULL);
@@ -1974,7 +1986,8 @@ static int reftable_be_rename_ref(struct ref_store *ref_store,
ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1);
if (ret)
goto done;
- ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg);
+ ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg,
+ REFTABLE_STACK_NEW_ADDITION_RELOAD);
done:
assert(ret != REFTABLE_API_ERROR);
@@ -2003,7 +2016,8 @@ static int reftable_be_copy_ref(struct ref_store *ref_store,
ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1);
if (ret)
goto done;
- ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg);
+ ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg,
+ REFTABLE_STACK_NEW_ADDITION_RELOAD);
done:
assert(ret != REFTABLE_API_ERROR);
@@ -2043,7 +2057,7 @@ static int reftable_reflog_iterator_advance(struct ref_iterator *ref_iterator)
strbuf_reset(&iter->last_name);
strbuf_addstr(&iter->last_name, iter->log.refname);
- iter->base.refname = iter->log.refname;
+ iter->base.ref.name = iter->log.refname;
break;
}
@@ -2063,13 +2077,6 @@ static int reftable_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSE
return -1;
}
-static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
- struct object_id *peeled UNUSED)
-{
- BUG("reftable reflog iterator cannot be peeled");
- return -1;
-}
-
static void reftable_reflog_iterator_release(struct ref_iterator *ref_iterator)
{
struct reftable_reflog_iterator *iter =
@@ -2082,7 +2089,6 @@ static void reftable_reflog_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable reftable_reflog_iterator_vtable = {
.advance = reftable_reflog_iterator_advance,
.seek = reftable_reflog_iterator_seek,
- .peel = reftable_reflog_iterator_peel,
.release = reftable_reflog_iterator_release,
};
@@ -2155,7 +2161,7 @@ static int yield_log_record(struct reftable_ref_store *refs,
full_committer = fmt_ident(log->value.update.name, log->value.update.email,
WANT_COMMITTER_IDENT, NULL, IDENT_NO_DATE);
- return fn(&old_oid, &new_oid, full_committer,
+ return fn(log->refname, &old_oid, &new_oid, full_committer,
log->value.update.time, log->value.update.tz_offset,
log->value.update.message, cb_data);
}
@@ -2375,7 +2381,8 @@ static int reftable_be_create_reflog(struct ref_store *ref_store,
goto done;
arg.stack = be->stack;
- ret = reftable_stack_add(be->stack, &write_reflog_existence_table, &arg);
+ ret = reftable_stack_add(be->stack, &write_reflog_existence_table, &arg,
+ REFTABLE_STACK_NEW_ADDITION_RELOAD);
done:
return ret;
@@ -2446,7 +2453,8 @@ static int reftable_be_delete_reflog(struct ref_store *ref_store,
return ret;
arg.stack = be->stack;
- ret = reftable_stack_add(be->stack, &write_reflog_delete_table, &arg);
+ ret = reftable_stack_add(be->stack, &write_reflog_delete_table, &arg,
+ REFTABLE_STACK_NEW_ADDITION_RELOAD);
assert(ret != REFTABLE_API_ERROR);
return ret;
@@ -2484,7 +2492,7 @@ static int write_reflog_expiry_table(struct reftable_writer *writer, void *cb_da
ref.refname = (char *)arg->refname;
ref.update_index = ts;
- if (!peel_object(arg->refs->base.repo, &arg->update_oid, &peeled)) {
+ if (!peel_object(arg->refs->base.repo, &arg->update_oid, &peeled, 0)) {
ref.value_type = REFTABLE_REF_VAL2;
memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
memcpy(ref.value.val2.value, arg->update_oid.hash, GIT_MAX_RAWSZ);
@@ -2567,15 +2575,16 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
if (ret < 0)
goto done;
- ret = reftable_stack_init_log_iterator(be->stack, &it);
+ ret = reftable_stack_new_addition(&add, be->stack,
+ REFTABLE_STACK_NEW_ADDITION_RELOAD);
if (ret < 0)
goto done;
- ret = reftable_iterator_seek_log(&it, refname);
+ ret = reftable_stack_init_log_iterator(be->stack, &it);
if (ret < 0)
goto done;
- ret = reftable_stack_new_addition(&add, be->stack, 0);
+ ret = reftable_iterator_seek_log(&it, refname);
if (ret < 0)
goto done;
@@ -2683,11 +2692,56 @@ done:
return ret;
}
-static int reftable_be_fsck(struct ref_store *ref_store UNUSED,
- struct fsck_options *o UNUSED,
+static void reftable_fsck_verbose_handler(const char *msg, void *cb_data)
+{
+ struct fsck_options *o = cb_data;
+
+ if (o->verbose)
+ fprintf_ln(stderr, "%s", msg);
+}
+
+static const enum fsck_msg_id fsck_msg_id_map[] = {
+ [REFTABLE_FSCK_ERROR_TABLE_NAME] = FSCK_MSG_BAD_REFTABLE_TABLE_NAME,
+};
+
+static int reftable_fsck_error_handler(struct reftable_fsck_info *info,
+ void *cb_data)
+{
+ struct fsck_ref_report report = { .path = info->path };
+ struct fsck_options *o = cb_data;
+ enum fsck_msg_id msg_id;
+
+ if (info->error < 0 || info->error >= REFTABLE_FSCK_MAX_VALUE)
+ BUG("unknown fsck error: %d", (int)info->error);
+
+ msg_id = fsck_msg_id_map[info->error];
+
+ if (!msg_id)
+ BUG("fsck_msg_id value missing for reftable error: %d", (int)info->error);
+
+ return fsck_report_ref(o, &report, msg_id, "%s", info->msg);
+}
+
+static int reftable_be_fsck(struct ref_store *ref_store, struct fsck_options *o,
struct worktree *wt UNUSED)
{
- return 0;
+ struct reftable_ref_store *refs;
+ struct strmap_entry *entry;
+ struct hashmap_iter iter;
+ int ret = 0;
+
+ refs = reftable_be_downcast(ref_store, REF_STORE_READ, "fsck");
+
+ ret |= reftable_fsck_check(refs->main_backend.stack, reftable_fsck_error_handler,
+ reftable_fsck_verbose_handler, o);
+
+ strmap_for_each_entry(&refs->worktree_backends, &iter, entry) {
+ struct reftable_backend *b = (struct reftable_backend *)entry->value;
+ ret |= reftable_fsck_check(b->stack, reftable_fsck_error_handler,
+ reftable_fsck_verbose_handler, o);
+ }
+
+ return ret;
}
struct ref_storage_be refs_be_reftable = {
@@ -2701,7 +2755,7 @@ struct ref_storage_be refs_be_reftable = {
.transaction_finish = reftable_be_transaction_finish,
.transaction_abort = reftable_be_transaction_abort,
- .pack_refs = reftable_be_pack_refs,
+ .optimize = reftable_be_optimize,
.rename_ref = reftable_be_rename_ref,
.copy_ref = reftable_be_copy_ref,