commit 1c4cdd89292391629861b9a13688e94879efe2ea from: Stefan Sperling date: Sun Jun 20 21:07:54 2021 UTC fix bogus 'permission denied' error when a file at work tree root is removed ok naddy commit - b4f3757062b79ae08d3c386051bbf6c37902ec35 commit + 1c4cdd89292391629861b9a13688e94879efe2ea blob - 77e9ecb628d437b68e991e2de6d272b5053ad9e0 blob + 8fda1956ff24817df54807e1982ca82da40af38a --- lib/worktree.c +++ lib/worktree.c @@ -2104,7 +2104,7 @@ static const struct got_error * remove_ondisk_file(const char *root_path, const char *path) { const struct got_error *err = NULL; - char *ondisk_path = NULL; + char *ondisk_path = NULL, *parent = NULL; if (asprintf(&ondisk_path, "%s/%s", root_path, path) == -1) return got_error_from_errno("asprintf"); @@ -2114,23 +2114,28 @@ remove_ondisk_file(const char *root_path, const char * err = got_error_from_errno2("unlink", ondisk_path); } else { size_t root_len = strlen(root_path); - do { - char *parent; - err = got_path_dirname(&parent, ondisk_path); - if (err) - break; + err = got_path_dirname(&parent, ondisk_path); + if (err) + goto done; + while (got_path_cmp(parent, root_path, + strlen(parent), root_len) != 0) { free(ondisk_path); ondisk_path = parent; + parent = NULL; if (rmdir(ondisk_path) == -1) { if (errno != ENOTEMPTY) err = got_error_from_errno2("rmdir", ondisk_path); break; } - } while (got_path_cmp(ondisk_path, root_path, - strlen(ondisk_path), root_len) != 0); + err = got_path_dirname(&parent, ondisk_path); + if (err) + break; + } } +done: free(ondisk_path); + free(parent); return err; } blob - c90dd13dc4e8de96ade487d14ace7bf99feecb82 blob + fa0398814a0312e4d8d4d343c490f6b7b4129804 --- regress/cmdline/update.sh +++ regress/cmdline/update.sh @@ -98,7 +98,8 @@ test_update_adds_file() { test_update_deletes_file() { local testroot=`test_init update_deletes_file` - got checkout $testroot/repo $testroot/wt > /dev/null + mkdir $testroot/wtparent + got checkout $testroot/repo $testroot/wtparent/wt > /dev/null ret="$?" if [ "$ret" != "0" ]; then test_done "$testroot" "$ret" @@ -113,7 +114,11 @@ test_update_deletes_file() { git_show_head $testroot/repo >> $testroot/stdout.expected echo >> $testroot/stdout.expected - (cd $testroot/wt && got update > $testroot/stdout) + # verify that no error occurs if the work tree's parent + # directory is not writable + chmod u-w $testroot/wtparent + (cd $testroot/wtparent/wt && got update > $testroot/stdout) + chmod u+w $testroot/wtparent cmp -s $testroot/stdout.expected $testroot/stdout ret="$?" @@ -123,7 +128,7 @@ test_update_deletes_file() { return 1 fi - if [ -e $testroot/wt/beta ]; then + if [ -e $testroot/wtparent/wt/beta ]; then echo "removed file beta still exists on disk" >&2 test_done "$testroot" "1" return 1