--- /dev/null
+<h3>History</h3>
+
+<ul class="history unstyled">
+{% for commit in repo.getHistory %}
+ <li {% if commit.hash == repo.hash %}class="active"{%endif%}>
+ {% spaceless %}
+ {% for dot in commit.getDots %}
+ <img src="/phorkie/dot-{{dot}}.png" alt="" style="padding-left:1px" width="4" height="4"/>
+ {% endfor %}
+ {% endspaceless %}
+ <a class="hash" href="{{repo.getLink('commit', commit.hash)}}">{{commit.hash|slice(0, 6)}}</a>
+ <img src="{{commit.getIconUrl}}" alt="{{commit.committerName}}" title="{{commit.committerName}}" width="20"/>
+ <span title="{{commit.committerTime|date('c')}}">{{commit.committerTime|date('Y-m-d')}}</span>
+ </li>
+{% else %}
+<p>No commits yet</p>
+{% endfor %}
+</ul>
\ No newline at end of file
*/
public $workDir;
+ /**
+ * Revision of the repository that shall be shown
+ *
+ * @var string
+ */
+ public $hash;
+
+
+
/**
* Load Repository data from GET-Request
*
}
$this->id = (int)$_GET['id'];
$this->loadDirs();
+ $this->loadHash();
}
protected function loadDirs()
$this->workDir = $workDir;
}
+ public function loadHash()
+ {
+ if ($this->hash !== null) {
+ return;
+ }
+
+ $output = $this->getVc()->getCommand('log')
+ ->setOption('pretty', 'format:%H')
+ ->setOption('max-count', 1)
+ ->execute();
+ $output = trim($output);
+ if (strlen($output) !== 40) {
+ throw new Exception(
+ 'Loading commit hash failed: ' . $output
+ );
+ }
+ $this->hash = $output;
+ }
+
public function loadById($id)
{
if (!is_numeric($id)) {
}
$this->id = (int)$id;
$this->loadDirs();
+ $this->loadHash();
}
public function getVc()
* Get a link to the repository
*
* @param string $type Link type. Supported are:
+ * - "commit"
* - "edit"
+ * - "delete"
+ * - "delete-confirm"
* - "display"
* - "fork"
+ * @param string $option
*
* @return string
*/
- public function getLink($type)
+ public function getLink($type, $option = null)
{
if ($type == 'edit') {
return '/' . $this->id . '/edit';
return '/' . $this->id . '/delete';
} else if ($type == 'delete-confirm') {
return '/' . $this->id . '/delete/confirm';
+ } else if ($type == 'commit') {
+ return '/' . $this->id . '/' . $option;
}
throw new Exception('Unknown link type');
}
}
return null;
}
+
+ /**
+ * Returns the history of the repository.
+ * We don't use VersionControl_Git's rev list fetcher since it does not
+ * give us separate email addresses and names, and it does not give us
+ * the amount of changed (added/deleted) lines.
+ *
+ * @return array Array of history objects
+ */
+ public function getHistory()
+ {
+ $output = $this->getVc()->getCommand('log')
+ ->setOption('pretty', 'format:commit %H%n%at%n%an%n%ae')
+ ->setOption('max-count', 10)
+ ->setOption('shortstat')
+ ->execute();
+
+ $arCommits = array();
+ $arOutput = explode("\n", $output);
+ $lines = count($arOutput);
+ $current = 0;
+ while ($current < $lines) {
+ $commit = new Repository_Commit();
+ list($name,$commit->hash) = explode(' ', $arOutput[$current]);
+ if ($name !== 'commit') {
+ throw new Exception(
+ 'Git log output format not as expected: ' . $arOutput[$current]
+ );
+ }
+ $commit->committerTime = $arOutput[$current + 1];
+ $commit->committerName = $arOutput[$current + 2];
+ $commit->committerEmail = $arOutput[$current + 3];
+
+ $arLineParts = explode(' ', trim($arOutput[$current + 4]));
+ $commit->filesChanged = $arLineParts[0];
+ $commit->linesAdded = $arLineParts[3];
+ $commit->linesDeleted = $arLineParts[5];
+
+ $current += 6;
+
+ $arCommits[] = $commit;
+ }
+
+ return $arCommits;
+ }
}
?>
--- /dev/null
+<?php
+namespace phorkie;
+
+
+class Repository_Commit
+{
+ public $hash;
+ public $committerName;
+ public $committerEmail;
+ public $committerTime;
+
+ public $linesAdded;
+ public $linesDeleted;
+ public $filesChanged;
+
+
+ public function getIconUrl()
+ {
+ //workaround for https://pear.php.net/bugs/bug.php?id=19384
+ require_once 'PEAR/Services/Libravatar.php';
+
+ $s = new \Services_Libravatar();
+ return $s->url('cweiske@cweiske.de'/*$this->committerEmail*/, array('s' => 32));
+ }
+
+ /**
+ * @return array Array with 7 fields, each has either "r", "g" or "n"
+ * ("red", "green" or "none")
+ */
+ public function getDots()
+ {
+ $r = $this->getDotNum($this->linesDeleted);
+ $g = $this->getDotNum($this->linesAdded);
+ $sum = $r + $g;
+ if ($sum > 7) {
+ $quot = ceil($sum / 7);
+ $r = int($r / $quot);
+ $g = int($g / $quot);
+ }
+ $string = str_repeat('g', $g) . str_repeat('r', $r) . str_repeat('n', 7 - $g - $r);
+
+ return str_split($string);
+ }
+
+ public function getDotNum($lines)
+ {
+ if ($lines == 0) {
+ return 0;
+ } else if ($lines == 1) {
+ return 1;
+ } else if ($lines == 2) {
+ return 2;
+ } else if ($lines == 3) {
+ return 3;
+ } else if ($lines == 4) {
+ return 4;
+ } else if ($lines < 10) {
+ return 5;
+ } else if ($lines < 50) {
+ return 6;
+ }
+ return 7;
+ }
+}
+
+?>
\ No newline at end of file