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

Re: [PATCH 0/4] Handling unmerged files with merged entries

From
Junio C Hamano <gitster@pobox.com>
Date
Aug 20, 2014, 22:19 UTC
Message-ID
<xmqqr40ast2g.fsf@gitster.dls.corp.google.com>
In-Reply-To
<cover.1408533065.git.jsorianopastor@gmail.com>
Jaime Soriano Pastor <jsorianopastor@gmail.com> writes:
Show 21 quoted lines
> New approach for the case of finding unmerged files with merged entries
> in the index.
> After some discussion the solution tries to:
> - Avoid the problems with infinite loops in this case.
> - Provide better information to the user in the commands affected.
> - Make sure there are ways to clean the index.
> - Provide also a way to specifically recover each one of the files with
>   this problem.
>
> With these patches the behaviour of these commands (for this case) change:
> - git reset is able to finish, cleaning the index, but warning out the
>   information about the removed stages.
> - git merge is able to finish, reporting that there is a merge in progress as
>   usual, it also warns about the unmerged files with merged entries.
> - git add fails when this case happens, telling the user to check the state
>   with 'git ls-files -s', before, it did nothing. The same with git commit -a.
> - git update-index --cacheinfo can be used to select an specific staged
>   version to resolve the conflict, without the need of reseting the working
>   copy. It did nothing before.
>
> Tests added for these cases. Rest of the tests remain unchanged and pass too.
Thanks.

After looking at what you did in 1/4, I started to wonder if we can solve this in add_index_entry_with_check() in a less intrusive way. When we call the function with a stage #0 entry, we are telling the index that any entry in higher stage for the same path must disappear. Since the current implementation of the function assumes that the index is not corrupt in this particular way to have both merged and unmerged entries for the same path, it fails to remove the higher stage entries. If we fix the function, wouldn't it make your 1/4 unnecessary? Read-only operations such as "ls-files -s" would not call add_index_entry() so diagnostic tools would not be affected even with such a fix.

... which may look something like the one attached at the end.
But then it made me wonder even more.

There are other ways a piece of software can leave a corrupt index for us to read from. Your fix, or the simpler one I suggested for that matter, would still assume that the index entries are in the sorted order, and a corrupt index that does not sort its entries correctly will cause us to behave in an undefined way. At some point we should draw a line and say "Your index is hopelessly corrupt.", send it back to whatever broken software that originally wrote such a mess and have the user use that software to fix the corrupt index up before talking to us.

For that, we need to catch an index whose entries are not sorted and error out, perhaps when read_index_from() iterates over the mmapped index entries. We can even draw that "hopelessly corrupt" line above the breakage you are addressing and add a check to make sure no path has both merged and unmerged entries to the same check to make it error out.

I suspect that such a "detect and error out" may be sufficient and also may be more robust than the approach that assumes that a breakage is only to have both merged and unmerged entries for the same path, the entries are still correctly sorted.

 read-cache.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/read-cache.c b/read-cache.c
index 7f5645e..56006a3 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -943,9 +943,16 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
 	if (pos >= 0) {
 		if (!new_only)
 			replace_index_entry(istate, pos, ce);
-		return 0;
+		/*
+		 * ... but protect ourselves from a corrupt index
+		 * that has an unmerged entry for the same path.
+		 */
+		if (istate->cache_nr <= pos + 1 ||
+		    !ce_same_name(ce, istate->cache[pos + 1]))
+			return 0;
+	} else {
+		pos = -pos-1;
 	}
-	pos = -pos-1;
 
 	/*
 	 * Inserting a merged entry ("stage 0") into the index





[Footnote]
Previous: Jaime Soriano PastorNext: Jaime Soriano Pastor
Message 21 of 51 in “read-cache.c: Ensure unmerged entries are removed”
  1. read-cache.c: Ensure unmerged entries are removedJaime Soriano Pastor, Aug 12, 2014
  2. read-cache.c: Ensure unmerged entries are removedJaime Soriano Pastor, Aug 12, 2014
  3. Junio C HamanoAug 12, 2014
  4. Jaime Soriano PastorAug 13, 2014
  5. Junio C HamanoAug 13, 2014
  6. Jaime Soriano PastorAug 15, 2014
  7. Junio C HamanoAug 15, 2014
  8. Jaime Soriano PastorAug 16, 2014
  9. Junio C HamanoAug 18, 2014
  10. Jaime Soriano PastorAug 18, 2014
  11. 0/4 Handling unmerged files with merged entriesJaime Soriano Pastor, Aug 20, 2014
  12. 1/4 read_index_unmerged doesn't loop forever if merged stage exists for unmerged fileJaime Soriano Pastor, Aug 20, 2014
  13. 2/4 Error out when adding a file with merged and unmerged entriesJaime Soriano Pastor, Aug 20, 2014
  14. 3/4 Added tests for the case of merged and unmerged entries for the same fileJaime Soriano Pastor, Aug 20, 2014
  15. Junio C HamanoAug 20, 2014
  16. Jaime Soriano PastorAug 21, 2014
  17. Junio C HamanoAug 21, 2014
  18. 4/4 git update-index --cacheinfo can be used to select a stage when there are merged and unmerged entriesJaime Soriano Pastor, Aug 20, 2014
  19. Junio C HamanoAug 20, 2014
  20. Jaime Soriano PastorAug 21, 2014
  21. Junio C HamanoAug 20, 2014
  22. Jaime Soriano PastorAug 21, 2014
  23. Check order when reading indexJaime Soriano Pastor, Aug 21, 2014
  24. Jaime Soriano PastorAug 21, 2014
  25. Duy NguyenAug 21, 2014
  26. Junio C HamanoAug 21, 2014
  27. 1/2 Check order when reading indexJaime Soriano Pastor, Aug 24, 2014
  28. 2/2 Loop index increases monotonically when reading unmerged entriesJaime Soriano Pastor, Aug 24, 2014
  29. Jaime Soriano PastorAug 24, 2014
  30. Junio C HamanoAug 25, 2014
  31. Junio C HamanoAug 25, 2014
  32. Jeff KingAug 25, 2014
  33. Junio C HamanoAug 25, 2014
  34. Jaime Soriano PastorAug 26, 2014
  35. Jeff KingAug 26, 2014
  36. Junio C HamanoAug 26, 2014
  37. Jaime Soriano PastorAug 26, 2014
  38. Junio C HamanoAug 26, 2014
  39. 1/2 read_index_from(): catch out of order entries when reading an index fileJaime Soriano Pastor, Aug 27, 2014
  40. 2/2 read_index_unmerged(): remove unnecessary loop index adjustmentJaime Soriano Pastor, Aug 27, 2014
  41. Eric SunshineAug 29, 2014
  42. read_index_from(): catch out of order entries when reading an index fileJaime Soriano Pastor, Aug 29, 2014
  43. Junio C HamanoAug 29, 2014
  44. Jaime Soriano PastorAug 27, 2014
  45. Junio C HamanoAug 27, 2014
  46. Jaime Soriano PastorAug 27, 2014
  47. Jaime Soriano PastorAug 25, 2014
  48. Johannes SixtAug 21, 2014
  49. Junio C HamanoAug 21, 2014
  50. Junio C HamanoAug 12, 2014
  51. Jaime Soriano PastorAug 13, 2014

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.