tvl-depot/third_party/git/t/t8013-blame-ignore-revs.sh
Vincent Ambo f4609b896f merge(3p/git): Merge git subtree at v2.29.2
This also bumps the stable nixpkgs to 20.09 as of 2020-11-21, because
there is some breakage in the git build related to the netrc
credentials helper which someone has taken care of in nixpkgs.

The stable channel is not used for anything other than git, so this
should be fine.

Change-Id: I3575a19dab09e1e9556cf8231d717de9890484fb
2020-11-21 19:45:56 +01:00

291 lines
8.3 KiB
Bash
Executable file

#!/bin/sh
test_description='ignore revisions when blaming'
. ./test-lib.sh
# Creates:
# A--B--X
# A added line 1 and B added line 2. X makes changes to those lines. Sanity
# check that X is blamed for both lines.
test_expect_success setup '
test_commit A file line1 &&
echo line2 >>file &&
git add file &&
test_tick &&
git commit -m B &&
git tag B &&
test_write_lines line-one line-two >file &&
git add file &&
test_tick &&
git commit -m X &&
git tag X &&
git tag -a -m "X (annotated)" XT &&
git blame --line-porcelain file >blame_raw &&
grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
git rev-parse X >expect &&
test_cmp expect actual &&
grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
git rev-parse X >expect &&
test_cmp expect actual
'
# Ensure bogus --ignore-rev requests are caught
test_expect_success 'validate --ignore-rev' '
test_must_fail git blame --ignore-rev X^{tree} file
'
# Ensure bogus --ignore-revs-file requests are caught
test_expect_success 'validate --ignore-revs-file' '
git rev-parse X^{tree} >ignore_x &&
test_must_fail git blame --ignore-revs-file ignore_x file
'
for I in X XT
do
# Ignore X (or XT), make sure A is blamed for line 1 and B for line 2.
# Giving X (i.e. commit) and XT (i.e. annotated tag to commit) should
# produce the same result.
test_expect_success "ignore_rev_changing_lines ($I)" '
git blame --line-porcelain --ignore-rev $I file >blame_raw &&
grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
git rev-parse A >expect &&
test_cmp expect actual &&
grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
git rev-parse B >expect &&
test_cmp expect actual
'
done
# For ignored revs that have added 'unblamable' lines, attribute those to the
# ignored commit.
# A--B--X--Y
# Where Y changes lines 1 and 2, and adds lines 3 and 4. The added lines ought
# to have nothing in common with "line-one" or "line-two", to keep any
# heuristics from matching them with any lines in the parent.
test_expect_success ignore_rev_adding_unblamable_lines '
test_write_lines line-one-change line-two-changed y3 y4 >file &&
git add file &&
test_tick &&
git commit -m Y &&
git tag Y &&
git rev-parse Y >expect &&
git blame --line-porcelain file --ignore-rev Y >blame_raw &&
grep -E "^[0-9a-f]+ [0-9]+ 3" blame_raw | sed -e "s/ .*//" >actual &&
test_cmp expect actual &&
grep -E "^[0-9a-f]+ [0-9]+ 4" blame_raw | sed -e "s/ .*//" >actual &&
test_cmp expect actual
'
# Ignore X and Y, both in separate files. Lines 1 == A, 2 == B.
test_expect_success ignore_revs_from_files '
git rev-parse X >ignore_x &&
git rev-parse Y >ignore_y &&
git blame --line-porcelain file --ignore-revs-file ignore_x --ignore-revs-file ignore_y >blame_raw &&
grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
git rev-parse A >expect &&
test_cmp expect actual &&
grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
git rev-parse B >expect &&
test_cmp expect actual
'
# Ignore X from the config option, Y from a file.
test_expect_success ignore_revs_from_configs_and_files '
git config --add blame.ignoreRevsFile ignore_x &&
git blame --line-porcelain file --ignore-revs-file ignore_y >blame_raw &&
grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
git rev-parse A >expect &&
test_cmp expect actual &&
grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
git rev-parse B >expect &&
test_cmp expect actual
'
# Override blame.ignoreRevsFile (ignore_x) with an empty string. X should be
# blamed now for lines 1 and 2, since we are no longer ignoring X.
test_expect_success override_ignore_revs_file '
git blame --line-porcelain file --ignore-revs-file "" --ignore-revs-file ignore_y >blame_raw &&
git rev-parse X >expect &&
grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
test_cmp expect actual &&
grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
test_cmp expect actual
'
test_expect_success bad_files_and_revs '
test_must_fail git blame file --ignore-rev NOREV 2>err &&
test_i18ngrep "cannot find revision NOREV to ignore" err &&
test_must_fail git blame file --ignore-revs-file NOFILE 2>err &&
test_i18ngrep "could not open.*: NOFILE" err &&
echo NOREV >ignore_norev &&
test_must_fail git blame file --ignore-revs-file ignore_norev 2>err &&
test_i18ngrep "invalid object name: NOREV" err
'
# For ignored revs that have added 'unblamable' lines, mark those lines with a
# '*'
# A--B--X--Y
# Lines 3 and 4 are from Y and unblamable. This was set up in
# ignore_rev_adding_unblamable_lines.
test_expect_success mark_unblamable_lines '
git config --add blame.markUnblamableLines true &&
git blame --ignore-rev Y file >blame_raw &&
echo "*" >expect &&
sed -n "3p" blame_raw | cut -c1 >actual &&
test_cmp expect actual &&
sed -n "4p" blame_raw | cut -c1 >actual &&
test_cmp expect actual
'
# Commit Z will touch the first two lines. Y touched all four.
# A--B--X--Y--Z
# The blame output when ignoring Z should be:
# ?Y ... 1)
# ?Y ... 2)
# Y ... 3)
# Y ... 4)
# We're checking only the first character
test_expect_success mark_ignored_lines '
git config --add blame.markIgnoredLines true &&
test_write_lines line-one-Z line-two-Z y3 y4 >file &&
git add file &&
test_tick &&
git commit -m Z &&
git tag Z &&
git blame --ignore-rev Z file >blame_raw &&
echo "?" >expect &&
sed -n "1p" blame_raw | cut -c1 >actual &&
test_cmp expect actual &&
sed -n "2p" blame_raw | cut -c1 >actual &&
test_cmp expect actual &&
sed -n "3p" blame_raw | cut -c1 >actual &&
! test_cmp expect actual &&
sed -n "4p" blame_raw | cut -c1 >actual &&
! test_cmp expect actual
'
# For ignored revs that added 'unblamable' lines and more recent commits changed
# the blamable lines, mark the unblamable lines with a
# '*'
# A--B--X--Y--Z
# Lines 3 and 4 are from Y and unblamable, as set up in
# ignore_rev_adding_unblamable_lines. Z changed lines 1 and 2.
test_expect_success mark_unblamable_lines_intermediate '
git config --add blame.markUnblamableLines true &&
git blame --ignore-rev Y file >blame_raw 2>stderr &&
echo "*" >expect &&
sed -n "3p" blame_raw | cut -c1 >actual &&
test_cmp expect actual &&
sed -n "4p" blame_raw | cut -c1 >actual &&
test_cmp expect actual
'
# The heuristic called by guess_line_blames() tries to find the size of a
# blame_entry 'e' in the parent's address space. Those calculations need to
# check for negative or zero values for when a blame entry is completely outside
# the window of the parent's version of a file.
#
# This happens when one commit adds several lines (commit B below). A later
# commit (C) changes one line in the middle of B's change. Commit C gets blamed
# for its change, and that breaks up B's change into multiple blame entries.
# When processing B, one of the blame_entries is outside A's window (which was
# zero - it had no lines added on its side of the diff).
#
# A--B--C, ignore B to test the ignore heuristic's boundary checks.
test_expect_success ignored_chunk_negative_parent_size '
rm -rf .git/ &&
git init &&
test_write_lines L1 L2 L7 L8 L9 >file &&
git add file &&
test_tick &&
git commit -m A &&
git tag A &&
test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 L9 >file &&
git add file &&
test_tick &&
git commit -m B &&
git tag B &&
test_write_lines L1 L2 L3 L4 xxx L6 L7 L8 L9 >file &&
git add file &&
test_tick &&
git commit -m C &&
git tag C &&
git blame file --ignore-rev B >blame_raw
'
# Resetting the repo and creating:
#
# A--B--M
# \ /
# C-+
#
# 'A' creates a file. B changes line 1, and C changes line 9. M merges.
test_expect_success ignore_merge '
rm -rf .git/ &&
git init &&
test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 L9 >file &&
git add file &&
test_tick &&
git commit -m A &&
git tag A &&
test_write_lines BB L2 L3 L4 L5 L6 L7 L8 L9 >file &&
git add file &&
test_tick &&
git commit -m B &&
git tag B &&
git reset --hard A &&
test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 CC >file &&
git add file &&
test_tick &&
git commit -m C &&
git tag C &&
test_merge M B &&
git blame --line-porcelain file --ignore-rev M >blame_raw &&
grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
git rev-parse B >expect &&
test_cmp expect actual &&
grep -E "^[0-9a-f]+ [0-9]+ 9" blame_raw | sed -e "s/ .*//" >actual &&
git rev-parse C >expect &&
test_cmp expect actual
'
test_done