Implement repository log page
Diff
src/git.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
src/methods/repo.rs | 13 +++++++++++--
templates/repo/log.html | 22 ++++++++++++++++++++++
3 files changed, 87 insertions(+), 33 deletions(-)
@@ -7,7 +7,7 @@
};
use arc_swap::ArcSwapOption;
use git2::{Oid, Repository, Signature};
use git2::{Oid, Repository, Signature, Sort};
use time::OffsetDateTime;
pub type RepositoryMetadataList = BTreeMap<Option<String>, Vec<RepositoryMetadata>>;
@@ -52,38 +52,38 @@
pub async fn get_refs<'a>(&'a self, repo: PathBuf) -> Arc<Refs> {
self.refs
.get_with(repo.clone(), async {
tokio::task::spawn_blocking(move || {
let repo = git2::Repository::open_bare(repo).unwrap();
let refs = repo.references().unwrap();
let mut built_refs = Refs::default();
for ref_ in refs {
let ref_ = ref_.unwrap();
if ref_.is_branch() {
let commit = ref_.peel_to_commit().unwrap();
built_refs.branch.push(Branch {
name: ref_.shorthand().unwrap().to_string(),
commit: commit.into(),
});
} else if ref_.is_tag() {
let commit = ref_.peel_to_commit().unwrap();
built_refs.tag.push(Tag {
name: ref_.shorthand().unwrap().to_string(),
commit: commit.into(),
});
tokio::task::spawn_blocking(move || {
let repo = git2::Repository::open_bare(repo).unwrap();
let refs = repo.references().unwrap();
let mut built_refs = Refs::default();
for ref_ in refs {
let ref_ = ref_.unwrap();
if ref_.is_branch() {
let commit = ref_.peel_to_commit().unwrap();
built_refs.branch.push(Branch {
name: ref_.shorthand().unwrap().to_string(),
commit: commit.into(),
});
} else if ref_.is_tag() {
let commit = ref_.peel_to_commit().unwrap();
built_refs.tag.push(Tag {
name: ref_.shorthand().unwrap().to_string(),
commit: commit.into(),
});
}
}
}
Arc::new(built_refs)
Arc::new(built_refs)
})
.await
.unwrap()
})
.await
.unwrap()
})
.await
}
pub async fn get_readme(&self, repo: PathBuf) -> Arc<str> {
@@ -95,7 +95,11 @@
let commit = head.peel_to_commit().unwrap();
let tree = commit.tree().unwrap();
let object = tree.get_name("README.md").unwrap().to_object(&repo).unwrap();
let object = tree
.get_name("README.md")
.unwrap()
.to_object(&repo)
.unwrap();
let blob = object.into_blob().unwrap();
Arc::from(String::from_utf8(blob.content().to_vec()).unwrap())
@@ -137,6 +141,27 @@
self.repository_metadata.store(Some(repos.clone()));
repos
}
pub async fn get_commits(&self, repo: PathBuf) -> Vec<Commit> {
tokio::task::spawn_blocking(move || {
let repo = Repository::open_bare(repo).unwrap();
let mut revs = repo.revwalk().unwrap();
revs.set_sorting(Sort::TIME).unwrap();
revs.push_head().unwrap();
let mut commits = Vec::with_capacity(200);
for rev in revs.skip(0).take(200) {
let rev = rev.unwrap();
let commit = repo.find_commit(rev).unwrap();
commits.push(commit.into());
}
commits
})
.await
.unwrap()
}
}
@@ -16,8 +16,8 @@
use serde::Deserialize;
use tower::{util::BoxCloneService, Service};
use crate::{git::Commit, layers::UnwrapInfallible, Git};
use crate::git::Refs;
use crate::{git::Commit, layers::UnwrapInfallible, Git};
#[derive(Clone)]
pub struct Repository(pub PathBuf);
@@ -90,14 +90,21 @@
}
#[allow(clippy::unused_async)]
pub async fn handle_log(Extension(repo): Extension<Repository>) -> Html<String> {
pub async fn handle_log(
Extension(repo): Extension<Repository>,
Extension(RepositoryPath(repository_path)): Extension<RepositoryPath>,
Extension(git): Extension<Git>,
) -> Html<String> {
#[derive(Template)]
#[template(path = "repo/log.html")]
pub struct View {
repo: Repository,
commits: Vec<Commit>,
}
Html(View { repo }.render().unwrap())
let commits = git.get_commits(repository_path).await;
Html(View { repo, commits }.render().unwrap())
}
#[allow(clippy::unused_async)]
@@ -1,6 +1,28 @@
{% extends "repo/base.html" %}
{% block log_nav_class %}active{% endblock %}
{% block content %}
<table class="repositories">
<thead>
<tr>
<th>Age</th>
<th>Commit message</th>
<th>Author</th>
</tr>
</thead>
<tbody>
{% for commit in commits %}
<tr>
<td>{{ commit.committer().time() }}</td>
<td><a href="/{{ repo.display() }}/commit/?id={{ commit.oid() }}">{{ commit.summary() }}</a></td>
<td>
<img src="https://www.gravatar.com/avatar/{{ commit.author().email_md5() }}?s=13&d=retro" width="13" height="13">
{{ commit.author().name() }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}