summaryrefslogtreecommitdiff
path: root/refs/files-backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'refs/files-backend.c')
-rw-r--r--refs/files-backend.c81
1 files changed, 66 insertions, 15 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c
index b859ddb4d0..1adc4b5182 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"
@@ -1528,6 +1527,15 @@ static int files_pack_refs(struct ref_store *ref_store,
return 0;
}
+static int files_optimize(struct ref_store *ref_store, struct pack_refs_opts *opts)
+{
+ /*
+ * For the "files" backend, "optimizing" is the same as "packing".
+ * So, we just call the existing worker function for packing.
+ */
+ return files_pack_refs(ref_store, opts);
+}
+
/*
* People using contrib's git-new-workdir have .git/logs/refs ->
* /some/other/path/.git/logs/refs, and that may live on another device.
@@ -2105,20 +2113,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 +2193,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 +2222,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 +2306,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 +2318,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 +2368,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;
@@ -2568,13 +2593,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 +2762,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 +2795,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;
}
@@ -3420,7 +3471,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 +3990,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);
}
@@ -3966,6 +4016,7 @@ struct ref_storage_be refs_be_files = {
.transaction_abort = files_transaction_abort,
.pack_refs = files_pack_refs,
+ .optimize = files_optimize,
.rename_ref = files_rename_ref,
.copy_ref = files_copy_ref,