From 72084f120c1e5a2270c0854540153c35819d0b35 Mon Sep 17 00:00:00 2001 From: Mischa POSLAWSKY Date: Fri, 15 Jan 2021 18:41:47 +0100 Subject: [PATCH] login/commits: syntax highlighting of diff lines Parse chunks returned by git's porcelain word diffing interface, formatting old/new columns similar to split github commit output. Ignore strict line numbers in favour of minimal text comparison. --- login/commits/index.php | 111 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 6 deletions(-) diff --git a/login/commits/index.php b/login/commits/index.php index c53bf39..dbd8cd9 100644 --- a/login/commits/index.php +++ b/login/commits/index.php @@ -9,20 +9,119 @@ if (!$hash) { return TRUE; } -print "

Wijzigingen in $hash

\n"; +$this->title = "Wijzigingen in ".strtoupper($hash); +print "

{$this->title}

\n"; -$gitcmd = "git show ".$hash; +$gitcmd = "git show " + . "--word-diff=porcelain --no-prefix --pretty='%H%n%at\t%an\t%w(0,0,1)%B' " + . escapeshellarg($hash); $log = popen($gitcmd, 'r'); -if (!$log or strpos(fgets($log), "commit $hash") !== 0) { +if (!$log or strpos(fgets($log), $hash) !== 0) { $Page->place['warn'] = "Kon inhoud niet ophalen met $gitcmd"; return; } -print '
';
+# read metadata and commit message
+list ($atime, $author, $msg) = explode("\t", fgets($log), 3);
 while ( $line = fgets($log) ) {
-	print htmlspecialchars($line);
+	if ($line == "\n") {
+		fgets($log); // assume another empty line
+		break;
+	}
+	$msg .= substr($line, 1);
 }
-print "
\n"; +# commit head +print '

'; +printf('%s • %s', + htmlspecialchars($author), strftime('%F %H:%M', $atime) +); +print "\n".nl2br(htmlspecialchars($msg)); +print "

\n"; + +print ''; + +# body +$row = $ln = NULL; +$col = ['', '']; +print ''; +while ( $line = fgets($log) ) { + preg_match(isset($ln) ? '/^(\W|\S+ )(.*)/' : '/^(\S+ )(.*)/', $line, $part); + $body = htmlspecialchars($part[2]); + switch ($part[1]) { + case 'diff ': + # file start + if (preg_match('/^--git (.+) (.*)/', $part[2], $diffhead)) { + $row = "$diffhead[1]"; + if ($diffhead[1] !== $diffhead[2]) { + $row .= " → $diffhead[2]"; + } + } + else { + $row = '?'; + } + $ln = NULL; + break; + case '@@ ': + # chunk start + if (preg_match('/^[-](\d+)(?:,\d+)? [+](\d+)(?:,\d+)? @@/', $part[2], $diffstart)) { + array_shift($diffstart); + $ln = $diffstart; + } + else { + $ln = ['?', '?']; # unrecognised diff header + } + print ''."\n"; + break; + case '-': + $col[0] .= "$body"; + break; + case '+': + $col[1] .= "$body"; + break; + case ' ': + $col[0] .= $body; + $col[1] .= $body; + break; + case '~': + # part end + print ''; + foreach ($col as $i => $line) { + if (empty($line)) { + print '%s', + $ln[$i]++, + $col[0] == $col[1] ? '' : ' class="change"', + $line + ); + } + print "\n"; + $col = ['', '']; + break; + } +} +print "
'.$row.'
'; + continue; + } + printf('%s
\n"; pclose($log); + return; -- 2.30.0