diff --git a/src/GitList/Git/Repository.php b/src/GitList/Git/Repository.php index 50d1f37..32ae329 100644 --- a/src/GitList/Git/Repository.php +++ b/src/GitList/Git/Repository.php @@ -26,10 +26,12 @@ class Repository extends BaseRepository $data = $format->parse($logs[0]); $commit = new Commit; $commit->importData($data[0]); - unset($logs[0]); - if (empty($logs[1])) { - $logs = explode("\n", $this->getClient()->run($this, 'diff ' . $commitHash . '~1..' . $commitHash)); + if ($commit->getParentsHash()) { + $command = 'diff ' . $commitHash . '~1..' . $commitHash; + $logs = explode("\n", $this->getClient()->run($this, $command)); + } else { + $logs = array_slice($logs, 1); } $commit->setDiffs($this->readDiffLogs($logs)); @@ -37,6 +39,89 @@ class Repository extends BaseRepository return $commit; } + /** + * Read diff logs and generate a collection of diffs + * + * @param array $logs Array of log rows + * @return array Array of diffs + */ + public function readDiffLogs(array $logs) + { + $diffs = array(); + $lineNumOld = 0; + $lineNumNew = 0; + foreach ($logs as $log) { + if ('diff' === substr($log, 0, 4)) { + if (isset($diff)) { + $diffs[] = $diff; + } + + $diff = new Diff; + if (preg_match('/^diff --[\S]+ a\/?(.+) b\/?/', $log, $name)) { + $diff->setFile($name[1]); + } + continue; + } + + if ('index' === substr($log, 0, 5)) { + $diff->setIndex($log); + continue; + } + + if ('---' === substr($log, 0, 3)) { + $diff->setOld($log); + continue; + } + + if ('+++' === substr($log, 0, 3)) { + $diff->setNew($log); + continue; + } + + // Handle binary files properly. + if ('Binary' === substr($log, 0, 6)) { + $m = array(); + if (preg_match('/Binary files (.+) and (.+) differ/', $log, $m)) { + $diff->setOld($m[1]); + $diff->setNew(" {$m[2]}"); + } + } + + if (!empty($log)) { + switch ($log[0]) { + case "@": + // Set the line numbers + preg_match('/@@ -([0-9]+)/', $log, $matches); + $lineNumOld = $matches[1] - 1; + $lineNumNew = $matches[1] - 1; + break; + case "-": + $lineNumOld++; + break; + case "+": + $lineNumNew++; + break; + default: + $lineNumOld++; + $lineNumNew++; + } + } else { + $lineNumOld++; + $lineNumNew++; + } + + if (isset($diff)) { + $diff->addLine($log, $lineNumOld, $lineNumNew); + } + } + + if (isset($diff)) { + $diffs[] = $diff; + } + + return $diffs; + } + /** * Show the repository commit log with pagination *