aboutsummaryrefslogtreecommitdiffstats
path: root/refs/reftable-backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'refs/reftable-backend.c')
-rw-r--r--refs/reftable-backend.c426
1 files changed, 246 insertions, 180 deletions
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 1cda48c504..21495dee03 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1,6 +1,8 @@
#include "../git-compat-util.h"
#include "../abspath.h"
#include "../chdir-notify.h"
+#include "../config.h"
+#include "../dir.h"
#include "../environment.h"
#include "../gettext.h"
#include "../hash.h"
@@ -15,7 +17,6 @@
#include "../reftable/reftable-record.h"
#include "../reftable/reftable-error.h"
#include "../reftable/reftable-iterator.h"
-#include "../reftable/reftable-merged.h"
#include "../setup.h"
#include "../strmap.h"
#include "parse.h"
@@ -129,7 +130,7 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store,
store->base.repo->commondir, wtname_buf.buf);
store->err = reftable_new_stack(&stack, wt_dir.buf,
- store->write_options);
+ &store->write_options);
assert(store->err != REFTABLE_API_ERROR);
strmap_put(&store->worktree_stacks, wtname_buf.buf, stack);
}
@@ -172,32 +173,30 @@ static int should_write_log(struct ref_store *refs, const char *refname)
}
}
-static void fill_reftable_log_record(struct reftable_log_record *log)
+static void fill_reftable_log_record(struct reftable_log_record *log, const struct ident_split *split)
{
- const char *info = git_committer_info(0);
- struct ident_split split = {0};
+ const char *tz_begin;
int sign = 1;
- if (split_ident_line(&split, info, strlen(info)))
- BUG("failed splitting committer info");
-
reftable_log_record_release(log);
log->value_type = REFTABLE_LOG_UPDATE;
log->value.update.name =
- xstrndup(split.name_begin, split.name_end - split.name_begin);
+ xstrndup(split->name_begin, split->name_end - split->name_begin);
log->value.update.email =
- xstrndup(split.mail_begin, split.mail_end - split.mail_begin);
- log->value.update.time = atol(split.date_begin);
- if (*split.tz_begin == '-') {
+ xstrndup(split->mail_begin, split->mail_end - split->mail_begin);
+ log->value.update.time = atol(split->date_begin);
+
+ tz_begin = split->tz_begin;
+ if (*tz_begin == '-') {
sign = -1;
- split.tz_begin++;
+ tz_begin++;
}
- if (*split.tz_begin == '+') {
+ if (*tz_begin == '+') {
sign = 1;
- split.tz_begin++;
+ tz_begin++;
}
- log->value.update.tz_offset = sign * atoi(split.tz_begin);
+ log->value.update.tz_offset = sign * atoi(tz_begin);
}
static int read_ref_without_reload(struct reftable_stack *stack,
@@ -230,6 +229,34 @@ done:
return ret;
}
+static int reftable_be_config(const char *var, const char *value,
+ const struct config_context *ctx,
+ void *_opts)
+{
+ struct reftable_write_options *opts = _opts;
+
+ if (!strcmp(var, "reftable.blocksize")) {
+ unsigned long block_size = git_config_ulong(var, value, ctx->kvi);
+ if (block_size > 16777215)
+ die("reftable block size cannot exceed 16MB");
+ opts->block_size = block_size;
+ } else if (!strcmp(var, "reftable.restartinterval")) {
+ unsigned long restart_interval = git_config_ulong(var, value, ctx->kvi);
+ if (restart_interval > UINT16_MAX)
+ die("reftable block size cannot exceed %u", (unsigned)UINT16_MAX);
+ opts->restart_interval = restart_interval;
+ } else if (!strcmp(var, "reftable.indexobjects")) {
+ opts->skip_index_objects = !git_config_bool(var, value);
+ } else if (!strcmp(var, "reftable.geometricfactor")) {
+ unsigned long factor = git_config_ulong(var, value, ctx->kvi);
+ if (factor > UINT8_MAX)
+ die("reftable geometric factor cannot exceed %u", (unsigned)UINT8_MAX);
+ opts->auto_compaction_factor = factor;
+ }
+
+ return 0;
+}
+
static struct ref_store *reftable_be_init(struct repository *repo,
const char *gitdir,
unsigned int store_flags)
@@ -245,12 +272,24 @@ static struct ref_store *reftable_be_init(struct repository *repo,
base_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable);
strmap_init(&refs->worktree_stacks);
refs->store_flags = store_flags;
- refs->write_options.block_size = 4096;
+
refs->write_options.hash_id = repo->hash_algo->format_id;
refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask);
refs->write_options.disable_auto_compact =
!git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1);
+ git_config(reftable_be_config, &refs->write_options);
+
+ /*
+ * It is somewhat unfortunate that we have to mirror the default block
+ * size of the reftable library here. But given that the write options
+ * wouldn't be updated by the library here, and given that we require
+ * the proper block size to trim reflog message so that they fit, we
+ * must set up a proper value here.
+ */
+ if (!refs->write_options.block_size)
+ refs->write_options.block_size = 4096;
+
/*
* Set up the main reftable stack that is hosted in GIT_COMMON_DIR.
* This stack contains both the shared and the main worktree refs.
@@ -265,7 +304,7 @@ static struct ref_store *reftable_be_init(struct repository *repo,
}
strbuf_addstr(&path, "/reftable");
refs->err = reftable_new_stack(&refs->main_stack, path.buf,
- refs->write_options);
+ &refs->write_options);
if (refs->err)
goto done;
@@ -282,7 +321,7 @@ static struct ref_store *reftable_be_init(struct repository *repo,
strbuf_addf(&path, "%s/reftable", gitdir);
refs->err = reftable_new_stack(&refs->worktree_stack, path.buf,
- refs->write_options);
+ &refs->write_options);
if (refs->err)
goto done;
}
@@ -295,12 +334,33 @@ done:
return &refs->base;
}
-static int reftable_be_init_db(struct ref_store *ref_store,
- int flags UNUSED,
- struct strbuf *err UNUSED)
+static void reftable_be_release(struct ref_store *ref_store)
+{
+ struct reftable_ref_store *refs = reftable_be_downcast(ref_store, 0, "release");
+ struct strmap_entry *entry;
+ struct hashmap_iter iter;
+
+ if (refs->main_stack) {
+ reftable_stack_destroy(refs->main_stack);
+ refs->main_stack = NULL;
+ }
+
+ if (refs->worktree_stack) {
+ reftable_stack_destroy(refs->worktree_stack);
+ refs->worktree_stack = NULL;
+ }
+
+ strmap_for_each_entry(&refs->worktree_stacks, &iter, entry)
+ reftable_stack_destroy(entry->value);
+ strmap_clear(&refs->worktree_stacks, 0);
+}
+
+static int reftable_be_create_on_disk(struct ref_store *ref_store,
+ int flags UNUSED,
+ struct strbuf *err UNUSED)
{
struct reftable_ref_store *refs =
- reftable_be_downcast(ref_store, REF_STORE_WRITE, "init_db");
+ reftable_be_downcast(ref_store, REF_STORE_WRITE, "create");
struct strbuf sb = STRBUF_INIT;
strbuf_addf(&sb, "%s/reftable", refs->base.gitdir);
@@ -324,6 +384,56 @@ static int reftable_be_init_db(struct ref_store *ref_store,
return 0;
}
+static int reftable_be_remove_on_disk(struct ref_store *ref_store,
+ struct strbuf *err)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_WRITE, "remove");
+ struct strbuf sb = STRBUF_INIT;
+ int ret = 0;
+
+ /*
+ * Release the ref store such that all stacks are closed. This is
+ * required so that the "tables.list" file is not open anymore, which
+ * would otherwise make it impossible to remove the file on Windows.
+ */
+ reftable_be_release(ref_store);
+
+ strbuf_addf(&sb, "%s/reftable", refs->base.gitdir);
+ if (remove_dir_recursively(&sb, 0) < 0) {
+ strbuf_addf(err, "could not delete reftables: %s",
+ strerror(errno));
+ ret = -1;
+ }
+ strbuf_reset(&sb);
+
+ strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir);
+ if (unlink(sb.buf) < 0) {
+ strbuf_addf(err, "could not delete stub HEAD: %s",
+ strerror(errno));
+ ret = -1;
+ }
+ strbuf_reset(&sb);
+
+ strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir);
+ if (unlink(sb.buf) < 0) {
+ strbuf_addf(err, "could not delete stub heads: %s",
+ strerror(errno));
+ ret = -1;
+ }
+ strbuf_reset(&sb);
+
+ strbuf_addf(&sb, "%s/refs", refs->base.gitdir);
+ if (rmdir(sb.buf) < 0) {
+ strbuf_addf(err, "could not delete stub heads: %s",
+ strerror(errno));
+ ret = -1;
+ }
+
+ strbuf_release(&sb);
+ return ret;
+}
+
struct reftable_ref_iterator {
struct ref_iterator base;
struct reftable_ref_store *refs;
@@ -356,8 +466,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
*/
if (!starts_with(iter->ref.refname, "refs/") &&
!(iter->flags & DO_FOR_EACH_INCLUDE_ROOT_REFS &&
- (is_pseudoref(&iter->refs->base, iter->ref.refname) ||
- is_headref(&iter->refs->base, iter->ref.refname)))) {
+ is_root_ref(iter->ref.refname))) {
continue;
}
@@ -464,7 +573,6 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
const char *prefix,
int flags)
{
- struct reftable_merged_table *merged_table;
struct reftable_ref_iterator *iter;
int ret;
@@ -484,9 +592,8 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
if (ret)
goto done;
- merged_table = reftable_stack_merged_table(stack);
-
- ret = reftable_merged_table_seek_ref(merged_table, &iter->iter, prefix);
+ reftable_stack_init_ref_iterator(stack, &iter->iter);
+ ret = reftable_iterator_seek_ref(&iter->iter, prefix);
if (ret)
goto done;
@@ -581,16 +688,6 @@ static int reftable_be_read_symbolic_ref(struct ref_store *ref_store,
return ret;
}
-/*
- * Return the refname under which update was originally requested.
- */
-static const char *original_update_refname(struct ref_update *update)
-{
- while (update->parent_update)
- update = update->parent_update;
- return update->refname;
-}
-
struct reftable_transaction_update {
struct ref_update *update;
struct object_id current_oid;
@@ -829,7 +926,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
new_update = ref_transaction_add_update(
transaction, "HEAD",
u->flags | REF_LOG_ONLY | REF_NO_DEREF,
- &u->new_oid, &u->old_oid, u->msg);
+ &u->new_oid, &u->old_oid, NULL, NULL, u->msg);
string_list_insert(&affected_refnames, new_update->refname);
}
@@ -837,7 +934,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
&current_oid, &referent, &u->type);
if (ret < 0)
goto done;
- if (ret > 0 && (!(u->flags & REF_HAVE_OLD) || is_null_oid(&u->old_oid))) {
+ if (ret > 0 && !ref_update_ref_must_exist(u)) {
/*
* The reference does not exist, and we either have no
* old object ID or expect the reference to not exist.
@@ -856,7 +953,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
* There is no need to write the reference deletion
* when the reference in question doesn't exist.
*/
- if (u->flags & REF_HAVE_NEW && !is_null_oid(&u->new_oid)) {
+ if ((u->flags & REF_HAVE_NEW) && !ref_update_has_null_new_value(u)) {
ret = queue_transaction_update(refs, tx_data, u,
&current_oid, err);
if (ret)
@@ -869,7 +966,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
/* The reference does not exist, but we expected it to. */
strbuf_addf(err, _("cannot lock ref '%s': "
"unable to resolve reference '%s'"),
- original_update_refname(u), u->refname);
+ ref_update_original_update_refname(u), u->refname);
ret = -1;
goto done;
}
@@ -907,8 +1004,11 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
* intertwined with the locking in files-backend.c.
*/
new_update = ref_transaction_add_update(
- transaction, referent.buf, new_flags,
- &u->new_oid, &u->old_oid, u->msg);
+ transaction, referent.buf, new_flags,
+ u->new_target ? NULL : &u->new_oid,
+ u->old_target ? NULL : &u->old_oid,
+ u->new_target, u->old_target, u->msg);
+
new_update->parent_update = u;
/*
@@ -938,20 +1038,25 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
* individual refs. But the error messages match what the files
* backend returns, which keeps our tests happy.
*/
- if (u->flags & REF_HAVE_OLD && !oideq(&current_oid, &u->old_oid)) {
+ if (u->old_target) {
+ if (ref_update_check_old_target(referent.buf, u, err)) {
+ ret = -1;
+ goto done;
+ }
+ } else if ((u->flags & REF_HAVE_OLD) && !oideq(&current_oid, &u->old_oid)) {
if (is_null_oid(&u->old_oid))
strbuf_addf(err, _("cannot lock ref '%s': "
- "reference already exists"),
- original_update_refname(u));
+ "reference already exists"),
+ ref_update_original_update_refname(u));
else if (is_null_oid(&current_oid))
strbuf_addf(err, _("cannot lock ref '%s': "
- "reference is missing but expected %s"),
- original_update_refname(u),
+ "reference is missing but expected %s"),
+ ref_update_original_update_refname(u),
oid_to_hex(&u->old_oid));
else
strbuf_addf(err, _("cannot lock ref '%s': "
- "is at %s but expected %s"),
- original_update_refname(u),
+ "is at %s but expected %s"),
+ ref_update_original_update_refname(u),
oid_to_hex(&current_oid),
oid_to_hex(&u->old_oid));
ret = -1;
@@ -1017,13 +1122,17 @@ static int transaction_update_cmp(const void *a, const void *b)
static int write_transaction_table(struct reftable_writer *writer, void *cb_data)
{
struct write_transaction_table_arg *arg = cb_data;
- struct reftable_merged_table *mt =
- reftable_stack_merged_table(arg->stack);
uint64_t ts = reftable_stack_next_update_index(arg->stack);
struct reftable_log_record *logs = NULL;
+ struct ident_split committer_ident = {0};
size_t logs_nr = 0, logs_alloc = 0, i;
+ const char *committer_info;
int ret = 0;
+ committer_info = git_committer_info(0);
+ if (split_ident_line(&committer_ident, committer_info, strlen(committer_info)))
+ BUG("failed splitting committer info");
+
QSORT(arg->updates, arg->updates_nr, transaction_update_cmp);
reftable_writer_set_limits(writer, ts, ts);
@@ -1043,10 +1152,14 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
* - `core.logAllRefUpdates` tells us to create the reflog for
* the given ref.
*/
- if (u->flags & REF_HAVE_NEW && !(u->type & REF_ISSYMREF) && is_null_oid(&u->new_oid)) {
+ if ((u->flags & REF_HAVE_NEW) &&
+ !(u->type & REF_ISSYMREF) &&
+ ref_update_has_null_new_value(u)) {
struct reftable_log_record log = {0};
struct reftable_iterator it = {0};
+ reftable_stack_init_log_iterator(arg->stack, &it);
+
/*
* When deleting refs we also delete all reflog entries
* with them. While it is not strictly required to
@@ -1056,7 +1169,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
* Unfortunately, we have no better way than to delete
* all reflog entries one by one.
*/
- ret = reftable_merged_table_seek_log(mt, &it, u->refname);
+ ret = reftable_iterator_seek_log(&it, u->refname);
while (ret == 0) {
struct reftable_log_record *tombstone;
@@ -1080,28 +1193,57 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
if (ret)
goto done;
- } else if (u->flags & REF_HAVE_NEW &&
+ } else if (!(u->flags & REF_SKIP_CREATE_REFLOG) &&
+ (u->flags & REF_HAVE_NEW) &&
(u->flags & REF_FORCE_CREATE_REFLOG ||
should_write_log(&arg->refs->base, u->refname))) {
struct reftable_log_record *log;
+ int create_reflog = 1;
+
+ if (u->new_target) {
+ if (!refs_resolve_ref_unsafe(&arg->refs->base, u->new_target,
+ RESOLVE_REF_READING, &u->new_oid, NULL)) {
+ /*
+ * TODO: currently we skip creating reflogs for dangling
+ * symref updates. It would be nice to capture this as
+ * zero oid updates however.
+ */
+ create_reflog = 0;
+ }
+ }
- ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
- log = &logs[logs_nr++];
- memset(log, 0, sizeof(*log));
-
- fill_reftable_log_record(log);
- log->update_index = ts;
- log->refname = xstrdup(u->refname);
- memcpy(log->value.update.new_hash, u->new_oid.hash, GIT_MAX_RAWSZ);
- memcpy(log->value.update.old_hash, tx_update->current_oid.hash, GIT_MAX_RAWSZ);
- log->value.update.message =
- xstrndup(u->msg, arg->refs->write_options.block_size / 2);
+ if (create_reflog) {
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ log = &logs[logs_nr++];
+ memset(log, 0, sizeof(*log));
+
+ fill_reftable_log_record(log, &committer_ident);
+ log->update_index = ts;
+ log->refname = xstrdup(u->refname);
+ memcpy(log->value.update.new_hash,
+ u->new_oid.hash, GIT_MAX_RAWSZ);
+ memcpy(log->value.update.old_hash,
+ tx_update->current_oid.hash, GIT_MAX_RAWSZ);
+ log->value.update.message =
+ xstrndup(u->msg, arg->refs->write_options.block_size / 2);
+ }
}
if (u->flags & REF_LOG_ONLY)
continue;
- if (u->flags & REF_HAVE_NEW && is_null_oid(&u->new_oid)) {
+ if (u->new_target) {
+ struct reftable_ref_record ref = {
+ .refname = (char *)u->refname,
+ .value_type = REFTABLE_REF_SYMREF,
+ .value.symref = (char *)u->new_target,
+ .update_index = ts,
+ };
+
+ ret = reftable_writer_add_ref(writer, &ref);
+ if (ret < 0)
+ goto done;
+ } else if ((u->flags & REF_HAVE_NEW) && ref_update_has_null_new_value(u)) {
struct reftable_ref_record ref = {
.refname = (char *)u->refname,
.update_index = ts,
@@ -1119,7 +1261,7 @@ 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(&u->new_oid, &peeled);
+ peel_error = peel_object(arg->refs->base.repo, &u->new_oid, &peeled);
if (!peel_error) {
ref.value_type = REFTABLE_REF_VAL2;
memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
@@ -1227,96 +1369,12 @@ out:
struct write_create_symref_arg {
struct reftable_ref_store *refs;
struct reftable_stack *stack;
+ struct strbuf *err;
const char *refname;
const char *target;
const char *logmsg;
};
-static int write_create_symref_table(struct reftable_writer *writer, void *cb_data)
-{
- struct write_create_symref_arg *create = cb_data;
- uint64_t ts = reftable_stack_next_update_index(create->stack);
- struct reftable_ref_record ref = {
- .refname = (char *)create->refname,
- .value_type = REFTABLE_REF_SYMREF,
- .value.symref = (char *)create->target,
- .update_index = ts,
- };
- struct reftable_log_record log = {0};
- struct object_id new_oid;
- struct object_id old_oid;
- int ret;
-
- reftable_writer_set_limits(writer, ts, ts);
-
- ret = reftable_writer_add_ref(writer, &ref);
- if (ret)
- return ret;
-
- /*
- * Note that it is important to try and resolve the reference before we
- * write the log entry. This is because `should_write_log()` will munge
- * `core.logAllRefUpdates`, which is undesirable when we create a new
- * repository because it would be written into the config. As HEAD will
- * not resolve for new repositories this ordering will ensure that this
- * never happens.
- */
- if (!create->logmsg ||
- !refs_resolve_ref_unsafe(&create->refs->base, create->target,
- RESOLVE_REF_READING, &new_oid, NULL) ||
- !should_write_log(&create->refs->base, create->refname))
- return 0;
-
- fill_reftable_log_record(&log);
- log.refname = xstrdup(create->refname);
- log.update_index = ts;
- log.value.update.message = xstrndup(create->logmsg,
- create->refs->write_options.block_size / 2);
- memcpy(log.value.update.new_hash, new_oid.hash, GIT_MAX_RAWSZ);
- if (refs_resolve_ref_unsafe(&create->refs->base, create->refname,
- RESOLVE_REF_READING, &old_oid, NULL))
- memcpy(log.value.update.old_hash, old_oid.hash, GIT_MAX_RAWSZ);
-
- ret = reftable_writer_add_log(writer, &log);
- reftable_log_record_release(&log);
- return ret;
-}
-
-static int reftable_be_create_symref(struct ref_store *ref_store,
- const char *refname,
- const char *target,
- const char *logmsg)
-{
- struct reftable_ref_store *refs =
- reftable_be_downcast(ref_store, REF_STORE_WRITE, "create_symref");
- struct reftable_stack *stack = stack_for(refs, refname, &refname);
- struct write_create_symref_arg arg = {
- .refs = refs,
- .stack = stack,
- .refname = refname,
- .target = target,
- .logmsg = logmsg,
- };
- int ret;
-
- ret = refs->err;
- if (ret < 0)
- goto done;
-
- ret = reftable_stack_reload(stack);
- if (ret)
- goto done;
-
- ret = reftable_stack_add(stack, &write_create_symref_table, &arg);
-
-done:
- assert(ret != REFTABLE_API_ERROR);
- if (ret)
- error("unable to write symref for %s: %s", refname,
- reftable_error_str(ret));
- return ret;
-}
-
struct write_copy_arg {
struct reftable_ref_store *refs;
struct reftable_stack *stack;
@@ -1330,15 +1388,20 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
{
struct write_copy_arg *arg = cb_data;
uint64_t deletion_ts, creation_ts;
- struct reftable_merged_table *mt = reftable_stack_merged_table(arg->stack);
struct reftable_ref_record old_ref = {0}, refs[2] = {0};
struct reftable_log_record old_log = {0}, *logs = NULL;
struct reftable_iterator it = {0};
struct string_list skip = STRING_LIST_INIT_NODUP;
+ struct ident_split committer_ident = {0};
struct strbuf errbuf = STRBUF_INIT;
size_t logs_nr = 0, logs_alloc = 0, i;
+ const char *committer_info;
int ret;
+ committer_info = git_committer_info(0);
+ if (split_ident_line(&committer_ident, committer_info, strlen(committer_info)))
+ BUG("failed splitting committer info");
+
if (reftable_stack_read_ref(arg->stack, arg->oldname, &old_ref)) {
ret = error(_("refname %s not found"), arg->oldname);
goto done;
@@ -1361,7 +1424,8 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
/*
* Verify that the new refname is available.
*/
- string_list_insert(&skip, arg->oldname);
+ if (arg->delete_old)
+ string_list_insert(&skip, arg->oldname);
ret = refs_verify_refname_available(&arg->refs->base, arg->newname,
NULL, &skip, &errbuf);
if (ret < 0) {
@@ -1412,7 +1476,7 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
memset(&logs[logs_nr], 0, sizeof(logs[logs_nr]));
- fill_reftable_log_record(&logs[logs_nr]);
+ fill_reftable_log_record(&logs[logs_nr], &committer_ident);
logs[logs_nr].refname = (char *)arg->newname;
logs[logs_nr].update_index = deletion_ts;
logs[logs_nr].value.update.message =
@@ -1444,7 +1508,7 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
*/
ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
memset(&logs[logs_nr], 0, sizeof(logs[logs_nr]));
- fill_reftable_log_record(&logs[logs_nr]);
+ fill_reftable_log_record(&logs[logs_nr], &committer_ident);
logs[logs_nr].refname = (char *)arg->newname;
logs[logs_nr].update_index = creation_ts;
logs[logs_nr].value.update.message =
@@ -1457,7 +1521,8 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
* copy over all log entries from the old reflog. Last but not least,
* when renaming we also have to delete all the old reflog entries.
*/
- ret = reftable_merged_table_seek_log(mt, &it, arg->oldname);
+ reftable_stack_init_log_iterator(arg->stack, &it);
+ ret = reftable_iterator_seek_log(&it, arg->oldname);
if (ret < 0)
goto done;
@@ -1663,7 +1728,6 @@ static struct ref_iterator_vtable reftable_reflog_iterator_vtable = {
static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftable_ref_store *refs,
struct reftable_stack *stack)
{
- struct reftable_merged_table *merged_table;
struct reftable_reflog_iterator *iter;
int ret;
@@ -1680,9 +1744,8 @@ static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftabl
if (ret < 0)
goto done;
- merged_table = reftable_stack_merged_table(stack);
-
- ret = reftable_merged_table_seek_log(merged_table, &iter->iter, "");
+ reftable_stack_init_log_iterator(stack, &iter->iter);
+ ret = reftable_iterator_seek_log(&iter->iter, "");
if (ret < 0)
goto done;
@@ -1740,7 +1803,6 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
struct reftable_ref_store *refs =
reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent_reverse");
struct reftable_stack *stack = stack_for(refs, refname, &refname);
- struct reftable_merged_table *mt = NULL;
struct reftable_log_record log = {0};
struct reftable_iterator it = {0};
int ret;
@@ -1748,8 +1810,8 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
if (refs->err < 0)
return refs->err;
- mt = reftable_stack_merged_table(stack);
- ret = reftable_merged_table_seek_log(mt, &it, refname);
+ reftable_stack_init_log_iterator(stack, &it);
+ ret = reftable_iterator_seek_log(&it, refname);
while (!ret) {
ret = reftable_iterator_next_log(&it, &log);
if (ret < 0)
@@ -1777,7 +1839,6 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
struct reftable_ref_store *refs =
reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent");
struct reftable_stack *stack = stack_for(refs, refname, &refname);
- struct reftable_merged_table *mt = NULL;
struct reftable_log_record *logs = NULL;
struct reftable_iterator it = {0};
size_t logs_alloc = 0, logs_nr = 0, i;
@@ -1786,8 +1847,8 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
if (refs->err < 0)
return refs->err;
- mt = reftable_stack_merged_table(stack);
- ret = reftable_merged_table_seek_log(mt, &it, refname);
+ reftable_stack_init_log_iterator(stack, &it);
+ ret = reftable_iterator_seek_log(&it, refname);
while (!ret) {
struct reftable_log_record log = {0};
@@ -1824,7 +1885,6 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
struct reftable_ref_store *refs =
reftable_be_downcast(ref_store, REF_STORE_READ, "reflog_exists");
struct reftable_stack *stack = stack_for(refs, refname, &refname);
- struct reftable_merged_table *mt = reftable_stack_merged_table(stack);
struct reftable_log_record log = {0};
struct reftable_iterator it = {0};
int ret;
@@ -1837,7 +1897,8 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
if (ret < 0)
goto done;
- ret = reftable_merged_table_seek_log(mt, &it, refname);
+ reftable_stack_init_log_iterator(stack, &it);
+ ret = reftable_iterator_seek_log(&it, refname);
if (ret < 0)
goto done;
@@ -1935,8 +1996,6 @@ struct write_reflog_delete_arg {
static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_data)
{
struct write_reflog_delete_arg *arg = cb_data;
- struct reftable_merged_table *mt =
- reftable_stack_merged_table(arg->stack);
struct reftable_log_record log = {0}, tombstone = {0};
struct reftable_iterator it = {0};
uint64_t ts = reftable_stack_next_update_index(arg->stack);
@@ -1944,12 +2003,14 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da
reftable_writer_set_limits(writer, ts, ts);
+ reftable_stack_init_log_iterator(arg->stack, &it);
+
/*
* In order to delete a table we need to delete all reflog entries one
* by one. This is inefficient, but the reftable format does not have a
* better marker right now.
*/
- ret = reftable_merged_table_seek_log(mt, &it, arg->refname);
+ ret = reftable_iterator_seek_log(&it, arg->refname);
while (ret == 0) {
ret = reftable_iterator_next_log(&it, &log);
if (ret < 0)
@@ -1993,6 +2054,7 @@ static int reftable_be_delete_reflog(struct ref_store *ref_store,
}
struct reflog_expiry_arg {
+ struct reftable_ref_store *refs;
struct reftable_stack *stack;
struct reftable_log_record *records;
struct object_id update_oid;
@@ -2021,7 +2083,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->update_oid, &peeled)) {
+ if (!peel_object(arg->refs->base.repo, &arg->update_oid, &peeled)) {
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);
@@ -2085,7 +2147,6 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
struct reftable_ref_store *refs =
reftable_be_downcast(ref_store, REF_STORE_WRITE, "reflog_expire");
struct reftable_stack *stack = stack_for(refs, refname, &refname);
- struct reftable_merged_table *mt = reftable_stack_merged_table(stack);
struct reftable_log_record *logs = NULL;
struct reftable_log_record *rewritten = NULL;
struct reftable_ref_record ref_record = {0};
@@ -2104,7 +2165,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
if (ret < 0)
goto done;
- ret = reftable_merged_table_seek_log(mt, &it, refname);
+ reftable_stack_init_log_iterator(stack, &it);
+
+ ret = reftable_iterator_seek_log(&it, refname);
if (ret < 0)
goto done;
@@ -2183,6 +2246,7 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
reftable_ref_record_val1(&ref_record))
oidread(&arg.update_oid, last_hash);
+ arg.refs = refs;
arg.records = rewritten;
arg.len = logs_nr;
arg.stack = stack,
@@ -2217,14 +2281,16 @@ done:
struct ref_storage_be refs_be_reftable = {
.name = "reftable",
.init = reftable_be_init,
- .init_db = reftable_be_init_db,
+ .release = reftable_be_release,
+ .create_on_disk = reftable_be_create_on_disk,
+ .remove_on_disk = reftable_be_remove_on_disk,
+
.transaction_prepare = reftable_be_transaction_prepare,
.transaction_finish = reftable_be_transaction_finish,
.transaction_abort = reftable_be_transaction_abort,
.initial_transaction_commit = reftable_be_initial_transaction_commit,
.pack_refs = reftable_be_pack_refs,
- .create_symref = reftable_be_create_symref,
.rename_ref = reftable_be_rename_ref,
.copy_ref = reftable_be_copy_ref,