Commit a9fa2909b9b3f681373c249f42a233d89335fc4c

Stefan Sperling 2019-07-27T21:51:52

fix 'got revert' on files in newly added subdirectories

diff --git a/lib/worktree.c b/lib/worktree.c
index 59a5e82..4f7c0c9 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -2645,29 +2645,32 @@ revert_file(struct got_worktree *worktree, struct got_fileindex *fileindex,
 		}
 	}
 
-	err = got_object_id_by_path(&tree_id, repo, worktree->base_commit_id,
-	    tree_path);
-	if (err)
-		goto done;
-
-	err = got_object_open_as_tree(&tree, repo, tree_id);
+	err = get_file_status(&status, &sb, ie, ondisk_path, repo);
 	if (err)
 		goto done;
 
-	te_name = basename(ie->path);
-	if (te_name == NULL) {
-		err = got_error_from_errno2("basename", ie->path);
-		goto done;
-	}
+	err = got_object_id_by_path(&tree_id, repo, worktree->base_commit_id,
+	    tree_path);
+	if (err) {
+		if (!(err->code == GOT_ERR_NO_TREE_ENTRY &&
+		    status == GOT_STATUS_ADD))
+			goto done;
+	} else {
+		err = got_object_open_as_tree(&tree, repo, tree_id);
+		if (err)
+			goto done;
 
-	err = get_file_status(&status, &sb, ie, ondisk_path, repo);
-	if (err)
-		goto done;
+		te_name = basename(ie->path);
+		if (te_name == NULL) {
+			err = got_error_from_errno2("basename", ie->path);
+			goto done;
+		}
 
-	te = got_object_tree_find_entry(tree, te_name);
-	if (te == NULL && status != GOT_STATUS_ADD) {
-		err = got_error(GOT_ERR_NO_TREE_ENTRY);
-		goto done;
+		te = got_object_tree_find_entry(tree, te_name);
+		if (te == NULL && status != GOT_STATUS_ADD) {
+			err = got_error(GOT_ERR_NO_TREE_ENTRY);
+			goto done;
+		}
 	}
 
 	switch (status) {
diff --git a/regress/cmdline/add.sh b/regress/cmdline/add.sh
index da716a3..727c09d 100755
--- a/regress/cmdline/add.sh
+++ b/regress/cmdline/add.sh
@@ -96,6 +96,31 @@ function test_add_multiple {
 	test_done "$testroot" "$ret"
 }
 
+function test_add_file_in_new_subdir {
+	local testroot=`test_init add_file_in_new_subdir`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	mkdir -p $testroot/wt/new
+	echo "new file" > $testroot/wt/new/foo
+
+	echo 'A  new/foo' > $testroot/stdout.expected
+	(cd $testroot/wt && got add new/foo > $testroot/stdout)
+
+	cmp -s $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_add_basic
 run_test test_double_add
 run_test test_add_multiple
+run_test test_add_file_in_new_subdir
diff --git a/regress/cmdline/revert.sh b/regress/cmdline/revert.sh
index 65ebe13..63d1e5e 100755
--- a/regress/cmdline/revert.sh
+++ b/regress/cmdline/revert.sh
@@ -183,7 +183,46 @@ function test_revert_multiple {
 	test_done "$testroot" "$ret"
 }
 
+function test_revert_file_in_new_subdir {
+	local testroot=`test_init revert_file_in_new_subdir`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+
+	mkdir -p $testroot/wt/newdir
+	echo new > $testroot/wt/newdir/new
+	(cd $testroot/wt && got add newdir/new > /dev/null)
+
+	(cd $testroot/wt && got revert newdir/new > $testroot/stdout)
+
+	echo "R  newdir/new" > $testroot/stdout.expected
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	(cd $testroot/wt && got status > $testroot/stdout)
+
+	echo "?  newdir/new" > $testroot/stdout.expected
+	cmp -s $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_revert_basic
 run_test test_revert_rm
 run_test test_revert_add
 run_test test_revert_multiple
+run_test test_revert_file_in_new_subdir