Commit Diff


commit - a7f9d64ddf028029e3ef5123758712ec89840a5f
commit + bd4792ec812265a57f6e881d9bff1f297d325749
blob - 257b5a5795a8fa1e54d49544a3136627fc550201
blob + 70174aa3d9e1dc0477a3ceb497937b6acca741a4
--- lib/fileindex.c
+++ lib/fileindex.c
@@ -564,24 +564,29 @@ in_same_subdir(struct got_fileindex_entry *ie, const c
 	return strchr(ie_name, '/') == NULL;
 }
 
+/*
+ * Decide whether ie or te are equivalent, and if they aren't,
+ * then decide which should be processed first.
+ */
 static int
 cmp_entries(struct got_fileindex_entry *ie, const char *parent_path,
     struct got_tree_entry *te)
 {
 	size_t parent_len = strlen(parent_path);
-	char *ie_name;
+	int cmp;
 
 	if (!in_same_subdir(ie, parent_path, te)) {
-		if (parent_path[0])
-			return strcmp(ie->path, parent_path);
-		return strcmp(ie->path, te->name);
+		cmp = strncmp(ie->path, parent_path, parent_len);
+		if (cmp == 0)
+			cmp = strcmp(ie->path + parent_len, te->name);
+	} else {
+		char *ie_name = ie->path + parent_len;
+		while (ie_name[0] == '/')
+			ie_name++;
+		cmp = strcmp(ie_name, te->name);
 	}
-
-	ie_name = ie->path + parent_len;
-	while (ie_name[0] == '/')
-		ie_name++;
+	return cmp;
 
-	return strcmp(ie_name, te->name);
 }
 
 static const struct got_error *
@@ -611,12 +616,7 @@ walk_tree(struct got_tree_entry **next, struct got_fil
 {
 	const struct got_error *err = NULL;
 
-	if (te && S_ISREG(te->mode)) {
-		*next = SIMPLEQ_NEXT(te, entry);
-		return NULL;
-	}
-
-	while (te && S_ISDIR(te->mode)) {
+	if (S_ISDIR(te->mode)) {
 		char *subpath;
 		struct got_tree_object *subtree;
 
@@ -630,22 +630,15 @@ walk_tree(struct got_tree_entry **next, struct got_fil
 			return err;
 		}
 
-		if (*ie == NULL || !in_same_subdir(*ie, path, te)) {
-			err = cb->diff_new(cb_arg, te, path);
-			if (err)
-				return err;
-		}
-
 		err = diff_fileindex_tree(fileindex, ie, subtree,
 		    subpath, repo, cb, cb_arg);
 		free(subpath);
 		got_object_tree_close(subtree);
 		if (err)
 			return err;
-		te = SIMPLEQ_NEXT(te, entry);
 	}
 
-	*next = te;
+	*next = SIMPLEQ_NEXT(te, entry);
 	return NULL;
 }
 
blob - 43321ad6065fe5af9c29235580ecc1b15138c1bc
blob + 2438bbf344f4501b2177c6b04e1a90e016407f2f
--- lib/worktree.c
+++ lib/worktree.c
@@ -560,19 +560,7 @@ install_blob(struct got_worktree *worktree, struct got
 	fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
 	    GOT_DEFAULT_FILE_MODE);
 	if (fd == -1) {
-		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) {
+		if (errno == EEXIST) {
 			struct stat sb;
 			if (lstat(ondisk_path, &sb) == -1) {
 				err = got_error_from_errno();
blob - b7d9d15172b1bc6145e019ed80dba37c3dea057e
blob + b121574a4f98dd2f74a69c2a49cd1b5f6081c721
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
@@ -379,10 +379,10 @@ function test_update_moves_files_upwards {
 	(cd $testroot/repo && git mv epsilon/psi/chi/tau epsilon/psi/tau)
 	git_commit $testroot/repo -m "moving files upwards"
 
-	echo "A  epsilon/mu" > $testroot/stdout.expected
-	echo "A  epsilon/psi/tau" >> $testroot/stdout.expected
-	echo "D  epsilon/psi/chi/tau" >> $testroot/stdout.expected
+	echo "D  epsilon/psi/chi/tau" > $testroot/stdout.expected
 	echo "D  epsilon/psi/mu" >> $testroot/stdout.expected
+	echo "A  epsilon/mu" >> $testroot/stdout.expected
+	echo "A  epsilon/psi/tau" >> $testroot/stdout.expected
 	echo -n "Updated to commit " >> $testroot/stdout.expected
 	git_show_head $testroot/repo >> $testroot/stdout.expected
 	echo >> $testroot/stdout.expected
@@ -491,16 +491,69 @@ function test_update_creates_missing_parent {
 	git_commit $testroot/repo -m "restructuring snake tree"
 
 	echo "D  Makefile" > $testroot/stdout.expected
+	echo "D  snake.6" >> $testroot/stdout.expected
+	echo "D  snake.c" >> $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 "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
+
+	test_done "$testroot" "0"
+}
+
+function test_update_creates_missing_parent_with_subdir {
+	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/sss/snake
+	(cd $testroot/repo && git mv Makefile snake.6 snake.c sss/snake)
+	touch $testroot/repo/sss/snake/move.c
+	touch $testroot/repo/sss/snake/pathnames.h
+	touch $testroot/repo/sss/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 "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 "A  sss/snake/Makefile" >> $testroot/stdout.expected
+	echo "A  sss/snake/move.c" >> $testroot/stdout.expected
+	echo "A  sss/snake/pathnames.h" >> $testroot/stdout.expected
+	echo "A  sss/snake/snake.6" >> $testroot/stdout.expected
+	echo "A  sss/snake/snake.c" >> $testroot/stdout.expected
+	echo "A  sss/snake/snake.h" >> $testroot/stdout.expected
 	echo -n "Updated to commit " >> $testroot/stdout.expected
 	git_show_head $testroot/repo >> $testroot/stdout.expected
 	echo >> $testroot/stdout.expected
@@ -526,5 +579,6 @@ run_test test_update_deletes_dir_recursively
 run_test test_update_sibling_dirs_with_common_prefix
 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_moves_files_to_new_dir
 run_test test_update_creates_missing_parent
+run_test test_update_creates_missing_parent_with_subdir