diff options
Diffstat (limited to 'entry.c')
| -rw-r--r-- | entry.c | 50 |
1 files changed, 39 insertions, 11 deletions
@@ -113,8 +113,7 @@ static int fstat_output(int fd, const struct checkout *state, struct stat *st) /* use fstat() only when path == ce->name */ if (fstat_is_reliable() && state->refresh_cache && !state->base_dir_len) { - fstat(fd, st); - return 1; + return !fstat(fd, st); } return 0; } @@ -161,7 +160,7 @@ static int remove_available_paths(struct string_list_item *item, void *cb_data) return !available; } -int finish_delayed_checkout(struct checkout *state) +int finish_delayed_checkout(struct checkout *state, int *nr_checkouts) { int errs = 0; unsigned delayed_object_count; @@ -226,7 +225,7 @@ int finish_delayed_checkout(struct checkout *state) ce = index_file_exists(state->istate, path->string, strlen(path->string), 0); if (ce) { - errs |= checkout_entry(ce, state, NULL); + errs |= checkout_entry(ce, state, NULL, nr_checkouts); filtered_bytes += ce->ce_stat_data.sd_size; display_throughput(progress, filtered_bytes); } else @@ -264,6 +263,9 @@ static int write_entry(struct cache_entry *ce, size_t newsize = 0; struct stat st; const struct submodule *sub; + struct checkout_metadata meta; + + clone_checkout_metadata(&meta, &state->meta, &ce->oid); if (ce_mode_s_ifmt == S_IFREG) { struct stream_filter *filter = get_stream_filter(state->istate, ce->name, @@ -315,13 +317,13 @@ static int write_entry(struct cache_entry *ce, */ if (dco && dco->state != CE_NO_DELAY) { ret = async_convert_to_working_tree(state->istate, ce->name, new_blob, - size, &buf, dco); + size, &buf, &meta, dco); if (ret && string_list_has_string(&dco->paths, ce->name)) { free(new_blob); goto delayed; } } else - ret = convert_to_working_tree(state->istate, ce->name, new_blob, size, &buf); + ret = convert_to_working_tree(state->istate, ce->name, new_blob, size, &buf, &meta); if (ret) { free(new_blob); @@ -373,7 +375,7 @@ finish: 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(state->istate, ce, &st); ce->ce_flags |= CE_UPDATE_IN_BASE; mark_fsmonitor_invalid(state->istate, ce); state->istate->cache_changed |= CE_ENTRY_CHANGED; @@ -435,12 +437,23 @@ static void mark_colliding_entries(const struct checkout *state, * its name is returned in topath[], which must be able to hold at * least TEMPORARY_FILENAME_LENGTH bytes long. */ -int checkout_entry(struct cache_entry *ce, - const struct checkout *state, char *topath) +int checkout_entry(struct cache_entry *ce, const struct checkout *state, + char *topath, int *nr_checkouts) { static struct strbuf path = STRBUF_INIT; struct stat st; + if (ce->ce_flags & CE_WT_REMOVE) { + if (topath) + /* + * No content and thus no path to create, so we have + * no pathname to return. + */ + BUG("Can't remove entry to a path"); + unlink_entry(ce); + return 0; + } + if (topath) return write_entry(ce, topath, state, 1); @@ -497,8 +510,6 @@ int checkout_entry(struct cache_entry *ce, /* If it is a gitlink, leave it alone! */ if (S_ISGITLINK(ce->ce_mode)) return 0; - if (!state->force) - return error("%s is a directory", path.buf); remove_subtree(&path); } else if (unlink(path.buf)) return error_errno("unable to unlink old '%s'", path.buf); @@ -506,5 +517,22 @@ int checkout_entry(struct cache_entry *ce, return 0; create_directories(path.buf, path.len, state); + if (nr_checkouts) + (*nr_checkouts)++; return write_entry(ce, path.buf, state, 0); } + +void unlink_entry(const struct cache_entry *ce) +{ + const struct submodule *sub = submodule_from_ce(ce); + if (sub) { + /* state.force is set at the caller. */ + submodule_move_head(ce->name, "HEAD", NULL, + SUBMODULE_MOVE_HEAD_FORCE); + } + if (!check_leading_path(ce->name, ce_namelen(ce))) + return; + if (remove_or_warn(ce->ce_mode, ce->name)) + return; + schedule_dir_for_removal(ce->name, ce_namelen(ce)); +} |
