* Re: [PATCH v2] test-lib-functions.sh: fix test_grep fail message wording
From: Kousik Sanagavarapu @ 2023-12-04 18:43 UTC (permalink / raw)
To: Shreyansh Paliwal; +Cc: git, Junio C Hamano
In-Reply-To: <20231203171956.771-1-shreyanshpaliwalcmsmn@gmail.com>
On Sun, Dec 03, 2023 at 10:47:59PM +0530, Shreyansh Paliwal wrote:
> From: shreyp135 <shreyanshpaliwalcmsmn@gmail.com>
>
> In the recent commit
> 2e87fca189 (test framework: further deprecate test_i18ngrep, 2023-10-31),
> the test_i18ngrep() function was deprecated.
s/In the/In a
is gramatically correct, but probably not worth a reroll.
> So if a test employing this function fails,
> the error messages may be confusing due to wording issues.
Isn't the confusion due to test_i18ngrep being displayed in place of
test_grep and not the other way around? Because the formation of the
sentence makes it look like the latter.
> It's important to address these wording changes to ensure smooth transitions
> for developers adapting to the deprecation of test_i18ngrep,
> and to maintain the effectiveness of the testing process.
>
> Signed-off-by: Shreyansh Paliwal <Shreyanshpaliwalcmsmn@gmail.com>
> ---
> t/test-lib-functions.sh | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
> index 9c3cf12b26..8737c95e0c 100644
> --- a/t/test-lib-functions.sh
> +++ b/t/test-lib-functions.sh
> @@ -1277,7 +1277,7 @@ test_grep () {
> if test $# -lt 2 ||
> { test "x!" = "x$1" && test $# -lt 3 ; }
> then
> - BUG "too few parameters to test_i18ngrep"
> + BUG "too few parameters to test_grep"
> fi
>
> if test "x!" = "x$1"
> --
> 2.43.0.1
Rest looks good.
Have a great time at the vacation Junio (and sorry for pinging in the
first place... although this email will indirectly ping too :P).
Thanks
^ permalink raw reply
* git status --porcelain=v2 -z returns paths relative to root
From: Ondra Medek @ 2023-12-04 19:04 UTC (permalink / raw)
To: git
Hello,
git status Porcelain Format Version 1 ignores config
"status.relativePaths" and returns paths relative to the working tree
root always.
On the other hand, git status Porcelain Format Version 2 respects
config "status.relativePaths". But, if the "-z" option is provided,
i.e. "git status --porcelain=v2 -z" it also ignores
"status.relativePaths" and returns paths relative to the working tree
root. Is this a bug or undocumented behaviour? See
https://git-scm.com/docs/git-status#_porcelain_format_version_2
Note: I would welcome some option to force git status to return
relative paths to the current working directory always.
Best regards
Ondra Medek
^ permalink raw reply
* Re: [PATCH 2/2] checkout: forbid "-B <branch>" from touching a branch used elsewhere
From: Eric Sunshine @ 2023-12-04 21:06 UTC (permalink / raw)
To: Willem Verstraeten; +Cc: phillip.wood, Junio C Hamano, git, Jeff King
In-Reply-To: <CAGX9RpH0RJfBADQwJ=c7PCHU955vOqd0Wdc7Yi7XUuAQQW_FNQ@mail.gmail.com>
On Mon, Dec 4, 2023 at 7:21 AM Willem Verstraeten
<willem.verstraeten@gmail.com> wrote:
> It's not clear for me from the email thread what the status is of this
> bug report, and whether there is still something expected from me.
>
> Is the current consensus that this is a real issue that needs fixing?
> If so, does the current patch-set fix the issue, and how does the fix
> get into (one of) the next release(s)?
>
> Do I still need to do something?
According to Junio's latest "What's cooking"[1], the status of this
patch series is:
* jc/checkout-B-branch-in-use (2023-11-23) 2 commits
- checkout: forbid "-B <branch>" from touching a branch used elsewhere
- checkout: refactor die_if_checked_out() caller
"git checkout -B <branch> [<start-point>]" allowed a branch that is
in use in another worktree to be updated and checked out, which
might be a bit unexpected. The rule has been tightened, which is a
breaking change. "--ignore-other-worktrees" option is required to
unbreak you, if you are used to the current behaviour that "-B"
overrides the safety.
Needs review and documentation updates.
I'm not sure if the "Needs review" comment is still applicable since
the patch did get some review comments, however, the mentioned
documentation update is probably still needed for this series to
graduate. I can't speak for what Junio had in mind, but perhaps
sufficient would be to add a side-note to the description of the -B
option saying that it historically (accidentally) would succeed even
if the named branch was checked out in another worktree, but now
requires --ignore-other-worktrees.
To move the series forward, someone will probably need to make the
necessary documentation update. That someone could be you, if you're
interested, either by rerolling Junio's series and modifying patch
[2/2] to also make the necessary documentation update, or by posting a
patch, [3/2] atop his series which updates the documentation.
[1]: https://lore.kernel.org/git/xmqq8r6j1dgt.fsf@gitster.g/
^ permalink raw reply
* Re: [PATCH v2] This PR enables a successful git build on z/OS.
From: Eric Sunshine @ 2023-12-04 21:46 UTC (permalink / raw)
To: Haritha via GitGitGadget; +Cc: git, brian m. carlson, Haritha D
In-Reply-To: <pull.1537.v2.git.git.1701699574054.gitgitgadget@gmail.com>
On Mon, Dec 4, 2023 at 9:19 AM Haritha via GitGitGadget
<gitgitgadget@gmail.com> wrote:
> Rename functions like "release" and "fetch"
> due to conflict in z/OS standard C libraries.
> Also disables autoconversion facility on z/OS
> and relies on iconv.
> New files created in binary format are also
> tagged as binary.
>
> Signed-off-by: Haritha D <harithamma.d@ibm.com>
> ---
> Enabling z/OS workflow for git
>
> z/OS is an IBM mainframe operating system, also known as OS/390. Our
> team has been actively involved in porting Git to z/OS and we have made
> significant modifications to facilitate this process. The patch below is
> the initial configuration for z/OS. I also have few follow up changes
> and I will send that after these changes are approved. Please let me
> know if there are any concerns.
It's fairly unlikely that this patch will be accepted as-is. Please
see brian's[1] and Junio's[2] valuable review comments in response to
your v1. They contain important suggestions which will give you a
better chance of landing these changes.
Generally speaking, the patch's commit message lacks sufficient detail
to allow a reviewer (or future reader) to understand why the changes
are being made. Moreover, this single patch seems to be addressing at
least three separate issues, hence should be split into three or more
patches, each standalone and tackling a single issue, and each easily
digested by a reviewer. The commit message of each patch should fully
explain and justify the changes made by the patch, keeping in mind
that most reviewers probably aren't familiar with z/OS, thus will need
extra hand-holding. More below...
[1]: https://lore.kernel.org/git/ZVKrWSv7JguKTSYw@tapette.crustytoothpaste.net/
[2]: https://lore.kernel.org/git/xmqqcywd2m9i.fsf@gitster.g/
> diff --git a/builtin/archive.c b/builtin/archive.c
> @@ -14,6 +14,15 @@
> static void create_output_file(const char *output_file)
> {
> int output_fd = xopen(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
> +#ifdef __MVS__
> + /*
> + * Since the data is in binary format,
> + * we need to set the z/OS file tag
> + * to binary to disable autoconversion
> + */
> + if (__setfdbinary(output_fd))
> + die_errno(_("could not tag archive file '%s'"), output_file);
> +#endif
As mentioned in an earlier review, the project generally doesn't want
#ifdef's littering the code and prefer that this sort of
platform-specific specialization be wrapped up in its own "compat"
file/function. For instance, perhaps you could create a
platform-specific specialization of xopen() and then `#define xopen`
to reference your specialized version. Your custom xopen() might first
call the xopen() which Git defines and then perform whatever extra
special work is needed for your platform. That way, you would not have
to muck around either in the code which calls xopen() or in the
Git-supplied xopen(). See, for example, how git-compat-util.h
overriedes certain functions, such as stat(), fstat(), etc. using an
#undefine/#define dance.
> diff --git a/combine-diff.c b/combine-diff.c
> @@ -1082,6 +1082,14 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
> + #ifdef __MVS__
> + /*
> + * Disable implicit autconversion on z/os,
> + * rely on conversion from iconv
> + */
> + __disableautocvt(fd);
> + #endif
> elem->mode = canon_mode(st.st_mode);
Similar comment. Try to find an abstraction which allows you to
perform this specialization in a way which does not require #ifdef's
within the main source code if possible.
> diff --git a/fetch-negotiator.h b/fetch-negotiator.h
> @@ -47,7 +47,7 @@ struct fetch_negotiator {
> - void (*release)(struct fetch_negotiator *);
> + void (*release_negotiator)(struct fetch_negotiator *);> diff --git a/fetch-pack.c b/fetch-pack.c
> @@ -1232,7 +1232,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
> if (negotiator)
> - negotiator->release(negotiator);
> + negotiator->release_negotiator(negotiator);
> return ref;
> }
> diff --git a/git-compat-util.h b/git-compat-util.h
> @@ -223,7 +223,15 @@ struct strbuf;
> +#ifdef __MVS__
> + #define release stdlib_release
> + #define fetch stdlib_fetch
> +#endif
> #include <stdlib.h>
> +#ifdef __MVS__
> + #undef fetch
> + #undef release
> +#endif
So, the problem is that z/OS is polluting the C namespace or the
preprocessor namespace with names "release" and "fetch"? When we've
run across this problem on other platforms, we modify
git-compat-util.h or some other files in compat/ to suppress the
pollution introduced by the platform headers rather than "fixing" the
Git source code. For instance, if "release" and "fetch" are macros on
z/OS, then you may be able to simply #undef them after pulling in
whichever z/OS header defines them. If they are actual system
functions (rather than macros), you may be able to employ the
#undef/#define dance to rename them to something else, such as
"zos_release" and "zos_fetch" _before_ including the system header
which declares those functions.
> diff --git a/read-cache.c b/read-cache.c
> @@ -205,6 +205,14 @@ static int ce_compare_data(struct index_state *istate,
> int fd = git_open_cloexec(ce->name, O_RDONLY);
> if (fd >= 0) {
> + #ifdef __MVS__
> + /*
> + * Since the data is in binary format,
> + * we need to set the z/OS file tag to
> + * binary to disable autoconversion
> + */
> + __disableautocvt(fd);
> + #endif
Same comment as above about encapsulating this in a platform-specific
specialization function in compat/ rather than polluting the code with
#ifdef.
^ permalink raw reply
* Re: [PATCH 05/24] midx: implement `DISP` chunk
From: Taylor Blau @ 2023-12-05 19:26 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Jeff King, Patrick Steinhardt
In-Reply-To: <xmqqjzpv4ecg.fsf@gitster.g>
On Sun, Dec 03, 2023 at 10:15:11PM +0900, Junio C Hamano wrote:
> Taylor Blau <me@ttaylorr.com> writes:
>
> > diff --git a/Documentation/git-multi-pack-index.txt b/Documentation/git-multi-pack-index.txt
> > index 3696506eb3..d130e65b28 100644
> > --- a/Documentation/git-multi-pack-index.txt
> > +++ b/Documentation/git-multi-pack-index.txt
> > @@ -49,6 +49,10 @@ write::
> > --stdin-packs::
> > Write a multi-pack index containing only the set of
> > line-delimited pack index basenames provided over stdin.
> > + Lines beginning with a '+' character (followed by the
> > + pack index basename as before) have their pack marked as
> > + "disjoint". See the "`DISP` chunk and disjoint packs"
> > + section in linkgit:gitformat-pack[5] for more.
>
> Makes one wonder who computes the set of packfiles, decides to
> prefix '+' to which ones, and how it does so, none of which appear
> in this step (which is understandable). As the flow of information
> is from the producer of individual "disjoint" packs (not in this
> step) to this new logic in "--stdin-packs" to the new "DISP" chunk
> writer (the primary focus of this step) to the final consumer of
> "DISP" chunk (not in this step), we are digging from the middle
> (hopefully to both directions in other steps). It is probably the
> easiest way to explain the idea to start from the primary data
> structures and "DISP" seems to be a good place to start.
Thanks. I found that laying out this series was rather tricky, since all
of the individual pieces really depend on the end state in order to make
any sense.
Hopefully you're satisfied with the way things are split up and
organized currently, but if you have suggestions on other ways I could
slice or dice this, please let me know.
> > + Two packs are "disjoint" with respect to one another when they have
> > + disjoint sets of objects.
> > + In other words, any object found in a pack
> > + contained in the set of disjoint packfiles is guaranteed to be
> > + uniquely located among those packs.
>
> I often advise people to rethink what they wrote _before_ "In other
> words", because the use of that phrase is a sign that the author
> considers the statement is hard to grok and needs rephrasing, in
> which case, the rephrased version may be a better way to explain the
> concept being presented without the harder-to-grok version.
>
> But I do not think this one is a good example to apply the advice.
> It is because "In other words," is somewhat misused in the sentence.
> Two "disjoint" packs do not store any common object (which is how
> you defined the adjective "disjoint" in the first sentence). "As a
> consequence"/"Hence", an object found in one pack among many
> "disjoint" packs will not appear in others.
Thanks, I'll replace this with "As a consequence", and try to follow
that general advice more often in the future ;-).
> OK, so it seems they really need to be strictly disjoint in order to
> participate in the reuse of the existing packdata.
I think that's generally true, though there are some exceptions.
I think the real condition here is that the *reused sections* must be
disjoint with respect to one another, not necessarily the packs
themselves. So having the packs be disjoint is a sufficient condition,
since we know that no matter which section(s) we reuse, they are
guaranteed to be disjoint.
I think that there is opportunity to be more clever here, e.g., by
allowing for different disjoint "groups" of packs, or mandating that you
can only reuse certain sections from different combinations of packs in
order to satisfy this property.
That's part of the reason why I left more space than is needed for the
"disjoint" state in the DISP chunk (it is 32 bits, of which we're only
using one of them). I'm not sure that we would want more relaxed
constraints here, since they'd be harder to satisfy. But my hope is that
we would be able to learn from running this in production to figure out
whether or not such a thing would be useful.
> > + - All objects stored as offset- or reference-deltas also include their
> > + base object in the resulting pack.
>
> Are thin packs obsolete?
No, I think I should clarify this to make it more obvious that this only
applies to non-thin packs.
> > + find $objdir/pack -type f -name "*.idx" | xargs -n 1 basename | sort >packs &&
>
> That is an overly-long line.
Thanks for spotting.
> > +test_expect_success 'non-disjoint packs are detected' '
> > + test_when_finished "rm -fr repo" &&
> > + git init repo &&
> > + (
> > + cd repo &&
> > +
> > + test_commit base &&
> > + git repack -d &&
> > + test_commit other &&
> > + git repack -a &&
> > +
> > + ls -la .git/objects/pack/ &&
>
> Is this line a leftover debugging aid?
Indeed, thanks.
> > + find $objdir/pack -type f -name "*.idx" |
> > + sed -e "s/.*\/\(.*\)$/+\1/g" >in &&
>
> Lose "g"; it adds unnecessary cognitive burden to the readers if the
> patterh is expected to match multiple times, and you know that is
> not possible (your pattern is right anchored at the end). This may
> apply equally to other uses of "sed" in this patch.
Thanks, I dropped the 'g' in both instances.
Thanks,
Taylor
^ permalink raw reply
* Re: git:// warn as connection not secure
From: Jonny Grant @ 2023-12-05 20:42 UTC (permalink / raw)
To: Eric Wong; +Cc: git
In-Reply-To: <20231201212423.M738201@dcvr>
On 01/12/2023 21:24, Eric Wong wrote:
> Jonny Grant <jg@jguk.org> wrote:
>> Hello
>> May I ask if anyone has suggested adding a default warning that git:// is not a secure connection?
>>
>> ie "warning: git:// is not a secure connection. https and ssh are secure."
>
> To be accurate, that would need an exclusion list of hosts behind
> already-encrypted and trusted networks. So stuff like .onion hostnames
> for Tor, and a user-configurable list of hosts in a private LAN/VPN.
That sounds good Eric.
Or even just an info message?
"info: git:// itself is an unencrypted connection. https and ssh are secure."
Kind regards
Jonny
^ permalink raw reply
* Re: [PATCH v2] This PR enables a successful git build on z/OS.
From: René Scharfe @ 2023-12-05 20:58 UTC (permalink / raw)
To: Eric Sunshine, Haritha via GitGitGadget; +Cc: git, brian m. carlson, Haritha D
In-Reply-To: <CAPig+cQ8eEU0TOoBf2KavTyf0OLhNtmOzs8+WqZy9JMXa=ydPQ@mail.gmail.com>
Am 04.12.23 um 22:46 schrieb Eric Sunshine:
> On Mon, Dec 4, 2023 at 9:19 AM Haritha via GitGitGadget
> <gitgitgadget@gmail.com> wrote:
>> diff --git a/fetch-negotiator.h b/fetch-negotiator.h
>> @@ -47,7 +47,7 @@ struct fetch_negotiator {
>> - void (*release)(struct fetch_negotiator *);
>> + void (*release_negotiator)(struct fetch_negotiator *);> diff --git a/fetch-pack.c b/fetch-pack.c
>> @@ -1232,7 +1232,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
>> if (negotiator)
>> - negotiator->release(negotiator);
>> + negotiator->release_negotiator(negotiator);
>> return ref;
>> }
>> diff --git a/git-compat-util.h b/git-compat-util.h
>> @@ -223,7 +223,15 @@ struct strbuf;
>> +#ifdef __MVS__
>> + #define release stdlib_release
>> + #define fetch stdlib_fetch
>> +#endif
>> #include <stdlib.h>
>> +#ifdef __MVS__
>> + #undef fetch
>> + #undef release
>> +#endif
>
> So, the problem is that z/OS is polluting the C namespace or the
> preprocessor namespace with names "release" and "fetch"? When we've
> run across this problem on other platforms, we modify
> git-compat-util.h or some other files in compat/ to suppress the
> pollution introduced by the platform headers rather than "fixing" the
> Git source code. For instance, if "release" and "fetch" are macros on
> z/OS, then you may be able to simply #undef them after pulling in
> whichever z/OS header defines them. If they are actual system
> functions (rather than macros), you may be able to employ the
> #undef/#define dance to rename them to something else, such as
> "zos_release" and "zos_fetch" _before_ including the system header
> which declares those functions.
I assume that [1] and [2] link to the documentation of these functions.
Both pages include the following paragraph:
"To avoid infringing on the user's name space, this nonstandard
function has two names. One name is prefixed with two underscore
characters, and one name is not. The name without the prefix
underscore characters is exposed only when using the runtime library
extensions."
[3] defines "runtime library extensions" and mentions the macro __EXT
and LANGLVL(EXTENDED). Do you need those extensions? If you don't then
perhaps turning them off avoids the name collisions without needing to
change the code?
René
[1] https://www.ibm.com/docs/en/zos/3.1.0?topic=functions-fetch-get-load-module
[2] https://www.ibm.com/docs/en/zos/3.1.0?topic=functions-release-delete-load-module
[3] https://www.ibm.com/docs/en/zos/3.1.0?topic=reference-zos-cc-compiler-feature#compiler_feature__ext_lib_func
^ permalink raw reply
* git switch has fatal dependency on default fetch config
From: Jeremiah Steele (Jerry) @ 2023-12-06 3:41 UTC (permalink / raw)
To: git
Changing the default fetch refspec for a remote breaks git switch:
% git branch -r
origin/HEAD -> origin/master
origin/feature
origin/master
% git remote set-branches origin master
% git switch -c feature --track origin/feature
fatal: cannot set up tracking information; starting point 'origin/feature' is not a branch
% git remote set-branches --add origin feature
% git switch -c feature --track origin/feature
branch 'feature' set up to track 'origin/feature'.
Switched to a new branch 'feature'
It seems like I should be able to fetch a remote branch and track it without having to monkey around with my default fetch config. Is there a reason git switch has a hard dependency on the default remote fetch refspec configuration?
^ permalink raw reply
* git checkout --recurse-submodules deletes local modifications
From: Simon Etter @ 2023-12-06 7:16 UTC (permalink / raw)
To: git
Hi there!
It seems git checkout --recurse-submodules doesn't live up to its
documentation. According to the docs:
> If local modifications in a submodule would be overwritten the checkout will fail unless -f is used.
Here's an MWE where git checkout --recurse-submodules does overwrite
local modifications:
```
# Prepare repo
rm -rf /tmp/test
mkdir /tmp/test
cd /tmp/test
git init
git submodule add git@github.com:octocat/Hello-World.git
git commit -m "Add submodule"
git checkout -b other
cd Hello-World
git checkout 762941318ee16e59dabbacb1b4049eec22f0d303
cd ..
git add Hello-World
git commit -m "Change submodule commit"
# Add local modification
echo boo! > Hello-World/README
# Switch branches. This completes without error, and deletes the
change introduced in the previous line.
git checkout main --recurse-submodules
```
I believe part of the problem is that
762941318ee16e59dabbacb1b4049eec22f0d303 and
7fd1a60b01f91b314f59955a4e4d4e80d8edf11d (the Hello-World master
commit) are the same; the last line does report an error if I make
`other` point at 553c2077f0edc3d5dc5d17262f6aa498e69d6f8e instead of
the above commit. However, I don't think this changes the fact that
the above MWE makes git checkout --recurse-submodules look pretty
dangerous.
I'd love to hear if
1) the above is intended behavior,
2) I'm doing something wrong, or
3) this is a bug.
Best regards, and thanks for all your hard work,
Simon
^ permalink raw reply
* [PATCH 3/7] revision: use die_for_incompatible_opt3() for --graph/--reverse/--walk-reflogs
From: René Scharfe @ 2023-12-06 11:51 UTC (permalink / raw)
To: git
In-Reply-To: <20231206115215.94467-1-l.s.r@web.de>
The revision options --reverse is incompatibel with --walk-reflogs and
--graph is incompatible with both --reverse and --walk-reflogs. So they
are all incompatible with each other.
Use the function for checking three mutually incompatible options,
die_for_incompatible_opt3(), to perform this check in one place and
without repetition. This is shorter and clearer.
Signed-off-by: René Scharfe <l.s.r@web.de>
---
revision.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/revision.c b/revision.c
index b2861474b1..1b7e1af6c6 100644
--- a/revision.c
+++ b/revision.c
@@ -3036,8 +3036,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
revs->grep_filter.ignore_locale = 1;
compile_grep_patterns(&revs->grep_filter);
- if (revs->reverse && revs->reflog_info)
- die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--walk-reflogs");
if (revs->reflog_info && revs->limited)
die("cannot combine --walk-reflogs with history-limiting options");
if (revs->rewrite_parents && revs->children.name)
@@ -3048,11 +3046,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
/*
* Limitations on the graph functionality
*/
- if (revs->reverse && revs->graph)
- die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--graph");
+ die_for_incompatible_opt3(!!revs->graph, "--graph",
+ !!revs->reverse, "--reverse",
+ !!revs->reflog_info, "--walk-reflogs");
- if (revs->reflog_info && revs->graph)
- die(_("options '%s' and '%s' cannot be used together"), "--walk-reflogs", "--graph");
if (revs->no_walk && revs->graph)
die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
--
2.43.0
^ permalink raw reply related
* [PATCH 4/7] revision, rev-parse: factorize incompatibility messages about --exclude-hidden
From: René Scharfe @ 2023-12-06 11:51 UTC (permalink / raw)
To: git
In-Reply-To: <20231206115215.94467-1-l.s.r@web.de>
Use the standard parameterized message for reporting incompatible
options to report options that are not accepted in combination with
--exclude-hidden. This reduces the number of strings to translate and
makes the UI a bit more consistent.
Signed-off-by: René Scharfe <l.s.r@web.de>
---
builtin/rev-parse.c | 9 ++++++---
revision.c | 18 ++++++++++++------
t/t6018-rev-list-glob.sh | 6 ++----
t/t6021-rev-list-exclude-hidden.sh | 4 ++--
4 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index fde8861ca4..917f122440 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -893,13 +893,15 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
}
if (opt_with_value(arg, "--branches", &arg)) {
if (ref_excludes.hidden_refs_configured)
- return error(_("--exclude-hidden cannot be used together with --branches"));
+ return error(_("options '%s' and '%s' cannot be used together"),
+ "--exclude-hidden", "--branches");
handle_ref_opt(arg, "refs/heads/");
continue;
}
if (opt_with_value(arg, "--tags", &arg)) {
if (ref_excludes.hidden_refs_configured)
- return error(_("--exclude-hidden cannot be used together with --tags"));
+ return error(_("options '%s' and '%s' cannot be used together"),
+ "--exclude-hidden", "--tags");
handle_ref_opt(arg, "refs/tags/");
continue;
}
@@ -909,7 +911,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
}
if (opt_with_value(arg, "--remotes", &arg)) {
if (ref_excludes.hidden_refs_configured)
- return error(_("--exclude-hidden cannot be used together with --remotes"));
+ return error(_("options '%s' and '%s' cannot be used together"),
+ "--exclude-hidden", "--remotes");
handle_ref_opt(arg, "refs/remotes/");
continue;
}
diff --git a/revision.c b/revision.c
index 1b7e1af6c6..25335a74ad 100644
--- a/revision.c
+++ b/revision.c
@@ -2709,7 +2709,8 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
clear_ref_exclusions(&revs->ref_excludes);
} else if (!strcmp(arg, "--branches")) {
if (revs->ref_excludes.hidden_refs_configured)
- return error(_("--exclude-hidden cannot be used together with --branches"));
+ return error(_("options '%s' and '%s' cannot be used together"),
+ "--exclude-hidden", "--branches");
handle_refs(refs, revs, *flags, refs_for_each_branch_ref);
clear_ref_exclusions(&revs->ref_excludes);
} else if (!strcmp(arg, "--bisect")) {
@@ -2720,12 +2721,14 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
revs->bisect = 1;
} else if (!strcmp(arg, "--tags")) {
if (revs->ref_excludes.hidden_refs_configured)
- return error(_("--exclude-hidden cannot be used together with --tags"));
+ return error(_("options '%s' and '%s' cannot be used together"),
+ "--exclude-hidden", "--tags");
handle_refs(refs, revs, *flags, refs_for_each_tag_ref);
clear_ref_exclusions(&revs->ref_excludes);
} else if (!strcmp(arg, "--remotes")) {
if (revs->ref_excludes.hidden_refs_configured)
- return error(_("--exclude-hidden cannot be used together with --remotes"));
+ return error(_("options '%s' and '%s' cannot be used together"),
+ "--exclude-hidden", "--remotes");
handle_refs(refs, revs, *flags, refs_for_each_remote_ref);
clear_ref_exclusions(&revs->ref_excludes);
} else if ((argcount = parse_long_opt("glob", argv, &optarg))) {
@@ -2743,21 +2746,24 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
} else if (skip_prefix(arg, "--branches=", &optarg)) {
struct all_refs_cb cb;
if (revs->ref_excludes.hidden_refs_configured)
- return error(_("--exclude-hidden cannot be used together with --branches"));
+ return error(_("options '%s' and '%s' cannot be used together"),
+ "--exclude-hidden", "--branches");
init_all_refs_cb(&cb, revs, *flags);
for_each_glob_ref_in(handle_one_ref, optarg, "refs/heads/", &cb);
clear_ref_exclusions(&revs->ref_excludes);
} else if (skip_prefix(arg, "--tags=", &optarg)) {
struct all_refs_cb cb;
if (revs->ref_excludes.hidden_refs_configured)
- return error(_("--exclude-hidden cannot be used together with --tags"));
+ return error(_("options '%s' and '%s' cannot be used together"),
+ "--exclude-hidden", "--tags");
init_all_refs_cb(&cb, revs, *flags);
for_each_glob_ref_in(handle_one_ref, optarg, "refs/tags/", &cb);
clear_ref_exclusions(&revs->ref_excludes);
} else if (skip_prefix(arg, "--remotes=", &optarg)) {
struct all_refs_cb cb;
if (revs->ref_excludes.hidden_refs_configured)
- return error(_("--exclude-hidden cannot be used together with --remotes"));
+ return error(_("options '%s' and '%s' cannot be used together"),
+ "--exclude-hidden", "--remotes");
init_all_refs_cb(&cb, revs, *flags);
for_each_glob_ref_in(handle_one_ref, optarg, "refs/remotes/", &cb);
clear_ref_exclusions(&revs->ref_excludes);
diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh
index 67d523d405..3b181f771c 100755
--- a/t/t6018-rev-list-glob.sh
+++ b/t/t6018-rev-list-glob.sh
@@ -214,15 +214,13 @@ do
for pseudoopt in branches tags remotes
do
test_expect_success "rev-parse --exclude-hidden=$section fails with --$pseudoopt" '
- echo "error: --exclude-hidden cannot be used together with --$pseudoopt" >expected &&
test_must_fail git rev-parse --exclude-hidden=$section --$pseudoopt 2>err &&
- test_cmp expected err
+ test_grep "error: options .--exclude-hidden. and .--$pseudoopt. cannot be used together" err
'
test_expect_success "rev-parse --exclude-hidden=$section fails with --$pseudoopt=pattern" '
- echo "error: --exclude-hidden cannot be used together with --$pseudoopt" >expected &&
test_must_fail git rev-parse --exclude-hidden=$section --$pseudoopt=pattern 2>err &&
- test_cmp expected err
+ test_grep "error: options .--exclude-hidden. and .--$pseudoopt. cannot be used together" err
'
done
done
diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
index cdf7aa9427..51df02105d 100755
--- a/t/t6021-rev-list-exclude-hidden.sh
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -151,12 +151,12 @@ do
do
test_expect_success "$section: fails with --$pseudoopt" '
test_must_fail git rev-list --exclude-hidden=$section --$pseudoopt 2>err &&
- test_grep "error: --exclude-hidden cannot be used together with --$pseudoopt" err
+ test_grep "error: options .--exclude-hidden. and .--$pseudoopt. cannot be used together" err
'
test_expect_success "$section: fails with --$pseudoopt=pattern" '
test_must_fail git rev-list --exclude-hidden=$section --$pseudoopt=pattern 2>err &&
- test_grep "error: --exclude-hidden cannot be used together with --$pseudoopt" err
+ test_grep "error: options .--exclude-hidden. and .--$pseudoopt. cannot be used together" err
'
done
done
--
2.43.0
^ permalink raw reply related
* [PATCH 1/7] push: use die_for_incompatible_opt4() for --delete/--tags/--all/--mirror
From: René Scharfe @ 2023-12-06 11:51 UTC (permalink / raw)
To: git
In-Reply-To: <20231206115215.94467-1-l.s.r@web.de>
The push option --delete is incompatible with --all, --mirror, and
--tags; --tags is incompatible with --all and --mirror; --all is
incompatible with --mirror. This means they are all incompatible with
each other. And --branches is an alias for --all.
Use the function for checking four mutually incompatible options,
die_for_incompatible_opt4(), to perform this check in one place and
without repetition. This is shorter and clearer.
Signed-off-by: René Scharfe <l.s.r@web.de>
---
builtin/push.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/builtin/push.c b/builtin/push.c
index 2e708383c2..f77f424324 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -639,8 +639,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)
: &push_options_config);
set_push_cert_flags(&flags, push_cert);
- if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
- die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--branches/--mirror/--tags");
+ die_for_incompatible_opt4(deleterefs, "--delete",
+ tags, "--tags",
+ flags & TRANSPORT_PUSH_ALL, "--all/--branches",
+ flags & TRANSPORT_PUSH_MIRROR, "--mirror");
if (deleterefs && argc < 2)
die(_("--delete doesn't make sense without any refs"));
@@ -677,19 +679,13 @@ int cmd_push(int argc, const char **argv, const char *prefix)
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
if (flags & TRANSPORT_PUSH_ALL) {
- if (tags)
- die(_("options '%s' and '%s' cannot be used together"), "--all", "--tags");
if (argc >= 2)
die(_("--all can't be combined with refspecs"));
}
if (flags & TRANSPORT_PUSH_MIRROR) {
- if (tags)
- die(_("options '%s' and '%s' cannot be used together"), "--mirror", "--tags");
if (argc >= 2)
die(_("--mirror can't be combined with refspecs"));
}
- if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
- die(_("options '%s' and '%s' cannot be used together"), "--all", "--mirror");
if (!is_empty_cas(&cas) && (flags & TRANSPORT_PUSH_FORCE_IF_INCLUDES))
cas.use_force_if_includes = 1;
--
2.43.0
^ permalink raw reply related
* [PATCH 0/7] standardize incompatibility messages
From: René Scharfe @ 2023-12-06 11:51 UTC (permalink / raw)
To: git
More of what a699367bb8 (i18n: factorize more 'incompatible options'
messages, 2022-01-31) did: Simplify checks for multiple mutually
exclusive options, reduce the number of strings to translate, improve UI
consistency a bit.
push: use die_for_incompatible_opt4() for --delete/--tags/--all/--mirror
repack: use die_for_incompatible_opt3() for -A/-k/--cruft
revision: use die_for_incompatible_opt3() for --graph/--reverse/--walk-reflogs
revision, rev-parse: factorize incompatibility messages about --exclude-hidden
clean: factorize incompatibility message
worktree: standardize incompatibility messages
worktree: simplify incompatibility message for --orphan and commit-ish
builtin/clean.c | 2 +-
builtin/push.c | 12 ++++--------
builtin/repack.c | 14 ++++----------
builtin/rev-parse.c | 9 ++++++---
builtin/worktree.c | 21 +++++++++++----------
revision.c | 27 +++++++++++++++------------
t/t2400-worktree-add.sh | 2 +-
t/t6018-rev-list-glob.sh | 6 ++----
t/t6021-rev-list-exclude-hidden.sh | 4 ++--
9 files changed, 46 insertions(+), 51 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH 2/7] repack: use die_for_incompatible_opt3() for -A/-k/--cruft
From: René Scharfe @ 2023-12-06 11:51 UTC (permalink / raw)
To: git
In-Reply-To: <20231206115215.94467-1-l.s.r@web.de>
The repack option --keep-unreachable is incompatible with -A, --cruft is
incompatible with -A and -k, and -k is short for --keep-unreachable. So
they are all incompatible with each other.
Use the function for checking three mutually incompatible options,
die_for_incompatible_opt3(), to perform this check in one place and
without repetition. This is shorter and clearer.
Signed-off-by: René Scharfe <l.s.r@web.de>
---
builtin/repack.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/builtin/repack.c b/builtin/repack.c
index edaee4dbec..c54777bbe5 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -1203,19 +1203,13 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
if (delete_redundant && repository_format_precious_objects)
die(_("cannot delete packs in a precious-objects repo"));
- if (keep_unreachable &&
- (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
- die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "-A");
+ die_for_incompatible_opt3(unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE), "-A",
+ keep_unreachable, "-k/--keep-unreachable",
+ pack_everything & PACK_CRUFT, "--cruft");
- if (pack_everything & PACK_CRUFT) {
+ if (pack_everything & PACK_CRUFT)
pack_everything |= ALL_INTO_ONE;
- if (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE))
- die(_("options '%s' and '%s' cannot be used together"), "--cruft", "-A");
- if (keep_unreachable)
- die(_("options '%s' and '%s' cannot be used together"), "--cruft", "-k");
- }
-
if (write_bitmaps < 0) {
if (!write_midx &&
(!(pack_everything & ALL_INTO_ONE) || !is_bare_repository()))
--
2.43.0
^ permalink raw reply related
* [PATCH 5/7] clean: factorize incompatibility message
From: René Scharfe @ 2023-12-06 11:51 UTC (permalink / raw)
To: git
In-Reply-To: <20231206115215.94467-1-l.s.r@web.de>
Use the standard parameterized message for reporting incompatible
options to inform users that they can't use -x and -X together. This
reduces the number of strings to translate and makes the UI slightly
more consistent.
Signed-off-by: René Scharfe <l.s.r@web.de>
---
builtin/clean.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/builtin/clean.c b/builtin/clean.c
index 49c224e626..d90766cad3 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -971,7 +971,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
if (ignored && ignored_only)
- die(_("-x and -X cannot be used together"));
+ die(_("options '%s' and '%s' cannot be used together"), "-x", "-X");
if (!ignored)
setup_standard_excludes(&dir);
if (ignored_only)
--
2.43.0
^ permalink raw reply related
* [PATCH 7/7] worktree: simplify incompatibility message for --orphan and commit-ish
From: René Scharfe @ 2023-12-06 11:52 UTC (permalink / raw)
To: git
In-Reply-To: <20231206115215.94467-1-l.s.r@web.de>
Use a single translatable string to report that the worktree add option
--orphan is incompatible with a commit-ish instead of having the
commit-ish in a separate translatable string. This reduces the number
of strings to translate and gives translators the full context.
A similar message is used in builtin/describe.c, but with the plural of
commit-ish, and here we need the singular form.
Signed-off-by: René Scharfe <l.s.r@web.de>
---
builtin/worktree.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 036ceaa981..4ac1621541 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -815,8 +815,8 @@ static int add(int ac, const char **av, const char *prefix)
die(_("options '%s' and '%s' cannot be used together"),
"--orphan", "--no-checkout");
if (opts.orphan && ac == 2)
- die(_("'%s' and '%s' cannot be used together"), "--orphan",
- _("<commit-ish>"));
+ die(_("option '%s' and commit-ish cannot be used together"),
+ "--orphan");
if (lock_reason && !keep_locked)
die(_("the option '%s' requires '%s'"), "--reason", "--lock");
if (lock_reason)
--
2.43.0
^ permalink raw reply related
* [PATCH 6/7] worktree: standardize incompatibility messages
From: René Scharfe @ 2023-12-06 11:52 UTC (permalink / raw)
To: git
In-Reply-To: <20231206115215.94467-1-l.s.r@web.de>
Use the standard parameterized message for reporting incompatible
options for worktree add. This reduces the number of strings to
translate and makes the UI slightly more consistent.
Signed-off-by: René Scharfe <l.s.r@web.de>
---
builtin/worktree.c | 17 +++++++++--------
t/t2400-worktree-add.sh | 2 +-
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 62b7e26f4b..036ceaa981 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -730,11 +730,11 @@ static int dwim_orphan(const struct add_opts *opts, int opt_track, int remote)
}
if (opt_track) {
- die(_("'%s' and '%s' cannot be used together"), "--orphan",
- "--track");
+ die(_("options '%s' and '%s' cannot be used together"),
+ "--orphan", "--track");
} else if (!opts->checkout) {
- die(_("'%s' and '%s' cannot be used together"), "--orphan",
- "--no-checkout");
+ die(_("options '%s' and '%s' cannot be used together"),
+ "--orphan", "--no-checkout");
}
return 1;
}
@@ -806,13 +806,14 @@ static int add(int ac, const char **av, const char *prefix)
if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
die(_("options '%s', '%s', and '%s' cannot be used together"), "-b", "-B", "--detach");
if (opts.detach && opts.orphan)
- die(_("options '%s', and '%s' cannot be used together"),
+ die(_("options '%s' and '%s' cannot be used together"),
"--orphan", "--detach");
if (opts.orphan && opt_track)
- die(_("'%s' and '%s' cannot be used together"), "--orphan", "--track");
+ die(_("options '%s' and '%s' cannot be used together"),
+ "--orphan", "--track");
if (opts.orphan && !opts.checkout)
- die(_("'%s' and '%s' cannot be used together"), "--orphan",
- "--no-checkout");
+ die(_("options '%s' and '%s' cannot be used together"),
+ "--orphan", "--no-checkout");
if (opts.orphan && ac == 2)
die(_("'%s' and '%s' cannot be used together"), "--orphan",
_("<commit-ish>"));
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index df4aff7825..245656b53a 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -711,7 +711,7 @@ test_dwim_orphan () {
local fetch_error_text="fatal: No local or remote refs exist despite at least one remote" &&
local orphan_hint="hint: If you meant to create a worktree containing a new orphan branch" &&
local invalid_ref_regex="^fatal: invalid reference: " &&
- local bad_combo_regex="^fatal: '[-a-z]*' and '[-a-z]*' cannot be used together" &&
+ local bad_combo_regex="^fatal: options '[-a-z]*' and '[-a-z]*' cannot be used together" &&
local git_ns="repo" &&
local dashc_args="-C $git_ns" &&
--
2.43.0
^ permalink raw reply related
* [PATCH 0/7] clone: fix init of refdb with wrong object format
From: Patrick Steinhardt @ 2023-12-06 12:39 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 2793 bytes --]
Hi,
when using git-clone(1), we initialize the complete repository before we
know about the object format used by the remote repository. This means
that we'll potentially create the refdb with the wrong object format in
case the local default object format and remote object format are not
the same.
This isn't much of a problem in the context of the files backend, which
never records the object format anyway. But it is a problem for the
reftable backend, which indeed records the object format in the on-disk
data structures. The result is thus a reftable with wrong object format.
This patch series aims to solve this issue by initializing the refdb at
a later point after we have learned about the remote object format. This
requires some careful reordering of code. Unfortunately, the end result
is not easily verifiable and thus I didn't add tests here. But it does
fix cloning of SHA256 repositories with the in-progress state of the
reftable backend.
While at it I noticed that this actually fixes a bug with bundle URIs
when the object formats diverge in this way.
The series is layed out as follows:
- Patch 1 + 2: split out a function to create the refdb and make it
possible to skip its initialization in `init_db()`.
- Patch 3: allows git-remote-curl(1) to work with repos that get
initialized during its lifetime.
- Patch 4 - 6: address various corner cases where we access the refdb
before we learned about the object format.
- Patch 7: move initialization of the refdb to happen after we have
learned about the object format.
This patch series is actually the last incompatibility for the reftable
backend that I have found. All tests except for the files-backend
specific ones pass now with the current state I have at [1], which is
currently at e6f2f592b7 (t: skip tests which are incompatible with
reftable, 2023-11-24)
Thanks in advance for your reviews!
Patrick
Patrick Steinhardt (7):
setup: extract function to create the refdb
setup: allow skipping creation of the refdb
remote-curl: rediscover repository when fetching refs
builtin/clone: fix bundle URIs with mismatching object formats
builtin/clone: set up sparse checkout later
builtin/clone: skip reading HEAD when retrieving remote
builtin/clone: create the refdb with the correct object format
builtin/clone.c | 65 ++++++++++++----------
remote-curl.c | 7 ++-
remote.c | 26 +++++----
remote.h | 1 +
setup.c | 106 +++++++++++++++++++++---------------
setup.h | 6 +-
t/t5558-clone-bundle-uri.sh | 18 ++++++
7 files changed, 140 insertions(+), 89 deletions(-)
--
2.43.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH 1/7] setup: extract function to create the refdb
From: Patrick Steinhardt @ 2023-12-06 12:39 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1701863960.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 4260 bytes --]
We're about to let callers skip creation of the reference database when
calling `init_db()`. Extract the logic into a standalone function so
that it becomes easier to do this refactoring.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
setup.c | 95 ++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 57 insertions(+), 38 deletions(-)
diff --git a/setup.c b/setup.c
index fc592dc6dd..9fcb64159f 100644
--- a/setup.c
+++ b/setup.c
@@ -1885,6 +1885,60 @@ void initialize_repository_version(int hash_algo, int reinit)
git_config_set_gently("extensions.objectformat", NULL);
}
+static int is_reinit(void)
+{
+ struct strbuf buf = STRBUF_INIT;
+ char junk[2];
+ int ret;
+
+ git_path_buf(&buf, "HEAD");
+ ret = !access(buf.buf, R_OK) || readlink(buf.buf, junk, sizeof(junk) - 1) != -1;
+ strbuf_release(&buf);
+ return ret;
+}
+
+static 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.
+ */
+ safe_create_dir(git_path("refs"), 1);
+ adjust_shared_perm(git_path("refs"));
+
+ if (refs_init_db(&err))
+ die("failed to set up refs db: %s", err.buf);
+
+ /*
+ * Point the HEAD symref to the initial branch with if HEAD does
+ * not yet exist.
+ */
+ if (!reinit) {
+ char *ref;
+
+ if (!initial_branch)
+ initial_branch = git_default_branch_name(quiet);
+
+ ref = xstrfmt("refs/heads/%s", initial_branch);
+ if (check_refname_format(ref, 0) < 0)
+ die(_("invalid initial branch name: '%s'"),
+ initial_branch);
+
+ if (create_symref("HEAD", ref, NULL) < 0)
+ exit(1);
+ free(ref);
+ }
+
+ if (reinit && initial_branch)
+ warning(_("re-init: ignored --initial-branch=%s"),
+ initial_branch);
+
+ strbuf_release(&err);
+}
+
static int create_default_files(const char *template_path,
const char *original_git_dir,
const char *initial_branch,
@@ -1896,10 +1950,8 @@ static int create_default_files(const char *template_path,
struct stat st1;
struct strbuf buf = STRBUF_INIT;
char *path;
- char junk[2];
int reinit;
int filemode;
- struct strbuf err = STRBUF_INIT;
const char *init_template_dir = NULL;
const char *work_tree = get_git_work_tree();
@@ -1919,6 +1971,8 @@ static int create_default_files(const char *template_path,
reset_shared_repository();
git_config(git_default_config, NULL);
+ reinit = is_reinit();
+
/*
* We must make sure command-line options continue to override any
* values we might have just re-read from the config.
@@ -1962,39 +2016,7 @@ static int create_default_files(const char *template_path,
adjust_shared_perm(get_git_dir());
}
- /*
- * We need to create a "refs" dir in any case so that older
- * versions of git can tell that this is a repository.
- */
- safe_create_dir(git_path("refs"), 1);
- adjust_shared_perm(git_path("refs"));
-
- if (refs_init_db(&err))
- die("failed to set up refs db: %s", err.buf);
-
- /*
- * Point the HEAD symref to the initial branch with if HEAD does
- * not yet exist.
- */
- path = git_path_buf(&buf, "HEAD");
- reinit = (!access(path, R_OK)
- || readlink(path, junk, sizeof(junk)-1) != -1);
- if (!reinit) {
- char *ref;
-
- if (!initial_branch)
- initial_branch = git_default_branch_name(quiet);
-
- ref = xstrfmt("refs/heads/%s", initial_branch);
- if (check_refname_format(ref, 0) < 0)
- die(_("invalid initial branch name: '%s'"),
- initial_branch);
-
- if (create_symref("HEAD", ref, NULL) < 0)
- exit(1);
- free(ref);
- }
-
+ create_reference_database(initial_branch, quiet);
initialize_repository_version(fmt->hash_algo, 0);
/* Check filemode trustability */
@@ -2158,9 +2180,6 @@ int init_db(const char *git_dir, const char *real_git_dir,
prev_bare_repository,
init_shared_repository,
flags & INIT_DB_QUIET);
- if (reinit && initial_branch)
- warning(_("re-init: ignored --initial-branch=%s"),
- initial_branch);
create_object_directory();
--
2.43.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 2/7] setup: allow skipping creation of the refdb
From: Patrick Steinhardt @ 2023-12-06 12:39 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1701863960.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 2753 bytes --]
Allow callers to skip creation of the reference database via a new flag
`INIT_DB_SKIP_REFDB`, which is required for git-clone(1) so that we can
create it at a later point once the object format has been discovered
from the remote repository.
Note that we also uplift the call to `create_reference_database()` into
`init_db()`, which makes it easier to handle the new flag for us. This
changes the order in which we do initialization so that we now set up
the Git configuration before we create the reference database. In
practice this move should not result in any change in behaviour.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
setup.c | 13 +++++--------
setup.h | 5 +++--
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/setup.c b/setup.c
index 9fcb64159f..a80fc09b9c 100644
--- a/setup.c
+++ b/setup.c
@@ -1941,11 +1941,9 @@ static void create_reference_database(const char *initial_branch, int quiet)
static int create_default_files(const char *template_path,
const char *original_git_dir,
- const char *initial_branch,
const struct repository_format *fmt,
int prev_bare_repository,
- int init_shared_repository,
- int quiet)
+ int init_shared_repository)
{
struct stat st1;
struct strbuf buf = STRBUF_INIT;
@@ -2016,7 +2014,6 @@ static int create_default_files(const char *template_path,
adjust_shared_perm(get_git_dir());
}
- create_reference_database(initial_branch, quiet);
initialize_repository_version(fmt->hash_algo, 0);
/* Check filemode trustability */
@@ -2176,11 +2173,11 @@ int init_db(const char *git_dir, const char *real_git_dir,
validate_hash_algorithm(&repo_fmt, hash);
reinit = create_default_files(template_dir, original_git_dir,
- initial_branch, &repo_fmt,
- prev_bare_repository,
- init_shared_repository,
- flags & INIT_DB_QUIET);
+ &repo_fmt, prev_bare_repository,
+ init_shared_repository);
+ if (!(flags & INIT_DB_SKIP_REFDB))
+ create_reference_database(initial_branch, flags & INIT_DB_QUIET);
create_object_directory();
if (get_shared_repository()) {
diff --git a/setup.h b/setup.h
index b48cf1c43b..cbf538286b 100644
--- a/setup.h
+++ b/setup.h
@@ -169,8 +169,9 @@ int verify_repository_format(const struct repository_format *format,
*/
void check_repository_format(struct repository_format *fmt);
-#define INIT_DB_QUIET 0x0001
-#define INIT_DB_EXIST_OK 0x0002
+#define INIT_DB_QUIET (1 << 0)
+#define INIT_DB_EXIST_OK (1 << 1)
+#define INIT_DB_SKIP_REFDB (1 << 2)
int init_db(const char *git_dir, const char *real_git_dir,
const char *template_dir, int hash_algo,
--
2.43.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 3/7] remote-curl: rediscover repository when fetching refs
From: Patrick Steinhardt @ 2023-12-06 12:39 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1701863960.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 1997 bytes --]
We're about to change git-clone(1) so that we set up the reference
database at a later point. This change will cause git-remote-curl(1) to
not detect the repository anymore due to "HEAD" not having been created
yet at the time it spawns, and thus causes it to error out once it is
asked to fetch the references.
We can address this issue by trying to re-discover the Git repository in
case none was detected at startup time. With this change, the clone will
look as following:
1. git-clone(1) sets up the initial repository, excluding the
reference database.
2. git-clone(1) spawns git-remote-curl(1), which will be unable to
detect the repository due to a missing "HEAD".
3. git-clone(1) asks git-remote-curl(1) to list remote references.
This works just fine as this step does not require a local
repository
4. git-clone(1) creates the reference database as it has now learned
about the object format.
5. git-clone(1) asks git-remote-curl(1) to fetch the remote packfile.
The latter notices that it doesn't have a repository available, but
it now knows to try and re-discover it.
If the re-discovery succeeds in the last step we can continue with the
clone.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
remote-curl.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/remote-curl.c b/remote-curl.c
index ef05752ca5..fc29757b65 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -1564,8 +1564,11 @@ int cmd_main(int argc, const char **argv)
if (buf.len == 0)
break;
if (starts_with(buf.buf, "fetch ")) {
- if (nongit)
- die(_("remote-curl: fetch attempted without a local repo"));
+ if (nongit) {
+ setup_git_directory_gently(&nongit);
+ if (nongit)
+ die(_("remote-curl: fetch attempted without a local repo"));
+ }
parse_fetch(&buf);
} else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
--
2.43.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 4/7] builtin/clone: fix bundle URIs with mismatching object formats
From: Patrick Steinhardt @ 2023-12-06 12:40 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1701863960.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 6666 bytes --]
We create the reference database in git-clone(1) quite early before
connecting to the remote repository. Given that we do not yet know about
the object format that the remote repository uses at that point in time
the consequence is that the refdb may be initialized with the wrong
object format.
This is not a problem in the context of the files backend as we do not
encode the object format anywhere, and furthermore the only reference
that we write between initializing the refdb and learning about the
object format is the "HEAD" symref. It will become a problem though once
we land the reftable backend, which indeed does require to know about
the proper object format at the time of creation. We thus need to
rearrange the logic in git-clone(1) so that we only initialize the refdb
once we have learned about the actual object format.
As a first step, move listing of remote references to happen earlier,
which also allow us to set up the hash algorithm of the repository
earlier now. While we aim to execute this logic as late as possible
until after most of the setup has happened already, detection of the
object format and thus later the setup of the reference database must
happen before any other logic that may spawn Git commands or otherwise
these Git commands may not recognize the repository as such.
The first Git step where we expect the repository to be fully initalized
is when we fetch bundles via bundle URIs. Funny enough, the comments
there also state that "the_repository must match the cloned repo", which
is indeed not necessarily the case for the hash algorithm right now. So
in practice it is the right thing to detect the remote's object format
before downloading bundle URIs anyway, and not doing so causes clones
with bundle URIS to fail when the local default object format does not
match the remote repository's format.
Unfortunately though, this creates a new issue: downloading bundles may
take a long time, so if we list refs beforehand they might've grown
stale meanwhile. It is not clear how to solve this issue except for a
second reference listing though after we have downloaded the bundles,
which may be an expensive thing to do.
Arguably though, it's preferable to have a staleness issue compared to
being unable to clone a repository altogether.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/clone.c | 48 ++++++++++++++++++-------------------
t/t5558-clone-bundle-uri.sh | 18 ++++++++++++++
2 files changed, 41 insertions(+), 25 deletions(-)
diff --git a/builtin/clone.c b/builtin/clone.c
index c6357af949..d188650881 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1266,6 +1266,26 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (transport->smart_options && !deepen && !filter_options.choice)
transport->smart_options->check_self_contained_and_connected = 1;
+ strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
+ refspec_ref_prefixes(&remote->fetch,
+ &transport_ls_refs_options.ref_prefixes);
+ if (option_branch)
+ expand_ref_prefix(&transport_ls_refs_options.ref_prefixes,
+ option_branch);
+ if (!option_no_tags)
+ strvec_push(&transport_ls_refs_options.ref_prefixes,
+ "refs/tags/");
+
+ refs = transport_get_remote_refs(transport, &transport_ls_refs_options);
+
+ /*
+ * Now that we know what algorithm the remote side is using, let's set
+ * ours to the same thing.
+ */
+ 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);
+
/*
* Before fetching from the remote, download and install bundle
* data from the --bundle-uri option.
@@ -1281,24 +1301,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
bundle_uri);
else if (has_heuristic)
git_config_set_gently("fetch.bundleuri", bundle_uri);
- }
-
- strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
- refspec_ref_prefixes(&remote->fetch,
- &transport_ls_refs_options.ref_prefixes);
- if (option_branch)
- expand_ref_prefix(&transport_ls_refs_options.ref_prefixes,
- option_branch);
- if (!option_no_tags)
- strvec_push(&transport_ls_refs_options.ref_prefixes,
- "refs/tags/");
-
- refs = transport_get_remote_refs(transport, &transport_ls_refs_options);
-
- if (refs)
- mapped_refs = wanted_peer_refs(refs, &remote->fetch);
-
- if (!bundle_uri) {
+ } else {
/*
* Populate transport->got_remote_bundle_uri and
* transport->bundle_uri. We might get nothing.
@@ -1319,13 +1322,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
}
}
- /*
- * Now that we know what algorithm the remote side is using,
- * let's set ours to the same thing.
- */
- 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);
+ if (refs)
+ mapped_refs = wanted_peer_refs(refs, &remote->fetch);
if (mapped_refs) {
/*
diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh
index 996a08e90c..1ca5f745e7 100755
--- a/t/t5558-clone-bundle-uri.sh
+++ b/t/t5558-clone-bundle-uri.sh
@@ -33,6 +33,15 @@ test_expect_success 'clone with path bundle' '
test_cmp expect actual
'
+test_expect_success 'clone with path bundle and non-default hash' '
+ test_when_finished "rm -rf clone-path-non-default-hash" &&
+ GIT_DEFAULT_HASH=sha256 git clone --bundle-uri="clone-from/B.bundle" \
+ clone-from clone-path-non-default-hash &&
+ git -C clone-path-non-default-hash rev-parse refs/bundles/topic >actual &&
+ git -C clone-from rev-parse topic >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'clone with file:// bundle' '
git clone --bundle-uri="file://$(pwd)/clone-from/B.bundle" \
clone-from clone-file &&
@@ -284,6 +293,15 @@ test_expect_success 'clone HTTP bundle' '
test_config -C clone-http log.excludedecoration refs/bundle/
'
+test_expect_success 'clone HTTP bundle with non-default hash' '
+ test_when_finished "rm -rf clone-http-non-default-hash" &&
+ GIT_DEFAULT_HASH=sha256 git clone --bundle-uri="$HTTPD_URL/B.bundle" \
+ "$HTTPD_URL/smart/fetch.git" clone-http-non-default-hash &&
+ git -C clone-http-non-default-hash rev-parse refs/bundles/topic >actual &&
+ git -C clone-from rev-parse topic >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'clone bundle list (HTTP, no heuristic)' '
test_when_finished rm -f trace*.txt &&
--
2.43.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 5/7] builtin/clone: set up sparse checkout later
From: Patrick Steinhardt @ 2023-12-06 12:40 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1701863960.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 1387 bytes --]
When asked to do a sparse checkout, then git-clone(1) will spawn
`git sparse-checkout set` to set up the configuration accordingly. This
requires a proper Git repository or otherwise the command will fail. But
as we are about to move creation of the reference database to a later
point, this prerequisite will not hold anymore.
Move the logic to a later point in time where we know to have created
the reference database already.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/clone.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/builtin/clone.c b/builtin/clone.c
index d188650881..9c60923f31 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1185,9 +1185,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_required_reference.nr || option_optional_reference.nr)
setup_reference();
- if (option_sparse_checkout && git_sparse_checkout_init(dir))
- return 1;
-
remote = remote_get(remote_name);
refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
@@ -1426,6 +1423,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
dissociate_from_references();
}
+ if (option_sparse_checkout && git_sparse_checkout_init(dir))
+ return 1;
+
junk_mode = JUNK_LEAVE_REPO;
err = checkout(submodule_progress, filter_submodules);
--
2.43.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 6/7] builtin/clone: skip reading HEAD when retrieving remote
From: Patrick Steinhardt @ 2023-12-06 12:40 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1701863960.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 5197 bytes --]
After we have set up the remote configuration in git-clone(1) we'll call
`remote_get()` to read the remote from the on-disk configuration. But
next to reading the on-disk configuration, `remote_get()` will also
cause us to try and read the repository's HEAD reference so that we can
figure out the current branch. Besides being pointless in git-clone(1)
because we're operating in an empty repository anyway, this will also
break once we move creation of the reference database to a later point
in time.
Refactor the code to introduce a new `remote_get_early()` function that
will skip reading the HEAD reference to address this issue.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/clone.c | 2 +-
remote.c | 26 ++++++++++++++++----------
remote.h | 1 +
3 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/builtin/clone.c b/builtin/clone.c
index 9c60923f31..06966c5d4c 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1185,7 +1185,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_required_reference.nr || option_optional_reference.nr)
setup_reference();
- remote = remote_get(remote_name);
+ remote = remote_get_early(remote_name);
refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
branch_top.buf);
diff --git a/remote.c b/remote.c
index abb24822be..051d0a64a0 100644
--- a/remote.c
+++ b/remote.c
@@ -509,7 +509,7 @@ static void alias_all_urls(struct remote_state *remote_state)
}
}
-static void read_config(struct repository *repo)
+static void read_config(struct repository *repo, int early)
{
int flag;
@@ -518,7 +518,7 @@ static void read_config(struct repository *repo)
repo->remote_state->initialized = 1;
repo->remote_state->current_branch = NULL;
- if (startup_info->have_repository) {
+ if (startup_info->have_repository && !early) {
const char *head_ref = refs_resolve_ref_unsafe(
get_main_ref_store(repo), "HEAD", 0, NULL, &flag);
if (head_ref && (flag & REF_ISSYMREF) &&
@@ -561,7 +561,7 @@ static const char *remotes_remote_for_branch(struct remote_state *remote_state,
const char *remote_for_branch(struct branch *branch, int *explicit)
{
- read_config(the_repository);
+ read_config(the_repository, 0);
die_on_missing_branch(the_repository, branch);
return remotes_remote_for_branch(the_repository->remote_state, branch,
@@ -587,7 +587,7 @@ remotes_pushremote_for_branch(struct remote_state *remote_state,
const char *pushremote_for_branch(struct branch *branch, int *explicit)
{
- read_config(the_repository);
+ read_config(the_repository, 0);
die_on_missing_branch(the_repository, branch);
return remotes_pushremote_for_branch(the_repository->remote_state,
@@ -599,7 +599,7 @@ static struct remote *remotes_remote_get(struct remote_state *remote_state,
const char *remote_ref_for_branch(struct branch *branch, int for_push)
{
- read_config(the_repository);
+ read_config(the_repository, 0);
die_on_missing_branch(the_repository, branch);
if (branch) {
@@ -709,7 +709,13 @@ remotes_remote_get(struct remote_state *remote_state, const char *name)
struct remote *remote_get(const char *name)
{
- read_config(the_repository);
+ read_config(the_repository, 0);
+ return remotes_remote_get(the_repository->remote_state, name);
+}
+
+struct remote *remote_get_early(const char *name)
+{
+ read_config(the_repository, 1);
return remotes_remote_get(the_repository->remote_state, name);
}
@@ -722,7 +728,7 @@ remotes_pushremote_get(struct remote_state *remote_state, const char *name)
struct remote *pushremote_get(const char *name)
{
- read_config(the_repository);
+ read_config(the_repository, 0);
return remotes_pushremote_get(the_repository->remote_state, name);
}
@@ -738,7 +744,7 @@ int remote_is_configured(struct remote *remote, int in_repo)
int for_each_remote(each_remote_fn fn, void *priv)
{
int i, result = 0;
- read_config(the_repository);
+ read_config(the_repository, 0);
for (i = 0; i < the_repository->remote_state->remotes_nr && !result;
i++) {
struct remote *remote =
@@ -1831,7 +1837,7 @@ struct branch *branch_get(const char *name)
{
struct branch *ret;
- read_config(the_repository);
+ read_config(the_repository, 0);
if (!name || !*name || !strcmp(name, "HEAD"))
ret = the_repository->remote_state->current_branch;
else
@@ -1973,7 +1979,7 @@ static const char *branch_get_push_1(struct remote_state *remote_state,
const char *branch_get_push(struct branch *branch, struct strbuf *err)
{
- read_config(the_repository);
+ read_config(the_repository, 0);
die_on_missing_branch(the_repository, branch);
if (!branch)
diff --git a/remote.h b/remote.h
index cdc8b1db42..79353ba226 100644
--- a/remote.h
+++ b/remote.h
@@ -118,6 +118,7 @@ struct remote {
* and configuration.
*/
struct remote *remote_get(const char *name);
+struct remote *remote_get_early(const char *name);
struct remote *pushremote_get(const char *name);
int remote_is_configured(struct remote *remote, int in_repo);
--
2.43.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply related
* [PATCH 7/7] builtin/clone: create the refdb with the correct object format
From: Patrick Steinhardt @ 2023-12-06 12:40 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1701863960.git.ps@pks.im>
[-- Attachment #1: Type: text/plain, Size: 3121 bytes --]
We're currently creating the reference database with a potentially
incorrect object format when the remote repository's object format is
different from the local default object format. This works just fine for
now because the files backend never records the object format anywhere.
But this logic will fail with any new reference backend that encodes
this information in some form either on-disk or in-memory.
The preceding commits have reshuffled code in git-clone(1) so that there
is no code path that will access the reference database before we have
detected the remote's object format. With these refactorings we can now
defer initialization of the reference database until after we have
learned the remote's object format and thus initialize it with the
correct format from the get-go.
These refactorings are required to make git-clone(1) work with the
upcoming reftable backend when cloning repositories with the SHA256
object format.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/clone.c | 9 ++++++++-
setup.c | 2 +-
setup.h | 1 +
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/builtin/clone.c b/builtin/clone.c
index 06966c5d4c..fd052b8b54 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1097,8 +1097,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
}
}
+ /*
+ * Initialize the repository, but skip initializing the reference
+ * database. We do not yet know about the object format of the
+ * 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,
- do_not_override_repo_unix_permissions, INIT_DB_QUIET);
+ do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
if (real_git_dir) {
free((char *)git_dir);
@@ -1282,6 +1288,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);
/*
* Before fetching from the remote, download and install bundle
diff --git a/setup.c b/setup.c
index a80fc09b9c..e1d0ce29c6 100644
--- a/setup.c
+++ b/setup.c
@@ -1897,7 +1897,7 @@ static int is_reinit(void)
return ret;
}
-static void create_reference_database(const char *initial_branch, int quiet)
+void create_reference_database(const char *initial_branch, int quiet)
{
struct strbuf err = STRBUF_INIT;
int reinit = is_reinit();
diff --git a/setup.h b/setup.h
index cbf538286b..3f0f17c351 100644
--- a/setup.h
+++ b/setup.h
@@ -178,6 +178,7 @@ int init_db(const char *git_dir, const char *real_git_dir,
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);
/*
* NOTE NOTE NOTE!!
--
2.43.0
[-- 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