Commit 723c305ce4ed16a470bbf2ced142668b5a633f03

joshua stein 2019-05-11T15:53:37

got: support adding multiple files at a time make adding files already in the file-index not a fatal error

diff --git a/TODO b/TODO
index 0b1f820..cc9cceb 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,6 @@
 lib:
 - handle checkout of trees which contain submodules by identifying and
   ignoring such tree entries; requires a .ini config parser (from isakmpd?)
-- allow adding multiple paths at once for 'got add'
 - allow removing multiple paths at once for 'got rm'
 - recursive addition: got add -R
 - recursive removal: got rm -R
diff --git a/got/got.c b/got/got.c
index 41b8e41..679e74f 100644
--- a/got/got.c
+++ b/got/got.c
@@ -1897,7 +1897,7 @@ cmd_add(int argc, char *argv[])
 	struct got_repository *repo = NULL;
 	struct got_worktree *worktree = NULL;
 	char *cwd = NULL, *path = NULL, *relpath = NULL;
-	int ch;
+	int ch, x;
 
 	while ((ch = getopt(argc, argv, "")) != -1) {
 		switch (ch) {
@@ -1910,21 +1910,24 @@ cmd_add(int argc, char *argv[])
 	argc -= optind;
 	argv += optind;
 
-	if (argc != 1)
+	if (argc < 1)
 		usage_add();
 
-	path = realpath(argv[0], NULL);
-	if (path == NULL) {
-		error = got_error_prefix_errno2("realpath", argv[0]);
-		goto done;
+	/* make sure each file exists before doing anything halfway */
+	for (x = 0; x < argc; x++) {
+		path = realpath(argv[x], NULL);
+		if (path == NULL) {
+			error = got_error_prefix_errno2("realpath", argv[x]);
+			goto done;
+		}
 	}
-	got_path_strip_trailing_slashes(path);
 
 	cwd = getcwd(NULL, 0);
 	if (cwd == NULL) {
 		error = got_error_prefix_errno("getcwd");
 		goto done;
 	}
+
 	error = got_worktree_open(&worktree, cwd);
 	if (error)
 		goto done;
@@ -1938,10 +1941,24 @@ cmd_add(int argc, char *argv[])
 	if (error)
 		goto done;
 
-	error = got_worktree_schedule_add(worktree, path, print_status, NULL,
-	    repo);
-	if (error)
-		goto done;
+	for (x = 0; x < argc; x++) {
+		path = realpath(argv[x], NULL);
+		if (path == NULL) {
+			error = got_error_prefix_errno2("realpath", argv[x]);
+			goto done;
+		}
+
+		got_path_strip_trailing_slashes(path);
+
+		error = got_worktree_schedule_add(worktree, path, print_status,
+		    NULL, repo);
+		if (errno == EEXIST) {
+			error = NULL;
+			continue;
+		}
+		else if (error)
+			goto done;
+	}
 done:
 	if (repo)
 		got_repo_close(repo);
diff --git a/regress/cmdline/add.sh b/regress/cmdline/add.sh
index 07907d1..eba7073 100755
--- a/regress/cmdline/add.sh
+++ b/regress/cmdline/add.sh
@@ -52,20 +52,39 @@ function test_double_add {
 	echo "new file" > $testroot/wt/foo
 	(cd $testroot/wt && got add foo > /dev/null)
 
-	echo "got: File exists" > $testroot/stderr.expected
-	(cd $testroot/wt && got add foo 2> $testroot/stderr)
+	(cd $testroot/wt && got add foo)
 	ret="$?"
-	if [ "$ret" == "0" ]; then
-		echo "got add command succeeded unexpectedly" >&2
+	if [ "$ret" != "0" ]; then
+		echo "got add failed unexpectedly" >&2
 		test_done "$testroot" 1
 		return 1
 	fi
 
-	cmp $testroot/stderr.expected $testroot/stderr
+	test_done "$testroot" "$ret"
+}
+
+function test_add_multiple {
+	local testroot=`test_init multiple_add`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
 	ret="$?"
 	if [ "$ret" != "0" ]; then
-		diff -u $testroot/stderr.expected $testroot/stderr
+		test_done "$testroot" "$ret"
+		return 1
 	fi
+
+	echo "new file" > $testroot/wt/foo
+	echo "new file" > $testroot/wt/bar
+	echo "new file" > $testroot/wt/baz
+	(cd $testroot/wt && got add foo bar baz)
+
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		echo "got add failed unexpectedly" >&2
+		test_done "$testroot" 1
+		return 1
+	fi
+
 	test_done "$testroot" "$ret"
 }