Re: [RFC PATCH v2 1/2] git-merge: add option to format default message using multiple lines

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

 



Hi

Thank you for your feedback!

09.03.2020 19:20, Junio C Hamano пишет:
> "i.Dark_Templar" <darktemplar@xxxxxxxxxxxxxxxxxxxxxxxxx> writes:
> 
>> +static int use_multiline = -1;
>>  
>>  int fmt_merge_msg_config(const char *key, const char *value, void *cb)
>>  {
>> @@ -32,6 +33,8 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)
>>  			merge_log_config = DEFAULT_MERGE_LOG_LEN;
>>  	} else if (!strcmp(key, "merge.branchdesc")) {
>>  		use_branch_desc = git_config_bool(key, value);
>> +	} else if (!strcmp(key, "merge.usemultiline")) {

I'm wondering if this config option name could be improved, but out of
ideas at the moment. Maybe you have some ideas?

>> +		use_multiline = git_config_int(key, value);
>>  	} else {
>>  		return git_default_config(key, value, cb);
>>  	}
>> @@ -413,6 +416,39 @@ static void shortlog(const char *name,
>>  	string_list_clear(&subjects, 0);
>>  }
>>  
>> +static int fmt_merge_refs_count(void)
>> +{
>> +	int i = 0;
>> +	int j = 0;
>> +	int objects_count = 0;
> 
> Call it "object_count" and drop "j"; that's shorter.
> 
> Also, this is a "STATIC" function, an implementation detail of the
> fmt_merge_msg program.  There is no need to repeat that fact by
> replicating fmt_merge_ in its name to differenciate with other
> things, unlike the functions that are visible from other places.
> 
> Just call it "count_srcs()" or something like that and do not use
> the word "ref" in its name, as "merging refs" is probably too
> ancient, limiting and misleading concept---we do not merge "refs".
> We merge commits (and more recently) tags, and "refs" is merely one
> of the ways to name these things that are merged.
> 
> 

Thanks, I'll rename this function to 'count_srcs'.

>> +	for (i = 0; i < srcs.nr; i++) {
>> +		struct src_data *src_data = srcs.items[i].util;
>> +
>> +		if (src_data->head_status == 1) {
>> +			++objects_count;
>> +			continue;
>> +		}
>> +		if (src_data->head_status == 3) {
>> +			++objects_count;
>> +		}
> 
> This part deserves commenting.  The bit #0 of head_status is special
> in that it signals a pull of the default branch (HEAD) of the remote
> repository, and it is special because in that case (and only in that
> case) none of the string lists in src_data is updated, so the number
> of merged heads is one more than the case where the bit #0 is off.
> 

I didn't know about such details. Thanks.

>> +		for (j = 0; j < src_data->branch.nr; j++) {
>> +			++objects_count;
>> +		}
>> +		for (j = 0; j < src_data->r_branch.nr; j++) {
>> +			++objects_count;
>> +		}
>> +		for (j = 0; j < src_data->tag.nr; j++) {
>> +			++objects_count;
>> +		}
>> +		for (j = 0; j < src_data->generic.nr; j++) {
>> +			++objects_count;
>> +		}
> 
> Isn't it sufficient to add .nr to object_count?  Why increment
> object_count by one as many times as j counts up from 0 to .nr?
> 

That's my fault, I overlooked optimization here.

> If the merge involves only the remote HEAD, then the lists are all
> empty, isn't it?  I do not see the point of treating the case where
> head_status is 3 == 1|2 any special, so the following is sufficient
> as the replacement for the above and should be far easier to follow,
> no?  Or am I missing something subtle in your version?
> 
> 		if (src_data->head_status & 01)
> 			/* 
>                          * the set of merged heads includes the
>                          * default branch of the remote, aka HEAD,
> 			 * which is not counted in any of the lists
> 			 * in src_data.
> 			 */
> 			object_count++;
> 
>                 object_count += (src->data->branch.nr +
>                                  src->data->r_branch.nr +
>                                  src->data->tag.nr +
>                                  src->data->generic.nr);
> 
> By the way, if you read the original code, you may have noticed that
> our codebase prefers post-increment over pre-increment, when the
> difference does not matter (in other words, "a = ++b;" is perfectly
> legit; it is just that we do not say "++b;" when "b++;" would do).
> 

I copied behaviour of 'fmt_merge_msg_title' function here. Thanks for
clarifying special cases and optimizing it. I didn't know most of these
details about head_status and branches/tags/etc lists. I'll replace it
with your optimized version.

>> +	}
>> +
>> +	return objects_count;
>> +}
>> +
>>  static void fmt_merge_msg_title(struct strbuf *out,
>>  				const char *current_branch)
>>  {
>> @@ -467,6 +503,68 @@ static void fmt_merge_msg_title(struct strbuf *out,
>>  		strbuf_addf(out, " into %s\n", current_branch);
>>  }
>>  
>> +static void fmt_merge_msg_title_multiline(struct strbuf *out,
>> +				const char *current_branch, int count)
>> +{
>> +	int i = 0;
>> +	int j = 0;
>> +
>> +	if (!strcmp("master", current_branch))
>> +		strbuf_addf(out, "Merge %d %s\n", count, (count == 1) ? "commit" : "commits");
>> +	else
>> +		strbuf_addf(out, "Merge %d %s into %s\n", count, (count == 1) ? "commit" : "commits", current_branch);
> 
> Overlong lines.
> 

Thanks, I'll fix it.

>> +	strbuf_addch(out, '\n');
>> +
>> +	if (count == 1)
>> +		strbuf_addstr(out, "Following commit is merged:\n");
>> +	else
>> +		strbuf_addstr(out, "Following commits are merged:\n");
> 
> The above makes me wonder if you are better off having "if there is
> only one, do these things, otherwise do these other things" at the
> top level, i.e.
> 
> 	if (count == 1) {
> 		strbuf_addstr(out, "Merge 1 commit");
> 		if (strcmp(current_branch, "master"))
> 			strbuf_addstr(out, " into %s", current_branch);
> 		strbuf_addstr(out, "\n\nFollowing commit is ...");
> 	} else {
> 		...similarly...
> 	}
> 
> But stepping back a bit, is there a point in handing count==1 case
> in this new format in the first place?  Why waste the most precious
> information real estate, which is the title line, to say a lot less
> informative "merge 1 commit" instead of what topic is merged there?
> 

By default, this new format is disabled. In patch 2 it's enabled only
when at least 2 new objects are merged. Due to that new message format
shouldn't ever be used with default settings for only 1 merged object,
but user could set new configuration option to '1' and hit this code path.

If such format for just 1 merged object is undesired, I can modify code
and documentation to make sure it turns on only when at least 2 objects
are merged, and get rid of 1 merged object use-case after that.

> Also, I am not sure if "Following commits are merged" is a good
> message for a few reasons.
> 
>  - Obviously, we allow pulling and merging a signed tag and in that
>    case, we are merging a tag, not a commit.
> 
>  - When we pull a topic branch and nothing else, the above code
>    would say "Merge 1 commit", but there may probably be more than
>    one commit on the history leading to that commit we are merging
>    into our history.
> 
> 
> What actually is happening, instead of "merge 1 commit", is that we
> are merging one lineage of history, which may have one or more
> commits.  The phrase suitable to call the lineage of history may be
> "a topic branch", but it may be "a release tag", in which case what
> you are merging would be the entire history built while developing
> towards that tag that you have been missing.
> 

I'll describe a bit why I used a word 'commit' in this code. When
deciding how to name merged objects, I came down to two options: just
'object' or 'commit'. I used 'commit' because 'man git-merge' usually
uses this word. What word would you want to use here instead? An
'object'? 'History'? Something else?



[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