diff --git a/.travis.yml b/.travis.yml index 7c8a201ea0..a9df407e8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ sudo: false before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - - export CARGO_TARGET_DIR=`pwd`/target - cargo test --no-default-features - cargo test - cargo run --manifest-path systest/Cargo.toml --release diff --git a/Cargo.toml b/Cargo.toml index a458787b55..ee69171639 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,3 +32,6 @@ unstable = [] default = ["ssh", "https"] ssh = ["libgit2-sys/ssh"] https = ["libgit2-sys/https"] + +[workspace] +members = ["systest", "git2-curl"] diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 74c59c016b..989e5d65d1 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -18,6 +18,7 @@ pub const GIT_MERGE_OPTIONS_VERSION: c_uint = 1; pub const GIT_REMOTE_CALLBACKS_VERSION: c_uint = 1; pub const GIT_STATUS_OPTIONS_VERSION: c_uint = 1; pub const GIT_BLAME_OPTIONS_VERSION: c_uint = 1; +pub const GIT_PROXY_OPTIONS_VERSION: c_uint = 1; macro_rules! git_enum { (pub enum $name:ident { $($variants:tt)* }) => { @@ -329,6 +330,7 @@ pub struct git_fetch_options { pub prune: git_fetch_prune_t, pub update_fetchhead: c_int, pub download_tags: git_remote_autotag_option_t, + pub proxy_opts: git_proxy_options, pub custom_headers: git_strarray, } @@ -838,6 +840,7 @@ pub struct git_push_options { pub version: c_uint, pub pb_parallelism: c_uint, pub callbacks: git_remote_callbacks, + pub proxy_opts: git_proxy_options, pub custom_headers: git_strarray, } @@ -1119,6 +1122,7 @@ pub const GIT_DIFF_FIND_REMOVE_UNMODIFIED: u32 = 1 << 16; #[repr(C)] pub struct git_diff_binary { + pub contains_data: c_uint, pub old_file: git_diff_binary_file, pub new_file: git_diff_binary_file, } @@ -1147,6 +1151,7 @@ pub struct git_merge_options { pub target_limit: c_uint, pub metric: *mut git_diff_similarity_metric, pub recursion_limit: c_uint, + pub default_driver: *const c_char, pub file_favor: git_merge_file_favor_t, pub file_flags: git_merge_file_flag_t, } @@ -1201,6 +1206,7 @@ pub struct git_transport { *const c_char, git_cred_acquire_cb, *mut c_void, + *const git_proxy_options, c_int, c_int) -> c_int, pub ls: extern fn(*mut *mut *const git_remote_head, *mut size_t, @@ -1224,6 +1230,24 @@ pub struct git_transport { pub free: extern fn(*mut git_transport), } +#[repr(C)] +pub struct git_proxy_options { + pub version: c_uint, + pub kind: git_proxy_t, + pub url: *const c_char, + pub credentials: Option, + pub certificate_check: Option, + pub payload: *mut c_void, +} + +git_enum! { + pub enum git_proxy_t { + GIT_PROXY_NONE = 0, + GIT_PROXY_AUTO = 1, + GIT_PROXY_SPECIFIED = 2, + } +} + git_enum! { pub enum git_smart_service_t { GIT_SERVICE_UPLOADPACK_LS = 1, @@ -1547,6 +1571,7 @@ extern { pub fn git_remote_connect(remote: *mut git_remote, dir: git_direction, callbacks: *const git_remote_callbacks, + proxy_opts: *const git_proxy_options, custom_headers: *const git_strarray) -> c_int; pub fn git_remote_connected(remote: *const git_remote) -> c_int; pub fn git_remote_disconnect(remote: *mut git_remote); @@ -2546,8 +2571,8 @@ extern { pub fn git_packbuilder_foreach(pb: *mut git_packbuilder, cb: git_packbuilder_foreach_cb, payload: *mut c_void) -> c_int; - pub fn git_packbuilder_object_count(pb: *mut git_packbuilder) -> u32; - pub fn git_packbuilder_written(pb: *mut git_packbuilder) -> u32; + pub fn git_packbuilder_object_count(pb: *mut git_packbuilder) -> size_t; + pub fn git_packbuilder_written(pb: *mut git_packbuilder) -> size_t; pub fn git_packbuilder_set_callbacks(pb: *mut git_packbuilder, progress_cb: Option, progress_cb_payload: *mut c_void) -> c_int; diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index c8fe6c0975..9fbbb0eec5 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit c8fe6c0975431e92d3dc4569734f30923b64dd18 +Subproject commit 9fbbb0eec5fc46cc9c36abf25b9baf653eb12372 diff --git a/src/diff.rs b/src/diff.rs index 602ce2fe02..7c769eca0e 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -873,6 +873,16 @@ impl Drop for DiffStats { } impl<'a> DiffBinary<'a> { + /// Returns whether there is data in this binary structure or not. + /// + /// If this is `true`, then this was produced and included binary content. + /// If this is `false` then this was generated knowing only that a binary + /// file changed but without providing the data, probably from a patch that + /// said `Binary files a/file.txt and b/file.txt differ`. + pub fn contains_data(&self) -> bool { + unsafe { (*self.raw).contains_data == 1 } + } + /// The contents of the old file. pub fn old_file(&self) -> DiffBinaryFile<'a> { unsafe { Binding::from_raw(&(*self.raw).old_file as *const _) } @@ -1195,7 +1205,7 @@ mod tests { t!(index.add_path(foo_path)); t!(index.add_path(bin_path)); let mut opts = DiffOptions::new(); - opts.include_untracked(true); + opts.include_untracked(true).show_binary(true); let diff = t!(repo.diff_tree_to_index(None, Some(&index), Some(&mut opts))); let mut bin_content = None; diff --git a/src/lib.rs b/src/lib.rs index e68fcb45d0..e5c2ed2a8f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,11 +88,11 @@ pub use config::{Config, ConfigEntry, ConfigEntries}; pub use cred::{Cred, CredentialHelper}; pub use describe::{Describe, DescribeFormatOptions, DescribeOptions}; pub use diff::{Diff, DiffDelta, DiffFile, DiffOptions, Deltas}; -pub use diff::{DiffLine, DiffHunk, DiffStats, DiffFindOptions}; pub use diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind}; -pub use merge::{AnnotatedCommit, MergeOptions}; +pub use diff::{DiffLine, DiffHunk, DiffStats, DiffFindOptions}; pub use error::Error; pub use index::{Index, IndexEntry, IndexEntries, IndexMatchedPath}; +pub use merge::{AnnotatedCommit, MergeOptions}; pub use message::{message_prettify, DEFAULT_COMMENT_CHAR}; pub use note::{Note, Notes}; pub use object::Object; @@ -100,6 +100,7 @@ pub use oid::Oid; pub use packbuilder::{PackBuilder, PackBuilderStage}; pub use pathspec::{Pathspec, PathspecMatchList, PathspecFailedEntries}; pub use pathspec::{PathspecDiffEntries, PathspecEntries}; +pub use proxy_options::ProxyOptions; pub use reference::{Reference, References, ReferenceNames}; pub use reflog::{Reflog, ReflogEntry, ReflogIter}; pub use refspec::Refspec; @@ -494,15 +495,16 @@ mod config; mod cred; mod describe; mod diff; -mod merge; mod error; mod index; +mod merge; mod message; mod note; mod object; mod oid; mod packbuilder; mod pathspec; +mod proxy_options; mod reference; mod reflog; mod refspec; diff --git a/src/packbuilder.rs b/src/packbuilder.rs index ccb3aaefa5..bfe118eefb 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -136,12 +136,12 @@ impl<'repo> PackBuilder<'repo> { /// Get the total number of objects the packbuilder will write out. pub fn object_count(&self) -> usize { - unsafe { raw::git_packbuilder_object_count(self.raw) as usize } + unsafe { raw::git_packbuilder_object_count(self.raw) } } /// Get the number of objects the packbuilder has already written out. pub fn written(&self) -> usize { - unsafe { raw::git_packbuilder_written(self.raw) as usize } + unsafe { raw::git_packbuilder_written(self.raw) } } /// Get the packfile's hash. A packfile's name is derived from the sorted diff --git a/src/proxy_options.rs b/src/proxy_options.rs new file mode 100644 index 0000000000..45ca19dc15 --- /dev/null +++ b/src/proxy_options.rs @@ -0,0 +1,58 @@ +use std::ffi::CString; +use std::marker; + +use raw; +use util::Binding; + +/// Options which can be specified to various fetch operations. +pub struct ProxyOptions<'a> { + url: Option, + proxy_kind: raw::git_proxy_t, + _marker: marker::PhantomData<&'a i32>, +} + +impl<'a> ProxyOptions<'a> { + /// Creates a new set of proxy options ready to be configured. + pub fn new() -> ProxyOptions<'a> { + ProxyOptions { + url: None, + proxy_kind: raw::GIT_PROXY_NONE, + _marker: marker::PhantomData, + } + } + + /// Try to auto-detect the proxy from the git configuration. + /// + /// Note that this will override `url` specified before. + pub fn auto(&mut self) -> &mut Self { + self.proxy_kind = raw::GIT_PROXY_AUTO; + self + } + + /// Specify the exact URL of the proxy to use. + /// + /// Note that this will override `auto` specified before. + pub fn url(&mut self, url: &str) -> &mut Self { + self.proxy_kind = raw::GIT_PROXY_SPECIFIED; + self.url = Some(CString::new(url).unwrap()); + self + } +} + +impl<'a> Binding for ProxyOptions<'a> { + type Raw = raw::git_proxy_options; + unsafe fn from_raw(_raw: raw::git_proxy_options) -> ProxyOptions<'a> { + panic!("can't create proxy from raw options") + } + + fn raw(&self) -> raw::git_proxy_options { + raw::git_proxy_options { + version: raw::GIT_PROXY_OPTIONS_VERSION, + kind: self.proxy_kind, + url: self.url.as_ref().map(|s| s.as_ptr()).unwrap_or(0 as *const _), + credentials: None, + certificate_check: None, + payload: 0 as *mut _, + } + } +} diff --git a/src/remote.rs b/src/remote.rs index 9b51d7350d..cd226ce94e 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -6,7 +6,7 @@ use std::slice; use std::str; use libc; -use {raw, Direction, Error, Refspec, Oid, FetchPrune}; +use {raw, Direction, Error, Refspec, Oid, FetchPrune, ProxyOptions}; use {RemoteCallbacks, Progress, Repository, AutotagOption}; use util::Binding; @@ -37,6 +37,7 @@ pub struct RemoteHead<'remote> { /// Options which can be specified to various fetch operations. pub struct FetchOptions<'cb> { callbacks: Option>, + proxy: Option>, prune: FetchPrune, update_fetchhead: bool, download_tags: AutotagOption, @@ -45,6 +46,7 @@ pub struct FetchOptions<'cb> { /// Options to control the behavior of a git push. pub struct PushOptions<'cb> { callbacks: Option>, + proxy: Option>, pb_parallelism: u32, } @@ -100,6 +102,7 @@ impl<'repo> Remote<'repo> { // TODO: can callbacks be exposed safely? unsafe { try_call!(raw::git_remote_connect(self.raw, dir, + 0 as *const _, 0 as *const _, 0 as *const _)); } @@ -304,6 +307,7 @@ impl<'cb> FetchOptions<'cb> { pub fn new() -> FetchOptions<'cb> { FetchOptions { callbacks: None, + proxy: None, prune: FetchPrune::Unspecified, update_fetchhead: true, download_tags: AutotagOption::Unspecified, @@ -316,6 +320,12 @@ impl<'cb> FetchOptions<'cb> { self } + /// Set the proxy options to use for the fetch operation. + pub fn proxy_options(&mut self, opts: ProxyOptions<'cb>) -> &mut Self { + self.proxy = Some(opts); + self + } + /// Set whether to perform a prune after the fetch. pub fn prune(&mut self, prune: FetchPrune) -> &mut Self { self.prune = prune; @@ -351,6 +361,8 @@ impl<'cb> Binding for FetchOptions<'cb> { version: 1, callbacks: self.callbacks.as_ref().map(|m| m.raw()) .unwrap_or_else(|| RemoteCallbacks::new().raw()), + proxy_opts: self.proxy.as_ref().map(|m| m.raw()) + .unwrap_or_else(|| ProxyOptions::new().raw()), prune: ::call::convert(&self.prune), update_fetchhead: ::call::convert(&self.update_fetchhead), download_tags: ::call::convert(&self.download_tags), @@ -368,6 +380,7 @@ impl<'cb> PushOptions<'cb> { pub fn new() -> PushOptions<'cb> { PushOptions { callbacks: None, + proxy: None, pb_parallelism: 1, } } @@ -378,6 +391,12 @@ impl<'cb> PushOptions<'cb> { self } + /// Set the proxy options to use for the fetch operation. + pub fn proxy_options(&mut self, opts: ProxyOptions<'cb>) -> &mut Self { + self.proxy = Some(opts); + self + } + /// If the transport being used to push to the remote requires the creation /// of a pack file, this controls the number of worker threads used by the /// packbuilder when creating that pack file to be sent to the remote. @@ -401,6 +420,8 @@ impl<'cb> Binding for PushOptions<'cb> { version: 1, callbacks: self.callbacks.as_ref().map(|m| m.raw()) .unwrap_or(RemoteCallbacks::new().raw()), + proxy_opts: self.proxy.as_ref().map(|m| m.raw()) + .unwrap_or_else(|| ProxyOptions::new().raw()), pb_parallelism: self.pb_parallelism as libc::c_uint, // TODO: expose this as a builder option custom_headers: raw::git_strarray { diff --git a/src/repo.rs b/src/repo.rs index c0738405f3..10eb92a71e 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -81,8 +81,9 @@ impl Repository { pub fn open_ext(path: P, flags: RepositoryOpenFlags, ceiling_dirs: I) - -> Result - where P: AsRef, O: AsRef, I: IntoIterator { + -> Result + where P: AsRef, O: AsRef, I: IntoIterator + { init(); let path = try!(path.as_ref().into_c_string()); let ceiling_dirs_os = try!(env::join_paths(ceiling_dirs)); @@ -1967,8 +1968,9 @@ mod tests { 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); + assert!(Repository::open_ext(&subdir, + ::RepositoryOpenFlags::empty(), + &[&subdir]).is_ok()); } fn graph_repo_init() -> (TempDir, Repository) { @@ -2086,6 +2088,8 @@ mod tests { let commit2 = repo.find_commit(oid2).unwrap(); println!("created oid2 {:?}", oid2); + t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); + // create commit oid3 on branchB let mut index = repo.index().unwrap(); let p = Path::new(repo.workdir().unwrap()).join("file_b"); @@ -2134,7 +2138,7 @@ mod tests { } assert!(found_oid2); assert!(found_oid3); - assert_eq!(merge_bases.len(), 2); + assert_eq!(merge_bases.len(), 2); } #[test]