diff options
author | Junio C Hamano <gitster@pobox.com> | 2014-01-27 22:45:33 +0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-01-27 22:45:33 +0400 |
commit | d0956cfa8ef8b3668ea6adc94b27f5dcdc93bde0 (patch) | |
tree | 188ea26d10feaf884b59423fdf8c8bafeb73e718 /dir.c | |
parent | c380cf85a79c78d9dceb9290c9d4017d30804521 (diff) | |
parent | 08f555cb82f92797ca0aa0d6ba32e6872f1331e5 (diff) |
Merge branch 'mh/safe-create-leading-directories'
Code clean-up and protection against concurrent write access to the
ref namespace.
* mh/safe-create-leading-directories:
rename_tmp_log(): on SCLD_VANISHED, retry
rename_tmp_log(): limit the number of remote_empty_directories() attempts
rename_tmp_log(): handle a possible mkdir/rmdir race
rename_ref(): extract function rename_tmp_log()
remove_dir_recurse(): handle disappearing files and directories
remove_dir_recurse(): tighten condition for removing unreadable dir
lock_ref_sha1_basic(): if locking fails with ENOENT, retry
lock_ref_sha1_basic(): on SCLD_VANISHED, retry
safe_create_leading_directories(): add new error value SCLD_VANISHED
cmd_init_db(): when creating directories, handle errors conservatively
safe_create_leading_directories(): introduce enum for return values
safe_create_leading_directories(): always restore slash at end of loop
safe_create_leading_directories(): split on first of multiple slashes
safe_create_leading_directories(): rename local variable
safe_create_leading_directories(): add explicit "slash" pointer
safe_create_leading_directories(): reduce scope of local variable
safe_create_leading_directories(): fix format of "if" chaining
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 27 |
1 files changed, 20 insertions, 7 deletions
@@ -1511,8 +1511,13 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up) flag &= ~REMOVE_DIR_KEEP_TOPLEVEL; dir = opendir(path->buf); if (!dir) { - /* an empty dir could be removed even if it is unreadble */ - if (!keep_toplevel) + if (errno == ENOENT) + return keep_toplevel ? -1 : 0; + else if (errno == EACCES && !keep_toplevel) + /* + * An empty dir could be removable even if it + * is unreadable: + */ return rmdir(path->buf); else return -1; @@ -1528,13 +1533,21 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up) strbuf_setlen(path, len); strbuf_addstr(path, e->d_name); - if (lstat(path->buf, &st)) - ; /* fall thru */ - else if (S_ISDIR(st.st_mode)) { + if (lstat(path->buf, &st)) { + if (errno == ENOENT) + /* + * file disappeared, which is what we + * wanted anyway + */ + continue; + /* fall thru */ + } else if (S_ISDIR(st.st_mode)) { if (!remove_dir_recurse(path, flag, &kept_down)) continue; /* happy */ - } else if (!only_empty && !unlink(path->buf)) + } else if (!only_empty && + (!unlink(path->buf) || errno == ENOENT)) { continue; /* happy, too */ + } /* path too long, stat fails, or non-directory still exists */ ret = -1; @@ -1544,7 +1557,7 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up) strbuf_setlen(path, original_len); if (!ret && !keep_toplevel && !kept_down) - ret = rmdir(path->buf); + ret = (!rmdir(path->buf) || errno == ENOENT) ? 0 : -1; else if (kept_up) /* * report the uplevel that it is not an error that we |