diff options
Diffstat (limited to 'refs')
-rw-r--r-- | refs/debug.c | 6 | ||||
-rw-r--r-- | refs/files-backend.c | 114 | ||||
-rw-r--r-- | refs/packed-backend.c | 39 | ||||
-rw-r--r-- | refs/packed-backend.h | 9 | ||||
-rw-r--r-- | refs/refs-internal.h | 5 |
5 files changed, 93 insertions, 80 deletions
diff --git a/refs/debug.c b/refs/debug.c index 791423c6a7..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; } diff --git a/refs/files-backend.c b/refs/files-backend.c index 90b671025a..f59589d6cc 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -86,16 +86,12 @@ static struct ref_store *files_ref_store_create(struct repository *repo, struct ref_store *ref_store = (struct ref_store *)refs; struct strbuf sb = STRBUF_INIT; - ref_store->repo = repo; - 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(repo, 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", @@ -281,11 +277,10 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, create_dir_entry(dir->cache, refname.buf, refname.len)); } else { - int ignore_errno; if (!refs_resolve_ref_unsafe(&refs->base, refname.buf, RESOLVE_REF_READING, - &oid, &flag, &ignore_errno)) { + &oid, &flag)) { oidclr(&oid); flag |= REF_ISBROKEN; } else if (is_null_oid(&oid)) { @@ -386,7 +381,6 @@ stat_ref: if (lstat(path, &st) < 0) { int ignore_errno; myerr = errno; - errno = 0; if (myerr != ENOENT) goto out; if (refs_read_raw_ref(refs->packed_ref_store, refname, oid, @@ -403,7 +397,6 @@ stat_ref: strbuf_reset(&sb_contents); if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) { myerr = errno; - errno = 0; if (myerr == ENOENT || myerr == EINVAL) /* inconsistent with lstat; retry */ goto stat_ref; @@ -473,6 +466,7 @@ out: strbuf_release(&sb_path); strbuf_release(&sb_contents); + errno = 0; return ret; } @@ -1011,7 +1005,6 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, { struct strbuf ref_file = STRBUF_INIT; struct ref_lock *lock; - int ignore_errno; files_assert_main_repository(refs, "lock_ref_oid_basic"); assert(err); @@ -1039,7 +1032,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, } if (!refs_resolve_ref_unsafe(&refs->base, lock->ref_name, 0, - &lock->old_oid, NULL, &ignore_errno)) + &lock->old_oid, NULL)) oidclr(&lock->old_oid); goto out; @@ -1121,7 +1114,8 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r) if (check_refname_format(r->name, 0)) return; - transaction = ref_store_transaction_begin(&refs->base, &err); + transaction = ref_store_transaction_begin(&refs->base, + REF_TRANSACTION_SKIP_HOOK, &err); if (!transaction) goto cleanup; ref_transaction_add_update( @@ -1192,7 +1186,8 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags) struct strbuf err = STRBUF_INIT; struct ref_transaction *transaction; - transaction = ref_store_transaction_begin(refs->packed_ref_store, &err); + transaction = ref_store_transaction_begin(refs->packed_ref_store, + REF_TRANSACTION_SKIP_HOOK, &err); if (!transaction) return -1; @@ -1249,6 +1244,7 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg, { struct files_ref_store *refs = files_downcast(ref_store, REF_STORE_WRITE, "delete_refs"); + struct ref_transaction *transaction = NULL; struct strbuf err = STRBUF_INIT; int i, result = 0; @@ -1258,10 +1254,15 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg, if (packed_refs_lock(refs->packed_ref_store, 0, &err)) goto error; - if (refs_delete_refs(refs->packed_ref_store, msg, refnames, flags)) { - packed_refs_unlock(refs->packed_ref_store); + transaction = ref_store_transaction_begin(refs->packed_ref_store, + REF_TRANSACTION_SKIP_HOOK, &err); + if (!transaction) + goto error; + + result = packed_refs_delete_refs(refs->packed_ref_store, + transaction, msg, refnames, flags); + if (result) goto error; - } packed_refs_unlock(refs->packed_ref_store); @@ -1272,6 +1273,7 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg, result |= error(_("could not remove reference %s"), refname); } + ref_transaction_free(transaction); strbuf_release(&err); return result; @@ -1288,6 +1290,7 @@ error: else error(_("could not delete references: %s"), err.buf); + ref_transaction_free(transaction); strbuf_release(&err); return -1; } @@ -1404,7 +1407,6 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, struct strbuf tmp_renamed_log = STRBUF_INIT; int log, ret; struct strbuf err = STRBUF_INIT; - int ignore_errno; files_reflog_path(refs, &sb_oldref, oldrefname); files_reflog_path(refs, &sb_newref, newrefname); @@ -1418,7 +1420,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, if (!refs_resolve_ref_unsafe(&refs->base, oldrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, - &orig_oid, &flag, &ignore_errno)) { + &orig_oid, &flag)) { ret = error("refname %s not found", oldrefname); goto out; } @@ -1464,7 +1466,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, */ if (!copy && refs_resolve_ref_unsafe(&refs->base, newrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, - NULL, NULL, &ignore_errno) && + NULL, NULL) && refs_delete_ref(&refs->base, NULL, newrefname, NULL, REF_NO_DEREF)) { if (errno == EISDIR) { @@ -1833,12 +1835,10 @@ static int commit_ref_update(struct files_ref_store *refs, */ int head_flag; const char *head_ref; - int ignore_errno; head_ref = refs_resolve_ref_unsafe(&refs->base, "HEAD", RESOLVE_REF_READING, - NULL, &head_flag, - &ignore_errno); + NULL, &head_flag); if (head_ref && (head_flag & REF_ISSYMREF) && !strcmp(head_ref, lock->ref_name)) { struct strbuf log_err = STRBUF_INIT; @@ -1882,12 +1882,10 @@ static void update_symref_reflog(struct files_ref_store *refs, { struct strbuf err = STRBUF_INIT; struct object_id new_oid; - int ignore_errno; if (logmsg && refs_resolve_ref_unsafe(&refs->base, target, - RESOLVE_REF_READING, &new_oid, NULL, - &ignore_errno) && + RESOLVE_REF_READING, &new_oid, NULL) && files_log_ref_write(refs, refname, &lock->old_oid, &new_oid, logmsg, 0, &err)) { error("%s", err.buf); @@ -2161,7 +2159,6 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator) (struct files_reflog_iterator *)ref_iterator; struct dir_iterator *diter = iter->dir_iterator; int ok; - int ignore_errno; while ((ok = dir_iterator_advance(diter)) == ITER_OK) { int flags; @@ -2175,8 +2172,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator) if (!refs_resolve_ref_unsafe(iter->ref_store, diter->relative_path, 0, - &iter->oid, &flags, - &ignore_errno)) { + &iter->oid, &flags)) { error("bad ref for %s", diter->path.buf); continue; } @@ -2520,11 +2516,9 @@ static int lock_ref_for_update(struct files_ref_store *refs, * the transaction, so we have to read it here * to record and possibly check old_oid: */ - int ignore_errno; if (!refs_resolve_ref_unsafe(&refs->base, referent.buf, 0, - &lock->old_oid, NULL, - &ignore_errno)) { + &lock->old_oid, NULL)) { if (update->flags & REF_HAVE_OLD) { strbuf_addf(err, "cannot lock ref '%s': " "error reading reference", @@ -2767,7 +2761,8 @@ static int files_transaction_prepare(struct ref_store *ref_store, */ if (!packed_transaction) { packed_transaction = ref_store_transaction_begin( - refs->packed_ref_store, err); + refs->packed_ref_store, + REF_TRANSACTION_SKIP_HOOK, err); if (!packed_transaction) { ret = TRANSACTION_GENERIC_ERROR; goto cleanup; @@ -3038,7 +3033,8 @@ static int files_initial_transaction_commit(struct ref_store *ref_store, &affected_refnames)) BUG("initial ref transaction called with existing refs"); - packed_transaction = ref_store_transaction_begin(refs->packed_ref_store, err); + packed_transaction = ref_store_transaction_begin(refs->packed_ref_store, + REF_TRANSACTION_SKIP_HOOK, err); if (!packed_transaction) { ret = TRANSACTION_GENERIC_ERROR; goto cleanup; @@ -3086,11 +3082,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, @@ -3098,33 +3095,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, @@ -3142,7 +3133,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; @@ -3178,7 +3170,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 @@ -3205,7 +3197,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 @@ -3215,16 +3207,14 @@ 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; const char *ref; ref = refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_NO_RECURSE, - NULL, &type, - &ignore_errno); + NULL, &type); update = !!(ref && !(type & REF_ISSYMREF)); } diff --git a/refs/packed-backend.c b/refs/packed-backend.c index 67152c664e..27dd8c3922 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -194,20 +194,19 @@ static int release_snapshot(struct snapshot *snapshot) } struct ref_store *packed_ref_store_create(struct repository *repo, - const char *path, + 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->repo = repo; - 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; } @@ -1522,15 +1521,10 @@ static int packed_initial_transaction_commit(struct ref_store *ref_store, static int packed_delete_refs(struct ref_store *ref_store, const char *msg, struct string_list *refnames, unsigned int flags) { - struct packed_ref_store *refs = - packed_downcast(ref_store, REF_STORE_WRITE, "delete_refs"); struct strbuf err = STRBUF_INIT; struct ref_transaction *transaction; - struct string_list_item *item; int ret; - (void)refs; /* We need the check above, but don't use the variable */ - if (!refnames->nr) return 0; @@ -1540,10 +1534,30 @@ static int packed_delete_refs(struct ref_store *ref_store, const char *msg, * updates into a single transaction. */ - transaction = ref_store_transaction_begin(ref_store, &err); + transaction = ref_store_transaction_begin(ref_store, 0, &err); if (!transaction) return -1; + ret = packed_refs_delete_refs(ref_store, transaction, + msg, refnames, flags); + + ref_transaction_free(transaction); + return ret; +} + +int packed_refs_delete_refs(struct ref_store *ref_store, + struct ref_transaction *transaction, + const char *msg, + struct string_list *refnames, + unsigned int flags) +{ + struct strbuf err = STRBUF_INIT; + struct string_list_item *item; + int ret; + + /* Assert that the ref store refers to a packed backend. */ + packed_downcast(ref_store, REF_STORE_WRITE, "delete_refs"); + for_each_string_list_item(item, refnames) { if (ref_transaction_delete(transaction, item->string, NULL, flags, msg, &err)) { @@ -1563,7 +1577,6 @@ static int packed_delete_refs(struct ref_store *ref_store, const char *msg, error(_("could not delete references: %s"), err.buf); } - ref_transaction_free(transaction); strbuf_release(&err); return ret; } diff --git a/refs/packed-backend.h b/refs/packed-backend.h index f61a73ec25..52e0490753 100644 --- a/refs/packed-backend.h +++ b/refs/packed-backend.h @@ -3,6 +3,7 @@ struct repository; struct ref_transaction; +struct string_list; /* * Support for storing references in a `packed-refs` file. @@ -14,7 +15,7 @@ struct ref_transaction; */ struct ref_store *packed_ref_store_create(struct repository *repo, - const char *path, + const char *gitdir, unsigned int store_flags); /* @@ -27,6 +28,12 @@ int packed_refs_lock(struct ref_store *ref_store, int flags, struct strbuf *err) void packed_refs_unlock(struct ref_store *ref_store); int packed_refs_is_locked(struct ref_store *ref_store); +int packed_refs_delete_refs(struct ref_store *ref_store, + struct ref_transaction *transaction, + const char *msg, + struct string_list *refnames, + unsigned int flags); + /* * Return true if `transaction` really needs to be carried out against * the specified packed_ref_store, or false if it can be skipped diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 46a839539e..6e15db3ca4 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -213,6 +213,7 @@ struct ref_transaction { size_t nr; enum ref_transaction_state state; void *backend_data; + unsigned int flags; }; /* @@ -710,8 +711,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. |