Commit Diff


commit - 1c11b35cd62a3d95ca80329b5edb14875c18fa6a
commit + 50952927133492b33519e6b09474d9a9ae77abb6
blob - b3b7b356254d4d7892f5ebfce76f811fbccf2813
blob + afdeab746035bdafbbd04d8bf67736896f49b640
--- lib/fileindex.c
+++ lib/fileindex.c
@@ -100,9 +100,8 @@ got_fileindex_entry_free(struct got_fileindex_entry *e
 	free(entry);
 }
 
-const struct got_error *
-got_fileindex_entry_add(struct got_fileindex *fileindex,
-    struct got_fileindex_entry *entry)
+static const struct got_error *
+add_entry(struct got_fileindex *fileindex, struct got_fileindex_entry *entry)
 {
 	if (fileindex->nentries >= GOT_FILEIDX_MAX_ENTRIES)
 		return got_error(GOT_ERR_NO_SPACE);
@@ -110,6 +109,16 @@ got_fileindex_entry_add(struct got_fileindex *fileinde
 	RB_INSERT(got_fileindex_tree, &fileindex->entries, entry);
 	fileindex->nentries++;
 	return NULL;
+}
+
+const struct got_error *
+got_fileindex_entry_add(struct got_fileindex *fileindex,
+    struct got_fileindex_entry *entry)
+{
+	/* Flag this entry until it gets written out to disk. */
+	entry->flags |= GOT_INDEX_ENTRY_F_INTENT_TO_ADD;
+
+	return add_entry(fileindex, entry);
 }
 
 void
@@ -309,6 +318,7 @@ got_fileindex_write(struct got_fileindex *fileindex, F
 		return got_ferror(outfile, GOT_ERR_IO);
 
 	RB_FOREACH(entry, got_fileindex_tree, &fileindex->entries) {
+		entry->flags &= ~GOT_INDEX_ENTRY_F_INTENT_TO_ADD;
 		err = write_fileindex_entry(&ctx, entry, outfile);
 		if (err)
 			return err;
@@ -505,7 +515,7 @@ got_fileindex_read(struct got_fileindex *fileindex, FI
 		err = read_fileindex_entry(&entry, &ctx, infile);
 		if (err)
 			return err;
-		err = got_fileindex_entry_add(fileindex, entry);
+		err = add_entry(fileindex, entry);
 		if (err)
 			return err;
 	}
@@ -525,7 +535,6 @@ in_same_subdir(struct got_fileindex_entry *ie, const c
     struct got_tree_entry *te)
 {
 	size_t parent_len = strlen(parent_path);
-	size_t te_name_len = strlen(te->name);
 	char *ie_name;
 
 	if (!got_path_is_child(ie->path, parent_path, parent_len))
@@ -534,12 +543,8 @@ in_same_subdir(struct got_fileindex_entry *ie, const c
 	ie_name = ie->path + parent_len;
 	while (ie_name[0] == '/')
 		ie_name++;
-	if (strncmp(ie_name, te->name, te_name_len) != 0)
-		return 0;
-	if (ie_name[te_name_len] == '/')
-		return 0;
 
-	return 1;
+	return strchr(ie_name, '/') == NULL;
 }
 
 static int
@@ -551,15 +556,15 @@ cmp_entries(struct got_fileindex_entry *ie, const char
 
 	if (!in_same_subdir(ie, parent_path, te)) {
 		if (parent_path[0])
-			return got_compare_paths(ie->path, parent_path);
-		return got_compare_paths(ie->path, te->name);
+			return strcmp(ie->path, parent_path);
+		return strcmp(ie->path, te->name);
 	}
 
 	ie_name = ie->path + parent_len;
 	while (ie_name[0] == '/')
 		ie_name++;
 
-	return got_compare_paths(ie_name, te->name);
+	return strcmp(ie_name, te->name);
 }
 
 static const struct got_error *
@@ -567,6 +572,20 @@ diff_fileindex_tree(struct got_fileindex *, struct got
     struct got_tree_object *, const char *, struct got_repository *,
     struct got_fileindex_diff_cb *, void *);
 
+struct got_fileindex_entry *
+walk_fileindex(struct got_fileindex *fileindex, struct got_fileindex_entry *ie)
+{
+	struct got_fileindex_entry *next;
+
+	next = RB_NEXT(got_fileindex_tree, &fileindex->entries, ie);
+
+	/* Skip entries which were newly added by diff callbacks. */
+	while (next && (next->flags & GOT_INDEX_ENTRY_F_INTENT_TO_ADD))
+		next = RB_NEXT(got_fileindex_tree, &fileindex->entries, next);
+
+	return next;
+}
+
 static const struct got_error *
 walk_tree(struct got_tree_entry **next, struct got_fileindex *fileindex,
     struct got_fileindex_entry **ie, struct got_tree_entry *te,
@@ -635,13 +654,11 @@ diff_fileindex_tree(struct got_fileindex *fileindex,
 				    path);
 				if (err)
 					break;
-				*ie = RB_NEXT(got_fileindex_tree,
-				    &fileindex->entries, *ie);
+				*ie = walk_fileindex(fileindex, *ie);
 				err = walk_tree(&te, fileindex, ie, te,
 				    path, repo, cb, cb_arg);
-			} else if (cmp < 0) {
-				next = RB_NEXT(got_fileindex_tree,
-				    &fileindex->entries, *ie);
+			} else if (cmp < 0 ) {
+				next = walk_fileindex(fileindex, *ie);
 				err = cb->diff_old(cb_arg, *ie, path);
 				if (err)
 					break;
@@ -656,8 +673,7 @@ diff_fileindex_tree(struct got_fileindex *fileindex,
 			if (err)
 				break;
 		} else if (*ie) {
-			next = RB_NEXT(got_fileindex_tree,
-			    &fileindex->entries, *ie);
+			next = walk_fileindex(fileindex, *ie);
 			err = cb->diff_old(cb_arg, *ie, path);
 			if (err)
 				break;
blob - 791dba0cf4be882a105d7d91c47c94691d177dc5
blob + 3aee1d309fe36ea2dc730b4d5680e7f97930541a
--- lib/got_lib_fileindex.h
+++ lib/got_lib_fileindex.h
@@ -53,6 +53,7 @@ struct got_fileindex_entry {
 #define GOT_INDEX_ENTRY_F_STAGE		0x00003000
 #define GOT_INDEX_ENTRY_F_EXTENDED	0x00004000
 #define GOT_INDEX_ENTRY_F_ASSUME_VALID	0x00008000
+#define GOT_INDEX_ENTRY_F_INTENT_TO_ADD	0x20000000
 
 	/*
 	 * UNIX-style path, relative to work tree root.
@@ -77,7 +78,7 @@ static inline int
 got_fileindex_cmp(const struct got_fileindex_entry *e1,
     const struct got_fileindex_entry *e2)
 {
-	return got_compare_paths(e1->path, e2->path);
+	return strcmp(e1->path, e2->path);
 }
 
 RB_PROTOTYPE(got_fileindex_tree, got_fileindex_entry, entry, got_fileindex_cmp);
blob - 1572dea6554f51a02a91ac2c15fe1024352791c9
blob + e28a3564b901a2fcd6f09d3552139ff4fb2dee1b
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
@@ -283,6 +283,46 @@ function test_update_sibling_dirs_with_common_prefix {
 	# U  epsilon/zeta
 	# D  epsilon2/mu <--- not intended
 	# A  epsilon2/mu <--- not intended
+	(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
+
+	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_dir_with_dot_sibling {
+	local testroot=`test_init update_dir_with_dot_sibling`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	if [ "$?" != "0" ]; then
+		test_done "$testroot" "$?"
+		return 1
+	fi
+
+	echo text > $testroot/repo/epsilon.txt
+	(cd $testroot/repo && git add epsilon.txt)
+	git_commit $testroot/repo -m "adding sibling of epsilon"
+	echo change > $testroot/repo/epsilon/zeta
+	git_commit $testroot/repo -m "changing epsilon/zeta"
+
+	echo "A  epsilon.txt" > $testroot/stdout.expected
+	echo "U  epsilon/zeta" >> $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
@@ -292,6 +332,16 @@ function test_update_sibling_dirs_with_common_prefix {
 		return 1
 	fi
 
+	echo "another change" > $testroot/repo/epsilon/zeta
+	git_commit $testroot/repo -m "changing epsilon/zeta again"
+
+	echo "U  epsilon/zeta" > $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
@@ -299,6 +349,13 @@ function test_update_sibling_dirs_with_common_prefix {
 		return 1
 	fi
 
+	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"
 }
 
@@ -309,3 +366,4 @@ run_test test_update_deletes_dir
 run_test test_update_deletes_dir_with_path_prefix
 run_test test_update_deletes_dir_recursively
 run_test test_update_sibling_dirs_with_common_prefix
+run_test test_update_dir_with_dot_sibling