Subject: Re: [PATCH] merge-file: consider core.crlf when writing merge markers

From: Beat Bolli <[email-masked]>
Date: Tue, 24 Nov 2015 23:50:30 +0100

On 24.11.15 23:43, Beat Bolli wrote:
> On 24.11.15 09:21, Johannes Schindelin wrote:
>> Hi Beat,
>>
>> On Mon, 23 Nov 2015, Beat Bolli wrote:
>>
>>> When merging files in repos with core.eol = crlf, git merge-file inserts
>>> just a LF at the end of the merge markers. Files with mixed line endings
>>> cause trouble in Windows editors and e.g. contrib/git-jump, where an
>>> unmerged file in a run of "git jump merge" is reported as simply "binary
>>> file matches".
>>
>> Wow, what a beautiful contribution!
>>
>> I wonder how difficult it would be to make this work with gitattributes,
>> i.e. when .gitattributes' `eol` setting disagrees with core.eol.
>>
>> I imagine that we could use convert.c to do all the hard work, e.g. by
>> adding a function
>>
>> 	const char *eol_for_path(const char *path, const char *contents)
>> 	{
>> 		enum eol eol;
>> 		struct conv_attrs ca;
>> 		struct text_stat stats;
>>
>> 		convert_attrs(&ca, path);
>> 		eol = output_eol(ca.crlf_action);
>> 		if (eol != EOL_CRLF)
>> 			eol = EOL_LF;
>> 		else if (!*contents || (crlf_action != CRLF_AUTO &&
>> 				crlf_action != CRLF_GUESS)
>> 			eol = EOL_CRLF;
>> 		else {
>> 			ca.crlf_action = input_crlf_action(ca.crlf_action,
>> 					ca.eol_attr);
>> 			if (crlf_action == CRLF_GUESS && stats.cr > stats.crlf)
>> 				eol = core_eol;
>> 			else if (stats.crlf)
>> 				eol = EOL_CRLF;
>> 			else
>> 				eol = EOL_LF;
>> 		}
>>
>> 		return eol == EOL_CRLF ? "\r\n" : "\n";
>> 	}
> 
> Hi Johannes,
> 
> I have implemented this according to your algorithm. Now, I have to set
> core.autocrlf to true for making the new test pass. Setting core.eol no
> longer has an effect on the merge markers. Is this expected? (I haven't
> set any attributes)

PS: the function looks like this now:

enum eol eol_for_path(const char *path, const char *src, size_t len)
{
        struct conv_attrs ca;
        struct text_stat stats;

        convert_attrs(&ca, path);
        if (output_eol(ca.crlf_action) != EOL_CRLF)
                return EOL_LF;
        if (!len || ca.crlf_action != CRLF_AUTO &&
	            ca.crlf_action != CRLF_GUESS)
                return EOL_CRLF;
        ca.crlf_action = input_crlf_action(ca.crlf_action, ca.eol_attr);
        gather_stats(src, len, &stats);
        if (ca.crlf_action == CRLF_GUESS && stats.cr > stats.crlf)
                return core_eol;
        else if (stats.crlf)
                return EOL_CRLF;
        else
                return EOL_LF;
}