diff options
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Show the root commit in a followed log
A followed log diffs each commit against its parent to learn whether the file changed there, and a root commit was skipped rather than diffed against the empty tree, so a file created in the first commit never showed that commit.
Diffstat (limited to '')
-rw-r--r--source/ui-log.c25
-rwxr-xr-xtests/t0103-log.sh38
2 files changed, 50 insertions, 13 deletions
diff --git a/source/ui-log.c b/source/ui-log.c
index f96689e..8adc5ac 100644
--- a/source/ui-log.c
+++ b/source/ui-log.c
@@ -88,15 +88,16 @@ static void follow_path(struct diff_filepair *pair)
/*
* Whether a commit belongs in the listing. When a single path is being
- * followed the commit is diffed against its one parent here, and the counts
- * that fall out of that diff are kept so the row does not repeat the work.
+ * followed the commit is diffed against its one parent here, or against the
+ * empty tree when it is the root, and the counts that fall out of that diff
+ * are kept so the row does not repeat the work.
*/
static int should_show(struct commit *commit, struct rev_info *revs)
{
// Static, because the walk keeps the address in its diff options.
static filepair_fn follow = follow_path;
struct commit_list *parents = commit->parents;
- struct commit *parent;
+ const struct object_id *parent_tree = NULL;
int found = 0, saved_fmt;
struct diff_flags saved_flags = revs->diffopt.flags;
@@ -108,22 +109,20 @@ static int should_show(struct commit *commit, struct rev_info *revs)
if (parents && parents->next)
return 0;
- if (!parents)
- return revs->show_root_diff;
-
- parent = parents->item;
-
- // A parent that does not parse is left for print_commit to report on,
- // so the commit is shown.
- if (repo_parse_commit(the_repository, parent))
- return 1;
+ if (parents) {
+ // A parent that does not parse is left for print_commit to
+ // report on, so the commit is shown.
+ if (repo_parse_commit(the_repository, parents->item))
+ return 1;
+ parent_tree = get_commit_tree_oid(parents->item);
+ }
file_count = 0;
added_lines = 0;
removed_lines = 0;
revs->diffopt.flags.recursive = 1;
- diff_tree_oid(get_commit_tree_oid(parent), get_commit_tree_oid(commit), "", &revs->diffopt);
+ diff_tree_oid(parent_tree, get_commit_tree_oid(commit), "", &revs->diffopt);
diffcore_std(&revs->diffopt);
found = !diff_queue_is_empty(&revs->diffopt);
diff --git a/tests/t0103-log.sh b/tests/t0103-log.sh
index 16fabda..08f9ddd 100755
--- a/tests/t0103-log.sh
+++ b/tests/t0103-log.sh
@@ -45,4 +45,42 @@ test_expect_success 'no links with space in path' '! grep "href=./with space/" t
test_expect_success 'no links with space in arg' '! grep "q=commit 1" tmp'
test_expect_success 'commit 2 is not visible' '! grep "commit 2" tmp'
+# Following a file diffs each commit for the name the file had there, so the
+# root commit that created it has to be diffed too.
+test_expect_success 'set up a renamed file to follow' '
+ test_create_repo repos/fol &&
+ (
+ cd repos/fol &&
+ echo 1 >a.txt &&
+ git add a.txt &&
+ git commit -m "create a" &&
+ for i in 2 3 4
+ do
+ echo $i >>a.txt &&
+ git commit -am "edit a $i" || return 1
+ done &&
+ git mv a.txt b.txt &&
+ git commit -m "rename to b" &&
+ for i in 6 7 8
+ do
+ echo $i >>b.txt &&
+ git commit -am "edit b $i" || return 1
+ done
+ ) &&
+ {
+ echo "virtual-root=/" &&
+ echo "cache-size=0" &&
+ echo "enable-follow-links=1" &&
+ echo "max-commit-count=3" &&
+ echo "repo.url=fol" &&
+ echo "repo.path=$PWD/repos/fol/.git"
+ } >folrc
+'
+
+test_expect_success 'a followed log reaches the root commit' '
+ CGIT_CONFIG="$PWD/folrc" QUERY_STRING="url=fol/log/b.txt&follow=1&ofs=6" cgit >tmp &&
+ grep ">edit a 2<" tmp &&
+ grep ">create a<" tmp
+'
+
test_done