git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] difftool: handle changing symlinks in dir-diff mode

From
Junio C Hamano <gitster@pobox.com>
Date
Mar 14, 2017, 04:13 UTC
Message-ID
<xmqq1su0lcm3.fsf@gitster.mtv.corp.google.com>
In-Reply-To
<xmqqlgs9rprt.fsf@gitster.mtv.corp.google.com>
Junio C Hamano <gitster@pobox.com> writes:
Show 30 quoted lines
>> +	struct strbuf path = STRBUF_INIT;
>> +	struct strbuf link = STRBUF_INIT;
>> +
>> +	int ok = 0;
>> +
>> +	if (strbuf_readlink(&link, ce->name, ce_namelen(ce)) == 0) {
>> +		strbuf_add(&path, state->base_dir, state->base_dir_len);
>> +		strbuf_add(&path, ce->name, ce_namelen(ce));
>> +
>> +		write_file_buf(path.buf, link.buf, link.len);
>
> This does "write content into symlink stand-in file", but why?  A
> symbolic link that is not changed on the right-hand side of the
> comparison (i.e. S_ISLNK(rmode) && !is_null_oid(&roid)) would go to
> checkout_entry() which
>
>  - creates a symbolic link, on a filesystem that supports symlink; or
>  - writes the stand-in file on a filesystem that does not.
>
> which is the right thing.  It seems that the other side of "if (!use_wt_file())"
> if/elseif/... cascade also does the right thing manually.
>
> Shouldn't this helper also do the same (i.e. create symlink and fall
> back to stand-in)?
>
> Also, I am not sure if strbuf_readlink() can unconditionally used
> here.  On a filesystem without symbolic link, the working tree
> entity that corresponds to the ce that represents a symlink is a
> stand-in regular file, so shouldn't we be opening it as a regular
> file and reading its contents in that case?

I _think_ I was mistaken (please correct me again if my reasoning below is wrong) and unconditional writing of a plain regular file is what this codepath wants to do, because we are preparing two temporary directories, to be fed to a Git-unaware tool that knows how to show a diff of two directories (e.g. "diff -r A B"). Because the tool is Git-unaware, if a symbolic link appears in either of these temporary directories, it will try to dereference and show the difference of the target of the symbolic link, which is not what we want, as the goal of the dir-diff mode is to produce an output that is logically equivalent to what "git diff" produces---most importantly, we want to get textual comparison of the result of the readlink(2). And write_file_buf() used here is exactly that---we write the contents of symlink to a regular file to force the external tool to compare the readlink(2) result as if it is a text. Even on a filesystem that is capable of doing a symbolic link.

The strbuf_readlink() that read the contents of symlink, however, is wrong on a filesystem that is not capable of a symbolic link; if core.symlinks is false, we do need to read them as a regular file.

Previous: Junio C HamanoNext: Junio C Hamano
Message 15 of 17 in “fatal error when diffing changed symlinks”
  1. Christophe MacabiauFeb 24, 2017
  2. Junio C HamanoFeb 24, 2017
  3. Junio C HamanoFeb 24, 2017
  4. Jeff KingFeb 24, 2017
  5. Johannes SchindelinFeb 25, 2017
  6. Junio C HamanoMar 7, 2017
  7. Johannes SchindelinMar 7, 2017
  8. difftool: handle changing symlinks in dir-diff modeDavid Aguilar, Mar 13, 2017
  9. Junio C HamanoMar 13, 2017
  10. Johannes SchindelinMar 13, 2017
  11. Johannes SchindelinMar 13, 2017
  12. Junio C HamanoMar 13, 2017
  13. David AguilarMar 14, 2017
  14. Junio C HamanoMar 14, 2017
  15. Junio C HamanoMar 14, 2017
  16. Junio C HamanoMar 13, 2017
  17. Johannes SchindelinMar 13, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.