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