commit 1dd5492090bfc3d9e553b4306a3cca1f03adaa71 from: Stefan Sperling date: Sat May 11 22:50:57 2019 UTC open the file index just once when adding multiple files 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