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
This commit is contained in:
27
dir.c
27
dir.c
@ -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
|
||||
|
||||
Reference in New Issue
Block a user