commit - 46cee7a3e76f2e44d2e0c5919de76d228b9c79af
commit + 4a1ddfc2ae992bd73e34ce89b7f309df643aeba5
blob - 45ace73306c72d723185ef208bb2d4b51fd09546
blob + f51b680fd50600a7dde8e98ca7bb6f718b81089c
--- lib/worktree.c
+++ lib/worktree.c
}
static const struct got_error *
+add_dir_on_disk(struct got_worktree *worktree, const char *path)
+{
+ const struct got_error *err = NULL;
+ char *abspath;
+
+ if (asprintf(&abspath, "%s/%s", worktree->root_path, path) == -1)
+ return got_error_from_errno();
+
+ /* XXX queue work rather than editing disk directly? */
+ if (mkdir(abspath, GOT_DEFAULT_DIR_MODE) == -1) {
+ struct stat sb;
+
+ if (errno != EEXIST) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
+ if (lstat(abspath, &sb) == -1) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
+ if (!S_ISDIR(sb.st_mode)) {
+ /* TODO directory is obstructed; do something */
+ return got_error(GOT_ERR_FILE_OBSTRUCTED);
+ }
+ }
+
+done:
+ free(abspath);
+ return err;
+}
+
+static const struct got_error *
install_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
struct got_fileindex_entry *entry, const char *path,
struct got_blob_object *blob,
fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
GOT_DEFAULT_FILE_MODE);
if (fd == -1) {
- if (errno == EEXIST) {
+ if (errno == ENOENT) {
+ char *parent = dirname(path);
+ if (parent == NULL)
+ return got_error_from_errno();
+ err = add_dir_on_disk(worktree, parent);
+ if (err)
+ return err;
+ fd = open(ondisk_path,
+ O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
+ GOT_DEFAULT_FILE_MODE);
+ if (fd == -1)
+ return got_error_from_errno();
+ } else if (errno == EEXIST) {
struct stat sb;
if (lstat(ondisk_path, &sb) == -1) {
err = got_error_from_errno();
close(fd);
free(ondisk_path);
free(tmppath);
- return err;
-}
-
-static const struct got_error *
-add_dir_on_disk(struct got_worktree *worktree, const char *path)
-{
- const struct got_error *err = NULL;
- char *abspath;
-
- if (asprintf(&abspath, "%s/%s", worktree->root_path, path) == -1)
- return got_error_from_errno();
-
- /* XXX queue work rather than editing disk directly? */
- if (mkdir(abspath, GOT_DEFAULT_DIR_MODE) == -1) {
- struct stat sb;
-
- if (errno != EEXIST) {
- err = got_error_from_errno();
- goto done;
- }
-
- if (lstat(abspath, &sb) == -1) {
- err = got_error_from_errno();
- goto done;
- }
-
- if (!S_ISDIR(sb.st_mode)) {
- /* TODO directory is obstructed; do something */
- return got_error(GOT_ERR_FILE_OBSTRUCTED);
- }
- }
-
-done:
- free(abspath);
return err;
}
blob - a8a3ea579510a1fb52d1335755b07681391a398d
blob + a7e8448f37599141ef907df5d2159eaac83edf3e
--- regress/cmdline/common.sh
+++ regress/cmdline/common.sh
function test_init
{
local testname="$1"
+ local no_tree="$2"
if [ -z "$testname" ]; then
echo "No test name provided" >&2
return 1
local testroot=`mktemp -p /tmp -d got-test-$testname-XXXXXXXX`
mkdir $testroot/repo
git_init $testroot/repo
- make_test_tree $testroot/repo
- git_commit $testroot/repo -m "adding the test tree"
+ if [ -z "$no_tree" ]; then
+ make_test_tree $testroot/repo
+ git_commit $testroot/repo -m "adding the test tree"
+ fi
echo "$testroot"
}
blob - 29675054ce70a9414adddb3bf89fd6f602397973
blob + b7d9d15172b1bc6145e019ed80dba37c3dea057e
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
if [ -e $testroot/wt/epsilon/psi/mu ]; then
echo "removed file epsilon/psi/mu still exists on disk" >&2
test_done "$testroot" "1"
+ return 1
+ fi
+
+ test_done "$testroot" "0"
+}
+
+function test_update_creates_missing_parent {
+ local testroot=`test_init update_creates_missing_parent no_tree`
+
+ touch $testroot/repo/Makefile
+ touch $testroot/repo/snake.6
+ touch $testroot/repo/snake.c
+ (cd $testroot/repo && git add .)
+ git_commit $testroot/repo -m "adding initial snake tree"
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ if [ "$?" != "0" ]; then
+ test_done "$testroot" "$?"
+ return 1
+ fi
+
+ mkdir -p $testroot/repo/snake
+ (cd $testroot/repo && git mv Makefile snake.6 snake.c snake)
+ touch $testroot/repo/snake/move.c
+ touch $testroot/repo/snake/pathnames.h
+ touch $testroot/repo/snake/snake.h
+ mkdir -p $testroot/repo/snscore
+ touch $testroot/repo/snscore/Makefile
+ touch $testroot/repo/snscore/snscore.c
+ (cd $testroot/repo && git add .)
+ git_commit $testroot/repo -m "restructuring snake tree"
+
+ echo "D Makefile" > $testroot/stdout.expected
+ echo "A snake/Makefile" >> $testroot/stdout.expected
+ echo "A snake/move.c" >> $testroot/stdout.expected
+ echo "A snake/pathnames.h" >> $testroot/stdout.expected
+ echo "A snake/snake.6" >> $testroot/stdout.expected
+ echo "A snake/snake.c" >> $testroot/stdout.expected
+ echo "A snake/snake.h" >> $testroot/stdout.expected
+ echo "D snake.6" >> $testroot/stdout.expected
+ echo "D snake.c" >> $testroot/stdout.expected
+ echo "A snscore/Makefile" >> $testroot/stdout.expected
+ echo "A snscore/snscore.c" >> $testroot/stdout.expected
+ echo -n "Updated to commit " >> $testroot/stdout.expected
+ git_show_head $testroot/repo >> $testroot/stdout.expected
+ echo >> $testroot/stdout.expected
+
+ (cd $testroot/wt && got update > $testroot/stdout)
+
+ cmp $testroot/stdout.expected $testroot/stdout
+ if [ "$?" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$?"
return 1
fi
run_test test_update_dir_with_dot_sibling
run_test test_update_moves_files_upwards
#run_test test_update_moves_files_to_new_dir # test is failing
+run_test test_update_creates_missing_parent