From: Stefan Sperling Subject: make 'got add' robert-compatible To: gameoftrees@openbsd.org Date: Tue, 6 Jul 2021 17:08:05 +0200 Require the -I option to add ignored files to version control even when 'got add' is not recursing into directories with -R. Inspired by robert@ accidentally committing a ./iridium.core file to the CVS ports tree in spite of "*.core" being on cvs's default ignore list. ok? By the way, Got relies on .cvsignore and .gitignore files only at present. We might want to add a hard-coded default ignore list in a separate patch, and put patterns like "*.core" on this list. diff aea75d87862c3ab54d0b8c5e5e280e13efe8ec4a /home/stsp/src/got blob - cc9598e29205c3fe87df2026697edbe3a56b8e01 file + got/got.1 --- got/got.1 +++ got/got.1 @@ -1125,6 +1125,9 @@ another repository. .It Cm add Oo Fl R Oc Oo Fl I Oc Ar path ... Schedule unversioned files in a work tree for addition to the repository in the next commit. +By default, files which match a +.Cm got status +ignore pattern will not be added. .Pp The options for .Cm got add @@ -1138,7 +1141,7 @@ will refuse to run if a specified .Ar path is a directory. .It Fl I -With -R, add files even if they match a +Add files even if they match a .Cm got status ignore pattern. .El blob - edd395ed589265482e441455dfb7bdf7047df17a file + got/got.c --- got/got.c +++ got/got.c @@ -6494,13 +6494,6 @@ cmd_add(int argc, char *argv[]) if (error) goto done; - if (!can_recurse && no_ignores) { - error = got_error_msg(GOT_ERR_BAD_PATH, - "disregarding ignores requires -R option"); - goto done; - - } - if (!can_recurse) { char *ondisk_path; struct stat sb; blob - 515ea2335fcce5c7e77172985fe6dc270ac9cf10 file + lib/worktree.c --- lib/worktree.c +++ lib/worktree.c @@ -3269,7 +3269,7 @@ struct diff_dir_cb_arg { got_cancel_cb cancel_cb; void *cancel_arg; /* A pathlist containing per-directory pathlists of ignore patterns. */ - struct got_pathlist_head ignores; + struct got_pathlist_head *ignores; int report_unchanged; int no_ignores; }; @@ -3573,7 +3573,7 @@ status_new(void *arg, struct dirent *de, const char *p if (de->d_type != DT_DIR && got_path_is_child(path, a->status_path, a->status_path_len) - && !match_ignores(&a->ignores, path)) + && !match_ignores(a->ignores, path)) err = (*a->status_cb)(a->status_arg, GOT_STATUS_UNVERSIONED, GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL); if (parent_path[0]) @@ -3590,12 +3590,12 @@ status_traverse(void *arg, const char *path, int dirfd if (a->no_ignores) return NULL; - err = add_ignores(&a->ignores, a->worktree->root_path, + err = add_ignores(a->ignores, a->worktree->root_path, path, dirfd, ".cvsignore"); if (err) return err; - err = add_ignores(&a->ignores, a->worktree->root_path, path, + err = add_ignores(a->ignores, a->worktree->root_path, path, dirfd, ".gitignore"); return err; @@ -3603,12 +3603,16 @@ status_traverse(void *arg, const char *path, int dirfd static const struct got_error * report_single_file_status(const char *path, const char *ondisk_path, -struct got_fileindex *fileindex, got_worktree_status_cb status_cb, -void *status_arg, struct got_repository *repo, int report_unchanged) + struct got_fileindex *fileindex, got_worktree_status_cb status_cb, + void *status_arg, struct got_repository *repo, int report_unchanged, + struct got_pathlist_head *ignores) { struct got_fileindex_entry *ie; struct stat sb; + if (match_ignores(ignores, path)) + return NULL; + ie = got_fileindex_entry_get(fileindex, path, strlen(path)); if (ie) return report_file_status(ie, ondisk_path, -1, NULL, @@ -3667,6 +3671,8 @@ add_ignores_from_parent_paths(struct got_pathlist_head err = NULL; /* traversed everything */ break; } + if (got_path_is_root_dir(parent_path)) + break; free(parent_path); parent_path = next_parent_path; next_parent_path = NULL; @@ -3689,8 +3695,9 @@ worktree_status(struct got_worktree *worktree, const c struct got_fileindex_diff_dir_cb fdiff_cb; struct diff_dir_cb_arg arg; char *ondisk_path = NULL; + struct got_pathlist_head ignores; - TAILQ_INIT(&arg.ignores); + TAILQ_INIT(&ignores); if (asprintf(&ondisk_path, "%s%s%s", worktree->root_path, path[0] ? "/" : "", path) == -1) @@ -3701,10 +3708,17 @@ worktree_status(struct got_worktree *worktree, const c if (errno != ENOTDIR && errno != ENOENT && errno != EACCES && errno != ELOOP) err = got_error_from_errno2("open", ondisk_path); - else + else { + if (!no_ignores) { + err = add_ignores_from_parent_paths(&ignores, + worktree->root_path, ondisk_path); + if (err) + goto done; + } err = report_single_file_status(path, ondisk_path, fileindex, status_cb, status_arg, repo, - report_unchanged); + report_unchanged, &ignores); + } } else { fdiff_cb.diff_old_new = status_old_new; fdiff_cb.diff_old = status_old; @@ -3722,16 +3736,17 @@ worktree_status(struct got_worktree *worktree, const c arg.report_unchanged = report_unchanged; arg.no_ignores = no_ignores; if (!no_ignores) { - err = add_ignores_from_parent_paths(&arg.ignores, + err = add_ignores_from_parent_paths(&ignores, worktree->root_path, path); if (err) goto done; } + arg.ignores = &ignores; err = got_fileindex_diff_dir(fileindex, fd, worktree->root_path, path, repo, &fdiff_cb, &arg); } done: - free_ignores(&arg.ignores); + free_ignores(&ignores); if (fd != -1 && close(fd) == -1 && err == NULL) err = got_error_from_errno("close"); free(ondisk_path); blob - a7fa11961629003f3de704711ae064f29cfb087b file + regress/cmdline/add.sh --- regress/cmdline/add.sh +++ regress/cmdline/add.sh @@ -181,7 +181,7 @@ test_add_directory() { (cd $testroot/wt && got add -I . > $testroot/stdout 2> $testroot/stderr) ret="$?" - echo "got: disregarding ignores requires -R option" \ + echo "got: adding directories requires -R option" \ > $testroot/stderr.expected cmp -s $testroot/stderr.expected $testroot/stderr ret="$?" @@ -237,6 +237,18 @@ test_add_directory() { (cd $testroot/wt && got add tree2/foo > $testroot/stdout) + 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 + + (cd $testroot/wt && got add -I tree2/foo > $testroot/stdout) + echo 'A tree2/foo' > $testroot/stdout.expected cmp -s $testroot/stdout.expected $testroot/stdout