A better Rust ATProto crate
at main 2.0 kB view raw
1use super::LexiconSource; 2use crate::{fetch::sources::parse_from_index_or_lexicon_file, lexicon::LexiconDoc}; 3use jacquard_common::IntoStatic; 4use miette::{IntoDiagnostic, Result, miette}; 5use std::collections::HashMap; 6use tempfile::TempDir; 7use tokio::process::Command; 8 9#[derive(Debug, Clone)] 10pub struct GitSource { 11 pub repo: String, 12 pub git_ref: Option<String>, 13 pub pattern: String, 14} 15 16impl LexiconSource for GitSource { 17 async fn fetch(&self) -> Result<HashMap<String, LexiconDoc<'_>>> { 18 // Create temp directory for clone 19 let temp_dir = TempDir::new().into_diagnostic()?; 20 let clone_path = temp_dir.path(); 21 22 // Shallow clone 23 let mut clone_cmd = Command::new("git"); 24 clone_cmd.arg("clone").arg("--depth").arg("1"); 25 26 if let Some(ref git_ref) = self.git_ref { 27 clone_cmd.arg("--branch").arg(git_ref); 28 } 29 30 clone_cmd.arg(&self.repo).arg(clone_path); 31 32 let output = clone_cmd.output().await.into_diagnostic()?; 33 34 if !output.status.success() { 35 let stderr = String::from_utf8_lossy(&output.stderr); 36 return Err(miette!("Git clone failed: {}", stderr)); 37 } 38 39 // Find lexicon files matching pattern 40 let mut lexicons = HashMap::new(); 41 42 for entry in glob::glob(&format!("{}/{}", clone_path.display(), self.pattern)) 43 .into_diagnostic()? 44 .filter_map(|e| e.ok()) 45 { 46 if !entry.is_file() { 47 continue; 48 } 49 50 // Try to parse as lexicon 51 let content = tokio::fs::read_to_string(&entry).await.into_diagnostic()?; 52 53 match parse_from_index_or_lexicon_file(&content) { 54 Ok((nsid, doc)) => { 55 let doc = doc.into_static(); 56 lexicons.insert(nsid, doc); 57 } 58 Err(_) => { 59 // Not a lexicon, skip 60 continue; 61 } 62 } 63 } 64 65 Ok(lexicons) 66 } 67}