summaryrefslogtreecommitdiff
path: root/refs
diff options
context:
space:
mode:
Diffstat (limited to 'refs')
-rw-r--r--refs/debug.c18
-rw-r--r--refs/files-backend.c124
-rw-r--r--refs/packed-backend.c23
-rw-r--r--refs/packed-backend.h4
-rw-r--r--refs/ref-cache.c10
-rw-r--r--refs/ref-cache.h1
-rw-r--r--refs/refs-internal.h17
7 files changed, 115 insertions, 82 deletions
diff --git a/refs/debug.c b/refs/debug.c
index 8667c64023..2b0771ca53 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -26,7 +26,8 @@ struct ref_store *maybe_debug_wrap_ref_store(const char *gitdir, struct ref_stor
be_copy->name = store->be->name;
trace_printf_key(&trace_refs, "ref_store for %s\n", gitdir);
res->refs = store;
- base_ref_store_init((struct ref_store *)res, be_copy);
+ base_ref_store_init((struct ref_store *)res, store->repo, gitdir,
+ be_copy);
return (struct ref_store *)res;
}
@@ -47,7 +48,8 @@ static int debug_transaction_prepare(struct ref_store *refs,
transaction->ref_store = drefs->refs;
res = drefs->refs->be->transaction_prepare(drefs->refs, transaction,
err);
- trace_printf_key(&trace_refs, "transaction_prepare: %d\n", res);
+ trace_printf_key(&trace_refs, "transaction_prepare: %d \"%s\"\n", res,
+ err->buf);
return res;
}
@@ -284,6 +286,7 @@ static int debug_print_reflog_ent(struct object_id *old_oid,
int ret;
char o[GIT_MAX_HEXSZ + 1] = "null";
char n[GIT_MAX_HEXSZ + 1] = "null";
+ char *msgend = strchrnul(msg, '\n');
if (old_oid)
oid_to_hex_r(o, old_oid);
if (new_oid)
@@ -291,8 +294,10 @@ static int debug_print_reflog_ent(struct object_id *old_oid,
ret = dbg->fn(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",
- dbg->refname, ret, o, n, committer, (long int)timestamp, msg);
+ trace_printf_key(&trace_refs,
+ "reflog_ent %s (ret %d): %s -> %s, %s %ld \"%.*s\"\n",
+ dbg->refname, ret, o, n, committer,
+ (long int)timestamp, (int)(msgend - msg), msg);
return ret;
}
@@ -339,11 +344,10 @@ static int debug_reflog_exists(struct ref_store *ref_store, const char *refname)
}
static int debug_create_reflog(struct ref_store *ref_store, const char *refname,
- int force_create, struct strbuf *err)
+ struct strbuf *err)
{
struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
- int res = drefs->refs->be->create_reflog(drefs->refs, refname,
- force_create, err);
+ int res = drefs->refs->be->create_reflog(drefs->refs, refname, err);
trace_printf_key(&trace_refs, "create_reflog: %s: %d\n", refname, res);
return res;
}
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 4bb4de72b6..43a3b882d7 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -16,8 +16,7 @@
* This backend uses the following flags in `ref_update::flags` for
* internal bookkeeping purposes. Their numerical values must not
* conflict with REF_NO_DEREF, REF_FORCE_CREATE_REFLOG, REF_HAVE_NEW,
- * REF_HAVE_OLD, or REF_IS_PRUNING, which are also stored in
- * `ref_update::flags`.
+ * or REF_HAVE_OLD, which are also stored in `ref_update::flags`.
*/
/*
@@ -79,22 +78,20 @@ static void clear_loose_ref_cache(struct files_ref_store *refs)
* Create a new submodule ref cache and add it to the internal
* set of caches.
*/
-static struct ref_store *files_ref_store_create(const char *gitdir,
+static struct ref_store *files_ref_store_create(struct repository *repo,
+ const char *gitdir,
unsigned int flags)
{
struct files_ref_store *refs = xcalloc(1, sizeof(*refs));
struct ref_store *ref_store = (struct ref_store *)refs;
struct strbuf sb = STRBUF_INIT;
- ref_store->gitdir = xstrdup(gitdir);
- base_ref_store_init(ref_store, &refs_be_files);
+ base_ref_store_init(ref_store, repo, gitdir, &refs_be_files);
refs->store_flags = flags;
-
get_common_dir_noenv(&sb, gitdir);
refs->gitcommondir = strbuf_detach(&sb, NULL);
- strbuf_addf(&sb, "%s/packed-refs", refs->gitcommondir);
- refs->packed_ref_store = packed_ref_store_create(sb.buf, flags);
- strbuf_release(&sb);
+ refs->packed_ref_store =
+ packed_ref_store_create(repo, refs->gitcommondir, flags);
chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir);
chdir_notify_reparent("files-backend $GIT_COMMONDIR",
@@ -741,6 +738,7 @@ struct files_ref_iterator {
struct ref_iterator base;
struct ref_iterator *iter0;
+ struct repository *repo;
unsigned int flags;
};
@@ -762,6 +760,7 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
!ref_resolves_to_object(iter->iter0->refname,
+ iter->repo,
iter->iter0->oid,
iter->iter0->flags))
continue;
@@ -840,7 +839,7 @@ static struct ref_iterator *files_ref_iterator_begin(
*/
loose_iter = cache_ref_iterator_begin(get_loose_ref_cache(refs),
- prefix, 1);
+ prefix, ref_store->repo, 1);
/*
* The packed-refs file might contain broken references, for
@@ -864,6 +863,7 @@ static struct ref_iterator *files_ref_iterator_begin(
base_ref_iterator_init(ref_iterator, &files_ref_iterator_vtable,
overlay_iter->ordered);
iter->iter0 = overlay_iter;
+ iter->repo = ref_store->repo;
iter->flags = flags;
return ref_iterator;
@@ -1170,7 +1170,7 @@ static int should_pack_ref(const char *refname,
return 0;
/* Do not pack broken refs: */
- if (!ref_resolves_to_object(refname, oid, ref_flags))
+ if (!ref_resolves_to_object(refname, the_repository, oid, ref_flags))
return 0;
return 1;
@@ -1193,7 +1193,8 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
packed_refs_lock(refs->packed_ref_store, LOCK_DIE_ON_ERROR, &err);
- iter = cache_ref_iterator_begin(get_loose_ref_cache(refs), NULL, 0);
+ iter = cache_ref_iterator_begin(get_loose_ref_cache(refs), NULL,
+ the_repository, 0);
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
/*
* If the loose reference can be packed, add an entry
@@ -1347,7 +1348,8 @@ static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname)
}
static int write_ref_to_lockfile(struct ref_lock *lock,
- const struct object_id *oid, struct strbuf *err);
+ const struct object_id *oid,
+ int skip_oid_verification, struct strbuf *err);
static int commit_ref_update(struct files_ref_store *refs,
struct ref_lock *lock,
const struct object_id *oid, const char *logmsg,
@@ -1494,7 +1496,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
}
oidcpy(&lock->old_oid, &orig_oid);
- if (write_ref_to_lockfile(lock, &orig_oid, &err) ||
+ if (write_ref_to_lockfile(lock, &orig_oid, 0, &err) ||
commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) {
error("unable to write current sha1 into %s: %s", newrefname, err.buf);
strbuf_release(&err);
@@ -1514,7 +1516,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
flag = log_all_ref_updates;
log_all_ref_updates = LOG_REFS_NONE;
- if (write_ref_to_lockfile(lock, &orig_oid, &err) ||
+ if (write_ref_to_lockfile(lock, &orig_oid, 0, &err) ||
commit_ref_update(refs, lock, &orig_oid, NULL, &err)) {
error("unable to write current sha1 into %s: %s", oldrefname, err.buf);
strbuf_release(&err);
@@ -1664,15 +1666,14 @@ error:
return -1;
}
-static int files_create_reflog(struct ref_store *ref_store,
- const char *refname, int force_create,
+static int files_create_reflog(struct ref_store *ref_store, const char *refname,
struct strbuf *err)
{
struct files_ref_store *refs =
files_downcast(ref_store, REF_STORE_WRITE, "create_reflog");
int fd;
- if (log_ref_setup(refs, refname, force_create, &fd, err))
+ if (log_ref_setup(refs, refname, 1, &fd, err))
return -1;
if (fd >= 0)
@@ -1750,26 +1751,31 @@ static int files_log_ref_write(struct files_ref_store *refs,
* errors, rollback the lockfile, fill in *err and return -1.
*/
static int write_ref_to_lockfile(struct ref_lock *lock,
- const struct object_id *oid, struct strbuf *err)
+ const struct object_id *oid,
+ int skip_oid_verification, struct strbuf *err)
{
static char term = '\n';
struct object *o;
int fd;
- o = parse_object(the_repository, oid);
- if (!o) {
- strbuf_addf(err,
- "trying to write ref '%s' with nonexistent object %s",
- lock->ref_name, oid_to_hex(oid));
- unlock_ref(lock);
- return -1;
- }
- if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {
- strbuf_addf(err,
- "trying to write non-commit object %s to branch '%s'",
- oid_to_hex(oid), lock->ref_name);
- unlock_ref(lock);
- return -1;
+ if (!skip_oid_verification) {
+ o = parse_object(the_repository, oid);
+ if (!o) {
+ strbuf_addf(
+ err,
+ "trying to write ref '%s' with nonexistent object %s",
+ lock->ref_name, oid_to_hex(oid));
+ unlock_ref(lock);
+ return -1;
+ }
+ if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {
+ strbuf_addf(
+ err,
+ "trying to write non-commit object %s to branch '%s'",
+ oid_to_hex(oid), lock->ref_name);
+ unlock_ref(lock);
+ return -1;
+ }
}
fd = get_lock_file_fd(&lock->lk);
if (write_in_full(fd, oid_to_hex(oid), the_hash_algo->hexsz) < 0 ||
@@ -2183,7 +2189,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
}
static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
+ struct object_id *peeled)
{
BUG("ref_iterator_peel() called for reflog_iterator");
}
@@ -2569,8 +2575,10 @@ static int lock_ref_for_update(struct files_ref_store *refs,
* The reference already has the desired
* value, so we don't need to write it.
*/
- } else if (write_ref_to_lockfile(lock, &update->new_oid,
- err)) {
+ } else if (write_ref_to_lockfile(
+ lock, &update->new_oid,
+ update->flags & REF_SKIP_OID_VERIFICATION,
+ err)) {
char *write_err = strbuf_detach(err, NULL);
/*
@@ -3073,11 +3081,12 @@ cleanup:
}
struct expire_reflog_cb {
- unsigned int flags;
reflog_expiry_should_prune_fn *should_prune_fn;
void *policy_cb;
FILE *newlog;
struct object_id last_kept_oid;
+ unsigned int rewrite:1,
+ dry_run:1;
};
static int expire_reflog_ent(struct object_id *ooid, struct object_id *noid,
@@ -3085,33 +3094,27 @@ static int expire_reflog_ent(struct object_id *ooid, struct object_id *noid,
const char *message, void *cb_data)
{
struct expire_reflog_cb *cb = cb_data;
- struct expire_reflog_policy_cb *policy_cb = cb->policy_cb;
+ reflog_expiry_should_prune_fn *fn = cb->should_prune_fn;
- if (cb->flags & EXPIRE_REFLOGS_REWRITE)
+ if (cb->rewrite)
ooid = &cb->last_kept_oid;
- if ((*cb->should_prune_fn)(ooid, noid, email, timestamp, tz,
- message, policy_cb)) {
- if (!cb->newlog)
- printf("would prune %s", message);
- else if (cb->flags & EXPIRE_REFLOGS_VERBOSE)
- printf("prune %s", message);
- } else {
- if (cb->newlog) {
- fprintf(cb->newlog, "%s %s %s %"PRItime" %+05d\t%s",
- oid_to_hex(ooid), oid_to_hex(noid),
- email, timestamp, tz, message);
- oidcpy(&cb->last_kept_oid, noid);
- }
- if (cb->flags & EXPIRE_REFLOGS_VERBOSE)
- printf("keep %s", message);
- }
+ if (fn(ooid, noid, email, timestamp, tz, message, cb->policy_cb))
+ return 0;
+
+ if (cb->dry_run)
+ return 0; /* --dry-run */
+
+ fprintf(cb->newlog, "%s %s %s %"PRItime" %+05d\t%s", oid_to_hex(ooid),
+ oid_to_hex(noid), email, timestamp, tz, message);
+ oidcpy(&cb->last_kept_oid, noid);
+
return 0;
}
static int files_reflog_expire(struct ref_store *ref_store,
const char *refname,
- unsigned int flags,
+ unsigned int expire_flags,
reflog_expiry_prepare_fn prepare_fn,
reflog_expiry_should_prune_fn should_prune_fn,
reflog_expiry_cleanup_fn cleanup_fn,
@@ -3129,7 +3132,8 @@ static int files_reflog_expire(struct ref_store *ref_store,
const struct object_id *oid;
memset(&cb, 0, sizeof(cb));
- cb.flags = flags;
+ cb.rewrite = !!(expire_flags & EXPIRE_REFLOGS_REWRITE);
+ cb.dry_run = !!(expire_flags & EXPIRE_REFLOGS_DRY_RUN);
cb.policy_cb = policy_cb_data;
cb.should_prune_fn = should_prune_fn;
@@ -3165,7 +3169,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
files_reflog_path(refs, &log_file_sb, refname);
log_file = strbuf_detach(&log_file_sb, NULL);
- if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) {
+ if (!cb.dry_run) {
/*
* Even though holding $GIT_DIR/logs/$reflog.lock has
* no locking implications, we use the lock_file
@@ -3192,7 +3196,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
refs_for_each_reflog_ent(ref_store, refname, expire_reflog_ent, &cb);
(*cleanup_fn)(cb.policy_cb);
- if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) {
+ if (!cb.dry_run) {
/*
* It doesn't make sense to adjust a reference pointed
* to by a symbolic ref based on expiring entries in
@@ -3202,7 +3206,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
*/
int update = 0;
- if ((flags & EXPIRE_REFLOGS_UPDATE_REF) &&
+ if ((expire_flags & EXPIRE_REFLOGS_UPDATE_REF) &&
!is_null_oid(&cb.last_kept_oid)) {
int ignore_errno;
int type;
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 52cdc94a26..d91a2018f6 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -193,19 +193,20 @@ static int release_snapshot(struct snapshot *snapshot)
}
}
-struct ref_store *packed_ref_store_create(const char *path,
+struct ref_store *packed_ref_store_create(struct repository *repo,
+ const char *gitdir,
unsigned int store_flags)
{
struct packed_ref_store *refs = xcalloc(1, sizeof(*refs));
struct ref_store *ref_store = (struct ref_store *)refs;
+ struct strbuf sb = STRBUF_INIT;
- base_ref_store_init(ref_store, &refs_be_packed);
- ref_store->gitdir = xstrdup(path);
+ base_ref_store_init(ref_store, repo, gitdir, &refs_be_packed);
refs->store_flags = store_flags;
- refs->path = xstrdup(path);
+ strbuf_addf(&sb, "%s/packed-refs", gitdir);
+ refs->path = strbuf_detach(&sb, NULL);
chdir_notify_reparent("packed-refs", &refs->path);
-
return ref_store;
}
@@ -776,6 +777,7 @@ struct packed_ref_iterator {
struct object_id oid, peeled;
struct strbuf refname_buf;
+ struct repository *repo;
unsigned int flags;
};
@@ -864,8 +866,8 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
continue;
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
- !ref_resolves_to_object(iter->base.refname, &iter->oid,
- iter->flags))
+ !ref_resolves_to_object(iter->base.refname, iter->repo,
+ &iter->oid, iter->flags))
continue;
return ITER_OK;
@@ -883,6 +885,9 @@ static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
struct packed_ref_iterator *iter =
(struct packed_ref_iterator *)ref_iterator;
+ if (iter->repo != the_repository)
+ BUG("peeling for non-the_repository is not supported");
+
if ((iter->base.flags & REF_KNOWS_PEELED)) {
oidcpy(peeled, &iter->peeled);
return is_null_oid(&iter->peeled) ? -1 : 0;
@@ -954,6 +959,7 @@ static struct ref_iterator *packed_ref_iterator_begin(
iter->base.oid = &iter->oid;
+ iter->repo = ref_store->repo;
iter->flags = flags;
if (prefix && *prefix)
@@ -1622,8 +1628,7 @@ static int packed_reflog_exists(struct ref_store *ref_store,
}
static int packed_create_reflog(struct ref_store *ref_store,
- const char *refname, int force_create,
- struct strbuf *err)
+ const char *refname, struct strbuf *err)
{
BUG("packed reference store does not support reflogs");
}
diff --git a/refs/packed-backend.h b/refs/packed-backend.h
index a01a0aff9c..9dd8a344c3 100644
--- a/refs/packed-backend.h
+++ b/refs/packed-backend.h
@@ -1,6 +1,7 @@
#ifndef REFS_PACKED_BACKEND_H
#define REFS_PACKED_BACKEND_H
+struct repository;
struct ref_transaction;
/*
@@ -12,7 +13,8 @@ struct ref_transaction;
* even among packed refs.
*/
-struct ref_store *packed_ref_store_create(const char *path,
+struct ref_store *packed_ref_store_create(struct repository *repo,
+ const char *gitdir,
unsigned int store_flags);
/*
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index a5ad8a39fb..be4aa5e098 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -378,6 +378,8 @@ struct cache_ref_iterator {
* on from there.)
*/
struct cache_ref_iterator_level *levels;
+
+ struct repository *repo;
};
static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
@@ -434,6 +436,11 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
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;
+
+ if (iter->repo != the_repository)
+ BUG("peeling for non-the_repository is not supported");
return peel_object(ref_iterator->oid, peeled) ? -1 : 0;
}
@@ -456,6 +463,7 @@ static struct ref_iterator_vtable cache_ref_iterator_vtable = {
struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
const char *prefix,
+ struct repository *repo,
int prime_dir)
{
struct ref_dir *dir;
@@ -490,5 +498,7 @@ struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
level->prefix_state = PREFIX_CONTAINS_DIR;
}
+ iter->repo = repo;
+
return ref_iterator;
}
diff --git a/refs/ref-cache.h b/refs/ref-cache.h
index 5c042ae718..850d9d3744 100644
--- a/refs/ref-cache.h
+++ b/refs/ref-cache.h
@@ -214,6 +214,7 @@ struct ref_entry *find_ref_entry(struct ref_dir *dir, const char *refname);
*/
struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
const char *prefix,
+ struct repository *repo,
int prime_dir);
#endif /* REFS_REF_CACHE_H */
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 2ecd3dea9f..7ff6fba4f0 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -66,6 +66,7 @@ int refname_is_safe(const char *refname);
* referred-to object does not exist, emit a warning and return false.
*/
int ref_resolves_to_object(const char *refname,
+ struct repository *repo,
const struct object_id *oid,
unsigned int flags);
@@ -525,7 +526,8 @@ struct ref_store;
* should call base_ref_store_init() to initialize the shared part of
* the ref_store and to record the ref_store for later lookup.
*/
-typedef struct ref_store *ref_store_init_fn(const char *gitdir,
+typedef struct ref_store *ref_store_init_fn(struct repository *repo,
+ const char *gitdir,
unsigned int flags);
typedef int ref_init_db_fn(struct ref_store *refs, struct strbuf *err);
@@ -590,7 +592,7 @@ typedef int for_each_reflog_ent_reverse_fn(struct ref_store *ref_store,
void *cb_data);
typedef int reflog_exists_fn(struct ref_store *ref_store, const char *refname);
typedef int create_reflog_fn(struct ref_store *ref_store, const char *refname,
- int force_create, struct strbuf *err);
+ struct strbuf *err);
typedef int delete_reflog_fn(struct ref_store *ref_store, const char *refname);
typedef int reflog_expire_fn(struct ref_store *ref_store,
const char *refname,
@@ -687,7 +689,12 @@ struct ref_store {
/* The backend describing this ref_store's storage scheme: */
const struct ref_storage_be *be;
- /* The gitdir that this ref_store applies to: */
+ struct repository *repo;
+
+ /*
+ * The gitdir that this ref_store applies to. Note that this is not
+ * necessarily repo->gitdir if the repo has multiple worktrees.
+ */
char *gitdir;
};
@@ -703,8 +710,8 @@ int parse_loose_ref_contents(const char *buf, struct object_id *oid,
* Fill in the generic part of refs and add it to our collection of
* reference stores.
*/
-void base_ref_store_init(struct ref_store *refs,
- const struct ref_storage_be *be);
+void base_ref_store_init(struct ref_store *refs, struct repository *repo,
+ const char *path, const struct ref_storage_be *be);
/*
* Support GIT_TRACE_REFS by optionally wrapping the given ref_store instance.