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