git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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;
>  

  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).