"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
fix 'got log -p path' bug
To:
gameoftrees@openbsd.org
Date:
Mon, 4 May 2020 15:06:22 +0200

Download raw body.

Thread
I noticed that this command in got's own Git repository will error
out on the commit which added .gitignore:

	got log -p .gitignore

The unexpected error is "got: no such entry found in tree".

This is a legitimate condition: The path does not exist in the parent
commit of the commit which added the .gitignore file. What is going wrong
is that our code doesn't gracefully handle this error condition.

Below is a fix and a test which reproduces the problem.

ok?

diff 010fe6f0ea0a54c2bc1f5eb998afd8d44e235b05 /home/stsp/src/got
blob - 7bf94578ea43d411c5be1b07496fbc6ab378c4c1
file + got/got.c
--- got/got.c
+++ got/got.c
@@ -2923,13 +2923,16 @@ print_patch(struct got_commit_object *commit, struct g
 			err = got_object_id_by_path(&obj_id1, repo,
 			    qid->id, path);
 			if (err) {
-				free(obj_id2);
-				goto done;
-			}
-			err = got_object_id_str(&id_str1, obj_id1);
-			if (err) {
-				free(obj_id2);
-				goto done;
+				if (err->code != GOT_ERR_NO_TREE_ENTRY) {
+					free(obj_id2);
+					goto done;
+				}
+			} else {
+				err = got_object_id_str(&id_str1, obj_id1);
+				if (err) {
+					free(obj_id2);
+					goto done;
+				}
 			}
 		}
 		err = got_object_get_type(&obj_type, repo, obj_id2);
blob - ea958f5ec1a9401d85234c78905402873c196e81
file + regress/cmdline/log.sh
--- regress/cmdline/log.sh
+++ regress/cmdline/log.sh
@@ -283,6 +283,40 @@ function test_log_limit {
 	test_done "$testroot" "0"
 }
 
+function test_log_patch_added_file {
+	local testroot=`test_init log_patch_added_file`
+	local commit_id0=`git_show_head $testroot/repo`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo "new file" > $testroot/wt/new
+	(cd $testroot/wt && got add new >/dev/null)
+	(cd $testroot/wt && got commit -m 'test log_limit' > /dev/null)
+	local commit_id1=`git_show_head $testroot/repo`
+
+	echo "commit $commit_id1 (master)" > $testroot/stdout.expected
+	# This used to fail with 'got: no such entry found in tree'
+	(cd $testroot/wt && got log -l1 -p new > $testroot/stdout.patch)
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		echo "got log command failed unexpectedly" >&2
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+	grep ^commit $testroot/stdout.patch > $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"
+}
+
 function test_log_nonexistent_path {
 	local testroot=`test_init log_nonexistent_path`
 	local head_rev=`git_show_head $testroot/repo`
@@ -618,6 +652,7 @@ run_test test_log_in_worktree
 run_test test_log_in_worktree_with_path_prefix
 run_test test_log_tag
 run_test test_log_limit
+run_test test_log_patch_added_file
 run_test test_log_nonexistent_path
 run_test test_log_end_at_commit
 run_test test_log_reverse_display