repository.rs

 1use anyhow::Result;
 2use collections::HashMap;
 3use parking_lot::Mutex;
 4use std::{
 5    path::{Path, PathBuf},
 6    sync::Arc,
 7};
 8
 9pub use git2::Repository as LibGitRepository;
10
11#[async_trait::async_trait]
12pub trait GitRepository: Send {
13    fn load_head_text(&self, relative_file_path: &Path) -> Option<String>;
14}
15
16#[async_trait::async_trait]
17impl GitRepository for LibGitRepository {
18    fn load_head_text(&self, relative_file_path: &Path) -> Option<String> {
19        fn logic(repo: &LibGitRepository, relative_file_path: &Path) -> Result<Option<String>> {
20            const STAGE_NORMAL: i32 = 0;
21            let index = repo.index()?;
22            let oid = match index.get_path(relative_file_path, STAGE_NORMAL) {
23                Some(entry) => entry.id,
24                None => return Ok(None),
25            };
26
27            let content = repo.find_blob(oid)?.content().to_owned();
28            let head_text = String::from_utf8(content)?;
29            Ok(Some(head_text))
30        }
31
32        match logic(&self, relative_file_path) {
33            Ok(value) => return value,
34            Err(err) => log::error!("Error loading head text: {:?}", err),
35        }
36        None
37    }
38}
39
40#[derive(Debug, Clone, Default)]
41pub struct FakeGitRepository {
42    state: Arc<Mutex<FakeGitRepositoryState>>,
43}
44
45#[derive(Debug, Clone, Default)]
46pub struct FakeGitRepositoryState {
47    pub index_contents: HashMap<PathBuf, String>,
48}
49
50impl FakeGitRepository {
51    pub fn open(state: Arc<Mutex<FakeGitRepositoryState>>) -> Arc<Mutex<dyn GitRepository>> {
52        Arc::new(Mutex::new(FakeGitRepository { state }))
53    }
54}
55
56#[async_trait::async_trait]
57impl GitRepository for FakeGitRepository {
58    fn load_head_text(&self, path: &Path) -> Option<String> {
59        let state = self.state.lock();
60        state.index_contents.get(path).cloned()
61    }
62}