-
Notifications
You must be signed in to change notification settings - Fork 137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
remote: branch setting fixes #1789
base: master
Are you sure you want to change the base?
Changes from all commits
d95a07a
a8dfe40
f30c77b
dba3124
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,6 +132,19 @@ static void add_branch(const char *key, const char *branchname, | |
git_config_set_multivar(key, tmp->buf, "^$", 0); | ||
} | ||
|
||
static int check_branch_names(const char **branches) | ||
{ | ||
int ret = 0; | ||
|
||
for (const char **b = branches; *b; b++) { | ||
if (check_refname_format(*b, REFNAME_ALLOW_ONELEVEL | | ||
REFNAME_REFSPEC_PATTERN)) | ||
ret = error(_("invalid branch name '%s'"), *b); | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
static const char mirror_advice[] = | ||
N_("--mirror is dangerous and deprecated; please\n" | ||
"\t use --mirror=fetch or --mirror=push instead"); | ||
|
@@ -158,7 +171,7 @@ static int add(int argc, const char **argv, const char *prefix) | |
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the Git mailing list, Junio C Hamano wrote (reply to this): "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> Store the list of branches to track in a ’struct strvec' instead of a
> 'struct string_list'. This in preparation for the next commit where it
> will be convenient to have them stored in a NULL terminated array. This
> means that we now duplicate the strings when storing them but the
> overhead is not significant.
>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
> builtin/remote.c | 13 ++++++-------
> 1 file changed, 6 insertions(+), 7 deletions(-)
This has a slight conflict with a topic that has already graduated
but nothing serious. If you need to reroll, you may want to base it
on a bit more recent tip of 'master', younger than bb424845 (Merge
branch 'rs/remote-leakfix', 2024-09-03).
Thanks.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the Git mailing list, Patrick Steinhardt wrote (reply to this): On Wed, Sep 11, 2024 at 03:18:36PM +0000, Phillip Wood via GitGitGadget wrote:
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> Store the list of branches to track in a ’struct strvec' instead of a
> 'struct string_list'. This in preparation for the next commit where it
s/in/is &/
> will be convenient to have them stored in a NULL terminated array. This
> means that we now duplicate the strings when storing them but the
> overhead is not significant.
Yup. Micro-optimizations like this typically don't really have any real
world effect anyway.
Patrick |
||
int fetch = 0, fetch_tags = TAGS_DEFAULT; | ||
unsigned mirror = MIRROR_NONE; | ||
struct string_list track = STRING_LIST_INIT_NODUP; | ||
struct strvec track = STRVEC_INIT; | ||
const char *master = NULL; | ||
struct remote *remote; | ||
struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT; | ||
|
@@ -171,8 +184,8 @@ static int add(int argc, const char **argv, const char *prefix) | |
N_("import all tags and associated objects when fetching\n" | ||
"or do not fetch any tag at all (--no-tags)"), | ||
TAGS_SET), | ||
OPT_STRING_LIST('t', "track", &track, N_("branch"), | ||
N_("branch(es) to track")), | ||
OPT_STRVEC('t', "track", &track, N_("branch"), | ||
N_("branch(es) to track")), | ||
OPT_STRING('m', "master", &master, N_("branch"), N_("master branch")), | ||
OPT_CALLBACK_F(0, "mirror", &mirror, "(push|fetch)", | ||
N_("set up remote as a mirror to push to or fetch from"), | ||
|
@@ -203,17 +216,19 @@ static int add(int argc, const char **argv, const char *prefix) | |
if (!valid_remote_name(name)) | ||
die(_("'%s' is not a valid remote name"), name); | ||
|
||
if (check_branch_names(track.v)) | ||
exit(128); | ||
|
||
strbuf_addf(&buf, "remote.%s.url", name); | ||
git_config_set(buf.buf, url); | ||
|
||
if (!mirror || mirror & MIRROR_FETCH) { | ||
strbuf_reset(&buf); | ||
strbuf_addf(&buf, "remote.%s.fetch", name); | ||
if (track.nr == 0) | ||
string_list_append(&track, "*"); | ||
strvec_push(&track, "*"); | ||
for (i = 0; i < track.nr; i++) { | ||
add_branch(buf.buf, track.items[i].string, | ||
name, mirror, &buf2); | ||
add_branch(buf.buf, track.v[i], name, mirror, &buf2); | ||
} | ||
} | ||
|
||
|
@@ -246,7 +261,7 @@ static int add(int argc, const char **argv, const char *prefix) | |
|
||
strbuf_release(&buf); | ||
strbuf_release(&buf2); | ||
string_list_clear(&track, 0); | ||
strvec_clear(&track); | ||
|
||
return 0; | ||
} | ||
|
@@ -1567,8 +1582,12 @@ static int update(int argc, const char **argv, const char *prefix) | |
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the Git mailing list, Junio C Hamano wrote (reply to this): "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> To replace the list of branches to be fetched "git remote set-branches"
> first removes the fetch refspecs for the remote and then creates a new
> set of fetch refspecs based and the branches passed on the commandline.
> When deleting the existing refspecs git_config_set_multivar_gently()
> will return a non-zero result if there was nothing to delete.
> Unfortunately the calling code treats that as an error and bails out
> rather than setting up the new branches. Fix this by not treating a
> return value of CONFIG_NOTHING_SET as an error.
Makes sense.
> diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
> index 08424e878e1..cfbd6139e00 100755
> --- a/t/t5505-remote.sh
> +++ b/t/t5505-remote.sh
> @@ -1131,7 +1131,9 @@ test_expect_success 'remote set-branches' '
> +refs/heads/next:refs/remotes/scratch/next
> +refs/heads/seen:refs/remotes/scratch/seen
> EOF
> -
> + cat <<-\EOF >expect.replace-missing &&
> + +refs/heads/topic:refs/remotes/scratch/topic
> + EOF
> git clone .git/ setbranches &&
> (
> cd setbranches &&
> @@ -1161,14 +1163,20 @@ test_expect_success 'remote set-branches' '
>
> git remote set-branches --add scratch seen &&
> git config --get-all remote.scratch.fetch >config-result &&
> - sort <config-result >../actual.respect-ffonly
> + sort <config-result >../actual.respect-ffonly &&
> +
> + git config --unset-all remote.scratch.fetch &&
OK, so we get rid of all "fetch" refspec elements and make sure we
can ...
> + git remote set-branches scratch topic &&
... set a single new one like this ...
> + git config --get-all remote.scratch.fetch \
> + >../actual.replace-missing
and we expect the mapping to appear in the output. For
maintainability, it would be better to also sort this one to mimick
the other one that contain multiple entries in the output, but
because we expect only one entry to be in the output, not sorting is
OK for now.
Looks good. Thanks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the Git mailing list, Patrick Steinhardt wrote (reply to this): On Wed, Sep 11, 2024 at 03:18:34PM +0000, Phillip Wood via GitGitGadget wrote:
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> To replace the list of branches to be fetched "git remote set-branches"
> first removes the fetch refspecs for the remote and then creates a new
> set of fetch refspecs based and the branches passed on the commandline.
s/and/on/
> When deleting the existing refspecs git_config_set_multivar_gently()
> will return a non-zero result if there was nothing to delete.
> Unfortunately the calling code treats that as an error and bails out
> rather than setting up the new branches. Fix this by not treating a
> return value of CONFIG_NOTHING_SET as an error.
>
> Reported-by: Han Jiang <jhcarl0814@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
> builtin/remote.c | 8 ++++++--
> t/t5505-remote.sh | 14 +++++++++++---
> 2 files changed, 17 insertions(+), 5 deletions(-)
>
> diff --git a/builtin/remote.c b/builtin/remote.c
> index d1f9292ed2b..794396ba02f 100644
> --- a/builtin/remote.c
> +++ b/builtin/remote.c
> @@ -1567,8 +1567,12 @@ static int update(int argc, const char **argv, const char *prefix)
>
> static int remove_all_fetch_refspecs(const char *key)
> {
> - return git_config_set_multivar_gently(key, NULL, NULL,
> - CONFIG_FLAGS_MULTI_REPLACE);
> + int res = git_config_set_multivar_gently(key, NULL, NULL,
> + CONFIG_FLAGS_MULTI_REPLACE);
> + if (res == CONFIG_NOTHING_SET)
> + res = 0;
> +
> + return res;
> }
Makes sense.
> static void add_branches(struct remote *remote, const char **branches,
> diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
> index 08424e878e1..cfbd6139e00 100755
> --- a/t/t5505-remote.sh
> +++ b/t/t5505-remote.sh
> @@ -1131,7 +1131,9 @@ test_expect_success 'remote set-branches' '
> +refs/heads/next:refs/remotes/scratch/next
> +refs/heads/seen:refs/remotes/scratch/seen
> EOF
> -
> + cat <<-\EOF >expect.replace-missing &&
s/ / /
Also, the redirect typically comes before the heredoc marker.
> + +refs/heads/topic:refs/remotes/scratch/topic
> + EOF
> git clone .git/ setbranches &&
> (
> cd setbranches &&
> @@ -1161,14 +1163,20 @@ test_expect_success 'remote set-branches' '
>
> git remote set-branches --add scratch seen &&
> git config --get-all remote.scratch.fetch >config-result &&
> - sort <config-result >../actual.respect-ffonly
> + sort <config-result >../actual.respect-ffonly &&
> +
> + git config --unset-all remote.scratch.fetch &&
> + git remote set-branches scratch topic &&
> + git config --get-all remote.scratch.fetch \
> + >../actual.replace-missing
I wonder whether we'd rather wnat to wire this up in a new test instead
of altering an existing one.
Patrick |
||
static int remove_all_fetch_refspecs(const char *key) | ||
{ | ||
return git_config_set_multivar_gently(key, NULL, NULL, | ||
CONFIG_FLAGS_MULTI_REPLACE); | ||
int res = git_config_set_multivar_gently(key, NULL, NULL, | ||
CONFIG_FLAGS_MULTI_REPLACE); | ||
if (res == CONFIG_NOTHING_SET) | ||
res = 0; | ||
|
||
return res; | ||
} | ||
|
||
static void add_branches(struct remote *remote, const char **branches, | ||
|
@@ -1598,7 +1617,11 @@ static int set_remote_branches(const char *remotename, const char **branches, | |
exit(2); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the Git mailing list, Junio C Hamano wrote (reply to this): "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> If the existing fetch refspecs cannot be removed when replacing the set
> of branches to fetch with "git remote set-branches" the command silently
> fails. Add an error message to tell the user what when wrong.
>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
> builtin/remote.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/builtin/remote.c b/builtin/remote.c
> index 794396ba02f..4dbf7a4c506 100644
> --- a/builtin/remote.c
> +++ b/builtin/remote.c
> @@ -1603,6 +1603,7 @@ static int set_remote_branches(const char *remotename, const char **branches,
> }
>
> if (!add_mode && remove_all_fetch_refspecs(key.buf)) {
> + error(_("could not remove existing fetch refspec"));
> strbuf_release(&key);
> return 1;
> }
It is a minor point, but would it help to say what we tried to
remove (e.g. "from remote X") or is it too obvious to the end user
in the context they get this error?
The reason why I had the above question was because inserting error()
before strbuf_release(&key) looked curious and I initially suspected
that it was because key was used in the error message somehow, but it
turns out that is not the case at all.
IOW, I would have expected something more like this:
if (!add_mode && remove_all_fetch_refspecs(key.buf)) {
strbuf_release(&key);
+ return error(_("failed to remove fetch refspec from '%s'"),
+ remotename);
}
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the Git mailing list, Patrick Steinhardt wrote (reply to this): On Wed, Sep 11, 2024 at 01:52:16PM -0700, Junio C Hamano wrote:
> "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > From: Phillip Wood <phillip.wood@dunelm.org.uk>
> >
> > If the existing fetch refspecs cannot be removed when replacing the set
> > of branches to fetch with "git remote set-branches" the command silently
> > fails. Add an error message to tell the user what when wrong.
> >
> > Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> > ---
> > builtin/remote.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/builtin/remote.c b/builtin/remote.c
> > index 794396ba02f..4dbf7a4c506 100644
> > --- a/builtin/remote.c
> > +++ b/builtin/remote.c
> > @@ -1603,6 +1603,7 @@ static int set_remote_branches(const char *remotename, const char **branches,
> > }
> >
> > if (!add_mode && remove_all_fetch_refspecs(key.buf)) {
> > + error(_("could not remove existing fetch refspec"));
> > strbuf_release(&key);
> > return 1;
> > }
>
> It is a minor point, but would it help to say what we tried to
> remove (e.g. "from remote X") or is it too obvious to the end user
> in the context they get this error?
>
> The reason why I had the above question was because inserting error()
> before strbuf_release(&key) looked curious and I initially suspected
> that it was because key was used in the error message somehow, but it
> turns out that is not the case at all.
>
> IOW, I would have expected something more like this:
>
> if (!add_mode && remove_all_fetch_refspecs(key.buf)) {
> strbuf_release(&key);
> + return error(_("failed to remove fetch refspec from '%s'"),
> + remotename);
>
> }
I don't think we want to return the error code from `error()`, do we?
`set_branches()` is wired up as a subcommand, so we'd ultimately do
`exit(-1)` instead of `exit(1)` if we returned the `error()` code here.
Patrick There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the Git mailing list, Junio C Hamano wrote (reply to this): Patrick Steinhardt <ps@pks.im> writes:
> I don't think we want to return the error code from `error()`, do we?
> `set_branches()` is wired up as a subcommand, so we'd ultimately do
> `exit(-1)` instead of `exit(1)` if we returned the `error()` code here.
Hmph, I thought there was somebody doing !! to canonicalize the
return value to exit status in the call chain.
... goes and looks again ...
After finding the subcommand in fn, cmd_remote() ends with
if (fn) {
return !!fn(argc, argv, prefix);
} else {
...
return !!show_all();
}
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the Git mailing list, Patrick Steinhardt wrote (reply to this): On Thu, Sep 12, 2024 at 09:22:13AM -0700, Junio C Hamano wrote:
> Patrick Steinhardt <ps@pks.im> writes:
>
> > I don't think we want to return the error code from `error()`, do we?
> > `set_branches()` is wired up as a subcommand, so we'd ultimately do
> > `exit(-1)` instead of `exit(1)` if we returned the `error()` code here.
>
> Hmph, I thought there was somebody doing !! to canonicalize the
> return value to exit status in the call chain.
>
> ... goes and looks again ...
>
> After finding the subcommand in fn, cmd_remote() ends with
>
> if (fn) {
> return !!fn(argc, argv, prefix);
> } else {
> ...
> return !!show_all();
> }
Ah, never mind in that case. I didn't look far enough indeed. Thanks for
correcting my claim!
Patrick There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the Git mailing list, phillip.wood123@gmail.com wrote (reply to this): On 11/09/2024 21:52, Junio C Hamano wrote:
> "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:
>> if (!add_mode && remove_all_fetch_refspecs(key.buf)) {
>> + error(_("could not remove existing fetch refspec"));
>> strbuf_release(&key);
>> return 1;
>> }
> > It is a minor point, but would it help to say what we tried to
> remove (e.g. "from remote X") or is it too obvious to the end user
> in the context they get this error?
The user has to give the remote name on the command line so I think it should be obvious to the user.
> The reason why I had the above question was because inserting error()
> before strbuf_release(&key) looked curious and I initially suspected
> that it was because key was used in the error message somehow, but it
> turns out that is not the case at all.
Arguably we should refactor this to use our standard "goto cleanup" pattern.
Best Wishes
Phillip
> IOW, I would have expected something more like this:
> > if (!add_mode && remove_all_fetch_refspecs(key.buf)) {
> strbuf_release(&key);
> + return error(_("failed to remove fetch refspec from '%s'"),
> + remotename);
> > }
> There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the Git mailing list, Junio C Hamano wrote (reply to this): phillip.wood123@gmail.com writes:
> On 11/09/2024 21:52, Junio C Hamano wrote:
>> "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:
>>> if (!add_mode && remove_all_fetch_refspecs(key.buf)) {
>>> + error(_("could not remove existing fetch refspec"));
>>> strbuf_release(&key);
>>> return 1;
>>> }
>> It is a minor point, but would it help to say what we tried to
>> remove (e.g. "from remote X") or is it too obvious to the end user
>> in the context they get this error?
>
> The user has to give the remote name on the command line so I think it
> should be obvious to the user.
That makes sense. Thanks. |
||
|
||
if (check_branch_names(branches)) | ||
exit(128); | ||
|
||
if (!add_mode && remove_all_fetch_refspecs(key.buf)) { | ||
error(_("could not remove existing fetch refspec")); | ||
strbuf_release(&key); | ||
return 1; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, Junio C Hamano wrote (reply to this):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, Patrick Steinhardt wrote (reply to this):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, Junio C Hamano wrote (reply to this):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, phillip.wood123@gmail.com wrote (reply to this):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, Junio C Hamano wrote (reply to this):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, phillip.wood123@gmail.com wrote (reply to this):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, Junio C Hamano wrote (reply to this):