Re: [PATCH v4] branch: let '--edit-description' default to rebased/bisected branch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Jan 12, 2020 at 10:47:06AM +0400, marcandre.lureau@xxxxxxxxxx wrote:
> diff --git a/builtin/branch.c b/builtin/branch.c
> @@ -745,33 +745,52 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
>  		string_list_clear(&output, 0);
>  		return 0;
>  	} else if (edit_description) {
> -		const char *branch_name;
> +		char *branch_name = NULL;

Do you need to assign NULL here? Doesn't 'branch_name' get assigned in
all cases in which the code doesn't otherwise die()?

>  		if (!argc) {
> -			if (filter.detached)
> -				die(_("Cannot give description to detached HEAD"));
> -			branch_name = head;
> +			if (!filter.detached)
> +				branch_name = xstrdup(head);
> +			else {
> +				struct wt_status_state state;
> +
> +				memset(&state, 0, sizeof(state));
> +				wt_status_get_state(the_repository, &state, 0);
> +				branch_name = state.branch;
> +				if (!branch_name)
> +					die(_("Cannot give description to detached HEAD"));
> +				free(state.onto);
> +				free(state.detached_from);

I was wondering if it would make sense to attempt this branch name
lookup much earlier in the function when it assigns 'head' (if 'head'
is detached), with the idea that perhaps other git-branch modes might
benefit from it rather than doing it only for this one special-case.
However, it looks like other code (such as branch copy and branch
rename) would actively be hurt by such a change.

At any rate, it might make the 'edit_description' case easier to read
if this special-case branch lookup code was factored out into its own
function. Not itself worth a re-roll, but something to consider if you
do re-roll.

> +			}
>  		} else if (argc == 1)
> -			branch_name = argv[0];
> +			branch_name = xstrdup(argv[0]);
>  		else
>  			die(_("cannot edit description of more than one branch"));
>  
>  		strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
>  		if (!ref_exists(branch_ref.buf)) {
> -			strbuf_release(&branch_ref);
> +			int ret;
>  
>  			if (!argc)
> -				return error(_("No commit on branch '%s' yet."),
> -					     branch_name);
> +				ret = error(_("No commit on branch '%s' yet."),
> +					    branch_name);
>  			else
> -				return error(_("No branch named '%s'."),
> -					     branch_name);
> +				ret = error(_("No branch named '%s'."),
> +					    branch_name);
> +
> +			strbuf_release(&branch_ref);
> +			free(branch_name);
> +			return ret;
> +
>  		}

Unnecessary blank line after 'return'.

A couple observations...

The extra cleanup needed to handle 'branch_name' makes this code quite
a bit more verbose. I was wondering if it would be possible to
consolidate the cleanup in a "failure path" as the target of a 'goto'
(which is a common way to perform cleanup in the Git code-base).
However, doing it that way doesn't really make the code much nicer,
which leads to the next observation...

Those `return error(...)` invocations are anomalies in this function.
Every other case of error in cmd_branch() simply die()s -- without
bothering to clean up. There is no apparent reason why this code
instead uses error(). Changing these two cases to die() would simplify
cleanup since you wouldn't have to do any, which would make the code
clearer, shorter, and more consistent with the rest of cmd_branch().
(Such a change probably ought to be done first in a preparatory patch,
making this a two-patch series.)

>  		strbuf_release(&branch_ref);
>  
> -		if (edit_branch_description(branch_name))
> +		if (edit_branch_description(branch_name)) {
> +			free(branch_name);
>  			return 1;
> +		}
> +
> +		free(branch_name);

Taking the above comments and observations into account, perhaps
something like this would be cleaner:

--- >8 ---
diff --git a/builtin/branch.c b/builtin/branch.c
index d8297f80ff..0eb519561e 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -601,6 +601,22 @@ static int edit_branch_description(const char *branch_name)
 	return 0;
 }
 
+/*
+ * Return branch name of current worktree -- even if HEAD is detached -- or
+ * NULL if no branch is associated with worktree. Caller is responsible for
+ * freeing result.
+ */
+static char *get_worktree_branch()
+{
+	struct wt_status_state state;
+
+	memset(&state, 0, sizeof(state));
+	wt_status_get_state(the_repository, &state, 0);
+	free(state.onto);
+	free(state.detached_from);
+	return state.branch;
+}
+
 int cmd_branch(int argc, const char **argv, const char *prefix)
 {
 	int delete = 0, rename = 0, copy = 0, force = 0, list = 0;
@@ -745,13 +761,16 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		string_list_clear(&output, 0);
 		return 0;
 	} else if (edit_description) {
+		int ret;
 		const char *branch_name;
+		char *to_free = NULL;
 		struct strbuf branch_ref = STRBUF_INIT;
 
 		if (!argc) {
-			if (filter.detached)
+			if (!filter.detached)
+				branch_name = head;
+			else if (!(branch_name = to_free = get_worktree_branch()))
 				die(_("Cannot give description to detached HEAD"));
-			branch_name = head;
 		} else if (argc == 1)
 			branch_name = argv[0];
 		else
@@ -759,19 +778,16 @@ 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)) {
-			strbuf_release(&branch_ref);
-
 			if (!argc)
-				return error(_("No commit on branch '%s' yet."),
-					     branch_name);
+				die(_("No commit on branch '%s' yet."), branch_name);
 			else
-				return error(_("No branch named '%s'."),
-					     branch_name);
+				die(_("No branch named '%s'."), branch_name);
 		}
 		strbuf_release(&branch_ref);
 
-		if (edit_branch_description(branch_name))
-			return 1;
+		ret = edit_branch_description(branch_name);
+		free(to_free);
+		return ret;
 	} else if (copy) {
 		if (!argc)
 			die(_("branch name required"));
--- >8 ---



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux