From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: "Rubén Justo" <rjusto@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: Tue, 07 Feb 2023 09:33:39 +0100 [thread overview]
Message-ID: <230207.86cz6l501v.gmgdl@evledraar.gmail.com> (raw)
In-Reply-To: <2193a4ed-b263-068e-92f8-847dcb053f8c@gmail.com>
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).
> 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/?:".
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-07 8:53 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 [this message]
2023-02-08 0:35 ` Rubén Justo
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=230207.86cz6l501v.gmgdl@evledraar.gmail.com \
--to=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=rjusto@gmail.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).