commit 6d022e974716847d3f3c3bc97dac50e61663c49c from: Stefan Sperling date: Sun Aug 04 10:45:17 2019 UTC use get_worktree_paths_from_argv consistently; improves add/rm edge cases Double 'got rm' becomes a no-op like double 'got add' already is, and 'got add' of an already staged file is now an error. commit - bc26cce8342b78e413cf9bca0416e175ea53bcf3 commit + 6d022e974716847d3f3c3bc97dac50e61663c49c blob - e415b9e5813fa173afa815954653374df55cd29c blob + 0b09fb1668f2ec1610a7dcc8531b8b0d42862b1c --- got/got.c +++ got/got.c @@ -2945,7 +2945,7 @@ cmd_add(int argc, char *argv[]) char *cwd = NULL; struct got_pathlist_head paths; struct got_pathlist_entry *pe; - int ch, x; + int ch; TAILQ_INIT(&paths); @@ -2987,20 +2987,10 @@ cmd_add(int argc, char *argv[]) if (error) goto done; - for (x = 0; x < argc; x++) { - char *path = realpath(argv[x], NULL); - if (path == NULL) { - error = got_error_from_errno2("realpath", argv[x]); - goto done; - } + error = get_worktree_paths_from_argv(&paths, argc, argv, worktree); + if (error) + goto done; - got_path_strip_trailing_slashes(path); - error = got_pathlist_insert(&pe, &paths, path, NULL); - if (error) { - free(path); - goto done; - } - } error = got_worktree_schedule_add(worktree, &paths, print_status, NULL, repo); done: @@ -3031,7 +3021,7 @@ cmd_remove(int argc, char *argv[]) char *cwd = NULL; struct got_pathlist_head paths; struct got_pathlist_entry *pe; - int ch, i, delete_local_mods = 0; + int ch, delete_local_mods = 0; TAILQ_INIT(&paths); @@ -3075,20 +3065,10 @@ cmd_remove(int argc, char *argv[]) if (error) goto done; - for (i = 0; i < argc; i++) { - char *path = realpath(argv[i], NULL); - if (path == NULL) { - error = got_error_from_errno2("realpath", argv[i]); - goto done; - } + error = get_worktree_paths_from_argv(&paths, argc, argv, worktree); + if (error) + goto done; - got_path_strip_trailing_slashes(path); - error = got_pathlist_insert(&pe, &paths, path, NULL); - if (error) { - free(path); - goto done; - } - } error = got_worktree_schedule_delete(worktree, &paths, delete_local_mods, print_status, NULL, repo); if (error) @@ -3129,9 +3109,7 @@ cmd_revert(int argc, char *argv[]) struct got_repository *repo = NULL; char *cwd = NULL, *path = NULL; struct got_pathlist_head paths; - struct got_pathlist_entry *pe; - const char *worktree_path; - int ch, i; + int ch; TAILQ_INIT(&paths); @@ -3172,38 +3150,9 @@ cmd_revert(int argc, char *argv[]) if (error) goto done; - worktree_path = got_worktree_get_root_path(worktree); - for (i = 0; i < argc; i++) { - char *path = realpath(argv[i], NULL); - if (path == NULL) { - if (errno != ENOENT) { - error = got_error_from_errno2("realpath", - argv[i]); - goto done; - } - if (got_path_is_child(argv[i], worktree_path, - strlen(worktree_path))) { - path = strdup(argv[i]); - if (path == NULL) { - error = got_error_from_errno("strdup"); - goto done; - } - - } else if (asprintf(&path, "%s/%s", - got_worktree_get_root_path(worktree), - argv[i]) == -1) { - error = got_error_from_errno("asprintf"); - goto done; - } - } - - got_path_strip_trailing_slashes(path); - error = got_pathlist_insert(&pe, &paths, path, NULL); - if (error) { - free(path); - goto done; - } - } + error = get_worktree_paths_from_argv(&paths, argc, argv, worktree); + if (error) + goto done; error = got_worktree_revert(worktree, &paths, revert_progress, NULL, repo); @@ -5246,8 +5195,7 @@ cmd_stage(int argc, char *argv[]) char *cwd = NULL; struct got_pathlist_head paths; struct got_pathlist_entry *pe; - const char *worktree_path; - int ch, x, list_stage = 0; + int ch, list_stage = 0; TAILQ_INIT(&paths); @@ -5292,60 +5240,14 @@ cmd_stage(int argc, char *argv[]) if (error) goto done; - worktree_path = got_worktree_get_root_path(worktree); - for (x = 0; x < argc; x++) { - char *path; - if (list_stage) { - error = got_worktree_resolve_path(&path, worktree, - argv[x]); - if (error) - break; - } else - path = realpath(argv[x], NULL); - if (path == NULL) { - if (errno != ENOENT) { - error = got_error_from_errno2("realpath", - argv[x]); - goto done; - } - if (got_path_is_child(argv[x], worktree_path, - strlen(worktree_path))) { - path = strdup(argv[x]); - if (path == NULL) { - error = got_error_from_errno("strdup"); - goto done; - } + error = get_worktree_paths_from_argv(&paths, argc, argv, worktree); + if (error) + goto done; - } else if (asprintf(&path, "%s/%s", - got_worktree_get_root_path(worktree), - argv[x]) == -1) { - error = got_error_from_errno("asprintf"); - goto done; - } - } - - got_path_strip_trailing_slashes(path); - error = got_pathlist_insert(&pe, &paths, path, NULL); - if (error) { - free(path); - goto done; - } - } - - if (list_stage) { - if (TAILQ_EMPTY(&paths)) { - char *s = strdup(""); - if (s == NULL) { - error = got_error_from_errno("strdup"); - goto done; - } - error = got_pathlist_append(&paths, s, NULL); - if (error) - goto done; - } + if (list_stage) error = got_worktree_status(worktree, &paths, repo, print_stage, NULL, check_cancelled, NULL); - } else + else error = got_worktree_stage(worktree, &paths, print_status, NULL, repo); done: blob - 45b06f78f26cdbaf2982b43dafebbdf3da0c9d88 blob + b1367b449134be08b066f2617522e11293a0a05d --- lib/worktree.c +++ lib/worktree.c @@ -2498,10 +2498,19 @@ schedule_addition(const char *ondisk_path, struct got_ { const struct got_error *err = NULL; struct got_fileindex_entry *ie; + unsigned char status; + struct stat sb; - /* Re-adding an existing entry is a no-op. */ - if (got_fileindex_entry_get(fileindex, relpath, strlen(relpath))) - return NULL; + ie = got_fileindex_entry_get(fileindex, relpath, strlen(relpath)); + if (ie) { + err = get_file_status(&status, &sb, ie, ondisk_path, repo); + if (err) + return err; + /* Re-adding an existing entry is a no-op. */ + if (status == GOT_STATUS_ADD) + return NULL; + return got_error_path(relpath, GOT_ERR_FILE_STATUS); + } err = got_fileindex_entry_alloc(&ie, ondisk_path, relpath, NULL, NULL); if (err) @@ -2518,7 +2527,7 @@ schedule_addition(const char *ondisk_path, struct got_ const struct got_error * got_worktree_schedule_add(struct got_worktree *worktree, - struct got_pathlist_head *ondisk_paths, + struct got_pathlist_head *paths, got_worktree_status_cb status_cb, void *status_arg, struct got_repository *repo) { @@ -2535,15 +2544,14 @@ got_worktree_schedule_add(struct got_worktree *worktre if (err) goto done; - TAILQ_FOREACH(pe, ondisk_paths, entry) { - char *relpath; - err = got_path_skip_common_ancestor(&relpath, - got_worktree_get_root_path(worktree), pe->path); - if (err) - break; - err = schedule_addition(pe->path, fileindex, relpath, + TAILQ_FOREACH(pe, paths, entry) { + char *ondisk_path; + if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, + pe->path) == -1) + return got_error_from_errno("asprintf"); + err = schedule_addition(ondisk_path, fileindex, pe->path, status_cb, status_arg, repo); - free(relpath); + free(ondisk_path); if (err) break; } @@ -2604,7 +2612,7 @@ schedule_for_deletion(const char *ondisk_path, struct const struct got_error * got_worktree_schedule_delete(struct got_worktree *worktree, - struct got_pathlist_head *ondisk_paths, int delete_local_mods, + struct got_pathlist_head *paths, int delete_local_mods, got_worktree_status_cb status_cb, void *status_arg, struct got_repository *repo) { @@ -2621,15 +2629,14 @@ got_worktree_schedule_delete(struct got_worktree *work if (err) goto done; - TAILQ_FOREACH(pe, ondisk_paths, entry) { - char *relpath; - err = got_path_skip_common_ancestor(&relpath, - got_worktree_get_root_path(worktree), pe->path); - if (err) - break; - err = schedule_for_deletion(pe->path, fileindex, relpath, + TAILQ_FOREACH(pe, paths, entry) { + char *ondisk_path; + if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, + pe->path) == -1) + return got_error_from_errno("asprintf"); + err = schedule_for_deletion(ondisk_path, fileindex, pe->path, delete_local_mods, status_cb, status_arg, repo); - free(relpath); + free(ondisk_path); if (err) break; } @@ -2817,8 +2824,13 @@ got_worktree_revert(struct got_worktree *worktree, goto done; TAILQ_FOREACH(pe, ondisk_paths, entry) { - err = revert_file(worktree, fileindex, pe->path, + char *ondisk_path; + if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, + pe->path) == -1) + return got_error_from_errno("asprintf"); + err = revert_file(worktree, fileindex, ondisk_path, progress_cb, progress_arg, repo); + free(ondisk_path); if (err) break; } @@ -5188,28 +5200,26 @@ got_worktree_stage(struct got_worktree *worktree, /* Check out-of-dateness before staging anything. */ TAILQ_FOREACH(pe, paths, entry) { - char *relpath; - err = got_path_skip_common_ancestor(&relpath, - got_worktree_get_root_path(worktree), pe->path); - if (err) - goto done; - err = stage_check_out_of_date(relpath, pe->path, + char *ondisk_path; + if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, + pe->path) == -1) + return got_error_from_errno("asprintf"); + err = stage_check_out_of_date(pe->path, ondisk_path, head_commit_id, worktree, fileindex, repo); - free(relpath); + free(ondisk_path); if (err) goto done; } TAILQ_FOREACH(pe, paths, entry) { - char *relpath; - err = got_path_skip_common_ancestor(&relpath, - got_worktree_get_root_path(worktree), pe->path); - if (err) - break; - err = stage_path(relpath, pe->path, + char *ondisk_path; + if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, + pe->path) == -1) + return got_error_from_errno("asprintf"); + err = stage_path(pe->path, ondisk_path, (const char *)pe->data, worktree, fileindex, repo, status_cb, status_arg); - free(relpath); + free(ondisk_path); if (err) break; } blob - 727c09da472e4766f3af6666d38bfef4fa9d78d8 blob + 0634eee1bd0a59644a8f17047cc75df2160d3023 --- regress/cmdline/add.sh +++ regress/cmdline/add.sh @@ -84,9 +84,9 @@ function test_add_multiple { return 1 fi - echo "A bar" > $testroot/stdout.expected + echo "A foo" > $testroot/stdout.expected + echo "A bar" >> $testroot/stdout.expected echo "A baz" >> $testroot/stdout.expected - echo "A foo" >> $testroot/stdout.expected cmp -s $testroot/stdout.expected $testroot/stdout ret="$?" @@ -120,7 +120,39 @@ function test_add_file_in_new_subdir { test_done "$testroot" "$ret" } +function test_add_deleted { + local testroot=`test_init add_deleted` + + 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 beta > /dev/null) + + echo -n > $testroot/stdout.expected + (cd $testroot/wt && got add beta > $testroot/stdout 2> $testroot/stderr) + ret="$?" + if [ "$ret" == "0" ]; then + echo "got add command succeeded unexpectedly" >&2 + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "1" + return 1 + fi + + echo "got: beta: file has unexpected status" > $testroot/stderr.expected + cmp -s $testroot/stderr.expected $testroot/stderr + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stderr.expected $testroot/stderr + fi + test_done "$testroot" "$ret" +} + run_test test_add_basic run_test test_double_add run_test test_add_multiple run_test test_add_file_in_new_subdir +run_test test_add_deleted blob - 34059af1fb4817e58dffc51d50920a50a7eb7522 blob + 8d663c816fcc48fad3790aeacf9f73d6ef7ee8be --- regress/cmdline/rm.sh +++ regress/cmdline/rm.sh @@ -112,19 +112,23 @@ function test_double_rm { (cd $testroot/wt && got rm beta > /dev/null) for fflag in "" "-f"; do - (cd $testroot/wt && got rm $fflag beta 2> $testroot/stderr) + echo -n > $testroot/stderr.expected + (cd $testroot/wt && got rm $fflag beta > $testroot/stdout \ + 2> $testroot/stderr) ret="$?" - if [ "$ret" == "0" ]; then - echo "got rm command succeeded unexpectedly" >&2 - test_done "$testroot" 1 + if [ "$ret" != "0" ]; then + echo "got rm command failed unexpectedly" >&2 + diff -u $testroot/stderr.expected $testroot/stderr + test_done "$testroot" "$ret" + return 1 fi - - grep "No such file or directory" $testroot/stderr > \ - $testroot/stderr.actual + echo -n > $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout ret="$?" if [ "$ret" != "0" ]; then - cat $testroot/stderr + diff -u $testroot/stdout.expected $testroot/stdout test_done "$testroot" "$ret" + return 1 fi done test_done "$testroot" "0" blob - 01207ce40325703136910fb48633cdfb2d750cb2 blob + 90a497423ef20cb8d2de19b2a16864d9bf423d98 --- regress/cmdline/stage.sh +++ regress/cmdline/stage.sh @@ -325,33 +325,18 @@ function test_stage_add_already_staged_file { (cd $testroot/wt && got add foo > /dev/null) (cd $testroot/wt && got stage alpha beta foo > $testroot/stdout) - - (cd $testroot/wt && got add beta \ - > $testroot/stdout 2> $testroot/stderr) - ret="$?" - if [ "$ret" == "0" ]; then - echo "got add command succeeded unexpectedly" >&2 - test_done "$testroot" "1" - return 1 - fi - echo "got: realpath: beta: No such file or directory" \ - > $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 - for f in alpha foo; do + for f in alpha beta foo; do (cd $testroot/wt && got add $f \ > $testroot/stdout 2> $testroot/stderr) + echo "got: $f: file has unexpected status" \ + > $testroot/stderr.expected + cmp -s $testroot/stderr.expected $testroot/stderr ret="$?" if [ "$ret" != "0" ]; then - echo "got add command failed unexpectedly" >&2 - test_done "$testroot" "1" + diff -u $testroot/stderr.expected $testroot/stderr + test_done "$testroot" "$ret" return 1 fi cmp -s $testroot/stdout.expected $testroot/stdout @@ -396,13 +381,20 @@ function test_stage_rm_already_staged_file { (cd $testroot/wt && got rm beta \ > $testroot/stdout 2> $testroot/stderr) ret="$?" - if [ "$ret" == "0" ]; then - echo "got rm command succeeded unexpectedly" >&2 + if [ "$ret" != "0" ]; then + echo "got rm command failed unexpectedly" >&2 test_done "$testroot" "1" return 1 fi - echo "got: realpath: beta: No such file or directory" \ - > $testroot/stderr.expected + 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 + echo -n > $testroot/stderr.expected cmp -s $testroot/stderr.expected $testroot/stderr ret="$?" if [ "$ret" != "0" ]; then