From 755876c268f288e104abd126ee7c2c3e8ac4fcb3 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sun, 29 Sep 2024 13:44:31 +0400 Subject: [PATCH] Add support for submodules --- src/git.rs | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- templates/repo/tree.html | 6 ++++++ 2 files changed, 77 insertions(+), 30 deletions(-) diff --git a/src/git.rs b/src/git.rs index b091838..67eda1b 100644 --- a/src/git.rs +++ a/src/git.rs @@ -1,15 +1,3 @@ -use std::{ - borrow::Cow, - collections::VecDeque, - ffi::OsStr, - fmt::{self, Arguments, Write}, - io::ErrorKind, - path::{Path, PathBuf}, - str::FromStr, - sync::Arc, - time::Duration, -}; - use anyhow::{anyhow, Context, Result}; use axum::response::IntoResponse; use bytes::{buf::Writer, BufMut, Bytes, BytesMut}; @@ -19,13 +7,26 @@ actor::SignatureRef, bstr::{BStr, BString, ByteSlice, ByteVec}, diff::blob::{platform::prepare_diff::Operation, Sink}, + object::tree::EntryKind, object::Kind, objs::tree::EntryRef, prelude::TreeEntryRefExt, traverse::tree::visit::Action, - ObjectId, ThreadSafeRepository, + url::Scheme, + ObjectId, ThreadSafeRepository, Url, }; use moka::future::Cache; +use std::{ + borrow::Cow, + collections::{BTreeMap, VecDeque}, + ffi::OsStr, + fmt::{self, Arguments, Write}, + io::ErrorKind, + path::{Path, PathBuf}, + str::FromStr, + sync::Arc, + time::Duration, +}; use tar::Builder; use time::{OffsetDateTime, UtcOffset}; use tracing::{error, instrument, warn}; @@ -106,6 +107,7 @@ } impl OpenRepository { + #[allow(clippy::too_many_lines)] pub async fn path( self: Arc, path: Option, @@ -182,32 +184,62 @@ } let mut tree_items = Vec::new(); + let submodules = repo + .submodules()? + .into_iter() + .flatten() + .filter_map(|v| Some((v.name().to_path_lossy().to_path_buf(), v.url().ok()?))) + .collect::>(); for item in tree.iter() { let item = item?; - let object = item - .object() - .context("Expected item in tree to be object but it wasn't")?; let path = path .clone() .unwrap_or_default() .join(item.filename().to_path_lossy()); + + match item.mode().kind() { + EntryKind::Tree + | EntryKind::Blob + | EntryKind::BlobExecutable + | EntryKind::Link => { + let object = item + .object() + .context("Expected item in tree to be object but it wasn't")?; + + tree_items.push(match object.kind { + Kind::Blob => TreeItem::File(File { + mode: item.mode().0, + size: object.into_blob().data.len(), + path, + name: item.filename().to_string(), + }), + Kind::Tree => TreeItem::Tree(Tree { + mode: item.mode().0, + path, + name: item.filename().to_string(), + }), + _ => continue, + }); + } + EntryKind::Commit => { + if let Some(mut url) = submodules.get(path.as_path()).cloned() { + if matches!(url.scheme, Scheme::Git | Scheme::Ssh) { + url.scheme = Scheme::Https; + } + + tree_items.push(TreeItem::Submodule(Submodule { + mode: item.mode().0, + name: item.filename().to_string(), + url, + oid: item.object_id(), + })); - tree_items.push(match object.kind { - Kind::Blob => TreeItem::File(File { - mode: item.mode().0, - size: object.into_blob().data.len(), - path, - name: item.filename().to_string(), - }), - Kind::Tree => TreeItem::Tree(Tree { - mode: item.mode().0, - path, - name: item.filename().to_string(), - }), - _ => continue, - }); + continue; + } + } + } } Ok(PathDestination::Tree(tree_items)) @@ -561,6 +593,15 @@ pub enum TreeItem { Tree(Tree), File(File), + Submodule(Submodule), +} + +#[derive(Debug)] +pub struct Submodule { + pub mode: u16, + pub name: String, + pub url: Url, + pub oid: ObjectId, } #[derive(Debug)] diff --git a/templates/repo/tree.html b/templates/repo/tree.html index a17b137..faa1be6 100644 --- a/templates/repo/tree.html +++ a/templates/repo/tree.html @@ -28,6 +28,12 @@
{{ file.name }}
{{ file.size }}
+ + {%- when crate::git::TreeItem::Submodule with (submodule) -%} +
{{ submodule.mode|file_perms }}
+
🔗 {{ submodule.name }} @ {{ submodule.oid.to_hex_with_len(7) }}
+ + {%- endmatch %} {% endfor -%} -- rgit 0.1.3