From: "Rubén Justo" <rjusto@gmail.com>
To: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Cc: Git List <git@vger.kernel.org>, Junio C Hamano <gitster@pobox.com>
Subject: Re: [PATCH v3 0/3] branch: operations on orphan branches
Date: Wed, 8 Feb 2023 01:35:26 +0100 [thread overview]
Message-ID: <1450c94f-b0e4-a424-edd4-8c88b72febf5@gmail.com> (raw)
In-Reply-To: <230207.86cz6l501v.gmgdl@evledraar.gmail.com>
On 07-feb-2023 09:33:39, Ævar Arnfjörð Bjarmason wrote:
Thank you reviewing this.
>
> On Tue, Feb 07 2023, Rubén Justo wrote:
>
> > Avoid some confusing errors operating with orphan branches when
> > working with worktrees.
> >
> > Changes from v2:
> >
> > - Renamed "ishead_and_reject_rebase_or_bisect_branch()" to
> > "die_if_branch_is_being_rebased_or_bisected()"
>
> Looking this over holistically, I think this is a great example of where
> factoring something out into a function is just making readbility
> worse. This function is only used in copy_or_rename_branch(), and the
> overloaded name & semantics are making things quite confusing.
>
> Whereas if we just start by pulling it into its only caller I think this
> gets much better, at the end of this message is a diff-on-top these
> three patches where I do that (I kept the "target" variable to minimize
> the diff with the move detection, but we probalby want the strbuf
> directly instead).
I'm sorry, but I don't agree. copy_or_rename_branch() already does some
heterogeneous things. IMHO, making it also iterate worktrees makes
things worse, in terms of readability. I could agree with maybe the
function die_if_branch_is_being_rebased_or_bisected() could be part of a
more general use, maybe something in worktree.h.
> > A proposed name "die_if_branch_is_is_use()" has not been used because
> > it could lead to confusion. We don't yet support copying or renaming
> > a branch being rebased or bisected, but we do under other uses.
>
> Another thing that I think could be improved in this series is if you
> skip the refactoring-while-at-it of changing the existing
> "if/if/die/die" into a "if/die/?:".
I'm sorry, but I don't agree with this reasoning either. The ternary op
here allows the code to be more clear, IMHO, in the intention: there is
no conditional die() or error(), the conditional is for the message.
>
> In the below diff I have that proposed change on top, but this snippet
> here shows the diff to "origin/master":
>
> @@ -806,7 +806,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
>
> strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
> if (!ref_exists(branch_ref.buf))
> - error((!argc || !strcmp(head, branch_name))
> + error((!argc || branch_checked_out(branch_ref.buf))
> ? _("No commit on branch '%s' yet.")
> : _("No branch named '%s'."),
> branch_name);
> @@ -851,10 +851,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
> }
>
> if (!ref_exists(branch->refname)) {
> - if (!argc || !strcmp(head, branch->name))
> + if (!argc || branch_checked_out(branch->refname))
> die(_("No commit on branch '%s' yet."), branch->name);
> die(_("branch '%s' does not exist"), branch->name);
> }
>
> I.e. your refactoring of this in 2/3 turns out to in the end have just
> been inflating the code change, for no functional benefit.
>
> I wouldn't mind if this were in some pre-cleanup, or if it actually made
> the code easier to read, but IMO this pattern of using a ternary to
> select the format to "error" or "die" makes things worse for
> readability. It's a few bytes less code, but makes things harder to follow overall.
>
> And even if you disagree with that as far as the end state is concerned,
> I think it's unarguable that it makes the 2/3 harder to follow, since
> it's sticking a refactoring that's not neede dfor the end-goal here into
> an otherwise functional change.
>
> I'm aware that some of the code in the context uses this pattern, and
> you probably changed the "if" block you modified to be consistent with
> the code above, but I think in this case it's better not to follow the
> existing style (which is used in that function, but is a rare exception
> overall in this codebase).
>
> The diff-on-top, mentioned above:
>
> == BEGIN
>
> diff --git a/builtin/branch.c b/builtin/branch.c
> index 7efda622241..dc7a3e3dde1 100644
> --- a/builtin/branch.c
> +++ b/builtin/branch.c
> @@ -486,45 +486,16 @@ static void print_current_branch_name(void)
> die(_("HEAD (%s) points outside of refs/heads/"), refname);
> }
>
> -/*
> - * Dies if the specified branch is being rebased or bisected. Otherwise returns
> - * 0 or, if the branch is HEAD in any worktree, returns 1. If the branch is HEAD
> - * and also orphan, returns 2.
> - */
> -static int die_if_branch_is_being_rebased_or_bisected(const char *target)
> -{
> - struct worktree **worktrees = get_worktrees();
> - int i, ret = 0;
> -
> - for (i = 0; worktrees[i]; i++) {
> - struct worktree *wt = worktrees[i];
> -
> - if (wt->head_ref && !strcmp(target, wt->head_ref))
> - ret = is_null_oid(&wt->head_oid) ? 2 : 1;
> -
> - if (!wt->is_detached)
> - continue;
> -
> - if (is_worktree_being_rebased(wt, target))
> - die(_("Branch %s is being rebased at %s"),
> - target, wt->path);
> -
> - if (is_worktree_being_bisected(wt, target))
> - die(_("Branch %s is being bisected at %s"),
> - target, wt->path);
> - }
> -
> - free_worktrees(worktrees);
> - return ret;
> -}
> -
> static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force)
> {
> struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
> struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
> const char *interpreted_oldname = NULL;
> const char *interpreted_newname = NULL;
> - int recovery = 0, oldref_is_head, oldref_is_orphan;
> + int recovery = 0, oldref_is_head = 0, oldref_is_orphan = 0;
> + struct worktree **worktrees;
> + int i;
> + const char *target;
>
> if (strbuf_check_branch_ref(&oldref, oldname)) {
> /*
> @@ -537,8 +508,29 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
> die(_("Invalid branch name: '%s'"), oldname);
> }
>
> - oldref_is_head = die_if_branch_is_being_rebased_or_bisected(oldref.buf);
> - oldref_is_orphan = (oldref_is_head > 1);
> + worktrees = get_worktrees();
> + target = oldref.buf;
> + for (i = 0; worktrees[i]; i++) {
> + struct worktree *wt = worktrees[i];
> +
> + if (wt->head_ref && !strcmp(target, wt->head_ref)) {
> + oldref_is_head = 1;
> + if (is_null_oid(&wt->head_oid))
> + oldref_is_orphan = 1;
> + }
> +
> + if (!wt->is_detached)
> + continue;
> +
> + if (is_worktree_being_rebased(wt, target))
> + die(_("Branch %s is being rebased at %s"),
> + target, wt->path);
> +
> + if (is_worktree_being_bisected(wt, target))
> + die(_("Branch %s is being bisected at %s"),
> + target, wt->path);
> + }
> + free_worktrees(worktrees);
>
> if ((copy || !oldref_is_head) &&
> (oldref_is_orphan || !ref_exists(oldref.buf)))
> @@ -858,10 +850,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
> die(_("no such branch '%s'"), argv[0]);
> }
>
> - if (!ref_exists(branch->refname))
> - die((!argc || branch_checked_out(branch->refname))
> - ? _("No commit on branch '%s' yet.")
> - : _("branch '%s' does not exist"), branch->name);
> + if (!ref_exists(branch->refname)) {
> + if (!argc || branch_checked_out(branch->refname))
> + die(_("No commit on branch '%s' yet."), branch->name);
> + die(_("branch '%s' does not exist"), branch->name);
> + }
> +
>
> dwim_and_setup_tracking(the_repository, branch->name,
> new_upstream, BRANCH_TRACK_OVERRIDE,
>
> == END
>
> P.S. if I were refactoring those ?: for style in that function I'd
> probably go for this on-top. The N_() followed by _() pattern is
> probably overdoing it, but included to show that one way out of this
> sort of thing with i18n is that you can pre-mark the string with N_(),
> then use it with _() to emit the message (right now the code uses
> "copy?" over "copy ?" instead to align them):
>
> diff --git a/builtin/branch.c b/builtin/branch.c
> index dc7a3e3dde1..e42f9bc4900 100644
> --- a/builtin/branch.c
> +++ b/builtin/branch.c
> @@ -805,31 +805,35 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
> }
>
> strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
> - if (!ref_exists(branch_ref.buf))
> - error((!argc || branch_checked_out(branch_ref.buf))
> - ? _("No commit on branch '%s' yet.")
> - : _("No branch named '%s'."),
> - branch_name);
> - else if (!edit_branch_description(branch_name))
> + if (!ref_exists(branch_ref.buf)) {
> + if (!argc || branch_checked_out(branch_ref.buf))
> + error(_("No commit on branch '%s' yet."),
> + branch_name);
> + else
> + error(_("No branch named '%s'."), branch_name);
> + } else if (!edit_branch_description(branch_name)) {
> ret = 0; /* happy */
> + }
>
> strbuf_release(&branch_ref);
> strbuf_release(&buf);
>
> return ret;
> } else if (copy || rename) {
> + static const char *cannot_copy = N_("cannot copy the current branch while not on any.");
> + static const char *cannot_rename = N_("cannot rename the current branch while not on any.");
> if (!argc)
> die(_("branch name required"));
> else if ((argc == 1) && filter.detached)
> - die(copy? _("cannot copy the current branch while not on any.")
> - : _("cannot rename the current branch while not on any."));
> + die("%s", copy ? _(cannot_copy) : _(cannot_rename));
> else if (argc == 1)
> copy_or_rename_branch(head, argv[0], copy, copy + rename > 1);
> else if (argc == 2)
> copy_or_rename_branch(argv[0], argv[1], copy, copy + rename > 1);
> + else if (copy)
> + die(_("too many branches for a copy operation"));
> else
> - die(copy? _("too many branches for a copy operation")
> - : _("too many arguments for a rename operation"));
> + die(_("too many arguments for a rename operation"));
> } else if (new_upstream) {
> struct branch *branch;
> struct strbuf buf = STRBUF_INIT;
>
next prev parent reply other threads:[~2023-02-08 0:35 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-30 22:59 [PATCH 0/2] branch: operations on orphan branches Rubén Justo
2022-12-30 23:04 ` [PATCH 1/2] branch: description for orphan branch errors Rubén Justo
2023-01-01 3:45 ` Junio C Hamano
2023-01-03 1:15 ` Rubén Justo
2023-01-04 6:58 ` Junio C Hamano
2023-01-06 23:39 ` Rubén Justo
2023-01-06 23:59 ` Junio C Hamano
2023-01-07 0:35 ` Rubén Justo
2023-01-07 0:00 ` Junio C Hamano
2022-12-30 23:12 ` [PATCH 2/2] branch: rename orphan branches in any worktree Rubén Justo
2023-01-15 23:54 ` [PATCH v2 0/3] branch: operations on orphan branches Rubén Justo
2023-01-16 0:00 ` [PATCH v2 1/3] avoid unnecessary worktrees traversing Rubén Justo
2023-01-19 21:24 ` Junio C Hamano
2023-01-19 23:26 ` Rubén Justo
2023-01-16 0:02 ` [PATCH v2 2/3] branch: description for orphan branch errors Rubén Justo
2023-01-16 0:04 ` [PATCH 3/3] branch: rename orphan branches in any worktree Rubén Justo
2023-01-19 21:33 ` Junio C Hamano
2023-01-19 23:34 ` Rubén Justo
2023-01-16 0:06 ` [PATCH v2 " Rubén Justo
2023-02-06 23:01 ` [PATCH v3 0/3] branch: operations on orphan branches Rubén Justo
2023-02-06 23:06 ` [PATCH v3 1/3] branch: avoid unnecessary worktrees traversals Rubén Justo
2023-02-11 4:16 ` Jonathan Tan
2023-02-15 22:00 ` Rubén Justo
2023-02-06 23:06 ` [PATCH v3 2/3] branch: description for orphan branch errors Rubén Justo
2023-02-06 23:06 ` [PATCH v3 3/3] branch: rename orphan branches in any worktree Rubén Justo
2023-02-07 0:11 ` [PATCH v3 0/3] branch: operations on orphan branches Junio C Hamano
2023-02-07 8:33 ` Ævar Arnfjörð Bjarmason
2023-02-08 0:35 ` Rubén Justo [this message]
2023-02-08 18:37 ` Junio C Hamano
2023-02-22 22:50 ` [PATCH v4 " Rubén Justo
2023-02-22 22:52 ` [PATCH v4 1/3] branch: avoid unnecessary worktrees traversals Rubén Justo
2023-02-25 15:08 ` Rubén Justo
2023-02-27 19:30 ` Jonathan Tan
2023-02-28 0:11 ` Rubén Justo
2023-02-22 22:55 ` [PATCH v4 2/3] branch: description for orphan branch errors Rubén Justo
2023-02-27 19:38 ` Jonathan Tan
2023-02-27 21:56 ` Junio C Hamano
2023-02-28 0:22 ` Rubén Justo
2023-02-22 22:56 ` [PATCH v4 3/3] branch: rename orphan branches in any worktree Rubén Justo
2023-02-27 19:41 ` Jonathan Tan
2023-02-28 0:23 ` Rubén Justo
2023-03-26 22:19 ` [PATCH v5 0/5] branch: operations on orphan branches Rubén Justo
2023-03-26 22:33 ` [PATCH v5 1/5] branch: test for failures while renaming branches Rubén Justo
2023-03-26 22:33 ` [PATCH v5 2/5] branch: use get_worktrees() in copy_or_rename_branch() Rubén Justo
2023-03-26 22:33 ` [PATCH v5 3/5] branch: description for orphan branch errors Rubén Justo
2023-03-26 22:33 ` [PATCH v5 4/5] branch: rename orphan branches in any worktree Rubén Justo
2023-03-26 22:33 ` [PATCH v5 5/5] branch: avoid unnecessary worktrees traversals Rubén Justo
2023-03-27 19:49 ` [PATCH v5 0/5] branch: operations on orphan branches Junio C Hamano
2023-05-01 22:19 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1450c94f-b0e4-a424-edd4-8c88b72febf5@gmail.com \
--to=rjusto@gmail.com \
--cc=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).