2687ace
use std::path::Path;
use crate::GitBaby;
use crate::error::BabyError;
use crate::share;
use crate::submodule::helper;
use crate::submodule::types::SubModule;
async fn read_blob_at_revision(
gitbaby: &GitBaby,
commit: &str,
blob_path: &str,
) -> Result<Option<Vec<u8>>, BabyError> {
share::validate_revision(commit)?;
share::validate_local_no_escape(Path::new(blob_path))?;
let dir = gitbaby
.facade
.git_repo_dir()
.await
.map_err(share::facade_error)?;
let alternates = gitbaby
.facade
.git_alternate_object_directories()
.await
.map_err(share::facade_error)?;
let env = share::build_env_safe(&alternates);
let args = vec![
"cat-file".to_string(),
"blob".to_string(),
"--end-of-options".to_string(),
format!("{}:{}", commit, blob_path),
];
let mut cmd = share::git_cmd("gitbaby::submodule", &dir, env, None, args);
match cmd.run().await {
Ok(output) => {
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
if stderr.contains("not a tree")
|| stderr.contains("does not exist")
|| stderr.contains("bad revision")
|| stderr.contains("could not read")
{
return Ok(None);
}
return Err(BabyError::SubModuleParse {
line: 0,
reason: format!("cat-file blob failed: {}", stderr.trim()),
});
}
Ok(Some(output.stdout))
}
Err(crate::command::error::CmdError::NonZeroExit { stderr, .. }) => {
if stderr.contains("not a tree")
|| stderr.contains("does not exist")
|| stderr.contains("bad revision")
|| stderr.contains("could not read")
{
Ok(None)
} else {
Err(BabyError::SubModuleParse {
line: 0,
reason: format!("cat-file blob failed: {}", stderr.trim()),
})
}
}
Err(e) => Err(BabyError::from(e)),
}
}
impl GitBaby {
pub async fn list_submodules(&self, commit: &str) -> Result<Vec<SubModule>, BabyError> {
share::validate_revision_non_empty(commit)?;
match read_blob_at_revision(self, commit, ".gitmodules").await? {
Some(bytes) => helper::parse_blob_to_submodules(&bytes),
None => Ok(Vec::new()),
}
}
pub async fn get_submodule(
&self,
commit: &str,
name: &str,
) -> Result<Option<SubModule>, BabyError> {
share::validate_revision_non_empty(commit)?;
if name.is_empty() {
return Err(BabyError::Custom(
"submodule name must not be empty".to_string(),
));
}
let subs = self.list_submodules(commit).await?;
Ok(helper::lookup(&subs, name).cloned())
}
}
fn _unused(_p: &Path) {}