summaryrefslogtreecommitdiff
path: root/server/common/src/git.rs
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@spawned.biz>2025-06-09 00:55:34 +0200
committerJoel Klinghed <the_jk@spawned.biz>2025-06-09 00:55:34 +0200
commit7311e02c89b66849f5e660b690ca69b5e8fd1383 (patch)
treefd1c2cb8f67fcb6b7fc6a82473f2d8e56acb7231 /server/common/src/git.rs
parenta7c04b3720318834bdbba1e9149e7d373516b0f6 (diff)
git: Add ls-tree
Diffstat (limited to 'server/common/src/git.rs')
-rw-r--r--server/common/src/git.rs68
1 files changed, 68 insertions, 0 deletions
diff --git a/server/common/src/git.rs b/server/common/src/git.rs
index c6a44e3..053ff3f 100644
--- a/server/common/src/git.rs
+++ b/server/common/src/git.rs
@@ -64,6 +64,20 @@ pub struct User {
pub username: String,
}
+#[derive(Debug, PartialEq)]
+pub enum ObjectType {
+ BLOB,
+ COMMIT,
+ TREE,
+}
+
+#[derive(Debug, PartialEq)]
+pub struct TreeEntry {
+ pub object_type: ObjectType,
+ pub object_name: String,
+ pub path: String,
+}
+
fn io_err(action: &str, e: std::io::Error) -> Error {
Error::new(format!("{action}: {e}"))
}
@@ -80,6 +94,34 @@ fn parse_user(output: String) -> User {
}
}
+fn parse_tree_entries(output: String) -> Vec<TreeEntry> {
+ let mut ret = Vec::new();
+ for line in output.split_terminator('\0') {
+ let mut parts = line.split_terminator('\t');
+ let mut parts2 = parts.next().unwrap_or("").split_terminator(' ');
+ parts2.next(); // object mode
+ let object_type = match parts2.next() {
+ Some(value) => match value {
+ "blob" => ObjectType::BLOB,
+ "commit" => ObjectType::COMMIT,
+ "tree" => ObjectType::TREE,
+ _ => continue,
+ },
+ None => continue,
+ };
+ if let Some(object_name) = parts2.next() {
+ if let Some(path) = parts.next() {
+ ret.push(TreeEntry {
+ object_type,
+ object_name: object_name.to_string(),
+ path: path.to_string(),
+ });
+ }
+ }
+ }
+ ret
+}
+
impl RepoData {
fn new() -> Self {
Self {
@@ -342,6 +384,21 @@ impl RepoData {
self.run(&mut cmd).await
}
+ async fn ls_tree(
+ &self,
+ repo: &Repository,
+ commit: &str,
+ recursive: bool,
+ ) -> Result<Vec<TreeEntry>, Error> {
+ let mut cmd = self.git_cmd(repo);
+ cmd.arg("ls-tree").arg("-z");
+ if recursive {
+ cmd.arg("-r");
+ }
+ cmd.arg(commit);
+ self.output(&mut cmd).map_ok(parse_tree_entries).await
+ }
+
async fn get_log_format(
&self,
repo: &Repository,
@@ -594,4 +651,15 @@ impl Repository {
data.delete_branch(self, branch.as_str()).await
}
+
+ pub async fn ls_tree(
+ &self,
+ commit: impl Into<String>,
+ recursive: bool,
+ ) -> Result<Vec<TreeEntry>, Error> {
+ let commit = commit.into();
+ let data = self.lock.read().await;
+
+ data.ls_tree(self, commit.as_str(), recursive).await
+ }
}