From e49c69da2e53c8938f4d58bd478bb68f060e3849 Mon Sep 17 00:00:00 2001
From: Alberto Bertogli <albertito@blitiri.com.ar>
Date: Sat, 2 Nov 2013 22:18:33 +0000
Subject: [PATCH 7/9] Show the age of a repository in the index, via javascript

This patch adds the age of the repository to the index view, using javascript
to give a nice human string for the age.

When javascript is not available, the element remains hidden.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
---
 git-arr            |    2 +
 git.py             |   13 ++++++++++-
 static/git-arr.css |   20 ++++++++++++++++
 static/git-arr.js  |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 views/index.html   |    4 ++-
 5 files changed, 100 insertions(+), 2 deletions(-)
 create mode 100644 static/git-arr.js

diff --git a/git-arr b/git-arr
index bc5716d..2a23128 100755
--- a/git-arr
+++ b/git-arr
@@ -352,6 +352,8 @@ def generate(output, skip_index = False):
     read_f = lambda f: open(f).read()
     write_to('static/git-arr.css', read_f, [static_path + '/git-arr.css'],
             os.stat(static_path + '/git-arr.css').st_mtime)
+    write_to('static/git-arr.js', read_f, [static_path + '/git-arr.js'],
+            os.stat(static_path + '/git-arr.js').st_mtime)
     write_to('static/syntax.css', read_f, [static_path + '/syntax.css'],
             os.stat(static_path + '/syntax.css').st_mtime)
 
diff --git a/git.py b/git.py
index deddeba..7e7ad74 100644
--- a/git.py
+++ b/git.py
@@ -207,11 +207,13 @@ class Repo:
         """Returns a GitCommand() on our path."""
         return GitCommand(self.path, cmd)
 
-    def for_each_ref(self, pattern = None, sort = None):
+    def for_each_ref(self, pattern = None, sort = None, count = None):
         """Returns a list of references."""
         cmd = self.cmd('for-each-ref')
         if sort:
             cmd.sort = sort
+        if count:
+            cmd.count = count
         if pattern:
             cmd.arg(pattern)
 
@@ -347,6 +349,15 @@ class Repo:
 
         return out.read()
 
+    def last_commit_timestamp(self):
+        """Return the timestamp of the last commit."""
+        refs = self.for_each_ref(pattern = 'refs/heads/',
+                sort = '-committerdate', count = 1)
+        for obj_id, _, _ in refs:
+            commit = self.commit(obj_id)
+            return commit.committer_epoch
+        return -1
+
 
 class Commit (object):
     """A git commit."""
diff --git a/static/git-arr.css b/static/git-arr.css
index 2e28c69..8da2b67 100644
--- a/static/git-arr.css
+++ b/static/git-arr.css
@@ -100,6 +100,26 @@ span.tag {
     background-color: #ffff88;
 }
 
+/* Age of an object.
+ * Note this is hidden by default as we rely on javascript to show it. */
+span.age {
+    display: none;
+    color: gray;
+    font-size: x-small;
+}
+
+span.age-band0 {
+    color: darkgreen;
+}
+
+span.age-band1 {
+    color: green;
+}
+
+span.age-band2 {
+    color: seagreen;
+}
+
 /* Commit message and diff. */
 pre.commit-message {
     font-size: large;
diff --git a/static/git-arr.js b/static/git-arr.js
new file mode 100644
index 0000000..d1e3b81
--- /dev/null
+++ b/static/git-arr.js
@@ -0,0 +1,63 @@
+/* Miscellaneous javascript functions for git-arr. */
+
+/* Return the current timestamp. */
+function now() {
+    return (new Date().getTime() / 1000);
+}
+
+/* Return a human readable string telling "how long ago" for a timestamp. */
+function how_long_ago(timestamp) {
+    if (timestamp < 0)
+        return "never";
+
+	var seconds = Math.floor(now() - timestamp);
+
+	var interval = Math.floor(seconds / (365 * 24 * 60 * 60));
+	if (interval > 1)
+		return interval + " years ago";
+
+	interval = Math.floor(seconds / (30 * 24 * 60 * 60));
+	if (interval > 1)
+		return interval + " months ago";
+
+	interval = Math.floor(seconds / (24 * 60 * 60));
+
+	if (interval > 1)
+		return interval + " days ago";
+	interval = Math.floor(seconds / (60 * 60));
+
+	if (interval > 1)
+		return interval + " hours ago";
+
+	interval = Math.floor(seconds / 60);
+	if (interval > 1)
+		return interval + " minutes ago";
+
+    if (seconds > 1)
+        return Math.floor(seconds) + " seconds ago";
+
+    return "about now";
+}
+
+/* Go through the document and replace the contents of the span.age elements
+ * with a human-friendly variant, and then show them. */
+function replace_timestamps() {
+    var elements = document.getElementsByClassName("age");
+    for (var i = 0; i < elements.length; i++) {
+        var e = elements[i];
+
+        var timestamp = e.innerHTML;
+        e.innerHTML = how_long_ago(timestamp);
+        e.style.display = "inline";
+
+        if (timestamp > 0) {
+            var age = now() - timestamp;
+            if (age < (2 * 60 * 60))
+                e.className = e.className + " age-band0";
+            else if (age < (3 * 24 * 60 * 60))
+                e.className = e.className + " age-band1";
+            else if (age < (30 * 24 * 60 * 60))
+                e.className = e.className + " age-band2";
+        }
+    }
+}
diff --git a/views/index.html b/views/index.html
index b218b8b..7967a7c 100644
--- a/views/index.html
+++ b/views/index.html
@@ -5,9 +5,10 @@
 <title>git</title>
 <link rel="stylesheet" type="text/css" href="static/git-arr.css"/>
 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<script src="static/git-arr.js"></script>
 </head>
 
-<body class="index">
+<body class="index" onload="replace_timestamps()">
 <h1>git</h1>
 
 <table class="nice">
@@ -20,6 +21,7 @@
     <tr>
         <td><a href="r/{{repo.name}}/">{{repo.name}}</a></td>
         <td><a href="r/{{repo.name}}/">{{repo.info.desc}}</a></td>
+        <td><span class="age">{{repo.last_commit_timestamp()}}</span></td>
     </tr>
     %end
 </table>
-- 
1.6.2.2.646.gb214

