-
-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy pathgit.rs
More file actions
61 lines (56 loc) · 1.85 KB
/
git.rs
File metadata and controls
61 lines (56 loc) · 1.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use std::{
collections::{hash_map::Entry, HashMap},
path::{Path, PathBuf},
};
use anyhow::{anyhow, Context};
use git2::{Blob, Oid, Repository};
#[derive(Default)]
pub struct Repos(HashMap<PathBuf, Repository>);
impl Repos {
pub fn open(&mut self, path: PathBuf) -> mdbook::errors::Result<&Repository> {
match self.0.entry(path) {
Entry::Occupied(occupied_entry) => Ok(occupied_entry.into_mut()),
Entry::Vacant(vacant_entry) => {
let repo = Repository::open(vacant_entry.key())?;
Ok(vacant_entry.insert(repo))
}
}
}
}
pub fn find_commit_by_msg(repo: &Repository, msg: &str) -> mdbook::errors::Result<Oid> {
let head = repo.head().context("Failed to look up repo HEAD")?;
let mut commit = head
.peel_to_commit()
.context("Failed to get the commit pointed to by HEAD")?;
while !commit
.message()
.ok_or(anyhow!("Non-UTF-8 commit message!?"))?
.strip_prefix(msg)
.is_some_and(|rest| rest.is_empty() || rest.starts_with('\n'))
{
commit = commit
.parent(0)
.context("Failed to find a commit with specified message")?;
}
Ok(commit.id())
}
pub fn get_file<'repos>(
repos: &'repos Repos,
(repo_path, commit_id): &(PathBuf, Oid),
path: &Path,
) -> mdbook::errors::Result<Blob<'repos>> {
let repo = &repos.0[repo_path];
let commit = repo.find_commit(*commit_id).unwrap();
let tree = commit
.tree()
.context("Unable to obtain the commit's tree")?;
let entry = tree
.get_path(path)
.context("Unable to find the specified file")?;
let object = entry
.to_object(repo)
.context("Unable to obtain the file's object in the repo")?;
object
.peel_to_blob()
.context("The specified path is not a file")
}