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

Re: [PATCH v2 07/11] streaming_write_entry(): use streaming API in write_entry()

From
Junio C Hamano <gitster@pobox.com>
Date
May 20, 2011, 22:52 UTC
Message-ID
<7vvcx50yt8.fsf@alter.siamese.dyndns.org>
In-Reply-To
<1305840826-7783-8-git-send-email-gitster@pobox.com>
Junio C Hamano <gitster@pobox.com> writes:
> When the output to a path does not have to be converted, we can read from
> the object database from the streaming API and write to the file in the
> working tree, without having to hold everything in the memory.

There was an embarrassing bug hiding here. The way I found it was doubly embarrassing.

Show 16 quoted lines
> diff --git a/entry.c b/entry.c
> index cc6502a..7733a6b 100644
> --- a/entry.c
> +++ b/entry.c
> @@ -114,6 +115,50 @@ static int fstat_output(int fd, const struct checkout *state, struct stat *st)
>  	return 0;
>  }
>  
> +static int streaming_write_entry(struct cache_entry *ce, char *path,
> +				 const struct checkout *state, int to_tempfile,
> +				 int *fstat_done, struct stat *statbuf)
> +{
> +	struct git_istream *st;
> +	enum object_type type;
> +	unsigned long sz;
> +	int result = -1;
We see result is initialized to -1 here...
Show 6 quoted lines
> +	int fd = -1;
> +
> +	st = open_istream(ce->sha1, &type, &sz);
> + ...
> +close_and_exit:
> +	close_istream(st);

...but nobody touches it before coming here via various codepaths. If I haven't opened the output, fd is -1, but if I have, then the condition of the next if statement is met, and I close the output.

> +	if (0 <= fd)
> +		result |= close(fd);

Oops. This is the embarrassment. This has to be an assignment, not OR-ing it in. I am not clearing the result in a successful case.

> +	if (result && 0 <= fd)
> +		unlink(path);
> +	return result;

Hence, even though the codepath fully wrote out, we run unlink(path), and return a failure.

Show 9 quoted lines
> @@ -124,6 +169,12 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
>  	size_t wrote, newsize = 0;
>  	struct stat st;
>  
> +	if ((ce_mode_s_ifmt == S_IFREG) &&
> +	    can_bypass_conversion(path) &&
> +	    !streaming_write_entry(ce, path, state, to_tempfile,
> +				   &fstat_done, &st))
> +		goto finish;

Then the caller just thinks that the contents could not be streamed (e.g. the data is in pack deltified) and takes the fall-back codepath to fix everything up, hiding the above bug.

>  	switch (ce_mode_s_ifmt) {
>  	case S_IFREG:
>  	case S_IFLNK:
>		... fall-back code follows ...

The other embarrassment is the way how I found the bug. I was trying to rewrite this "if regular file and can bypass conversion, try streaming" logic, and botched the result to jump to "finish" when streaming write returned failure.

Will re-queue with the obvious fix squashed in.
Previous: Junio C HamanoNext: Junio C Hamano
Message 43 of 49 in “writing out a huge blob to working tree”
  1. 00/11 writing out a huge blob to working treeJunio C Hamano, May 16, 2011
  2. 01/11 packed_object_info_detail(): do not return a stringJunio C Hamano, May 16, 2011
  3. Thiago FarinaMay 17, 2011
  4. Junio C HamanoMay 17, 2011
  5. 02/11 sha1_object_info_extended(): expose a bit more infoJunio C Hamano, May 16, 2011
  6. 03/11 sha1_object_info_extended(): hint about objects in delta-base cacheJunio C Hamano, May 16, 2011
  7. Shawn PearceMay 16, 2011
  8. 04/11 unpack_object_header(): make it publicJunio C Hamano, May 16, 2011
  9. 05/11 write_entry(): separate two helper functions outJunio C Hamano, May 16, 2011
  10. 06/11 streaming: a new API to read from the object storeJunio C Hamano, May 16, 2011
  11. Jeff KingMay 18, 2011
  12. Junio C HamanoMay 19, 2011
  13. 07/11 streaming_write_entry(): use streaming API in write_entry()Junio C Hamano, May 16, 2011
  14. 08/11 streaming_write_entry(): support files with holesJunio C Hamano, May 16, 2011
  15. Nguyen Thai Ngoc DuyMay 16, 2011
  16. Junio C HamanoMay 16, 2011
  17. Nguyen Thai Ngoc DuyMay 17, 2011
  18. Junio C HamanoMay 17, 2011
  19. Thiago FarinaMay 16, 2011
  20. 09/11 streaming: read non-delta incrementally from a packJunio C Hamano, May 16, 2011
  21. Shawn PearceMay 16, 2011
  22. Junio C HamanoMay 16, 2011
  23. 10/11 sha1_file.c: expose helpers to read loose objectsJunio C Hamano, May 16, 2011
  24. 11/11 streaming: read loose objects incrementallyJunio C Hamano, May 16, 2011
  25. Shawn PearceMay 16, 2011
  26. Jeff KingMay 18, 2011
  27. Jeff KingMay 18, 2011
  28. Jeff KingMay 18, 2011
  29. Junio C HamanoMay 18, 2011
  30. Jeff KingMay 18, 2011
  31. 00/11 writing out a huge blob to working treeJunio C Hamano, May 19, 2011
  32. 01/11 packed_object_info_detail(): do not return a stringJunio C Hamano, May 19, 2011
  33. 02/11 sha1_object_info_extended(): expose a bit more infoJunio C Hamano, May 19, 2011
  34. 03/11 sha1_object_info_extended(): hint about objects in delta-base cacheJunio C Hamano, May 19, 2011
  35. René ScharfeMay 20, 2011
  36. Junio C HamanoMay 21, 2011
  37. 04/11 unpack_object_header(): make it publicJunio C Hamano, May 19, 2011
  38. 05/11 write_entry(): separate two helper functions outJunio C Hamano, May 19, 2011
  39. 06/11 streaming: a new API to read from the object storeJunio C Hamano, May 19, 2011
  40. René ScharfeMay 20, 2011
  41. Junio C HamanoMay 21, 2011
  42. 07/11 streaming_write_entry(): use streaming API in write_entry()Junio C Hamano, May 19, 2011
  43. Junio C HamanoMay 20, 2011
  44. 08/11 streaming_write_entry(): support files with holesJunio C Hamano, May 19, 2011
  45. 09/11 streaming: read non-delta incrementally from a packJunio C Hamano, May 19, 2011
  46. 10/11 sha1_file.c: expose helpers to read loose objectsJunio C Hamano, May 19, 2011
  47. 11/11 streaming: read loose objects incrementallyJunio C Hamano, May 19, 2011
  48. 02/11 interdiffJunio C Hamano, May 19, 2011
  49. Jeff KingMay 19, 2011

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.