From 1761c49ed2374b17d7ede6372e657f063f58a825 Mon Sep 17 00:00:00 2001
From: Tuomas Siipola
Date: Sun, 26 Jan 2020 01:51:05 +0200
Subject: Show last commit on files page

---
 public/style.css     | 39 ++++++++++++++++++++++++++++---------
 src/main.rs          | 27 ++++++++++++++++++--------
 templates/files.html | 54 +++++++++++++++++++++++++++++++++++++---------------
 3 files changed, 88 insertions(+), 32 deletions(-)

diff --git a/public/style.css b/public/style.css
index dad786c..6767f94 100644
--- a/public/style.css
+++ b/public/style.css
@@ -86,25 +86,46 @@ a:hover {
 }
 
 .files {
-    padding: 0;
-    list-style: none;
+    border-collapse: collapse;
+    width: 100%;
 }
 
-.files a {
-    display: block;
+.files thead,
+.file {
+    border-bottom: 1px solid #ddd;
+}
+
+.files thead {
+    text-align: left;
+}
+
+.files th:last-child {
+    text-align: right;
+}
+
+.file a {
+    display: inline-block;
     color: inherit;
-    padding: 0.25rem;
-    border-bottom: 1px solid silver;
 }
 
-.files li:first-child a {
-    border-top: 1px solid silver;
+.files th,
+.file a {
+    padding: 0.25rem 0;
 }
 
-.files img {
+.file img {
     vertical-align: middle;
 }
 
+.file-commit,
+.file-time {
+    color: gray;
+}
+
+.file-time {
+    text-align: right;
+}
+
 .commits {
     padding: 0;
     list-style: none;
diff --git a/src/main.rs b/src/main.rs
index 9081830..afb7fa8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -182,14 +182,14 @@ impl<'a> Commit<'a> {
     }
 }
 
-struct CommitIterator<'a> {
+struct CommitIterator<'a, 'b> {
     repo: &'a git2::Repository,
-    path: Option<&'a str>,
+    path: Option<&'b str>,
     revwalk: git2::Revwalk<'a>,
 }
 
-impl<'a> CommitIterator<'a> {
-    fn new(repo: &'a git2::Repository, oid: git2::Oid, path: Option<&'a str>) -> Self {
+impl<'a, 'b> CommitIterator<'a, 'b> {
+    fn new(repo: &'a git2::Repository, oid: git2::Oid, path: Option<&'b str>) -> Self {
         let mut revwalk = repo.revwalk().unwrap();
         revwalk.push(oid).unwrap();
         Self {
@@ -200,7 +200,7 @@ impl<'a> CommitIterator<'a> {
     }
 }
 
-impl<'a> Iterator for CommitIterator<'a> {
+impl<'a, 'b> Iterator for CommitIterator<'a, 'b> {
     type Item = Commit<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -330,10 +330,11 @@ async fn raw(name: &str, path: &str) -> MyResponse {
         .unwrap())
 }
 
-struct File2 {
+struct File2<'a> {
     id: git2::Oid,
     name: Option<String>,
     dir: bool,
+    commit: Commit<'a>,
 }
 
 #[derive(Template)]
@@ -342,7 +343,7 @@ struct FilesTemplate<'a> {
     tab: Tab,
     repo: &'a RepoMetadata,
     path: &'a str,
-    files: &'a [File2],
+    files: &'a [File2<'a>],
     breadcrumb: &'a [(&'a str, &'a str)],
 }
 
@@ -358,12 +359,19 @@ async fn files(name: &str, parts: &[&str]) -> MyResponse {
     }
 
     let (meta, repo) = find_repo(name)?;
-    let mut tree = repo.head()?.peel_to_tree()?;
+    let object = repo.head()?;
+    let commit = object.peel_to_commit()?;
+    let mut tree = object.peel_to_tree()?;
     if !path.is_empty() {
         tree = repo.find_tree(tree.get_path(&Path::new(&path))?.id())?;
     }
     let mut files = Vec::new();
     for entry in tree.iter() {
+        let file_path = if path.is_empty() {
+            entry.name().unwrap().to_string()
+        } else {
+            format!("{}/{}", path, entry.name().unwrap())
+        };
         files.push(File2 {
             id: entry.id(),
             name: entry.name().map(|s| s.to_string()),
@@ -372,6 +380,9 @@ async fn files(name: &str, parts: &[&str]) -> MyResponse {
             } else {
                 false
             },
+            commit: CommitIterator::new(&repo, commit.id(), Some(&file_path))
+                .next()
+                .unwrap(),
         });
     }
     files.sort_by(|a, b| a.dir.cmp(&b.dir).reverse());
diff --git a/templates/files.html b/templates/files.html
index fab48c3..254e39c 100644
--- a/templates/files.html
+++ b/templates/files.html
@@ -33,19 +33,43 @@
     </ul>
     <a href="/{{ repo.name }}/commits/{% for entry in breadcrumb[1..] %}{{ entry.1 }}{% if !loop.last %}/{% endif %}{% endfor %}">History</a>
   </div>
-  <ul class="files">
-    {% for file in files %}
-      <li>
-        <a href="/{{ repo.name }}/{% if file.dir %}files{% else %}blob{% endif %}/{{ path }}{% if !path.is_empty() %}/{% endif %}{% match file.name %}{% when Some with (name) %}{{ name }}{% when None %}{% endmatch %}">
-          <img src="/{% if file.dir %}folder{% else %}file{% endif %}-solid.svg" width="16px" height="16px">
-          {% match file.name %}
-            {% when Some with (name) %}
-              {{ name }}
-            {% when None %}
-              invalid name
-          {% endmatch %}
-        </a>
-      </li>
-    {% endfor %}
-  </ul>
+  <table class="files">
+    <thead>
+      <tr>
+        <th>Name</th>
+        <th>Last commit</th>
+        <th>Last update</th>
+      </tr>
+    </thead>
+    <tbody>
+      {% for file in files %}
+        <tr class="file">
+          <td class="file-name">
+            <img src="/{% if file.dir %}folder{% else %}file{% endif %}-solid.svg" width="16px" height="16px">
+            <a href="/{{ repo.name }}/{% if file.dir %}files{% else %}blob{% endif %}/{{ path }}{% if !path.is_empty() %}/{% endif %}{% match file.name %}{% when Some with (name) %}{{ name }}{% when None %}{% endmatch %}">
+              {% match file.name %}
+                {% when Some with (name) %}
+                  {{ name }}
+                {% when None %}
+                  invalid name
+              {% endmatch %}
+            </a>
+          </td>
+          <td class="file-commit">
+            <a href="/{{ repo.name }}/commit/{{ file.commit.id }}">
+              {% match file.commit.summary() %}
+                {% when Some with (summary) %}
+                  {{ summary }}
+                {% when None %}
+                  no summary
+              {% endmatch %}
+            </a>
+          </td>
+          <td class="file-time">
+            {{ file.commit.datetime()|relativetime }}
+          </td>
+        </tr>
+      {% endfor %}
+    </tbody>
+  </table>
 {% endblock %}
-- 
cgit v1.1