* Re: [PATCH] mem-pool: fix big allocations
From: Phillip Wood @ 2023-12-28 15:10 UTC (permalink / raw)
To: René Scharfe, Git List; +Cc: Jameson Miller
In-Reply-To: <fa89d269-1a23-4ed6-bebc-30c0b629f444@web.de>
Hi René
On 21/12/2023 23:13, René Scharfe wrote:
> +#define check_ptr(a, op, b) check_int(((a) op (b)), ==, 1)
> [...]
> +static void t_calloc_100(struct mem_pool *pool)
> +{
> + size_t size = 100;
> + char *buffer = mem_pool_calloc(pool, 1, size);
> + for (size_t i = 0; i < size; i++)
> + check_int(buffer[i], ==, 0);
> + if (!check_ptr(pool->mp_block, !=, NULL))
> + return;
> + check_ptr(pool->mp_block->next_free, <=, pool->mp_block->end);
> + check_ptr(pool->mp_block->next_free, !=, NULL);
> + check_ptr(pool->mp_block->end, !=, NULL);
> +}
It's great to see the unit test framework being used here. I wonder
though if it would be simpler just to use
check(ptr != NULL)
as I'm not sure what the check_ptr() macro adds. The diff at the end of
this email shows a possible implementation of a check_ptr() macro for
the unit test library. I'm wary of adding it though because I'm not sure
printing the pointer values is actually very useful most of the
time. I'm also concerned that the rules around pointer arithmetic and
comparisons mean that many pointer tests such as
check_ptr(pool->mp_block->next_free, <=, pool->mp_block->end);
will be undefined if they fail. The documentation for check_ptr() below
tries to illustrate that concern. If the compiler can prove that a check
is undefined when that check fails it is at liberty to hard code the
test as passing. In practice I think most failing pointer comparisons
would fall into the category of "this is undefined but the compiler
can't prove it" but that doesn't really make me any happier.
Best Wishes
Phillip
---- >8 ----
diff --git a/t/unit-tests/test-lib.h b/t/unit-tests/test-lib.h
index a8f07ae0b7..ecd1fce17d 100644
--- a/t/unit-tests/test-lib.h
+++ b/t/unit-tests/test-lib.h
@@ -99,6 +99,39 @@ int check_int_loc(const char *loc, const char *check, int ok,
int check_uint_loc(const char *loc, const char *check, int ok,
uintmax_t a, uintmax_t b);
+/*
+ * Compare two pointers. Prints a message with the two values if the
+ * comparison fails. NB this is not thread safe.
+ *
+ * Use this with care. The rules around pointer arithmetic and comparison
+ * in C are quite strict and violating them results in undefined behavior
+ * To avoid a failing comparison resulting undefined behavior we compare
+ * the integer value of the pointers. While this avoids undefined
+ * behavior in the comparison in many cases a failing test will be the
+ * result of creating an invalid pointer in a way that violates the
+ * rules on pointer arithmetic. For example if `start` and `end` are
+ * pointers to the beginning and end of an allocation and `offset` is an
+ * integer then
+ *
+ * check_ptr(start + offset, <=, end)
+ *
+ * is undefined when `offset` is larger than `end - start`. Rewriting the
+ * comparison as
+ *
+ * check_uint(offset, <=, end - start)
+ *
+ * avoids undefined behavior when offset is too large, but is still
+ * undefined if there is a bug that means `start` and `end` do not point
+ * to the same allocation.
+ */
+#define check_ptr(a, op, b) \
+ (test__tmp[0].p = (a), test__tmp[1].p = (b), \
+ check_ptr_loc(TEST_LOCATION(), #a" "#op" "#b, \
+ (uintptr_t)test__tmp[0].p op (uintptr_t)test__tmp[1].p, \
+ test__tmp[0].p, test__tmp[1].p))
+
+int check_ptr_loc(const char *loc, const char *check, int ok, void *a, void *b);
+
/*
* Compare two chars. Prints a message with the two values if the
* comparison fails. NB this is not thread safe.
@@ -133,6 +166,7 @@ int check_str_loc(const char *loc, const char *check,
#define TEST__MAKE_LOCATION(line) __FILE__ ":" TEST__STR(line)
union test__tmp {
+ void *p;
intmax_t i;
uintmax_t u;
char c;
diff --git a/t/unit-tests/test-lib.c b/t/unit-tests/test-lib.c
index 7bf9dfdb95..cb757edbd8 100644
--- a/t/unit-tests/test-lib.c
+++ b/t/unit-tests/test-lib.c
@@ -311,6 +311,18 @@ int check_uint_loc(const char *loc, const char *check, int ok,
return ret;
}
+int check_ptr_loc(const char *loc, const char *check, int ok, void *a, void *b)
+{
+ int ret = test_assert(loc, check, ok);
+
+ if (!ret) {
+ test_msg(" left: %p", a);
+ test_msg(" right: %p", b);
+ }
+
+ return ret;
+}
+
static void print_one_char(char ch, char quote)
{
if ((unsigned char)ch < 0x20u || ch == 0x7f) {
^ permalink raw reply related
* Re: Git mirror at gitlab
From: Phillip Wood @ 2023-12-28 14:50 UTC (permalink / raw)
To: Patrick Steinhardt, Olliver Schinagl
Cc: git, gitster, Ævar Arnfjörð Bjarmason, psteinhardt
In-Reply-To: <ZY1YYtoIw4dIpZ6Q@tanuki>
On 28/12/2023 11:13, Patrick Steinhardt wrote:
> On Fri, Dec 22, 2023 at 03:06:08PM +0100, Olliver Schinagl wrote:
>> Hey Patrick,
>>
>> On December 21, 2023 12:48:12 p.m. GMT+01:00, Patrick Steinhardt <ps@pks.im> wrote:
>>> On Thu, Dec 21, 2023 at 12:30:02PM +0100, Olliver Schinagl wrote:
>>> Not to throw a wrench into this, but are you aware of the official
>>> GitLab mirror at https://gitlab.com/git-vcs/git? I myself wasn't aware
>>> of this mirror for a rather long time.
>>
>> Not a wrench at all, and no, I didn't know. How old is it though :p
>> could be that git-vcs was created cause I owned gitscm :)
>>
>> I had chosen gitscm to match the official site, git-scm.org. the
>> hyphen I left out because afaik it wasn't allowed on docker hub.
>
> No idea when exactly this mirror was created. The first mention of it in
> the "What's cooking" report is in December 2020, 489058b80d (What's
> cooking (2023/12 #05), 2023-12-27).
I think Ævar set it up towards the end of 2018 [1]. I think he used it
to do some testing using the gcc compile farm [2]
Best Wishes
Phillip
[1] https://lore.kernel.org/git/87k1mecj96.fsf@evledraar.gmail.com/
[2] https://lore.kernel.org/git/875zwm15k2.fsf@evledraar.gmail.com/
^ permalink raw reply
* [PATCH 1/1] Replace SID with domain/username
From: Sören Krecker @ 2023-12-28 13:28 UTC (permalink / raw)
To: git; +Cc: soekkle
In-Reply-To: <20231228132844.4240-1-soekkle@freenet.de>
From: soekkle <soekkle@freenet.de>
Replace SID with domain/username in erromessage, if owner of repository
and user are not equal on windows systems.
Signed-off-by: Sören Krecker <soekkle@freenet.de>
---
compat/mingw.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw.c
index 42053c1f65..7318f0e20e 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -2684,6 +2684,25 @@ static PSID get_current_user_sid(void)
return result;
}
+BOOL user_sid_to_string(PSID sid, LPSTR* str)
+{
+ SID_NAME_USE peUse;
+ DWORD lenName = { 0 }, lenDomain = { 0 };
+ LookupAccountSidA(NULL, sid, NULL, &lenName, NULL,
+ &lenDomain, &peUse); // returns only FALSE, because the string pointers are NULL
+ ALLOC_ARRAY((*str), (size_t)lenDomain + (size_t)lenName); // Alloc neded Space of the strings
+ BOOL retVal = LookupAccountSidA(NULL, sid, (*str) + lenDomain, &lenName,
+ *str,
+ &lenDomain, &peUse);
+ *(*str + lenDomain) = '/';
+ if (retVal == FALSE)
+ {
+ free(*str);
+ *str = NULL;
+ }
+ return retVal;
+}
+
static int acls_supported(const char *path)
{
size_t offset = offset_1st_component(path);
@@ -2767,7 +2786,7 @@ int is_path_owned_by_current_sid(const char *path, struct strbuf *report)
} else if (report) {
LPSTR str1, str2, to_free1 = NULL, to_free2 = NULL;
- if (ConvertSidToStringSidA(sid, &str1))
+ if (user_sid_to_string(sid, &str1))
to_free1 = str1;
else
str1 = "(inconvertible)";
@@ -2776,7 +2795,7 @@ int is_path_owned_by_current_sid(const char *path, struct strbuf *report)
str2 = "(none)";
else if (!IsValidSid(current_user_sid))
str2 = "(invalid)";
- else if (ConvertSidToStringSidA(current_user_sid, &str2))
+ else if (user_sid_to_string(current_user_sid, &str2))
to_free2 = str2;
else
str2 = "(inconvertible)";
@@ -2784,8 +2803,8 @@ int is_path_owned_by_current_sid(const char *path, struct strbuf *report)
"'%s' is owned by:\n"
"\t'%s'\nbut the current user is:\n"
"\t'%s'\n", path, str1, str2);
- LocalFree(to_free1);
- LocalFree(to_free2);
+ free(to_free1);
+ free(to_free2);
}
}
--
2.39.2
^ permalink raw reply related
* [PATCH 0/1] Replace SID with domain/username on Windows
From: Sören Krecker @ 2023-12-28 13:28 UTC (permalink / raw)
To: git; +Cc: Sören Krecker
*** BLURB HERE ***
soekkle (1):
Replace SID with domain/username
compat/mingw.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
base-commit: e79552d19784ee7f4bbce278fe25f93fbda196fa
--
2.39.2
^ permalink raw reply
* Re: [PATCH] sparse-checkout: be consistent with end of options markers
From: Jeff King @ 2023-12-28 11:43 UTC (permalink / raw)
To: Junio C Hamano
Cc: Elijah Newren via GitGitGadget, git, Randall S. Becker,
Elijah Newren
In-Reply-To: <xmqqfrzoj31l.fsf@gitster.g>
On Tue, Dec 26, 2023 at 09:18:14AM -0800, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
>
> > On Sun, Dec 24, 2023 at 01:00:11AM +0000, Elijah Newren via GitGitGadget wrote:
> >
> >> Remove the erroneous PARSE_OPT_KEEP_UNKNOWN_OPT flag now to fix this
> >> bug. Note that this does mean that anyone who might have been using
> >> [...]
> >
> > Thanks for wrapping this up in patch form. It looks good to me,
> > including the reasoning. You didn't add any tests, but I find it rather
> > unlikely that we'd later regress here.
>
> Surely. I am certainly OK with just dropping KEEP_UNKNOWN but I
> would strongly prefer to document what we "fixed" (your "misspelt
> option name" example) and what (mis|ab)use the people may have been
> relying on we have "broken" (the same "misspelt" behaviour that can
> be intentional is now forbidden, and we document that this change in
> behaviour is intentional) with a new test.
Yeah, thank you for talking some sense into me. I do not foresee us
regressing "--sikp-checks", but certainly covering --end-of-options in
more places is worthwhile. As it's handled centrally, it can have
unexpected consequences for various commands.
Elijah's latest version looks good to me.
-Peff
^ permalink raw reply
* Re: Git mirror at gitlab
From: Patrick Steinhardt @ 2023-12-28 11:13 UTC (permalink / raw)
To: Olliver Schinagl
Cc: git, gitster, Ævar Arnfjörð Bjarmason, psteinhardt
In-Reply-To: <1D1CDDF3-E0D2-4059-9C9A-796145AB6E24@schinagl.nl>
[-- Attachment #1: Type: text/plain, Size: 3629 bytes --]
On Fri, Dec 22, 2023 at 03:06:08PM +0100, Olliver Schinagl wrote:
> Hey Patrick,
>
> On December 21, 2023 12:48:12 p.m. GMT+01:00, Patrick Steinhardt <ps@pks.im> wrote:
> >On Thu, Dec 21, 2023 at 12:30:02PM +0100, Olliver Schinagl wrote:
> >> Hey list,
> >>
> >> For years, I wanted (tried, but time) to run the mirror for git on gitlab.
> >> Actually, the original idea was to run a docker container ([0] 10k+ pulls
> >> :p)
> >>
> >> I initially set this up via docker build containers, where docker hub would
> >> pull my mirror of the git repo. My mirror, because I added a Dockerfile
> >> which was enough for docker to do its trick. I was planning (time ..) on
> >> submitting this upstream to the list, but never did. Because of me not doing
> >> that, I had to manually (I was even too lazy to script it) rebase the
> >> branch. Docker then did some changes to their business, where the docker
> >> builds where not possible anymore.
> >>
> >> So then I figured, I'll do the same on gitlab and push it to the docker hub.
> >> Thus I setup a mirror on gitlab [1], with the idea to work there on it.
> >>
> >> Again, I never got around to finalize this work, mostly because the docker
> >> container 'just worked' for pretty much everything. After all, git is very
> >> stable overal.
> >>
> >> So very interestingly, last month commit 0e3b67e2aa25edb ("ci: add support
> >> for GitLab CI") landed, which started to trigger pipeline jobs!
> >>
> >> Sadly, this only worked for 3 builds, as that's when the minutes ran out :)
> >>
> >> So one, I would very much like to offer the registered names (cause they are
> >> pretty nice in name) to here, so people can use and find it.
> >
> >Not to throw a wrench into this, but are you aware of the official
> >GitLab mirror at https://gitlab.com/git-vcs/git? I myself wasn't aware
> >of this mirror for a rather long time.
>
> Not a wrench at all, and no, I didn't know. How old is it though :p
> could be that git-vcs was created cause I owned gitscm :)
>
> I had chosen gitscm to match the official site, git-scm.org. the
> hyphen I left out because afaik it wasn't allowed on docker hub.
No idea when exactly this mirror was created. The first mention of it in
the "What's cooking" report is in December 2020, 489058b80d (What's
cooking (2023/12 #05), 2023-12-27).
> >I also wondered whether we want to have https://gitlab.com/git/git as we
> >do on GitHub. I don't think anybody registered it, but it is blocked
> >from being registered as far as I can tell. Maybe we block the namespace
> >out of caution, I dunno. I can certainly check in with our SREs in case
> >it is something the Git project would like to own.
>
> Yeah couldn't figure out who it was either ... hence gitscm.
>
> Sadly gitlab doesn't support aliases :) I'm more then happy to hand
> over the space. Whatever name is decided to be best.
I don't particularly mind the name we ultimately settle with. The most
pragmatic choice would likely be to stick with what we already have.
Ideally, all the others would then be created as forks of the official
one so that they point back to it. Like this, users can learn about the
canonical location of the official GitLab-hosted mirror more easily.
In any case, regardless of which location it is going to be, I certainly
agree that having CI jobs running for it would be great. Folks here at
GitLab are mostly on vacation though, but I'll take care of this once
they are back and once Ævar has responded so that I can get access to
the current official mirror.
Patrick
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH] ci: add job performing static analysis on GitLab CI
From: Patrick Steinhardt @ 2023-12-28 11:02 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
[-- Attachment #1: Type: text/plain, Size: 2504 bytes --]
Our GitHub Workflows definitions have a static analysis job that
runs the following tasks:
- Coccinelle to check for suggested refactorings.
- `make hdr-check` to check for missing includes or forward
declarations in our header files.
- `make check-pot` to check our translations for issues.
- `./ci/check-directional-formatting.bash` to check whether our
sources contain any Unicode directional formatting code points.
Add an equivalent job to our GitLab CI definitions.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
This addition is inspired by my reftable patch series where I forgot to
add a "hash-ll.h" include. This would've been catched by our GitLab CI
pipeline if we already had the static-analysis job added in this patch.
These changes are part of [1], which thus also contains an example
pipeline run.
[1]: https://gitlab.com/gitlab-org/git/-/merge_requests/79
.gitlab-ci.yml | 10 ++++++++++
ci/install-docker-dependencies.sh | 7 ++++++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index cd98bcb18a..793243421c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -51,3 +51,13 @@ test:
paths:
- t/failed-test-artifacts
when: on_failure
+
+static-analysis:
+ image: ubuntu:22.04
+ variables:
+ jobname: StaticAnalysis
+ before_script:
+ - ./ci/install-docker-dependencies.sh
+ script:
+ - ./ci/run-static-analysis.sh
+ - ./ci/check-directional-formatting.bash
diff --git a/ci/install-docker-dependencies.sh b/ci/install-docker-dependencies.sh
index 48c43f0f90..eb2c9e1eca 100755
--- a/ci/install-docker-dependencies.sh
+++ b/ci/install-docker-dependencies.sh
@@ -21,7 +21,7 @@ linux-musl)
apache2 apache2-http2 apache2-proxy apache2-ssl apache2-webdav apr-util-dbd_sqlite3 \
bash cvs gnupg perl-cgi perl-dbd-sqlite >/dev/null
;;
-linux-*)
+linux-*|StaticAnalysis)
# Required so that apt doesn't wait for user input on certain packages.
export DEBIAN_FRONTEND=noninteractive
@@ -31,6 +31,11 @@ linux-*)
perl-modules liberror-perl libauthen-sasl-perl libemail-valid-perl \
libdbd-sqlite3-perl libio-socket-ssl-perl libnet-smtp-ssl-perl ${CC_PACKAGE:-${CC:-gcc}} \
apache2 cvs cvsps gnupg libcgi-pm-perl subversion
+
+ if test "$jobname" = StaticAnalysis
+ then
+ apt install -q -y coccinelle
+ fi
;;
pedantic)
dnf -yq update >/dev/null &&
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* Re: [PATCH 2/2] ref-filter: support filtering of operational refs
From: Patrick Steinhardt @ 2023-12-28 10:34 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Karthik Nayak, git, christian.couder
In-Reply-To: <xmqqzfy3l270.fsf@gitster.g>
[-- Attachment #1: Type: text/plain, Size: 3250 bytes --]
On Thu, Dec 21, 2023 at 12:40:03PM -0800, Junio C Hamano wrote:
> Karthik Nayak <karthik.188@gmail.com> writes:
> > With the upcoming introduction of the reftable backend, it becomes ever
> > so important to provide the necessary tooling for printing all refs
> > associated with a repository.
>
> We have pseudoref (those all caps files outside the refs/ hierarchy)
> as an official term defined in the glossary, and Patrick's reftable
> work based on Han-Wen's work revealed the need to treat FETCH_HEAD
> and MERGE_HEAD as "even more pecurilar than pseudorefs" that need
> different term (tentatively called "special refs"). Please avoid
> coming up with yet another random name "operational" without
> discussing.
>
> With a quick look at the table in this patch, "pseudorefs" appears
> to be the closest word that people are already familiar with, I
> think.
Agreed, this thought also crossed my mind while reading through the
patches.
> A lot more reasonable thing to do may be to scan the
> $GIT_DIR for files whose name satisfy refs.c:is_pseudoref_syntax()
> and list them, instead of having a hardcoded list of these special
> refs.
Agreed, as well. Despite the reasons mentioned below, the chance for
such a hardcoded list to grow stale is also quite high. And while it
certainly feels very hacky to iterate over the files one by one and
check for each of them whether it could be a pseudo ref, it is the best
we can do to dynamically detect any such reference.
One interesting question is how we should treat files that look like a
pseudoref, but which really aren't. I'm not aware of any such files
written by Git itself, but it could certainly be that a user wrote such
a file into the repository manually. But given that we're adding new
behaviour that will be opt-in (e.g. via a new switch) I'd rather err on
the side of caution and mark any such file as broken instead of silently
ignoring them.
> In addition, when reftable and other backends that can
> natively store things outside refs/ hierarchy is in use, they ought
> to know what they have so enumerating these would not be an issue
> for them without having such a hardcoded table of names.
Yup, for the reftable we don't have the issue of "How do we detect refs
dynamically" at all. So I would love for there to be a way to print all
refs in the refdb, regardless of whether they start with `refs/` or look
like a pseudoref or whatever else. Otherwise it wouldn't be possible for
a user to delete anything stored in the refdb that may have a funny
name, be it intentionally, by accident or due to a bug.
In the reftable backend, the ref iterator's `_advance()` function has a
hardcoded `starts_with(refname, "refs/")` check. If false, then we'd
skip the ref in order to retain the same behaviour that the files
backend has. So maybe what we should be doing is to introduce a new flag
`DO_FOR_EACH_ALL_REFS` and expose it via git-for-each-ref(1) or
git-show-ref(1). So:
- For the reftable backend we'd skip the `starts_with()` check and
simply return all refs.
- For the files backend we'd also iterate through all files in
$GIT_DIR and check whether they are pseudoref-like.
Patrick
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH 6/6] builtin/worktree: create refdb via ref backend
From: Patrick Steinhardt @ 2023-12-28 10:00 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1703754513.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 4397 bytes --]
When creating a worktree we create the worktree's ref database manually
by first writing a "HEAD" file so that the directory is recognized as a
Git repository by other commands, and then running git-update-ref(1) or
git-symbolic-ref(1) to write the actual value. But while this is fine
for the files backend, this logic simply assumes too much about how the
ref backend works and will leave behind an invalid ref database once any
other ref backend lands.
Refactor the code to instead use `refs_init_db()` to initialize the ref
database so that git-worktree(1) itself does not need to know about how
to initialize it. This will allow future ref backends to customize how
the per-worktree ref database is set up. Furthermore, as we now already
have a worktree ref store around, we can also avoid spawning external
commands to write the HEAD reference and instead use the refs API to do
so.
Note that we do not have an equivalent to passing the `--quiet` flag to
git-symbolic-ref(1) as we did before. This flag does not have an effect
anyway though, as git-symbolic-ref(1) only honors it when reading a
symref, but never when writing one.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/worktree.c | 48 +++++++++++++++++++++-------------------------
1 file changed, 22 insertions(+), 26 deletions(-)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 58937a2a68..9d935bee84 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -416,7 +416,6 @@ static int add_worktree(const char *path, const char *refname,
struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT;
const char *name;
- struct child_process cp = CHILD_PROCESS_INIT;
struct strvec child_env = STRVEC_INIT;
unsigned int counter = 0;
int len, ret;
@@ -424,7 +423,8 @@ static int add_worktree(const char *path, const char *refname,
struct commit *commit = NULL;
int is_branch = 0;
struct strbuf sb_name = STRBUF_INIT;
- struct worktree **worktrees;
+ struct worktree **worktrees, *wt = NULL;
+ struct ref_store *wt_refs;
worktrees = get_worktrees();
check_candidate_path(path, opts->force, worktrees, "add");
@@ -500,15 +500,26 @@ static int add_worktree(const char *path, const char *refname,
write_file(sb.buf, "../..");
/*
- * This is to keep resolve_ref() happy. We need a valid HEAD
- * or is_git_directory() will reject the directory. Any value which
- * looks like an object ID will do since it will be immediately
- * replaced by the symbolic-ref or update-ref invocation in the new
- * worktree.
+ * Set up the ref store of the worktree and create the HEAD reference.
*/
- strbuf_reset(&sb);
- strbuf_addf(&sb, "%s/HEAD", sb_repo.buf);
- write_file(sb.buf, "%s", oid_to_hex(null_oid()));
+ wt = get_linked_worktree(name);
+ if (!wt) {
+ ret = error(_("could not find created worktree '%s'"), name);
+ goto done;
+ }
+ wt_refs = get_worktree_ref_store(wt);
+
+ ret = refs_init_db(wt_refs, REFS_INIT_DB_IS_WORKTREE, &sb);
+ if (ret)
+ goto done;
+
+ if (!is_branch && commit)
+ ret = refs_update_ref(wt_refs, NULL, "HEAD", &commit->object.oid,
+ NULL, 0, UPDATE_REFS_MSG_ON_ERR);
+ else
+ ret = refs_create_symref(wt_refs, "HEAD", symref.buf, NULL);
+ if (ret)
+ goto done;
/*
* If the current worktree has sparse-checkout enabled, then copy
@@ -527,22 +538,6 @@ static int add_worktree(const char *path, const char *refname,
strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
strvec_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
- cp.git_cmd = 1;
-
- if (!is_branch && commit) {
- strvec_pushl(&cp.args, "update-ref", "HEAD",
- oid_to_hex(&commit->object.oid), NULL);
- } else {
- strvec_pushl(&cp.args, "symbolic-ref", "HEAD",
- symref.buf, NULL);
- if (opts->quiet)
- strvec_push(&cp.args, "--quiet");
- }
-
- strvec_pushv(&cp.env, child_env.v);
- ret = run_command(&cp);
- if (ret)
- goto done;
if (opts->orphan &&
(ret = make_worktree_orphan(refname, opts, &child_env)))
@@ -588,6 +583,7 @@ static int add_worktree(const char *path, const char *refname,
strbuf_release(&sb_git);
strbuf_release(&sb_name);
strbuf_release(&realpath);
+ free_worktree(wt);
return ret;
}
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 5/6] worktree: expose interface to look up worktree by name
From: Patrick Steinhardt @ 2023-12-28 10:00 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1703754513.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 2396 bytes --]
Our worktree interfaces do not provide a way to look up a worktree by
its name. Expose `get_linked_worktree()` to allow for this usecase. As
callers are responsible for freeing this worktree, introduce a new
function `free_worktree()` that does so.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
worktree.c | 25 +++++++++++++++----------
worktree.h | 11 +++++++++++
2 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/worktree.c b/worktree.c
index a56a6c2a3d..085f2cc41a 100644
--- a/worktree.c
+++ b/worktree.c
@@ -12,18 +12,23 @@
#include "wt-status.h"
#include "config.h"
+void free_worktree(struct worktree *worktree)
+{
+ if (!worktree)
+ return;
+ free(worktree->path);
+ free(worktree->id);
+ free(worktree->head_ref);
+ free(worktree->lock_reason);
+ free(worktree->prune_reason);
+ free(worktree);
+}
+
void free_worktrees(struct worktree **worktrees)
{
int i = 0;
-
- for (i = 0; worktrees[i]; i++) {
- free(worktrees[i]->path);
- free(worktrees[i]->id);
- free(worktrees[i]->head_ref);
- free(worktrees[i]->lock_reason);
- free(worktrees[i]->prune_reason);
- free(worktrees[i]);
- }
+ for (i = 0; worktrees[i]; i++)
+ free_worktree(worktrees[i]);
free (worktrees);
}
@@ -74,7 +79,7 @@ static struct worktree *get_main_worktree(void)
return worktree;
}
-static struct worktree *get_linked_worktree(const char *id)
+struct worktree *get_linked_worktree(const char *id)
{
struct worktree *worktree = NULL;
struct strbuf path = STRBUF_INIT;
diff --git a/worktree.h b/worktree.h
index ce45b66de9..8a75691eac 100644
--- a/worktree.h
+++ b/worktree.h
@@ -57,6 +57,12 @@ struct worktree *find_worktree(struct worktree **list,
const char *prefix,
const char *arg);
+/*
+ * Look up the worktree corresponding to `id`, or NULL of no such worktree
+ * exists.
+ */
+struct worktree *get_linked_worktree(const char *id);
+
/*
* Return the worktree corresponding to `path`, or NULL if no such worktree
* exists.
@@ -134,6 +140,11 @@ void repair_worktrees(worktree_repair_fn, void *cb_data);
*/
void repair_worktree_at_path(const char *, worktree_repair_fn, void *cb_data);
+/*
+ * Free up the memory for a worktree.
+ */
+void free_worktree(struct worktree *);
+
/*
* Free up the memory for worktree(s)
*/
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 4/6] builtin/worktree: move setup of commondir file earlier
From: Patrick Steinhardt @ 2023-12-28 10:00 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1703754513.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 1533 bytes --]
Shuffle around how we create supporting worktree files so that we first
ensure that the worktree has all link files ("gitdir", "commondir")
before we try to initialize the ref database by writing "HEAD". This
will be required by a subsequent commit where we start to initialize the
ref database via `refs_init_db()`, which will require an initialized
`struct worktree *`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/worktree.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 4ac1621541..58937a2a68 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -495,6 +495,10 @@ static int add_worktree(const char *path, const char *refname,
strbuf_realpath(&realpath, get_git_common_dir(), 1);
write_file(sb_git.buf, "gitdir: %s/worktrees/%s",
realpath.buf, name);
+ strbuf_reset(&sb);
+ strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
+ write_file(sb.buf, "../..");
+
/*
* This is to keep resolve_ref() happy. We need a valid HEAD
* or is_git_directory() will reject the directory. Any value which
@@ -505,9 +509,6 @@ static int add_worktree(const char *path, const char *refname,
strbuf_reset(&sb);
strbuf_addf(&sb, "%s/HEAD", sb_repo.buf);
write_file(sb.buf, "%s", oid_to_hex(null_oid()));
- strbuf_reset(&sb);
- strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
- write_file(sb.buf, "../..");
/*
* If the current worktree has sparse-checkout enabled, then copy
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 3/6] refs/files: skip creation of "refs/{heads,tags}" for worktrees
From: Patrick Steinhardt @ 2023-12-28 10:00 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1703754513.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 2384 bytes --]
The files ref backend will create both "refs/heads" and "refs/tags" in
the Git directory. While this logic makes sense for normal repositories,
it does not fo worktrees because those refs are "common" refs that would
always be contained in the main repository's ref database.
Introduce a new flag telling the backend that it is expected to create a
per-worktree ref database and skip creation of these dirs in the files
backend when the flag is set. No other backends (currently) need
worktree-specific logic, so this is the only required change to start
creating per-worktree ref databases via `refs_init_db()`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
refs.h | 2 ++
refs/files-backend.c | 22 ++++++++++++++--------
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/refs.h b/refs.h
index 6090e92578..8ed890841b 100644
--- a/refs.h
+++ b/refs.h
@@ -123,6 +123,8 @@ int should_autocreate_reflog(const char *refname);
int is_branch(const char *refname);
+#define REFS_INIT_DB_IS_WORKTREE (1 << 0)
+
int refs_init_db(struct ref_store *refs, int flags, struct strbuf *err);
/*
diff --git a/refs/files-backend.c b/refs/files-backend.c
index ed47c5dc08..a82d6c453f 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3221,7 +3221,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
}
static int files_init_db(struct ref_store *ref_store,
- int flags UNUSED,
+ int flags,
struct strbuf *err UNUSED)
{
struct files_ref_store *refs =
@@ -3245,15 +3245,21 @@ static int files_init_db(struct ref_store *ref_store,
adjust_shared_perm(sb.buf);
/*
- * Create .git/refs/{heads,tags}
+ * There is no need to create directories for common refs when creating
+ * a worktree ref store.
*/
- strbuf_reset(&sb);
- files_ref_path(refs, &sb, "refs/heads");
- safe_create_dir(sb.buf, 1);
+ if (!(flags & REFS_INIT_DB_IS_WORKTREE)) {
+ /*
+ * Create .git/refs/{heads,tags}
+ */
+ strbuf_reset(&sb);
+ files_ref_path(refs, &sb, "refs/heads");
+ safe_create_dir(sb.buf, 1);
- strbuf_reset(&sb);
- files_ref_path(refs, &sb, "refs/tags");
- safe_create_dir(sb.buf, 1);
+ strbuf_reset(&sb);
+ files_ref_path(refs, &sb, "refs/tags");
+ safe_create_dir(sb.buf, 1);
+ }
strbuf_release(&sb);
return 0;
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 2/6] setup: move creation of "refs/" into the files backend
From: Patrick Steinhardt @ 2023-12-28 9:59 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1703754513.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 3400 bytes --]
When creating the ref database we unconditionally create the "refs/"
directory in "setup.c". This is a mandatory prerequisite for all Git
repositories regardless of the ref backend in use, because Git will be
unable to detect the directory as a repository if "refs/" doesn't exist.
We are about to add another new caller that will want to create a ref
database when creating worktrees. We would require the same logic to
create the "refs/" directory even though the caller really should not
care about such low-level details. Ideally, the ref database should be
fully initialized after calling `refs_init_db()`.
Move the code to create the directory into the files backend itself to
make it so. This means that future ref backends will also need to have
equivalent logic around to ensure that the directory exists, but it
seems a lot more sensible to have it this way round than to require
callers to create the directory themselves.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
refs/files-backend.c | 17 +++++++++++++++++
setup.c | 15 ---------------
2 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 387eeb5037..ed47c5dc08 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3228,9 +3228,26 @@ static int files_init_db(struct ref_store *ref_store,
files_downcast(ref_store, REF_STORE_WRITE, "init_db");
struct strbuf sb = STRBUF_INIT;
+ /*
+ * We need to create a "refs" dir in any case so that older versions of
+ * Git can tell that this is a repository. This serves two main purposes:
+ *
+ * - Clients will know to stop walking the parent-directory chain when
+ * detecting the Git repository. Otherwise they may end up detecting
+ * a Git repository in a parent directory instead.
+ *
+ * - Instead of failing to detect a repository with unknown reference
+ * format altogether, old clients will print an error saying that
+ * they do not understand the reference format extension.
+ */
+ strbuf_addf(&sb, "%s/refs", ref_store->gitdir);
+ safe_create_dir(sb.buf, 1);
+ adjust_shared_perm(sb.buf);
+
/*
* Create .git/refs/{heads,tags}
*/
+ strbuf_reset(&sb);
files_ref_path(refs, &sb, "refs/heads");
safe_create_dir(sb.buf, 1);
diff --git a/setup.c b/setup.c
index a4eb2a38ac..f2d55994e2 100644
--- a/setup.c
+++ b/setup.c
@@ -1904,21 +1904,6 @@ void create_reference_database(const char *initial_branch, int quiet)
struct strbuf err = STRBUF_INIT;
int reinit = is_reinit();
- /*
- * We need to create a "refs" dir in any case so that older versions of
- * Git can tell that this is a repository. This serves two main purposes:
- *
- * - Clients will know to stop walking the parent-directory chain when
- * detecting the Git repository. Otherwise they may end up detecting
- * a Git repository in a parent directory instead.
- *
- * - Instead of failing to detect a repository with unknown reference
- * format altogether, old clients will print an error saying that
- * they do not understand the reference format extension.
- */
- safe_create_dir(git_path("refs"), 1);
- adjust_shared_perm(git_path("refs"));
-
if (refs_init_db(get_main_ref_store(the_repository), 0, &err))
die("failed to set up refs db: %s", err.buf);
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 1/6] refs: prepare `refs_init_db()` for initializing worktree refs
From: Patrick Steinhardt @ 2023-12-28 9:59 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1703754513.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 4448 bytes --]
The purpose of `refs_init_db()` is to initialize the on-disk files of a
new ref database. The function is quite inflexible right now though, as
callers can neither specify the `struct ref_store` nor can they pass any
flags.
Refactor the interface to accept both of these. This will be required so
that we can start initializing per-worktree ref databases via the ref
backend instead of open-coding the initialization in "worktree.c".
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
refs.c | 6 ++----
refs.h | 2 +-
refs/debug.c | 4 ++--
refs/files-backend.c | 4 +++-
refs/packed-backend.c | 1 +
refs/refs-internal.h | 4 +++-
setup.c | 2 +-
7 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/refs.c b/refs.c
index 16bfa21df7..87e2659db7 100644
--- a/refs.c
+++ b/refs.c
@@ -1928,11 +1928,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
}
/* backend functions */
-int refs_init_db(struct strbuf *err)
+int refs_init_db(struct ref_store *refs, int flags, struct strbuf *err)
{
- struct ref_store *refs = get_main_ref_store(the_repository);
-
- return refs->be->init_db(refs, err);
+ return refs->be->init_db(refs, flags, err);
}
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
diff --git a/refs.h b/refs.h
index ff113bb12a..6090e92578 100644
--- a/refs.h
+++ b/refs.h
@@ -123,7 +123,7 @@ int should_autocreate_reflog(const char *refname);
int is_branch(const char *refname);
-int refs_init_db(struct strbuf *err);
+int refs_init_db(struct ref_store *refs, int flags, struct strbuf *err);
/*
* Return the peeled value of the oid currently being iterated via
diff --git a/refs/debug.c b/refs/debug.c
index 83b7a0ba65..c061def8b5 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -33,10 +33,10 @@ struct ref_store *maybe_debug_wrap_ref_store(const char *gitdir, struct ref_stor
return (struct ref_store *)res;
}
-static int debug_init_db(struct ref_store *refs, struct strbuf *err)
+static int debug_init_db(struct ref_store *refs, int flags, struct strbuf *err)
{
struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
- int res = drefs->refs->be->init_db(drefs->refs, err);
+ int res = drefs->refs->be->init_db(drefs->refs, flags, err);
trace_printf_key(&trace_refs, "init_db: %d\n", res);
return res;
}
diff --git a/refs/files-backend.c b/refs/files-backend.c
index ad8b1d143f..387eeb5037 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3220,7 +3220,9 @@ static int files_reflog_expire(struct ref_store *ref_store,
return -1;
}
-static int files_init_db(struct ref_store *ref_store, struct strbuf *err UNUSED)
+static int files_init_db(struct ref_store *ref_store,
+ int flags UNUSED,
+ struct strbuf *err UNUSED)
{
struct files_ref_store *refs =
files_downcast(ref_store, REF_STORE_WRITE, "init_db");
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index b9fa097a29..3f10bccf44 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -1246,6 +1246,7 @@ static const char PACKED_REFS_HEADER[] =
"# pack-refs with: peeled fully-peeled sorted \n";
static int packed_init_db(struct ref_store *ref_store UNUSED,
+ int flags UNUSED,
struct strbuf *err UNUSED)
{
/* Nothing to do. */
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 4af83bf9a5..a33b28c19d 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -529,7 +529,9 @@ 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);
+typedef int ref_init_db_fn(struct ref_store *refs,
+ int flags,
+ struct strbuf *err);
typedef int ref_transaction_prepare_fn(struct ref_store *refs,
struct ref_transaction *transaction,
diff --git a/setup.c b/setup.c
index bc90bbd033..a4eb2a38ac 100644
--- a/setup.c
+++ b/setup.c
@@ -1919,7 +1919,7 @@ void create_reference_database(const char *initial_branch, int quiet)
safe_create_dir(git_path("refs"), 1);
adjust_shared_perm(git_path("refs"));
- if (refs_init_db(&err))
+ if (refs_init_db(get_main_ref_store(the_repository), 0, &err))
die("failed to set up refs db: %s", err.buf);
/*
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 0/6] worktree: initialize refdb via ref backends
From: Patrick Steinhardt @ 2023-12-28 9:59 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 4262 bytes --]
Hi,
when initializing worktrees we manually create the on-disk data
structures required for the ref backend in "worktree.c". This works just
fine right now where we only have a single user-exposed ref backend, but
it will become unwieldy once we have multiple ref backends. This patch
series thus refactors how we initialize worktrees so that we can use
`refs_init_db()` to initialize required files for us.
This patch series conflicts with ps/refstorage-extension. The conflict
can be solved as shown below. I'm happy to defer this patch series
though until the topic has landed on `master` in case this causes
issues.
Patrick
diff --cc setup.c
index f2d55994e2,4712bba6f8..0000000000
--- a/setup.c
+++ b/setup.c
@@@ -1904,7 -1926,23 +1926,8 @@@ void create_reference_database(int ref_
struct strbuf err = STRBUF_INIT;
int reinit = is_reinit();
- /*
- * We need to create a "refs" dir in any case so that older versions of
- * Git can tell that this is a repository. This serves two main purposes:
- *
- * - Clients will know to stop walking the parent-directory chain when
- * detecting the Git repository. Otherwise they may end up detecting
- * a Git repository in a parent directory instead.
- *
- * - Instead of failing to detect a repository with unknown reference
- * format altogether, old clients will print an error saying that
- * they do not understand the reference format extension.
- */
- safe_create_dir(git_path("refs"), 1);
- adjust_shared_perm(git_path("refs"));
-
+ repo_set_ref_storage_format(the_repository, ref_storage_format);
- if (refs_init_db(&err))
+ if (refs_init_db(get_main_ref_store(the_repository), 0, &err))
die("failed to set up refs db: %s", err.buf);
/*
diff --cc worktree.c
index 085f2cc41a,9702ed0308..0000000000
--- a/worktree.c
+++ b/worktree.c
@@@ -79,7 -75,8 +80,8 @@@ static struct worktree *get_main_worktr
return worktree;
}
- struct worktree *get_linked_worktree(const char *id)
-static struct worktree *get_linked_worktree(const char *id,
- int skip_reading_head)
++struct worktree *get_linked_worktree(const char *id,
++ int skip_reading_head)
{
struct worktree *worktree = NULL;
struct strbuf path = STRBUF_INIT;
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 9d935bee84..558c5537f5 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -502,7 +502,7 @@ static int add_worktree(const char *path, const char *refname,
/*
* Set up the ref store of the worktree and create the HEAD reference.
*/
- wt = get_linked_worktree(name);
+ wt = get_linked_worktree(name, 1);
if (!wt) {
ret = error(_("could not find created worktree '%s'"), name);
goto done;
diff --git a/worktree.h b/worktree.h
index 8a75691eac..f14784a2ff 100644
--- a/worktree.h
+++ b/worktree.h
@@ -61,7 +61,8 @@ struct worktree *find_worktree(struct worktree **list,
* Look up the worktree corresponding to `id`, or NULL of no such worktree
* exists.
*/
-struct worktree *get_linked_worktree(const char *id);
+struct worktree *get_linked_worktree(const char *id,
+ int skip_reading_head);
/*
* Return the worktree corresponding to `path`, or NULL if no such worktree
Patrick Steinhardt (6):
refs: prepare `refs_init_db()` for initializing worktree refs
setup: move creation of "refs/" into the files backend
refs/files: skip creation of "refs/{heads,tags}" for worktrees
builtin/worktree: move setup of commondir file earlier
worktree: expose interface to look up worktree by name
builtin/worktree: create refdb via ref backend
builtin/worktree.c | 53 ++++++++++++++++++++-----------------------
refs.c | 6 ++---
refs.h | 4 +++-
refs/debug.c | 4 ++--
refs/files-backend.c | 37 +++++++++++++++++++++++++-----
refs/packed-backend.c | 1 +
refs/refs-internal.h | 4 +++-
setup.c | 17 +-------------
worktree.c | 25 ++++++++++++--------
worktree.h | 11 +++++++++
10 files changed, 94 insertions(+), 68 deletions(-)
base-commit: e79552d19784ee7f4bbce278fe25f93fbda196fa
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v2 12/12] t9500: write "extensions.refstorage" into config
From: Patrick Steinhardt @ 2023-12-28 9:58 UTC (permalink / raw)
To: git; +Cc: Karthik Nayak, Junio C Hamano
In-Reply-To: <cover.1703753910.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 1312 bytes --]
In t9500 we're writing a custom configuration that sets up gitweb. This
requires us to manually ensure that the repository format is configured
as required, including both the repository format version and
extensions. With the introduction of the "extensions.refStorage"
extension we need to update the test to also write this new one.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/t9500-gitweb-standalone-no-errors.sh | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 0333065d4d..7679780fb8 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -627,6 +627,7 @@ test_expect_success \
test_expect_success 'setup' '
version=$(git config core.repositoryformatversion) &&
algo=$(test_might_fail git config extensions.objectformat) &&
+ refstorage=$(test_might_fail git config extensions.refstorage) &&
cat >.git/config <<-\EOF &&
# testing noval and alternate separator
[gitweb]
@@ -637,6 +638,10 @@ test_expect_success 'setup' '
if test -n "$algo"
then
git config extensions.objectformat "$algo"
+ fi &&
+ if test -n "$refstorage"
+ then
+ git config extensions.refstorage "$refstorage"
fi
'
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v2 11/12] builtin/clone: introduce `--ref-format=` value flag
From: Patrick Steinhardt @ 2023-12-28 9:58 UTC (permalink / raw)
To: git; +Cc: Karthik Nayak, Junio C Hamano
In-Reply-To: <cover.1703753910.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 3995 bytes --]
Introduce a new `--ref-format` value flag for git-clone(1) that allows
the user to specify the ref format that is to be used for a newly
initialized repository.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Documentation/git-clone.txt | 6 ++++++
builtin/clone.c | 12 +++++++++++-
t/t5601-clone.sh | 17 +++++++++++++++++
3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index c37c4a37f7..6e43eb9c20 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -311,6 +311,12 @@ or `--mirror` is given)
The result is Git repository can be separated from working
tree.
+--ref-format=<ref-format::
+
+Specify the given ref storage format for the repository. The valid values are:
++
+include::ref-storage-format.txt[]
+
-j <n>::
--jobs <n>::
The number of submodules fetched at the same time.
diff --git a/builtin/clone.c b/builtin/clone.c
index 0fb3816d0c..18093d5d16 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -72,6 +72,7 @@ static char *remote_name = NULL;
static char *option_branch = NULL;
static struct string_list option_not = STRING_LIST_INIT_NODUP;
static const char *real_git_dir;
+static const char *ref_format;
static char *option_upload_pack = "git-upload-pack";
static int option_verbosity;
static int option_progress = -1;
@@ -157,6 +158,8 @@ static struct option builtin_clone_options[] = {
N_("any cloned submodules will be shallow")),
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
N_("separate git dir from working tree")),
+ OPT_STRING(0, "ref-format", &ref_format, N_("format"),
+ N_("specify the reference format to use")),
OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
N_("set config inside the new repository")),
OPT_STRING_LIST(0, "server-option", &server_options,
@@ -932,6 +935,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
int submodule_progress;
int filter_submodules = 0;
int hash_algo;
+ int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
const int do_not_override_repo_unix_permissions = -1;
struct transport_ls_refs_options transport_ls_refs_options =
@@ -957,6 +961,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_single_branch == -1)
option_single_branch = deepen ? 1 : 0;
+ if (ref_format) {
+ ref_storage_format = ref_storage_format_by_name(ref_format);
+ if (ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN)
+ die(_("unknown ref storage format '%s'"), ref_format);
+ }
+
if (option_mirror)
option_bare = 1;
@@ -1108,7 +1118,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
* their on-disk data structures.
*/
init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN,
- REF_STORAGE_FORMAT_UNKNOWN, NULL,
+ ref_storage_format, NULL,
do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
if (real_git_dir) {
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 47eae641f0..fb1b9c686d 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -157,6 +157,23 @@ test_expect_success 'clone --mirror does not repeat tags' '
'
+test_expect_success 'clone with files ref format' '
+ test_when_finished "rm -rf ref-storage" &&
+ git clone --ref-format=files --mirror src ref-storage &&
+ echo files >expect &&
+ git -C ref-storage rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'clone with garbage ref format' '
+ cat >expect <<-EOF &&
+ fatal: unknown ref storage format ${SQ}garbage${SQ}
+ EOF
+ test_must_fail git clone --ref-format=garbage --mirror src ref-storage 2>err &&
+ test_cmp expect err &&
+ test_path_is_missing ref-storage
+'
+
test_expect_success 'clone to destination with trailing /' '
git clone src target-1/ &&
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v2 10/12] builtin/init: introduce `--ref-format=` value flag
From: Patrick Steinhardt @ 2023-12-28 9:58 UTC (permalink / raw)
To: git; +Cc: Karthik Nayak, Junio C Hamano
In-Reply-To: <cover.1703753910.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 4852 bytes --]
Introduce a new `--ref-format` value flag for git-init(1) that allows
the user to specify the ref format that is to be used for a newly
initialized repository.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Documentation/git-init.txt | 7 +++++++
builtin/init-db.c | 13 ++++++++++++-
t/t0001-init.sh | 26 ++++++++++++++++++++++++++
3 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index 6f0d2973bf..e8dc645bb5 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -11,6 +11,7 @@ SYNOPSIS
[verse]
'git init' [-q | --quiet] [--bare] [--template=<template-directory>]
[--separate-git-dir <git-dir>] [--object-format=<format>]
+ [--ref-format=<format>]
[-b <branch-name> | --initial-branch=<branch-name>]
[--shared[=<permissions>]] [<directory>]
@@ -57,6 +58,12 @@ values are 'sha1' and (if enabled) 'sha256'. 'sha1' is the default.
+
include::object-format-disclaimer.txt[]
+--ref-format=<format>::
+
+Specify the given ref storage format for the repository. The valid values are:
++
+include::ref-storage-format.txt[]
+
--template=<template-directory>::
Specify the directory from which templates will be used. (See the "TEMPLATE
diff --git a/builtin/init-db.c b/builtin/init-db.c
index b6e80feab6..770b2822fe 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -58,6 +58,7 @@ static int shared_callback(const struct option *opt, const char *arg, int unset)
static const char *const init_db_usage[] = {
N_("git init [-q | --quiet] [--bare] [--template=<template-directory>]\n"
" [--separate-git-dir <git-dir>] [--object-format=<format>]\n"
+ " [--ref-format=<format>]\n"
" [-b <branch-name> | --initial-branch=<branch-name>]\n"
" [--shared[=<permissions>]] [<directory>]"),
NULL
@@ -77,8 +78,10 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
const char *template_dir = NULL;
unsigned int flags = 0;
const char *object_format = NULL;
+ const char *ref_format = NULL;
const char *initial_branch = NULL;
int hash_algo = GIT_HASH_UNKNOWN;
+ int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
int init_shared_repository = -1;
const struct option init_db_options[] = {
OPT_STRING(0, "template", &template_dir, N_("template-directory"),
@@ -96,6 +99,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
N_("override the name of the initial branch")),
OPT_STRING(0, "object-format", &object_format, N_("hash"),
N_("specify the hash algorithm to use")),
+ OPT_STRING(0, "ref-format", &ref_format, N_("format"),
+ N_("specify the reference format to use")),
OPT_END()
};
@@ -159,6 +164,12 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
die(_("unknown hash algorithm '%s'"), object_format);
}
+ if (ref_format) {
+ ref_storage_format = ref_storage_format_by_name(ref_format);
+ if (ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN)
+ die(_("unknown ref storage format '%s'"), ref_format);
+ }
+
if (init_shared_repository != -1)
set_shared_repository(init_shared_repository);
@@ -237,6 +248,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
flags |= INIT_DB_EXIST_OK;
return init_db(git_dir, real_git_dir, template_dir, hash_algo,
- REF_STORAGE_FORMAT_UNKNOWN, initial_branch,
+ ref_storage_format, initial_branch,
init_shared_repository, flags);
}
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 30ce752cc1..b131d665db 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -576,6 +576,32 @@ test_expect_success 'init with GIT_DEFAULT_REF_FORMAT=garbage' '
test_cmp expect err
'
+test_expect_success 'init with --ref-format=files' '
+ test_when_finished "rm -rf refformat" &&
+ git init --ref-format=files refformat &&
+ echo files >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 're-init with same format' '
+ test_when_finished "rm -rf refformat" &&
+ git init --ref-format=files refformat &&
+ git init --ref-format=files refformat &&
+ echo files >expect &&
+ git -C refformat rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'init with --ref-format=garbage' '
+ test_when_finished "rm -rf refformat" &&
+ cat >expect <<-EOF &&
+ fatal: unknown ref storage format ${SQ}garbage${SQ}
+ EOF
+ test_must_fail git init --ref-format=garbage refformat 2>err &&
+ test_cmp expect err
+'
+
test_expect_success MINGW 'core.hidedotfiles = false' '
git config --global core.hidedotfiles false &&
rm -rf newdir &&
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v2 09/12] builtin/rev-parse: introduce `--show-ref-format` flag
From: Patrick Steinhardt @ 2023-12-28 9:58 UTC (permalink / raw)
To: git; +Cc: Karthik Nayak, Junio C Hamano
In-Reply-To: <cover.1703753910.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 2428 bytes --]
Introduce a new `--show-ref-format` to git-rev-parse(1) that causes it
to print the ref format used by a repository.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Documentation/git-rev-parse.txt | 3 +++
builtin/rev-parse.c | 4 ++++
t/t1500-rev-parse.sh | 17 +++++++++++++++++
3 files changed, 24 insertions(+)
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 912fab9f5e..546faf9017 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -307,6 +307,9 @@ The following options are unaffected by `--path-format`:
input, multiple algorithms may be printed, space-separated.
If not specified, the default is "storage".
+--show-ref-format::
+ Show the reference storage format used for the repository.
+
Other Options
~~~~~~~~~~~~~
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 917f122440..d08987646a 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -1062,6 +1062,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
puts(the_hash_algo->name);
continue;
}
+ if (!strcmp(arg, "--show-ref-format")) {
+ puts(ref_storage_format_to_name(the_repository->ref_storage_format));
+ continue;
+ }
if (!strcmp(arg, "--end-of-options")) {
seen_end_of_options = 1;
if (filter & (DO_FLAGS | DO_REVS))
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 3f9e7f62e4..a669e592f1 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -208,6 +208,23 @@ test_expect_success 'rev-parse --show-object-format in repo' '
grep "unknown mode for --show-object-format: squeamish-ossifrage" err
'
+test_expect_success 'rev-parse --show-ref-format' '
+ test_detect_ref_format >expect &&
+ git rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rev-parse --show-ref-format with invalid storage' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git config extensions.refstorage broken &&
+ test_must_fail git rev-parse --show-ref-format 2>err &&
+ grep "error: invalid value for ${SQ}extensions.refstorage${SQ}: ${SQ}broken${SQ}" err
+ )
+'
+
test_expect_success '--show-toplevel from subdir of working tree' '
pwd >expect &&
git -C sub/dir rev-parse --show-toplevel >actual &&
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v2 08/12] t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvar
From: Patrick Steinhardt @ 2023-12-28 9:57 UTC (permalink / raw)
To: git; +Cc: Karthik Nayak, Junio C Hamano
In-Reply-To: <cover.1703753910.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 2531 bytes --]
Introduce a new GIT_TEST_DEFAULT_REF_FORMAT environment variable that
lets developers run the test suite with a different default ref format
without impacting the ref format used by non-test Git invocations. This
is modeled after GIT_TEST_DEFAULT_OBJECT_FORMAT, which does the same
thing for the repository's object format.
Adapt the setup of the `REFFILES` test prerequisite to be conditionally
set based on the default ref format.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
t/README | 3 +++
t/test-lib-functions.sh | 5 +++++
t/test-lib.sh | 11 ++++++++++-
3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/t/README b/t/README
index 36463d0742..621d3b8c09 100644
--- a/t/README
+++ b/t/README
@@ -479,6 +479,9 @@ GIT_TEST_DEFAULT_HASH=<hash-algo> specifies which hash algorithm to
use in the test scripts. Recognized values for <hash-algo> are "sha1"
and "sha256".
+GIT_TEST_DEFAULT_REF_FORMAT=<format> specifies which ref storage format
+to use in the test scripts. Recognized values for <format> are "files".
+
GIT_TEST_NO_WRITE_REV_INDEX=<boolean>, when true disables the
'pack.writeReverseIndex' setting.
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 5eb57914ab..a3a51ea9e8 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1659,6 +1659,11 @@ test_detect_hash () {
test_hash_algo="${GIT_TEST_DEFAULT_HASH:-sha1}"
}
+# Detect the hash algorithm in use.
+test_detect_ref_format () {
+ echo "${GIT_TEST_DEFAULT_REF_FORMAT:-files}"
+}
+
# Load common hash metadata and common placeholder object IDs for use with
# test_oid.
test_oid_init () {
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 4685cc3d48..fc93aa57e6 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -542,6 +542,8 @@ export EDITOR
GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-sha1}"
export GIT_DEFAULT_HASH
+GIT_DEFAULT_REF_FORMAT="${GIT_TEST_DEFAULT_REF_FORMAT:-files}"
+export GIT_DEFAULT_REF_FORMAT
GIT_TEST_MERGE_ALGORITHM="${GIT_TEST_MERGE_ALGORITHM:-ort}"
export GIT_TEST_MERGE_ALGORITHM
@@ -1745,7 +1747,14 @@ parisc* | hppa*)
;;
esac
-test_set_prereq REFFILES
+case "$GIT_DEFAULT_REF_FORMAT" in
+files)
+ test_set_prereq REFFILES;;
+*)
+ echo 2>&1 "error: unknown ref format $GIT_DEFAULT_REF_FORMAT"
+ exit 1
+ ;;
+esac
( COLUMNS=1 && test $COLUMNS = 1 ) && test_set_prereq COLUMNS_CAN_BE_1
test -z "$NO_CURL" && test_set_prereq LIBCURL
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v2 07/12] setup: introduce GIT_DEFAULT_REF_FORMAT envvar
From: Patrick Steinhardt @ 2023-12-28 9:57 UTC (permalink / raw)
To: git; +Cc: Karthik Nayak, Junio C Hamano
In-Reply-To: <cover.1703753910.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 3130 bytes --]
Introduce a new GIT_DEFAULT_REF_FORMAT environment variable that lets
users control the default ref format used by both git-init(1) and
git-clone(1). This is modeled after GIT_DEFAULT_OBJECT_FORMAT, which
does the same thing for the repository's object format.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Documentation/git.txt | 5 +++++
setup.c | 7 +++++++
t/t0001-init.sh | 18 ++++++++++++++++++
3 files changed, 30 insertions(+)
diff --git a/Documentation/git.txt b/Documentation/git.txt
index bf9e6af695..88e4ed4bd6 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -556,6 +556,11 @@ double-quotes and respecting backslash escapes. E.g., the value
is always used. The default is "sha1".
See `--object-format` in linkgit:git-init[1].
+`GIT_DEFAULT_REF_FORMAT`::
+ If this variable is set, the default reference backend format for new
+ repositories will be set to this value. The default is "files".
+ See `--ref-format` in linkgit:git-init[1].
+
Git Commits
~~~~~~~~~~~
`GIT_AUTHOR_NAME`::
diff --git a/setup.c b/setup.c
index 3aac8c01cd..4712bba6f8 100644
--- a/setup.c
+++ b/setup.c
@@ -2162,12 +2162,19 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
static void validate_ref_storage_format(struct repository_format *repo_fmt, int format)
{
+ const char *name = getenv("GIT_DEFAULT_REF_FORMAT");
+
if (repo_fmt->version >= 0 &&
format != REF_STORAGE_FORMAT_UNKNOWN &&
format != repo_fmt->ref_storage_format) {
die(_("attempt to reinitialize repository with different reference storage format"));
} else if (format != REF_STORAGE_FORMAT_UNKNOWN) {
repo_fmt->ref_storage_format = format;
+ } else if (name) {
+ format = ref_storage_format_by_name(name);
+ if (format == REF_STORAGE_FORMAT_UNKNOWN)
+ die(_("unknown ref storage format '%s'"), name);
+ repo_fmt->ref_storage_format = format;
}
}
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 38b3e4c39e..30ce752cc1 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -558,6 +558,24 @@ test_expect_success DEFAULT_REPO_FORMAT 'extensions.refStorage with unknown back
grep "invalid value for ${SQ}extensions.refstorage${SQ}: ${SQ}garbage${SQ}" err
'
+test_expect_success DEFAULT_REPO_FORMAT 'init with GIT_DEFAULT_REF_FORMAT=files' '
+ test_when_finished "rm -rf refformat" &&
+ GIT_DEFAULT_REF_FORMAT=files git init refformat &&
+ echo 0 >expect &&
+ git -C refformat config core.repositoryformatversion >actual &&
+ test_cmp expect actual &&
+ test_must_fail git -C refformat config extensions.refstorage
+'
+
+test_expect_success 'init with GIT_DEFAULT_REF_FORMAT=garbage' '
+ test_when_finished "rm -rf refformat" &&
+ cat >expect <<-EOF &&
+ fatal: unknown ref storage format ${SQ}garbage${SQ}
+ EOF
+ test_must_fail env GIT_DEFAULT_REF_FORMAT=garbage git init refformat 2>err &&
+ test_cmp expect err
+'
+
test_expect_success MINGW 'core.hidedotfiles = false' '
git config --global core.hidedotfiles false &&
rm -rf newdir &&
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v2 06/12] setup: introduce "extensions.refStorage" extension
From: Patrick Steinhardt @ 2023-12-28 9:57 UTC (permalink / raw)
To: git; +Cc: Karthik Nayak, Junio C Hamano
In-Reply-To: <cover.1703753910.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 9372 bytes --]
Introduce a new "extensions.refStorage" extension that allows us to
specify the ref storage format used by a repository. For now, the only
supported format is the "files" format, but this list will likely soon
be extended to also support the upcoming "reftable" format.
There have been discussions on the Git mailing list in the past around
how exactly this extension should look like. One alternative [1] that
was discussed was whether it would make sense to model the extension in
such a way that backends are arbitrarily stackable. This would allow for
a combined value of e.g. "loose,packed-refs" or "loose,reftable", which
indicates that new refs would be written via "loose" files backend and
compressed into "packed-refs" or "reftable" backends, respectively.
It is arguable though whether this flexibility and the complexity that
it brings with it is really required for now. It is not foreseeable that
there will be a proliferation of backends in the near-term future, and
the current set of existing formats and formats which are on the horizon
can easily be configured with the much simpler proposal where we have a
single value, only.
Furthermore, if we ever see that we indeed want to gain the ability to
arbitrarily stack the ref formats, then we can adapt the current
extension rather easily. Given that Git clients will refuse any unknown
value for the "extensions.refStorage" extension they would also know to
ignore a stacked "loose,packed-refs" in the future.
So let's stick with the easy proposal for the time being and wire up the
extension.
[1]: <pull.1408.git.1667846164.gitgitgadget@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
Documentation/config/extensions.txt | 11 ++++++++
Documentation/ref-storage-format.txt | 1 +
.../technical/repository-version.txt | 5 ++++
builtin/clone.c | 2 +-
setup.c | 23 +++++++++++++---
setup.h | 3 ++-
t/t0001-init.sh | 26 +++++++++++++++++++
t/test-lib.sh | 2 +-
8 files changed, 67 insertions(+), 6 deletions(-)
create mode 100644 Documentation/ref-storage-format.txt
diff --git a/Documentation/config/extensions.txt b/Documentation/config/extensions.txt
index bccaec7a96..66db0e15da 100644
--- a/Documentation/config/extensions.txt
+++ b/Documentation/config/extensions.txt
@@ -7,6 +7,17 @@ Note that this setting should only be set by linkgit:git-init[1] or
linkgit:git-clone[1]. Trying to change it after initialization will not
work and will produce hard-to-diagnose issues.
+extensions.refStorage::
+ Specify the ref storage format to use. The acceptable values are:
++
+include::../ref-storage-format.txt[]
++
+It is an error to specify this key unless `core.repositoryFormatVersion` is 1.
++
+Note that this setting should only be set by linkgit:git-init[1] or
+linkgit:git-clone[1]. Trying to change it after initialization will not
+work and will produce hard-to-diagnose issues.
+
extensions.worktreeConfig::
If enabled, then worktrees will load config settings from the
`$GIT_DIR/config.worktree` file in addition to the
diff --git a/Documentation/ref-storage-format.txt b/Documentation/ref-storage-format.txt
new file mode 100644
index 0000000000..1a65cac468
--- /dev/null
+++ b/Documentation/ref-storage-format.txt
@@ -0,0 +1 @@
+* `files` for loose files with packed-refs. This is the default.
diff --git a/Documentation/technical/repository-version.txt b/Documentation/technical/repository-version.txt
index 045a76756f..27be3741e6 100644
--- a/Documentation/technical/repository-version.txt
+++ b/Documentation/technical/repository-version.txt
@@ -100,3 +100,8 @@ If set, by default "git config" reads from both "config" and
multiple working directory mode, "config" file is shared while
"config.worktree" is per-working directory (i.e., it's in
GIT_COMMON_DIR/worktrees/<id>/config.worktree)
+
+==== `refStorage`
+
+Specifies the file format for the ref database. The only valid value
+is `files` (loose references with a packed-refs file).
diff --git a/builtin/clone.c b/builtin/clone.c
index 48aeb1b90b..0fb3816d0c 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1291,7 +1291,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
* ours to the same thing.
*/
hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
- initialize_repository_version(hash_algo, 1);
+ initialize_repository_version(hash_algo, the_repository->ref_storage_format, 1);
repo_set_hash_algo(the_repository, hash_algo);
create_reference_database(the_repository->ref_storage_format, NULL, 1);
diff --git a/setup.c b/setup.c
index 3d980814bc..3aac8c01cd 100644
--- a/setup.c
+++ b/setup.c
@@ -592,6 +592,17 @@ static enum extension_result handle_extension(const char *var,
"extensions.objectformat", value);
data->hash_algo = format;
return EXTENSION_OK;
+ } else if (!strcmp(ext, "refstorage")) {
+ int format;
+
+ if (!value)
+ return config_error_nonbool(var);
+ format = ref_storage_format_by_name(value);
+ if (format == REF_STORAGE_FORMAT_UNKNOWN)
+ return error(_("invalid value for '%s': '%s'"),
+ "extensions.refstorage", value);
+ data->ref_storage_format = format;
+ return EXTENSION_OK;
}
return EXTENSION_UNKNOWN;
}
@@ -1871,12 +1882,14 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree)
return 1;
}
-void initialize_repository_version(int hash_algo, int reinit)
+void initialize_repository_version(int hash_algo, int ref_storage_format,
+ int reinit)
{
char repo_version_string[10];
int repo_version = GIT_REPO_VERSION;
- if (hash_algo != GIT_HASH_SHA1)
+ if (hash_algo != GIT_HASH_SHA1 ||
+ ref_storage_format != REF_STORAGE_FORMAT_FILES)
repo_version = GIT_REPO_VERSION_READ;
/* This forces creation of new config file */
@@ -1889,6 +1902,10 @@ void initialize_repository_version(int hash_algo, int reinit)
hash_algos[hash_algo].name);
else if (reinit)
git_config_set_gently("extensions.objectformat", NULL);
+
+ if (ref_storage_format != REF_STORAGE_FORMAT_FILES)
+ git_config_set("extensions.refstorage",
+ ref_storage_format_to_name(ref_storage_format));
}
static int is_reinit(void)
@@ -2030,7 +2047,7 @@ static int create_default_files(const char *template_path,
adjust_shared_perm(get_git_dir());
}
- initialize_repository_version(fmt->hash_algo, 0);
+ initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, 0);
/* Check filemode trustability */
path = git_path_buf(&buf, "config");
diff --git a/setup.h b/setup.h
index 4927abf2cf..89033ae1d9 100644
--- a/setup.h
+++ b/setup.h
@@ -180,7 +180,8 @@ int init_db(const char *git_dir, const char *real_git_dir,
int ref_storage_format,
const char *initial_branch, int init_shared_repository,
unsigned int flags);
-void initialize_repository_version(int hash_algo, int reinit);
+void initialize_repository_version(int hash_algo, int ref_storage_format,
+ int reinit);
void create_reference_database(int ref_storage_format,
const char *initial_branch, int quiet);
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 2b78e3be47..38b3e4c39e 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -532,6 +532,32 @@ test_expect_success 'init rejects attempts to initialize with different hash' '
test_must_fail git -C sha256 init --object-format=sha1
'
+test_expect_success DEFAULT_REPO_FORMAT 'extensions.refStorage is not allowed with repo version 0' '
+ test_when_finished "rm -rf refstorage" &&
+ git init refstorage &&
+ git -C refstorage config extensions.refStorage files &&
+ test_must_fail git -C refstorage rev-parse 2>err &&
+ grep "repo version is 0, but v1-only extension found" err
+'
+
+test_expect_success DEFAULT_REPO_FORMAT 'extensions.refStorage with files backend' '
+ test_when_finished "rm -rf refstorage" &&
+ git init refstorage &&
+ git -C refstorage config core.repositoryformatversion 1 &&
+ git -C refstorage config extensions.refStorage files &&
+ test_commit -C refstorage A &&
+ git -C refstorage rev-parse --verify HEAD
+'
+
+test_expect_success DEFAULT_REPO_FORMAT 'extensions.refStorage with unknown backend' '
+ test_when_finished "rm -rf refstorage" &&
+ git init refstorage &&
+ git -C refstorage config core.repositoryformatversion 1 &&
+ git -C refstorage config extensions.refStorage garbage &&
+ test_must_fail git -C refstorage rev-parse 2>err &&
+ grep "invalid value for ${SQ}extensions.refstorage${SQ}: ${SQ}garbage${SQ}" err
+'
+
test_expect_success MINGW 'core.hidedotfiles = false' '
git config --global core.hidedotfiles false &&
rm -rf newdir &&
diff --git a/t/test-lib.sh b/t/test-lib.sh
index dc03f06b8e..4685cc3d48 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1937,7 +1937,7 @@ test_lazy_prereq SHA1 '
'
test_lazy_prereq DEFAULT_REPO_FORMAT '
- test_have_prereq SHA1
+ test_have_prereq SHA1,REFFILES
'
# Ensure that no test accidentally triggers a Git command
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v2 05/12] setup: set repository's formats on init
From: Patrick Steinhardt @ 2023-12-28 9:57 UTC (permalink / raw)
To: git; +Cc: Karthik Nayak, Junio C Hamano
In-Reply-To: <cover.1703753910.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 2231 bytes --]
The proper hash algorithm and ref storage format that will be used for a
newly initialized repository will be figured out in `init_db()` via
`validate_hash_algorithm()` and `validate_ref_storage_format()`. Until
now though, we never set up the hash algorithm or ref storage format of
`the_repository` accordingly.
There are only two callsites of `init_db()`, one in git-init(1) and one
in git-clone(1). The former function doesn't care for the formats to be
set up properly because it never access the repository after calling the
function in the first place.
For git-clone(1) it's a different story though, as we call `init_db()`
before listing remote refs. While we do indeed have the wrong hash
function in `the_repository` when `init_db()` sets up a non-default
object format for the repository, it never mattered because we adjust
the hash after learning about the remote's hash function via the listed
refs.
So the current state is correct for the hash algo, but it's not for the
ref storage format because git-clone(1) wouldn't know to set it up
properly. But instead of adjusting only the `ref_storage_format`, set
both the hash algo and the ref storage format so that `the_repository`
is in the correct state when `init_db()` exits. This is fine as we will
adjust the hash later on anyway and makes it easier to reason about the
end state of `the_repository`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
setup.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/setup.c b/setup.c
index e58ab7e786..3d980814bc 100644
--- a/setup.c
+++ b/setup.c
@@ -2205,6 +2205,13 @@ int init_db(const char *git_dir, const char *real_git_dir,
&repo_fmt, prev_bare_repository,
init_shared_repository);
+ /*
+ * Now that we have set up both the hash algorithm and the ref storage
+ * format we can update the repository's settings accordingly.
+ */
+ repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
+ repo_set_ref_storage_format(the_repository, repo_fmt.ref_storage_format);
+
if (!(flags & INIT_DB_SKIP_REFDB))
create_reference_database(repo_fmt.ref_storage_format,
initial_branch, flags & INIT_DB_QUIET);
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v2 04/12] setup: start tracking ref storage format
From: Patrick Steinhardt @ 2023-12-28 9:57 UTC (permalink / raw)
To: git; +Cc: Karthik Nayak, Junio C Hamano
In-Reply-To: <cover.1703753910.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 10025 bytes --]
In order to discern which ref storage format a repository is supposed to
use we need to start setting up and/or discovering the format. This
needs to happen in two separate code paths.
- The first path is when we create a repository via `init_db()`. When
we are re-initializing a preexisting repository we need to retain
the previously used ref storage format -- if the user asked for a
different format then this indicates an error and we error out.
Otherwise we either initialize the repository with the format asked
for by the user or the default format, which currently is the
"files" backend.
- The second path is when discovering repositories, where we need to
read the config of that repository. There is not yet any way to
configure something other than the "files" backend, so we can just
blindly set the ref storage format to this backend.
Wire up this logic so that we have the ref storage format always readily
available when needed. As there is only a single backend and because it
is not configurable we cannot yet verify that this tracking works as
expected via tests, but tests will be added in subsequent commits. To
countermand this ommission now though, raise a BUG() in case the ref
storage format is not set up properly in `ref_store_init()`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/clone.c | 5 +++--
builtin/init-db.c | 4 +++-
refs.c | 4 ++--
repository.c | 6 ++++++
repository.h | 4 ++++
setup.c | 26 +++++++++++++++++++++++---
setup.h | 6 +++++-
7 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/builtin/clone.c b/builtin/clone.c
index 343f536cf8..48aeb1b90b 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1107,7 +1107,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
* repository, and reference backends may persist that information into
* their on-disk data structures.
*/
- init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
+ init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN,
+ REF_STORAGE_FORMAT_UNKNOWN, NULL,
do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
if (real_git_dir) {
@@ -1292,7 +1293,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
initialize_repository_version(hash_algo, 1);
repo_set_hash_algo(the_repository, hash_algo);
- create_reference_database(NULL, 1);
+ create_reference_database(the_repository->ref_storage_format, NULL, 1);
/*
* Before fetching from the remote, download and install bundle
diff --git a/builtin/init-db.c b/builtin/init-db.c
index cb727c826f..b6e80feab6 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -11,6 +11,7 @@
#include "object-file.h"
#include "parse-options.h"
#include "path.h"
+#include "refs.h"
#include "setup.h"
#include "strbuf.h"
@@ -236,5 +237,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
flags |= INIT_DB_EXIST_OK;
return init_db(git_dir, real_git_dir, template_dir, hash_algo,
- initial_branch, init_shared_repository, flags);
+ REF_STORAGE_FORMAT_UNKNOWN, initial_branch,
+ init_shared_repository, flags);
}
diff --git a/refs.c b/refs.c
index ab14634731..be8fcabde0 100644
--- a/refs.c
+++ b/refs.c
@@ -2045,10 +2045,10 @@ static struct ref_store *ref_store_init(struct repository *repo,
const char *gitdir,
unsigned int flags)
{
- int format = REF_STORAGE_FORMAT_FILES;
- const struct ref_storage_be *be = find_ref_storage_backend(format);
+ const struct ref_storage_be *be;
struct ref_store *refs;
+ be = find_ref_storage_backend(repo->ref_storage_format);
if (!be)
BUG("reference backend is unknown");
diff --git a/repository.c b/repository.c
index a7679ceeaa..691cabf45b 100644
--- a/repository.c
+++ b/repository.c
@@ -104,6 +104,11 @@ void repo_set_hash_algo(struct repository *repo, int hash_algo)
repo->hash_algo = &hash_algos[hash_algo];
}
+void repo_set_ref_storage_format(struct repository *repo, int format)
+{
+ repo->ref_storage_format = format;
+}
+
/*
* Attempt to resolve and set the provided 'gitdir' for repository 'repo'.
* Return 0 upon success and a non-zero value upon failure.
@@ -184,6 +189,7 @@ int repo_init(struct repository *repo,
goto error;
repo_set_hash_algo(repo, format.hash_algo);
+ repo_set_ref_storage_format(repo, format.ref_storage_format);
repo->repository_format_worktree_config = format.worktree_config;
/* take ownership of format.partial_clone */
diff --git a/repository.h b/repository.h
index ea4c488b81..d3a24da4d6 100644
--- a/repository.h
+++ b/repository.h
@@ -163,6 +163,9 @@ struct repository {
/* Repository's current hash algorithm, as serialized on disk. */
const struct git_hash_algo *hash_algo;
+ /* Repository's reference storage format, as serialized on disk. */
+ int ref_storage_format;
+
/* A unique-id for tracing purposes. */
int trace2_repo_id;
@@ -202,6 +205,7 @@ void repo_set_gitdir(struct repository *repo, const char *root,
const struct set_gitdir_args *extra_args);
void repo_set_worktree(struct repository *repo, const char *path);
void repo_set_hash_algo(struct repository *repo, int algo);
+void repo_set_ref_storage_format(struct repository *repo, int format);
void initialize_the_repository(void);
RESULT_MUST_BE_USED
int repo_init(struct repository *r, const char *gitdir, const char *worktree);
diff --git a/setup.c b/setup.c
index bc90bbd033..e58ab7e786 100644
--- a/setup.c
+++ b/setup.c
@@ -1566,6 +1566,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
}
if (startup_info->have_repository) {
repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
+ repo_set_ref_storage_format(the_repository,
+ repo_fmt.ref_storage_format);
the_repository->repository_format_worktree_config =
repo_fmt.worktree_config;
/* take ownership of repo_fmt.partial_clone */
@@ -1659,6 +1661,8 @@ void check_repository_format(struct repository_format *fmt)
check_repository_format_gently(get_git_dir(), fmt, NULL);
startup_info->have_repository = 1;
repo_set_hash_algo(the_repository, fmt->hash_algo);
+ repo_set_ref_storage_format(the_repository,
+ fmt->ref_storage_format);
the_repository->repository_format_worktree_config =
fmt->worktree_config;
the_repository->repository_format_partial_clone =
@@ -1899,7 +1903,8 @@ static int is_reinit(void)
return ret;
}
-void create_reference_database(const char *initial_branch, int quiet)
+void create_reference_database(int ref_storage_format,
+ const char *initial_branch, int quiet)
{
struct strbuf err = STRBUF_INIT;
int reinit = is_reinit();
@@ -1919,6 +1924,7 @@ void create_reference_database(const char *initial_branch, int quiet)
safe_create_dir(git_path("refs"), 1);
adjust_shared_perm(git_path("refs"));
+ repo_set_ref_storage_format(the_repository, ref_storage_format);
if (refs_init_db(&err))
die("failed to set up refs db: %s", err.buf);
@@ -2137,8 +2143,20 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
}
}
+static void validate_ref_storage_format(struct repository_format *repo_fmt, int format)
+{
+ if (repo_fmt->version >= 0 &&
+ format != REF_STORAGE_FORMAT_UNKNOWN &&
+ format != repo_fmt->ref_storage_format) {
+ die(_("attempt to reinitialize repository with different reference storage format"));
+ } else if (format != REF_STORAGE_FORMAT_UNKNOWN) {
+ repo_fmt->ref_storage_format = format;
+ }
+}
+
int init_db(const char *git_dir, const char *real_git_dir,
- const char *template_dir, int hash, const char *initial_branch,
+ const char *template_dir, int hash,
+ int ref_storage_format, const char *initial_branch,
int init_shared_repository, unsigned int flags)
{
int reinit;
@@ -2181,13 +2199,15 @@ int init_db(const char *git_dir, const char *real_git_dir,
check_repository_format(&repo_fmt);
validate_hash_algorithm(&repo_fmt, hash);
+ validate_ref_storage_format(&repo_fmt, ref_storage_format);
reinit = create_default_files(template_dir, original_git_dir,
&repo_fmt, prev_bare_repository,
init_shared_repository);
if (!(flags & INIT_DB_SKIP_REFDB))
- create_reference_database(initial_branch, flags & INIT_DB_QUIET);
+ create_reference_database(repo_fmt.ref_storage_format,
+ initial_branch, flags & INIT_DB_QUIET);
create_object_directory();
if (get_shared_repository()) {
diff --git a/setup.h b/setup.h
index 3f0f17c351..4927abf2cf 100644
--- a/setup.h
+++ b/setup.h
@@ -115,6 +115,7 @@ struct repository_format {
int worktree_config;
int is_bare;
int hash_algo;
+ int ref_storage_format;
int sparse_index;
char *work_tree;
struct string_list unknown_extensions;
@@ -131,6 +132,7 @@ struct repository_format {
.version = -1, \
.is_bare = -1, \
.hash_algo = GIT_HASH_SHA1, \
+ .ref_storage_format = REF_STORAGE_FORMAT_FILES, \
.unknown_extensions = STRING_LIST_INIT_DUP, \
.v1_only_extensions = STRING_LIST_INIT_DUP, \
}
@@ -175,10 +177,12 @@ void check_repository_format(struct repository_format *fmt);
int init_db(const char *git_dir, const char *real_git_dir,
const char *template_dir, int hash_algo,
+ int ref_storage_format,
const char *initial_branch, int init_shared_repository,
unsigned int flags);
void initialize_repository_version(int hash_algo, int reinit);
-void create_reference_database(const char *initial_branch, int quiet);
+void create_reference_database(int ref_storage_format,
+ const char *initial_branch, int quiet);
/*
* NOTE NOTE NOTE!!
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH v2 03/12] refs: refactor logic to look up storage backends
From: Patrick Steinhardt @ 2023-12-28 9:57 UTC (permalink / raw)
To: git; +Cc: Karthik Nayak, Junio C Hamano
In-Reply-To: <cover.1703753910.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 5129 bytes --]
In order to look up ref storage backends, we're currently using a linked
list of backends, where each backend is expected to set up its `next`
pointer to the next ref storage backend. This is kind of a weird setup
as backends need to be aware of other backends without much of a reason.
Refactor the code so that the array of backends is centrally defined in
"refs.c", where each backend is now identified by an integer constant.
Expose functions to translate from those integer constants to the name
and vice versa, which will be required by subsequent patches.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
refs.c | 34 +++++++++++++++++++++++++---------
refs.h | 3 +++
refs/debug.c | 1 -
refs/files-backend.c | 1 -
refs/packed-backend.c | 1 -
refs/refs-internal.h | 1 -
repository.h | 3 +++
7 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/refs.c b/refs.c
index 16bfa21df7..ab14634731 100644
--- a/refs.c
+++ b/refs.c
@@ -33,17 +33,33 @@
/*
* List of all available backends
*/
-static struct ref_storage_be *refs_backends = &refs_be_files;
+static const struct ref_storage_be *refs_backends[] = {
+ [REF_STORAGE_FORMAT_FILES] = &refs_be_files,
+};
-static struct ref_storage_be *find_ref_storage_backend(const char *name)
+static const struct ref_storage_be *find_ref_storage_backend(int ref_storage_format)
{
- struct ref_storage_be *be;
- for (be = refs_backends; be; be = be->next)
- if (!strcmp(be->name, name))
- return be;
+ if (ref_storage_format < ARRAY_SIZE(refs_backends))
+ return refs_backends[ref_storage_format];
return NULL;
}
+int ref_storage_format_by_name(const char *name)
+{
+ for (int i = 0; i < ARRAY_SIZE(refs_backends); i++)
+ if (refs_backends[i] && !strcmp(refs_backends[i]->name, name))
+ return i;
+ return REF_STORAGE_FORMAT_UNKNOWN;
+}
+
+const char *ref_storage_format_to_name(int ref_storage_format)
+{
+ const struct ref_storage_be *be = find_ref_storage_backend(ref_storage_format);
+ if (!be)
+ return "unknown";
+ return be->name;
+}
+
/*
* How to handle various characters in refnames:
* 0: An acceptable character for refs
@@ -2029,12 +2045,12 @@ static struct ref_store *ref_store_init(struct repository *repo,
const char *gitdir,
unsigned int flags)
{
- const char *be_name = "files";
- struct ref_storage_be *be = find_ref_storage_backend(be_name);
+ int format = REF_STORAGE_FORMAT_FILES;
+ const struct ref_storage_be *be = find_ref_storage_backend(format);
struct ref_store *refs;
if (!be)
- BUG("reference backend %s is unknown", be_name);
+ BUG("reference backend is unknown");
refs = be->init(repo, gitdir, flags);
return refs;
diff --git a/refs.h b/refs.h
index ff113bb12a..e2098ea51b 100644
--- a/refs.h
+++ b/refs.h
@@ -11,6 +11,9 @@ struct string_list;
struct string_list_item;
struct worktree;
+int ref_storage_format_by_name(const char *name);
+const char *ref_storage_format_to_name(int ref_storage_format);
+
/*
* Resolve a reference, recursively following symbolic refererences.
*
diff --git a/refs/debug.c b/refs/debug.c
index 83b7a0ba65..b9775f2c37 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -426,7 +426,6 @@ static int debug_reflog_expire(struct ref_store *ref_store, const char *refname,
}
struct ref_storage_be refs_be_debug = {
- .next = NULL,
.name = "debug",
.init = NULL,
.init_db = debug_init_db,
diff --git a/refs/files-backend.c b/refs/files-backend.c
index ad8b1d143f..43fd0ac760 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3241,7 +3241,6 @@ static int files_init_db(struct ref_store *ref_store, struct strbuf *err UNUSED)
}
struct ref_storage_be refs_be_files = {
- .next = NULL,
.name = "files",
.init = files_ref_store_create,
.init_db = files_init_db,
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index b9fa097a29..8d1090e284 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -1705,7 +1705,6 @@ static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_s
}
struct ref_storage_be refs_be_packed = {
- .next = NULL,
.name = "packed",
.init = packed_ref_store_create,
.init_db = packed_init_db,
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 4af83bf9a5..8e9f04cc67 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -663,7 +663,6 @@ typedef int read_symbolic_ref_fn(struct ref_store *ref_store, const char *refnam
struct strbuf *referent);
struct ref_storage_be {
- struct ref_storage_be *next;
const char *name;
ref_store_init_fn *init;
ref_init_db_fn *init_db;
diff --git a/repository.h b/repository.h
index 5f18486f64..ea4c488b81 100644
--- a/repository.h
+++ b/repository.h
@@ -24,6 +24,9 @@ enum fetch_negotiation_setting {
FETCH_NEGOTIATION_NOOP,
};
+#define REF_STORAGE_FORMAT_UNKNOWN 0
+#define REF_STORAGE_FORMAT_FILES 1
+
struct repo_settings {
int initialized;
--
2.43.GIT
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox