Passed
Pull Request — release-2.1 (#6367)
by John
04:41
created

find_signed_off_parents()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 28
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 4
eloc 13
c 1
b 0
f 1
nc 5
nop 1
dl 0
loc 28
rs 9.8333
1
<?php
2
3
/**
4
 * Simple Machines Forum (SMF)
5
 *
6
 * @package SMF
7
 * @author Simple Machines https://www.simplemachines.org
8
 * @copyright 2020 Simple Machines and individual contributors
9
 * @license https://www.simplemachines.org/about/smf/license.php BSD
10
 *
11
 * @version 2.1 RC3
12
 */
13
14
// Debug stuff.
15
define('DEBUG_MODE', false);
16
17
if (DEBUG_MODE)
18
	debugPrint("--- DEBUG MSGS START ---");
19
20
// First, lets do a basic test.  This is non GPG signed commits.
21
$signedoff = find_signed_off();
22
23
// Now Try to test for the GPG if we don't have a message.
24
if (empty($signedoff))
25
	$signedoff = find_gpg();
26
27
// Nothing yet?  Lets ask your parents.
28
if (empty($signedoff) && isset($_SERVER['argv'], $_SERVER['argv'][1]) && $_SERVER['argv'][1] == 'travis')
29
	$signedoff = find_signed_off_parents();
30
31
if (DEBUG_MODE)
32
	debugPrint("--- DEBUG MSGS END ---");
33
34
// Nothing?  Well darn.
35
if (empty($signedoff))
36
{
37
	fwrite(STDERR, 'Error: Signed-off-by not found in commit message');
38
	exit(1);
39
}
40
elseif (DEBUG_MODE)
41
	debugPrint('Valid signed off found');
42
43
// Find a commit by Signed Off
44
function find_signed_off($commit = 'HEAD', $childs = array(), $level = 0)
45
{
46
	$commit = trim($commit);
47
48
	// Where we are at.
49
	debugPrint('Attempting to find signed off on commit ' . $commit);
50
51
	// To many recrusions here.
52
	if ($level > 10)
53
	{
54
		debugPrint('Recusion limit exceeded on find_signed_off');
55
		return false;
56
	}
57
58
	// What string tests should we look for?
59
	$stringTests = array('Signed-off-by:', 'Signed by');
60
61
	// Get message data and clean it up, should only need the last line.
62
	$message = trim(shell_exec('git show -s --format=%B ' . $commit));
63
	$lines = explode("\n", trim(str_replace("\r", "\n", $message)));
64
	$lastLine = $lines[count($lines) - 1];
65
66
	// Debug info.
67
	debugPrint('Testing line "' . $lastLine . '"');
68
69
	// loop through each test and find one.
70
	$result = false;
71
	foreach ($stringTests as $testedString)
72
	{
73
		debugPrint('Testing "' . $testedString . '"');
74
75
		$result = stripos($lastLine, $testedString);
76
77
		// We got a result.
78
		if ($result !== false)
79
		{
80
			debugPrint('Found "' . $testedString . '"');
81
			break;
82
		}
83
	}
84
85
	// Debugger.
86
	$debugMsgs = array(
87
		'raw body' => '"' . rtrim(shell_exec('git show -s --format=%B ' . $commit)) . '"',
88
		'body' => '"' . rtrim(shell_exec('git show -s --format=%b ' . $commit)) . '"',
89
		'commit notes' => '"' . rtrim(shell_exec('git show -s --format=%N ' . $commit)) . '"',
90
		'ref names' => '"' . rtrim(shell_exec('git show -s --format=%d ' . $commit)) . '"',
91
		'commit hash' => '"' . rtrim(shell_exec('git show -s --format=%H ' . $commit)) . '"',
92
		'tree hash' => '"' . rtrim(shell_exec('git show -s --format=%T ' . $commit)) . '"',
93
		'parent hash' => '"' . rtrim(shell_exec('git show -s --format=%P ' . $commit)) . '"',
94
		'result' => '"' . $result . '"',
0 ignored issues
show
Bug introduced by
Are you sure $result of type false|integer can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

94
		'result' => '"' . /** @scrutinizer ignore-type */ $result . '"',
Loading history...
95
		'testedString' => '"' . $testedString . '"',
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $testedString seems to be defined by a foreach iteration on line 71. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
96
	);
97
	debugPrint('Commit ' . $commit . ' at time ' . time() . ": " . rtrim(print_r($debugMsgs, true)));
98
99
100
	// No result and found a merge? Lets go deeper.
101
	if ($result === false && preg_match('~Merge ([A-Za-z0-9]{40}) into ([A-Za-z0-9]{40})~i', $lastLine, $merges))
102
	{
103
		debugPrint('Found Merge, attempting to get more parent commit: ' . $merges[1]);
104
105
		return find_signed_off($merges[1], array_merge(array($merges[1]), $childs), ++$level);
106
	}
107
108
	return $result !== false;
109
}
110
111
// Find a commit by GPG
112
function find_gpg($commit = 'HEAD', $childs = array())
0 ignored issues
show
Unused Code introduced by
The parameter $childs is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

112
function find_gpg($commit = 'HEAD', /** @scrutinizer ignore-unused */ $childs = array())

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
113
{
114
	$commit = trim($commit);
115
116
	debugPrint('Attempting to Find GPG on commit ' . $commit);
117
118
	// Get verify commit data.
119
	$message = trim(shell_exec('git verify-commit ' . $commit . ' -v --raw'));
120
121
	// Should we actually test for gpg results?  Perhaps, but it seems doing that with travis may fail since it has no way to verify a GPG signature from GitHub.  GitHub should have prevented a bad GPG from making a commit to a authors repository and could be trusted in most cases it seems.
122
	$result = strlen($message) > 0;
123
124
	// Debugger.
125
	$debugMsgs = array(
126
		// Raw body.
127
		'verify-commit' => '"' . rtrim(shell_exec('git verify-commit ' . $commit . ' -v --raw')) . '"',
128
		// Result.
129
		'result' => '"' . $result . '"',
130
		// Last tested string, or the correct string.
131
		'message' => '"' . $message . '"',
132
	);
133
	debugPrint('Commit ' . $commit . ' at time ' . time() . ": " . rtrim(print_r($debugMsgs, true)));
134
135
	return $result;
136
}
137
138
// Looks at all the parents, and tries to find a signed off by somewhere.
139
function find_signed_off_parents($commit = 'HEAD')
140
{
141
	$commit = trim($commit);
142
143
	debugPrint('Attempting to find parents on commit ' . $commit);
144
145
	$parentsRaw = rtrim(shell_exec('git show -s --format=%P ' . $commit));
146
	$parents = explode(' ', $parentsRaw);
147
148
	// Test each one.
149
	foreach ($parents as $p)
150
	{
151
		$p = trim($p);
152
		debugPrint('Testing parent of ' . $commit . ' for signed off');
153
154
		// Basic tests.
155
		$test = find_signed_off($p);
156
157
		// No, maybe it has a GPG parent.
158
		if (empty($test))
159
			$test = find_gpg($p);
160
161
		if (!empty($test))
162
			return $test;
163
	}
164
165
	// Lucked out.
166
	return false;
167
}
168
169
// Print a debug line
170
function debugPrint($msg)
171
{
172
	if (DEBUG_MODE)
173
		echo $msg, "\n";
174
}