FUNC(BAD_EMAIL, ERROR) \
FUNC(BAD_NAME, ERROR) \
FUNC(BAD_OBJECT_SHA1, ERROR) \
+ FUNC(BAD_PACKED_REF_HEADER, ERROR) \
FUNC(BAD_PARENT_SHA1, ERROR) \
FUNC(BAD_REF_CONTENT, ERROR) \
FUNC(BAD_REF_FILETYPE, ERROR) \
FUNC(MISSING_TYPE, ERROR) \
FUNC(MISSING_TYPE_ENTRY, ERROR) \
FUNC(MULTIPLE_AUTHORS, ERROR) \
+ FUNC(PACKED_REF_ENTRY_NOT_TERMINATED, ERROR) \
FUNC(TREE_NOT_SORTED, ERROR) \
FUNC(UNKNOWN_TYPE, ERROR) \
FUNC(ZERO_PADDED_DATE, ERROR) \
return empty_ref_iterator_begin();
}
+static int packed_fsck_ref_next_line(struct fsck_options *o,
+ unsigned long line_number, const char *start,
+ const char *eof, const char **eol)
+{
+ int ret = 0;
+
+ *eol = memchr(start, '\n', eof - start);
+ if (!*eol) {
+ struct strbuf packed_entry = STRBUF_INIT;
+ struct fsck_ref_report report = { 0 };
+
+ strbuf_addf(&packed_entry, "packed-refs line %lu", line_number);
+ report.path = packed_entry.buf;
+ ret = fsck_report_ref(o, &report,
+ FSCK_MSG_PACKED_REF_ENTRY_NOT_TERMINATED,
+ "'%.*s' is not terminated with a newline",
+ (int)(eof - start), start);
+
+ /*
+ * There is no newline but we still want to parse it to the end of
+ * the buffer.
+ */
+ *eol = eof;
+ strbuf_release(&packed_entry);
+ }
+
+ return ret;
+}
+
+static int packed_fsck_ref_header(struct fsck_options *o,
+ const char *start, const char *eol)
+{
+ if (!starts_with(start, "# pack-refs with: ")) {
+ struct fsck_ref_report report = { 0 };
+ report.path = "packed-refs.header";
+
+ return fsck_report_ref(o, &report,
+ FSCK_MSG_BAD_PACKED_REF_HEADER,
+ "'%.*s' does not start with '# pack-refs with: '",
+ (int)(eol - start), start);
+ }
+
+ return 0;
+}
+
+static int packed_fsck_ref_content(struct fsck_options *o,
+ const char *start, const char *eof)
+{
+ unsigned long line_number = 1;
+ const char *eol;
+ int ret = 0;
+
+ ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol);
+ if (*start == '#') {
+ ret |= packed_fsck_ref_header(o, start, eol);
+
+ start = eol + 1;
+ line_number++;
+ }
+
+ return ret;
+}
+
static int packed_fsck(struct ref_store *ref_store,
struct fsck_options *o,
struct worktree *wt)
{
struct packed_ref_store *refs = packed_downcast(ref_store,
REF_STORE_READ, "fsck");
+ struct strbuf packed_ref_content = STRBUF_INIT;
struct stat st;
int ret = 0;
int fd = -1;
goto cleanup;
}
+ if (strbuf_read(&packed_ref_content, fd, 0) < 0) {
+ ret = error_errno(_("unable to read '%s'"), refs->path);
+ goto cleanup;
+ }
+
+ ret = packed_fsck_ref_content(o, packed_ref_content.buf,
+ packed_ref_content.buf + packed_ref_content.len);
+
cleanup:
if (fd >= 0)
close(fd);
+ strbuf_release(&packed_ref_content);
return ret;
}
)
'
+test_expect_success 'packed-refs header should be checked' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit default &&
+
+ git refs verify 2>err &&
+ test_must_be_empty err &&
+
+ for bad_header in "# pack-refs wit: peeled fully-peeled sorted " \
+ "# pack-refs with traits: peeled fully-peeled sorted " \
+ "# pack-refs with a: peeled fully-peeled" \
+ "# pack-refs with:peeled fully-peeled sorted"
+ do
+ printf "%s\n" "$bad_header" >.git/packed-refs &&
+ test_must_fail git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ error: packed-refs.header: badPackedRefHeader: '\''$bad_header'\'' does not start with '\''# pack-refs with: '\''
+ EOF
+ rm .git/packed-refs &&
+ test_cmp expect err || return 1
+ done
+ )
+'
+
+test_expect_success 'packed-refs missing header should not be reported' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit default &&
+
+ printf "$(git rev-parse HEAD) refs/heads/main\n" >.git/packed-refs &&
+ git refs verify 2>err &&
+ test_must_be_empty err
+ )
+'
+
+test_expect_success 'packed-refs unknown traits should not be reported' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit default &&
+
+ printf "# pack-refs with: peeled fully-peeled sorted foo\n" >.git/packed-refs &&
+ git refs verify 2>err &&
+ test_must_be_empty err
+ )
+'
+
test_done