You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
274 lines
7.8 KiB
274 lines
7.8 KiB
#!/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 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 |
|
' |
|
|
|
# Ignore X, make sure A is blamed for line 1 and B for line 2. |
|
test_expect_success ignore_rev_changing_lines ' |
|
git blame --line-porcelain --ignore-rev X 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 |
|
' |
|
|
|
# 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
|
|
|