aboutsummaryrefslogtreecommitdiffstats
path: root/t/perf/p6010-merge-base.sh
blob: 54f52fa23ee1e7a637f10a8531d22448eb5e6d0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/bin/sh

test_description='Test git merge-base'

. ./perf-lib.sh

test_perf_fresh_repo

#
# Creates lots of merges to make history traversal costly.  In
# particular it creates 2^($max_level-1)-1 2-way merges on top of
# 2^($max_level-1) root commits.  E.g., the commit history looks like
# this for a $max_level of 3:
#
#     _1_
#    /   \
#   2     3
#  / \   / \
# 4   5 6   7
#
# The numbers are the fast-import marks, which also are the commit
# messages.  1 is the HEAD commit and a merge, 2 and 3 are also merges,
# 4-7 are the root commits.
#
build_history () {
	local max_level="$1" &&
	local level="${2:-1}" &&
	local mark="${3:-1}" &&
	if test $level -eq $max_level
	then
		echo "reset refs/heads/master" &&
		echo "from $ZERO_OID" &&
		echo "commit refs/heads/master" &&
		echo "mark :$mark" &&
		echo "committer C <c@example.com> 1234567890 +0000" &&
		echo "data <<EOF" &&
		echo "$mark" &&
		echo "EOF"
	else
		local level1=$((level+1)) &&
		local mark1=$((2*mark)) &&
		local mark2=$((2*mark+1)) &&
		build_history $max_level $level1 $mark1 &&
		build_history $max_level $level1 $mark2 &&
		echo "commit refs/heads/master" &&
		echo "mark :$mark" &&
		echo "committer C <c@example.com> 1234567890 +0000" &&
		echo "data <<EOF" &&
		echo "$mark" &&
		echo "EOF" &&
		echo "from :$mark1" &&
		echo "merge :$mark2"
	fi
}

#
# Creates a new merge history in the same shape as build_history does,
# while reusing the same root commits.  This way the two top commits
# have 2^($max_level-1) merge bases between them.
#
build_history2 () {
	local max_level="$1" &&
	local level="${2:-1}" &&
	local mark="${3:-1}" &&
	if test $level -lt $max_level
	then
		local level1=$((level+1)) &&
		local mark1=$((2*mark)) &&
		local mark2=$((2*mark+1)) &&
		build_history2 $max_level $level1 $mark1 &&
		build_history2 $max_level $level1 $mark2 &&
		echo "commit refs/heads/master" &&
		echo "mark :$mark" &&
		echo "committer C <c@example.com> 1234567890 +0000" &&
		echo "data <<EOF" &&
		echo "$mark II" &&
		echo "EOF" &&
		echo "from :$mark1" &&
		echo "merge :$mark2"
	fi
}

test_expect_success 'setup' '
	max_level=15 &&
	build_history $max_level | git fast-import --export-marks=marks &&
	git tag one &&
	build_history2 $max_level | git fast-import --import-marks=marks --force &&
	git tag two &&
	git gc &&
	git log --format=%H --no-merges >expect
'

test_perf 'git merge-base' '
	git merge-base --all one two >actual
'

test_expect_success 'verify result' '
	test_cmp expect actual
'

test_done