commit - efaf56b722e9595f43c4177384f7e54c88fbc285
commit + 90285c3b5b24fe56d9ea77e33199bcd395595b95
blob - a0db6ed9feeabdacaad31a547840dd969d114d4a
blob + 59cca6fff1cd992952d074f19528f0b9831465d0
--- got/Makefile
+++ got/Makefile
PROG= got
SRCS= got.c blame.c commit_graph.c delta.c diff.c diffoffset.c \
diffreg.c error.c fileindex.c object.c object_cache.c \
- object_idset.c object_parse.c opentemp.c path.c pack.c \
- privsep.c reference.c repository.c sha1.c worktree.c inflate.c
+ object_idset.c object_parse.c opentemp.c path.c pathset.c \
+ pack.c privsep.c reference.c repository.c sha1.c worktree.c \
+ inflate.c
CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib \
-DGOT_LIBEXECDIR=${GOT_LIBEXECDIR}
blob - e43e15f1fb069fc763545860dc8cdbbdb516522a
blob + a728112ef99a5c737f7c452c927196b2e2bc58e0
--- lib/worktree.c
+++ lib/worktree.c
#include "got_lib_worktree.h"
#include "got_lib_path.h"
+#include "got_lib_pathset.h"
#include "got_lib_sha1.h"
#include "got_lib_fileindex.h"
#include "got_lib_inflate.h"
struct collect_missing_entry_args {
struct got_fileindex *fileindex;
const struct got_tree_entries *entries;
- struct got_fileindex missing_entries;
+ struct got_pathset *missing_entries;
const char *current_subdir;
};
static const struct got_error *
collect_missing_file(void *args, struct got_fileindex_entry *entry)
{
+ const struct got_error *err = NULL;
struct collect_missing_entry_args *a = args;
char *start, *end;
ptrdiff_t len;
return NULL;
got_fileindex_entry_remove(a->fileindex, entry);
- return got_fileindex_entry_add(&a->missing_entries, entry);
+ err = got_pathset_add(a->missing_entries, entry->path, NULL);
+ got_fileindex_entry_free(entry);
+ return err;
+}
+
+struct remove_missing_file_args {
+ const char *root_path;
+ got_worktree_checkout_cb progress_cb;
+ void *progress_arg;
+ got_worktree_cancel_cb cancel_cb;
+ void *cancel_arg;
+};
+
+static const struct got_error *
+remove_missing_file(const char *path, void *data, void *arg)
+{
+ const struct got_error *err = NULL;
+ char *ondisk_path = NULL;
+ struct remove_missing_file_args *a = arg;
+
+ if (a->cancel_cb) {
+ err = (*a->cancel_cb)(a->cancel_arg);
+ if (err)
+ return err;
+ }
+
+ (*a->progress_cb)(a->progress_arg, GOT_STATUS_DELETE, path);
+
+ if (asprintf(&ondisk_path, "%s/%s", a->root_path, path) == -1)
+ return got_error_from_errno();
+
+ if (unlink(ondisk_path) == -1)
+ err = got_error_from_errno();
+ else {
+ char *parent = dirname(ondisk_path);
+ while (parent && strcmp(parent, a->root_path) != 0) {
+ if (rmdir(parent) == -1 && errno != ENOTEMPTY) {
+ err = got_error_from_errno();
+ break;
+ }
+ parent = dirname(parent);
+ }
+ }
+ free(ondisk_path);
+ return err;
}
/* Remove files which exist in the file index but not in the tree. */
{
const struct got_error *err = NULL;
struct collect_missing_entry_args a;
- struct got_fileindex_entry *entry, *tmp;
+ struct remove_missing_file_args a2;
a.fileindex = fileindex;
a.entries = entries;
- a.missing_entries.nentries = 0;
+ a.missing_entries = got_pathset_alloc();
+ if (a.missing_entries == NULL)
+ return got_error_from_errno();
a.current_subdir = apply_path_prefix(worktree, path);
- TAILQ_INIT(&a.missing_entries.entries);
err = got_fileindex_for_each_entry_safe(fileindex,
collect_missing_file, &a);
if (err)
return err;
- TAILQ_FOREACH_SAFE(entry, &a.missing_entries.entries, entry, tmp) {
- char *ondisk_path = NULL;
+ a2.root_path = worktree->root_path;
+ a2.cancel_cb = cancel_cb;
+ a2.cancel_arg = cancel_arg;
+ a2.progress_cb = progress_cb;
+ a2.progress_arg = progress_arg;
- if (cancel_cb) {
- err = (*cancel_cb)(cancel_arg);
- if (err)
- break;
- }
-
- (*progress_cb)(progress_arg, GOT_STATUS_DELETE, entry->path);
-
- if (asprintf(&ondisk_path, "%s/%s", worktree->root_path,
- entry->path) == -1) {
- err = got_error_from_errno();
- break;
- }
-
- if (unlink(ondisk_path) == -1)
- err = got_error_from_errno();
- else {
- char *parent = dirname(ondisk_path);
- if (rmdir(parent) == -1 && errno != ENOTEMPTY)
- err = got_error_from_errno();
- }
- free(ondisk_path);
- if (err)
- break;
-
- TAILQ_REMOVE(&a.missing_entries.entries, entry, entry);
- got_fileindex_entry_free(entry);
- }
-
- if (err) {
- while (!TAILQ_EMPTY(&a.missing_entries.entries)) {
- entry = TAILQ_FIRST(&a.missing_entries.entries);
- TAILQ_REMOVE(&a.missing_entries.entries, entry, entry);
- got_fileindex_entry_free(entry);
- }
- }
-
+ err = got_pathset_for_each(a.missing_entries, remove_missing_file, &a2);
+ got_pathset_free(a.missing_entries);
return err;
}
blob - 5c505f1af4c5dc561754cca6e9a7158054f939d5
blob + eb351e57fada625d5e0502ffd0f5e3a0b7065c4b
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
test_done "$testroot" "0"
}
+function test_update_deletes_dir_recursively {
+ local testroot=`test_init update_deletes_dir_recursively`
+ local first_rev=`git_show_head $testroot/repo`
+
+ mkdir $testroot/repo/epsilon/psi
+ echo mu > $testroot/repo/epsilon/psi/mu
+ mkdir $testroot/repo/epsilon/psi/chi
+ echo tau > $testroot/repo/epsilon/psi/chi/tau
+ (cd $testroot/repo && git add .)
+ git_commit $testroot/repo -m "adding a sub-directory beneath epsilon"
+
+ # check out the epsilon/ sub-tree
+ got checkout -p epsilon $testroot/repo $testroot/wt > /dev/null
+ if [ "$?" != "0" ]; then
+ test_done "$testroot" "$?"
+ return 1
+ fi
+
+ # update back to first commit and expect psi/mu to be deleted
+ echo "D psi/chi/tau" > $testroot/stdout.expected
+ echo "D psi/mu" >> $testroot/stdout.expected
+ echo "Updated to commit $first_rev" >> $testroot/stdout.expected
+
+ (cd $testroot/wt && got update -c $first_rev > $testroot/stdout)
+
+ cmp $testroot/stdout.expected $testroot/stdout
+ if [ "$?" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$?"
+ return 1
+ fi
+
+ if [ -e $testroot/wt/psi ]; then
+ echo "removed dir psi still exists on disk" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ test_done "$testroot" "0"
+}
+
run_test test_update_basic
run_test test_update_adds_file
run_test test_update_deletes_file
run_test test_update_deletes_dir
run_test test_update_deletes_dir_with_path_prefix
+run_test test_update_deletes_dir_recursively
blob - 622918d65a3235175fbd16aaffcc60725d7d93cc
blob + 7046be709f854cb231dae101e6b5e9fe1670cc55
--- regress/idset/Makefile
+++ regress/idset/Makefile
.PATH:${.CURDIR}/../../lib
PROG = idset_test
-SRCS = error.c object.c privsep.c sha1.c pack.c inflate.c path.c opentemp.c \
- delta.c repository.c reference.c worktree.c fileindex.c object_cache.c \
- object_idset.c object_parse.c idset_test.c
+SRCS = error.c object.c privsep.c sha1.c pack.c inflate.c path.c pathset.c \
+ opentemp.c delta.c repository.c reference.c worktree.c fileindex.c \
+ object_cache.c object_idset.c object_parse.c idset_test.c
CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib
LDADD = -lutil -lz
blob - 5da0a61342d57368a2ad4a97cf0cfcacf13e6028
blob + 7eba96e9e3b3cf49fc84691bde7194b8a506ac39
--- regress/repository/Makefile
+++ regress/repository/Makefile
SRCS = path.c repository.c error.c reference.c object.c object_cache.c \
object_idset.c object_parse.c opentemp.c sha1.c diff.c diffreg.c \
pack.c privsep.c delta.c fileindex.c worktree.c inflate.c \
- repository_test.c
+ pathset.c repository_test.c
CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib \
-DGOT_LIBEXECDIR=${GOT_LIBEXECDIR}
blob - 967be5ea5fc6fb725eea04040ce5afa44a56ca59
blob + c7e2786beead1950de2cd83f434b064dc3366aa0
--- regress/worktree/Makefile
+++ regress/worktree/Makefile
PROG = worktree_test
SRCS = worktree.c repository.c object.c object_cache.c object_idset.c \
- object_parse.c opentemp.c path.c error.c reference.c sha1.c \
+ object_parse.c opentemp.c path.c pathset.c error.c reference.c sha1.c \
pack.c privsep.c delta.c inflate.c fileindex.c worktree_test.c
CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib \
blob - 72f8d6d7e4c381ebb68b1e052998d0843ff100aa
blob + fb527723e3ad29a2d4e54676089954a3376cfaa1
--- tog/Makefile
+++ tog/Makefile
PROG= tog
SRCS= tog.c blame.c commit_graph.c delta.c diff.c diffoffset.c \
diffreg.c error.c fileindex.c object.c object_cache.c \
- object_idset.c object_parse.c opentemp.c path.c pack.c \
- privsep.c reference.c repository.c sha1.c worktree.c \
+ object_idset.c object_parse.c opentemp.c path.c pathset.c \
+ pack.c privsep.c reference.c repository.c sha1.c worktree.c \
utf8.c inflate.c
CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib \