commit 70e3e7f5a129106c0c31204233b35dfdf0d6a990 from: Tracey Emery date: Fri Dec 13 20:05:57 2019 UTC add -k option to 'got remove' to keep files on disk ok stsp commit - ab0d43616704b463cc02e5c8ea982dcf10f83f4b commit + 70e3e7f5a129106c0c31204233b35dfdf0d6a990 blob - 42403d111ef601d3428f3750208becb5665fcfc0 blob + 891a15aa6bdc4403a76ecd39911b337be71d6a8d --- got/got.1 +++ got/got.1 @@ -645,7 +645,7 @@ With -R, add files even if they match a .Cm got status ignore pattern. .El -.It Cm remove Oo Fl R Oc Ar file-path ... +.It Cm remove Oo Fl f Oc Oo Fl k Oc Oo Fl R Oc Ar file-path ... Remove versioned files from a work tree and schedule them for deletion from the repository in the next commit. .Pp @@ -655,6 +655,8 @@ are as follows: .Bl -tag -width Ds .It Fl f Perform the operation even if a file contains uncommitted modifications. +.It Fl k +Keep affected files on disk. .It Fl R Permit recursion into directories. If this option is not specified, blob - 8c969b31a3b2e2b4c4a35686c98b8c2423e129aa blob + a79e4584ac3231621c120c9b63775d4498bb090a --- got/got.c +++ got/got.c @@ -4296,7 +4296,7 @@ done: __dead static void usage_remove(void) { - fprintf(stderr, "usage: %s remove [-f] [-R] file-path ...\n", + fprintf(stderr, "usage: %s remove [-f] [-k] [-R] file-path ...\n", getprogname()); exit(1); } @@ -4324,15 +4324,18 @@ cmd_remove(int argc, char *argv[]) char *cwd = NULL; struct got_pathlist_head paths; struct got_pathlist_entry *pe; - int ch, delete_local_mods = 0, can_recurse = 0; + int ch, delete_local_mods = 0, can_recurse = 0, keep_on_disk = 0; TAILQ_INIT(&paths); - while ((ch = getopt(argc, argv, "fR")) != -1) { + while ((ch = getopt(argc, argv, "fkR")) != -1) { switch (ch) { case 'f': delete_local_mods = 1; break; + case 'k': + keep_on_disk = 1; + break; case 'R': can_recurse = 1; break; @@ -4406,7 +4409,7 @@ cmd_remove(int argc, char *argv[]) } error = got_worktree_schedule_delete(worktree, &paths, - delete_local_mods, print_remove_status, NULL, repo); + delete_local_mods, print_remove_status, NULL, repo, keep_on_disk); if (error) goto done; done: blob - 336d1632ff268f2001439c5e88406df75d8d3a58 blob + 09b7625b9d125ef255c71f181a0dad5efddd31d0 --- include/got_worktree.h +++ include/got_worktree.h @@ -180,7 +180,7 @@ const struct got_error *got_worktree_schedule_add(stru const struct got_error * got_worktree_schedule_delete(struct got_worktree *, struct got_pathlist_head *, int, got_worktree_delete_cb, void *, - struct got_repository *); + struct got_repository *, int); /* A callback function which is used to select or reject a patch. */ typedef const struct got_error *(*got_worktree_patch_cb)(int *, void *, blob - 2e614c890d931081960fe19a11e0d4e1f71b6022 blob + 1c03382cebef540e39e114d8abddb5fd5b2a270d --- lib/worktree.c +++ lib/worktree.c @@ -2929,6 +2929,7 @@ struct schedule_deletion_args { void *progress_arg; struct got_repository *repo; int delete_local_mods; + int keep_on_disk; }; static const struct got_error * @@ -2977,7 +2978,7 @@ schedule_for_deletion(void *arg, unsigned char status, } } - if (status != GOT_STATUS_MISSING) { + if (!a->keep_on_disk && status != GOT_STATUS_MISSING) { if (dirfd != -1) { if (unlinkat(dirfd, de_name, 0) != 0) { err = got_error_from_errno2("unlinkat", @@ -3005,7 +3006,7 @@ const struct got_error * got_worktree_schedule_delete(struct got_worktree *worktree, struct got_pathlist_head *paths, int delete_local_mods, got_worktree_delete_cb progress_cb, void *progress_arg, - struct got_repository *repo) + struct got_repository *repo, int keep_on_disk) { struct got_fileindex *fileindex = NULL; char *fileindex_path = NULL; @@ -3027,6 +3028,7 @@ got_worktree_schedule_delete(struct got_worktree *work sda.progress_arg = progress_arg; sda.repo = repo; sda.delete_local_mods = delete_local_mods; + sda.keep_on_disk = keep_on_disk; TAILQ_FOREACH(pe, paths, entry) { err = worktree_status(worktree, pe->path, fileindex, repo, blob - 551feb1fb11346676d2f161b062a605bde93e6d9 blob + 9ea8be8b1e091a6c1974b3a81b2f05a550bcd266 --- regress/cmdline/rm.sh +++ regress/cmdline/rm.sh @@ -241,9 +241,90 @@ function test_rm_directory { test_done "$testroot" "$ret" } + +function test_rm_directory_keep_files { + local testroot=`test_init rm_directory` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + (cd $testroot/wt && got rm . > $testroot/stdout 2> $testroot/stderr) + ret="$?" + echo "got: removing directories requires -R option" \ + > $testroot/stderr.expected + cmp -s $testroot/stderr.expected $testroot/stderr + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stderr.expected $testroot/stderr + test_done "$testroot" "$ret" + return 1 + fi + 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 && got rm -k -R . > $testroot/stdout) + + echo 'D alpha' > $testroot/stdout.expected + echo 'D beta' >> $testroot/stdout.expected + echo 'D epsilon/zeta' >> $testroot/stdout.expected + echo 'D gamma/delta' >> $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 && got st . > $testroot/stdout) + + echo 'D alpha' > $testroot/stdout.expected + echo 'D beta' >> $testroot/stdout.expected + echo 'D epsilon/zeta' >> $testroot/stdout.expected + echo 'D gamma/delta' >> $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 && got commit -m "keep" > /dev/null) + (cd $testroot/wt && got st . > $testroot/stdout) + + echo '? alpha' > $testroot/stdout.expected + echo '? beta' >> $testroot/stdout.expected + echo '? epsilon/zeta' >> $testroot/stdout.expected + echo '? gamma/delta' >> $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" +} + 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