]> granicus.if.org Git - git/commitdiff
entry.c: update cache entry only for existing files
authorLars Schneider <larsxschneider@gmail.com>
Thu, 5 Oct 2017 10:44:06 +0000 (12:44 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 5 Oct 2017 11:01:07 +0000 (20:01 +0900)
In 2841e8f ("convert: add "status=delayed" to filter process protocol",
2017-06-30) we taught the filter process protocol to delay responses.

That means an external filter might answer in the first write_entry()
call on a file that requires filtering  "I got your request, but I
can't answer right now. Ask again later!". As Git got no answer, we do
not write anything to the filesystem. Consequently, the lstat() call in
the finish block of the function writes garbage to the cache entry.
The garbage is eventually overwritten when the filter answers with
the final file content in a subsequent write_entry() call.

Fix the brief time window of garbage in the cache entry by adding a
special finish block that does nothing for delayed responses. The cache
entry is written properly in a subsequent write_entry() call where
the filter responds with the final file content.

Reported-by: Jeff King <peff@peff.net>
Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
entry.c

diff --git a/entry.c b/entry.c
index 65458f07a4453fa29731fe2b9c20848d6b192b20..f879758c73894fa2d3bec01d310feb63924ec8c1 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -290,7 +290,7 @@ static int write_entry(struct cache_entry *ce,
                                        ce->name, new, size, &buf, dco);
                                if (ret && string_list_has_string(&dco->paths, ce->name)) {
                                        free(new);
-                                       goto finish;
+                                       goto delayed;
                                }
                        } else
                                ret = convert_to_working_tree(
@@ -346,6 +346,7 @@ finish:
                ce->ce_flags |= CE_UPDATE_IN_BASE;
                state->istate->cache_changed |= CE_ENTRY_CHANGED;
        }
+delayed:
        return 0;
 }