02d8172
use std::collections::HashMap;
use crate::rpcgit::commit::types::TreeEntryMode;
use serde::{Deserialize, Serialize};
use crate::context::facade::GitContext;
use crate::service::GitService;
use crate::service::cache::{self, IMMUTABLE_TTL};
use crate::share::errors::{GitError, map_baby};
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct SubmoduleDto {
pub path: String,
pub url: String,
pub branch: Option<String>,
pub commit_sha: Option<String>,
}
impl GitService {
pub async fn submodule_list(
&self,
ctx: &GitContext,
revision: String,
) -> Result<Vec<SubmoduleDto>, GitError> {
let baby = self.baby(&ctx);
let rev_oid = baby.rev_parse(&revision).await.map_err(map_baby)?;
let key = format!("repo.{}.submodules.{}", ctx.model.id, rev_oid);
cache::cached_fetch(&ctx.cache, &key, IMMUTABLE_TTL, || async {
let entries = baby
.get_tree_entries(&revision, std::path::Path::new(""))
.await
.map_err(map_baby)?;
let mut meta: HashMap<String, (String, String)> = HashMap::new();
if let Ok(submodules) = baby.list_submodules(&revision).await {
for s in submodules {
meta.insert(s.path.clone(), (s.url.clone(), s.branch.clone()));
}
}
let mut out = Vec::new();
for e in entries {
if e.mode == TreeEntryMode::Submodule {
let (url, branch) = meta.get(&e.name).cloned().unwrap_or_default();
out.push(SubmoduleDto {
path: e.name.clone(),
url,
branch: Some(branch).filter(|b| !b.is_empty()),
commit_sha: Some(e.oid.to_string()),
});
}
}
Ok(out)
})
.await
}
pub async fn submodule_resolve(
&self,
ctx: &GitContext,
revision: String,
path: String,
) -> Result<String, GitError> {
let baby = self.baby(&ctx);
let rev_oid = baby.rev_parse(&revision).await.map_err(map_baby)?;
let key = format!(
"repo.{}.submodule_resolve.{}.{}",
ctx.model.id, rev_oid, path
);
cache::cached_fetch(&ctx.cache, &key, IMMUTABLE_TTL, || async {
let entries = baby
.get_tree_entries(&revision, std::path::Path::new(""))
.await
.map_err(map_baby)?;
entries
.into_iter()
.find(|e| e.name == path && e.mode == TreeEntryMode::Submodule)
.map(|e| e.oid.to_string())
.ok_or(GitError::NotFound)
})
.await
}
}