Commit Diff


commit - 2b01eb6c2d76b941e4ba4c04450a6e18305c86c0
commit + 1dd5492090bfc3d9e553b4306a3cca1f03adaa71
blob - 73e05ddc0a8fead0d6cbcccb206f9ff3313248ea
blob + d99ceb078c138c3e79068d3b272080668b809c84
--- got/got.c
+++ got/got.c
@@ -35,12 +35,12 @@
 #include "got_object.h"
 #include "got_reference.h"
 #include "got_repository.h"
+#include "got_path.h"
 #include "got_worktree.h"
 #include "got_diff.h"
 #include "got_commit_graph.h"
 #include "got_blame.h"
 #include "got_privsep.h"
-#include "got_path.h"
 
 #ifndef nitems
 #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
@@ -1896,8 +1896,12 @@ cmd_add(int argc, char *argv[])
 	const struct got_error *error = NULL;
 	struct got_repository *repo = NULL;
 	struct got_worktree *worktree = NULL;
-	char *cwd = NULL, *path = NULL, *relpath = NULL;
+	char *cwd = NULL;
+	struct got_pathlist_head paths;
+	struct got_pathlist_entry *pe;
 	int ch, x;
+
+	TAILQ_INIT(&paths);
 
 	while ((ch = getopt(argc, argv, "")) != -1) {
 		switch (ch) {
@@ -1915,11 +1919,12 @@ cmd_add(int argc, char *argv[])
 
 	/* make sure each file exists before doing anything halfway */
 	for (x = 0; x < argc; x++) {
-		path = realpath(argv[x], NULL);
+		char *path = realpath(argv[x], NULL);
 		if (path == NULL) {
 			error = got_error_prefix_errno2("realpath", argv[x]);
 			goto done;
 		}
+		free(path);
 	}
 
 	cwd = getcwd(NULL, 0);
@@ -1942,30 +1947,29 @@ cmd_add(int argc, char *argv[])
 		goto done;
 
 	for (x = 0; x < argc; x++) {
-		path = realpath(argv[x], NULL);
+		char *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)
+		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:
 	if (repo)
 		got_repo_close(repo);
 	if (worktree)
 		got_worktree_close(worktree);
-	free(path);
-	free(relpath);
+	TAILQ_FOREACH(pe, &paths, entry)
+		free((char *)pe->path);
+	got_pathlist_free(&paths);
 	free(cwd);
 	return error;
 }
blob - 0261d1079837ceb9ddcff0869f8fce0735d7504b
blob + 3c54627d7d7a81f4bdda04d9700580311324fe9e
--- include/got_worktree.h
+++ include/got_worktree.h
@@ -138,9 +138,10 @@ const struct got_error *got_worktree_status(struct got
 const struct got_error *got_worktree_resolve_path(char **,
     struct got_worktree *, const char *);
 
-/* Schedule a file at an on-disk path for addition in the next commit. */
+/* Schedule files at on-disk paths for addition in the next commit. */
 const struct got_error *got_worktree_schedule_add(struct got_worktree *,
-    const char *, got_worktree_status_cb, void *, struct got_repository *);
+    struct got_pathlist_head *, got_worktree_status_cb, void *,
+    struct got_repository *);
 
 /*
  * Remove a file from disk and schedule it to be deleted in the next commit.
blob - 51cd9ab428652c5c6affa2a392e422b3f039339a
blob + bb149215b22b865bfb3a53e4acaa5b5083b9a841
--- lib/repository.c
+++ lib/repository.c
@@ -38,9 +38,9 @@
 #include "got_error.h"
 #include "got_reference.h"
 #include "got_repository.h"
+#include "got_path.h"
 #include "got_worktree.h"
 #include "got_object.h"
-#include "got_path.h"
 
 #include "got_lib_delta.h"
 #include "got_lib_inflate.h"
blob - 3ce4537de69fcf88a9f3b1085890a750e0cfafb2
blob + da771a2cb37e40dc3f8acea8b76c2e5079339067
--- lib/worktree.c
+++ lib/worktree.c
@@ -38,9 +38,9 @@
 #include "got_repository.h"
 #include "got_reference.h"
 #include "got_object.h"
+#include "got_path.h"
 #include "got_worktree.h"
 #include "got_opentemp.h"
-#include "got_path.h"
 
 #include "got_lib_worktree.h"
 #include "got_lib_sha1.h"
@@ -1818,24 +1818,20 @@ done:
 
 const struct got_error *
 got_worktree_schedule_add(struct got_worktree *worktree,
-    const char *ondisk_path, got_worktree_status_cb status_cb, void *status_arg,
+    struct got_pathlist_head *ondisk_paths,
+    got_worktree_status_cb status_cb, void *status_arg,
     struct got_repository *repo)
 {
 	struct got_fileindex *fileindex = NULL;
-	struct got_fileindex_entry *ie = NULL;
-	char *relpath, *fileindex_path = NULL, *new_fileindex_path = NULL;
+	char *fileindex_path = NULL, *new_fileindex_path = NULL;
 	FILE *index = NULL, *new_index = NULL;
 	const struct got_error *err = NULL, *unlockerr = NULL;
-	int ie_added = 0;
+	struct got_pathlist_entry *pe;
 
 	err = lock_worktree(worktree, LOCK_EX);
 	if (err)
 		return err;
 
-	err = got_path_skip_common_ancestor(&relpath,
-	    got_worktree_get_root_path(worktree), ondisk_path);
-	if (err)
-		goto done;
 
 	fileindex = got_fileindex_alloc();
 	if (fileindex == NULL) {
@@ -1860,20 +1856,37 @@ got_worktree_schedule_add(struct got_worktree *worktre
 	if (err)
 		goto done;
 
-	if (got_fileindex_entry_get(fileindex, relpath) != NULL) {
-		err = got_error_set_errno(EEXIST, relpath);
-		goto done;
-	}
+	TAILQ_FOREACH(pe, ondisk_paths, entry) {
+		struct got_fileindex_entry *ie = NULL;
+		char *relpath;
 
-	err = got_fileindex_entry_alloc(&ie, ondisk_path, relpath, NULL, NULL);
-	if (err)
-		goto done;
+		err = got_path_skip_common_ancestor(&relpath,
+		    got_worktree_get_root_path(worktree), pe->path);
+		if (err)
+			goto done;
 
-	err = got_fileindex_entry_add(fileindex, ie);
-	if (err)
-		goto done;
-	ie_added = 1; /* now owned by fileindex; don't free separately */
+		/* Re-adding an existing entry is a no-op. */
+		if (got_fileindex_entry_get(fileindex, relpath) != NULL)
+			continue;
+
+		err = got_fileindex_entry_alloc(&ie, pe->path, relpath,
+		    NULL, NULL);
+		free(relpath);
+		if (err)
+			goto done;
+
+		err = got_fileindex_entry_add(fileindex, ie);
+		if (err) {
+			got_fileindex_entry_free(ie);
+			goto done;
+		}
 
+		err = report_file_status(ie, pe->path, status_cb, status_arg,
+		    repo);
+		if (err)
+			goto done;
+	}
+
 	err = got_opentemp_named(&new_fileindex_path, &new_index,
 	    fileindex_path);
 	if (err)
@@ -1892,7 +1905,6 @@ got_worktree_schedule_add(struct got_worktree *worktre
 	free(new_fileindex_path);
 	new_fileindex_path = NULL;
 
-	err = report_file_status(ie, ondisk_path, status_cb, status_arg, repo);
 done:
 	if (index) {
 		if (fclose(index) != 0 && err == NULL)
@@ -1904,14 +1916,11 @@ done:
 			    new_fileindex_path);
 		free(new_fileindex_path);
 	}
-	if (ie && !ie_added)
-		got_fileindex_entry_free(ie);
 	if (fileindex)
 		got_fileindex_free(fileindex);
 	unlockerr = lock_worktree(worktree, LOCK_SH);
 	if (unlockerr && err == NULL)
 		err = unlockerr;
-	free(relpath);
 	return err;
 }
 
blob - 54bb129e75442480e7dd497a09270cae4611f0e5
blob + df3b5beb37efbdff4ef25f786d68a5b0f0f2663a
--- regress/worktree/worktree_test.c
+++ regress/worktree/worktree_test.c
@@ -34,10 +34,10 @@
 #include "got_object.h"
 #include "got_reference.h"
 #include "got_repository.h"
+#include "got_path.h"
 #include "got_worktree.h"
 #include "got_opentemp.h"
 #include "got_privsep.h"
-#include "got_path.h"
 
 #include "got_lib_worktree.h"
 
blob - 3f82dba73037dd8d4fb3bccffbf2831304355d75
blob + c3da2f33949c3eb4e55a511d97ffeb286484f524
--- tog/tog.c
+++ tog/tog.c
@@ -47,6 +47,7 @@
 #include "got_utf8.h"
 #include "got_blame.h"
 #include "got_privsep.h"
+#include "got_path.h"
 #include "got_worktree.h"
 
 #ifndef MIN