1use std::{env, path::PathBuf, process::Command};
2
3use git2::Repository;
4
5use crate::error::Error;
6
7pub struct RepoContext {
8 pub repo: Repository,
9 pub state_dir: PathBuf,
10}
11
12impl RepoContext {
13 pub fn resolve_rev(&self, refspec: &str) -> Result<String, Error> {
16 let work_dir = self
17 .repo
18 .workdir()
19 .unwrap_or_else(|| self.repo.path())
20 .to_path_buf();
21 let out = Command::new("git")
22 .args(["rev-parse", "--verify", refspec])
23 .current_dir(&work_dir)
24 .output()?;
25 if !out.status.success() {
26 let msg = String::from_utf8_lossy(&out.stderr).trim().to_string();
27 return Err(Error::Validation(msg));
28 }
29 Ok(String::from_utf8_lossy(&out.stdout).trim().to_string())
30 }
31}
32
33pub fn open() -> Result<RepoContext, Error> {
34 let (repo, git_dir) = if let Ok(val) = env::var("GIT_DIR") {
35 let git_dir = PathBuf::from(&val);
36 if !git_dir.join("HEAD").exists() {
37 return Err(Error::Validation(format!(
38 "GIT_DIR '{val}' does not look like a git directory"
39 )));
40 }
41 let repo = Repository::open(&git_dir)?;
42 (repo, git_dir)
43 } else {
44 let cwd = env::current_dir()?;
45 let repo = Repository::discover(&cwd)?;
46 let git_dir = repo.path().to_path_buf();
47 (repo, git_dir)
48 };
49
50 Ok(RepoContext {
51 state_dir: git_dir.join("psect"),
52 repo,
53 })
54}