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

Re: [PATCH] Fix incorrect diff of a link -> file change if core.filemode = false.

From
Junio C Hamano <junkio@cox.net>
Date
Feb 17, 2007, 00:15 UTC
Message-ID
<7vodntzljb.fsf@assigned-by-dhcp.cox.net>
In-Reply-To
<200702170030.04014.johannes.sixt@telecom.at>
Johannes Sixt <johannes.sixt@telecom.at> writes:
> The fix is that the cached mode must only be allowed to override the file's 
> actual mode (which includes the type information) if _both_ the working tree 
> entry and the cached entry are regular files.
Ah, I misunderstood.

I suspect you do not want to get random, unreliable executable bit from lstat(), even when previously index recorded non regular file for a path that is now a regular file. In builtin-update-index.c, add_file_to_cache() has this:

	ce->ce_mode = create_ce_mode(st.st_mode);
	if (!trust_executable_bit) {
		/* If there is an existing entry, pick the mode bits
		 * from it, otherwise assume unexecutable.
		 */
		int pos = cache_name_pos(path, namelen);
		if (0 <= pos)
			ce->ce_mode = active_cache[pos]->ce_mode;
		else if (S_ISREG(st.st_mode))
			ce->ce_mode = create_ce_mode(S_IFREG | 0666);
	}

and I agree what it _tries_ to do, although I think the above also makes the regular file being added to a symlink and needs to be fixed. You helped us find another bug.

	# In a new, empty directory...
	$ git init
        $ ln -s foo A
        $ git add A
        $ git ls-files -s
	120000 19102815663d23f8b75a47e7a01965dcdc96468c 0	A
        $ git config core.filemode false
        $ rm A ; echo foo >A
        $ git add A
        $ git ls-files -s
	120000 19102815663d23f8b75a47e7a01965dcdc96468c 0	A
The fix is probably like this:
	ce->ce_mode = create_ce_mode(st.st_mode);
	if (!trust_executable_bit && S_ISREG(st.st_mode)) {
		/* If there is an existing entry, pick the mode bits
		 * from it, otherwise assume unexecutable.
		 */
		int pos = cache_name_pos(path, namelen);
		if (0 <= pos &&
                    S_ISREG(ntohl(active_cache[pos]->ce_mode)))
			ce->ce_mode = active_cache[pos]->ce_mode;
		else 
			ce->ce_mode = create_ce_mode(S_IFREG | 0666);
	}

Back to the part of the code you patched, I think the fix should be something like this instead:

	mode = create_ce_mode(st.st_mode);
	if (!trust_executable_bit && S_ISREG(st.st_mode)) {
		/* If there is an existing entry, pick the mode bits
		 * from it, otherwise assume unexecutable.
		 */
                if (S_ISREG(ntohl(ce->ce_mode)))
			mode = ce->ce_mode;
                else
                	mode = create_ce_mode(S_IFREG | 0666);
                
        }
Previous: Johannes SixtNext: Junio C Hamano
Message 4 of 7 in “Fix incorrect diff of a link -> file change if core.filemode = false.”
  1. Fix incorrect diff of a link -> file change if core.filemode = false.Johannes Sixt, Feb 16, 2007
  2. Junio C HamanoFeb 16, 2007
  3. Johannes SixtFeb 16, 2007
  4. Junio C HamanoFeb 17, 2007
  5. Do not take mode bits from index after type change.Junio C Hamano, Feb 17, 2007
  6. Johannes SixtFeb 17, 2007
  7. Junio C HamanoFeb 17, 2007

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.