show history in sidebar
authorChristian Weiske <cweiske@cweiske.de>
Tue, 17 Apr 2012 07:37:39 +0000 (09:37 +0200)
committerChristian Weiske <cweiske@cweiske.de>
Tue, 17 Apr 2012 07:37:39 +0000 (09:37 +0200)
data/templates/display-sidebar-history.htm [new file with mode: 0644]
data/templates/display.htm
src/phorkie/Repository.php
src/phorkie/Repository/Commit.php [new file with mode: 0644]
www/phorkie.css
www/phorkie/dot-g.png [new file with mode: 0644]
www/phorkie/dot-n.png [new file with mode: 0644]
www/phorkie/dot-r.png [new file with mode: 0644]

diff --git a/data/templates/display-sidebar-history.htm b/data/templates/display-sidebar-history.htm
new file mode 100644 (file)
index 0000000..627420b
--- /dev/null
@@ -0,0 +1,18 @@
+<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
index e021296..847a8ea 100644 (file)
@@ -18,5 +18,5 @@
 {% endblock %}
 
 {% block sidebar %}
-sidebar FIXME
+ {% include 'display-sidebar-history.htm' %}
 {% endblock %}
index 1a55af8..aa1ea4c 100644 (file)
@@ -26,6 +26,15 @@ class Repository
     public $workDir;
 
     /**
+     * Revision of the repository that shall be shown
+     *
+     * @var string
+     */
+    public $hash;
+
+
+
+    /**
      * Load Repository data from GET-Request
      *
      * @return void
@@ -42,6 +51,7 @@ class Repository
         }
         $this->id = (int)$_GET['id'];
         $this->loadDirs();
+        $this->loadHash();
     }
 
     protected function loadDirs()
@@ -63,6 +73,25 @@ class Repository
         $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)) {
@@ -70,6 +99,7 @@ class Repository
         }
         $this->id = (int)$id;
         $this->loadDirs();
+        $this->loadHash();
     }
 
     public function getVc()
@@ -147,13 +177,17 @@ class Repository
      * 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';
@@ -165,6 +199,8 @@ class Repository
             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');
     }
@@ -177,6 +213,51 @@ class Repository
         }
         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;
+    }
 }
 
 ?>
diff --git a/src/phorkie/Repository/Commit.php b/src/phorkie/Repository/Commit.php
new file mode 100644 (file)
index 0000000..ec4a04a
--- /dev/null
@@ -0,0 +1,66 @@
+<?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
index b59f54c..60bf8ff 100644 (file)
@@ -59,6 +59,18 @@ div.annotations div.alert {
     margin-bottom: 1ex;
 }
 
+ul.history li {
+    padding-left: 2px;
+    padding-bottom: 1px;
+}
+ul.history li.active {
+    background-color: #EEE;
+    border-radius: 3px;
+}
+ul.history a.hash {
+    font-family: monospace;
+}
+
 
 ul.pager {
     margin-top: 2ex;
diff --git a/www/phorkie/dot-g.png b/www/phorkie/dot-g.png
new file mode 100644 (file)
index 0000000..7de3e70
Binary files /dev/null and b/www/phorkie/dot-g.png differ
diff --git a/www/phorkie/dot-n.png b/www/phorkie/dot-n.png
new file mode 100644 (file)
index 0000000..8aaec05
Binary files /dev/null and b/www/phorkie/dot-n.png differ
diff --git a/www/phorkie/dot-r.png b/www/phorkie/dot-r.png
new file mode 100644 (file)
index 0000000..9388421
Binary files /dev/null and b/www/phorkie/dot-r.png differ