commit 15341bfd54bbabbe30297c358faf41ee05e247da from: Tracey Emery date: Thu Mar 05 14:39:37 2020 UTC trim directories in got remove -R This is a racy solution that needs to be properly implemented in the future. ok stsp commit - 5b87815ed2f346f81374261ce2d633feae711886 commit + 15341bfd54bbabbe30297c358faf41ee05e247da blob - c9da5df6a4a5a861d6cae4274f1237a6f0bc599f blob + 9f9917254ace14896c27a0a7fc4e35e35c42eb71 --- lib/worktree.c +++ lib/worktree.c @@ -2992,7 +2992,7 @@ schedule_for_deletion(void *arg, unsigned char status, const struct got_error *err = NULL; struct got_fileindex_entry *ie = NULL; struct stat sb; - char *ondisk_path; + char *ondisk_path, *parent = NULL; ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath)); if (ie == NULL) @@ -3038,6 +3038,26 @@ schedule_for_deletion(void *arg, unsigned char status, } else if (unlink(ondisk_path) != 0) { err = got_error_from_errno2("unlink", ondisk_path); goto done; + } + + parent = dirname(ondisk_path); + + if (parent == NULL) { + err = got_error_from_errno2("dirname", ondisk_path); + goto done; + } + while (parent && strcmp(parent, a->worktree->root_path) != 0) { + if (rmdir(parent) == -1) { + if (errno != ENOTEMPTY) + err = got_error_from_errno2("rmdir", + parent); + break; + } + parent = dirname(parent); + if (parent == NULL) { + err = got_error_from_errno2("dirname", parent); + goto done; + } } } blob - fdeae68f86183c12278162f1e566e5eccf587652 blob + 21b308c15e0b334333d5c674b394de80c25a671d --- regress/cmdline/revert.sh +++ regress/cmdline/revert.sh @@ -979,7 +979,70 @@ function test_revert_added_subtree { echo "? epsilon/foo/bar/baz/c.o" >> $testroot/stdout.expected echo "? epsilon/foo/bar/baz/f.d" >> $testroot/stdout.expected echo "? epsilon/foo/bar/baz/f.o" >> $testroot/stdout.expected + + (cd $testroot/wt && got status > $testroot/stdout) + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" +} + +function test_revert_deleted_subtree { + local testroot=`test_init revert_deleted_subtree` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + mkdir -p $testroot/wt/epsilon/foo/bar/baz + mkdir -p $testroot/wt/epsilon/foo/bar/bax + echo "new file" > $testroot/wt/epsilon/foo/a.o + echo "new file" > $testroot/wt/epsilon/foo/a.o + echo "new file" > $testroot/wt/epsilon/foo/bar/b.o + echo "new file" > $testroot/wt/epsilon/foo/bar/b.d + echo "new file" > $testroot/wt/epsilon/foo/bar/baz/f.o + echo "new file" > $testroot/wt/epsilon/foo/bar/baz/f.d + echo "new file" > $testroot/wt/epsilon/foo/bar/baz/c.o + echo "new file" > $testroot/wt/epsilon/foo/bar/baz/c.d + echo "new file" > $testroot/wt/epsilon/foo/bar/bax/e.o + echo "new file" > $testroot/wt/epsilon/foo/bar/bax/e.d + echo "new file" > $testroot/wt/epsilon/foo/bar/bax/x.o + echo "new file" > $testroot/wt/epsilon/foo/bar/bax/x.d + (cd $testroot/wt && got add -R epsilon >/dev/null) + (cd $testroot/wt && got commit -m "add subtree" >/dev/null) + # now delete and revert the entire subtree + (cd $testroot/wt && got rm -R epsilon/foo >/dev/null) + + echo "R epsilon/foo/a.o" > $testroot/stdout.expected + echo "R epsilon/foo/bar/b.d" >> $testroot/stdout.expected + echo "R epsilon/foo/bar/b.o" >> $testroot/stdout.expected + echo "R epsilon/foo/bar/bax/e.d" >> $testroot/stdout.expected + echo "R epsilon/foo/bar/bax/e.o" >> $testroot/stdout.expected + echo "R epsilon/foo/bar/bax/x.d" >> $testroot/stdout.expected + echo "R epsilon/foo/bar/bax/x.o" >> $testroot/stdout.expected + echo "R epsilon/foo/bar/baz/c.d" >> $testroot/stdout.expected + echo "R epsilon/foo/bar/baz/c.o" >> $testroot/stdout.expected + echo "R epsilon/foo/bar/baz/f.d" >> $testroot/stdout.expected + echo "R epsilon/foo/bar/baz/f.o" >> $testroot/stdout.expected + + (cd $testroot/wt && got revert -R . > $testroot/stdout) + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo -n > $testroot/stdout.expected (cd $testroot/wt && got status > $testroot/stdout) cmp -s $testroot/stdout.expected $testroot/stdout @@ -1003,3 +1066,4 @@ run_test test_revert_patch_added run_test test_revert_patch_removed run_test test_revert_patch_one_change run_test test_revert_added_subtree +run_test test_revert_deleted_subtree blob - 9ea8be8b1e091a6c1974b3a81b2f05a550bcd266 blob + 569901043e4f61febe7b340a1600a12e0c1f8879 --- regress/cmdline/rm.sh +++ regress/cmdline/rm.sh @@ -239,6 +239,30 @@ function test_rm_directory { return 1 fi + (cd $testroot/wt && ls -l > $testroot/stdout) + + echo -n '' > $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + (cd $testroot/wt && ls -l > $testroot/stdout) + + echo -n '' > $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + test_done "$testroot" "$ret" } @@ -322,9 +346,68 @@ function test_rm_directory_keep_files { test_done "$testroot" "$ret" } +function test_rm_subtree { + local testroot=`test_init rm_subtree` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + mkdir -p $testroot/wt/epsilon/foo/bar/baz + mkdir -p $testroot/wt/epsilon/foo/bar/bax + echo "new file" > $testroot/wt/epsilon/foo/a.o + echo "new file" > $testroot/wt/epsilon/foo/a.o + echo "new file" > $testroot/wt/epsilon/foo/bar/b.o + echo "new file" > $testroot/wt/epsilon/foo/bar/b.d + echo "new file" > $testroot/wt/epsilon/foo/bar/baz/f.o + echo "new file" > $testroot/wt/epsilon/foo/bar/baz/f.d + echo "new file" > $testroot/wt/epsilon/foo/bar/baz/c.o + echo "new file" > $testroot/wt/epsilon/foo/bar/baz/c.d + echo "new file" > $testroot/wt/epsilon/foo/bar/bax/e.o + echo "new file" > $testroot/wt/epsilon/foo/bar/bax/e.d + echo "new file" > $testroot/wt/epsilon/foo/bar/bax/x.o + echo "new file" > $testroot/wt/epsilon/foo/bar/bax/x.d + (cd $testroot/wt && got add -R epsilon >/dev/null) + (cd $testroot/wt && got commit -m "add subtree" >/dev/null) + + # now delete and revert the entire subtree + (cd $testroot/wt && got rm -R epsilon/foo >/dev/null) + + if [ -d $testroot/wt/epsilon/foo ]; then + echo "removed dir epsilon/foo still exists on disk" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "D epsilon/foo/a.o" > $testroot/stdout.expected + echo "D epsilon/foo/bar/b.d" >> $testroot/stdout.expected + echo "D epsilon/foo/bar/b.o" >> $testroot/stdout.expected + echo "D epsilon/foo/bar/bax/e.d" >> $testroot/stdout.expected + echo "D epsilon/foo/bar/bax/e.o" >> $testroot/stdout.expected + echo "D epsilon/foo/bar/bax/x.d" >> $testroot/stdout.expected + echo "D epsilon/foo/bar/bax/x.o" >> $testroot/stdout.expected + echo "D epsilon/foo/bar/baz/c.d" >> $testroot/stdout.expected + echo "D epsilon/foo/bar/baz/c.o" >> $testroot/stdout.expected + echo "D epsilon/foo/bar/baz/f.d" >> $testroot/stdout.expected + echo "D epsilon/foo/bar/baz/f.o" >> $testroot/stdout.expected + + (cd $testroot/wt && got status > $testroot/stdout) + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" +} + run_test test_rm_basic run_test test_rm_with_local_mods run_test test_double_rm run_test test_rm_and_add_elsewhere run_test test_rm_directory run_test test_rm_directory_keep_files +run_test test_rm_subtree