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

Re: [PATCH v5 10/11] setup_git_directory_gently_1(): avoid die()ing

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Mar 13, 2017, 19:38 UTC
Message-ID
<alpine.DEB.2.20.1703131826330.3767@virtualbox>
In-Reply-To
<xmqqefy5yn4k.fsf@gitster.mtv.corp.google.com>
Hi Junio,

PLEASE NOTE: the purpose of this patch series is to allow the same function (setup_git_directory_gently_1()) to be the work horse for setup_git_directory() as before, but also for the new discover_git_directory() function that is introduced to fix read_early_config() to avoid hardconfig .git/config.

The purpose is *not* to change any current behavior. Please do not ask me to do that in this patch series.

Now to your comments:
On Fri, 10 Mar 2017, Junio C Hamano wrote:
Show 22 quoted lines
> Johannes Schindelin <johannes.schindelin@gmx.de> writes:
> 
> > @@ -890,14 +892,22 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
> >  	if (one_filesystem)
> >  		current_device = get_device_or_die(dir->buf, NULL, 0);
> >  	for (;;) {
> > -		int offset = dir->len;
> > +		int offset = dir->len, error_code = 0;
> >  
> >  		if (offset > min_offset)
> >  			strbuf_addch(dir, '/');
> >  		strbuf_addstr(dir, DEFAULT_GIT_DIR_ENVIRONMENT);
> > -		gitdirenv = read_gitfile(dir->buf);
> > -		if (!gitdirenv && is_git_directory(dir->buf))
> > -			gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT;
> > +		gitdirenv = read_gitfile_gently(dir->buf, die_on_error ?
> > +						NULL : &error_code);
> > +		if (!gitdirenv) {
> 
> We tried to read ".git" as a regular file, but couldn't.  There are
> some cases but I am having trouble to convince myself all cases are
> covered correctly here, so let me follow the code aloud.
It is subtle and finicky, I agree.
Show 24 quoted lines
> > +			if (die_on_error ||
> > +			    error_code == READ_GITFILE_ERR_NOT_A_FILE) {
> > +				if (is_git_directory(dir->buf))
> > +					gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT;
> 
> If we are told to die on error, but if it is a Git directory, then
> we do not have to (and want to) die and instead report that
> directory as discovered.
> 
> If we are to report the failure status instead of dying, we also do
> want to recover when the read_gitfile_gentrly() failed only because
> it was a real Git directory.  READ_GITFILE_ERR_NOT_A_FILE could be a
> signal for that, and we recover after making sure it is a Git
> directory.
> 
> Among the READ_GITFILE_ERR_* codes, ERR_NOT_A_FILE is the only one
> we attempt this recovery.  All others just take the "else if" thing
> below.
> 
> What happens when is_git_directory() test here does not pass,
> though?  Let's say stat() in read_gitfile_gently() found a FIFO
> there, it gives us ERR_NOT_A_FILE, is_git_directory() would say
> "Nah", and then ...?  Don't we want the other side for this if()
> statement that returns failure?

The current code as per `master` detects the NOT_A_FILE condition, and as the parameter return_error_code was passed as NULL (because read_gitfile is actually #define'd in cache.h to call read_gitfile_gently with NULL as second parameter), it calls read_gitfile_error_die(). That function *ignores* the NOT_A_FILE error condition, and as a consequence returns to read_gitfile_gently() which then returns NULL because there *was* an error_code.

That means that setup_git_directory_gently_1() will retrieve a NULL from the read_gitfile() call, which means it then goes on to test whether it is looking at a .git/ directory via is_git_directory() and if that returns false, the loop will continue to look at the *parent* directory.

That, in turn, means that what you are asking for is a change in behavior, and as I am unwilling to introduce a change in behavior with this patch series, my patch does the exact right thing.

Show 19 quoted lines
> > +			} else if (error_code &&
> > +				   error_code != READ_GITFILE_ERR_STAT_FAILED)
> > +				return GIT_DIR_INVALID_GITFILE;
> > +		}
> 
> On the other hand, if read_gitfile_gently() didn't say "we found
> something that is not a regular file" we come here.  If the error
> came because there wasn't ".git" in the directory we are looking at,
> i.e. stat(2) in read_gitfile_gently() gave ENOENT, it is perfectly
> normal and we just want to go one level up.
> 
> But shouldn't read_gitfile_gently() be inspecting errno when it sees
> a stat() failure?  If there _is_ ".git" but we failed to stat it for
> whatever reason (EACCES, ELOOP,...), we do not want to go up but
> give the INVALID_GITFILE from here, just like other cases, no?
> For that I imagine that ERR_STAT_FAILED needs to be split into two,
> one for true ERR_STAT_FAILED (from which we cannot recover) and the
> other for ERR_ENOENT to signal us that there is nothing there (which
> allows us to go up).

True. But again, you are asking for a *change in behavior*, which is not the purpose of this patch series.

> By the way, is the "error_code &&" needed?

It is not! I had the order of the if/else blocks completely differently originally [*1*] and just overlooked that the error_code could no longer be 0 in that condition.

Ciao, Dscho

Footnote *1*: Yes, I wanted to construct an English sentence with three -ly words in a row.

Previous: Junio C HamanoNext: Junio C Hamano
Message 101 of 123 in “Pie-in-the-sky attempt to fix the early config”
  1. 0/7 Pie-in-the-sky attempt to fix the early configJohannes Schindelin, Dec 8, 2016
  2. 3/7 Mark builtins that create .git/ directoriesJohannes Schindelin, Dec 8, 2016
  3. 1/7 Make read_early_config() reusableJohannes Schindelin, Dec 8, 2016
  4. 2/7 read_early_config(): avoid .git/config hack when unneededJohannes Schindelin, Dec 8, 2016
  5. 4/7 read_early_config(): special-case `init` and `clone`Johannes Schindelin, Dec 8, 2016
  6. 5/7 read_early_config(): really discover .git/Johannes Schindelin, Dec 8, 2016
  7. 7/7 WIP: read_early_config(): add testsJohannes Schindelin, Dec 8, 2016
  8. 6/7 WIP read_config_early(): respect ceiling directoriesJohannes Schindelin, Dec 8, 2016
  9. Jeff KingDec 8, 2016
  10. Johannes SchindelinDec 9, 2016
  11. Jeff KingDec 9, 2016
  12. Duy NguyenDec 9, 2016
  13. Johannes SchindelinDec 9, 2016
  14. 0/9 Fix the early configJohannes Schindelin, Mar 3, 2017
  15. 3/9 setup_git_directory(): avoid changing global state during discoveryJohannes Schindelin, Mar 3, 2017
  16. Jeff KingMar 3, 2017
  17. Johannes SchindelinMar 3, 2017
  18. 4/9 Export the discover_git_directory() functionJohannes Schindelin, Mar 3, 2017
  19. Jeff KingMar 3, 2017
  20. Johannes SchindelinMar 3, 2017
  21. 2/9 setup_git_directory(): use is_dir_sep() helperJohannes Schindelin, Mar 3, 2017
  22. Jeff KingMar 3, 2017
  23. Johannes SchindelinMar 3, 2017
  24. Jeff KingMar 3, 2017
  25. Johannes SchindelinMar 3, 2017
  26. 1/9 t7006: replace dubious testJohannes Schindelin, Mar 3, 2017
  27. Jeff KingMar 3, 2017
  28. Johannes SchindelinMar 3, 2017
  29. 5/9 Make read_early_config() reusableJohannes Schindelin, Mar 3, 2017
  30. Jeff KingMar 3, 2017
  31. Johannes SchindelinMar 3, 2017
  32. 6/9 read_early_config(): special-case builtins that create a repositoryJohannes Schindelin, Mar 3, 2017
  33. Jeff KingMar 3, 2017
  34. Johannes SchindelinMar 3, 2017
  35. 7/9 read_early_config(): avoid .git/config hack when unneededJohannes Schindelin, Mar 3, 2017
  36. Jeff KingMar 3, 2017
  37. 9/9 Test read_early_config()Johannes Schindelin, Mar 3, 2017
  38. Jeff KingMar 3, 2017
  39. Johannes SchindelinMar 3, 2017
  40. 8/9 read_early_config(): really discover .git/Johannes Schindelin, Mar 3, 2017
  41. Jeff KingMar 3, 2017
  42. Johannes SchindelinMar 3, 2017
  43. Jeff KingMar 3, 2017
  44. Johannes SchindelinMar 3, 2017
  45. 0/9 Fix the early configJohannes Schindelin, Mar 3, 2017
  46. 1/9 t7006: replace dubious testJohannes Schindelin, Mar 3, 2017
  47. 2/9 setup_git_directory(): use is_dir_sep() helperJohannes Schindelin, Mar 3, 2017
  48. 3/9 Prepare setup_discovered_git_directory() the root directoryJohannes Schindelin, Mar 3, 2017
  49. 4/9 setup_git_directory_1(): avoid changing global stateJohannes Schindelin, Mar 3, 2017
  50. 7/9 read_early_config(): avoid .git/config hack when unneededJohannes Schindelin, Mar 3, 2017
  51. 5/9 Export the discover_git_directory() functionJohannes Schindelin, Mar 3, 2017
  52. 6/9 Make read_early_config() reusableJohannes Schindelin, Mar 3, 2017
  53. 9/9 Test read_early_config()Johannes Schindelin, Mar 3, 2017
  54. 8/9 read_early_config(): really discover .git/Johannes Schindelin, Mar 3, 2017
  55. Junio C HamanoMar 3, 2017
  56. Johannes SchindelinMar 7, 2017
  57. Johannes SchindelinMar 7, 2017
  58. Jeff KingMar 4, 2017
  59. Junio C HamanoMar 5, 2017
  60. Johannes SchindelinMar 7, 2017
  61. Jeff KingMar 8, 2017
  62. Johannes SchindelinMar 8, 2017
  63. Jeff KingMar 8, 2017
  64. Junio C HamanoMar 8, 2017
  65. Jeff KingMar 8, 2017
  66. Junio C HamanoMar 8, 2017
  67. Johannes SchindelinMar 9, 2017
  68. Jeff KingMar 9, 2017
  69. Junio C HamanoMar 10, 2017
  70. 00/10 Fix the early configJohannes Schindelin, Mar 7, 2017
  71. 01/10 t7006: replace dubious testJohannes Schindelin, Mar 7, 2017
  72. 02/10 setup_git_directory(): use is_dir_sep() helperJohannes Schindelin, Mar 7, 2017
  73. 03/10 Prepare setup_discovered_git_directory() the root directoryJohannes Schindelin, Mar 7, 2017
  74. 04/10 setup_git_directory_1(): avoid changing global stateJohannes Schindelin, Mar 7, 2017
  75. Junio C HamanoMar 7, 2017
  76. Brandon WilliamsMar 7, 2017
  77. Johannes SchindelinMar 8, 2017
  78. Brandon WilliamsMar 8, 2017
  79. 05/10 Introduce the discover_git_directory() functionJohannes Schindelin, Mar 7, 2017
  80. 06/10 Make read_early_config() reusableJohannes Schindelin, Mar 7, 2017
  81. 08/10 read_early_config(): really discover .git/Johannes Schindelin, Mar 7, 2017
  82. 10/10 setup_git_directory_gently_1(): avoid die()ingJohannes Schindelin, Mar 7, 2017
  83. 09/10 Test read_early_config()Johannes Schindelin, Mar 7, 2017
  84. 07/10 read_early_config(): avoid .git/config hack when unneededJohannes Schindelin, Mar 7, 2017
  85. 00/11 Fix the early configJohannes Schindelin, Mar 9, 2017
  86. 01/11 t7006: replace dubious testJohannes Schindelin, Mar 9, 2017
  87. 02/11 setup_git_directory(): use is_dir_sep() helperJohannes Schindelin, Mar 9, 2017
  88. 03/11 Prepare setup_discovered_git_directory() the root directoryJohannes Schindelin, Mar 9, 2017
  89. 04/11 setup_git_directory_1(): avoid changing global stateJohannes Schindelin, Mar 9, 2017
  90. Junio C HamanoMar 10, 2017
  91. 05/11 Introduce the discover_git_directory() functionJohannes Schindelin, Mar 9, 2017
  92. 07/11 read_early_config(): avoid .git/config hack when unneededJohannes Schindelin, Mar 9, 2017
  93. 08/11 read_early_config(): really discover .git/Johannes Schindelin, Mar 9, 2017
  94. 06/11 Make read_early_config() reusableJohannes Schindelin, Mar 9, 2017
  95. 09/11 Test read_early_config()Johannes Schindelin, Mar 9, 2017
  96. Junio C HamanoMar 10, 2017
  97. Johannes SchindelinMar 13, 2017
  98. Junio C HamanoMar 13, 2017
  99. 10/11 setup_git_directory_gently_1(): avoid die()ingJohannes Schindelin, Mar 9, 2017
  100. Junio C HamanoMar 10, 2017
  101. Johannes SchindelinMar 13, 2017
  102. Junio C HamanoMar 13, 2017
  103. Junio C HamanoMar 13, 2017
  104. Johannes SchindelinMar 13, 2017
  105. Junio C HamanoMar 13, 2017
  106. 11/11 t1309: document cases where we would want early config not to die()Johannes Schindelin, Mar 9, 2017
  107. 00/12 Fix the early configJohannes Schindelin, Mar 13, 2017
  108. 01/12 t7006: replace dubious testJohannes Schindelin, Mar 13, 2017
  109. 02/12 setup_git_directory(): use is_dir_sep() helperJohannes Schindelin, Mar 13, 2017
  110. 03/12 Prepare setup_discovered_git_directory() the root directoryJohannes Schindelin, Mar 13, 2017
  111. Junio C HamanoMar 13, 2017
  112. Johannes SchindelinMar 13, 2017
  113. 04/12 setup_git_directory_1(): avoid changing global stateJohannes Schindelin, Mar 13, 2017
  114. 05/12 Introduce the discover_git_directory() functionJohannes Schindelin, Mar 13, 2017
  115. 08/12 read_early_config(): really discover .git/Johannes Schindelin, Mar 13, 2017
  116. 07/12 read_early_config(): avoid .git/config hack when unneededJohannes Schindelin, Mar 13, 2017
  117. 06/12 Make read_early_config() reusableJohannes Schindelin, Mar 13, 2017
  118. 09/12 Add t1309 to test read_early_config()Johannes Schindelin, Mar 13, 2017
  119. 10/12 setup_git_directory_gently_1(): avoid die()ingJohannes Schindelin, Mar 13, 2017
  120. 11/12 t1309: document cases where we would want early config not to die()Johannes Schindelin, Mar 13, 2017
  121. 12/12 setup.c: mention unresolved problemsJohannes Schindelin, Mar 13, 2017
  122. Junio C HamanoMar 13, 2017
  123. Jeff KingMar 14, 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.