Skip to content

Add binding for git_repository_open_ext #126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions libgit2-sys/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,14 @@ git_enum! {
}
}

git_enum! {
pub enum git_repository_open_flag_t {
GIT_REPOSITORY_OPEN_NO_SEARCH = (1 << 0),
GIT_REPOSITORY_OPEN_CROSS_FS = (1 << 1),
GIT_REPOSITORY_OPEN_BARE = (1 << 2),
}
}

#[repr(C)]
pub struct git_repository_init_options {
pub version: c_uint,
Expand Down Expand Up @@ -1382,6 +1390,10 @@ extern {
pub fn git_repository_free(repo: *mut git_repository);
pub fn git_repository_open(repo: *mut *mut git_repository,
path: *const c_char) -> c_int;
pub fn git_repository_open_ext(repo: *mut *mut git_repository,
path: *const c_char,
flags: c_uint,
ceiling_dirs: *const c_char) -> c_int;
pub fn git_repository_init(repo: *mut *mut git_repository,
path: *const c_char,
is_bare: c_uint) -> c_int;
Expand Down
7 changes: 7 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::env::JoinPathsError;
use std::ffi::{CStr, NulError};
use std::error;
use std::fmt;
Expand Down Expand Up @@ -214,6 +215,12 @@ impl From<NulError> for Error {
}
}

impl From<JoinPathsError> for Error {
fn from(e: JoinPathsError) -> Error {
Error::from_str(error::Error::description(&e))
}
}


#[cfg(test)]
mod tests {
Expand Down
14 changes: 14 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,20 @@ Flags for APIs that add files matching pathspec
}
}

bitflags! {
#[doc = "
Flags for `Repository::open_ext`
"]
flags RepositoryOpenFlags: u32 {
/// Only open the specified path; don't walk upward searching.
const REPOSITORY_OPEN_NO_SEARCH = raw::GIT_REPOSITORY_OPEN_NO_SEARCH as u32,
/// Search across filesystem boundaries.
const REPOSITORY_OPEN_CROSS_FS = raw::GIT_REPOSITORY_OPEN_CROSS_FS as u32,
/// Force opening as bare repository, and defer loading its config.
const REPOSITORY_OPEN_BARE = raw::GIT_REPOSITORY_OPEN_BARE as u32,
}
}

bitflags! {
#[doc = "
Flags for the return value of `Repository::revparse`
Expand Down
67 changes: 65 additions & 2 deletions src/repo.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::ffi::{CStr, CString};
use std::env;
use std::ffi::{CStr, CString, OsStr};
use std::iter::IntoIterator;
use std::mem;
use std::path::Path;
use std::str;
use libc::{c_int, c_char, size_t, c_void, c_uint};

use {raw, Revspec, Error, init, Object, RepositoryState, Remote, Buf};
use {raw, Revspec, Error, init, Object, RepositoryOpenFlags, RepositoryState, Remote, Buf};
use {ResetType, Signature, Reference, References, Submodule, Blame, BlameOptions};
use {Branches, BranchType, Index, Config, Oid, Blob, Branch, Commit, Tree};
use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus};
Expand Down Expand Up @@ -59,6 +60,43 @@ impl Repository {
}
}

/// Find and open an existing repository, with additional options.
///
/// If flags contains REPOSITORY_OPEN_NO_SEARCH, the path must point
/// directly to a repository; otherwise, this may point to a subdirectory
/// of a repository, and `open_ext` will search up through parent
/// directories.
///
/// If flags contains REPOSITORY_OPEN_CROSS_FS, the search through parent
/// directories will not cross a filesystem boundary (detected when the
/// stat st_dev field changes).
///
/// If flags contains REPOSITORY_OPEN_BARE, force opening the repository as
/// bare even if it isn't, ignoring any working directory, and defer
/// loading the repository configuration for performance.
///
/// ceiling_dirs specifies a list of paths that the search through parent
/// directories will stop before entering. Use the functions in std::env
/// to construct or manipulate such a path list.
pub fn open_ext<P, O, I>(path: P,
flags: RepositoryOpenFlags,
ceiling_dirs: I)
-> Result<Repository, Error>
where P: AsRef<Path>, O: AsRef<OsStr>, I: IntoIterator<Item=O> {
init();
let path = try!(path.as_ref().into_c_string());
let ceiling_dirs_os = try!(env::join_paths(ceiling_dirs));
let ceiling_dirs = try!(ceiling_dirs_os.into_c_string());
let mut ret = 0 as *mut raw::git_repository;
unsafe {
try_call!(raw::git_repository_open_ext(&mut ret,
path,
flags.bits() as c_uint,
ceiling_dirs));
Ok(Binding::from_raw(ret))
}
}

/// Attempt to open an already-existing repository at or above `path`
///
/// This starts at `path` and looks up the filesystem hierarchy
Expand Down Expand Up @@ -1663,6 +1701,7 @@ impl RepositoryInitOptions {

#[cfg(test)]
mod tests {
use std::ffi::OsStr;
use std::fs;
use std::path::Path;
use tempdir::TempDir;
Expand Down Expand Up @@ -1754,6 +1793,30 @@ mod tests {
::test::realpath(&td.path().join("")).unwrap());
}

#[test]
fn smoke_open_ext() {
let td = TempDir::new("test").unwrap();
let subdir = td.path().join("subdir");
fs::create_dir(&subdir).unwrap();
Repository::init(td.path()).unwrap();

let repo = Repository::open_ext(&subdir, ::RepositoryOpenFlags::empty(), &[] as &[&OsStr]).unwrap();
assert!(!repo.is_bare());
assert_eq!(::test::realpath(&repo.path()).unwrap(),
::test::realpath(&td.path().join(".git")).unwrap());

let repo = Repository::open_ext(&subdir, ::REPOSITORY_OPEN_BARE, &[] as &[&OsStr]).unwrap();
assert!(repo.is_bare());
assert_eq!(::test::realpath(&repo.path()).unwrap(),
::test::realpath(&td.path().join(".git")).unwrap());

let err = Repository::open_ext(&subdir, ::REPOSITORY_OPEN_NO_SEARCH, &[] as &[&OsStr]).err().unwrap();
assert_eq!(err.code(), ::ErrorCode::NotFound);

let err = Repository::open_ext(&subdir, ::RepositoryOpenFlags::empty(), &[&subdir]).err().unwrap();
assert_eq!(err.code(), ::ErrorCode::NotFound);
}

fn graph_repo_init() -> (TempDir, Repository) {
let (_td, repo) = ::test::repo_init();
{
Expand Down