1 use std::fs::File;
2 use std::io;
3 use std::path::{Path, PathBuf};
4 #[cfg(unix)]
5 use std::ptr;
6 use tempfile::TempDir;
7 use url::Url;
8 
9 use crate::{Branch, Oid, Repository, RepositoryInitOptions};
10 
11 macro_rules! t {
12     ($e:expr) => {
13         match $e {
14             Ok(e) => e,
15             Err(e) => panic!("{} failed with {}", stringify!($e), e),
16         }
17     };
18 }
19 
repo_init() -> (TempDir, Repository)20 pub fn repo_init() -> (TempDir, Repository) {
21     let td = TempDir::new().unwrap();
22     let mut opts = RepositoryInitOptions::new();
23     opts.initial_head("main");
24     let repo = Repository::init_opts(td.path(), &opts).unwrap();
25     {
26         let mut config = repo.config().unwrap();
27         config.set_str("user.name", "name").unwrap();
28         config.set_str("user.email", "email").unwrap();
29         let mut index = repo.index().unwrap();
30         let id = index.write_tree().unwrap();
31 
32         let tree = repo.find_tree(id).unwrap();
33         let sig = repo.signature().unwrap();
34         repo.commit(Some("HEAD"), &sig, &sig, "initial", &tree, &[])
35             .unwrap();
36     }
37     (td, repo)
38 }
39 
commit(repo: &Repository) -> (Oid, Oid)40 pub fn commit(repo: &Repository) -> (Oid, Oid) {
41     let mut index = t!(repo.index());
42     let root = repo.path().parent().unwrap();
43     t!(File::create(&root.join("foo")));
44     t!(index.add_path(Path::new("foo")));
45 
46     let tree_id = t!(index.write_tree());
47     let tree = t!(repo.find_tree(tree_id));
48     let sig = t!(repo.signature());
49     let head_id = t!(repo.refname_to_id("HEAD"));
50     let parent = t!(repo.find_commit(head_id));
51     let commit = t!(repo.commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent]));
52     (commit, tree_id)
53 }
54 
path2url(path: &Path) -> String55 pub fn path2url(path: &Path) -> String {
56     Url::from_file_path(path).unwrap().to_string()
57 }
58 
worktrees_env_init(repo: &Repository) -> (TempDir, Branch<'_>)59 pub fn worktrees_env_init(repo: &Repository) -> (TempDir, Branch<'_>) {
60     let oid = repo.head().unwrap().target().unwrap();
61     let commit = repo.find_commit(oid).unwrap();
62     let branch = repo.branch("wt-branch", &commit, true).unwrap();
63     let wtdir = TempDir::new().unwrap();
64     (wtdir, branch)
65 }
66 
67 #[cfg(windows)]
realpath(original: &Path) -> io::Result<PathBuf>68 pub fn realpath(original: &Path) -> io::Result<PathBuf> {
69     Ok(original.to_path_buf())
70 }
71 #[cfg(unix)]
realpath(original: &Path) -> io::Result<PathBuf>72 pub fn realpath(original: &Path) -> io::Result<PathBuf> {
73     use libc::c_char;
74     use std::ffi::{CStr, CString, OsString};
75     use std::os::unix::prelude::*;
76     extern "C" {
77         fn realpath(name: *const c_char, resolved: *mut c_char) -> *mut c_char;
78     }
79     unsafe {
80         let cstr = CString::new(original.as_os_str().as_bytes())?;
81         let ptr = realpath(cstr.as_ptr(), ptr::null_mut());
82         if ptr.is_null() {
83             return Err(io::Error::last_os_error());
84         }
85         let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
86         libc::free(ptr as *mut _);
87         Ok(PathBuf::from(OsString::from_vec(bytes)))
88     }
89 }
90