commit - 25a102ed18cbd4e83888ece62f235f98117e0425
commit + f8836425010d0756365e9d64f63e3dfb517b1c6b
blob - bbeefdbe310df9fd0d9081fee286a6a2755f8201
blob + b7547794d998714acf55500591e26289b431c87e
--- lib/worktree.c
+++ lib/worktree.c
free(next_parent_path);
return err;
}
+
+struct find_missing_children_args {
+ const char *parent_path;
+ size_t parent_len;
+ struct got_pathlist_head *children;
+ got_cancel_cb cancel_cb;
+ void *cancel_arg;
+};
+
static const struct got_error *
+find_missing_children(void *arg, struct got_fileindex_entry *ie)
+{
+ const struct got_error *err = NULL;
+ struct find_missing_children_args *a = arg;
+
+ if (a->cancel_cb) {
+ err = a->cancel_cb(a->cancel_arg);
+ if (err)
+ return err;
+ }
+
+ if (got_path_is_child(ie->path, a->parent_path, a->parent_len))
+ err = got_pathlist_append(a->children, ie->path, NULL);
+
+ return err;
+}
+
+static const struct got_error *
+report_children(struct got_pathlist_head *children,
+ struct got_worktree *worktree, struct got_fileindex *fileindex,
+ struct got_repository *repo, int is_root_dir, int report_unchanged,
+ struct got_pathlist_head *ignores, int no_ignores,
+ got_worktree_status_cb status_cb, void *status_arg,
+ got_cancel_cb cancel_cb, void *cancel_arg)
+{
+ const struct got_error *err = NULL;
+ struct got_pathlist_entry *pe;
+ char *ondisk_path = NULL;
+
+ TAILQ_FOREACH(pe, children, entry) {
+ if (cancel_cb) {
+ err = cancel_cb(cancel_arg);
+ if (err)
+ break;
+ }
+
+ if (asprintf(&ondisk_path, "%s%s%s", worktree->root_path,
+ !is_root_dir ? "/" : "", pe->path) == -1) {
+ err = got_error_from_errno("asprintf");
+ ondisk_path = NULL;
+ break;
+ }
+
+ err = report_single_file_status(pe->path, ondisk_path,
+ fileindex, status_cb, status_arg, repo, report_unchanged,
+ ignores, no_ignores);
+ if (err)
+ break;
+
+ free(ondisk_path);
+ ondisk_path = NULL;
+ }
+
+ free(ondisk_path);
+ return err;
+}
+
+static const struct got_error *
worktree_status(struct got_worktree *worktree, const char *path,
struct got_fileindex *fileindex, struct got_repository *repo,
got_worktree_status_cb status_cb, void *status_arg,
struct got_fileindex_diff_dir_cb fdiff_cb;
struct diff_dir_cb_arg arg;
char *ondisk_path = NULL;
- struct got_pathlist_head ignores;
+ struct got_pathlist_head ignores, missing_children;
struct got_fileindex_entry *ie;
TAILQ_INIT(&ignores);
+ TAILQ_INIT(&missing_children);
if (asprintf(&ondisk_path, "%s%s%s",
worktree->root_path, path[0] ? "/" : "", path) == -1)
fileindex, status_cb, status_arg, repo,
report_unchanged, &ignores, no_ignores);
goto done;
+ } else {
+ struct find_missing_children_args fmca;
+ fmca.parent_path = path;
+ fmca.parent_len = strlen(path);
+ fmca.children = &missing_children;
+ fmca.cancel_cb = cancel_cb;
+ fmca.cancel_arg = cancel_arg;
+ err = got_fileindex_for_each_entry_safe(fileindex,
+ find_missing_children, &fmca);
+ if (err)
+ goto done;
}
fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
if (err)
goto done;
}
- err = report_single_file_status(path, ondisk_path,
- fileindex, status_cb, status_arg, repo,
- report_unchanged, &ignores, no_ignores);
+ if (TAILQ_EMPTY(&missing_children)) {
+ err = report_single_file_status(path,
+ ondisk_path, fileindex,
+ status_cb, status_arg, repo,
+ report_unchanged, &ignores, no_ignores);
+ if (err)
+ goto done;
+ } else {
+ err = report_children(&missing_children,
+ worktree, fileindex, repo,
+ (path[0] == '\0'), report_unchanged,
+ &ignores, no_ignores,
+ status_cb, status_arg,
+ cancel_cb, cancel_arg);
+ }
}
} else {
fdiff_cb.diff_old_new = status_old_new;
blob - 3ae6b968f8817e9efb7b1abb879557fe19622e08
blob + dcea98961cf673717907f69c3761b59218c16e1a
--- regress/cmdline/revert.sh
+++ regress/cmdline/revert.sh
echo "new untracked file" > $testroot/content.expected
cat $testroot/wt/epsilon/new_file > $testroot/content
+
+ cmp -s $testroot/content.expected $testroot/content
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/content.expected $testroot/content
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "zeta" > $testroot/content.expected
+ cat $testroot/wt/epsilon/zeta > $testroot/content
cmp -s $testroot/content.expected $testroot/content
ret=$?
if [ $ret -ne 0 ]; then
diff -u $testroot/content.expected $testroot/content
+ fi
+
+ test_done "$testroot" "$ret"
+}
+
+test_revert_missing_directory() {
+ local testroot=`test_init revert_missing_directory`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
test_done "$testroot" "$ret"
return 1
fi
+ rm -r $testroot/wt/epsilon
+
+ (cd $testroot/wt && got revert -R epsilon > $testroot/stdout)
+
+ echo 'R epsilon/zeta' >> $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
echo "zeta" > $testroot/content.expected
cat $testroot/wt/epsilon/zeta > $testroot/content
run_test test_revert_no_arguments
run_test test_revert_directory
run_test test_revert_directory_unknown
+run_test test_revert_missing_directory
run_test test_revert_patch
run_test test_revert_patch_added
run_test test_revert_patch_removed
blob - b48ce4011c7e953f442dffb07e92ceeb2fc2a62b
blob + 6d656a615120185ccc425dcf94d85399757b7de5
--- regress/cmdline/rm.sh
+++ regress/cmdline/rm.sh
return 1
fi
- echo "got: epsilon: No such file or directory" \
+ echo "got: epsilon/zeta: No such file or directory" \
> $testroot/stderr.expected
cmp -s $testroot/stderr.expected $testroot/stderr
ret=$?
return 1
fi
- echo -n '' > $testroot/stdout.expected
+ echo 'D epsilon/zeta' > $testroot/stdout.expected
cmp -s $testroot/stdout.expected $testroot/stdout
ret=$?
if [ $ret -ne 0 ]; then