fix another path ordering bug during status/update crawl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
diff --git a/lib/fileindex.c b/lib/fileindex.c
index 69121f8..85b4399 100644
--- a/lib/fileindex.c
+++ b/lib/fileindex.c
@@ -605,25 +605,6 @@ walk_tree(struct got_tree_entry **next, struct got_fileindex *fileindex,
return NULL;
}
-/*
- * Decide whether a fileindex entry path is equivalent to a tree entry path,
- * and if it is not, then decide which of the two should be processed first.
- */
-static int
-cmp_entries(const char *ie_path, const char *parent_path,
- size_t parent_len, const char *te_name)
-{
- int cmp = strncmp(ie_path, parent_path, parent_len);
- if (cmp == 0) {
- const char *ie_name = ie_path + parent_len;
- while (ie_name[0] == '/')
- ie_name++;
- cmp = strcmp(ie_name, te_name);
- }
- return cmp;
-
-}
-
static const struct got_error *
diff_fileindex_tree(struct got_fileindex *fileindex,
struct got_fileindex_entry **ie, struct got_tree_object *tree,
@@ -640,8 +621,14 @@ diff_fileindex_tree(struct got_fileindex *fileindex,
te = SIMPLEQ_FIRST(&entries->head);
while ((*ie && got_path_is_child((*ie)->path, path, path_len)) || te) {
if (te && *ie) {
- int cmp = cmp_entries((*ie)->path, path, path_len,
- te->name);
+ char *te_path;
+ int cmp;
+ if (asprintf(&te_path, "%s/%s", path, te->name) == -1) {
+ err = got_error_from_errno();
+ break;
+ }
+ cmp = got_path_cmp((*ie)->path, te_path);
+ free(te_path);
if (cmp == 0) {
err = cb->diff_old_new(cb_arg, *ie, te,
path);
@@ -799,10 +786,16 @@ diff_fileindex_dir(struct got_fileindex *fileindex,
dle = TAILQ_FIRST(&dirlist);
while ((*ie && got_path_is_child((*ie)->path, path, path_len)) || dle) {
if (dle && *ie) {
+ char *de_path;
int cmp;
de = dle->data;
- cmp = cmp_entries((*ie)->path, path, path_len,
- de->d_name);
+ if (asprintf(&de_path, "%s/%s", path,
+ de->d_name) == -1) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ cmp = got_path_cmp((*ie)->path, de_path);
+ free(de_path);
if (cmp == 0) {
err = cb->diff_old_new(cb_arg, *ie, de, path);
if (err)
diff --git a/regress/cmdline/status.sh b/regress/cmdline/status.sh
index 024aa63..e1df9d4 100755
--- a/regress/cmdline/status.sh
+++ b/regress/cmdline/status.sh
@@ -202,8 +202,57 @@ function test_status_shows_local_mods_after_update {
test_done "$testroot" "$ret"
}
+function test_status_unversioned_subdirs {
+ local testroot=`test_init status_unversioned_subdirs 1`
+
+ mkdir $testroot/repo/cdfs/
+ touch $testroot/repo/cdfs/Makefile
+ mkdir $testroot/repo/common/
+ touch $testroot/repo/common/Makefile
+ mkdir $testroot/repo/iso/
+ touch $testroot/repo/iso/Makefile
+ mkdir $testroot/repo/ramdisk/
+ touch $testroot/repo/ramdisk/Makefile
+ touch $testroot/repo/ramdisk/list.local
+ mkdir $testroot/repo/ramdisk_cd/
+ touch $testroot/repo/ramdisk_cd/Makefile
+ touch $testroot/repo/ramdisk_cd/list.local
+ (cd $testroot/repo && git add .)
+ git_commit $testroot/repo -m "first commit"
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ mkdir $testroot/wt/cdfs/obj
+ mkdir $testroot/wt/ramdisk/obj
+ mkdir $testroot/wt/ramdisk_cd/obj
+ mkdir $testroot/wt/iso/obj
+
+ echo -n > $testroot/stdout.expected
+
+ # This used to erroneously print:
+ #
+ # ! ramdisk_cd/Makefile
+ # ! ramdisk_cd/list.local
+ # ? ramdisk_cd/Makefile
+ # ? ramdisk_cd/list.local
+ (cd $testroot/wt && got status > $testroot/stdout)
+
+ cmp $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
+ test_done "$testroot" "$ret"
+}
+
run_test test_status_basic
run_test test_status_subdir_no_mods
run_test test_status_subdir_no_mods2
run_test test_status_obstructed
run_test test_status_shows_local_mods_after_update
+run_test test_status_unversioned_subdirs
diff --git a/regress/cmdline/update.sh b/regress/cmdline/update.sh
index 0a6f228..f950162 100755
--- a/regress/cmdline/update.sh
+++ b/regress/cmdline/update.sh
@@ -510,14 +510,14 @@ 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 "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