Commit Diff


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