|
1 |
| -use std::ffi::{CStr, CString}; |
| 1 | +use std::env; |
| 2 | +use std::ffi::{CStr, CString, OsStr}; |
2 | 3 | use std::iter::IntoIterator;
|
3 | 4 | use std::mem;
|
4 | 5 | use std::path::Path;
|
5 | 6 | use std::str;
|
6 | 7 | use libc::{c_int, c_char, size_t, c_void, c_uint};
|
7 | 8 |
|
8 |
| -use {raw, Revspec, Error, init, Object, RepositoryState, Remote, Buf}; |
| 9 | +use {raw, Revspec, Error, init, Object, RepositoryOpenFlags, RepositoryState, Remote, Buf}; |
9 | 10 | use {ResetType, Signature, Reference, References, Submodule, Blame, BlameOptions};
|
10 | 11 | use {Branches, BranchType, Index, Config, Oid, Blob, Branch, Commit, Tree};
|
11 | 12 | use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus};
|
@@ -59,6 +60,43 @@ impl Repository {
|
59 | 60 | }
|
60 | 61 | }
|
61 | 62 |
|
| 63 | + /// Find and open an existing repository, with additional options. |
| 64 | + /// |
| 65 | + /// If flags contains REPOSITORY_OPEN_NO_SEARCH, the path must point |
| 66 | + /// directly to a repository; otherwise, this may point to a subdirectory |
| 67 | + /// of a repository, and `open_ext` will search up through parent |
| 68 | + /// directories. |
| 69 | + /// |
| 70 | + /// If flags contains REPOSITORY_OPEN_CROSS_FS, the search through parent |
| 71 | + /// directories will not cross a filesystem boundary (detected when the |
| 72 | + /// stat st_dev field changes). |
| 73 | + /// |
| 74 | + /// If flags contains REPOSITORY_OPEN_BARE, force opening the repository as |
| 75 | + /// bare even if it isn't, ignoring any working directory, and defer |
| 76 | + /// loading the repository configuration for performance. |
| 77 | + /// |
| 78 | + /// ceiling_dirs specifies a list of paths that the search through parent |
| 79 | + /// directories will stop before entering. Use the functions in std::env |
| 80 | + /// to construct or manipulate such a path list. |
| 81 | + pub fn open_ext<P, O, I>(path: P, |
| 82 | + flags: RepositoryOpenFlags, |
| 83 | + ceiling_dirs: I) |
| 84 | + -> Result<Repository, Error> |
| 85 | + where P: AsRef<Path>, O: AsRef<OsStr>, I: IntoIterator<Item=O> { |
| 86 | + init(); |
| 87 | + let path = try!(path.as_ref().into_c_string()); |
| 88 | + let ceiling_dirs_os = try!(env::join_paths(ceiling_dirs)); |
| 89 | + let ceiling_dirs = try!(ceiling_dirs_os.into_c_string()); |
| 90 | + let mut ret = 0 as *mut raw::git_repository; |
| 91 | + unsafe { |
| 92 | + try_call!(raw::git_repository_open_ext(&mut ret, |
| 93 | + path, |
| 94 | + flags.bits() as c_uint, |
| 95 | + ceiling_dirs)); |
| 96 | + Ok(Binding::from_raw(ret)) |
| 97 | + } |
| 98 | + } |
| 99 | + |
62 | 100 | /// Attempt to open an already-existing repository at or above `path`
|
63 | 101 | ///
|
64 | 102 | /// This starts at `path` and looks up the filesystem hierarchy
|
@@ -1663,6 +1701,7 @@ impl RepositoryInitOptions {
|
1663 | 1701 |
|
1664 | 1702 | #[cfg(test)]
|
1665 | 1703 | mod tests {
|
| 1704 | + use std::ffi::OsStr; |
1666 | 1705 | use std::fs;
|
1667 | 1706 | use std::path::Path;
|
1668 | 1707 | use tempdir::TempDir;
|
@@ -1754,6 +1793,30 @@ mod tests {
|
1754 | 1793 | ::test::realpath(&td.path().join("")).unwrap());
|
1755 | 1794 | }
|
1756 | 1795 |
|
| 1796 | + #[test] |
| 1797 | + fn smoke_open_ext() { |
| 1798 | + let td = TempDir::new("test").unwrap(); |
| 1799 | + let subdir = td.path().join("subdir"); |
| 1800 | + fs::create_dir(&subdir).unwrap(); |
| 1801 | + Repository::init(td.path()).unwrap(); |
| 1802 | + |
| 1803 | + let repo = Repository::open_ext(&subdir, ::RepositoryOpenFlags::empty(), &[] as &[&OsStr]).unwrap(); |
| 1804 | + assert!(!repo.is_bare()); |
| 1805 | + assert_eq!(::test::realpath(&repo.path()).unwrap(), |
| 1806 | + ::test::realpath(&td.path().join(".git")).unwrap()); |
| 1807 | + |
| 1808 | + let repo = Repository::open_ext(&subdir, ::REPOSITORY_OPEN_BARE, &[] as &[&OsStr]).unwrap(); |
| 1809 | + assert!(repo.is_bare()); |
| 1810 | + assert_eq!(::test::realpath(&repo.path()).unwrap(), |
| 1811 | + ::test::realpath(&td.path().join(".git")).unwrap()); |
| 1812 | + |
| 1813 | + let err = Repository::open_ext(&subdir, ::REPOSITORY_OPEN_NO_SEARCH, &[] as &[&OsStr]).err().unwrap(); |
| 1814 | + assert_eq!(err.code(), ::ErrorCode::NotFound); |
| 1815 | + |
| 1816 | + let err = Repository::open_ext(&subdir, ::RepositoryOpenFlags::empty(), &[&subdir]).err().unwrap(); |
| 1817 | + assert_eq!(err.code(), ::ErrorCode::NotFound); |
| 1818 | + } |
| 1819 | + |
1757 | 1820 | fn graph_repo_init() -> (TempDir, Repository) {
|
1758 | 1821 | let (_td, repo) = ::test::repo_init();
|
1759 | 1822 | {
|
|
0 commit comments