summaryrefslogtreecommitdiff
path: root/refs/files-backend.c
diff options
context:
space:
mode:
authorshejialuo <shejialuo@gmail.com>2024-11-20 19:52:18 +0800
committerJunio C Hamano <gitster@pobox.com>2024-11-21 08:21:34 +0900
commitc9f03f38821ee4472a137a3272bf6ddd7037f5fd (patch)
tree63fb7b5a76adf5512f2a3c4bbba53780dd4e921c /refs/files-backend.c
parentd996b4475c7a49e568c22ffd4217d8dba8352fcb (diff)
ref: add symlink ref content check for files backend
Besides the textual symref, we also allow symbolic links as the symref. So, we should also provide the consistency check as what we have done for textual symref. And also we consider deprecating writing the symbolic links. We first need to access whether symbolic links still be used. So, add a new fsck message "symlinkRef(INFO)" to tell the user be aware of this information. We have already introduced "files_fsck_symref_target". We should reuse this function to handle the symrefs which use legacy symbolic links. We should not check the trailing garbage for symbolic refs. Add a new parameter "symbolic_link" to disable some checks which should only be executed for textual symrefs. And we need to also generate the "referent" parameter for reusing "files_fsck_symref_target" by the following steps: 1. Use "strbuf_add_real_path" to resolve the symlink and get the absolute path "ref_content" which the symlink ref points to. 2. Generate the absolute path "abs_gitdir" of "gitdir" and combine "ref_content" and "abs_gitdir" to extract the relative path "relative_referent_path". 3. If "ref_content" is outside of "gitdir", we just set "referent" with "ref_content". Instead, we set "referent" with "relative_referent_path". Mentored-by: Patrick Steinhardt <ps@pks.im> Mentored-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: shejialuo <shejialuo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs/files-backend.c')
-rw-r--r--refs/files-backend.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c
index c2b99fdf40..ea5961e48c 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1,6 +1,7 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "../git-compat-util.h"
+#include "../abspath.h"
#include "../config.h"
#include "../copy.h"
#include "../environment.h"
@@ -3511,7 +3512,8 @@ typedef int (*files_fsck_refs_fn)(struct ref_store *ref_store,
static int files_fsck_symref_target(struct fsck_options *o,
struct fsck_ref_report *report,
- struct strbuf *referent)
+ struct strbuf *referent,
+ unsigned int symbolic_link)
{
int is_referent_root;
char orig_last_byte;
@@ -3520,7 +3522,8 @@ static int files_fsck_symref_target(struct fsck_options *o,
orig_len = referent->len;
orig_last_byte = referent->buf[orig_len - 1];
- strbuf_rtrim(referent);
+ if (!symbolic_link)
+ strbuf_rtrim(referent);
is_referent_root = is_root_ref(referent->buf);
if (!is_referent_root &&
@@ -3539,6 +3542,9 @@ static int files_fsck_symref_target(struct fsck_options *o,
goto out;
}
+ if (symbolic_link)
+ goto out;
+
if (referent->len == orig_len ||
(referent->len < orig_len && orig_last_byte != '\n')) {
ret = fsck_report_ref(o, report,
@@ -3562,6 +3568,7 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
struct dir_iterator *iter)
{
struct strbuf ref_content = STRBUF_INIT;
+ struct strbuf abs_gitdir = STRBUF_INIT;
struct strbuf referent = STRBUF_INIT;
struct fsck_ref_report report = { 0 };
const char *trailing = NULL;
@@ -3572,8 +3579,30 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
report.path = target_name;
- if (S_ISLNK(iter->st.st_mode))
+ if (S_ISLNK(iter->st.st_mode)) {
+ const char *relative_referent_path = NULL;
+
+ ret = fsck_report_ref(o, &report,
+ FSCK_MSG_SYMLINK_REF,
+ "use deprecated symbolic link for symref");
+
+ strbuf_add_absolute_path(&abs_gitdir, ref_store->repo->gitdir);
+ strbuf_normalize_path(&abs_gitdir);
+ if (!is_dir_sep(abs_gitdir.buf[abs_gitdir.len - 1]))
+ strbuf_addch(&abs_gitdir, '/');
+
+ strbuf_add_real_path(&ref_content, iter->path.buf);
+ skip_prefix(ref_content.buf, abs_gitdir.buf,
+ &relative_referent_path);
+
+ if (relative_referent_path)
+ strbuf_addstr(&referent, relative_referent_path);
+ else
+ strbuf_addbuf(&referent, &ref_content);
+
+ ret |= files_fsck_symref_target(o, &report, &referent, 1);
goto cleanup;
+ }
if (strbuf_read_file(&ref_content, iter->path.buf, 0) < 0) {
/*
@@ -3611,13 +3640,14 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
goto cleanup;
}
} else {
- ret = files_fsck_symref_target(o, &report, &referent);
+ ret = files_fsck_symref_target(o, &report, &referent, 0);
goto cleanup;
}
cleanup:
strbuf_release(&ref_content);
strbuf_release(&referent);
+ strbuf_release(&abs_gitdir);
return ret;
}