| From 8fb8d8ca3122affc447e81d61588081dc5107bff Mon Sep 17 00:00:00 2001 |
| From: Jeff King <peff@peff.net> |
| Date: Mon, 14 May 2018 11:00:56 -0400 |
| Subject: update-index: stat updated files earlier |
| |
| commit eb12dd0c764d2b71bebd5ffffb7379a3835253ae upstream. |
| |
| In the update_one(), we check verify_path() on the proposed |
| path before doing anything else. In preparation for having |
| verify_path() look at the file mode, let's stat the file |
| earlier, so we can check the mode accurately. |
| |
| This is made a bit trickier by the fact that this function |
| only does an lstat in a few code paths (the ones that flow |
| down through process_path()). So we can speculatively do the |
| lstat() here and pass the results down, and just use a dummy |
| mode for cases where we won't actually be updating the index |
| from the filesystem. |
| |
| Signed-off-by: Jeff King <peff@peff.net> |
| Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> |
| --- |
| builtin/update-index.c | 25 +++++++++++++++++-------- |
| 1 file changed, 17 insertions(+), 8 deletions(-) |
| |
| diff --git a/builtin/update-index.c b/builtin/update-index.c |
| index f3f07e7f1c..e14f928a63 100644 |
| --- a/builtin/update-index.c |
| +++ b/builtin/update-index.c |
| @@ -354,10 +354,9 @@ static int process_directory(const char *path, int len, struct stat *st) |
| return error("%s: is a directory - add files inside instead", path); |
| } |
| |
| -static int process_path(const char *path) |
| +static int process_path(const char *path, struct stat *st, int stat_errno) |
| { |
| int pos, len; |
| - struct stat st; |
| const struct cache_entry *ce; |
| |
| len = strlen(path); |
| @@ -381,13 +380,13 @@ static int process_path(const char *path) |
| * First things first: get the stat information, to decide |
| * what to do about the pathname! |
| */ |
| - if (lstat(path, &st) < 0) |
| - return process_lstat_error(path, errno); |
| + if (stat_errno) |
| + return process_lstat_error(path, stat_errno); |
| |
| - if (S_ISDIR(st.st_mode)) |
| - return process_directory(path, len, &st); |
| + if (S_ISDIR(st->st_mode)) |
| + return process_directory(path, len, st); |
| |
| - return add_one_path(ce, path, len, &st); |
| + return add_one_path(ce, path, len, st); |
| } |
| |
| static int add_cacheinfo(unsigned int mode, const struct object_id *oid, |
| @@ -439,6 +438,16 @@ static void chmod_path(char flip, const char *path) |
| |
| static void update_one(const char *path) |
| { |
| + int stat_errno = 0; |
| + struct stat st; |
| + |
| + if (mark_valid_only || mark_skip_worktree_only || force_remove) |
| + st.st_mode = 0; |
| + else if (lstat(path, &st) < 0) { |
| + st.st_mode = 0; |
| + stat_errno = errno; |
| + } /* else stat is valid */ |
| + |
| if (!verify_path(path)) { |
| fprintf(stderr, "Ignoring path %s\n", path); |
| return; |
| @@ -460,7 +469,7 @@ static void update_one(const char *path) |
| report("remove '%s'", path); |
| return; |
| } |
| - if (process_path(path)) |
| + if (process_path(path, &st, stat_errno)) |
| die("Unable to process path %s", path); |
| report("add '%s'", path); |
| } |
| -- |
| 2.17.0.921.gf22659ad46 |
| |