135 lines
3.2 KiB
Rust
135 lines
3.2 KiB
Rust
use std::time::Duration;
|
|
|
|
use juniper::graphql_object;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::{
|
|
cmd::{
|
|
oid::ObjectId,
|
|
tree::{TreeEntry, TreeInfo, TreeKind},
|
|
},
|
|
graphql::{
|
|
GraphqlContext,
|
|
cache_helper::{IMMUTABLE_TTL, cache_key, cached_json},
|
|
},
|
|
};
|
|
|
|
const TREE_TTL: Duration = IMMUTABLE_TTL;
|
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
pub struct TreeInfoGql {
|
|
pub oid: String,
|
|
pub entry_count: i32,
|
|
pub is_empty: bool,
|
|
}
|
|
|
|
#[graphql_object(context = GraphqlContext)]
|
|
impl TreeInfoGql {
|
|
fn oid(&self) -> &str {
|
|
&self.oid
|
|
}
|
|
fn entry_count(&self) -> i32 {
|
|
self.entry_count
|
|
}
|
|
fn is_empty(&self) -> bool {
|
|
self.is_empty
|
|
}
|
|
}
|
|
|
|
impl From<TreeInfo> for TreeInfoGql {
|
|
fn from(info: TreeInfo) -> Self {
|
|
TreeInfoGql {
|
|
oid: info.oid.0,
|
|
entry_count: info.entry_count as i32,
|
|
is_empty: info.is_empty,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
pub struct TreeEntryGql {
|
|
pub name: String,
|
|
pub oid: String,
|
|
pub kind: String,
|
|
pub filemode: i32,
|
|
pub is_binary: bool,
|
|
pub is_lfs: bool,
|
|
}
|
|
|
|
#[graphql_object(context = GraphqlContext)]
|
|
impl TreeEntryGql {
|
|
fn name(&self) -> &str {
|
|
&self.name
|
|
}
|
|
fn oid(&self) -> &str {
|
|
&self.oid
|
|
}
|
|
fn kind(&self) -> &str {
|
|
&self.kind
|
|
}
|
|
fn filemode(&self) -> i32 {
|
|
self.filemode
|
|
}
|
|
fn is_binary(&self) -> bool {
|
|
self.is_binary
|
|
}
|
|
fn is_lfs(&self) -> bool {
|
|
self.is_lfs
|
|
}
|
|
}
|
|
|
|
impl From<TreeEntry> for TreeEntryGql {
|
|
fn from(entry: TreeEntry) -> Self {
|
|
TreeEntryGql {
|
|
name: entry.name,
|
|
oid: entry.oid.0,
|
|
kind: match entry.kind {
|
|
TreeKind::Blob => "blob".to_string(),
|
|
TreeKind::Tree => "tree".to_string(),
|
|
TreeKind::LfsPointer => "lfs_pointer".to_string(),
|
|
},
|
|
filemode: entry.filemode as i32,
|
|
is_binary: entry.is_binary,
|
|
is_lfs: entry.is_lfs,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn resolve_tree(
|
|
ctx: &GraphqlContext,
|
|
oid: String,
|
|
) -> anyhow::Result<TreeInfoGql> {
|
|
let key = cache_key("query:git:tree", &[&oid]);
|
|
cached_json(&ctx.cache, &key, TREE_TTL, || {
|
|
let repo = ctx.repo.clone();
|
|
let oid_obj = ObjectId::new(&oid);
|
|
async move {
|
|
let info =
|
|
tokio::task::spawn_blocking(move || repo.resolve_tree(oid_obj))
|
|
.await?
|
|
.map_err(|e| anyhow::anyhow!(e))?;
|
|
Ok(TreeInfoGql::from(info))
|
|
}
|
|
})
|
|
.await
|
|
}
|
|
|
|
pub async fn resolve_tree_entries(
|
|
ctx: &GraphqlContext,
|
|
tree_oid: String,
|
|
) -> anyhow::Result<Vec<TreeEntryGql>> {
|
|
let key = cache_key("query:git:tree_entries", &[&tree_oid]);
|
|
cached_json(&ctx.cache, &key, TREE_TTL, || {
|
|
let repo = ctx.repo.clone();
|
|
let oid_obj = ObjectId::new(&tree_oid);
|
|
async move {
|
|
let entries =
|
|
tokio::task::spawn_blocking(move || repo.tree_entries(oid_obj))
|
|
.await?
|
|
.map_err(|e| anyhow::anyhow!(e))?;
|
|
Ok(entries.into_iter().map(TreeEntryGql::from).collect())
|
|
}
|
|
})
|
|
.await
|
|
}
|