Merge branch 'ls/filter-process-delayed'

Bugfixes to an already graduated series.

* ls/filter-process-delayed:
  write_entry: untangle symlink and regular-file cases
  write_entry: avoid reading blobs in CE_RETRY case
  write_entry: fix leak when retrying delayed filter
  entry.c: check if file exists after checkout
  entry.c: update cache entry only for existing files
maint
Junio C Hamano 2017-10-11 14:52:24 +09:00
commit 6909bf6bd9
1 changed files with 53 additions and 37 deletions

90
entry.c
View File

@ -253,6 +253,7 @@ static int write_entry(struct cache_entry *ce,
char *path, const struct checkout *state, int to_tempfile) char *path, const struct checkout *state, int to_tempfile)
{ {
unsigned int ce_mode_s_ifmt = ce->ce_mode & S_IFMT; unsigned int ce_mode_s_ifmt = ce->ce_mode & S_IFMT;
struct delayed_checkout *dco = state->delayed_checkout;
int fd, ret, fstat_done = 0; int fd, ret, fstat_done = 0;
char *new; char *new;
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
@ -273,55 +274,65 @@ static int write_entry(struct cache_entry *ce,
} }


switch (ce_mode_s_ifmt) { switch (ce_mode_s_ifmt) {
case S_IFREG:
case S_IFLNK: case S_IFLNK:
new = read_blob_entry(ce, &size); new = read_blob_entry(ce, &size);
if (!new) if (!new)
return error("unable to read sha1 file of %s (%s)", return error("unable to read sha1 file of %s (%s)",
path, oid_to_hex(&ce->oid)); path, oid_to_hex(&ce->oid));


if (ce_mode_s_ifmt == S_IFLNK && has_symlinks && !to_tempfile) { /*
ret = symlink(new, path); * We can't make a real symlink; write out a regular file entry
free(new); * with the symlink destination as its contents.
if (ret) */
return error_errno("unable to create symlink %s", if (!has_symlinks || to_tempfile)
path); goto write_file_entry;
break;
ret = symlink(new, path);
free(new);
if (ret)
return error_errno("unable to create symlink %s", path);
break;

case S_IFREG:
/*
* We do not send the blob in case of a retry, so do not
* bother reading it at all.
*/
if (dco && dco->state == CE_RETRY) {
new = NULL;
size = 0;
} else {
new = read_blob_entry(ce, &size);
if (!new)
return error("unable to read sha1 file of %s (%s)",
path, oid_to_hex(&ce->oid));
} }


/* /*
* Convert from git internal format to working tree format * Convert from git internal format to working tree format
*/ */
if (ce_mode_s_ifmt == S_IFREG) { if (dco && dco->state != CE_NO_DELAY) {
struct delayed_checkout *dco = state->delayed_checkout; ret = async_convert_to_working_tree(ce->name, new,
if (dco && dco->state != CE_NO_DELAY) { size, &buf, dco);
/* Do not send the blob in case of a retry. */ if (ret && string_list_has_string(&dco->paths, ce->name)) {
if (dco->state == CE_RETRY) {
new = NULL;
size = 0;
}
ret = async_convert_to_working_tree(
ce->name, new, size, &buf, dco);
if (ret && string_list_has_string(&dco->paths, ce->name)) {
free(new);
goto finish;
}
} else
ret = convert_to_working_tree(
ce->name, new, size, &buf);

if (ret) {
free(new); free(new);
new = strbuf_detach(&buf, &newsize); goto delayed;
size = newsize;
} }
/* } else
* No "else" here as errors from convert are OK at this ret = convert_to_working_tree(ce->name, new, size, &buf);
* point. If the error would have been fatal (e.g.
* filter is required), then we would have died already.
*/
}


if (ret) {
free(new);
new = strbuf_detach(&buf, &newsize);
size = newsize;
}
/*
* No "else" here as errors from convert are OK at this
* point. If the error would have been fatal (e.g.
* filter is required), then we would have died already.
*/

write_file_entry:
fd = open_output_fd(path, ce, to_tempfile); fd = open_output_fd(path, ce, to_tempfile);
if (fd < 0) { if (fd < 0) {
free(new); free(new);
@ -336,6 +347,7 @@ static int write_entry(struct cache_entry *ce,
if (wrote < 0) if (wrote < 0)
return error("unable to write file %s", path); return error("unable to write file %s", path);
break; break;

case S_IFGITLINK: case S_IFGITLINK:
if (to_tempfile) if (to_tempfile)
return error("cannot create temporary submodule %s", path); return error("cannot create temporary submodule %s", path);
@ -347,6 +359,7 @@ static int write_entry(struct cache_entry *ce,
NULL, oid_to_hex(&ce->oid), NULL, oid_to_hex(&ce->oid),
state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0); state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0);
break; break;

default: default:
return error("unknown file mode for %s in index", path); return error("unknown file mode for %s in index", path);
} }
@ -355,11 +368,14 @@ finish:
if (state->refresh_cache) { if (state->refresh_cache) {
assert(state->istate); assert(state->istate);
if (!fstat_done) if (!fstat_done)
lstat(ce->name, &st); if (lstat(ce->name, &st) < 0)
return error_errno("unable to stat just-written file %s",
ce->name);
fill_stat_cache_info(ce, &st); fill_stat_cache_info(ce, &st);
ce->ce_flags |= CE_UPDATE_IN_BASE; ce->ce_flags |= CE_UPDATE_IN_BASE;
state->istate->cache_changed |= CE_ENTRY_CHANGED; state->istate->cache_changed |= CE_ENTRY_CHANGED;
} }
delayed:
return 0; return 0;
} }