From ae8056249922bf561903ad6b3e2d9add85d9567d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 26 May 2016 10:20:11 -0700 Subject: [PATCH 001/860] Bump curl version --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 9ca1413043..65e6dd798c 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -14,7 +14,7 @@ Intended to be used with the git2 crate. """ [dependencies] -curl = { git = "https://github.com/alexcrichton/curl-rust" } +curl = "0.3" url = "1.0" log = "0.3" git2 = { path = "..", version = "0.4" } From 47080a9d0883457ff4943187327e32852fe166f6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 26 May 2016 10:20:44 -0700 Subject: [PATCH 002/860] Bump git2-curl to 0.5.0 --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 65e6dd798c..f848a2f6e6 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.4.1" +version = "0.5.0" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/git2-rs" From f3cf8a32fa03beba804805db6b99f7a8ec458623 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 8 Jun 2016 00:01:11 -0700 Subject: [PATCH 003/860] Implement PartialEq for git2::Error (and thus Result) This allows comparing Error values using == and !=, which in turn also allows comparing Result for any T that implements PartialEq. --- src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/error.rs b/src/error.rs index ab4173a075..7d8f42c843 100644 --- a/src/error.rs +++ b/src/error.rs @@ -8,7 +8,7 @@ use libc::c_int; use {raw, ErrorClass, ErrorCode}; /// A structure to represent errors coming out of libgit2. -#[derive(Debug)] +#[derive(Debug,PartialEq)] pub struct Error { code: c_int, klass: c_int, From 06de9d9a5afe20dd7ab1f6da008033feddef3198 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 8 Jun 2016 00:22:36 -0700 Subject: [PATCH 004/860] config: Add parse bindings Add bindings for git_config_parse_bool, git_config_parse_int32, and git_config_parse_int64, as static functions of Config. --- src/config.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/config.rs b/src/config.rs index 36d0f26596..4c15873cdc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -349,6 +349,43 @@ impl Config { Ok(Binding::from_raw(ret)) } } + + /// Parse a string as a bool. + /// Interprets "true", "yes", "on", 1, or any non-zero number as true. + /// Interprets "false", "no", "off", 0, or an empty string as false. + pub fn parse_bool(s: S) -> Result { + let s = try!(s.into_c_string()); + let mut out = 0; + ::init(); + unsafe { + try_call!(raw::git_config_parse_bool(&mut out, s)); + } + Ok(out != 0) + } + + /// Parse a string as an i32; handles suffixes like k, M, or G, and + /// multiplies by the appropriate power of 1024. + pub fn parse_i32(s: S) -> Result { + let s = try!(s.into_c_string()); + let mut out = 0; + ::init(); + unsafe { + try_call!(raw::git_config_parse_int32(&mut out, s)); + } + Ok(out) + } + + /// Parse a string as an i64; handles suffixes like k, M, or G, and + /// multiplies by the appropriate power of 1024. + pub fn parse_i64(s: S) -> Result { + let s = try!(s.into_c_string()); + let mut out = 0; + ::init(); + unsafe { + try_call!(raw::git_config_parse_int64(&mut out, s)); + } + Ok(out) + } } impl Binding for Config { @@ -496,4 +533,44 @@ mod tests { entry.level(); } } + + #[test] + fn parse() { + assert_eq!(Config::parse_bool("").unwrap(), false); + assert_eq!(Config::parse_bool("false").unwrap(), false); + assert_eq!(Config::parse_bool("no").unwrap(), false); + assert_eq!(Config::parse_bool("off").unwrap(), false); + assert_eq!(Config::parse_bool("0").unwrap(), false); + + assert_eq!(Config::parse_bool("true").unwrap(), true); + assert_eq!(Config::parse_bool("yes").unwrap(), true); + assert_eq!(Config::parse_bool("on").unwrap(), true); + assert_eq!(Config::parse_bool("1").unwrap(), true); + assert_eq!(Config::parse_bool("42").unwrap(), true); + + assert!(Config::parse_bool(" ").is_err()); + assert!(Config::parse_bool("some-string").is_err()); + assert!(Config::parse_bool("-").is_err()); + + assert_eq!(Config::parse_i32("0").unwrap(), 0); + assert_eq!(Config::parse_i32("1").unwrap(), 1); + assert_eq!(Config::parse_i32("100").unwrap(), 100); + assert_eq!(Config::parse_i32("-1").unwrap(), -1); + assert_eq!(Config::parse_i32("-100").unwrap(), -100); + assert_eq!(Config::parse_i32("1k").unwrap(), 1024); + assert_eq!(Config::parse_i32("4k").unwrap(), 4096); + assert_eq!(Config::parse_i32("1M").unwrap(), 1048576); + assert_eq!(Config::parse_i32("1G").unwrap(), 1024*1024*1024); + + assert_eq!(Config::parse_i64("0").unwrap(), 0); + assert_eq!(Config::parse_i64("1").unwrap(), 1); + assert_eq!(Config::parse_i64("100").unwrap(), 100); + assert_eq!(Config::parse_i64("-1").unwrap(), -1); + assert_eq!(Config::parse_i64("-100").unwrap(), -100); + assert_eq!(Config::parse_i64("1k").unwrap(), 1024); + assert_eq!(Config::parse_i64("4k").unwrap(), 4096); + assert_eq!(Config::parse_i64("1M").unwrap(), 1048576); + assert_eq!(Config::parse_i64("1G").unwrap(), 1024*1024*1024); + assert_eq!(Config::parse_i64("100G").unwrap(), 100*1024*1024*1024); + } } From 70b636e051644bba7aca15414488f9e1c6307fa8 Mon Sep 17 00:00:00 2001 From: Nikita Baksalyar Date: Mon, 13 Jun 2016 14:40:39 +0500 Subject: [PATCH 005/860] Fix compilation of libgit2-sys on Illumos/Solaris --- libgit2-sys/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 5c6ebf62d1..ed9bf302b0 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -54,6 +54,8 @@ openssl-sys = "0.7.0" openssl-sys = "0.7.0" [target.x86_64-unknown-dragonfly.dependencies] openssl-sys = "0.7.0" +[target.x86_64-sun-solaris.dependencies] +openssl-sys = "0.7.0" [features] ssh = ["libssh2-sys"] From 2780beee57c38cdc046a8e69552f5727f69f10d7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 16 Jul 2016 09:45:43 -0700 Subject: [PATCH 006/860] Bump to 0.4.4 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d175086b47..21fd9e6384 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.4.3" +version = "0.4.4" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From ae757da69e3a08111cc7e11a44269598d5068429 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 16 Jul 2016 09:49:00 -0700 Subject: [PATCH 007/860] Bump libgit2-sys to 0.4.4 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index ed9bf302b0..3cc7fcbf4d 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.4.3" +version = "0.4.4" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 03da362c516ff51877efbf36c9aa1c7f1e3c9c12 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 16 Jul 2016 09:49:45 -0700 Subject: [PATCH 008/860] Bump dependency on libgit2-sys --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 21fd9e6384..a458787b55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ repositories. url = "1.0" bitflags = "0.1" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.4.3" } +libgit2-sys = { path = "libgit2-sys", version = "0.4.4" } [dev-dependencies] docopt = "0.6" From 43ee65fe5ec22823931f3a8f8697b114b1a1183a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 6 Aug 2016 17:34:26 -0700 Subject: [PATCH 009/860] Initialize OpenSSL in openssl_init Ensures that the OpenSSL library, if used, is initialized by that point. --- libgit2-sys/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a46c3af9ac..74c59c016b 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1306,6 +1306,8 @@ pub type git_packbuilder_foreach_cb = extern fn(*const c_void, size_t, /// Initialize openssl for the libgit2 library #[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] pub fn openssl_init() { + openssl::init(); + if !cfg!(target_os = "linux") && !cfg!(target_os = "freebsd") { return } // Currently, libgit2 leverages OpenSSL for SSL support when cloning From c83a9c0e39e9b501144cf36ed786b06c59a7b424 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 6 Aug 2016 17:35:03 -0700 Subject: [PATCH 010/860] Bump libgit2-sys to 0.4.5 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 3cc7fcbf4d..fc78481d01 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.4.4" +version = "0.4.5" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 3edcdcd75cb3d9ac7a8d05a93fcd2a872fafcbe1 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 11 Aug 2016 16:45:38 -1000 Subject: [PATCH 011/860] src/repo.rs: Fix typo in docs for reset: s/derefernceable/dereferenceable/ --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 3b51613e95..c0738405f3 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -462,7 +462,7 @@ impl Repository { /// will be left alone, however.) /// /// The `target` is a commit-ish to which the head should be moved to. The - /// object can either be a commit or a tag, but tags must be derefernceable + /// object can either be a commit or a tag, but tags must be dereferenceable /// to a commit. /// /// The `checkout` options will only be used for a hard reset. From fb9a8e6df5459c645ff2058338fbbd8ce7c7bb5c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 6 Aug 2016 18:21:24 -0700 Subject: [PATCH 012/860] Update libgit2 --- .travis.yml | 1 - Cargo.toml | 3 +++ libgit2-sys/lib.rs | 29 ++++++++++++++++++++-- libgit2-sys/libgit2 | 2 +- src/diff.rs | 12 ++++++++- src/lib.rs | 8 +++--- src/packbuilder.rs | 4 +-- src/proxy_options.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++ src/remote.rs | 23 +++++++++++++++++- src/repo.rs | 14 +++++++---- 10 files changed, 138 insertions(+), 16 deletions(-) create mode 100644 src/proxy_options.rs 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(https://github.com/&mut%20self,%20url:%20&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] From f2508ed0a1f7002bd7795d24a0c75852e6bf9f1c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 3 Oct 2016 17:22:04 -0700 Subject: [PATCH 013/860] Update dependency on bitflags! Brings in some nice OpEq traits and whatnot. --- Cargo.toml | 2 +- src/lib.rs | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ee69171639..aada0a490d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ repositories. [dependencies] url = "1.0" -bitflags = "0.1" +bitflags = "0.7" libc = "0.2" libgit2-sys = { path = "libgit2-sys", version = "0.4.4" } diff --git a/src/lib.rs b/src/lib.rs index e5c2ed2a8f..67040cae0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -346,7 +346,7 @@ pub enum FileFavor { bitflags! { /// Orderings that may be specified for Revwalk iteration. - flags Sort: u32 { + pub flags Sort: u32 { /// Sort the repository contents in no particular ordering. /// /// This sorting is arbitrary, implementation-specific, and subject to @@ -373,7 +373,7 @@ bitflags! { bitflags! { /// Types of credentials that can be requested by a credential callback. - flags CredentialType: u32 { + pub flags CredentialType: u32 { #[allow(missing_docs)] const USER_PASS_PLAINTEXT = raw::GIT_CREDTYPE_USERPASS_PLAINTEXT as u32, #[allow(missing_docs)] @@ -393,7 +393,7 @@ bitflags! { bitflags! { /// Flags for the `flags` field of an IndexEntry. - flags IndexEntryFlag: u16 { + pub flags IndexEntryFlag: u16 { /// Set when the `extended_flags` field is valid. const IDXENTRY_EXTENDED = raw::GIT_IDXENTRY_EXTENDED as u16, /// "Assume valid" flag @@ -403,7 +403,7 @@ bitflags! { bitflags! { /// Flags for the `extended_flags` field of an IndexEntry. - flags IndexEntryExtendedFlag: u16 { + pub flags IndexEntryExtendedFlag: u16 { /// An "intent to add" entry from "git add -N" const IDXENTRY_INTENT_TO_ADD = raw::GIT_IDXENTRY_INTENT_TO_ADD as u16, /// Skip the associated worktree file, for sparse checkouts @@ -438,7 +438,7 @@ bitflags! { bitflags! { /// Flags for APIs that add files matching pathspec - flags IndexAddOption: u32 { + pub flags IndexAddOption: u32 { #[allow(missing_docs)] const ADD_DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32, #[allow(missing_docs)] @@ -453,7 +453,7 @@ bitflags! { bitflags! { /// Flags for `Repository::open_ext` - flags RepositoryOpenFlags: u32 { + pub 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. @@ -465,7 +465,7 @@ bitflags! { bitflags! { /// Flags for the return value of `Repository::revparse` - flags RevparseMode: u32 { + pub flags RevparseMode: u32 { /// The spec targeted a single object const REVPARSE_SINGLE = raw::GIT_REVPARSE_SINGLE as u32, /// The spec targeted a range of commits @@ -621,7 +621,7 @@ bitflags! { /// represents the status of file in the index relative to the HEAD, and the /// `STATUS_WT_*` set of flags represent the status of the file in the /// working directory relative to the index. - flags Status: u32 { + pub flags Status: u32 { #[allow(missing_docs)] const STATUS_CURRENT = raw::GIT_STATUS_CURRENT as u32, @@ -656,7 +656,7 @@ bitflags! { bitflags! { /// Mode options for RepositoryInitOptions - flags RepositoryInitMode: u32 { + pub flags RepositoryInitMode: u32 { /// Use permissions configured by umask - the default const REPOSITORY_INIT_SHARED_UMASK = raw::GIT_REPOSITORY_INIT_SHARED_UMASK as u32, @@ -738,7 +738,7 @@ bitflags! { /// Lastly, the following will only be returned for ignore "NONE". /// /// * WD_UNTRACKED - wd contains untracked files - flags SubmoduleStatus: u32 { + pub flags SubmoduleStatus: u32 { #[allow(missing_docs)] const SUBMODULE_STATUS_IN_HEAD = raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32, @@ -805,7 +805,7 @@ pub enum SubmoduleIgnore { bitflags! { /// ... - flags PathspecFlags: u32 { + pub flags PathspecFlags: u32 { /// Use the default pathspec matching configuration. const PATHSPEC_DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32, /// Force matching to ignore case, otherwise matching will use native @@ -834,7 +834,7 @@ bitflags! { bitflags! { /// Types of notifications emitted from checkouts. - flags CheckoutNotificationType: u32 { + pub flags CheckoutNotificationType: u32 { /// Notification about a conflict. const CHECKOUT_NOTIFICATION_CONFLICT = raw::GIT_CHECKOUT_NOTIFY_CONFLICT as u32, /// Notification about a dirty file. @@ -865,7 +865,7 @@ pub enum DiffFormat { bitflags! { /// Formatting options for diff stats - flags DiffStatsFormat: raw::git_diff_stats_format_t { + pub flags DiffStatsFormat: raw::git_diff_stats_format_t { /// Don't generate any stats const DIFF_STATS_NONE = raw::GIT_DIFF_STATS_NONE, /// Equivalent of `--stat` in git From 3f8c1d3f405ad6560985931b1e736efd233aaa87 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 4 Oct 2016 10:06:29 -0700 Subject: [PATCH 014/860] Enable curl support in libgit2 Add a feature for using libgit2's direct support for curl, avoiding the need for the `git2-curl` crate. --- .travis.yml | 10 +++++++--- Cargo.toml | 3 ++- libgit2-sys/Cargo.toml | 4 +++- libgit2-sys/build.rs | 10 +++++++++- libgit2-sys/lib.rs | 2 ++ 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index a9df407e8a..d8aa97d04c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,9 +23,13 @@ after_success: notifications: email: on_success: never -os: - - linux - - osx +matrix: + include: + - os: osx + rust: stable + before_install: + - export OPENSSL_INCLUDE_DIR=`brew --prefix openssl`/include + - export OPENSSL_LIB_DIR=`brew --prefix openssl`/lib addons: apt: sources: diff --git a/Cargo.toml b/Cargo.toml index aada0a490d..729ca0f294 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,9 +29,10 @@ tempdir = "0.3" [features] unstable = [] -default = ["ssh", "https"] +default = ["ssh", "https", "curl"] ssh = ["libgit2-sys/ssh"] https = ["libgit2-sys/https"] +curl = ["libgit2-sys/curl"] [workspace] members = ["systest", "git2-curl"] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index fc78481d01..3088b5c0de 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -14,8 +14,9 @@ name = "libgit2_sys" path = "lib.rs" [dependencies] -libssh2-sys = { version = ">= 0", optional = true } +curl-sys = { version = ">= 0", optional = true } libc = "0.2" +libssh2-sys = { version = ">= 0", optional = true } libz-sys = ">= 0" [build-dependencies] @@ -60,3 +61,4 @@ openssl-sys = "0.7.0" [features] ssh = ["libssh2-sys"] https = [] +curl = ["curl-sys"] diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index b4d58b3210..330dd4cc14 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -19,12 +19,16 @@ macro_rules! t { fn main() { let https = env::var("CARGO_FEATURE_HTTPS").is_ok(); let ssh = env::var("CARGO_FEATURE_SSH").is_ok(); + let curl = env::var("CARGO_FEATURE_CURL").is_ok(); if ssh { register_dep("SSH2"); } if https { register_dep("OPENSSL"); } + if curl { + register_dep("CURL"); + } let has_pkgconfig = Command::new("pkg-config").output().is_ok(); if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() { @@ -101,13 +105,17 @@ fn main() { } else { cfg.define("USE_OPENSSL", "OFF"); } + if curl { + cfg.register_dep("CURL"); + } else { + cfg.define("CURL", "OFF"); + } let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap()); t!(fs::create_dir_all(env::var("OUT_DIR").unwrap())); let dst = cfg.define("BUILD_SHARED_LIBS", "OFF") .define("BUILD_CLAR", "OFF") - .define("CURL", "OFF") .register_dep("Z") .build(); diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 989e5d65d1..04cfdfc749 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -4,6 +4,8 @@ extern crate libc; #[cfg(feature = "ssh")] extern crate libssh2_sys as libssh2; +#[cfg(feature = "curl")] +extern crate curl_sys; #[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] extern crate openssl_sys as openssl; extern crate libz_sys as libz; From 333a62cd867e0134ace95ed516450b79f0629460 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 5 Oct 2016 10:00:29 -0700 Subject: [PATCH 015/860] Try to fix appveyor errors --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 13fe54d58a..8b05c5e6e4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,7 +10,7 @@ install: - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-$%7Benv:TARGET%7D.exe" - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - set PATH=%PATH%;C:\Program Files (x86)\Rust\bin - - if defined MSYS_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS_BITS%\bin;C:\msys64\usr\bin + - if defined MSYS_BITS set PATH=C:\msys64\mingw%MSYS_BITS%\bin;C:\msys64\usr\bin;%PATH% - set CARGO_TARGET_DIR=%APPVEYOR_BUILD_FOLDER%\target - rustc -V - cargo -V From 080e129b9aabb2938f9237913d0d61eeb46d52db Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 5 Oct 2016 14:02:36 -0700 Subject: [PATCH 016/860] Bump to libgit2-sys 0.5.0 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 3088b5c0de..8a572025e2 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.4.5" +version = "0.5.0" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From ed12434942e0ec5a16dd0940e1be3b26b4c8b598 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 5 Oct 2016 14:04:04 -0700 Subject: [PATCH 017/860] Bump to 0.5.0 --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 729ca0f294..16405646a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.4.4" +version = "0.5.0" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -19,7 +19,7 @@ repositories. url = "1.0" bitflags = "0.7" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.4.4" } +libgit2-sys = { path = "libgit2-sys", version = "0.5" } [dev-dependencies] docopt = "0.6" From b28591af5d725904d10c6476854eabefd841d5e4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 5 Oct 2016 15:19:36 -0700 Subject: [PATCH 018/860] Depend on crates.io git2 for git2-curl --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index f848a2f6e6..fc07a5db19 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -17,7 +17,7 @@ Intended to be used with the git2 crate. curl = "0.3" url = "1.0" log = "0.3" -git2 = { path = "..", version = "0.4" } +git2 = "0.4" [dev-dependencies] civet = "0.8" From 4081a8f59c69c0118a61b92ea9f3ae102e814619 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 6 Oct 2016 15:42:16 -0700 Subject: [PATCH 019/860] Update deps of git2-curl --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index fc07a5db19..eaa716fc64 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -17,7 +17,7 @@ Intended to be used with the git2 crate. curl = "0.3" url = "1.0" log = "0.3" -git2 = "0.4" +git2 = { path = "..", version = "0.5", default-features = false } [dev-dependencies] civet = "0.8" From 08ae242d14176a20e4ddadf94db94282a3a3345d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 6 Oct 2016 15:42:26 -0700 Subject: [PATCH 020/860] Bump git2-curl to 0.6.0 --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index eaa716fc64..5ae45d156b 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.5.0" +version = "0.6.0" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/git2-rs" From 9ab1cac1fb9a0fe904ff0861fedc1aa2c6c5c4b4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 10 Oct 2016 16:28:49 -0700 Subject: [PATCH 021/860] pass TARGET on appveyor --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 8b05c5e6e4..31aaccb0ec 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,6 +18,6 @@ install: build: false test_script: - - cargo test - - cargo test --no-default-features - - cargo run --manifest-path systest/Cargo.toml + - cargo test --target %TARGET% + - cargo test --no-default-features --target %TARGET% + - cargo run --manifest-path systest/Cargo.toml --target %TARGET% From f59d2a053ed59364eb8bc74ac1ff9a6f3bc26574 Mon Sep 17 00:00:00 2001 From: raph Date: Wed, 12 Oct 2016 14:36:20 +0200 Subject: [PATCH 022/860] Update README.md Cargo says we should use `git2 = "0.5.0"` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b4b5e2cec..fec6b7c01f 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ libgit2 bindings for Rust ```toml [dependencies] -git2 = "0.3" +git2 = "0.5" ``` ## Building git2-rs From 9311c3962b3502b2c44d3ba5d26904b12d153457 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 17 Oct 2016 09:29:03 -0700 Subject: [PATCH 023/860] Make openssl-sys an optional dep --- libgit2-sys/Cargo.toml | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 8a572025e2..e80060d80b 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -25,40 +25,9 @@ cmake = "0.1.2" gcc = "0.3" [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] -openssl-sys = "0.7.0" - -[target.i686-unknown-linux-gnu.dependencies] -openssl-sys = "0.7.0" -[target.i586-unknown-linux-gnu.dependencies] -openssl-sys = "0.7.0" -[target.x86_64-unknown-linux-gnu.dependencies] -openssl-sys = "0.7.0" -[target.x86_64-unknown-linux-musl.dependencies] -openssl-sys = "0.7.0" -[target.aarch64-unknown-linux-gnu.dependencies] -openssl-sys = "0.7.0" -[target.powerpc64-unknown-linux-gnu.dependencies] -openssl-sys = "0.7.0" -[target.powerpc64le-unknown-linux-gnu.dependencies] -openssl-sys = "0.7.0" -[target.arm-unknown-linux-gnueabihf.dependencies] -openssl-sys = "0.7.0" -[target.armv7-unknown-linux-gnueabihf.dependencies] -openssl-sys = "0.7.0" -[target.i686-unknown-freebsd.dependencies] -openssl-sys = "0.7.0" -[target.x86_64-unknown-freebsd.dependencies] -openssl-sys = "0.7.0" -[target.x86_64-unknown-bitrig.dependencies] -openssl-sys = "0.7.0" -[target.x86_64-unknown-openbsd.dependencies] -openssl-sys = "0.7.0" -[target.x86_64-unknown-dragonfly.dependencies] -openssl-sys = "0.7.0" -[target.x86_64-sun-solaris.dependencies] -openssl-sys = "0.7.0" +openssl-sys = { version = "0.7.0", optional = true } [features] ssh = ["libssh2-sys"] -https = [] +https = ["openssl-sys"] curl = ["curl-sys"] From fc29bedf708932c1995639a30394b7545a5aeab5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 17 Oct 2016 09:30:05 -0700 Subject: [PATCH 024/860] Bump libgit2-sys to 0.5.1 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index e80060d80b..8e7177e026 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.5.0" +version = "0.5.1" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 9ace81016cc0be55743400abd07c3b12aff00a86 Mon Sep 17 00:00:00 2001 From: Andres Medina Date: Mon, 31 Oct 2016 10:14:08 -0700 Subject: [PATCH 025/860] allow empty git credential_helper previously, if .gitconfig had a credential_helper field that was empty the add_command function would crash due to trying to slice the empty command string from [1..]. Signed-off-by: Alpha Chen Signed-off-by: Andres Medina --- src/cred.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/cred.rs b/src/cred.rs index 94113b739f..c7f2f3938e 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -232,7 +232,11 @@ impl CredentialHelper { // see https://www.kernel.org/pub/software/scm/git/docs/technical // /api-credentials.html#_credential_helpers fn add_command(&mut self, cmd: Option<&str>) { - let cmd = match cmd { Some(s) => s, None => return }; + let cmd = match cmd { + Some("") | None => return, + Some(s) => s, + }; + if cmd.starts_with("!") { self.commands.push(cmd[1..].to_string()); } else if cmd.starts_with("/") || cmd.starts_with("\\") || @@ -443,6 +447,16 @@ echo username=c assert_eq!(p, "b"); } + #[test] + fn credential_helper6() { + let cfg = cfg! { + "credential.helper" => "" + }; + assert!(CredentialHelper::new("https://example.com/foo/bar") + .config(&cfg) + .execute().is_none()); + } + #[cfg(unix)] fn chmod(path: &Path) { use std::os::unix::prelude::*; From 5d5ee1fc8f1c9180aa1e118e628a2e69326e7521 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 1 Nov 2016 15:59:40 -0600 Subject: [PATCH 026/860] libgit2-sys: Add git_patch type and associated functions --- libgit2-sys/lib.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 04cfdfc749..2a77baab34 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -73,6 +73,7 @@ pub enum git_pathspec {} pub enum git_pathspec_match_list {} pub enum git_diff {} pub enum git_diff_stats {} +pub enum git_patch {} pub enum git_reflog {} pub enum git_reflog_entry {} pub enum git_describe_result {} @@ -2488,6 +2489,58 @@ extern { commit: *const git_oid, ancestor: *const git_oid) -> c_int; + // patch + pub fn git_patch_from_diff(out: *mut *mut git_patch, + diff: *mut git_diff, + idx: size_t) -> c_int; + pub fn git_patch_from_blobs(out: *mut *mut git_patch, + old_blob: *const git_blob, + old_as_path: *const c_char, + new_blob: *const git_blob, + new_as_path: *const c_char, + opts: *const git_diff_options) -> c_int; + pub fn git_patch_from_blob_and_buffer(out: *mut *mut git_patch, + old_blob: *const git_blob, + old_as_path: *const c_char, + buffer: *const c_char, + buffer_len: size_t, + buffer_as_path: *const c_char, + opts: *const git_diff_options) -> c_int; + pub fn git_patch_from_buffers(out: *mut *mut git_patch, + old_buffer: *const c_void, + old_len: size_t, + old_as_path: *const c_char, + new_buffer: *const c_char, + new_len: size_t, + new_as_path: *const c_char, + opts: *const git_diff_options) -> c_int; + pub fn git_patch_free(patch: *mut git_patch); + pub fn git_patch_get_delta(patch: *const git_patch) -> *const git_diff_delta; + pub fn git_patch_num_hunks(patch: *const git_patch) -> size_t; + pub fn git_patch_line_stats(total_context: *mut size_t, + total_additions: *mut size_t, + total_deletions: *mut size_t, + patch: *const git_patch) -> c_int; + pub fn git_patch_get_hunk(out: *mut *const git_diff_hunk, + lines_in_hunk: *mut size_t, + patch: *mut git_patch, + hunk_idx: size_t) -> c_int; + pub fn git_patch_num_lines_in_hunk(patch: *const git_patch, + hunk_idx: size_t) -> c_int; + pub fn git_patch_get_line_in_hunk(out: *mut *const git_diff_line, + patch: *mut git_patch, + hunk_idx: size_t, + line_of_hunk: size_t) -> c_int; + pub fn git_patch_size(patch: *mut git_patch, + include_context: c_int, + include_hunk_headers: c_int, + include_file_headers: c_int) -> size_t; + pub fn git_patch_print(patch: *mut git_patch, + print_cb: git_diff_line_cb, + payload: *mut c_void) -> c_int; + pub fn git_patch_to_buf(buf: *mut git_buf, + patch: *mut git_patch) -> c_int; + // reflog pub fn git_reflog_append(reflog: *mut git_reflog, id: *const git_oid, From 5f8f12c2eaa5ed4c1e6941bc3ff717d13e102602 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 1 Nov 2016 16:00:42 -0600 Subject: [PATCH 027/860] Add Patch type wrapping all associated libgit2 functions In particular, this now exposes the functionality to diff blobs and buffers. --- src/diff.rs | 2 +- src/lib.rs | 2 + src/patch.rs | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.rs | 9 +++ 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 src/patch.rs diff --git a/src/diff.rs b/src/diff.rs index 7c769eca0e..fbd0797faf 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -229,7 +229,7 @@ impl<'repo> Diff<'repo> { // TODO: num_deltas_of_type, format_email, find_similar } -extern fn print_cb(delta: *const raw::git_diff_delta, +pub extern fn print_cb(delta: *const raw::git_diff_delta, hunk: *const raw::git_diff_hunk, line: *const raw::git_diff_line, data: *mut c_void) -> c_int { diff --git a/src/lib.rs b/src/lib.rs index 67040cae0c..8999ea3708 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 patch::Patch; pub use proxy_options::ProxyOptions; pub use reference::{Reference, References, ReferenceNames}; pub use reflog::{Reflog, ReflogEntry, ReflogIter}; @@ -504,6 +505,7 @@ mod object; mod oid; mod packbuilder; mod pathspec; +mod patch; mod proxy_options; mod reference; mod reflog; diff --git a/src/patch.rs b/src/patch.rs new file mode 100644 index 0000000000..691df0181c --- /dev/null +++ b/src/patch.rs @@ -0,0 +1,201 @@ +use std::path::Path; +use libc::{c_char, c_int, c_void}; + +use {raw, Blob, Buf, Diff, DiffDelta, DiffHunk, DiffLine, DiffOptions, Error}; +use diff::{LineCb, print_cb}; +use util::{Binding, into_opt_c_string}; + +/// A structure representing the text changes in a single diff delta. +/// +/// This is an opaque structure. +pub struct Patch { + raw: *mut raw::git_patch, +} + +unsafe impl Send for Patch {} + +impl Binding for Patch { + type Raw = *mut raw::git_patch; + unsafe fn from_raw(raw: Self::Raw) -> Patch { + Patch { raw: raw } + } + fn raw(&self) -> Self::Raw { self.raw } +} + +impl Drop for Patch { + fn drop(&mut self) { + unsafe { raw::git_patch_free(self.raw) } + } +} + +impl Patch { + /// Return a Patch for one file in a Diff. + /// + /// Returns Ok(None) for an unchanged or binary file. + pub fn from_diff(diff: &Diff, idx: usize) -> Result, Error> { + let mut ret = 0 as *mut raw::git_patch; + unsafe { + try_call!(raw::git_patch_from_diff(&mut ret, diff.raw(), idx)); + Ok(Binding::from_raw_opt(ret)) + } + } + + /// Generate a Patch by diffing two blobs. + pub fn from_blobs(old_blob: &Blob, + old_path: Option<&Path>, + new_blob: &Blob, + new_path: Option<&Path>, + opts: Option<&mut DiffOptions>) + -> Result + { + let mut ret = 0 as *mut raw::git_patch; + let old_path = try!(into_opt_c_string(old_path)); + let new_path = try!(into_opt_c_string(new_path)); + unsafe { + try_call!(raw::git_patch_from_blobs(&mut ret, + old_blob.raw(), + old_path, + new_blob.raw(), + new_path, + opts.map(|s| s.raw()))); + Ok(Binding::from_raw(ret)) + } + } + + /// Generate a Patch by diffing a blob and a buffer. + pub fn from_blob_and_buffer(old_blob: &Blob, + old_path: Option<&Path>, + new_buffer: &[u8], + new_path: Option<&Path>, + opts: Option<&mut DiffOptions>) + -> Result + { + let mut ret = 0 as *mut raw::git_patch; + let old_path = try!(into_opt_c_string(old_path)); + let new_path = try!(into_opt_c_string(new_path)); + unsafe { + try_call!(raw::git_patch_from_blob_and_buffer(&mut ret, + old_blob.raw(), + old_path, + new_buffer.as_ptr() as *const c_char, + new_buffer.len(), + new_path, + opts.map(|s| s.raw()))); + Ok(Binding::from_raw(ret)) + } + } + + /// Generate a Patch by diffing two buffers. + pub fn from_buffers(old_buffer: &[u8], + old_path: Option<&Path>, + new_buffer: &[u8], + new_path: Option<&Path>, + opts: Option<&mut DiffOptions>) + -> Result + { + let mut ret = 0 as *mut raw::git_patch; + let old_path = try!(into_opt_c_string(old_path)); + let new_path = try!(into_opt_c_string(new_path)); + unsafe { + try_call!(raw::git_patch_from_buffers(&mut ret, + old_buffer.as_ptr() as *const c_void, + old_buffer.len(), + old_path, + new_buffer.as_ptr() as *const c_char, + new_buffer.len(), + new_path, + opts.map(|s| s.raw()))); + Ok(Binding::from_raw(ret)) + } + } + + /// Get the DiffDelta associated with the Patch. + pub fn delta(&self) -> DiffDelta { + unsafe { + Binding::from_raw(raw::git_patch_get_delta(self.raw) as *mut _) + } + } + + /// Get the number of hunks in the Patch. + pub fn num_hunks(&self) -> usize { + unsafe { + raw::git_patch_num_hunks(self.raw) + } + } + + /// Get the number of lines of context, additions, and deletions in the Patch. + pub fn line_stats(&self) -> Result<(usize, usize, usize), Error> { + let mut context = 0; + let mut additions = 0; + let mut deletions = 0; + unsafe { + try_call!(raw::git_patch_line_stats(&mut context, + &mut additions, + &mut deletions, + self.raw)); + } + Ok((context, additions, deletions)) + } + + /// Get a DiffHunk and its total line count from the Patch. + pub fn hunk(&mut self, hunk_idx: usize) -> Result<(DiffHunk, usize), Error> { + let mut ret = 0 as *const raw::git_diff_hunk; + let mut lines = 0; + unsafe { + try_call!(raw::git_patch_get_hunk(&mut ret, &mut lines, self.raw, hunk_idx)); + Ok((Binding::from_raw(ret), lines)) + } + } + + /// Get the number of lines in a hunk. + pub fn num_lines_in_hunk(&self, hunk_idx: usize) -> Result { + unsafe { + Ok(try_call!(raw::git_patch_num_lines_in_hunk(self.raw, hunk_idx)) as usize) + } + } + + /// Get a DiffLine from a hunk of the Patch. + pub fn line_in_hunk(&mut self, + hunk_idx: usize, + line_of_hunk: usize) -> Result { + let mut ret = 0 as *const raw::git_diff_line; + unsafe { + try_call!(raw::git_patch_get_line_in_hunk(&mut ret, + self.raw, + hunk_idx, + line_of_hunk)); + Ok(Binding::from_raw(ret)) + } + } + + /// Get the size of a Patch's diff data in bytes. + pub fn size(&self, + include_context: bool, + include_hunk_headers: bool, + include_file_headers: bool) -> usize { + unsafe { + raw::git_patch_size(self.raw, + include_context as c_int, + include_hunk_headers as c_int, + include_file_headers as c_int) + } + } + + /// Print the Patch to text via a callback. + pub fn print(&mut self, mut line_cb: &mut LineCb) -> Result<(), Error> { + let ptr = &mut line_cb as *mut _ as *mut c_void; + unsafe { + try_call!(raw::git_patch_print(self.raw, print_cb, ptr)); + return Ok(()) + } + } + + /// Get the Patch text as a Buf. + pub fn to_buf(&mut self) -> Result { + let buf = Buf::new(); + unsafe { + try_call!(raw::git_patch_to_buf(buf.raw(), self.raw)); + } + Ok(buf) + } +} diff --git a/src/util.rs b/src/util.rs index 91dd9b1de2..e111628eae 100644 --- a/src/util.rs +++ b/src/util.rs @@ -141,3 +141,12 @@ impl IntoCString for Vec { Ok(try!(CString::new(self))) } } + +pub fn into_opt_c_string(opt_s: Option) -> Result, Error> + where S: IntoCString +{ + match opt_s { + None => Ok(None), + Some(s) => Ok(Some(try!(s.into_c_string()))), + } +} From a301ea9613d4820d51cac217de9fb18087f14ed3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 5 Nov 2016 22:33:41 -0700 Subject: [PATCH 028/860] Bump dep on openssl crate --- Cargo.toml | 6 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/lib.rs | 126 +--------------------------------------- src/lib.rs | 128 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 134 insertions(+), 128 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 16405646a9..a4229ad7e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,10 @@ bitflags = "0.7" libc = "0.2" libgit2-sys = { path = "libgit2-sys", version = "0.5" } +[target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] +openssl-sys = { version = "0.9.0", optional = true } +openssl-probe = { version = "0.1", optional = true } + [dev-dependencies] docopt = "0.6" rustc-serialize = "0.3" @@ -31,7 +35,7 @@ tempdir = "0.3" unstable = [] default = ["ssh", "https", "curl"] ssh = ["libgit2-sys/ssh"] -https = ["libgit2-sys/https"] +https = ["libgit2-sys/https", "openssl-sys", "openssl-probe"] curl = ["libgit2-sys/curl"] [workspace] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 8e7177e026..724411b9cb 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -25,7 +25,7 @@ cmake = "0.1.2" gcc = "0.3" [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] -openssl-sys = { version = "0.7.0", optional = true } +openssl-sys = { version = ">= 0", optional = true } [features] ssh = ["libssh2-sys"] diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 2a77baab34..650bd4da80 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -7,7 +7,7 @@ extern crate libssh2_sys as libssh2; #[cfg(feature = "curl")] extern crate curl_sys; #[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] -extern crate openssl_sys as openssl; +extern crate openssl_sys; extern crate libz_sys as libz; use libc::{c_int, c_char, c_uint, size_t, c_uchar, c_void}; @@ -1330,130 +1330,6 @@ git_enum! { pub type git_packbuilder_foreach_cb = extern fn(*const c_void, size_t, *mut c_void) -> c_int; -/// Initialize openssl for the libgit2 library -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] -pub fn openssl_init() { - openssl::init(); - - if !cfg!(target_os = "linux") && !cfg!(target_os = "freebsd") { return } - - // Currently, libgit2 leverages OpenSSL for SSL support when cloning - // repositories over HTTPS. This means that we're picking up an OpenSSL - // dependency on non-Windows platforms (where it has its own HTTPS - // subsystem). As a result, we need to link to OpenSSL. - // - // Now actually *linking* to OpenSSL isn't so hard. We just need to make - // sure to use pkg-config to discover any relevant system dependencies for - // differences between distributions like CentOS and Ubuntu. The actual - // trickiness comes about when we start *distributing* the resulting - // binaries. Currently Cargo is distributed in binary form as nightlies, - // which means we're distributing a binary with OpenSSL linked in. - // - // For historical reasons, the Linux nightly builder is running a CentOS - // distribution in order to have as much ABI compatibility with other - // distributions as possible. Sadly, however, this compatibility does not - // extend to OpenSSL. Currently OpenSSL has two major versions, 0.9 and 1.0, - // which are incompatible (many ABI differences). The CentOS builder we - // build on has version 1.0, as do most distributions today. Some still have - // 0.9, however. This means that if we are to distribute the binaries built - // by the CentOS machine, we would only be compatible with OpenSSL 1.0 and - // we would fail to run (a dynamic linker error at runtime) on systems with - // only 9.8 installed (hopefully). - // - // But wait, the plot thickens! Apparently CentOS has dubbed their OpenSSL - // library as `libssl.so.10`, notably the `10` is included at the end. On - // the other hand Ubuntu, for example, only distributes `libssl.so`. This - // means that the binaries created at CentOS are hard-wired to probe for a - // file called `libssl.so.10` at runtime (using the LD_LIBRARY_PATH), which - // will not be found on ubuntu. The conclusion of this is that binaries - // built on CentOS cannot be distributed to Ubuntu and run successfully. - // - // There are a number of sneaky things we could do, including, but not - // limited to: - // - // 1. Create a shim program which runs "just before" cargo runs. The - // responsibility of this shim program would be to locate `libssl.so`, - // whatever it's called, on the current system, make sure there's a - // symlink *somewhere* called `libssl.so.10`, and then set up - // LD_LIBRARY_PATH and run the actual cargo. - // - // This approach definitely seems unconventional, and is borderline - // overkill for this problem. It's also dubious if we can find a - // libssl.so reliably on the target system. - // - // 2. Somehow re-work the CentOS installation so that the linked-against - // library is called libssl.so instead of libssl.so.10 - // - // The problem with this approach is that systems with 0.9 installed will - // start to silently fail, due to also having libraries called libssl.so - // (probably symlinked under a more appropriate version). - // - // 3. Compile Cargo against both OpenSSL 1.0 *and* OpenSSL 0.9, and - // distribute both. Also make sure that the linked-against name of the - // library is `libssl.so`. At runtime we determine which version is - // installed, and we then the appropriate binary. - // - // This approach clearly has drawbacks in terms of infrastructure and - // feasibility. - // - // 4. Build a nightly of Cargo for each distribution we'd like to support. - // You would then pick the appropriate Cargo nightly to install locally. - // - // So, with all this in mind, the decision was made to *statically* link - // OpenSSL. This solves any problem of relying on a downstream OpenSSL - // version being available. This does, however, open a can of worms related - // to security issues. It's generally a good idea to dynamically link - // OpenSSL as you'll get security updates over time without having to do - // anything (the system administrator will update the local openssl - // package). By statically linking, we're forfeiting this feature. - // - // The conclusion was made it is likely appropriate for the Cargo nightlies - // to statically link OpenSSL, but highly encourage distributions and - // packagers of Cargo to dynamically link OpenSSL. Packagers are targeting - // one system and are distributing to only that system, so none of the - // problems mentioned above would arise. - // - // In order to support this, a new package was made: openssl-static-sys. - // This package currently performs a fairly simple task: - // - // 1. Run pkg-config to discover where openssl is installed. - // 2. If openssl is installed in a nonstandard location, *and* static copies - // of the libraries are available, copy them to $OUT_DIR. - // - // This library will bring in libssl.a and libcrypto.a into the local build, - // allowing them to be picked up by this crate. This allows us to configure - // our own buildbots to have pkg-config point to these local pre-built - // copies of a static OpenSSL (with very few dependencies) while allowing - // most other builds of Cargo to naturally dynamically link OpenSSL. - // - // So in summary, if you're with me so far, we've statically linked OpenSSL - // to the Cargo binary (or any binary, for that matter) and we're ready to - // distribute it to *all* linux distributions. Remember that our original - // intent for openssl was for HTTPS support, which implies that we need some - // for of CA certificate store to validate certificates. This is normally - // installed in a standard system location. - // - // Unfortunately, as one might imagine, OpenSSL is configured for where this - // standard location is at *build time*, but it often varies widely - // per-system. Consequently, it was discovered that OpenSSL will respect the - // SSL_CERT_FILE and SSL_CERT_DIR environment variables in order to assist - // in discovering the location of this file (hurray!). - // - // So, finally getting to the point, this function solely exists to support - // our static builds of OpenSSL by probing for the "standard system - // location" of certificates and setting relevant environment variable to - // point to them. - // - // Ah, and as a final note, this is only a problem on Linux, not on OS X. On - // OS X the OpenSSL binaries are stable enough that we can just rely on - // dynamic linkage (plus they have some weird modifications to OpenSSL which - // means we wouldn't want to link statically). - openssl::probe::init_ssl_cert_env_vars(); -} - -#[cfg(any(windows, target_os = "macos", target_os = "ios", not(feature = "https")))] -pub fn openssl_init() {} - extern { // threads pub fn git_libgit2_init() -> c_int; diff --git a/src/lib.rs b/src/lib.rs index 8999ea3708..2cdebf9551 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -526,7 +526,7 @@ mod treebuilder; fn init() { static INIT: Once = ONCE_INIT; INIT.call_once(|| unsafe { - raw::openssl_init(); + openssl_init(); let r = raw::git_libgit2_init(); assert!(r >= 0, "couldn't initialize the libgit2 library: {}", r); @@ -537,6 +537,132 @@ fn init() { } } +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] +fn openssl_init() { + extern crate openssl_sys; + extern crate openssl_probe; + + openssl_sys::init(); + + if !cfg!(target_os = "linux") && !cfg!(target_os = "freebsd") { return } + + // Currently, libgit2 leverages OpenSSL for SSL support when cloning + // repositories over HTTPS. This means that we're picking up an OpenSSL + // dependency on non-Windows platforms (where it has its own HTTPS + // subsystem). As a result, we need to link to OpenSSL. + // + // Now actually *linking* to OpenSSL isn't so hard. We just need to make + // sure to use pkg-config to discover any relevant system dependencies for + // differences between distributions like CentOS and Ubuntu. The actual + // trickiness comes about when we start *distributing* the resulting + // binaries. Currently Cargo is distributed in binary form as nightlies, + // which means we're distributing a binary with OpenSSL linked in. + // + // For historical reasons, the Linux nightly builder is running a CentOS + // distribution in order to have as much ABI compatibility with other + // distributions as possible. Sadly, however, this compatibility does not + // extend to OpenSSL. Currently OpenSSL has two major versions, 0.9 and 1.0, + // which are incompatible (many ABI differences). The CentOS builder we + // build on has version 1.0, as do most distributions today. Some still have + // 0.9, however. This means that if we are to distribute the binaries built + // by the CentOS machine, we would only be compatible with OpenSSL 1.0 and + // we would fail to run (a dynamic linker error at runtime) on systems with + // only 9.8 installed (hopefully). + // + // But wait, the plot thickens! Apparently CentOS has dubbed their OpenSSL + // library as `libssl.so.10`, notably the `10` is included at the end. On + // the other hand Ubuntu, for example, only distributes `libssl.so`. This + // means that the binaries created at CentOS are hard-wired to probe for a + // file called `libssl.so.10` at runtime (using the LD_LIBRARY_PATH), which + // will not be found on ubuntu. The conclusion of this is that binaries + // built on CentOS cannot be distributed to Ubuntu and run successfully. + // + // There are a number of sneaky things we could do, including, but not + // limited to: + // + // 1. Create a shim program which runs "just before" cargo runs. The + // responsibility of this shim program would be to locate `libssl.so`, + // whatever it's called, on the current system, make sure there's a + // symlink *somewhere* called `libssl.so.10`, and then set up + // LD_LIBRARY_PATH and run the actual cargo. + // + // This approach definitely seems unconventional, and is borderline + // overkill for this problem. It's also dubious if we can find a + // libssl.so reliably on the target system. + // + // 2. Somehow re-work the CentOS installation so that the linked-against + // library is called libssl.so instead of libssl.so.10 + // + // The problem with this approach is that systems with 0.9 installed will + // start to silently fail, due to also having libraries called libssl.so + // (probably symlinked under a more appropriate version). + // + // 3. Compile Cargo against both OpenSSL 1.0 *and* OpenSSL 0.9, and + // distribute both. Also make sure that the linked-against name of the + // library is `libssl.so`. At runtime we determine which version is + // installed, and we then the appropriate binary. + // + // This approach clearly has drawbacks in terms of infrastructure and + // feasibility. + // + // 4. Build a nightly of Cargo for each distribution we'd like to support. + // You would then pick the appropriate Cargo nightly to install locally. + // + // So, with all this in mind, the decision was made to *statically* link + // OpenSSL. This solves any problem of relying on a downstream OpenSSL + // version being available. This does, however, open a can of worms related + // to security issues. It's generally a good idea to dynamically link + // OpenSSL as you'll get security updates over time without having to do + // anything (the system administrator will update the local openssl + // package). By statically linking, we're forfeiting this feature. + // + // The conclusion was made it is likely appropriate for the Cargo nightlies + // to statically link OpenSSL, but highly encourage distributions and + // packagers of Cargo to dynamically link OpenSSL. Packagers are targeting + // one system and are distributing to only that system, so none of the + // problems mentioned above would arise. + // + // In order to support this, a new package was made: openssl-static-sys. + // This package currently performs a fairly simple task: + // + // 1. Run pkg-config to discover where openssl is installed. + // 2. If openssl is installed in a nonstandard location, *and* static copies + // of the libraries are available, copy them to $OUT_DIR. + // + // This library will bring in libssl.a and libcrypto.a into the local build, + // allowing them to be picked up by this crate. This allows us to configure + // our own buildbots to have pkg-config point to these local pre-built + // copies of a static OpenSSL (with very few dependencies) while allowing + // most other builds of Cargo to naturally dynamically link OpenSSL. + // + // So in summary, if you're with me so far, we've statically linked OpenSSL + // to the Cargo binary (or any binary, for that matter) and we're ready to + // distribute it to *all* linux distributions. Remember that our original + // intent for openssl was for HTTPS support, which implies that we need some + // for of CA certificate store to validate certificates. This is normally + // installed in a standard system location. + // + // Unfortunately, as one might imagine, OpenSSL is configured for where this + // standard location is at *build time*, but it often varies widely + // per-system. Consequently, it was discovered that OpenSSL will respect the + // SSL_CERT_FILE and SSL_CERT_DIR environment variables in order to assist + // in discovering the location of this file (hurray!). + // + // So, finally getting to the point, this function solely exists to support + // our static builds of OpenSSL by probing for the "standard system + // location" of certificates and setting relevant environment variable to + // point to them. + // + // Ah, and as a final note, this is only a problem on Linux, not on OS X. On + // OS X the OpenSSL binaries are stable enough that we can just rely on + // dynamic linkage (plus they have some weird modifications to OpenSSL which + // means we wouldn't want to link statically). + openssl_probe::init_ssl_cert_env_vars(); +} + +#[cfg(any(windows, target_os = "macos", target_os = "ios", not(feature = "https")))] +fn openssl_init() {} + unsafe fn opt_bytes<'a, T>(_anchor: &'a T, c: *const libc::c_char) -> Option<&'a [u8]> { if c.is_null() { From 1aa4791038c41974553d32f679ab0d0dd9529971 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 5 Nov 2016 22:57:48 -0700 Subject: [PATCH 029/860] Add a shim for backcompat --- libgit2-sys/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 650bd4da80..a8a562493c 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1330,6 +1330,9 @@ git_enum! { pub type git_packbuilder_foreach_cb = extern fn(*const c_void, size_t, *mut c_void) -> c_int; +#[doc(hidden)] +pub fn openssl_init() {} + extern { // threads pub fn git_libgit2_init() -> c_int; From 624af2e6e9bbb1771841dc5ac587d94cff80b6c9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 6 Nov 2016 08:36:03 -0800 Subject: [PATCH 030/860] Bump libgit2-sys to 0.5.2 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 724411b9cb..74e26f74ec 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.5.1" +version = "0.5.2" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 1da6671e4c804289b011831b62999f594312a38d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 6 Nov 2016 08:36:39 -0800 Subject: [PATCH 031/860] Bump to 0.5.1 --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a4229ad7e9..f3cbeae34f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.5.0" +version = "0.5.1" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -19,7 +19,7 @@ repositories. url = "1.0" bitflags = "0.7" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.5" } +libgit2-sys = { path = "libgit2-sys", version = "0.5.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 2788860466af377249fba5c0ff1dcc4dcedf7f2e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 6 Nov 2016 21:27:13 -0800 Subject: [PATCH 032/860] Update libgit2 submodule --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 9fbbb0eec5..5fe5557e8a 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 9fbbb0eec5fc46cc9c36abf25b9baf653eb12372 +Subproject commit 5fe5557e8a8d3fd6a4617c2d8c863c1f62848020 From fc3f8872d7b61ecb3a6347d7086054a13df128a4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 6 Nov 2016 21:29:34 -0800 Subject: [PATCH 033/860] Depend on ctest from crates.io --- systest/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systest/Cargo.toml b/systest/Cargo.toml index 22b85073c1..f43b0cf635 100644 --- a/systest/Cargo.toml +++ b/systest/Cargo.toml @@ -9,4 +9,4 @@ libgit2-sys = { path = "../libgit2-sys" } libc = "0.2" [build-dependencies] -ctest = { git = "https://github.com/alexcrichton/ctest" } +ctest = "0.1" From 12d36de1d4be90ce88a72744c996be3b9f4d3ba8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 Nov 2016 12:54:44 -0800 Subject: [PATCH 034/860] Revert back to earlier openssl --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f3cbeae34f..c06ed3964e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ libc = "0.2" libgit2-sys = { path = "libgit2-sys", version = "0.5.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] -openssl-sys = { version = "0.9.0", optional = true } +openssl-sys = { version = "0.7.0", optional = true } openssl-probe = { version = "0.1", optional = true } [dev-dependencies] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 74e26f74ec..a083852a60 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -14,9 +14,9 @@ name = "libgit2_sys" path = "lib.rs" [dependencies] -curl-sys = { version = ">= 0", optional = true } +curl-sys = { version = "0.2", optional = true } libc = "0.2" -libssh2-sys = { version = ">= 0", optional = true } +libssh2-sys = { version = "0.1", optional = true } libz-sys = ">= 0" [build-dependencies] @@ -25,7 +25,7 @@ cmake = "0.1.2" gcc = "0.3" [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] -openssl-sys = { version = ">= 0", optional = true } +openssl-sys = { version = "0.7", optional = true } [features] ssh = ["libssh2-sys"] From 4fada5b715176dfed252c5f1d5667aff45fad9e9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 Nov 2016 12:54:58 -0800 Subject: [PATCH 035/860] Bump to libgit2-sys 0.5.3 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index a083852a60..d76c23c0b6 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.5.2" +version = "0.5.3" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From b2f6295c29cf709c2d4f7971c7b9140e17147135 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 Nov 2016 12:55:45 -0800 Subject: [PATCH 036/860] Bump to 0.5.2 --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c06ed3964e..871d4dc35b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.5.1" +version = "0.5.2" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -19,7 +19,7 @@ repositories. url = "1.0" bitflags = "0.7" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.5.2" } +libgit2-sys = { path = "libgit2-sys", version = "0.5.3" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.7.0", optional = true } From 754e8b5e974f1b05ba56822448ae20fff98b2c90 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 Nov 2016 12:57:13 -0800 Subject: [PATCH 037/860] Bump versions of dependencies --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 871d4dc35b..3bbbb9f2a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ libc = "0.2" libgit2-sys = { path = "libgit2-sys", version = "0.5.3" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] -openssl-sys = { version = "0.7.0", optional = true } +openssl-sys = { version = "0.9.0", optional = true } openssl-probe = { version = "0.1", optional = true } [dev-dependencies] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index d76c23c0b6..81e0ab54d8 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -14,9 +14,9 @@ name = "libgit2_sys" path = "lib.rs" [dependencies] -curl-sys = { version = "0.2", optional = true } +curl-sys = { version = "0.3", optional = true } libc = "0.2" -libssh2-sys = { version = "0.1", optional = true } +libssh2-sys = { version = "0.2", optional = true } libz-sys = ">= 0" [build-dependencies] @@ -25,7 +25,7 @@ cmake = "0.1.2" gcc = "0.3" [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] -openssl-sys = { version = "0.7", optional = true } +openssl-sys = { version = "0.9", optional = true } [features] ssh = ["libssh2-sys"] From b09fd6cfd568073d046fdddb3c1c011101530eba Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 Nov 2016 12:57:40 -0800 Subject: [PATCH 038/860] Bump libgit2-sys to 0.6.0 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 81e0ab54d8..7f135040b3 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.5.3" +version = "0.6.0" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 6bfd2b6963fd3314910717426b5615bcd683ed47 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 Nov 2016 12:58:08 -0800 Subject: [PATCH 039/860] Bump to 0.6.0 --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3bbbb9f2a8..f5e5d28226 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.5.2" +version = "0.6.0" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -19,7 +19,7 @@ repositories. url = "1.0" bitflags = "0.7" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.5.3" } +libgit2-sys = { path = "libgit2-sys", version = "0.6.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 1400714b02c638372705e061465ec81326b75474 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 Nov 2016 12:59:24 -0800 Subject: [PATCH 040/860] Bump git2-curl to 0.7.0 --- git2-curl/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 5ae45d156b..417acf63a6 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -14,10 +14,10 @@ Intended to be used with the git2 crate. """ [dependencies] -curl = "0.3" +curl = "0.4" url = "1.0" log = "0.3" -git2 = { path = "..", version = "0.5", default-features = false } +git2 = { path = "..", version = "0.6", default-features = false } [dev-dependencies] civet = "0.8" From 000c407240bcd42f74c2b6de94f4251c1be12c61 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 Nov 2016 12:59:58 -0800 Subject: [PATCH 041/860] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fec6b7c01f..c97c8274c5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ libgit2 bindings for Rust ```toml [dependencies] -git2 = "0.5" +git2 = "0.6" ``` ## Building git2-rs From 96362427df3855b981c87d6303a7e8c402fd221c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 Nov 2016 13:00:11 -0800 Subject: [PATCH 042/860] Actually bump git2-curl --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 417acf63a6..6b2d6881d8 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.6.0" +version = "0.7.0" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/git2-rs" From 4b88c1064e260f5c99681dc11d40cf2420ecfb6e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 9 Nov 2016 14:22:56 -0800 Subject: [PATCH 043/860] libgit2-sys: Add git_revwalk_hide_cb and git_revwalk_add_hide_cb --- libgit2-sys/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a8a562493c..e39584f16f 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -641,6 +641,8 @@ pub type git_treewalk_cb = extern fn(*const c_char, *const git_tree_entry, pub type git_treebuilder_filter_cb = extern fn(*const git_tree_entry, *mut c_void) -> c_int; +pub type git_revwalk_hide_cb = extern fn(*const git_oid, *mut c_void) -> c_int; + #[repr(C)] #[derive(Copy, Clone)] pub struct git_buf { @@ -2211,6 +2213,9 @@ extern { refname: *const c_char) -> c_int; pub fn git_revwalk_hide_glob(walk: *mut git_revwalk, refname: *const c_char) -> c_int; + pub fn git_revwalk_add_hide_cb(walk: *mut git_revwalk, + hide_cb: git_revwalk_hide_cb, + payload: *mut c_void) -> c_int; pub fn git_revwalk_next(out: *mut git_oid, walk: *mut git_revwalk) -> c_int; From fd6fa405a618155ff085593c65918156235cce02 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 9 Nov 2016 19:27:33 -0800 Subject: [PATCH 044/860] Update logic of registering dependencies --- libgit2-sys/build.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 330dd4cc14..d36bd4c2f0 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -167,11 +167,18 @@ fn main() { } fn register_dep(dep: &str) { - match env::var(&format!("DEP_{}_ROOT", dep)) { - Ok(s) => { - prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig")); + if let Some(s) = env::var_os(&format!("DEP_{}_ROOT", dep)) { + prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig")); + return + } + if let Some(s) = env::var_os(&format!("DEP_{}_INCLUDE", dep)) { + let root = Path::new(&s).parent().unwrap(); + env::set_var(&format!("DEP_{}_ROOT", dep), root); + let path = root.join("lib/pkgconfig"); + if path.exists() { + prepend("PKG_CONFIG_PATH", path); + return } - Err(..) => {} } } From 9adc59c7f4af25d86a31b3d3d69e580212590861 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 9 Nov 2016 19:34:46 -0800 Subject: [PATCH 045/860] Bump libgit2-sys to 0.6.1 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 7f135040b3..5b6f7fb44b 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.0" +version = "0.6.1" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 520f0d557e1a0461c2fdaee5b19bb4d79ee84993 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 1 Jul 2016 18:23:05 -0700 Subject: [PATCH 046/860] Support GIT_REPOSITORY_OPEN_NO_DOTGIT and GIT_REPOSITORY_OPEN_FROM_ENV Update libgit2 to a version with support for these flags. --- libgit2-sys/lib.rs | 2 ++ src/lib.rs | 4 ++++ src/repo.rs | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index e39584f16f..e3f1fb51aa 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -867,6 +867,8 @@ git_enum! { GIT_REPOSITORY_OPEN_NO_SEARCH = (1 << 0), GIT_REPOSITORY_OPEN_CROSS_FS = (1 << 1), GIT_REPOSITORY_OPEN_BARE = (1 << 2), + GIT_REPOSITORY_OPEN_NO_DOTGIT = (1 << 3), + GIT_REPOSITORY_OPEN_FROM_ENV = (1 << 4), } } diff --git a/src/lib.rs b/src/lib.rs index 2cdebf9551..7d9cbd69a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -461,6 +461,10 @@ bitflags! { 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, + /// Don't try appending `/.git` to the specified repository path. + const REPOSITORY_OPEN_NO_DOTGIT = raw::GIT_REPOSITORY_OPEN_NO_DOTGIT as u32, + /// Respect environment variables like `$GIT_DIR`. + const REPOSITORY_OPEN_FROM_ENV = raw::GIT_REPOSITORY_OPEN_FROM_ENV as u32, } } diff --git a/src/repo.rs b/src/repo.rs index 10eb92a71e..277dc8f3bc 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -75,6 +75,13 @@ impl Repository { /// bare even if it isn't, ignoring any working directory, and defer /// loading the repository configuration for performance. /// + /// If flags contains REPOSITORY_OPEN_NO_DOTGIT, don't try appending + /// `/.git` to `path`. + /// + /// If flags contains REPOSITORY_OPEN_FROM_ENV, `open_ext` will ignore + /// other flags and `ceiling_dirs`, and respect the same environment + /// variables git does. Note, however, that `path` overrides `$GIT_DIR`. + /// /// 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. From b6454749f7df6c61d94df038719f07d6bdfeea69 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 1 Jul 2016 18:31:57 -0700 Subject: [PATCH 047/860] Add Repository::open_from_env as additional binding to git_repository_open_ext Repository::open_ext can't fully support the GIT_REPOSITORY_OPEN_FROM_ENV flag of git_repository_open_ext, because it doesn't allow passing a NULL path. Add a new binding Repository::open_from_env to handle this case. This also makes the common case (opening a repository exactly as git would) much simpler. --- src/repo.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 277dc8f3bc..64cc71e02a 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -60,6 +60,23 @@ impl Repository { } } + /// Find and open an existing repository, respecting git environment + /// variables. This acts like `open_ext` with the + /// `REPOSITORY_OPEN_FROM_ENV` flag, but additionally respects `$GIT_DIR`. + /// With `$GIT_DIR` unset, this will search for a repository starting in + /// the current directory. + pub fn open_from_env() -> Result { + init(); + let mut ret = 0 as *mut raw::git_repository; + unsafe { + try_call!(raw::git_repository_open_ext(&mut ret, + 0 as *const _, + raw::GIT_REPOSITORY_OPEN_FROM_ENV, + 0 as *const _)); + Ok(Binding::from_raw(ret)) + } + } + /// Find and open an existing repository, with additional options. /// /// If flags contains REPOSITORY_OPEN_NO_SEARCH, the path must point @@ -80,7 +97,8 @@ impl Repository { /// /// If flags contains REPOSITORY_OPEN_FROM_ENV, `open_ext` will ignore /// other flags and `ceiling_dirs`, and respect the same environment - /// variables git does. Note, however, that `path` overrides `$GIT_DIR`. + /// variables git does. Note, however, that `path` overrides `$GIT_DIR`; to + /// respect `$GIT_DIR` as well, use `open_from_env`. /// /// ceiling_dirs specifies a list of paths that the search through parent /// directories will stop before entering. Use the functions in std::env From 0334cf039b92c19706833f41d4a2e0fb11d25e62 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 10 Nov 2016 11:01:08 -0800 Subject: [PATCH 048/860] Fix compile on MSVC --- src/repo.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 64cc71e02a..4abdfc36d4 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -68,10 +68,11 @@ impl Repository { pub fn open_from_env() -> Result { init(); let mut ret = 0 as *mut raw::git_repository; + let flags = raw::GIT_REPOSITORY_OPEN_FROM_ENV; unsafe { try_call!(raw::git_repository_open_ext(&mut ret, 0 as *const _, - raw::GIT_REPOSITORY_OPEN_FROM_ENV, + flags as c_uint, 0 as *const _)); Ok(Binding::from_raw(ret)) } From 3c61ccd7c66787638fc3582ab0aa303316f4529d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 11 Nov 2016 07:18:35 -0800 Subject: [PATCH 049/860] Update libgit2 --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 5fe5557e8a..b7822050c9 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 5fe5557e8a8d3fd6a4617c2d8c863c1f62848020 +Subproject commit b7822050c99b8ea198d96e98cb720aa24a8230d0 From 22d385bd1999d0fe07c3ceb67e43103ca7f5f677 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 11 Nov 2016 07:18:53 -0800 Subject: [PATCH 050/860] Bump libgit2-sys to 0.6.2 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 5b6f7fb44b..1d5668a212 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.1" +version = "0.6.2" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 6b910aa062291591255f6023aaecb578fb4435ab Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Sat, 12 Nov 2016 08:08:29 -0800 Subject: [PATCH 051/860] add git_config_set_multivar --- libgit2-sys/lib.rs | 4 ++++ src/config.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index e3f1fb51aa..6c492bb20a 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2010,6 +2010,10 @@ extern { pub fn git_config_set_int64(cfg: *mut git_config, name: *const c_char, value: i64) -> c_int; + pub fn git_config_set_multivar(cfg: *mut git_config, + name: *const c_char, + regexp: *const c_char, + value: *const c_char) -> c_int; pub fn git_config_set_string(cfg: *mut git_config, name: *const c_char, value: *const c_char) -> c_int; diff --git a/src/config.rs b/src/config.rs index 4c15873cdc..93a9d356e2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -326,6 +326,18 @@ impl Config { Ok(()) } + /// Set the value of an multivar config variable in the config file with the + /// highest level (usually the local one). + pub fn set_multivar(&mut self, name: &str, regexp: &str, value: &str) -> Result<(), Error> { + let name = try!(CString::new(name)); + let regexp = try!(CString::new(regexp)); + let value = try!(CString::new(value)); + unsafe { + try_call!(raw::git_config_set_multivar(self.raw, name, regexp, value)); + } + Ok(()) + } + /// Set the value of a string config variable in the config file with the /// highest level (usually the local one). pub fn set_str(&mut self, name: &str, value: &str) -> Result<(), Error> { @@ -534,6 +546,25 @@ mod tests { } } + #[test] + fn multivar() { + let td = TempDir::new("test").unwrap(); + let path = td.path().join("foo"); + File::create(&path).unwrap(); + + let mut cfg = Config::open(&path).unwrap(); + cfg.set_multivar("foo.bar", "^$", "baz").unwrap(); + cfg.set_multivar("foo.bar", "^$", "qux").unwrap(); + + let mut values: Vec = cfg.entries(None) + .unwrap() + .into_iter() + .map(|entry| entry.unwrap().value().unwrap().into()) + .collect(); + values.sort(); + assert_eq!(values, ["baz", "qux"]); + } + #[test] fn parse() { assert_eq!(Config::parse_bool("").unwrap(), false); From 06b1cb301b4823479e2d3c90b0518e97a217f26c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 19 Nov 2016 08:56:20 -0800 Subject: [PATCH 052/860] Update travis token --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d8aa97d04c..1ace5bdf6d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,4 +41,4 @@ addons: - libdw-dev env: global: - secure: HlDs6Eyhy/67Wmqd6frmCnOMYQyqbv2ulL9qqqFF2zdlinJ2/Z0FDs+0GHNWu0BQ9v6+51KHbhieUaz3dTYDCKPlDiA2OmE8DQuXloxrrJfGmPLc1F+cKQGn5a5FrIrLJDkEpcfWXZItRtzSPkpVNEWGA66Osx50/Nd8lkdjFYA= + secure: "SVk5cv4VnBQAoaBXt9pIHk+FQ7Z58zT5EaPo7Ac81LltKztwHovhN/R1otKzgrAJqFsZ/nKR4cGyQGbYtfVJcsqweQVM75LI6Oh6lYyEdfX211ZI3SWQ50JO93CmwLtanC5UpECdXvJLCgXrHGJXuL1oi7hySGy47/yQlKH6eaM=" From 7d1a160291d18def2cade37fe833dd40ed70cedc Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 22 Nov 2016 01:26:37 +0100 Subject: [PATCH 053/860] Switch from whitelist to blacklist in detecting OpenSSL path This enables support for OpenBSD and NetBSD (and possibly DragonFlyBSD?). --- src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7d9cbd69a8..0800aeb2cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -548,8 +548,6 @@ fn openssl_init() { openssl_sys::init(); - if !cfg!(target_os = "linux") && !cfg!(target_os = "freebsd") { return } - // Currently, libgit2 leverages OpenSSL for SSL support when cloning // repositories over HTTPS. This means that we're picking up an OpenSSL // dependency on non-Windows platforms (where it has its own HTTPS From d7b28f4c62e3cc0400ff7df83da0c747637d63d9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 23 Nov 2016 18:47:58 -0800 Subject: [PATCH 054/860] Bump to 0.6.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f5e5d28226..f7b9d471b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.0" +version = "0.6.1" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 188ef0a3164d2c05df6fb364519fed72e0214a56 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 23 Nov 2016 18:49:08 -0800 Subject: [PATCH 055/860] Bump libgit2-sys to 0.6.3 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 1d5668a212..5c88a59f56 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.2" +version = "0.6.3" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 29481da32511f608669bb4ab5d408088f8d5eacc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 23 Nov 2016 18:49:38 -0800 Subject: [PATCH 056/860] Bump dep on libgit2-sys --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f7b9d471b5..c3781dace9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ repositories. url = "1.0" bitflags = "0.7" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.6.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.6.3" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 402378e5d64b3d260cbe87f2efca4c805839e38d Mon Sep 17 00:00:00 2001 From: Silvio Fricke Date: Fri, 25 Nov 2016 10:24:28 +0100 Subject: [PATCH 057/860] fix wrong name break_rewries to break_rewrites Signed-off-by: Silvio Fricke --- src/diff.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diff.rs b/src/diff.rs index fbd0797faf..b3ae71f52a 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -1017,7 +1017,7 @@ impl DiffFindOptions { } /// Actually split large rewrites into delete/add pairs - pub fn break_rewries(&mut self, find: bool) -> &mut DiffFindOptions { + pub fn break_rewrites(&mut self, find: bool) -> &mut DiffFindOptions { self.flag(raw::GIT_DIFF_BREAK_REWRITES, find) } From 071902aa24be86bbb5dc8512f2290f69968c2959 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 26 Nov 2016 09:06:16 -0800 Subject: [PATCH 058/860] Push init into libgit2-sys --- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/lib.rs | 39 +++++++++++++++++++++++++++++++++------ src/lib.rs | 21 +++++++-------------- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 5c88a59f56..8d1d6859e3 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -16,7 +16,7 @@ path = "lib.rs" [dependencies] curl-sys = { version = "0.3", optional = true } libc = "0.2" -libssh2-sys = { version = "0.2", optional = true } +libssh2-sys = { version = "0.2.4", optional = true } libz-sys = ">= 0" [build-dependencies] diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 6c492bb20a..f9b8c1a66f 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1334,9 +1334,6 @@ git_enum! { pub type git_packbuilder_foreach_cb = extern fn(*const c_void, size_t, *mut c_void) -> c_int; -#[doc(hidden)] -pub fn openssl_init() {} - extern { // threads pub fn git_libgit2_init() -> c_int; @@ -2524,7 +2521,37 @@ extern { pub fn git_packbuilder_free(pb: *mut git_packbuilder); } -#[test] -fn smoke() { - unsafe { git_threads_init(); } +pub fn init() { + use std::sync::{Once, ONCE_INIT}; + + static INIT: Once = ONCE_INIT; + INIT.call_once(|| unsafe { + openssl_init(); + ssh_init(); + let r = git_libgit2_init(); + assert!(r >= 0, + "couldn't initialize the libgit2 library: {}", r); + assert_eq!(libc::atexit(shutdown), 0); + }); + extern fn shutdown() { + unsafe { git_libgit2_shutdown(); } + } +} + +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] +#[doc(hidden)] +pub fn openssl_init() { + openssl_sys::init(); } + +#[cfg(any(windows, target_os = "macos", target_os = "ios", not(feature = "https")))] +#[doc(hidden)] +pub fn openssl_init() {} + +#[cfg(feature = "ssh")] +fn ssh_init() { + libssh2::init(); +} + +#[cfg(not(feature = "ssh"))] +fn ssh_init() {} diff --git a/src/lib.rs b/src/lib.rs index 0800aeb2cf..afb175dc49 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -528,26 +528,19 @@ mod tree; mod treebuilder; fn init() { + raw::init(); + static INIT: Once = ONCE_INIT; - INIT.call_once(|| unsafe { - openssl_init(); - let r = raw::git_libgit2_init(); - assert!(r >= 0, - "couldn't initialize the libgit2 library: {}", r); - assert_eq!(libc::atexit(shutdown), 0); + + INIT.call_once(|| { + openssl_env_init(); }); - extern fn shutdown() { - unsafe { raw::git_libgit2_shutdown(); } - } } #[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] -fn openssl_init() { - extern crate openssl_sys; +fn openssl_env_init() { extern crate openssl_probe; - openssl_sys::init(); - // Currently, libgit2 leverages OpenSSL for SSL support when cloning // repositories over HTTPS. This means that we're picking up an OpenSSL // dependency on non-Windows platforms (where it has its own HTTPS @@ -663,7 +656,7 @@ fn openssl_init() { } #[cfg(any(windows, target_os = "macos", target_os = "ios", not(feature = "https")))] -fn openssl_init() {} +fn openssl_env_init() {} unsafe fn opt_bytes<'a, T>(_anchor: &'a T, c: *const libc::c_char) -> Option<&'a [u8]> { From 1402be3953674ed2628ccf98dcec924416fd30f7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 26 Nov 2016 09:07:04 -0800 Subject: [PATCH 059/860] Bump libgit2-sys to 0.6.4 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 8d1d6859e3..589035b002 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.3" +version = "0.6.4" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 4b6efa44f34b909599336678a02721db69454e4f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 26 Nov 2016 09:09:00 -0800 Subject: [PATCH 060/860] Bump dep on libgit2-sys --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c3781dace9..0f27f84bde 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ repositories. url = "1.0" bitflags = "0.7" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.6.3" } +libgit2-sys = { path = "libgit2-sys", version = "0.6.4" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From a3bdbfb82a359ef734d3ed7c4ce9f86bb1eec47d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 26 Nov 2016 09:09:07 -0800 Subject: [PATCH 061/860] Add back old method name for backcompat --- src/diff.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/diff.rs b/src/diff.rs index b3ae71f52a..94d1beb504 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -1021,6 +1021,11 @@ impl DiffFindOptions { self.flag(raw::GIT_DIFF_BREAK_REWRITES, find) } + #[doc(hidden)] + pub fn break_rewries(&mut self, find: bool) -> &mut DiffFindOptions { + self.break_rewrites(find) + } + /// Find renames/copies for untracked items in working directory. /// /// For this to work correctly use the `include_untracked` option when the From 0375ba306ff435fe3dd531f1457a3f0eb3bddd48 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 26 Nov 2016 09:09:46 -0800 Subject: [PATCH 062/860] Bump to 0.6.2 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 0f27f84bde..f455df4e64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.1" +version = "0.6.2" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From a8f4a7faa0f8c98a0f113a59e017f0cf8f825384 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 28 Nov 2016 15:46:44 -0800 Subject: [PATCH 063/860] Init openssl env vars before libgit2 Apparently libgit2 needs them set, so if we initialize them afterwards they're not actually used. --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index afb175dc49..cca8e8f0b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -528,13 +528,13 @@ mod tree; mod treebuilder; fn init() { - raw::init(); - static INIT: Once = ONCE_INIT; INIT.call_once(|| { openssl_env_init(); }); + + raw::init(); } #[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] From 89f70f157a33a5a3d78553084e43b537efbbb7b1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 28 Nov 2016 15:47:21 -0800 Subject: [PATCH 064/860] Bump to 0.6.3 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f455df4e64..e0753ba9e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.2" +version = "0.6.3" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 4df68db506aeab4339355449364b71376a896fb1 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 30 Nov 2016 22:11:29 -0800 Subject: [PATCH 065/860] libgit2-sys: Update libgit2 by one commit This pulls in the fix for https://github.com/libgit2/libgit2/pull/3992 --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index b7822050c9..c9e967a1b4 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit b7822050c99b8ea198d96e98cb720aa24a8230d0 +Subproject commit c9e967a1b48c7a0b484fd3a4860e9c7a0aa4a319 From b42dc20a5a585975ce8e3ec4b9600c7bca015f05 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 2 Dec 2016 10:50:58 -0800 Subject: [PATCH 066/860] Support /MT on MSVC --- libgit2-sys/build.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index d36bd4c2f0..1fe60b9454 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -57,7 +57,13 @@ fn main() { // Currently liblibc links to msvcrt which apparently is a dynamic CRT, // so we need to turn this off to get it to link right. - cfg.define("STATIC_CRT", "OFF"); + let features = env::var("CARGO_CFG_TARGET_FEATURE") + .unwrap_or(String::new()); + if features.contains("crt-static") { + cfg.define("STATIC_CRT", "ON"); + } else { + cfg.define("STATIC_CRT", "OFF"); + } } // libgit2 uses pkg-config to discover libssh2, but this doesn't work on From 5eb686d7ff15461e9af5434947efd8ddc6261ab8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 2 Dec 2016 13:28:12 -0800 Subject: [PATCH 067/860] Bump libgit2-sys to 0.6.5 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 589035b002..3ebcf98c6d 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.4" +version = "0.6.5" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From fca4791e6c5ae31aa29fdf38c8220d6f905c6f6b Mon Sep 17 00:00:00 2001 From: Stanislav Panferov Date: Thu, 1 Dec 2016 11:29:26 +0100 Subject: [PATCH 068/860] feat: bindings for Stash --- libgit2-sys/lib.rs | 72 ++++++++++++ src/lib.rs | 51 ++++++++ src/stash.rs | 287 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 src/stash.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index f9b8c1a66f..6f0a2af31b 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -15,6 +15,7 @@ use libc::{c_int, c_char, c_uint, size_t, c_uchar, c_void}; pub const GIT_OID_RAWSZ: usize = 20; pub const GIT_OID_HEXSZ: usize = GIT_OID_RAWSZ * 2; pub const GIT_CLONE_OPTIONS_VERSION: c_uint = 1; +pub const GIT_STASH_APPLY_OPTIONS_VERSION: c_uint = 1; pub const GIT_CHECKOUT_OPTIONS_VERSION: c_uint = 1; pub const GIT_MERGE_OPTIONS_VERSION: c_uint = 1; pub const GIT_REMOTE_CALLBACKS_VERSION: c_uint = 1; @@ -1331,6 +1332,52 @@ git_enum! { } } +git_enum! { + pub enum git_stash_flags { + GIT_STASH_DEFAULT = 0, + GIT_STASH_KEEP_INDEX = 1 << 0, + GIT_STASH_INCLUDE_UNTRACKED = 1 << 1, + GIT_STASH_INCLUDE_IGNORED = 1 << 2, + } +} + +git_enum! { + pub enum git_stash_apply_flags { + GIT_STASH_APPLY_DEFAULT = 0, + GIT_STASH_APPLY_REINSTATE_INDEX = 1 << 0, + } +} + +git_enum! { + pub enum git_stash_apply_progress_t { + GIT_STASH_APPLY_PROGRESS_NONE = 0, + GIT_STASH_APPLY_PROGRESS_LOADING_STASH, + GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX, + GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED, + GIT_STASH_APPLY_PROGRESS_ANALYZE_UNTRACKED, + GIT_STASH_APPLY_PROGRESS_CHECKOUT_UNTRACKED, + GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED, + GIT_STASH_APPLY_PROGRESS_DONE, + } +} + +#[repr(C)] +pub struct git_stash_apply_options { + pub version: c_uint, + pub flags: git_stash_apply_flags, + pub checkout_options: git_checkout_options, + pub progress_cb: git_stash_apply_progress_cb, + pub progress_payload: *mut c_void, +} + +pub type git_stash_apply_progress_cb = extern fn(progress: git_stash_apply_progress_t, + payload: *mut c_void) -> c_int; + +pub type git_stash_cb = extern fn(index: size_t, + message: *const c_char, + stash_id: *const git_oid, + payload: *mut c_void) -> c_int; + pub type git_packbuilder_foreach_cb = extern fn(*const c_void, size_t, *mut c_void) -> c_int; @@ -1658,6 +1705,31 @@ extern { pub fn git_reference_ensure_log(repo: *mut git_repository, name: *const c_char) -> c_int; + // stash + pub fn git_stash_save(out: *mut git_oid, + repo: *mut git_repository, + stasher: *const git_signature, + message: *const c_char, + flags: c_uint) -> c_int; + + pub fn git_stash_apply_init_options(opts: *mut git_stash_apply_options, + version: c_uint) -> c_int; + + pub fn git_stash_apply(repo: *mut git_repository, + index: size_t, + options: *const git_stash_apply_options) -> c_int; + + pub fn git_stash_foreach(repo: *mut git_repository, + callback: git_stash_cb, + payload: *mut c_void) -> c_int; + + pub fn git_stash_drop(repo: *mut git_repository, + index: size_t) -> c_int; + + pub fn git_stash_pop(repo: *mut git_repository, + index: size_t, + options: *const git_stash_apply_options) -> c_int; + // submodules pub fn git_submodule_add_finalize(submodule: *mut git_submodule) -> c_int; pub fn git_submodule_add_setup(submodule: *mut *mut git_submodule, diff --git a/src/lib.rs b/src/lib.rs index cca8e8f0b1..779ea6d118 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -113,6 +113,7 @@ pub use revspec::Revspec; pub use revwalk::Revwalk; pub use signature::Signature; pub use status::{StatusOptions, Statuses, StatusIter, StatusEntry, StatusShow}; +pub use stash::{Stash, StashApplyOptions, StashCb, StashApplyProgressCb}; pub use submodule::Submodule; pub use tag::Tag; pub use time::{Time, IndexTime}; @@ -522,6 +523,7 @@ mod revwalk; mod signature; mod status; mod submodule; +mod stash; mod tag; mod time; mod tree; @@ -1026,6 +1028,55 @@ pub enum FetchPrune { Off, } +#[allow(missing_docs)] +#[derive(Debug)] +pub enum StashApplyProgress { + /// None + None, + /// Loading the stashed data from the object database + LoadingStash, + /// The stored index is being analyzed + AnalyzeIndex, + /// The modified files are being analyzed + AnalyzeModified, + /// The untracked and ignored files are being analyzed + AnalyzeUntracked, + /// The untracked files are being written to disk + CheckoutUntracked, + /// The modified files are being written to disk + CheckoutModified, + /// The stash was applied successfully + Done, +} + +bitflags! { + #[allow(missing_docs)] + pub flags StashApplyFlags: u32 { + #[allow(missing_docs)] + const STASH_APPLY_DEFAULT = raw::GIT_STASH_APPLY_DEFAULT as u32, + /// Try to reinstate not only the working tree's changes, + /// but also the index's changes. + const STASH_APPLY_REINSTATE_INDEX = raw::GIT_STASH_APPLY_REINSTATE_INDEX as u32, + } +} + +bitflags! { + #[allow(missing_docs)] + pub flags StashFlags: u32 { + #[allow(missing_docs)] + const STASH_DEFAULT = raw::GIT_STASH_DEFAULT as u32, + /// All changes already added to the index are left intact in + /// the working directory + const STASH_KEEP_INDEX = raw::GIT_STASH_KEEP_INDEX as u32, + /// All untracked files are also stashed and then cleaned up + /// from the working directory + const STASH_INCLUDE_UNTRACKED = raw::GIT_STASH_INCLUDE_UNTRACKED as u32, + /// All ignored files are also stashed and then cleaned up from + /// the working directory + const STASH_INCLUDE_IGNORED = raw::GIT_STASH_INCLUDE_IGNORED as u32, + } +} + #[cfg(test)] mod tests { use super::ObjectType; diff --git a/src/stash.rs b/src/stash.rs new file mode 100644 index 0000000000..0986b5cbed --- /dev/null +++ b/src/stash.rs @@ -0,0 +1,287 @@ +use {raw, panic, StashFlags, Oid, Error, Repository, Signature, StashApplyProgress}; +use std::ffi::{CString, CStr}; +use util::{Binding}; +use libc::{c_int, c_char, size_t, c_void, c_uint}; +use build::{CheckoutBuilder}; +use std::mem; + +/// Stash application progress notification function. +/// +/// Return `true` to continue processing, or `false` to +/// abort the stash application. +pub type StashApplyProgressCb<'a> = FnMut(StashApplyProgress) -> bool + 'a; + +/// This is a callback function you can provide to iterate over all the +/// stashed states that will be invoked per entry. +pub type StashCb<'a> = FnMut(usize, &str, &Oid) -> bool + 'a; + +#[allow(unused)] +/// Stash application options structure +pub struct StashApplyOptions<'cb> { + progress: Option>>, + raw_opts: raw::git_stash_apply_options +} + +impl<'cb> StashApplyOptions<'cb> { + /// Creates a default set of merge options. + pub fn new() -> StashApplyOptions<'cb> { + let mut opts = StashApplyOptions { + progress: None, + raw_opts: unsafe { mem::zeroed() }, + }; + assert_eq!(unsafe { + raw::git_stash_apply_init_options(&mut opts.raw_opts, 1) + }, 0); + opts + } + + /// Set stash application flag + pub fn flags(&mut self, flags: raw::git_stash_apply_flags) -> &mut StashApplyOptions<'cb> { + self.raw_opts.flags = flags; + self + } + + /// Options to use when writing files to the working directory + pub fn checkout_options(&mut self, mut opts: CheckoutBuilder) -> &mut StashApplyOptions<'cb> { + unsafe { + opts.configure(&mut self.raw_opts.checkout_options); + } + self + } + + /// Optional callback to notify the consumer of application progress. + /// + /// Return `true` to continue processing, or `false` to + /// abort the stash application. + pub fn progress_cb(&mut self, callback: Box>) -> &mut StashApplyOptions<'cb> { + self.progress = Some(callback); + self.raw_opts.progress_cb = stash_apply_progress_cb; + self.raw_opts.progress_payload = self as *mut _ as *mut _; + self + } + + /// Pointer to a raw git_stash_apply_options + fn raw(&self) -> &raw::git_stash_apply_options { + &self.raw_opts + } +} + +/// A set of stash methods +pub struct Stash { + +} + +impl Stash { + /// Save the local modifications to a new stash. + pub fn save(repo: &mut Repository, + stasher: &Signature, + message: &str, + flags: Option) + -> Result { + unsafe { + let mut raw_oid = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let message = try!(CString::new(message)); + let flags = flags.unwrap_or(StashFlags::empty()); + try_call!(raw::git_stash_save( + &mut raw_oid, + repo.raw(), + stasher.raw(), + message, + flags.bits() as c_uint + )); + + Ok(Binding::from_raw(&raw_oid as *const _)) + } + } + + /// Apply a single stashed state from the stash list. + pub fn apply(repo: &mut Repository, + index: usize, + opts: Option<&mut StashApplyOptions>) + -> Result<(), Error> { + unsafe { + let opts = opts.map(|opts| opts.raw()); + try_call!(raw::git_stash_apply( + repo.raw(), + index, + opts + )); + + Ok(()) + } + } + + /// Loop over all the stashed states and issue a callback for each one. + /// + /// Return `true` to continue iterating or `false` to stop. + pub fn foreach(repo: &mut Repository, callback: Box) -> Result<(), Error> { + unsafe { + let mut data = Box::new(StashCbData { callback: callback }); + try_call!(raw::git_stash_foreach( + repo.raw(), + stash_cb, + &mut *data as *mut _ as *mut _ + )); + Ok(()) + } + } + + /// Remove a single stashed state from the stash list. + pub fn drop(repo: &mut Repository, index: usize) -> Result<(), Error> { + unsafe { + try_call!(raw::git_stash_drop( + repo.raw(), + index + )); + Ok(()) + } + } + + /// Apply a single stashed state from the stash list and remove it from the list if successful. + pub fn pop(repo: &mut Repository, + index: usize, + opts: Option<&mut StashApplyOptions>) + -> Result<(), Error> { + unsafe { + let opts = opts.map(|opts| opts.raw()); + try_call!(raw::git_stash_pop( + repo.raw(), + index, + opts + )); + Ok(()) + } + } +} + +#[allow(unused)] +struct StashCbData<'a> { + callback: Box> +} + +#[allow(unused)] +extern fn stash_cb(index: size_t, + message: *const c_char, + stash_id: *const raw::git_oid, + payload: *mut c_void) + -> c_int +{ + panic::wrap(|| unsafe { + let mut data = &mut *(payload as *mut StashCbData); + let res = { + let mut callback = &mut data.callback; + callback( + index, + CStr::from_ptr(message).to_str().unwrap(), + &Binding::from_raw(stash_id) + ) + }; + + if res { 0 } else { 1 } + }).unwrap() +} + +fn convert_progress(progress: raw::git_stash_apply_progress_t) -> StashApplyProgress { + match progress { + raw::GIT_STASH_APPLY_PROGRESS_NONE => StashApplyProgress::None, + raw::GIT_STASH_APPLY_PROGRESS_LOADING_STASH => StashApplyProgress::LoadingStash, + raw::GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX => StashApplyProgress::AnalyzeIndex, + raw::GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED => StashApplyProgress::AnalyzeModified, + raw::GIT_STASH_APPLY_PROGRESS_ANALYZE_UNTRACKED => StashApplyProgress::AnalyzeUntracked, + raw::GIT_STASH_APPLY_PROGRESS_CHECKOUT_UNTRACKED => StashApplyProgress::CheckoutUntracked, + raw::GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED => StashApplyProgress::CheckoutModified, + raw::GIT_STASH_APPLY_PROGRESS_DONE => StashApplyProgress::Done, + + _ => StashApplyProgress::None + } +} + +#[allow(unused)] +extern fn stash_apply_progress_cb(progress: raw::git_stash_apply_progress_t, + payload: *mut c_void) + -> c_int +{ + panic::wrap(|| unsafe { + let mut options = &mut *(payload as *mut StashApplyOptions); + let res = { + let mut callback = options.progress.as_mut().unwrap(); + callback(convert_progress(progress)) + }; + + if res { 0 } else { -1 } + }).unwrap() +} + +#[cfg(test)] +mod tests { + use stash::{Stash, StashApplyOptions}; + use std::io::{Write}; + use std::fs; + use std::path::Path; + use test::{repo_init}; + use {Repository, STATUS_WT_NEW, STASH_INCLUDE_UNTRACKED}; + + fn make_stash(next: C) where C: FnOnce(&mut Repository) { + let (_td, mut repo) = repo_init(); + let signature = repo.signature().unwrap(); + + let p = Path::new(repo.workdir().unwrap()).join("file_b.txt"); + println!("using path {:?}", p); + fs::File::create(&p).unwrap() + .write("data".as_bytes()).unwrap(); + + let rel_p = Path::new("file_b.txt"); + assert!(repo.status_file(&rel_p).unwrap() == STATUS_WT_NEW); + + Stash::save(&mut repo, &signature, "msg1", Some(STASH_INCLUDE_UNTRACKED)).unwrap(); + + assert!(repo.status_file(&rel_p).is_err()); + + let mut count = 0; + Stash::foreach(&mut repo, Box::new(|index, name, _oid| { + count += 1; + assert!(index == 0); + assert!(name == "On master: msg1"); + true + })).unwrap(); + + assert!(count == 1); + next(&mut repo); + } + + fn count_stash(repo: &mut Repository) -> usize { + let mut count = 0; + Stash::foreach(repo, Box::new(|_, _, _| { count += 1; true })).unwrap(); + count + } + + #[test] + fn smoke_stash_save_drop() { + make_stash(|repo| { + Stash::drop(repo, 0).unwrap(); + assert!(count_stash(repo) == 0) + }) + } + + #[test] + fn smoke_stash_save_pop() { + make_stash(|repo| { + Stash::pop(repo, 0, None).unwrap(); + assert!(count_stash(repo) == 0) + }) + } + + #[test] + fn smoke_stash_save_apply() { + make_stash(|repo| { + let mut options = StashApplyOptions::new(); + options.progress_cb(Box::new(|progress| { + println!("{:?}", progress); + true + })); + + Stash::apply(repo, 0, Some(&mut options)).unwrap(); + assert!(count_stash(repo) == 1) + }) + } +} \ No newline at end of file From 52ab7d7bd2b0d99c5521bec73ca17fa5bfe19a8e Mon Sep 17 00:00:00 2001 From: Stanislav Panferov Date: Tue, 6 Dec 2016 09:32:09 +0100 Subject: [PATCH 069/860] refactor: review feedback --- src/lib.rs | 1 - src/repo.rs | 85 ++++++++++++++++++++++++++++++- src/stash.rs | 139 +++++++++++---------------------------------------- 3 files changed, 112 insertions(+), 113 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 779ea6d118..be0b16b9fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -113,7 +113,6 @@ pub use revspec::Revspec; pub use revwalk::Revwalk; pub use signature::Signature; pub use status::{StatusOptions, Statuses, StatusIter, StatusEntry, StatusShow}; -pub use stash::{Stash, StashApplyOptions, StashCb, StashApplyProgressCb}; pub use submodule::Submodule; pub use tag::Tag; pub use time::{Time, IndexTime}; diff --git a/src/repo.rs b/src/repo.rs index 4abdfc36d4..9599057860 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -6,7 +6,7 @@ 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, RepositoryOpenFlags, RepositoryState, Remote, Buf}; +use {raw, Revspec, Error, init, Object, RepositoryOpenFlags, RepositoryState, Remote, Buf, StashFlags}; use {ResetType, Signature, Reference, References, Submodule, Blame, BlameOptions}; use {Branches, BranchType, Index, Config, Oid, Blob, Branch, Commit, Tree}; use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus}; @@ -14,6 +14,7 @@ use {ObjectType, Tag, Note, Notes, StatusOptions, Statuses, Status, Revwalk}; use {RevparseMode, RepositoryInitMode, Reflog, IntoCString, Describe}; use {DescribeOptions, TreeBuilder, Diff, DiffOptions, PackBuilder}; use build::{RepoBuilder, CheckoutBuilder}; +use stash::{StashApplyOptions, StashCb, StashCbData, stash_cb}; use string_array::StringArray; use oid_array::OidArray; use util::{self, Binding}; @@ -1712,6 +1713,88 @@ impl Repository { } } + /// Save the local modifications to a new stash. + pub fn stash_save(&mut self, + stasher: &Signature, + message: &str, + flags: Option) + -> Result { + unsafe { + let mut raw_oid = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let message = try!(CString::new(message)); + let flags = flags.unwrap_or(StashFlags::empty()); + try_call!(raw::git_stash_save( + &mut raw_oid, + self.raw(), + stasher.raw(), + message, + flags.bits() as c_uint + )); + + Ok(Binding::from_raw(&raw_oid as *const _)) + } + } + + /// Apply a single stashed state from the stash list. + pub fn stash_apply(&mut self, + index: usize, + opts: Option<&mut StashApplyOptions>) + -> Result<(), Error> { + unsafe { + let opts = opts.map(|opts| opts.raw()); + try_call!(raw::git_stash_apply( + self.raw(), + index, + opts + )); + + Ok(()) + } + } + + /// Loop over all the stashed states and issue a callback for each one. + /// + /// Return `true` to continue iterating or `false` to stop. + pub fn stash_foreach(&mut self, callback: C) -> Result<(), Error> + where C: FnMut(usize, &str, &Oid) -> bool + { + unsafe { + let mut data = Box::new(StashCbData { callback: Box::new(callback) as Box }); + try_call!(raw::git_stash_foreach( + self.raw(), + stash_cb, + &mut *data as *mut _ as *mut _ + )); + Ok(()) + } + } + + /// Remove a single stashed state from the stash list. + pub fn stash_drop(&mut self, index: usize) -> Result<(), Error> { + unsafe { + try_call!(raw::git_stash_drop( + self.raw(), + index + )); + Ok(()) + } + } + + /// Apply a single stashed state from the stash list and remove it from the list if successful. + pub fn stash_pop(&mut self, + index: usize, + opts: Option<&mut StashApplyOptions>) + -> Result<(), Error> { + unsafe { + let opts = opts.map(|opts| opts.raw()); + try_call!(raw::git_stash_pop( + self.raw(), + index, + opts + )); + Ok(()) + } + } } impl Binding for Repository { diff --git a/src/stash.rs b/src/stash.rs index 0986b5cbed..48f70645c9 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -1,7 +1,7 @@ -use {raw, panic, StashFlags, Oid, Error, Repository, Signature, StashApplyProgress}; -use std::ffi::{CString, CStr}; +use {raw, panic, Oid, StashApplyProgress}; +use std::ffi::{CStr}; use util::{Binding}; -use libc::{c_int, c_char, size_t, c_void, c_uint}; +use libc::{c_int, c_char, size_t, c_void}; use build::{CheckoutBuilder}; use std::mem; @@ -19,6 +19,7 @@ pub type StashCb<'a> = FnMut(usize, &str, &Oid) -> bool + 'a; /// Stash application options structure pub struct StashApplyOptions<'cb> { progress: Option>>, + checkout_options: Option>, raw_opts: raw::git_stash_apply_options } @@ -27,6 +28,7 @@ impl<'cb> StashApplyOptions<'cb> { pub fn new() -> StashApplyOptions<'cb> { let mut opts = StashApplyOptions { progress: None, + checkout_options: None, raw_opts: unsafe { mem::zeroed() }, }; assert_eq!(unsafe { @@ -35,17 +37,18 @@ impl<'cb> StashApplyOptions<'cb> { opts } - /// Set stash application flag - pub fn flags(&mut self, flags: raw::git_stash_apply_flags) -> &mut StashApplyOptions<'cb> { - self.raw_opts.flags = flags; + /// Set stash application flag to GIT_STASH_APPLY_REINSTATE_INDEX + pub fn reinstantiate_index(&mut self) -> &mut StashApplyOptions<'cb> { + self.raw_opts.flags = raw::GIT_STASH_APPLY_REINSTATE_INDEX; self } /// Options to use when writing files to the working directory - pub fn checkout_options(&mut self, mut opts: CheckoutBuilder) -> &mut StashApplyOptions<'cb> { + pub fn checkout_options(&mut self, mut opts: CheckoutBuilder<'cb>) -> &mut StashApplyOptions<'cb> { unsafe { opts.configure(&mut self.raw_opts.checkout_options); } + self.checkout_options = Some(opts); self } @@ -53,114 +56,28 @@ impl<'cb> StashApplyOptions<'cb> { /// /// Return `true` to continue processing, or `false` to /// abort the stash application. - pub fn progress_cb(&mut self, callback: Box>) -> &mut StashApplyOptions<'cb> { - self.progress = Some(callback); + pub fn progress_cb(&mut self, callback: C) -> &mut StashApplyOptions<'cb> + where C: FnMut(StashApplyProgress) -> bool + 'cb + { + self.progress = Some(Box::new(callback) as Box>); self.raw_opts.progress_cb = stash_apply_progress_cb; self.raw_opts.progress_payload = self as *mut _ as *mut _; self } /// Pointer to a raw git_stash_apply_options - fn raw(&self) -> &raw::git_stash_apply_options { + pub fn raw(&self) -> &raw::git_stash_apply_options { &self.raw_opts } } -/// A set of stash methods -pub struct Stash { - -} - -impl Stash { - /// Save the local modifications to a new stash. - pub fn save(repo: &mut Repository, - stasher: &Signature, - message: &str, - flags: Option) - -> Result { - unsafe { - let mut raw_oid = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; - let message = try!(CString::new(message)); - let flags = flags.unwrap_or(StashFlags::empty()); - try_call!(raw::git_stash_save( - &mut raw_oid, - repo.raw(), - stasher.raw(), - message, - flags.bits() as c_uint - )); - - Ok(Binding::from_raw(&raw_oid as *const _)) - } - } - - /// Apply a single stashed state from the stash list. - pub fn apply(repo: &mut Repository, - index: usize, - opts: Option<&mut StashApplyOptions>) - -> Result<(), Error> { - unsafe { - let opts = opts.map(|opts| opts.raw()); - try_call!(raw::git_stash_apply( - repo.raw(), - index, - opts - )); - - Ok(()) - } - } - - /// Loop over all the stashed states and issue a callback for each one. - /// - /// Return `true` to continue iterating or `false` to stop. - pub fn foreach(repo: &mut Repository, callback: Box) -> Result<(), Error> { - unsafe { - let mut data = Box::new(StashCbData { callback: callback }); - try_call!(raw::git_stash_foreach( - repo.raw(), - stash_cb, - &mut *data as *mut _ as *mut _ - )); - Ok(()) - } - } - - /// Remove a single stashed state from the stash list. - pub fn drop(repo: &mut Repository, index: usize) -> Result<(), Error> { - unsafe { - try_call!(raw::git_stash_drop( - repo.raw(), - index - )); - Ok(()) - } - } - - /// Apply a single stashed state from the stash list and remove it from the list if successful. - pub fn pop(repo: &mut Repository, - index: usize, - opts: Option<&mut StashApplyOptions>) - -> Result<(), Error> { - unsafe { - let opts = opts.map(|opts| opts.raw()); - try_call!(raw::git_stash_pop( - repo.raw(), - index, - opts - )); - Ok(()) - } - } -} - #[allow(unused)] -struct StashCbData<'a> { - callback: Box> +pub struct StashCbData<'a> { + pub callback: Box> } #[allow(unused)] -extern fn stash_cb(index: size_t, +pub extern fn stash_cb(index: size_t, message: *const c_char, stash_id: *const raw::git_oid, payload: *mut c_void) @@ -214,7 +131,7 @@ extern fn stash_apply_progress_cb(progress: raw::git_stash_apply_progress_t, #[cfg(test)] mod tests { - use stash::{Stash, StashApplyOptions}; + use stash::{StashApplyOptions}; use std::io::{Write}; use std::fs; use std::path::Path; @@ -233,17 +150,17 @@ mod tests { let rel_p = Path::new("file_b.txt"); assert!(repo.status_file(&rel_p).unwrap() == STATUS_WT_NEW); - Stash::save(&mut repo, &signature, "msg1", Some(STASH_INCLUDE_UNTRACKED)).unwrap(); + repo.stash_save(&signature, "msg1", Some(STASH_INCLUDE_UNTRACKED)).unwrap(); assert!(repo.status_file(&rel_p).is_err()); let mut count = 0; - Stash::foreach(&mut repo, Box::new(|index, name, _oid| { + repo.stash_foreach(|index, name, _oid| { count += 1; assert!(index == 0); assert!(name == "On master: msg1"); true - })).unwrap(); + }).unwrap(); assert!(count == 1); next(&mut repo); @@ -251,14 +168,14 @@ mod tests { fn count_stash(repo: &mut Repository) -> usize { let mut count = 0; - Stash::foreach(repo, Box::new(|_, _, _| { count += 1; true })).unwrap(); + repo.stash_foreach(|_, _, _| { count += 1; true }).unwrap(); count } #[test] fn smoke_stash_save_drop() { make_stash(|repo| { - Stash::drop(repo, 0).unwrap(); + repo.stash_drop(0).unwrap(); assert!(count_stash(repo) == 0) }) } @@ -266,7 +183,7 @@ mod tests { #[test] fn smoke_stash_save_pop() { make_stash(|repo| { - Stash::pop(repo, 0, None).unwrap(); + repo.stash_pop(0, None).unwrap(); assert!(count_stash(repo) == 0) }) } @@ -275,12 +192,12 @@ mod tests { fn smoke_stash_save_apply() { make_stash(|repo| { let mut options = StashApplyOptions::new(); - options.progress_cb(Box::new(|progress| { + options.progress_cb(|progress| { println!("{:?}", progress); true - })); + }); - Stash::apply(repo, 0, Some(&mut options)).unwrap(); + repo.stash_apply(0, Some(&mut options)).unwrap(); assert!(count_stash(repo) == 1) }) } From e79eb2b2060bf3ae019533bffe23faab40431295 Mon Sep 17 00:00:00 2001 From: Stanislav Panferov Date: Thu, 8 Dec 2016 11:24:09 +0100 Subject: [PATCH 070/860] refactor: review feedback --- src/lib.rs | 1 + src/repo.rs | 65 +++++++++++++++++++--------------------------------- src/stash.rs | 32 +++++++++++++------------- 3 files changed, 41 insertions(+), 57 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index be0b16b9fe..5e540d68b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -113,6 +113,7 @@ pub use revspec::Revspec; pub use revwalk::Revwalk; pub use signature::Signature; pub use status::{StatusOptions, Statuses, StatusIter, StatusEntry, StatusShow}; +pub use stash::{StashApplyOptions, StashCb, StashApplyProgressCb}; pub use submodule::Submodule; pub use tag::Tag; pub use time::{Time, IndexTime}; diff --git a/src/repo.rs b/src/repo.rs index 9599057860..526dab3e0c 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -14,7 +14,7 @@ use {ObjectType, Tag, Note, Notes, StatusOptions, Statuses, Status, Revwalk}; use {RevparseMode, RepositoryInitMode, Reflog, IntoCString, Describe}; use {DescribeOptions, TreeBuilder, Diff, DiffOptions, PackBuilder}; use build::{RepoBuilder, CheckoutBuilder}; -use stash::{StashApplyOptions, StashCb, StashCbData, stash_cb}; +use stash::{StashApplyOptions, StashCbData, stash_cb}; use string_array::StringArray; use oid_array::OidArray; use util::{self, Binding}; @@ -1715,39 +1715,31 @@ impl Repository { /// Save the local modifications to a new stash. pub fn stash_save(&mut self, - stasher: &Signature, - message: &str, - flags: Option) - -> Result { + stasher: &Signature, + message: &str, + flags: Option) + -> Result { unsafe { let mut raw_oid = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; let message = try!(CString::new(message)); let flags = flags.unwrap_or(StashFlags::empty()); - try_call!(raw::git_stash_save( - &mut raw_oid, - self.raw(), - stasher.raw(), - message, - flags.bits() as c_uint - )); - + try_call!(raw::git_stash_save(&mut raw_oid, + self.raw(), + stasher.raw(), + message, + flags.bits() as c_uint)); Ok(Binding::from_raw(&raw_oid as *const _)) } } /// Apply a single stashed state from the stash list. pub fn stash_apply(&mut self, - index: usize, - opts: Option<&mut StashApplyOptions>) - -> Result<(), Error> { + index: usize, + opts: Option<&mut StashApplyOptions>) + -> Result<(), Error> { unsafe { let opts = opts.map(|opts| opts.raw()); - try_call!(raw::git_stash_apply( - self.raw(), - index, - opts - )); - + try_call!(raw::git_stash_apply(self.raw(), index, opts)); Ok(()) } } @@ -1755,16 +1747,14 @@ impl Repository { /// Loop over all the stashed states and issue a callback for each one. /// /// Return `true` to continue iterating or `false` to stop. - pub fn stash_foreach(&mut self, callback: C) -> Result<(), Error> + pub fn stash_foreach(&mut self, mut callback: C) -> Result<(), Error> where C: FnMut(usize, &str, &Oid) -> bool { unsafe { - let mut data = Box::new(StashCbData { callback: Box::new(callback) as Box }); - try_call!(raw::git_stash_foreach( - self.raw(), - stash_cb, - &mut *data as *mut _ as *mut _ - )); + let mut data = Box::new(StashCbData { callback: &mut callback }); + try_call!(raw::git_stash_foreach(self.raw(), + stash_cb, + &mut *data as *mut _ as *mut _)); Ok(()) } } @@ -1772,26 +1762,19 @@ impl Repository { /// Remove a single stashed state from the stash list. pub fn stash_drop(&mut self, index: usize) -> Result<(), Error> { unsafe { - try_call!(raw::git_stash_drop( - self.raw(), - index - )); + try_call!(raw::git_stash_drop(self.raw(), index)); Ok(()) } } /// Apply a single stashed state from the stash list and remove it from the list if successful. pub fn stash_pop(&mut self, - index: usize, - opts: Option<&mut StashApplyOptions>) - -> Result<(), Error> { + index: usize, + opts: Option<&mut StashApplyOptions>) + -> Result<(), Error> { unsafe { let opts = opts.map(|opts| opts.raw()); - try_call!(raw::git_stash_pop( - self.raw(), - index, - opts - )); + try_call!(raw::git_stash_pop(self.raw(), index, opts)); Ok(()) } } diff --git a/src/stash.rs b/src/stash.rs index 48f70645c9..dd6c0a9298 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -44,10 +44,7 @@ impl<'cb> StashApplyOptions<'cb> { } /// Options to use when writing files to the working directory - pub fn checkout_options(&mut self, mut opts: CheckoutBuilder<'cb>) -> &mut StashApplyOptions<'cb> { - unsafe { - opts.configure(&mut self.raw_opts.checkout_options); - } + pub fn checkout_options(&mut self, opts: CheckoutBuilder<'cb>) -> &mut StashApplyOptions<'cb> { self.checkout_options = Some(opts); self } @@ -66,36 +63,39 @@ impl<'cb> StashApplyOptions<'cb> { } /// Pointer to a raw git_stash_apply_options - pub fn raw(&self) -> &raw::git_stash_apply_options { + pub fn raw(&mut self) -> &raw::git_stash_apply_options { + unsafe { + if let Some(opts) = self.checkout_options.as_mut() { + opts.configure(&mut self.raw_opts.checkout_options); + } + } &self.raw_opts } } #[allow(unused)] pub struct StashCbData<'a> { - pub callback: Box> + pub callback: &'a mut StashCb<'a> } #[allow(unused)] pub extern fn stash_cb(index: size_t, - message: *const c_char, - stash_id: *const raw::git_oid, - payload: *mut c_void) - -> c_int + message: *const c_char, + stash_id: *const raw::git_oid, + payload: *mut c_void) + -> c_int { panic::wrap(|| unsafe { let mut data = &mut *(payload as *mut StashCbData); let res = { let mut callback = &mut data.callback; - callback( - index, - CStr::from_ptr(message).to_str().unwrap(), - &Binding::from_raw(stash_id) - ) + callback(index, + CStr::from_ptr(message).to_str().unwrap(), + &Binding::from_raw(stash_id)) }; if res { 0 } else { 1 } - }).unwrap() + }).unwrap_or(1) } fn convert_progress(progress: raw::git_stash_apply_progress_t) -> StashApplyProgress { From 41ca18ec22553da97ce7fa1e80fc727ff65d5a15 Mon Sep 17 00:00:00 2001 From: Stanislav Panferov Date: Fri, 9 Dec 2016 09:48:54 +0100 Subject: [PATCH 071/860] refactor: review feedback --- src/repo.rs | 4 ++-- src/stash.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index 526dab3e0c..b6b1c4b2e4 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1751,10 +1751,10 @@ impl Repository { where C: FnMut(usize, &str, &Oid) -> bool { unsafe { - let mut data = Box::new(StashCbData { callback: &mut callback }); + let mut data = StashCbData { callback: &mut callback }; try_call!(raw::git_stash_foreach(self.raw(), stash_cb, - &mut *data as *mut _ as *mut _)); + &mut data as *mut _ as *mut _)); Ok(()) } } diff --git a/src/stash.rs b/src/stash.rs index dd6c0a9298..ca61c53355 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -126,7 +126,7 @@ extern fn stash_apply_progress_cb(progress: raw::git_stash_apply_progress_t, }; if res { 0 } else { -1 } - }).unwrap() + }).unwrap_or(-1) } #[cfg(test)] From 516f3c4e8be204fc3833c66fa54157c5844de53f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 27 Dec 2016 14:21:49 -0800 Subject: [PATCH 072/860] Add PartialEq,Eq on Delta Closes #167 --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 5e540d68b5..5cb4a4a4cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -796,7 +796,7 @@ bitflags! { } /// What type of change is described by a `DiffDelta`? -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Delta { /// No changes Unmodified, From 448bd8cb31682ddca2d6c046d45dbd26d94573cd Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Wed, 4 Jan 2017 12:09:49 +0100 Subject: [PATCH 073/860] update libgit2 to 42ad85ef01e372f1d65b9c561c1895d954450811 This contains a fix necessary for building with libressl Signed-off-by: Marc-Antoine Perennou --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index c9e967a1b4..42ad85ef01 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit c9e967a1b48c7a0b484fd3a4860e9c7a0aa4a319 +Subproject commit 42ad85ef01e372f1d65b9c561c1895d954450811 From 53d6bf11a0722c72a0512b90f4e1bebaf0e885eb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Jan 2017 09:25:07 -0800 Subject: [PATCH 074/860] Bump libgit2-sys to 0.6.6 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 3ebcf98c6d..c91e5bf3fc 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.5" +version = "0.6.6" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 05190ce00bf404af6430d05103dc8eec4e87f60e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 25 Jan 2017 11:34:40 -0800 Subject: [PATCH 075/860] Add binding for push_update_reference Needed to check if a push was successful --- src/remote.rs | 21 ++++++++++++++++-- src/remote_callbacks.rs | 48 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/remote.rs b/src/remote.rs index cd226ce94e..6e7cc43507 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -193,6 +193,10 @@ impl<'repo> Remote<'repo> { /// /// Perform all the steps for a push. If no refspecs are passed then the /// configured refspecs will be used. + /// + /// Note that you'll likely want to use `RemoteCallbacks` and set + /// `push_update_reference` to test whether all the references were pushed + /// successfully. pub fn push(&mut self, refspecs: &[&str], opts: Option<&mut PushOptions>) -> Result<(), Error> { @@ -437,7 +441,7 @@ mod tests { use std::cell::Cell; use tempdir::TempDir; use {Repository, Remote, RemoteCallbacks, Direction, FetchOptions}; - use {AutotagOption}; + use {AutotagOption, PushOptions}; #[test] fn smoke() { @@ -577,7 +581,20 @@ mod tests { Repository::init_bare(td2.path()).unwrap(); // git push let mut remote = repo.remote("origin", &url).unwrap(); - remote.push(&["refs/heads/master"], None).unwrap(); + let mut updated = false; + { + let mut callbacks = RemoteCallbacks::new(); + callbacks.push_update_reference(|refname, status| { + updated = true; + assert_eq!(refname, "refs/heads/master"); + assert_eq!(status, None); + Ok(()) + }); + let mut options = PushOptions::new(); + options.remote_callbacks(callbacks); + remote.push(&["refs/heads/master"], Some(&mut options)).unwrap(); + } + assert!(updated); let repo = Repository::clone(&url, td3.path()).unwrap(); let commit = repo.head().unwrap().target().unwrap(); diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 6035f3cda2..7598dfd335 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -20,6 +20,7 @@ pub struct RemoteCallbacks<'a> { sideband_progress: Option>>, update_tips: Option>>, certificate_check: Option>>, + push_update_reference: Option>>, } /// Struct representing the progress by an in-flight transfer. @@ -68,6 +69,13 @@ pub type UpdateTips<'a> = FnMut(&str, Oid, Oid) -> bool + 'a; /// argument. pub type CertificateCheck<'a> = FnMut(&Cert, &str) -> bool + 'a; +/// Callback for each updated reference on push. +/// +/// The first argument here is the `refname` of the reference, and the second is +/// the status message sent by a server. If the status is `Some` then the update +/// was rejected by the remote server with a reason why. +pub type PushUpdateReference<'a> = FnMut(&str, Option<&str>) -> Result<(), Error> + 'a; + impl<'a> RemoteCallbacks<'a> { /// Creates a new set of empty callbacks pub fn new() -> RemoteCallbacks<'a> { @@ -77,6 +85,7 @@ impl<'a> RemoteCallbacks<'a> { sideband_progress: None, update_tips: None, certificate_check: None, + push_update_reference: None, } } @@ -123,6 +132,18 @@ impl<'a> RemoteCallbacks<'a> { self.certificate_check = Some(Box::new(cb) as Box>); self } + + /// Set a callback to get invoked for each updated reference on a push. + /// + /// The first argument to the callback is the name of the reference and the + /// second is a status message sent by the server. If the status is `Some` + /// then the push was rejected. + pub fn push_update_reference(&mut self, cb: F) -> &mut RemoteCallbacks<'a> + where F: FnMut(&str, Option<&str>) -> Result<(), Error> + 'a, + { + self.push_update_reference = Some(Box::new(cb) as Box>); + self + } } impl<'a> Binding for RemoteCallbacks<'a> { @@ -153,6 +174,10 @@ impl<'a> Binding for RemoteCallbacks<'a> { certificate_check_cb; callbacks.certificate_check = Some(f); } + if self.push_update_reference.is_some() { + let f: extern fn(_, _, _) -> c_int = push_update_reference_cb; + callbacks.push_update_reference = Some(f); + } if self.update_tips.is_some() { let f: extern fn(*const c_char, *const raw::git_oid, *const raw::git_oid, *mut c_void) -> c_int @@ -332,3 +357,26 @@ extern fn certificate_check_cb(cert: *mut raw::git_cert, }); if ok == Some(true) {0} else {-1} } + +extern fn push_update_reference_cb(refname: *const c_char, + status: *const c_char, + data: *mut c_void) -> c_int { + panic::wrap(|| unsafe { + let payload = &mut *(data as *mut RemoteCallbacks); + let callback = match payload.push_update_reference { + Some(ref mut c) => c, + None => return 0, + }; + let refname = str::from_utf8(CStr::from_ptr(refname).to_bytes()) + .unwrap(); + let status = if status.is_null() { + None + } else { + Some(str::from_utf8(CStr::from_ptr(status).to_bytes()).unwrap()) + }; + match callback(refname, status) { + Ok(()) => 0, + Err(e) => e.raw_code(), + } + }).unwrap_or(-1) +} From a0f4e4b1f4434d347a0c36c982f01e0d4d6b9501 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 25 Jan 2017 11:35:05 -0800 Subject: [PATCH 076/860] Bump to 0.6.4 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e0753ba9e6..2f83b769df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.3" +version = "0.6.4" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From fdd4c7602974d5aa26a97b877a43381a6b12b3c8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 25 Jan 2017 11:37:53 -0800 Subject: [PATCH 077/860] Update metadata/doc urls --- Cargo.toml | 9 +++++++-- README.md | 2 +- src/lib.rs | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2f83b769df..c23714af61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,18 +8,23 @@ readme = "README.md" keywords = ["git"] repository = "https://github.com/alexcrichton/git2-rs" homepage = "https://github.com/alexcrichton/git2-rs" -documentation = "http://alexcrichton.com/git2-rs" +documentation = "https://docs.rs/git2-rs" description = """ Bindings to libgit2 for interoperating with git repositories. This library is both threadsafe and memory safe and allows both reading and writing git repositories. """ +categories = ["api-bindings"] + +[badges] +travis-ci = { repository = "alexcrichton/git2-rs" } +appveyor = { repository = "alexcrichton/git2-rs" } [dependencies] url = "1.0" bitflags = "0.7" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.6.4" } +libgit2-sys = { path = "libgit2-sys", version = "0.6.6" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/README.md b/README.md index c97c8274c5..9503a1952f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build Status](https://travis-ci.org/alexcrichton/git2-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/git2-rs) [![Build Status](https://ci.appveyor.com/api/projects/status/6vem3xgno2kuxnfm?svg=true)](https://ci.appveyor.com/project/alexcrichton/git2-rs) -[Documentation](http://alexcrichton.com/git2-rs/git2/index.html) +[Documentation](https://docs.rs/git2) libgit2 bindings for Rust diff --git a/src/lib.rs b/src/lib.rs index 5cb4a4a4cb..5762c7eb7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,7 +63,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "http://alexcrichton.com/git2-rs")] +#![doc(html_root_url = "https://docs.rs/git2/0.6")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![cfg_attr(test, deny(warnings))] From f3db4416ac7a543ef2a9c2385664896085a7e3ef Mon Sep 17 00:00:00 2001 From: Marthog Date: Thu, 26 Jan 2017 14:23:00 +0100 Subject: [PATCH 078/860] Fixed link to documentation. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c23714af61..31a11291cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ readme = "README.md" keywords = ["git"] repository = "https://github.com/alexcrichton/git2-rs" homepage = "https://github.com/alexcrichton/git2-rs" -documentation = "https://docs.rs/git2-rs" +documentation = "https://docs.rs/git2" description = """ Bindings to libgit2 for interoperating with git repositories. This library is both threadsafe and memory safe and allows both reading and writing git From 90cbc5d25ecb617c0c3f6d9d8c076f9f7b4255d0 Mon Sep 17 00:00:00 2001 From: Yong Wen Chua Date: Wed, 1 Feb 2017 13:41:17 +0800 Subject: [PATCH 079/860] Add RemoteConnection struct for Remote::connect --- examples/fetch.rs | 2 +- examples/ls-remote.rs | 3 +- src/lib.rs | 2 +- src/remote.rs | 66 ++++++++++++++++++++++++++++++++++--------- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/examples/fetch.rs b/examples/fetch.rs index a03ea4af2e..0b73bdd6b4 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -76,7 +76,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { // Connect to the remote end specifying that we want to fetch information // from it. - try!(remote.connect(Direction::Fetch)); + let _connection = try!(remote.connect(Direction::Fetch, None, None)); // Download the packfile and index it. This function updates the amount of // received data and the indexer stats which lets you inform the user about diff --git a/examples/ls-remote.rs b/examples/ls-remote.rs index 7522cafd78..ace0ce65dd 100644 --- a/examples/ls-remote.rs +++ b/examples/ls-remote.rs @@ -35,14 +35,13 @@ fn run(args: &Args) -> Result<(), git2::Error> { // Connect to the remote and call the printing function for each of the // remote references. - try!(remote.connect(Direction::Fetch)); + let _connection = try!(remote.connect(Direction::Fetch, None, None)); // Get the list of references on the remote and print out their name next to // what they point to. for head in try!(remote.list()).iter() { println!("{}\t{}", head.oid(), head.name()); } - Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 5762c7eb7c..4bb4322c1a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,7 +105,7 @@ pub use proxy_options::ProxyOptions; pub use reference::{Reference, References, ReferenceNames}; pub use reflog::{Reflog, ReflogEntry, ReflogIter}; pub use refspec::Refspec; -pub use remote::{Remote, Refspecs, RemoteHead, FetchOptions, PushOptions}; +pub use remote::{Remote, RemoteConnection, Refspecs, RemoteHead, FetchOptions, PushOptions}; pub use remote_callbacks::{RemoteCallbacks, Credentials, TransferProgress}; pub use remote_callbacks::{TransportMessage, Progress, UpdateTips}; pub use repo::{Repository, RepositoryInitOptions}; diff --git a/src/remote.rs b/src/remote.rs index 6e7cc43507..41dd56fee8 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -50,6 +50,16 @@ pub struct PushOptions<'cb> { pb_parallelism: u32, } +/// Holds callbacks for a connection to a `Remote`. Disconnects when dropped +// To prevent use after free for the callbacks for the lifetime of the remote connection +#[allow(dead_code)] +pub struct RemoteConnection<'repo, 'connection, 'cb> where 'repo: 'connection { + callbacks: Option>, + proxy: Option>, + remote_raw: *mut raw::git_remote, + _marker: marker::PhantomData<&'connection Remote<'repo>>, +} + impl<'repo> Remote<'repo> { /// Ensure the remote name is well-formed. pub fn is_valid_name(remote_name: &str) -> bool { @@ -98,15 +108,31 @@ impl<'repo> Remote<'repo> { } /// Open a connection to a remote. - pub fn connect(&mut self, dir: Direction) -> Result<(), Error> { - // TODO: can callbacks be exposed safely? + /// + /// Returns a `RemoteConnection` that will disconnect once dropped + pub fn connect<'connection, 'cb>(&mut self, + dir: Direction, + cb: Option>, + proxy_options: Option>) + -> Result, Error> { + + let cb_raw = cb.as_ref().map(|m| &m.raw() as *const raw::git_remote_callbacks) + .unwrap_or_else(|| 0 as *const _); + let proxy_raw = proxy_options.as_ref().map(|m| &m.raw() as *const raw::git_proxy_options) + .unwrap_or_else(|| 0 as *const _); unsafe { try_call!(raw::git_remote_connect(self.raw, dir, - 0 as *const _, - 0 as *const _, + cb_raw, + proxy_raw, 0 as *const _)); } - Ok(()) + + Ok(RemoteConnection::<'repo, 'connection, 'cb> { + callbacks: cb, + proxy: proxy_options, + remote_raw: self.raw.clone(), + _marker: marker::PhantomData + }) } /// Check whether the remote is connected @@ -116,7 +142,11 @@ impl<'repo> Remote<'repo> { /// Disconnect from the remote pub fn disconnect(&mut self) { - unsafe { raw::git_remote_disconnect(self.raw) } + Remote::disconnect_raw(self.raw) + } + + fn disconnect_raw(remote_raw: *mut raw::git_remote) { + unsafe { raw::git_remote_disconnect(remote_raw) } } /// Download and index the packfile @@ -436,6 +466,12 @@ impl<'cb> Binding for PushOptions<'cb> { } } +impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb> { + fn drop(&mut self) { + Remote::disconnect_raw(self.remote_raw) + } +} + #[cfg(test)] mod tests { use std::cell::Cell; @@ -499,14 +535,18 @@ mod tests { assert_eq!(remotes.iter().next().unwrap(), Some("origin")); } - origin.connect(Direction::Push).unwrap(); - assert!(origin.connected()); - origin.disconnect(); + { + let _connection = origin.connect(Direction::Push, None, None).unwrap(); + assert!(origin.connected()); + } + assert!(!origin.connected()); - origin.connect(Direction::Fetch).unwrap(); - assert!(origin.connected()); - origin.download(&[], None).unwrap(); - origin.disconnect(); + { + let _connection = origin.connect(Direction::Fetch, None, None).unwrap(); + assert!(origin.connected()); + origin.download(&[], None).unwrap(); + } + assert!(!origin.connected()); origin.fetch(&[], None, None).unwrap(); origin.fetch(&[], None, Some("foo")).unwrap(); From 40bc55f8770baf8b7302a27bbd1dee814ab64d96 Mon Sep 17 00:00:00 2001 From: Yong Wen Chua Date: Wed, 1 Feb 2017 16:29:47 +0800 Subject: [PATCH 080/860] Add test that causes `SIGSEGV: invalid memory reference` --- src/remote.rs | 52 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/src/remote.rs b/src/remote.rs index 41dd56fee8..f440b8c0f6 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -51,11 +51,9 @@ pub struct PushOptions<'cb> { } /// Holds callbacks for a connection to a `Remote`. Disconnects when dropped -// To prevent use after free for the callbacks for the lifetime of the remote connection -#[allow(dead_code)] pub struct RemoteConnection<'repo, 'connection, 'cb> where 'repo: 'connection { - callbacks: Option>, - proxy: Option>, + callbacks: RemoteCallbacks<'cb>, + proxy: ProxyOptions<'cb>, remote_raw: *mut raw::git_remote, _marker: marker::PhantomData<&'connection Remote<'repo>>, } @@ -116,23 +114,20 @@ impl<'repo> Remote<'repo> { proxy_options: Option>) -> Result, Error> { - let cb_raw = cb.as_ref().map(|m| &m.raw() as *const raw::git_remote_callbacks) - .unwrap_or_else(|| 0 as *const _); - let proxy_raw = proxy_options.as_ref().map(|m| &m.raw() as *const raw::git_proxy_options) - .unwrap_or_else(|| 0 as *const _); + let connection = RemoteConnection { + callbacks: cb.unwrap_or_else(|| RemoteCallbacks::new()), + proxy: proxy_options.unwrap_or_else(|| ProxyOptions::new()), + remote_raw: self.raw.clone(), + _marker: marker::PhantomData + }; unsafe { try_call!(raw::git_remote_connect(self.raw, dir, - cb_raw, - proxy_raw, + &connection.callbacks.raw(), + &connection.proxy.raw(), 0 as *const _)); } - Ok(RemoteConnection::<'repo, 'connection, 'cb> { - callbacks: cb, - proxy: proxy_options, - remote_raw: self.raw.clone(), - _marker: marker::PhantomData - }) + Ok(connection) } /// Check whether the remote is connected @@ -544,7 +539,6 @@ mod tests { { let _connection = origin.connect(Direction::Fetch, None, None).unwrap(); assert!(origin.connected()); - origin.download(&[], None).unwrap(); } assert!(!origin.connected()); @@ -611,6 +605,30 @@ mod tests { assert!(progress_hit.get()); } + /// This test is meant to assure that the callbacks provided to connect will not cause + /// segfaults + #[test] + fn connect_cb() { + let (td, _repo) = ::test::repo_init(); + let td2 = TempDir::new("git").unwrap(); + let url = ::test::path2url(https://github.com/&td.path()); + + let repo = Repository::init(td2.path()).unwrap(); + let mut callbacks = RemoteCallbacks::new(); + callbacks.sideband_progress(|_progress| { + // no-op + true + }); + + let mut origin = repo.remote("origin", &url).unwrap(); + + { + let _connection = origin.connect(Direction::Fetch, Some(callbacks), None); + origin.fetch(&[], None, None).unwrap(); + } + assert!(!origin.connected()); + } + #[test] fn push() { let (_td, repo) = ::test::repo_init(); From c7420350121398d034dd2f6759ac8893e23cf81d Mon Sep 17 00:00:00 2001 From: Yong Wen Chua Date: Wed, 1 Feb 2017 18:11:30 +0800 Subject: [PATCH 081/860] Fix segfault --- src/remote.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/remote.rs b/src/remote.rs index f440b8c0f6..e2ec85d79c 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -51,9 +51,12 @@ pub struct PushOptions<'cb> { } /// Holds callbacks for a connection to a `Remote`. Disconnects when dropped +#[allow(dead_code)] pub struct RemoteConnection<'repo, 'connection, 'cb> where 'repo: 'connection { callbacks: RemoteCallbacks<'cb>, + callbacks_raw: raw::git_remote_callbacks, proxy: ProxyOptions<'cb>, + proxy_raw: raw::git_proxy_options, remote_raw: *mut raw::git_remote, _marker: marker::PhantomData<&'connection Remote<'repo>>, } @@ -114,20 +117,25 @@ impl<'repo> Remote<'repo> { proxy_options: Option>) -> Result, Error> { - let connection = RemoteConnection { - callbacks: cb.unwrap_or_else(|| RemoteCallbacks::new()), - proxy: proxy_options.unwrap_or_else(|| ProxyOptions::new()), - remote_raw: self.raw.clone(), - _marker: marker::PhantomData - }; + let cb = cb.unwrap_or_else(|| RemoteCallbacks::new()); + let cb_raw = cb.raw(); + let proxy_options = proxy_options.unwrap_or_else(|| ProxyOptions::new()); + let proxy_raw = proxy_options.raw(); unsafe { try_call!(raw::git_remote_connect(self.raw, dir, - &connection.callbacks.raw(), - &connection.proxy.raw(), + &cb_raw, + &proxy_raw, 0 as *const _)); } - Ok(connection) + Ok(RemoteConnection { + callbacks: cb, + callbacks_raw: cb_raw, + proxy: proxy_options, + proxy_raw: proxy_raw, + remote_raw: self.raw.clone(), + _marker: marker::PhantomData + }) } /// Check whether the remote is connected From 5f07fe263b99b34e724a77a88d99587a95b49ce5 Mon Sep 17 00:00:00 2001 From: Yong Wen Chua Date: Wed, 1 Feb 2017 18:15:10 +0800 Subject: [PATCH 082/860] Indentation fixes --- src/remote.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/remote.rs b/src/remote.rs index e2ec85d79c..21626bdfa9 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -112,9 +112,9 @@ impl<'repo> Remote<'repo> { /// /// Returns a `RemoteConnection` that will disconnect once dropped pub fn connect<'connection, 'cb>(&mut self, - dir: Direction, - cb: Option>, - proxy_options: Option>) + dir: Direction, + cb: Option>, + proxy_options: Option>) -> Result, Error> { let cb = cb.unwrap_or_else(|| RemoteCallbacks::new()); From 6aec20d7c823aa8b034d9f1e6d0d276f85d9a6e3 Mon Sep 17 00:00:00 2001 From: Yong Wen Chua Date: Fri, 3 Feb 2017 09:56:19 +0800 Subject: [PATCH 083/860] Expose `list` and `connected` through `RemoteConnection` - `RemoteConnection` will now hold a mutable reference to its `Remote` - So it will have to be dropped before the `Remote` is usable again - Removed the manual `connect` in `examples/fetch.rs` because it's not needed. -- `fetch` will automatically connect --- examples/fetch.rs | 6 +---- examples/ls-remote.rs | 4 ++-- src/remote.rs | 52 ++++++++++++++++++++++++++++--------------- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/examples/fetch.rs b/examples/fetch.rs index 0b73bdd6b4..12719f973f 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -19,7 +19,7 @@ extern crate docopt; extern crate rustc_serialize; use docopt::Docopt; -use git2::{Repository, RemoteCallbacks, Direction, AutotagOption, FetchOptions}; +use git2::{Repository, RemoteCallbacks, AutotagOption, FetchOptions}; use std::io::{self, Write}; use std::str; @@ -74,10 +74,6 @@ fn run(args: &Args) -> Result<(), git2::Error> { true }); - // Connect to the remote end specifying that we want to fetch information - // from it. - let _connection = try!(remote.connect(Direction::Fetch, None, None)); - // Download the packfile and index it. This function updates the amount of // received data and the indexer stats which lets you inform the user about // progress. diff --git a/examples/ls-remote.rs b/examples/ls-remote.rs index ace0ce65dd..41a6e56362 100644 --- a/examples/ls-remote.rs +++ b/examples/ls-remote.rs @@ -35,11 +35,11 @@ fn run(args: &Args) -> Result<(), git2::Error> { // Connect to the remote and call the printing function for each of the // remote references. - let _connection = try!(remote.connect(Direction::Fetch, None, None)); + let connection = try!(remote.connect(Direction::Fetch, None, None)); // Get the list of references on the remote and print out their name next to // what they point to. - for head in try!(remote.list()).iter() { + for head in try!(connection.list()).iter() { println!("{}\t{}", head.oid(), head.name()); } Ok(()) diff --git a/src/remote.rs b/src/remote.rs index 21626bdfa9..79ce81e578 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -57,8 +57,7 @@ pub struct RemoteConnection<'repo, 'connection, 'cb> where 'repo: 'connection { callbacks_raw: raw::git_remote_callbacks, proxy: ProxyOptions<'cb>, proxy_raw: raw::git_proxy_options, - remote_raw: *mut raw::git_remote, - _marker: marker::PhantomData<&'connection Remote<'repo>>, + remote: &'connection mut Remote<'repo>, } impl<'repo> Remote<'repo> { @@ -111,7 +110,7 @@ impl<'repo> Remote<'repo> { /// Open a connection to a remote. /// /// Returns a `RemoteConnection` that will disconnect once dropped - pub fn connect<'connection, 'cb>(&mut self, + pub fn connect<'connection, 'cb>(&'connection mut self, dir: Direction, cb: Option>, proxy_options: Option>) @@ -133,8 +132,7 @@ impl<'repo> Remote<'repo> { callbacks_raw: cb_raw, proxy: proxy_options, proxy_raw: proxy_raw, - remote_raw: self.raw.clone(), - _marker: marker::PhantomData + remote: self, }) } @@ -145,11 +143,7 @@ impl<'repo> Remote<'repo> { /// Disconnect from the remote pub fn disconnect(&mut self) { - Remote::disconnect_raw(self.raw) - } - - fn disconnect_raw(remote_raw: *mut raw::git_remote) { - unsafe { raw::git_remote_disconnect(remote_raw) } + unsafe { raw::git_remote_disconnect(self.raw) } } /// Download and index the packfile @@ -469,9 +463,24 @@ impl<'cb> Binding for PushOptions<'cb> { } } +impl<'repo, 'connection, 'cb> RemoteConnection<'repo, 'connection, 'cb> { + /// Check whether the remote is (still) connected + pub fn connected(&mut self) -> bool { + self.remote.connected() + } + + /// Get the remote repository's reference advertisement list. + /// + /// This list is available as soon as the connection to + /// the remote is initiated and it remains available after disconnecting. + pub fn list(&self) -> Result<&[RemoteHead], Error> { + self.remote.list() + } +} + impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb> { fn drop(&mut self) { - Remote::disconnect_raw(self.remote_raw) + self.remote.disconnect() } } @@ -539,14 +548,14 @@ mod tests { } { - let _connection = origin.connect(Direction::Push, None, None).unwrap(); - assert!(origin.connected()); + let mut connection = origin.connect(Direction::Push, None, None).unwrap(); + assert!(connection.connected()); } assert!(!origin.connected()); { - let _connection = origin.connect(Direction::Fetch, None, None).unwrap(); - assert!(origin.connected()); + let mut connection = origin.connect(Direction::Fetch, None, None).unwrap(); + assert!(connection.connected()); } assert!(!origin.connected()); @@ -616,7 +625,7 @@ mod tests { /// This test is meant to assure that the callbacks provided to connect will not cause /// segfaults #[test] - fn connect_cb() { + fn connect_list() { let (td, _repo) = ::test::repo_init(); let td2 = TempDir::new("git").unwrap(); let url = ::test::path2url(https://github.com/&td.path()); @@ -631,8 +640,15 @@ mod tests { let mut origin = repo.remote("origin", &url).unwrap(); { - let _connection = origin.connect(Direction::Fetch, Some(callbacks), None); - origin.fetch(&[], None, None).unwrap(); + let mut connection = origin.connect(Direction::Fetch, Some(callbacks), None).unwrap(); + assert!(connection.connected()); + + let list = t!(connection.list()); + assert_eq!(list.len(), 2); + assert_eq!(list[0].name(), "HEAD"); + assert!(!list[0].is_local()); + assert_eq!(list[1].name(), "refs/heads/master"); + assert!(!list[1].is_local()); } assert!(!origin.connected()); } From 3b9fea0471422c8d28760329cb0f831b7f401e9a Mon Sep 17 00:00:00 2001 From: Yong Wen Chua Date: Tue, 7 Feb 2017 10:24:53 +0800 Subject: [PATCH 084/860] Box up callbacks and proxy options --- src/remote.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/remote.rs b/src/remote.rs index 79ce81e578..3d49de1024 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -53,10 +53,8 @@ pub struct PushOptions<'cb> { /// Holds callbacks for a connection to a `Remote`. Disconnects when dropped #[allow(dead_code)] pub struct RemoteConnection<'repo, 'connection, 'cb> where 'repo: 'connection { - callbacks: RemoteCallbacks<'cb>, - callbacks_raw: raw::git_remote_callbacks, - proxy: ProxyOptions<'cb>, - proxy_raw: raw::git_proxy_options, + callbacks: Box>, + proxy: Box>, remote: &'connection mut Remote<'repo>, } @@ -116,22 +114,18 @@ impl<'repo> Remote<'repo> { proxy_options: Option>) -> Result, Error> { - let cb = cb.unwrap_or_else(|| RemoteCallbacks::new()); - let cb_raw = cb.raw(); - let proxy_options = proxy_options.unwrap_or_else(|| ProxyOptions::new()); - let proxy_raw = proxy_options.raw(); + let cb = Box::new(cb.unwrap_or_else(|| RemoteCallbacks::new())); + let proxy_options = Box::new(proxy_options.unwrap_or_else(|| ProxyOptions::new())); unsafe { try_call!(raw::git_remote_connect(self.raw, dir, - &cb_raw, - &proxy_raw, + &cb.raw(), + &proxy_options.raw(), 0 as *const _)); } Ok(RemoteConnection { callbacks: cb, - callbacks_raw: cb_raw, proxy: proxy_options, - proxy_raw: proxy_raw, remote: self, }) } From 8392c95ddbd239a6ffc05d4d6417e8d5aa9c764f Mon Sep 17 00:00:00 2001 From: Yong Wen Chua Date: Wed, 8 Feb 2017 09:30:07 +0800 Subject: [PATCH 085/860] Unbox proxy_options --- src/remote.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/remote.rs b/src/remote.rs index 3d49de1024..5e5f021332 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -51,10 +51,9 @@ pub struct PushOptions<'cb> { } /// Holds callbacks for a connection to a `Remote`. Disconnects when dropped -#[allow(dead_code)] pub struct RemoteConnection<'repo, 'connection, 'cb> where 'repo: 'connection { - callbacks: Box>, - proxy: Box>, + _callbacks: Box>, + _proxy: ProxyOptions<'cb>, remote: &'connection mut Remote<'repo>, } @@ -115,7 +114,7 @@ impl<'repo> Remote<'repo> { -> Result, Error> { let cb = Box::new(cb.unwrap_or_else(|| RemoteCallbacks::new())); - let proxy_options = Box::new(proxy_options.unwrap_or_else(|| ProxyOptions::new())); + let proxy_options = proxy_options.unwrap_or_else(|| ProxyOptions::new()); unsafe { try_call!(raw::git_remote_connect(self.raw, dir, &cb.raw(), @@ -124,8 +123,8 @@ impl<'repo> Remote<'repo> { } Ok(RemoteConnection { - callbacks: cb, - proxy: proxy_options, + _callbacks: cb, + _proxy: proxy_options, remote: self, }) } From b18a81279f0f167b06ff30506fefad549619d7d5 Mon Sep 17 00:00:00 2001 From: William Bain Date: Sat, 11 Feb 2017 16:12:14 -0500 Subject: [PATCH 086/860] Docs: Update cross-reference in Commit::amend --- src/commit.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/commit.rs b/src/commit.rs index 91929d15e5..3aab0b8e19 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -178,7 +178,9 @@ impl<'repo> Commit<'repo> { /// except that any non-`None` values will be updated. The new commit has /// the same parents as the old commit. /// - /// For information about `update_ref`, see `new`. + /// For information about `update_ref`, see [`Repository::commit`]. + /// + /// [`Repository::commit`]: struct.Repository.html#method.commit pub fn amend(&self, update_ref: Option<&str>, author: Option<&Signature>, From c2a4f3aec7d254a11addd13f8174c81d8dbc3d43 Mon Sep 17 00:00:00 2001 From: Yong Wen Chua Date: Mon, 13 Feb 2017 09:56:33 +0800 Subject: [PATCH 087/860] Rename function to `connect_auth` --- examples/ls-remote.rs | 2 +- src/remote.rs | 35 ++++++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/examples/ls-remote.rs b/examples/ls-remote.rs index 41a6e56362..130fa779f2 100644 --- a/examples/ls-remote.rs +++ b/examples/ls-remote.rs @@ -35,7 +35,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { // Connect to the remote and call the printing function for each of the // remote references. - let connection = try!(remote.connect(Direction::Fetch, None, None)); + let connection = try!(remote.connect_auth(Direction::Fetch, None, None)); // Get the list of references on the remote and print out their name next to // what they point to. diff --git a/src/remote.rs b/src/remote.rs index 5e5f021332..c5fa08b39f 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -105,12 +105,24 @@ impl<'repo> Remote<'repo> { } /// Open a connection to a remote. + pub fn connect(&mut self, dir: Direction) -> Result<(), Error> { + // 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 _)); + } + Ok(()) + } + + /// Open a connection to a remote with callbacks and proxy settings /// /// Returns a `RemoteConnection` that will disconnect once dropped - pub fn connect<'connection, 'cb>(&'connection mut self, - dir: Direction, - cb: Option>, - proxy_options: Option>) + pub fn connect_auth<'connection, 'cb>(&'connection mut self, + dir: Direction, + cb: Option>, + proxy_options: Option>) -> Result, Error> { let cb = Box::new(cb.unwrap_or_else(|| RemoteCallbacks::new())); @@ -540,14 +552,23 @@ mod tests { assert_eq!(remotes.iter().next().unwrap(), Some("origin")); } + origin.connect(Direction::Push).unwrap(); + assert!(origin.connected()); + origin.disconnect(); + + origin.connect(Direction::Fetch).unwrap(); + assert!(origin.connected()); + origin.download(&[], None).unwrap(); + origin.disconnect(); + { - let mut connection = origin.connect(Direction::Push, None, None).unwrap(); + let mut connection = origin.connect_auth(Direction::Push, None, None).unwrap(); assert!(connection.connected()); } assert!(!origin.connected()); { - let mut connection = origin.connect(Direction::Fetch, None, None).unwrap(); + let mut connection = origin.connect_auth(Direction::Fetch, None, None).unwrap(); assert!(connection.connected()); } assert!(!origin.connected()); @@ -633,7 +654,7 @@ mod tests { let mut origin = repo.remote("origin", &url).unwrap(); { - let mut connection = origin.connect(Direction::Fetch, Some(callbacks), None).unwrap(); + let mut connection = origin.connect_auth(Direction::Fetch, Some(callbacks), None).unwrap(); assert!(connection.connected()); let list = t!(connection.list()); From 0cd7d63189c54b03740d457dc8e2119b93c7b339 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 15 Feb 2017 14:13:51 -0800 Subject: [PATCH 088/860] Update libgit2 submodule --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 42ad85ef01..a59545de5e 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 42ad85ef01e372f1d65b9c561c1895d954450811 +Subproject commit a59545de5e57769f858ed2657b9fb850675f227f From 0d745cf0efad95a9e407beecd7b508ca9a37df80 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 15 Feb 2017 14:15:08 -0800 Subject: [PATCH 089/860] Bump libgit2-sys to 0.6.7 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index c91e5bf3fc..2592897c27 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.6" +version = "0.6.7" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 077eb0ead340842f097af2122493d9d6a3efc4de Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 16 Feb 2017 13:44:35 -0800 Subject: [PATCH 090/860] Update git2-curl docs --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 6b2d6881d8..a9bf353901 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/git2-rs" homepage = "https://github.com/alexcrichton/git2-rs" -documentation = "http://alexcrichton.com/git2-rs/git2-curl" +documentation = "https://docs.rs/git2-curl" description = """ Backend for an HTTP transport in libgit2 powered by libcurl. From 63a4e9ffdeecd91c935c1b55c8b3c467397da6e9 Mon Sep 17 00:00:00 2001 From: Mateusz Mikula Date: Mon, 13 Mar 2017 02:16:23 +0100 Subject: [PATCH 091/860] mingw: detect and link http_parser Otherwise it fails with "undefined reference to `http_parser_parse_url`" --- libgit2-sys/build.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 1fe60b9454..018562fa46 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -136,16 +136,6 @@ fn main() { } } - if target.contains("windows") { - println!("cargo:rustc-link-lib=winhttp"); - println!("cargo:rustc-link-lib=rpcrt4"); - println!("cargo:rustc-link-lib=ole32"); - println!("cargo:rustc-link-lib=crypt32"); - println!("cargo:rustc-link-lib=static=git2"); - println!("cargo:rustc-link-search=native={}/lib", dst.display()); - return - } - // libgit2 requires the http_parser library for the HTTP transport to be // implemented, and it will attempt to use the system http_parser if it's // available. Detect this situation and report using the system http parser @@ -163,6 +153,16 @@ fn main() { } } + if target.contains("windows") { + println!("cargo:rustc-link-lib=winhttp"); + println!("cargo:rustc-link-lib=rpcrt4"); + println!("cargo:rustc-link-lib=ole32"); + println!("cargo:rustc-link-lib=crypt32"); + println!("cargo:rustc-link-lib=static=git2"); + println!("cargo:rustc-link-search=native={}/lib", dst.display()); + return + } + println!("cargo:rustc-link-lib=static=git2"); println!("cargo:rustc-link-search=native={}", dst.join("lib").display()); if target.contains("apple") { From 34b0dbe07e3d899934dc4906fd56d75599df0abb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 24 Apr 2017 06:44:12 -0700 Subject: [PATCH 092/860] Update libgit2 to 0.25.1 --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index a59545de5e..2fcb8705e5 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit a59545de5e57769f858ed2657b9fb850675f227f +Subproject commit 2fcb8705e584ca61f6c4657525c9d2713f6a39d2 From 160cbdc67296a7f119de83965ae2d11f72921620 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 24 Apr 2017 06:48:51 -0700 Subject: [PATCH 093/860] Note that libgit2 0.25.1 is required --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 9503a1952f..76df26097b 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,12 @@ libgit2 bindings for Rust git2 = "0.6" ``` +## Version of libgit2 + +Currently this library requires libgit2 0.25.1. The source for libgit2 is +included in the libgit2-sys crate so there's no need to pre-install the libgit2 +library, the libgit2-sys crate will figure that and/or build that for you. + ## Building git2-rs First, you'll need to install _CMake_. Afterwards, just run: From 00abecd932c886aba6224960bec962f23a491229 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 24 Apr 2017 06:49:51 -0700 Subject: [PATCH 094/860] Bump libgit2-sys to 0.6.8 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 2592897c27..5334f61096 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.7" +version = "0.6.8" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 6a4f91d1e3cf269f5adddebdc09cd92ff0694f5c Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Thu, 27 Apr 2017 21:26:43 +0200 Subject: [PATCH 095/860] libgit2-sys: unset DESTDIR during libgit2 build As we run cmake install, DESTDIR is used when defined, libgit2.a ends up in and we get this failure: Compiling libgit2-sys v0.6.8 (file:///home/keruspe/Sources/git2-rs/libgit2-sys) Running `rustc --crate-name libgit2_sys lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=8c05c334c8251b8f -C extra-filename=-8c05c334c8251b8f --out-dir /home/keruspe/Sources/git2-rs/target/debug/deps -L dependency=/home/keruspe/Sources/git2-rs/target/debug/deps --extern libz_sys=/home/keruspe/Sources/git2-rs/target/debug/deps/liblibz_sys-b34e05ee2e9e1468.rlib --extern libc=/home/keruspe/Sources/git2-rs/target/debug/deps/liblibc-5dc7b85e748840b4.rlib -L native=/home/keruspe/Sources/git2-rs/target/debug/build/libgit2-sys-7842f88a9e389e71/out/lib -l static=git2 -L native=/usr/x86_64-pc-linux-gnu/lib` error: could not find native static library `git2`, perhaps an -L flag is missing? error: Could not compile `libgit2-sys`. Caused by: process didn't exit successfully: `rustc --crate-name libgit2_sys lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=8c05c334c8251b8f -C extra-filename=-8c05c334c8251b8f --out-dir /home/keruspe/Sources/git2-rs/target/debug/deps -L dependency=/home/keruspe/Sources/git2-rs/target/debug/deps --extern libz_sys=/home/keruspe/Sources/git2-rs/target/debug/deps/liblibz_sys-b34e05ee2e9e1468.rlib --extern libc=/home/keruspe/Sources/git2-rs/target/debug/deps/liblibc-5dc7b85e748840b4.rlib -L native=/home/keruspe/Sources/git2-rs/target/debug/build/libgit2-sys-7842f88a9e389e71/out/lib -l static=git2 -L native=/usr/x86_64-pc-linux-gnu/lib` (exit code: 101) Signed-off-by: Marc-Antoine Perennou --- libgit2-sys/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 018562fa46..a89eef4390 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -120,6 +120,8 @@ fn main() { let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap()); t!(fs::create_dir_all(env::var("OUT_DIR").unwrap())); + // Unset DESTDIR or libgit2.a ends up in it and cargo can't find it + env::remove_var("DESTDIR"); let dst = cfg.define("BUILD_SHARED_LIBS", "OFF") .define("BUILD_CLAR", "OFF") .register_dep("Z") From 53c5b04991d16317dec68f99cc0a6b60dcb63b46 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Fri, 28 Apr 2017 09:54:42 +0200 Subject: [PATCH 096/860] libgit2: update to ee89941fa2b861332defb5e3a8ce12c23c496ed7 This fixes cmopatibility with libressl Signed-off-by: Marc-Antoine Perennou --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 2fcb8705e5..ee89941fa2 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 2fcb8705e584ca61f6c4657525c9d2713f6a39d2 +Subproject commit ee89941fa2b861332defb5e3a8ce12c23c496ed7 From 3dc4e80bf818996c601a01971afe93e83c940337 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 29 Apr 2017 21:14:28 -0700 Subject: [PATCH 097/860] Bump libgit2-sys to 0.6.9 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 5334f61096..d4c09f0928 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.8" +version = "0.6.9" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 196065d7bfc833cd6e3982a143e713bc55cd96c8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 8 May 2017 09:14:58 -0700 Subject: [PATCH 098/860] Update OSX instructions --- README.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/README.md b/README.md index 76df26097b..1d32bf8f55 100644 --- a/README.md +++ b/README.md @@ -38,17 +38,6 @@ been removed, but if you're using Homebrew you can install them via: brew install openssl ``` -To get this library to pick them up the [standard `rust-openssl` -instructions][instr] can be used to transitively inform libssh2-sys about where -the header files are: - -[instr]: https://github.com/sfackler/rust-openssl#osx - -```sh -export OPENSSL_INCLUDE_DIR=`brew --prefix openssl`/include -export OPENSSL_LIB_DIR=`brew --prefix openssl`/lib -``` - # License `git2-rs` is primarily distributed under the terms of both the MIT license and From 77c6e810f6233621235883dc6cf22da930ea4749 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Tue, 9 May 2017 10:33:14 -0700 Subject: [PATCH 099/860] Add `git_index_has_conflicts` to libgit2-sys --- libgit2-sys/lib.rs | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 libgit2-sys/lib.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs old mode 100644 new mode 100755 index 6f0a2af31b..30f12eeb99 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1981,6 +1981,7 @@ extern { pub fn git_index_get_bypath(index: *mut git_index, path: *const c_char, stage: c_int) -> *const git_index_entry; + pub fn git_index_has_conflicts(index: *const git_index) -> c_int; pub fn git_index_new(index: *mut *mut git_index) -> c_int; pub fn git_index_open(index: *mut *mut git_index, index_path: *const c_char) -> c_int; From 1564d2799c5b205196b87660fefbe549fbbebced Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Tue, 9 May 2017 10:43:10 -0700 Subject: [PATCH 100/860] Add the `git2::Index::has_conflicts` method The method takes `&self` and returns `true` if the `Index` contains conflicts, `false` otherwise. --- src/index.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/index.rs b/src/index.rs index d9629cb808..cb2f7618c2 100644 --- a/src/index.rs +++ b/src/index.rs @@ -247,6 +247,15 @@ impl Index { } } + /// Does this index have conflicts? + /// + /// Returns `true` if the index contains conflicts, `false` if it does not. + pub fn has_conflicts(&self) -> bool { + unsafe { + raw::git_index_has_conflicts(self.raw) == 1 + } + } + /// Get the full path to the index file on disk. /// /// Returns `None` if this is an in-memory index. @@ -617,4 +626,3 @@ mod tests { } } } - From 80371d2b6809219817d57a31715270069ae41478 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 May 2017 11:32:39 -0700 Subject: [PATCH 101/860] Bump libgit2-sys to 0.6.10 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index d4c09f0928..b474e5a425 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.9" +version = "0.6.10" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From d33a53f9ddfcda75ad000bd78c4f594fb418194b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 May 2017 11:33:15 -0700 Subject: [PATCH 102/860] Bump to 0.6.5 --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 31a11291cd..1ff0945af8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.4" +version = "0.6.5" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -24,7 +24,7 @@ appveyor = { repository = "alexcrichton/git2-rs" } url = "1.0" bitflags = "0.7" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.6.6" } +libgit2-sys = { path = "libgit2-sys", version = "0.6.10" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From c0ad15449fe6262855ca75c910f5f70ef81c84dd Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 21 May 2017 11:26:19 -0400 Subject: [PATCH 103/860] Bump bitflags. --- Cargo.toml | 2 +- src/lib.rs | 212 ++++++++++++++++++++++++++--------------------------- 2 files changed, 107 insertions(+), 107 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1ff0945af8..655cf087dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ appveyor = { repository = "alexcrichton/git2-rs" } [dependencies] url = "1.0" -bitflags = "0.7" +bitflags = "0.9" libc = "0.2" libgit2-sys = { path = "libgit2-sys", version = "0.6.10" } diff --git a/src/lib.rs b/src/lib.rs index 4bb4322c1a..e790c55aed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -348,136 +348,136 @@ pub enum FileFavor { bitflags! { /// Orderings that may be specified for Revwalk iteration. - pub flags Sort: u32 { + pub struct Sort: u32 { /// Sort the repository contents in no particular ordering. /// /// This sorting is arbitrary, implementation-specific, and subject to /// change at any time. This is the default sorting for new walkers. - const SORT_NONE = raw::GIT_SORT_NONE as u32, + const SORT_NONE = raw::GIT_SORT_NONE as u32; /// Sort the repository contents in topological order (parents before /// children). /// /// This sorting mode can be combined with time sorting. - const SORT_TOPOLOGICAL = raw::GIT_SORT_TOPOLOGICAL as u32, + const SORT_TOPOLOGICAL = raw::GIT_SORT_TOPOLOGICAL as u32; /// Sort the repository contents by commit time. /// /// This sorting mode can be combined with topological sorting. - const SORT_TIME = raw::GIT_SORT_TIME as u32, + const SORT_TIME = raw::GIT_SORT_TIME as u32; /// Iterate through the repository contents in reverse order. /// /// This sorting mode can be combined with any others. - const SORT_REVERSE = raw::GIT_SORT_REVERSE as u32, + const SORT_REVERSE = raw::GIT_SORT_REVERSE as u32; } } bitflags! { /// Types of credentials that can be requested by a credential callback. - pub flags CredentialType: u32 { + pub struct CredentialType: u32 { #[allow(missing_docs)] - const USER_PASS_PLAINTEXT = raw::GIT_CREDTYPE_USERPASS_PLAINTEXT as u32, + const USER_PASS_PLAINTEXT = raw::GIT_CREDTYPE_USERPASS_PLAINTEXT as u32; #[allow(missing_docs)] - const SSH_KEY = raw::GIT_CREDTYPE_SSH_KEY as u32, + const SSH_KEY = raw::GIT_CREDTYPE_SSH_KEY as u32; #[allow(missing_docs)] - const SSH_MEMORY = raw::GIT_CREDTYPE_SSH_MEMORY as u32, + const SSH_MEMORY = raw::GIT_CREDTYPE_SSH_MEMORY as u32; #[allow(missing_docs)] - const SSH_CUSTOM = raw::GIT_CREDTYPE_SSH_CUSTOM as u32, + const SSH_CUSTOM = raw::GIT_CREDTYPE_SSH_CUSTOM as u32; #[allow(missing_docs)] - const DEFAULT = raw::GIT_CREDTYPE_DEFAULT as u32, + const DEFAULT = raw::GIT_CREDTYPE_DEFAULT as u32; #[allow(missing_docs)] - const SSH_INTERACTIVE = raw::GIT_CREDTYPE_SSH_INTERACTIVE as u32, + const SSH_INTERACTIVE = raw::GIT_CREDTYPE_SSH_INTERACTIVE as u32; #[allow(missing_docs)] - const USERNAME = raw::GIT_CREDTYPE_USERNAME as u32, + const USERNAME = raw::GIT_CREDTYPE_USERNAME as u32; } } bitflags! { /// Flags for the `flags` field of an IndexEntry. - pub flags IndexEntryFlag: u16 { + pub struct IndexEntryFlag: u16 { /// Set when the `extended_flags` field is valid. - const IDXENTRY_EXTENDED = raw::GIT_IDXENTRY_EXTENDED as u16, + const IDXENTRY_EXTENDED = raw::GIT_IDXENTRY_EXTENDED as u16; /// "Assume valid" flag - const IDXENTRY_VALID = raw::GIT_IDXENTRY_VALID as u16, + const IDXENTRY_VALID = raw::GIT_IDXENTRY_VALID as u16; } } bitflags! { /// Flags for the `extended_flags` field of an IndexEntry. - pub flags IndexEntryExtendedFlag: u16 { + pub struct IndexEntryExtendedFlag: u16 { /// An "intent to add" entry from "git add -N" - const IDXENTRY_INTENT_TO_ADD = raw::GIT_IDXENTRY_INTENT_TO_ADD as u16, + const IDXENTRY_INTENT_TO_ADD = raw::GIT_IDXENTRY_INTENT_TO_ADD as u16; /// Skip the associated worktree file, for sparse checkouts - const IDXENTRY_SKIP_WORKTREE = raw::GIT_IDXENTRY_SKIP_WORKTREE as u16, + const IDXENTRY_SKIP_WORKTREE = raw::GIT_IDXENTRY_SKIP_WORKTREE as u16; /// Reserved for a future on-disk extended flag - const IDXENTRY_EXTENDED2 = raw::GIT_IDXENTRY_EXTENDED2 as u16, + const IDXENTRY_EXTENDED2 = raw::GIT_IDXENTRY_EXTENDED2 as u16; #[allow(missing_docs)] - const IDXENTRY_UPDATE = raw::GIT_IDXENTRY_UPDATE as u16, + const IDXENTRY_UPDATE = raw::GIT_IDXENTRY_UPDATE as u16; #[allow(missing_docs)] - const IDXENTRY_REMOVE = raw::GIT_IDXENTRY_REMOVE as u16, + const IDXENTRY_REMOVE = raw::GIT_IDXENTRY_REMOVE as u16; #[allow(missing_docs)] - const IDXENTRY_UPTODATE = raw::GIT_IDXENTRY_UPTODATE as u16, + const IDXENTRY_UPTODATE = raw::GIT_IDXENTRY_UPTODATE as u16; #[allow(missing_docs)] - const IDXENTRY_ADDED = raw::GIT_IDXENTRY_ADDED as u16, + const IDXENTRY_ADDED = raw::GIT_IDXENTRY_ADDED as u16; #[allow(missing_docs)] - const IDXENTRY_HASHED = raw::GIT_IDXENTRY_HASHED as u16, + const IDXENTRY_HASHED = raw::GIT_IDXENTRY_HASHED as u16; #[allow(missing_docs)] - const IDXENTRY_UNHASHED = raw::GIT_IDXENTRY_UNHASHED as u16, + const IDXENTRY_UNHASHED = raw::GIT_IDXENTRY_UNHASHED as u16; #[allow(missing_docs)] - const IDXENTRY_WT_REMOVE = raw::GIT_IDXENTRY_WT_REMOVE as u16, + const IDXENTRY_WT_REMOVE = raw::GIT_IDXENTRY_WT_REMOVE as u16; #[allow(missing_docs)] - const IDXENTRY_CONFLICTED = raw::GIT_IDXENTRY_CONFLICTED as u16, + const IDXENTRY_CONFLICTED = raw::GIT_IDXENTRY_CONFLICTED as u16; #[allow(missing_docs)] - const IDXENTRY_UNPACKED = raw::GIT_IDXENTRY_UNPACKED as u16, + const IDXENTRY_UNPACKED = raw::GIT_IDXENTRY_UNPACKED as u16; #[allow(missing_docs)] - const IDXENTRY_NEW_SKIP_WORKTREE = raw::GIT_IDXENTRY_NEW_SKIP_WORKTREE as u16, + const IDXENTRY_NEW_SKIP_WORKTREE = raw::GIT_IDXENTRY_NEW_SKIP_WORKTREE as u16; } } bitflags! { /// Flags for APIs that add files matching pathspec - pub flags IndexAddOption: u32 { + pub struct IndexAddOption: u32 { #[allow(missing_docs)] - const ADD_DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32, + const ADD_DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32; #[allow(missing_docs)] - const ADD_FORCE = raw::GIT_INDEX_ADD_FORCE as u32, + const ADD_FORCE = raw::GIT_INDEX_ADD_FORCE as u32; #[allow(missing_docs)] const ADD_DISABLE_PATHSPEC_MATCH = - raw::GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH as u32, + raw::GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH as u32; #[allow(missing_docs)] - const ADD_CHECK_PATHSPEC = raw::GIT_INDEX_ADD_CHECK_PATHSPEC as u32, + const ADD_CHECK_PATHSPEC = raw::GIT_INDEX_ADD_CHECK_PATHSPEC as u32; } } bitflags! { /// Flags for `Repository::open_ext` - pub flags RepositoryOpenFlags: u32 { + pub struct 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, + 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, + 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, + const REPOSITORY_OPEN_BARE = raw::GIT_REPOSITORY_OPEN_BARE as u32; /// Don't try appending `/.git` to the specified repository path. - const REPOSITORY_OPEN_NO_DOTGIT = raw::GIT_REPOSITORY_OPEN_NO_DOTGIT as u32, + const REPOSITORY_OPEN_NO_DOTGIT = raw::GIT_REPOSITORY_OPEN_NO_DOTGIT as u32; /// Respect environment variables like `$GIT_DIR`. - const REPOSITORY_OPEN_FROM_ENV = raw::GIT_REPOSITORY_OPEN_FROM_ENV as u32, + const REPOSITORY_OPEN_FROM_ENV = raw::GIT_REPOSITORY_OPEN_FROM_ENV as u32; } } bitflags! { /// Flags for the return value of `Repository::revparse` - pub flags RevparseMode: u32 { + pub struct RevparseMode: u32 { /// The spec targeted a single object - const REVPARSE_SINGLE = raw::GIT_REVPARSE_SINGLE as u32, + const REVPARSE_SINGLE = raw::GIT_REVPARSE_SINGLE as u32; /// The spec targeted a range of commits - const REVPARSE_RANGE = raw::GIT_REVPARSE_RANGE as u32, + const REVPARSE_RANGE = raw::GIT_REVPARSE_RANGE as u32; /// The spec used the `...` operator, which invokes special semantics. - const REVPARSE_MERGE_BASE = raw::GIT_REVPARSE_MERGE_BASE as u32, + const REVPARSE_MERGE_BASE = raw::GIT_REVPARSE_MERGE_BASE as u32; } } @@ -746,52 +746,52 @@ bitflags! { /// represents the status of file in the index relative to the HEAD, and the /// `STATUS_WT_*` set of flags represent the status of the file in the /// working directory relative to the index. - pub flags Status: u32 { + pub struct Status: u32 { #[allow(missing_docs)] - const STATUS_CURRENT = raw::GIT_STATUS_CURRENT as u32, + const STATUS_CURRENT = raw::GIT_STATUS_CURRENT as u32; #[allow(missing_docs)] - const STATUS_INDEX_NEW = raw::GIT_STATUS_INDEX_NEW as u32, + const STATUS_INDEX_NEW = raw::GIT_STATUS_INDEX_NEW as u32; #[allow(missing_docs)] - const STATUS_INDEX_MODIFIED = raw::GIT_STATUS_INDEX_MODIFIED as u32, + const STATUS_INDEX_MODIFIED = raw::GIT_STATUS_INDEX_MODIFIED as u32; #[allow(missing_docs)] - const STATUS_INDEX_DELETED = raw::GIT_STATUS_INDEX_DELETED as u32, + const STATUS_INDEX_DELETED = raw::GIT_STATUS_INDEX_DELETED as u32; #[allow(missing_docs)] - const STATUS_INDEX_RENAMED = raw::GIT_STATUS_INDEX_RENAMED as u32, + const STATUS_INDEX_RENAMED = raw::GIT_STATUS_INDEX_RENAMED as u32; #[allow(missing_docs)] - const STATUS_INDEX_TYPECHANGE = raw::GIT_STATUS_INDEX_TYPECHANGE as u32, + const STATUS_INDEX_TYPECHANGE = raw::GIT_STATUS_INDEX_TYPECHANGE as u32; #[allow(missing_docs)] - const STATUS_WT_NEW = raw::GIT_STATUS_WT_NEW as u32, + const STATUS_WT_NEW = raw::GIT_STATUS_WT_NEW as u32; #[allow(missing_docs)] - const STATUS_WT_MODIFIED = raw::GIT_STATUS_WT_MODIFIED as u32, + const STATUS_WT_MODIFIED = raw::GIT_STATUS_WT_MODIFIED as u32; #[allow(missing_docs)] - const STATUS_WT_DELETED = raw::GIT_STATUS_WT_DELETED as u32, + const STATUS_WT_DELETED = raw::GIT_STATUS_WT_DELETED as u32; #[allow(missing_docs)] - const STATUS_WT_TYPECHANGE = raw::GIT_STATUS_WT_TYPECHANGE as u32, + const STATUS_WT_TYPECHANGE = raw::GIT_STATUS_WT_TYPECHANGE as u32; #[allow(missing_docs)] - const STATUS_WT_RENAMED = raw::GIT_STATUS_WT_RENAMED as u32, + const STATUS_WT_RENAMED = raw::GIT_STATUS_WT_RENAMED as u32; #[allow(missing_docs)] - const STATUS_IGNORED = raw::GIT_STATUS_IGNORED as u32, + const STATUS_IGNORED = raw::GIT_STATUS_IGNORED as u32; #[allow(missing_docs)] - const STATUS_CONFLICTED = raw::GIT_STATUS_CONFLICTED as u32, + const STATUS_CONFLICTED = raw::GIT_STATUS_CONFLICTED as u32; } } bitflags! { /// Mode options for RepositoryInitOptions - pub flags RepositoryInitMode: u32 { + pub struct RepositoryInitMode: u32 { /// Use permissions configured by umask - the default const REPOSITORY_INIT_SHARED_UMASK = - raw::GIT_REPOSITORY_INIT_SHARED_UMASK as u32, + raw::GIT_REPOSITORY_INIT_SHARED_UMASK as u32; /// Use `--shared=group` behavior, chmod'ing the new repo to be /// group writable and \"g+sx\" for sticky group assignment const REPOSITORY_INIT_SHARED_GROUP = - raw::GIT_REPOSITORY_INIT_SHARED_GROUP as u32, + raw::GIT_REPOSITORY_INIT_SHARED_GROUP as u32; /// Use `--shared=all` behavior, adding world readability. const REPOSITORY_INIT_SHARED_ALL = - raw::GIT_REPOSITORY_INIT_SHARED_ALL as u32, + raw::GIT_REPOSITORY_INIT_SHARED_ALL as u32; } } @@ -863,49 +863,49 @@ bitflags! { /// Lastly, the following will only be returned for ignore "NONE". /// /// * WD_UNTRACKED - wd contains untracked files - pub flags SubmoduleStatus: u32 { + pub struct SubmoduleStatus: u32 { #[allow(missing_docs)] const SUBMODULE_STATUS_IN_HEAD = - raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32, + raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_IN_INDEX = - raw::GIT_SUBMODULE_STATUS_IN_INDEX as u32, + raw::GIT_SUBMODULE_STATUS_IN_INDEX as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_IN_CONFIG = - raw::GIT_SUBMODULE_STATUS_IN_CONFIG as u32, + raw::GIT_SUBMODULE_STATUS_IN_CONFIG as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_IN_WD = - raw::GIT_SUBMODULE_STATUS_IN_WD as u32, + raw::GIT_SUBMODULE_STATUS_IN_WD as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_INDEX_ADDED = - raw::GIT_SUBMODULE_STATUS_INDEX_ADDED as u32, + raw::GIT_SUBMODULE_STATUS_INDEX_ADDED as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_INDEX_DELETED = - raw::GIT_SUBMODULE_STATUS_INDEX_DELETED as u32, + raw::GIT_SUBMODULE_STATUS_INDEX_DELETED as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_INDEX_MODIFIED = - raw::GIT_SUBMODULE_STATUS_INDEX_MODIFIED as u32, + raw::GIT_SUBMODULE_STATUS_INDEX_MODIFIED as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_WD_UNINITIALIZED = - raw::GIT_SUBMODULE_STATUS_WD_UNINITIALIZED as u32, + raw::GIT_SUBMODULE_STATUS_WD_UNINITIALIZED as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_WD_ADDED = - raw::GIT_SUBMODULE_STATUS_WD_ADDED as u32, + raw::GIT_SUBMODULE_STATUS_WD_ADDED as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_WD_DELETED = - raw::GIT_SUBMODULE_STATUS_WD_DELETED as u32, + raw::GIT_SUBMODULE_STATUS_WD_DELETED as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_WD_MODIFIED = - raw::GIT_SUBMODULE_STATUS_WD_MODIFIED as u32, + raw::GIT_SUBMODULE_STATUS_WD_MODIFIED as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_WD_INDEX_MODIFIED = - raw::GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED as u32, + raw::GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_WD_WD_MODIFIED = - raw::GIT_SUBMODULE_STATUS_WD_WD_MODIFIED as u32, + raw::GIT_SUBMODULE_STATUS_WD_WD_MODIFIED as u32; #[allow(missing_docs)] const SUBMODULE_STATUS_WD_UNTRACKED = - raw::GIT_SUBMODULE_STATUS_WD_UNTRACKED as u32, + raw::GIT_SUBMODULE_STATUS_WD_UNTRACKED as u32; } } @@ -930,46 +930,46 @@ pub enum SubmoduleIgnore { bitflags! { /// ... - pub flags PathspecFlags: u32 { + pub struct PathspecFlags: u32 { /// Use the default pathspec matching configuration. - const PATHSPEC_DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32, + const PATHSPEC_DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32; /// Force matching to ignore case, otherwise matching will use native /// case sensitivity fo the platform filesystem. - const PATHSPEC_IGNORE_CASE = raw::GIT_PATHSPEC_IGNORE_CASE as u32, + const PATHSPEC_IGNORE_CASE = raw::GIT_PATHSPEC_IGNORE_CASE as u32; /// Force case sensitive matches, otherwise match will use the native /// case sensitivity of the platform filesystem. - const PATHSPEC_USE_CASE = raw::GIT_PATHSPEC_USE_CASE as u32, + const PATHSPEC_USE_CASE = raw::GIT_PATHSPEC_USE_CASE as u32; /// Disable glob patterns and just use simple string comparison for /// matching. - const PATHSPEC_NO_GLOB = raw::GIT_PATHSPEC_NO_GLOB as u32, + const PATHSPEC_NO_GLOB = raw::GIT_PATHSPEC_NO_GLOB as u32; /// Means that match functions return the error code `NotFound` if no /// matches are found. By default no matches is a success. - const PATHSPEC_NO_MATCH_ERROR = raw::GIT_PATHSPEC_NO_MATCH_ERROR as u32, + const PATHSPEC_NO_MATCH_ERROR = raw::GIT_PATHSPEC_NO_MATCH_ERROR as u32; /// Means that the list returned should track which patterns matched /// which files so that at the end of the match we can identify patterns /// that did not match any files. - const PATHSPEC_FIND_FAILURES = raw::GIT_PATHSPEC_FIND_FAILURES as u32, + const PATHSPEC_FIND_FAILURES = raw::GIT_PATHSPEC_FIND_FAILURES as u32; /// Means that the list returned does not need to keep the actual /// matching filenames. Use this to just test if there were any matches /// at all or in combination with `PATHSPEC_FAILURES` to validate a /// pathspec. - const PATHSPEC_FAILURES_ONLY = raw::GIT_PATHSPEC_FAILURES_ONLY as u32, + const PATHSPEC_FAILURES_ONLY = raw::GIT_PATHSPEC_FAILURES_ONLY as u32; } } bitflags! { /// Types of notifications emitted from checkouts. - pub flags CheckoutNotificationType: u32 { + pub struct CheckoutNotificationType: u32 { /// Notification about a conflict. - const CHECKOUT_NOTIFICATION_CONFLICT = raw::GIT_CHECKOUT_NOTIFY_CONFLICT as u32, + const CHECKOUT_NOTIFICATION_CONFLICT = raw::GIT_CHECKOUT_NOTIFY_CONFLICT as u32; /// Notification about a dirty file. - const CHECKOUT_NOTIFICATION_DIRTY = raw::GIT_CHECKOUT_NOTIFY_DIRTY as u32, + const CHECKOUT_NOTIFICATION_DIRTY = raw::GIT_CHECKOUT_NOTIFY_DIRTY as u32; /// Notification about an updated file. - const CHECKOUT_NOTIFICATION_UPDATED = raw::GIT_CHECKOUT_NOTIFY_UPDATED as u32, + const CHECKOUT_NOTIFICATION_UPDATED = raw::GIT_CHECKOUT_NOTIFY_UPDATED as u32; /// Notification about an untracked file. - const CHECKOUT_NOTIFICATION_UNTRACKED = raw::GIT_CHECKOUT_NOTIFY_UNTRACKED as u32, + const CHECKOUT_NOTIFICATION_UNTRACKED = raw::GIT_CHECKOUT_NOTIFY_UNTRACKED as u32; /// Notification about an ignored file. - const CHECKOUT_NOTIFICATION_IGNORED = raw::GIT_CHECKOUT_NOTIFY_IGNORED as u32, + const CHECKOUT_NOTIFICATION_IGNORED = raw::GIT_CHECKOUT_NOTIFY_IGNORED as u32; } } @@ -990,19 +990,19 @@ pub enum DiffFormat { bitflags! { /// Formatting options for diff stats - pub flags DiffStatsFormat: raw::git_diff_stats_format_t { + pub struct DiffStatsFormat: raw::git_diff_stats_format_t { /// Don't generate any stats - const DIFF_STATS_NONE = raw::GIT_DIFF_STATS_NONE, + const DIFF_STATS_NONE = raw::GIT_DIFF_STATS_NONE; /// Equivalent of `--stat` in git - const DIFF_STATS_FULL = raw::GIT_DIFF_STATS_FULL, + const DIFF_STATS_FULL = raw::GIT_DIFF_STATS_FULL; /// Equivalent of `--shortstat` in git - const DIFF_STATS_SHORT = raw::GIT_DIFF_STATS_SHORT, + const DIFF_STATS_SHORT = raw::GIT_DIFF_STATS_SHORT; /// Equivalent of `--numstat` in git - const DIFF_STATS_NUMBER = raw::GIT_DIFF_STATS_NUMBER, + const DIFF_STATS_NUMBER = raw::GIT_DIFF_STATS_NUMBER; /// Extended header information such as creations, renames and mode /// changes, equivalent of `--summary` in git const DIFF_STATS_INCLUDE_SUMMARY = - raw::GIT_DIFF_STATS_INCLUDE_SUMMARY, + raw::GIT_DIFF_STATS_INCLUDE_SUMMARY; } } @@ -1051,29 +1051,29 @@ pub enum StashApplyProgress { bitflags! { #[allow(missing_docs)] - pub flags StashApplyFlags: u32 { + pub struct StashApplyFlags: u32 { #[allow(missing_docs)] - const STASH_APPLY_DEFAULT = raw::GIT_STASH_APPLY_DEFAULT as u32, + const STASH_APPLY_DEFAULT = raw::GIT_STASH_APPLY_DEFAULT as u32; /// Try to reinstate not only the working tree's changes, /// but also the index's changes. - const STASH_APPLY_REINSTATE_INDEX = raw::GIT_STASH_APPLY_REINSTATE_INDEX as u32, + const STASH_APPLY_REINSTATE_INDEX = raw::GIT_STASH_APPLY_REINSTATE_INDEX as u32; } } bitflags! { #[allow(missing_docs)] - pub flags StashFlags: u32 { + pub struct StashFlags: u32 { #[allow(missing_docs)] - const STASH_DEFAULT = raw::GIT_STASH_DEFAULT as u32, + const STASH_DEFAULT = raw::GIT_STASH_DEFAULT as u32; /// All changes already added to the index are left intact in /// the working directory - const STASH_KEEP_INDEX = raw::GIT_STASH_KEEP_INDEX as u32, + const STASH_KEEP_INDEX = raw::GIT_STASH_KEEP_INDEX as u32; /// All untracked files are also stashed and then cleaned up /// from the working directory - const STASH_INCLUDE_UNTRACKED = raw::GIT_STASH_INCLUDE_UNTRACKED as u32, + const STASH_INCLUDE_UNTRACKED = raw::GIT_STASH_INCLUDE_UNTRACKED as u32; /// All ignored files are also stashed and then cleaned up from /// the working directory - const STASH_INCLUDE_IGNORED = raw::GIT_STASH_INCLUDE_IGNORED as u32, + const STASH_INCLUDE_IGNORED = raw::GIT_STASH_INCLUDE_IGNORED as u32; } } From fad10d2781e31cd659dd9a06f8417ba1ca0e26b9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 May 2017 11:33:15 -0700 Subject: [PATCH 104/860] Add basic doc example for `Remote::fetch`. --- src/remote.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/remote.rs b/src/remote.rs index c5fa08b39f..1f1dc9fa27 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -192,6 +192,19 @@ impl<'repo> Remote<'repo> { /// /// Convenience function to connect to a remote, download the data, /// disconnect and update the remote-tracking branches. + /// + /// # Examples + /// + /// Example of functionality similar to `git fetch origin/master`: + /// + /// ```no_run + /// fn fetch_origin_master(repo: git2::Repository) -> Result<(), git2::Error> { + /// repo.find_remote("origin")?.fetch(&["master"], None, None) + /// } + /// + /// let repo = git2::Repository::discover("rust").unwrap(); + /// fetch_origin_master(repo).unwrap(); + /// ``` pub fn fetch(&mut self, refspecs: &[&str], opts: Option<&mut FetchOptions>, From 24d233cb77d57f4c62e772c2e950f9f0b47c2ba6 Mon Sep 17 00:00:00 2001 From: Ryan Coffman Date: Tue, 23 May 2017 15:02:22 -0700 Subject: [PATCH 105/860] Added fetch_respecs and push_refspecs bindings to remote --- libgit2-sys/lib.rs | 2 ++ src/remote.rs | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 30f12eeb99..72f65c23dd 100755 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1519,6 +1519,8 @@ extern { source: *mut git_remote) -> c_int; pub fn git_remote_get_fetch_refspecs(array: *mut git_strarray, remote: *const git_remote) -> c_int; + pub fn git_remote_get_push_refspecs(array: *mut git_strarray, + remote: *const git_remote) -> c_int; pub fn git_remote_get_refspec(remote: *const git_remote, n: size_t) -> *const git_refspec; pub fn git_remote_is_valid_name(remote_name: *const c_char) -> c_int; diff --git a/src/remote.rs b/src/remote.rs index 1f1dc9fa27..c3aeb0f585 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -8,6 +8,7 @@ use libc; use {raw, Direction, Error, Refspec, Oid, FetchPrune, ProxyOptions}; use {RemoteCallbacks, Progress, Repository, AutotagOption}; +use string_array::StringArray; use util::Binding; /// A structure representing a [remote][1] of a git repository. @@ -280,6 +281,24 @@ impl<'repo> Remote<'repo> { &[RemoteHead]>(slice)) } } + + /// Get the remote's list of fetch refspecs + pub fn fetch_refspecs(&self) -> Result { + unsafe { + let mut raw: raw::git_strarray = mem::zeroed(); + try_call!(raw::git_remote_get_fetch_refspecs(&mut raw, self.raw)); + Ok(StringArray::from_raw(raw)) + } + } + + /// Get the remote's list of push refspecs + pub fn push_refspecs(&self) -> Result { + unsafe { + let mut raw: raw::git_strarray = mem::zeroed(); + try_call!(raw::git_remote_get_push_refspecs(&mut raw, self.raw)); + Ok(StringArray::from_raw(raw)) + } + } } impl<'repo> Clone for Remote<'repo> { From 899c988f8228f4d8a4123295834cfe66e4101362 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 26 May 2017 07:41:16 -0700 Subject: [PATCH 106/860] Update libgit2 Picks up a fix for rust-lang/cargo#4091 --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index ee89941fa2..a1023a4302 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit ee89941fa2b861332defb5e3a8ce12c23c496ed7 +Subproject commit a1023a43027207ac7a5df7233bddfe7347bee256 From 4f4786b0464602628d9a194c67c25cdcdc06107f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 26 May 2017 07:43:15 -0700 Subject: [PATCH 107/860] Bump to 0.6.11 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index b474e5a425..ce516a655b 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.10" +version = "0.6.11" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 5b765d18b783ebb037f6a76d71cbd2e9116c31e4 Mon Sep 17 00:00:00 2001 From: Ryan Coffman Date: Sat, 27 May 2017 10:41:38 -0700 Subject: [PATCH 108/860] Added merge analysis bindings --- libgit2-sys/lib.rs | 26 +++++++++++++++ src/lib.rs | 2 +- src/merge.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++++ src/repo.rs | 23 +++++++++++++- 4 files changed, 128 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 72f65c23dd..7de9980405 100755 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1196,6 +1196,24 @@ git_enum! { } } +git_enum! { + pub enum git_merge_analysis_t { + GIT_MERGE_ANALYSIS_NONE = 0, + GIT_MERGE_ANALYSIS_NORMAL = (1 << 0), + GIT_MERGE_ANALYSIS_UP_TO_DATE = (1 << 1), + GIT_MERGE_ANALYSIS_FASTFORWARD = (1 << 2), + GIT_MERGE_ANALYSIS_UNBORN = (1 << 3), + } +} + +git_enum! { + pub enum git_merge_preference_t { + GIT_MERGE_PREFERENCE_NONE = 0, + GIT_MERGE_PREFERENCE_NO_FASTFORWARD = (1 << 0), + GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY = (1 << 1), + } +} + pub type git_transport_cb = extern fn(out: *mut *mut git_transport, owner: *mut git_remote, param: *mut c_void) -> c_int; @@ -2215,6 +2233,14 @@ extern { opts: *const git_merge_options) -> c_int; pub fn git_repository_state_cleanup(repo: *mut git_repository) -> c_int; + // merge analysis + + pub fn git_merge_analysis(analysis_out: *mut git_merge_analysis_t, + pref_out: *mut git_merge_preference_t, + repo: *mut git_repository, + their_heads: *mut *const git_annotated_commit, + their_heads_len: usize) -> c_int; + // notes pub fn git_note_author(note: *const git_note) -> *const git_signature; pub fn git_note_committer(note: *const git_note) -> *const git_signature; diff --git a/src/lib.rs b/src/lib.rs index e790c55aed..f3a57e6ad4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,7 @@ pub use diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind}; 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 merge::{AnnotatedCommit, MergeOptions, MergeAnalysis, MergePreference}; pub use message::{message_prettify, DEFAULT_COMMENT_CHAR}; pub use note::{Note, Notes}; pub use object::Object; diff --git a/src/merge.rs b/src/merge.rs index 045e9faf86..649ce4ebb3 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -21,6 +21,39 @@ pub struct MergeOptions { raw: raw::git_merge_options, } +/// The results of `merge_analysis` indicating the merge opportunities. +pub enum MergeAnalysis { + /// No merge is possible. + None, + /// A "normal" merge; both HEAD and the given merge input have diverged + /// from their common ancestor. The divergent commits must be merged. + Normal, + /// All given merge inputs are reachable from HEAD, meaning the + /// repository is up-to-date and no merge needs to be performed. + UpToDate, + /// The given merge input is a fast-forward from HEAD and no merge + /// needs to be performed. Instead, the client can check out the + /// given merge input. + Fastforward, + /// The HEAD of the current repository is "unborn" and does not point to + /// a valid commit. No merge can be performed, but the caller may wish + /// to simply set HEAD to the target commit(s). + Unborn +} + +/// The user's stated preference for merges. +pub enum MergePreference { + /// No configuration was found that suggests a preferred behavior for + /// merge. + None, + /// There is a `merge.ff=false` configuration setting, suggesting that + /// the user does not want to allow a fast-forward merge. + NoFastforward, + /// There is a `merge.ff=only` configuration setting, suggesting that + /// the user only wants fast-forward merges. + FastforwardOnly, +} + impl<'repo> AnnotatedCommit<'repo> { /// Gets the commit ID that the given git_annotated_commit refers to pub fn id(&self) -> Oid { @@ -152,3 +185,49 @@ impl<'repo> Drop for AnnotatedCommit<'repo> { unsafe { raw::git_annotated_commit_free(self.raw) } } } + +impl Binding for MergeAnalysis { + type Raw = raw::git_merge_analysis_t; + + unsafe fn from_raw(raw: raw::git_merge_analysis_t) -> MergeAnalysis { + match raw { + raw::GIT_MERGE_ANALYSIS_NONE => MergeAnalysis::None, + raw::GIT_MERGE_ANALYSIS_NORMAL => MergeAnalysis::Normal, + raw::GIT_MERGE_ANALYSIS_UP_TO_DATE => MergeAnalysis::UpToDate, + raw::GIT_MERGE_ANALYSIS_FASTFORWARD => MergeAnalysis::Fastforward, + raw::GIT_MERGE_ANALYSIS_UNBORN => MergeAnalysis::Unborn, + _ => panic!("Unknown merge analysis type: {}", raw), + } + } + + fn raw(&self) -> raw::git_merge_analysis_t { + match *self { + MergeAnalysis::None => raw::GIT_MERGE_ANALYSIS_NONE, + MergeAnalysis::Normal => raw::GIT_MERGE_ANALYSIS_NORMAL, + MergeAnalysis::UpToDate => raw::GIT_MERGE_ANALYSIS_UP_TO_DATE, + MergeAnalysis::Fastforward => raw::GIT_MERGE_ANALYSIS_FASTFORWARD, + MergeAnalysis::Unborn => raw::GIT_MERGE_ANALYSIS_UNBORN + } + } +} + +impl Binding for MergePreference { + type Raw = raw::git_merge_preference_t; + + unsafe fn from_raw(raw: raw::git_merge_preference_t) -> MergePreference { + match raw { + raw::GIT_MERGE_PREFERENCE_NONE => MergePreference::None, + raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD => MergePreference::NoFastforward, + raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY => MergePreference::FastforwardOnly, + _ => panic!("Unknown merge preference type: {}", raw), + } + } + + fn raw(&self) -> raw::git_merge_preference_t { + match *self { + MergePreference::None => raw::GIT_MERGE_PREFERENCE_NONE, + MergePreference::NoFastforward => raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD, + MergePreference::FastforwardOnly => raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY + } + } +} diff --git a/src/repo.rs b/src/repo.rs index b6b1c4b2e4..bd4e7178f4 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -9,7 +9,7 @@ use libc::{c_int, c_char, size_t, c_void, c_uint}; use {raw, Revspec, Error, init, Object, RepositoryOpenFlags, RepositoryState, Remote, Buf, StashFlags}; use {ResetType, Signature, Reference, References, Submodule, Blame, BlameOptions}; use {Branches, BranchType, Index, Config, Oid, Blob, Branch, Commit, Tree}; -use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus}; +use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus, MergeAnalysis, MergePreference}; use {ObjectType, Tag, Note, Notes, StatusOptions, Statuses, Status, Revwalk}; use {RevparseMode, RepositoryInitMode, Reflog, IntoCString, Describe}; use {DescribeOptions, TreeBuilder, Diff, DiffOptions, PackBuilder}; @@ -1323,6 +1323,27 @@ impl Repository { Ok(()) } + /// Analyzes the given branch(es) and determines the opportunities for + /// merging them into the HEAD of the repository. + pub fn merge_analysis(&self, + their_heads: &[&AnnotatedCommit]) + -> Result<(MergeAnalysis, MergePreference), Error> { + unsafe { + let mut raw_merge_analysis = 0 as raw::git_merge_analysis_t; + let mut raw_merge_preference = 0 as raw::git_merge_preference_t; + let mut their_heads = their_heads + .iter() + .map(|v| v.raw() as *const _) + .collect::>(); + try_call!(raw::git_merge_analysis(&mut raw_merge_analysis, + &mut raw_merge_preference, + self.raw, + their_heads.as_mut_ptr() as *mut _, + their_heads.len())); + Ok((Binding::from_raw(raw_merge_analysis), Binding::from_raw(raw_merge_preference))) + } + } + /// Add a note for an object /// /// The `notes_ref` argument is the canonical name of the reference to use, From 3d0ad3185b9bfb5b886b9a23972b7db1d604577a Mon Sep 17 00:00:00 2001 From: Ryan Coffman Date: Sat, 27 May 2017 14:36:31 -0700 Subject: [PATCH 109/860] Added lookup_annotated_commit binding --- libgit2-sys/lib.rs | 3 +++ src/repo.rs | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 72f65c23dd..522767293f 100755 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1922,6 +1922,9 @@ extern { pub fn git_commit_header_field(out: *mut git_buf, commit: *const git_commit, field: *const c_char) -> c_int; + pub fn git_annotated_commit_lookup(out: *mut *mut git_annotated_commit, + repo: *mut git_repository, + id: *const git_oid) -> c_int; // branch pub fn git_branch_create(out: *mut *mut git_reference, diff --git a/src/repo.rs b/src/repo.rs index b6b1c4b2e4..c875c18eec 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -856,6 +856,15 @@ impl Repository { } } + /// Creates a `AnnotatedCommit` from the given commit id. + pub fn find_annotated_commit(&self, id: Oid) -> Result { + unsafe { + let mut raw = 0 as *mut raw::git_annotated_commit; + try_call!(raw::git_annotated_commit_lookup(&mut raw, self.raw(), id.raw())); + Ok(Binding::from_raw(raw)) + } + } + /// Lookup a reference to one of the objects in a repository. pub fn find_object(&self, oid: Oid, kind: Option) -> Result { From 4b82c43d57c4671db3591ae152f5c402ddae0fe4 Mon Sep 17 00:00:00 2001 From: Ryan Coffman Date: Sat, 27 May 2017 15:34:12 -0700 Subject: [PATCH 110/860] Implement MergeAnalysis and MergePreference as bitflags --- src/merge.rs | 108 ++++++++++++++++----------------------------------- src/repo.rs | 2 +- 2 files changed, 34 insertions(+), 76 deletions(-) diff --git a/src/merge.rs b/src/merge.rs index 649ce4ebb3..b922d8a6ca 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -21,37 +21,41 @@ pub struct MergeOptions { raw: raw::git_merge_options, } -/// The results of `merge_analysis` indicating the merge opportunities. -pub enum MergeAnalysis { - /// No merge is possible. - None, - /// A "normal" merge; both HEAD and the given merge input have diverged - /// from their common ancestor. The divergent commits must be merged. - Normal, - /// All given merge inputs are reachable from HEAD, meaning the - /// repository is up-to-date and no merge needs to be performed. - UpToDate, - /// The given merge input is a fast-forward from HEAD and no merge - /// needs to be performed. Instead, the client can check out the - /// given merge input. - Fastforward, - /// The HEAD of the current repository is "unborn" and does not point to - /// a valid commit. No merge can be performed, but the caller may wish - /// to simply set HEAD to the target commit(s). - Unborn +bitflags! { + /// The results of `merge_analysis` indicating the merge opportunities. + pub struct MergeAnalysis: u32 { + /// No merge is possible. + const MERGE_ANALYSIS_NONE = raw::GIT_MERGE_ANALYSIS_NONE as u32; + /// A "normal" merge; both HEAD and the given merge input have diverged + /// from their common ancestor. The divergent commits must be merged. + const MERGE_ANALYSIS_NORMAL = raw::GIT_MERGE_ANALYSIS_NORMAL as u32; + /// All given merge inputs are reachable from HEAD, meaning the + /// repository is up-to-date and no merge needs to be performed. + const MERGE_ANALYSIS_UP_TO_DATE = raw::GIT_MERGE_ANALYSIS_UP_TO_DATE as u32; + /// The given merge input is a fast-forward from HEAD and no merge + /// needs to be performed. Instead, the client can check out the + /// given merge input. + const MERGE_ANALYSIS_FASTFORWARD = raw::GIT_MERGE_ANALYSIS_FASTFORWARD as u32; + /// The HEAD of the current repository is "unborn" and does not point to + /// a valid commit. No merge can be performed, but the caller may wish + /// to simply set HEAD to the target commit(s). + const MERGE_ANALYSIS_UNBORN = raw::GIT_MERGE_ANALYSIS_UNBORN as u32; + } } -/// The user's stated preference for merges. -pub enum MergePreference { - /// No configuration was found that suggests a preferred behavior for - /// merge. - None, - /// There is a `merge.ff=false` configuration setting, suggesting that - /// the user does not want to allow a fast-forward merge. - NoFastforward, - /// There is a `merge.ff=only` configuration setting, suggesting that - /// the user only wants fast-forward merges. - FastforwardOnly, +bitflags! { + /// The user's stated preference for merges. + pub struct MergePreference: u32 { + /// No configuration was found that suggests a preferred behavior for + /// merge. + const MERGE_PREFERENCE_NONE = raw::GIT_MERGE_PREFERENCE_NONE; + /// There is a `merge.ff=false` configuration setting, suggesting that + /// the user does not want to allow a fast-forward merge. + const MERGE_PREFERENCE_NO_FAST_FORWARD = raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD; + /// There is a `merge.ff=only` configuration setting, suggesting that + /// the user only wants fast-forward merges. + const MERGE_PREFERENCE_FASTFORWARD_ONLY = raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY; + } } impl<'repo> AnnotatedCommit<'repo> { @@ -185,49 +189,3 @@ impl<'repo> Drop for AnnotatedCommit<'repo> { unsafe { raw::git_annotated_commit_free(self.raw) } } } - -impl Binding for MergeAnalysis { - type Raw = raw::git_merge_analysis_t; - - unsafe fn from_raw(raw: raw::git_merge_analysis_t) -> MergeAnalysis { - match raw { - raw::GIT_MERGE_ANALYSIS_NONE => MergeAnalysis::None, - raw::GIT_MERGE_ANALYSIS_NORMAL => MergeAnalysis::Normal, - raw::GIT_MERGE_ANALYSIS_UP_TO_DATE => MergeAnalysis::UpToDate, - raw::GIT_MERGE_ANALYSIS_FASTFORWARD => MergeAnalysis::Fastforward, - raw::GIT_MERGE_ANALYSIS_UNBORN => MergeAnalysis::Unborn, - _ => panic!("Unknown merge analysis type: {}", raw), - } - } - - fn raw(&self) -> raw::git_merge_analysis_t { - match *self { - MergeAnalysis::None => raw::GIT_MERGE_ANALYSIS_NONE, - MergeAnalysis::Normal => raw::GIT_MERGE_ANALYSIS_NORMAL, - MergeAnalysis::UpToDate => raw::GIT_MERGE_ANALYSIS_UP_TO_DATE, - MergeAnalysis::Fastforward => raw::GIT_MERGE_ANALYSIS_FASTFORWARD, - MergeAnalysis::Unborn => raw::GIT_MERGE_ANALYSIS_UNBORN - } - } -} - -impl Binding for MergePreference { - type Raw = raw::git_merge_preference_t; - - unsafe fn from_raw(raw: raw::git_merge_preference_t) -> MergePreference { - match raw { - raw::GIT_MERGE_PREFERENCE_NONE => MergePreference::None, - raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD => MergePreference::NoFastforward, - raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY => MergePreference::FastforwardOnly, - _ => panic!("Unknown merge preference type: {}", raw), - } - } - - fn raw(&self) -> raw::git_merge_preference_t { - match *self { - MergePreference::None => raw::GIT_MERGE_PREFERENCE_NONE, - MergePreference::NoFastforward => raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD, - MergePreference::FastforwardOnly => raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY - } - } -} diff --git a/src/repo.rs b/src/repo.rs index bd4e7178f4..7d02e96502 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1340,7 +1340,7 @@ impl Repository { self.raw, their_heads.as_mut_ptr() as *mut _, their_heads.len())); - Ok((Binding::from_raw(raw_merge_analysis), Binding::from_raw(raw_merge_preference))) + Ok((MergeAnalysis::from_bits_truncate(raw_merge_analysis), MergePreference::from_bits_truncate(raw_merge_preference))) } } From 6b3756defc945a23eec71bb94529135a8c340c89 Mon Sep 17 00:00:00 2001 From: Ryan Coffman Date: Sat, 27 May 2017 15:42:41 -0700 Subject: [PATCH 111/860] Moved MergeAnalysis and MergePreference to top-level module so bitflags are accessible --- src/lib.rs | 39 ++++++++++++++++++++++++++++++++++++++- src/merge.rs | 37 ------------------------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f3a57e6ad4..25e66296f9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,7 @@ pub use diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind}; pub use diff::{DiffLine, DiffHunk, DiffStats, DiffFindOptions}; pub use error::Error; pub use index::{Index, IndexEntry, IndexEntries, IndexMatchedPath}; -pub use merge::{AnnotatedCommit, MergeOptions, MergeAnalysis, MergePreference}; +pub use merge::{AnnotatedCommit, MergeOptions}; pub use message::{message_prettify, DEFAULT_COMMENT_CHAR}; pub use note::{Note, Notes}; pub use object::Object; @@ -481,6 +481,43 @@ bitflags! { } } +bitflags! { + /// The results of `merge_analysis` indicating the merge opportunities. + pub struct MergeAnalysis: u32 { + /// No merge is possible. + const MERGE_ANALYSIS_NONE = raw::GIT_MERGE_ANALYSIS_NONE as u32; + /// A "normal" merge; both HEAD and the given merge input have diverged + /// from their common ancestor. The divergent commits must be merged. + const MERGE_ANALYSIS_NORMAL = raw::GIT_MERGE_ANALYSIS_NORMAL as u32; + /// All given merge inputs are reachable from HEAD, meaning the + /// repository is up-to-date and no merge needs to be performed. + const MERGE_ANALYSIS_UP_TO_DATE = raw::GIT_MERGE_ANALYSIS_UP_TO_DATE as u32; + /// The given merge input is a fast-forward from HEAD and no merge + /// needs to be performed. Instead, the client can check out the + /// given merge input. + const MERGE_ANALYSIS_FASTFORWARD = raw::GIT_MERGE_ANALYSIS_FASTFORWARD as u32; + /// The HEAD of the current repository is "unborn" and does not point to + /// a valid commit. No merge can be performed, but the caller may wish + /// to simply set HEAD to the target commit(s). + const MERGE_ANALYSIS_UNBORN = raw::GIT_MERGE_ANALYSIS_UNBORN as u32; + } +} + +bitflags! { + /// The user's stated preference for merges. + pub struct MergePreference: u32 { + /// No configuration was found that suggests a preferred behavior for + /// merge. + const MERGE_PREFERENCE_NONE = raw::GIT_MERGE_PREFERENCE_NONE; + /// There is a `merge.ff=false` configuration setting, suggesting that + /// the user does not want to allow a fast-forward merge. + const MERGE_PREFERENCE_NO_FAST_FORWARD = raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD; + /// There is a `merge.ff=only` configuration setting, suggesting that + /// the user only wants fast-forward merges. + const MERGE_PREFERENCE_FASTFORWARD_ONLY = raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY; + } +} + #[cfg(test)] #[macro_use] mod test; #[macro_use] mod panic; mod call; diff --git a/src/merge.rs b/src/merge.rs index b922d8a6ca..045e9faf86 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -21,43 +21,6 @@ pub struct MergeOptions { raw: raw::git_merge_options, } -bitflags! { - /// The results of `merge_analysis` indicating the merge opportunities. - pub struct MergeAnalysis: u32 { - /// No merge is possible. - const MERGE_ANALYSIS_NONE = raw::GIT_MERGE_ANALYSIS_NONE as u32; - /// A "normal" merge; both HEAD and the given merge input have diverged - /// from their common ancestor. The divergent commits must be merged. - const MERGE_ANALYSIS_NORMAL = raw::GIT_MERGE_ANALYSIS_NORMAL as u32; - /// All given merge inputs are reachable from HEAD, meaning the - /// repository is up-to-date and no merge needs to be performed. - const MERGE_ANALYSIS_UP_TO_DATE = raw::GIT_MERGE_ANALYSIS_UP_TO_DATE as u32; - /// The given merge input is a fast-forward from HEAD and no merge - /// needs to be performed. Instead, the client can check out the - /// given merge input. - const MERGE_ANALYSIS_FASTFORWARD = raw::GIT_MERGE_ANALYSIS_FASTFORWARD as u32; - /// The HEAD of the current repository is "unborn" and does not point to - /// a valid commit. No merge can be performed, but the caller may wish - /// to simply set HEAD to the target commit(s). - const MERGE_ANALYSIS_UNBORN = raw::GIT_MERGE_ANALYSIS_UNBORN as u32; - } -} - -bitflags! { - /// The user's stated preference for merges. - pub struct MergePreference: u32 { - /// No configuration was found that suggests a preferred behavior for - /// merge. - const MERGE_PREFERENCE_NONE = raw::GIT_MERGE_PREFERENCE_NONE; - /// There is a `merge.ff=false` configuration setting, suggesting that - /// the user does not want to allow a fast-forward merge. - const MERGE_PREFERENCE_NO_FAST_FORWARD = raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD; - /// There is a `merge.ff=only` configuration setting, suggesting that - /// the user only wants fast-forward merges. - const MERGE_PREFERENCE_FASTFORWARD_ONLY = raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY; - } -} - impl<'repo> AnnotatedCommit<'repo> { /// Gets the commit ID that the given git_annotated_commit refers to pub fn id(&self) -> Oid { From a695c4b0ced9be5d21c3a4cd0068efe008ef090b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 27 May 2017 15:44:16 -0700 Subject: [PATCH 112/860] Update submodules manually --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1ace5bdf6d..c62fb4d7f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,12 @@ rust: - beta - nightly sudo: false +git: + submodules: false before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: + - git submodule update --init - cargo test --no-default-features - cargo test - cargo run --manifest-path systest/Cargo.toml --release From 51c93566d2ff78957e73b5752da705082f4a308a Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 10:56:43 -0700 Subject: [PATCH 113/860] clippy: zero_ptr --- src/branch.rs | 10 ++-- src/buf.rs | 4 +- src/build.rs | 5 +- src/call.rs | 6 +- src/commit.rs | 5 +- src/config.rs | 21 +++---- src/cred.rs | 13 +++-- src/describe.rs | 3 +- src/diff.rs | 7 ++- src/index.rs | 11 ++-- src/object.rs | 6 +- src/patch.rs | 13 +++-- src/pathspec.rs | 11 ++-- src/proxy_options.rs | 5 +- src/reference.rs | 14 ++--- src/remote.rs | 17 +++--- src/remote_callbacks.rs | 3 +- src/repo.rs | 119 ++++++++++++++++++++-------------------- src/signature.rs | 7 ++- src/submodule.rs | 3 +- src/tag.rs | 5 +- src/test.rs | 3 +- src/transport.rs | 3 +- src/tree.rs | 7 ++- src/treebuilder.rs | 3 +- 25 files changed, 163 insertions(+), 141 deletions(-) diff --git a/src/branch.rs b/src/branch.rs index 34ba296263..75edd2b30a 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -1,7 +1,7 @@ use std::ffi::CString; use std::marker; +use std::ptr; use std::str; -use libc; use {raw, Error, Reference, BranchType, References}; use util::Binding; @@ -46,7 +46,7 @@ impl<'repo> Branch<'repo> { /// Move/rename an existing local branch reference. pub fn rename(&mut self, new_branch_name: &str, force: bool) -> Result, Error> { - let mut ret = 0 as *mut raw::git_reference; + let mut ret = ptr::null_mut(); let new_branch_name = try!(CString::new(new_branch_name)); unsafe { try_call!(raw::git_branch_move(&mut ret, self.get().raw(), @@ -64,7 +64,7 @@ impl<'repo> Branch<'repo> { /// Return the name of the given local or remote branch. pub fn name_bytes(&self) -> Result<&[u8], Error> { - let mut ret = 0 as *const libc::c_char; + let mut ret = ptr::null(); unsafe { try_call!(raw::git_branch_name(&mut ret, &*self.get().raw())); Ok(::opt_bytes(self, ret).unwrap()) @@ -74,7 +74,7 @@ impl<'repo> Branch<'repo> { /// Return the reference supporting the remote tracking branch, given a /// local branch reference. pub fn upstream<'a>(&'a self) -> Result, Error> { - let mut ret = 0 as *mut raw::git_reference; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_branch_upstream(&mut ret, &*self.get().raw())); Ok(Branch::wrap(Binding::from_raw(ret))) @@ -113,7 +113,7 @@ impl<'repo> Branches<'repo> { impl<'repo> Iterator for Branches<'repo> { type Item = Result<(Branch<'repo>, BranchType), Error>; fn next(&mut self) -> Option, BranchType), Error>> { - let mut ret = 0 as *mut raw::git_reference; + let mut ret = ptr::null_mut(); let mut typ = raw::GIT_BRANCH_LOCAL; unsafe { try_call_iter!(raw::git_branch_next(&mut ret, &mut typ, self.raw)); diff --git a/src/buf.rs b/src/buf.rs index 330f948bc8..384720ac63 100644 --- a/src/buf.rs +++ b/src/buf.rs @@ -1,7 +1,7 @@ use std::slice; use std::str; +use std::ptr; use std::ops::{Deref, DerefMut}; -use libc; use raw; use util::Binding; @@ -20,7 +20,7 @@ impl Buf { ::init(); unsafe { Binding::from_raw(&mut raw::git_buf { - ptr: 0 as *mut libc::c_char, + ptr: ptr::null_mut(), size: 0, asize: 0, } as *mut _) diff --git a/src/build.rs b/src/build.rs index 3ac6bd7b3f..33b9c2c9e3 100644 --- a/src/build.rs +++ b/src/build.rs @@ -3,6 +3,7 @@ use std::ffi::{CStr, CString}; use std::mem; use std::path::Path; +use std::ptr; use libc::{c_char, size_t, c_void, c_uint, c_int}; use {raw, panic, Error, Repository, FetchOptions, IntoCString}; @@ -133,7 +134,7 @@ impl<'cb> RepoBuilder<'cb> { opts.bare = self.bare as c_int; opts.checkout_branch = self.branch.as_ref().map(|s| { s.as_ptr() - }).unwrap_or(0 as *const _); + }).unwrap_or(ptr::null()); opts.local = match (self.local, self.hardlinks) { (true, false) => raw::GIT_CLONE_LOCAL_NO_LINKS, @@ -157,7 +158,7 @@ impl<'cb> RepoBuilder<'cb> { let url = try!(CString::new(url)); let into = try!(into.into_c_string()); - let mut raw = 0 as *mut raw::git_repository; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_clone(&mut raw, url, into, &opts)); Ok(Binding::from_raw(raw)) diff --git a/src/call.rs b/src/call.rs index 1107e69f4d..ba5a1d5656 100644 --- a/src/call.rs +++ b/src/call.rs @@ -52,6 +52,8 @@ pub fn last_error(code: libc::c_int) -> Error { mod impls { use std::ffi::CString; + use std::ptr; + use libc; use {raw, ConfigLevel, ResetType, ObjectType, BranchType, Direction}; @@ -81,13 +83,13 @@ mod impls { impl> Convert<*const T> for Option { fn convert(&self) -> *const T { - self.as_ref().map(|s| s.convert()).unwrap_or(0 as *const _) + self.as_ref().map(|s| s.convert()).unwrap_or(ptr::null()) } } impl> Convert<*mut T> for Option { fn convert(&self) -> *mut T { - self.as_ref().map(|s| s.convert()).unwrap_or(0 as *mut _) + self.as_ref().map(|s| s.convert()).unwrap_or(ptr::null_mut()) } } diff --git a/src/commit.rs b/src/commit.rs index 3aab0b8e19..891c1b0f29 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -1,6 +1,7 @@ use std::marker; use std::mem; use std::ops::Range; +use std::ptr; use std::str; use libc; @@ -42,7 +43,7 @@ impl<'repo> Commit<'repo> { /// Get the tree pointed to by a commit. pub fn tree(&self) -> Result, Error> { - let mut ret = 0 as *mut raw::git_tree; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_commit_tree(&mut ret, &*self.raw)); Ok(Binding::from_raw(ret)) @@ -210,7 +211,7 @@ impl<'repo> Commit<'repo> { /// Use the `parents` iterator to return an iterator over all parents. pub fn parent(&self, i: usize) -> Result, Error> { unsafe { - let mut raw = 0 as *mut raw::git_commit; + let mut raw = ptr::null_mut(); try_call!(raw::git_commit_parent(&mut raw, &*self.raw, i as libc::c_uint)); Ok(Binding::from_raw(raw)) diff --git a/src/config.rs b/src/config.rs index 93a9d356e2..c1102130ac 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,7 @@ use std::ffi::CString; use std::marker; use std::path::{Path, PathBuf}; +use std::ptr; use std::str; use libc; @@ -34,7 +35,7 @@ impl Config { /// anything with it. pub fn new() -> Result { ::init(); - let mut raw = 0 as *mut raw::git_config; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_config_new(&mut raw)); Ok(Binding::from_raw(raw)) @@ -44,7 +45,7 @@ impl Config { /// Create a new config instance containing a single on-disk file pub fn open(path: &Path) -> Result { ::init(); - let mut raw = 0 as *mut raw::git_config; + let mut raw = ptr::null_mut(); let path = try!(path.into_c_string()); unsafe { try_call!(raw::git_config_open_ondisk(&mut raw, path)); @@ -59,7 +60,7 @@ impl Config { /// be used when accessing default config data outside a repository. pub fn open_default() -> Result { ::init(); - let mut raw = 0 as *mut raw::git_config; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_config_open_default(&mut raw)); Ok(Binding::from_raw(raw)) @@ -192,7 +193,7 @@ impl Config { /// /// This method will return an error if this `Config` is not a snapshot. pub fn get_bytes(&self, name: &str) -> Result<&[u8], Error> { - let mut ret = 0 as *const libc::c_char; + let mut ret = ptr::null(); let name = try!(CString::new(name)); unsafe { try_call!(raw::git_config_get_string(&mut ret, &*self.raw, name)); @@ -226,7 +227,7 @@ impl Config { /// Get the ConfigEntry for a config variable. pub fn get_entry(&self, name: &str) -> Result { - let mut ret = 0 as *mut raw::git_config_entry; + let mut ret = ptr::null_mut(); let name = try!(CString::new(name)); unsafe { try_call!(raw::git_config_get_entry(&mut ret, self.raw, name)); @@ -253,7 +254,7 @@ impl Config { /// } /// ``` pub fn entries(&self, glob: Option<&str>) -> Result { - let mut ret = 0 as *mut raw::git_config_iterator; + let mut ret = ptr::null_mut(); unsafe { match glob { Some(s) => { @@ -277,7 +278,7 @@ impl Config { /// shouldn't be used unless the use has created it explicitly. With this /// function you'll open the correct one to write to. pub fn open_global(&mut self) -> Result { - let mut raw = 0 as *mut raw::git_config; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_config_open_global(&mut raw, self.raw)); Ok(Binding::from_raw(raw)) @@ -289,7 +290,7 @@ impl Config { /// The returned config object can be used to perform get/set/delete /// operations on a single specific level. pub fn open_level(&self, level: ConfigLevel) -> Result { - let mut raw = 0 as *mut raw::git_config; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_config_open_level(&mut raw, &*self.raw, level)); Ok(Binding::from_raw(raw)) @@ -355,7 +356,7 @@ impl Config { /// you to look into a consistent view of the configuration for looking up /// complex values (e.g. a remote, submodule). pub fn snapshot(&mut self) -> Result { - let mut ret = 0 as *mut raw::git_config; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_config_snapshot(&mut ret, self.raw)); Ok(Binding::from_raw(ret)) @@ -476,7 +477,7 @@ impl<'cfg> Binding for ConfigEntries<'cfg> { impl<'cfg, 'b> Iterator for &'b ConfigEntries<'cfg> { type Item = Result, Error>; fn next(&mut self) -> Option, Error>> { - let mut raw = 0 as *mut raw::git_config_entry; + let mut raw = ptr::null_mut(); unsafe { try_call_iter!(raw::git_config_next(&mut raw, self.raw)); Some(Ok(ConfigEntry { diff --git a/src/cred.rs b/src/cred.rs index c7f2f3938e..32833c6e37 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -3,6 +3,7 @@ use std::io::Write; use std::mem; use std::path::Path; use std::process::{Command, Stdio}; +use std::ptr; use url; use {raw, Error, Config, IntoCString}; @@ -29,7 +30,7 @@ impl Cred { /// or Kerberos authentication. pub fn default() -> Result { ::init(); - let mut out = 0 as *mut raw::git_cred; + let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_cred_default_new(&mut out)); Ok(Binding::from_raw(out)) @@ -41,7 +42,7 @@ impl Cred { /// The username specified is the username to authenticate. pub fn ssh_key_from_agent(username: &str) -> Result { ::init(); - let mut out = 0 as *mut raw::git_cred; + let mut out = ptr::null_mut(); let username = try!(CString::new(username)); unsafe { try_call!(raw::git_cred_ssh_key_from_agent(&mut out, username)); @@ -59,7 +60,7 @@ impl Cred { let publickey = try!(::opt_cstr(publickey)); let privatekey = try!(privatekey.into_c_string()); let passphrase = try!(::opt_cstr(passphrase)); - let mut out = 0 as *mut raw::git_cred; + let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_cred_ssh_key_new(&mut out, username, publickey, privatekey, passphrase)); @@ -73,7 +74,7 @@ impl Cred { ::init(); let username = try!(CString::new(username)); let password = try!(CString::new(password)); - let mut out = 0 as *mut raw::git_cred; + let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_cred_userpass_plaintext_new(&mut out, username, password)); @@ -112,7 +113,7 @@ impl Cred { pub fn username(username: &str) -> Result { ::init(); let username = try!(CString::new(username)); - let mut out = 0 as *mut raw::git_cred; + let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_cred_username_new(&mut out, username)); Ok(Binding::from_raw(out)) @@ -131,7 +132,7 @@ impl Cred { /// Unwrap access to the underlying raw pointer, canceling the destructor pub unsafe fn unwrap(mut self) -> *mut raw::git_cred { - mem::replace(&mut self.raw, 0 as *mut raw::git_cred) + mem::replace(&mut self.raw, ptr::null_mut()) } } diff --git a/src/describe.rs b/src/describe.rs index 55aaca6cb0..db75221ec0 100644 --- a/src/describe.rs +++ b/src/describe.rs @@ -1,6 +1,7 @@ use std::marker; use std::mem; use std::ffi::CString; +use std::ptr; use libc::{c_uint, c_int}; @@ -31,7 +32,7 @@ impl<'repo> Describe<'repo> { pub fn format(&self, opts: Option<&DescribeFormatOptions>) -> Result { let buf = Buf::new(); - let opts = opts.map(|o| &o.raw as *const _).unwrap_or(0 as *const _); + let opts = opts.map(|o| &o.raw as *const _).unwrap_or(ptr::null()); unsafe { try_call!(raw::git_describe_format(buf.raw(), self.raw, opts)); } diff --git a/src/diff.rs b/src/diff.rs index 94d1beb504..ff78a0626a 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -3,6 +3,7 @@ use std::marker; use std::mem; use std::ops::Range; use std::path::Path; +use std::ptr; use std::slice; use libc::{c_char, size_t, c_void, c_int}; @@ -206,7 +207,7 @@ impl<'repo> Diff<'repo> { /// Accumulate diff statistics for all patches. pub fn stats(&self) -> Result { - let mut ret = 0 as *mut raw::git_diff_stats; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_get_stats(&mut ret, self.raw)); Ok(Binding::from_raw(ret)) @@ -689,9 +690,9 @@ impl DiffOptions { /// structure is not moved, modified, or used elsewhere. pub unsafe fn raw(&mut self) -> *const raw::git_diff_options { self.raw.old_prefix = self.old_prefix.as_ref().map(|s| s.as_ptr()) - .unwrap_or(0 as *const _); + .unwrap_or(ptr::null()); self.raw.new_prefix = self.new_prefix.as_ref().map(|s| s.as_ptr()) - .unwrap_or(0 as *const _); + .unwrap_or(ptr::null()); self.raw.pathspec.count = self.pathspec_ptrs.len() as size_t; self.raw.pathspec.strings = self.pathspec_ptrs.as_ptr() as *mut _; &self.raw as *const _ diff --git a/src/index.rs b/src/index.rs index cb2f7618c2..697a12723b 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1,6 +1,7 @@ use std::ffi::{CStr, OsString, CString}; use std::ops::Range; use std::path::Path; +use std::ptr; use std::slice; use libc::{c_int, c_uint, size_t, c_void, c_char}; @@ -56,7 +57,7 @@ impl Index { /// used to perform in-memory index operations. pub fn new() -> Result { ::init(); - let mut raw = 0 as *mut raw::git_index; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_index_new(&mut raw)); Ok(Binding::from_raw(raw)) @@ -73,7 +74,7 @@ impl Index { /// on `Repository`. pub fn open(index_path: &Path) -> Result { ::init(); - let mut raw = 0 as *mut raw::git_index; + let mut raw = ptr::null_mut(); let index_path = try!(index_path.into_c_string()); unsafe { try_call!(raw::git_index_open(&mut raw, index_path)); @@ -204,7 +205,7 @@ impl Index { flag.bits() as c_uint, callback, ptr.map(|p| p as *mut _) - .unwrap_or(0 as *mut _) + .unwrap_or(ptr::null_mut()) as *mut c_void)); } return Ok(()); @@ -345,7 +346,7 @@ impl Index { &raw_strarray, callback, ptr.map(|p| p as *mut _) - .unwrap_or(0 as *mut _) + .unwrap_or(ptr::null_mut()) as *mut c_void)); } return Ok(()); @@ -380,7 +381,7 @@ impl Index { &raw_strarray, callback, ptr.map(|p| p as *mut _) - .unwrap_or(0 as *mut _) + .unwrap_or(ptr::null_mut()) as *mut c_void)); } return Ok(()); diff --git a/src/object.rs b/src/object.rs index c7b75e7d47..4af5ee71cb 100644 --- a/src/object.rs +++ b/src/object.rs @@ -35,7 +35,7 @@ impl<'repo> Object<'repo> { /// peeled until the type changes (e.g. a tag will be chased until the /// referenced object is no longer a tag). pub fn peel(&self, kind: ObjectType) -> Result, Error> { - let mut raw = 0 as *mut raw::git_object; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_object_peel(&mut raw, &*self.raw(), kind)); Ok(Binding::from_raw(raw)) @@ -117,7 +117,7 @@ impl<'repo> Object<'repo> { /// Performs a describe operation on this commitish object. pub fn describe(&self, opts: &DescribeOptions) -> Result { - let mut ret = 0 as *mut _; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_describe_commit(&mut ret, self.raw, opts.raw())); Ok(Binding::from_raw(ret)) @@ -149,7 +149,7 @@ impl<'repo> Object<'repo> { impl<'repo> Clone for Object<'repo> { fn clone(&self) -> Object<'repo> { - let mut raw = 0 as *mut raw::git_object; + let mut raw = ptr::null_mut(); unsafe { let rc = raw::git_object_dup(&mut raw, self.raw); assert_eq!(rc, 0); diff --git a/src/patch.rs b/src/patch.rs index 691df0181c..eccf83205b 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -1,4 +1,5 @@ use std::path::Path; +use std::ptr; use libc::{c_char, c_int, c_void}; use {raw, Blob, Buf, Diff, DiffDelta, DiffHunk, DiffLine, DiffOptions, Error}; @@ -33,7 +34,7 @@ impl Patch { /// /// Returns Ok(None) for an unchanged or binary file. pub fn from_diff(diff: &Diff, idx: usize) -> Result, Error> { - let mut ret = 0 as *mut raw::git_patch; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_patch_from_diff(&mut ret, diff.raw(), idx)); Ok(Binding::from_raw_opt(ret)) @@ -48,7 +49,7 @@ impl Patch { opts: Option<&mut DiffOptions>) -> Result { - let mut ret = 0 as *mut raw::git_patch; + let mut ret = ptr::null_mut(); let old_path = try!(into_opt_c_string(old_path)); let new_path = try!(into_opt_c_string(new_path)); unsafe { @@ -70,7 +71,7 @@ impl Patch { opts: Option<&mut DiffOptions>) -> Result { - let mut ret = 0 as *mut raw::git_patch; + let mut ret = ptr::null_mut(); let old_path = try!(into_opt_c_string(old_path)); let new_path = try!(into_opt_c_string(new_path)); unsafe { @@ -93,7 +94,7 @@ impl Patch { opts: Option<&mut DiffOptions>) -> Result { - let mut ret = 0 as *mut raw::git_patch; + let mut ret = ptr::null_mut(); let old_path = try!(into_opt_c_string(old_path)); let new_path = try!(into_opt_c_string(new_path)); unsafe { @@ -139,7 +140,7 @@ impl Patch { /// Get a DiffHunk and its total line count from the Patch. pub fn hunk(&mut self, hunk_idx: usize) -> Result<(DiffHunk, usize), Error> { - let mut ret = 0 as *const raw::git_diff_hunk; + let mut ret = ptr::null(); let mut lines = 0; unsafe { try_call!(raw::git_patch_get_hunk(&mut ret, &mut lines, self.raw, hunk_idx)); @@ -158,7 +159,7 @@ impl Patch { pub fn line_in_hunk(&mut self, hunk_idx: usize, line_of_hunk: usize) -> Result { - let mut ret = 0 as *const raw::git_diff_line; + let mut ret = ptr::null(); unsafe { try_call!(raw::git_patch_get_line_in_hunk(&mut ret, self.raw, diff --git a/src/pathspec.rs b/src/pathspec.rs index 888e8eacff..e1ee3d2250 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -2,6 +2,7 @@ use std::iter::IntoIterator; use std::marker; use std::ops::Range; use std::path::Path; +use std::ptr; use libc::size_t; use {raw, Error, Diff, Tree, PathspecFlags, Index, Repository, DiffDelta, IntoCString}; @@ -43,7 +44,7 @@ impl Pathspec { where T: IntoCString, I: IntoIterator { let (_a, _b, arr) = try!(::util::iter2cstrs(specs)); unsafe { - let mut ret = 0 as *mut raw::git_pathspec; + let mut ret = ptr::null_mut(); try_call!(raw::git_pathspec_new(&mut ret, &arr)); Ok(Binding::from_raw(ret)) } @@ -57,7 +58,7 @@ impl Pathspec { /// specified. pub fn match_diff(&self, diff: &Diff, flags: PathspecFlags) -> Result { - let mut ret = 0 as *mut raw::git_pathspec_match_list; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_pathspec_match_diff(&mut ret, diff.raw(), flags.bits(), self.raw)); @@ -73,7 +74,7 @@ impl Pathspec { /// specified. pub fn match_tree(&self, tree: &Tree, flags: PathspecFlags) -> Result { - let mut ret = 0 as *mut raw::git_pathspec_match_list; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_pathspec_match_tree(&mut ret, tree.raw(), flags.bits(), self.raw)); @@ -89,7 +90,7 @@ impl Pathspec { /// specified. pub fn match_index(&self, index: &Index, flags: PathspecFlags) -> Result { - let mut ret = 0 as *mut raw::git_pathspec_match_list; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_pathspec_match_index(&mut ret, index.raw(), flags.bits(), self.raw)); @@ -111,7 +112,7 @@ impl Pathspec { /// specified. pub fn match_workdir(&self, repo: &Repository, flags: PathspecFlags) -> Result { - let mut ret = 0 as *mut raw::git_pathspec_match_list; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_pathspec_match_workdir(&mut ret, repo.raw(), flags.bits(), self.raw)); diff --git a/src/proxy_options.rs b/src/proxy_options.rs index 45ca19dc15..a14fd2b81a 100644 --- a/src/proxy_options.rs +++ b/src/proxy_options.rs @@ -1,5 +1,6 @@ use std::ffi::CString; use std::marker; +use std::ptr; use raw; use util::Binding; @@ -49,10 +50,10 @@ impl<'a> Binding for ProxyOptions<'a> { 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 _), + url: self.url.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()), credentials: None, certificate_check: None, - payload: 0 as *mut _, + payload: ptr::null_mut(), } } } diff --git a/src/reference.rs b/src/reference.rs index e7af200df5..9528ae7588 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -2,8 +2,8 @@ use std::cmp::Ordering; use std::ffi::CString; use std::marker; use std::mem; +use std::ptr; use std::str; -use libc; use {raw, Error, Oid, Repository, Object, ObjectType}; use util::Binding; @@ -142,7 +142,7 @@ impl<'repo> Reference<'repo> { /// If a direct reference is passed as an argument, a copy of that /// reference is returned. pub fn resolve(&self) -> Result, Error> { - let mut raw = 0 as *mut raw::git_reference; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_resolve(&mut raw, &*self.raw)); Ok(Binding::from_raw(raw)) @@ -154,7 +154,7 @@ impl<'repo> Reference<'repo> { /// This method recursively peels the reference until it reaches /// an object of the specified type. pub fn peel(&self, kind: ObjectType) -> Result, Error> { - let mut raw = 0 as *mut raw::git_object; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_peel(&mut raw, self.raw, kind)); Ok(Binding::from_raw(raw)) @@ -169,7 +169,7 @@ impl<'repo> Reference<'repo> { /// the given name, the renaming will fail. pub fn rename(&mut self, new_name: &str, force: bool, msg: &str) -> Result, Error> { - let mut raw = 0 as *mut raw::git_reference; + let mut raw = ptr::null_mut(); let new_name = try!(CString::new(new_name)); let msg = try!(CString::new(msg)); unsafe { @@ -187,7 +187,7 @@ impl<'repo> Reference<'repo> { /// reference. pub fn set_target(&mut self, id: Oid, reflog_msg: &str) -> Result, Error> { - let mut raw = 0 as *mut raw::git_reference; + let mut raw = ptr::null_mut(); let msg = try!(CString::new(reflog_msg)); unsafe { try_call!(raw::git_reference_set_target(&mut raw, self.raw, @@ -261,7 +261,7 @@ impl<'repo> Binding for References<'repo> { impl<'repo> Iterator for References<'repo> { type Item = Result, Error>; fn next(&mut self) -> Option, Error>> { - let mut out = 0 as *mut raw::git_reference; + let mut out = ptr::null_mut(); unsafe { try_call_iter!(raw::git_reference_next(&mut out, self.raw)); Some(Ok(Binding::from_raw(out))) @@ -278,7 +278,7 @@ impl<'repo> Drop for References<'repo> { impl<'repo> Iterator for ReferenceNames<'repo> { type Item = Result<&'repo str, Error>; fn next(&mut self) -> Option> { - let mut out = 0 as *const libc::c_char; + let mut out = ptr::null(); unsafe { try_call_iter!(raw::git_reference_next_name(&mut out, self.inner.raw)); diff --git a/src/remote.rs b/src/remote.rs index c3aeb0f585..7b6493cb3e 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -2,6 +2,7 @@ use std::ffi::CString; use std::ops::Range; use std::marker; use std::mem; +use std::ptr; use std::slice; use std::str; use libc; @@ -110,9 +111,9 @@ 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 _)); + ptr::null(), + ptr::null(), + ptr::null())); } Ok(()) } @@ -132,7 +133,7 @@ impl<'repo> Remote<'repo> { try_call!(raw::git_remote_connect(self.raw, dir, &cb.raw(), &proxy_options.raw(), - 0 as *const _)); + ptr::null())); } Ok(RemoteConnection { @@ -271,7 +272,7 @@ impl<'repo> Remote<'repo> { /// the remote is initiated and it remains available after disconnecting. pub fn list(&self) -> Result<&[RemoteHead], Error> { let mut size = 0; - let mut base = 0 as *mut _; + let mut base = ptr::null_mut(); unsafe { try_call!(raw::git_remote_ls(&mut base, &mut size, self.raw)); assert_eq!(mem::size_of::(), @@ -303,7 +304,7 @@ impl<'repo> Remote<'repo> { impl<'repo> Clone for Remote<'repo> { fn clone(&self) -> Remote<'repo> { - let mut ret = 0 as *mut raw::git_remote; + let mut ret = ptr::null_mut(); let rc = unsafe { call!(raw::git_remote_dup(&mut ret, self.raw)) }; assert_eq!(rc, 0); Remote { @@ -437,7 +438,7 @@ impl<'cb> Binding for FetchOptions<'cb> { // TODO: expose this as a builder option custom_headers: raw::git_strarray { count: 0, - strings: 0 as *mut _, + strings: ptr::null_mut(), }, } } @@ -494,7 +495,7 @@ impl<'cb> Binding for PushOptions<'cb> { // TODO: expose this as a builder option custom_headers: raw::git_strarray { count: 0, - strings: 0 as *mut _, + strings: ptr::null_mut(), }, } } diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 7598dfd335..494c0110a1 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -2,6 +2,7 @@ use std::ffi::CStr; use std::marker; use std::mem; use std::slice; +use std::ptr; use std::str; use libc::{c_void, c_int, c_char, c_uint}; @@ -258,7 +259,7 @@ extern fn credentials_cb(ret: *mut *mut raw::git_cred, let payload = &mut *(payload as *mut RemoteCallbacks); let callback = try!(payload.credentials.as_mut() .ok_or(raw::GIT_PASSTHROUGH as c_int)); - *ret = 0 as *mut raw::git_cred; + *ret = ptr::null_mut(); let url = try!(str::from_utf8(CStr::from_ptr(url).to_bytes()) .map_err(|_| raw::GIT_PASSTHROUGH as c_int)); let username_from_url = match ::opt_bytes(&url, username_from_url) { diff --git a/src/repo.rs b/src/repo.rs index da7dd6e03c..106fbb5881 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -3,6 +3,7 @@ use std::ffi::{CStr, CString, OsStr}; use std::iter::IntoIterator; use std::mem; use std::path::Path; +use std::ptr; use std::str; use libc::{c_int, c_char, size_t, c_void, c_uint}; @@ -54,7 +55,7 @@ impl Repository { pub fn open>(path: P) -> Result { init(); let path = try!(path.as_ref().into_c_string()); - let mut ret = 0 as *mut raw::git_repository; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_repository_open(&mut ret, path)); Ok(Binding::from_raw(ret)) @@ -68,13 +69,13 @@ impl Repository { /// the current directory. pub fn open_from_env() -> Result { init(); - let mut ret = 0 as *mut raw::git_repository; + let mut ret = ptr::null_mut(); let flags = raw::GIT_REPOSITORY_OPEN_FROM_ENV; unsafe { try_call!(raw::git_repository_open_ext(&mut ret, - 0 as *const _, + ptr::null(), flags as c_uint, - 0 as *const _)); + ptr::null())); Ok(Binding::from_raw(ret)) } } @@ -115,7 +116,7 @@ impl Repository { 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; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_repository_open_ext(&mut ret, path, @@ -136,7 +137,7 @@ impl Repository { let path = try!(path.as_ref().into_c_string()); unsafe { try_call!(raw::git_repository_discover(buf.raw(), path, 1, - 0 as *const _)); + ptr::null())); } Repository::open(util::bytes2path(&*buf)) } @@ -164,7 +165,7 @@ impl Repository { -> Result { init(); let path = try!(path.as_ref().into_c_string()); - let mut ret = 0 as *mut raw::git_repository; + let mut ret = ptr::null_mut(); unsafe { let mut opts = opts.raw(); try_call!(raw::git_repository_init_ext(&mut ret, path, &mut opts)); @@ -188,8 +189,8 @@ impl Repository { /// returned if one occurs. pub fn revparse(&self, spec: &str) -> Result { let mut raw = raw::git_revspec { - from: 0 as *mut _, - to: 0 as *mut _, + from: ptr::null_mut(), + to: ptr::null_mut(), flags: 0, }; let spec = try!(CString::new(spec)); @@ -205,7 +206,7 @@ impl Repository { /// Find a single object, as specified by a revision string. pub fn revparse_single(&self, spec: &str) -> Result { let spec = try!(CString::new(spec)); - let mut obj = 0 as *mut raw::git_object; + let mut obj = ptr::null_mut(); unsafe { try_call!(raw::git_revparse_single(&mut obj, self.raw, spec)); assert!(!obj.is_null()); @@ -225,8 +226,8 @@ impl Repository { pub fn revparse_ext(&self, spec: &str) -> Result<(Object, Option), Error> { let spec = try!(CString::new(spec)); - let mut git_obj = 0 as *mut raw::git_object; - let mut git_ref = 0 as *mut raw::git_reference; + let mut git_obj = ptr::null_mut(); + let mut git_ref = ptr::null_mut(); unsafe { try_call!(raw::git_revparse_ext(&mut git_obj, &mut git_ref, self.raw, spec)); @@ -348,7 +349,7 @@ impl Repository { /// Get the information for a particular remote pub fn find_remote(&self, name: &str) -> Result { - let mut ret = 0 as *mut raw::git_remote; + let mut ret = ptr::null_mut(); let name = try!(CString::new(name)); unsafe { try_call!(raw::git_remote_lookup(&mut ret, self.raw, name)); @@ -359,7 +360,7 @@ impl Repository { /// Add a remote with the default fetch refspec to the repository's /// configuration. pub fn remote(&self, name: &str, url: &str) -> Result { - let mut ret = 0 as *mut raw::git_remote; + let mut ret = ptr::null_mut(); let name = try!(CString::new(name)); let url = try!(CString::new(url)); unsafe { @@ -374,7 +375,7 @@ impl Repository { /// this when you have a URL instead of a remote's name. Note that anonymous /// remotes cannot be converted to persisted remotes. pub fn remote_anonymous(&self, url: &str) -> Result { - let mut ret = 0 as *mut raw::git_remote; + let mut ret = ptr::null_mut(); let url = try!(CString::new(url)); unsafe { try_call!(raw::git_remote_create_anonymous(&mut ret, self.raw, url)); @@ -533,7 +534,7 @@ impl Repository { /// Retrieve and resolve the reference pointed at by HEAD. pub fn head(&self) -> Result { - let mut ret = 0 as *mut raw::git_reference; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_repository_head(&mut ret, self.raw)); Ok(Binding::from_raw(ret)) @@ -580,7 +581,7 @@ impl Repository { /// Create an iterator for the repo's references pub fn references(&self) -> Result { - let mut ret = 0 as *mut raw::git_reference_iterator; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_reference_iterator_new(&mut ret, self.raw)); Ok(Binding::from_raw(ret)) @@ -590,7 +591,7 @@ impl Repository { /// Create an iterator for the repo's references that match the specified /// glob pub fn references_glob(&self, glob: &str) -> Result { - let mut ret = 0 as *mut raw::git_reference_iterator; + let mut ret = ptr::null_mut(); let glob = try!(CString::new(glob)); unsafe { try_call!(raw::git_reference_iterator_glob_new(&mut ret, self.raw, @@ -625,7 +626,7 @@ impl Repository { data: *mut c_void) -> c_int { unsafe { let data = &mut *(data as *mut Data); - let mut raw = 0 as *mut raw::git_submodule; + let mut raw = ptr::null_mut(); let rc = raw::git_submodule_lookup(&mut raw, data.repo.raw(), name); assert_eq!(rc, 0); @@ -643,11 +644,11 @@ impl Repository { /// with no pathspec so that all files can be considered. pub fn statuses(&self, options: Option<&mut StatusOptions>) -> Result { - let mut ret = 0 as *mut raw::git_status_list; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_status_list_new(&mut ret, self.raw, options.map(|s| s.raw()) - .unwrap_or(0 as *const _))); + .unwrap_or(ptr::null()))); Ok(Binding::from_raw(ret)) } } @@ -699,7 +700,7 @@ impl Repository { /// Create an iterator which loops over the requested branches. pub fn branches(&self, filter: Option) -> Result { - let mut raw = 0 as *mut raw::git_branch_iterator; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_branch_iterator_new(&mut raw, self.raw(), filter)); Ok(Branches::from_raw(raw)) @@ -711,7 +712,7 @@ impl Repository { /// If a custom index has not been set, the default index for the repository /// will be returned (the one located in .git/index). pub fn index(&self) -> Result { - let mut raw = 0 as *mut raw::git_index; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_repository_index(&mut raw, self.raw())); Ok(Binding::from_raw(raw)) @@ -731,7 +732,7 @@ impl Repository { /// repository will be returned, including global and system configurations /// (if they are available). pub fn config(&self) -> Result { - let mut raw = 0 as *mut raw::git_config; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_repository_config(&mut raw, self.raw())); Ok(Binding::from_raw(raw)) @@ -770,7 +771,7 @@ impl Repository { /// Lookup a reference to one of the objects in a repository. pub fn find_blob(&self, oid: Oid) -> Result { - let mut raw = 0 as *mut raw::git_blob; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_blob_lookup(&mut raw, self.raw(), oid.raw())); Ok(Binding::from_raw(raw)) @@ -787,7 +788,7 @@ impl Repository { target: &Commit, force: bool) -> Result { let branch_name = try!(CString::new(branch_name)); - let mut raw = 0 as *mut raw::git_reference; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_branch_create(&mut raw, self.raw(), @@ -802,7 +803,7 @@ impl Repository { pub fn find_branch(&self, name: &str, branch_type: BranchType) -> Result { let name = try!(CString::new(name)); - let mut ret = 0 as *mut raw::git_reference; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_branch_lookup(&mut ret, self.raw(), name, branch_type)); @@ -837,7 +838,7 @@ impl Repository { update_ref, author.raw(), committer.raw(), - 0 as *const c_char, + ptr::null(), message, tree.raw(), parents.len() as size_t, @@ -849,7 +850,7 @@ impl Repository { /// Lookup a reference to one of the commits in a repository. pub fn find_commit(&self, oid: Oid) -> Result { - let mut raw = 0 as *mut raw::git_commit; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_commit_lookup(&mut raw, self.raw(), oid.raw())); Ok(Binding::from_raw(raw)) @@ -868,7 +869,7 @@ impl Repository { /// Lookup a reference to one of the objects in a repository. pub fn find_object(&self, oid: Oid, kind: Option) -> Result { - let mut raw = 0 as *mut raw::git_object; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_object_lookup(&mut raw, self.raw(), oid.raw(), kind)); @@ -885,7 +886,7 @@ impl Repository { log_message: &str) -> Result { let name = try!(CString::new(name)); let log_message = try!(CString::new(log_message)); - let mut raw = 0 as *mut raw::git_reference; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_create(&mut raw, self.raw(), name, id.raw(), force, @@ -932,7 +933,7 @@ impl Repository { log_message: &str) -> Result { let name = try!(CString::new(name)); let log_message = try!(CString::new(log_message)); - let mut raw = 0 as *mut raw::git_reference; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_create_matching(&mut raw, self.raw(), @@ -957,7 +958,7 @@ impl Repository { let name = try!(CString::new(name)); let target = try!(CString::new(target)); let log_message = try!(CString::new(log_message)); - let mut raw = 0 as *mut raw::git_reference; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_symbolic_create(&mut raw, self.raw(), name, target, force, @@ -986,7 +987,7 @@ impl Repository { let target = try!(CString::new(target)); let current_value = try!(CString::new(current_value)); let log_message = try!(CString::new(log_message)); - let mut raw = 0 as *mut raw::git_reference; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_symbolic_create_matching(&mut raw, self.raw(), @@ -1002,7 +1003,7 @@ impl Repository { /// Lookup a reference to one of the objects in a repository. pub fn find_reference(&self, name: &str) -> Result { let name = try!(CString::new(name)); - let mut raw = 0 as *mut raw::git_reference; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_lookup(&mut raw, self.raw(), name)); Ok(Binding::from_raw(raw)) @@ -1026,7 +1027,7 @@ impl Repository { /// Creates a git_annotated_commit from the given reference. pub fn reference_to_annotated_commit(&self, reference: &Reference) -> Result { - let mut ret = 0 as *mut raw::git_annotated_commit; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_annotated_commit_from_ref(&mut ret, self.raw(), @@ -1042,7 +1043,7 @@ impl Repository { /// based on that information. It will return `NotFound` if either the /// user.name or user.email are not set. pub fn signature(&self) -> Result, Error> { - let mut ret = 0 as *mut raw::git_signature; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_signature_default(&mut ret, self.raw())); Ok(Binding::from_raw(ret)) @@ -1065,7 +1066,7 @@ impl Repository { use_gitlink: bool) -> Result { let url = try!(CString::new(url)); let path = try!(path.into_c_string()); - let mut raw = 0 as *mut raw::git_submodule; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_submodule_add_setup(&mut raw, self.raw(), url, path, use_gitlink)); @@ -1079,7 +1080,7 @@ impl Repository { /// this returns a structure describing the submodule. pub fn find_submodule(&self, name: &str) -> Result { let name = try!(CString::new(name)); - let mut raw = 0 as *mut raw::git_submodule; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_submodule_lookup(&mut raw, self.raw(), name)); Ok(Binding::from_raw(raw)) @@ -1103,7 +1104,7 @@ impl Repository { /// Lookup a reference to one of the objects in a repository. pub fn find_tree(&self, oid: Oid) -> Result { - let mut raw = 0 as *mut raw::git_tree; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_tree_lookup(&mut raw, self.raw(), oid.raw())); Ok(Binding::from_raw(raw)) @@ -1117,10 +1118,10 @@ impl Repository { /// write them as tree objects to the database. pub fn treebuilder(&self, tree: Option<&Tree>) -> Result { unsafe { - let mut ret = 0 as *mut raw::git_treebuilder; + let mut ret = ptr::null_mut(); let tree = match tree { Some(tree) => tree.raw(), - None => 0 as *mut raw::git_tree, + None => ptr::null_mut(), }; try_call!(raw::git_treebuilder_new(&mut ret, self.raw, tree)); Ok(Binding::from_raw(ret)) @@ -1173,7 +1174,7 @@ impl Repository { /// Lookup a tag object from the repository. pub fn find_tag(&self, id: Oid) -> Result { - let mut raw = 0 as *mut raw::git_tag; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_tag_lookup(&mut raw, self.raw, id.raw())); Ok(Binding::from_raw(raw)) @@ -1301,7 +1302,7 @@ impl Repository { commit_ptrs.as_mut_ptr(), annotated_commits.len() as size_t, merge_opts.map(|o| o.raw()) - .unwrap_or(0 as *const _), + .unwrap_or(ptr::null()), &raw_checkout_opts)); } Ok(()) @@ -1313,7 +1314,7 @@ impl Repository { /// should resolve any conflicts that arose as part of the merge. pub fn merge_commits(&self, our_commit: &Commit, their_commit: &Commit, opts: Option<&MergeOptions>) -> Result { - let mut raw = 0 as *mut raw::git_index; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_merge_commits(&mut raw, self.raw, our_commit.raw(), @@ -1400,7 +1401,7 @@ impl Repository { /// annotating. pub fn notes(&self, notes_ref: Option<&str>) -> Result { let notes_ref = try!(::opt_cstr(notes_ref)); - let mut ret = 0 as *mut raw::git_note_iterator; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_note_iterator_new(&mut ret, self.raw, notes_ref)); Ok(Binding::from_raw(ret)) @@ -1416,7 +1417,7 @@ impl Repository { pub fn find_note(&self, notes_ref: Option<&str>, id: Oid) -> Result { let notes_ref = try!(::opt_cstr(notes_ref)); - let mut ret = 0 as *mut raw::git_note; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_note_read(&mut ret, self.raw, notes_ref, id.raw())); @@ -1445,7 +1446,7 @@ impl Repository { /// Create a revwalk that can be used to traverse the commit graph. pub fn revwalk(&self) -> Result { - let mut raw = 0 as *mut raw::git_revwalk; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_revwalk_new(&mut raw, self.raw())); Ok(Binding::from_raw(raw)) @@ -1456,7 +1457,7 @@ impl Repository { pub fn blame_file(&self, path: &Path, opts: Option<&mut BlameOptions>) -> Result { let path = try!(path.into_c_string()); - let mut raw = 0 as *mut raw::git_blame; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_blame_file(&mut raw, @@ -1480,7 +1481,7 @@ impl Repository { /// Find all merge bases between two commits pub fn merge_bases(&self, one: Oid, two: Oid) -> Result { let mut arr = raw::git_oidarray { - ids: 0 as *mut raw::git_oid, + ids: ptr::null_mut(), count: 0, }; unsafe { @@ -1526,7 +1527,7 @@ impl Repository { /// object will be returned. pub fn reflog(&self, name: &str) -> Result { let name = try!(CString::new(name)); - let mut ret = 0 as *mut raw::git_reflog; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_reflog_read(&mut ret, self.raw, name)); Ok(Binding::from_raw(ret)) @@ -1577,7 +1578,7 @@ impl Repository { /// After performing a describe on HEAD, a status is run and description is /// considered to be dirty if there are. pub fn describe(&self, opts: &DescribeOptions) -> Result { - let mut ret = 0 as *mut _; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_describe_workdir(&mut ret, self.raw, opts.raw())); Ok(Binding::from_raw(ret)) @@ -1597,7 +1598,7 @@ impl Repository { new_tree: Option<&Tree>, opts: Option<&mut DiffOptions>) -> Result { - let mut ret = 0 as *mut raw::git_diff; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_tree_to_tree(&mut ret, self.raw(), @@ -1626,7 +1627,7 @@ impl Repository { index: Option<&Index>, opts: Option<&mut DiffOptions>) -> Result { - let mut ret = 0 as *mut raw::git_diff; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_tree_to_index(&mut ret, self.raw(), @@ -1646,7 +1647,7 @@ impl Repository { new_index: &Index, opts: Option<&mut DiffOptions>) -> Result { - let mut ret = 0 as *mut raw::git_diff; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_index_to_index(&mut ret, self.raw(), @@ -1674,7 +1675,7 @@ impl Repository { index: Option<&Index>, opts: Option<&mut DiffOptions>) -> Result { - let mut ret = 0 as *mut raw::git_diff; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_index_to_workdir(&mut ret, self.raw(), @@ -1706,7 +1707,7 @@ impl Repository { old_tree: Option<&Tree>, opts: Option<&mut DiffOptions>) -> Result { - let mut ret = 0 as *mut raw::git_diff; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_tree_to_workdir(&mut ret, self.raw(), @@ -1726,7 +1727,7 @@ impl Repository { old_tree: Option<&Tree>, opts: Option<&mut DiffOptions>) -> Result { - let mut ret = 0 as *mut raw::git_diff; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_tree_to_workdir_with_index(&mut ret, self.raw(), old_tree.map(|s| s.raw()), opts.map(|s| s.raw()))); @@ -1736,7 +1737,7 @@ impl Repository { /// Create a PackBuilder pub fn packbuilder(&self) -> Result { - let mut ret = 0 as *mut raw::git_packbuilder; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_packbuilder_new(&mut ret, self.raw())); Ok(Binding::from_raw(ret)) diff --git a/src/signature.rs b/src/signature.rs index 5951960b40..61e7a8948a 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -1,6 +1,7 @@ use std::ffi::CString; use std::marker; use std::mem; +use std::ptr; use std::str; use std::fmt; use libc; @@ -29,7 +30,7 @@ impl<'a> Signature<'a> { /// See `new` for more information pub fn now(name: &str, email: &str) -> Result, Error> { ::init(); - let mut ret = 0 as *mut raw::git_signature; + let mut ret = ptr::null_mut(); let name = try!(CString::new(name)); let email = try!(CString::new(email)); unsafe { @@ -47,7 +48,7 @@ impl<'a> Signature<'a> { pub fn new(name: &str, email: &str, time: &Time) -> Result, Error> { ::init(); - let mut ret = 0 as *mut raw::git_signature; + let mut ret = ptr::null_mut(); let name = try!(CString::new(name)); let email = try!(CString::new(email)); unsafe { @@ -128,7 +129,7 @@ impl Clone for Signature<'static> { fn clone(&self) -> Signature<'static> { // TODO: can this be defined for 'a and just do a plain old copy if the // lifetime isn't static? - let mut raw = 0 as *mut raw::git_signature; + let mut raw = ptr::null_mut(); let rc = unsafe { raw::git_signature_dup(&mut raw, &*self.raw) }; assert_eq!(rc, 0); unsafe { Binding::from_raw(raw) } diff --git a/src/submodule.rs b/src/submodule.rs index 32d141e5f5..234a8815e9 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -1,4 +1,5 @@ use std::marker; +use std::ptr; use std::str; use std::path::Path; @@ -108,7 +109,7 @@ impl<'repo> Submodule<'repo> { /// This will only work if the submodule is checked out into the working /// directory. pub fn open(&self) -> Result { - let mut raw = 0 as *mut raw::git_repository; + let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_submodule_open(&mut raw, self.raw)); Ok(Binding::from_raw(raw)) diff --git a/src/tag.rs b/src/tag.rs index 85739748de..2b2716de97 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -1,5 +1,6 @@ use std::marker; use std::mem; +use std::ptr; use std::str; use {raw, signature, Error, Oid, Object, Signature, ObjectType}; @@ -47,7 +48,7 @@ impl<'repo> Tag<'repo> { /// Recursively peel a tag until a non tag git_object is found pub fn peel(&self) -> Result, Error> { - let mut ret = 0 as *mut raw::git_object; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_tag_peel(&mut ret, &*self.raw)); Ok(Binding::from_raw(ret)) @@ -73,7 +74,7 @@ impl<'repo> Tag<'repo> { /// This method performs a repository lookup for the given object and /// returns it pub fn target(&self) -> Result, Error> { - let mut ret = 0 as *mut raw::git_object; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_tag_target(&mut ret, &*self.raw)); Ok(Binding::from_raw(ret)) diff --git a/src/test.rs b/src/test.rs index 55144611dc..02cea2d903 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,5 +1,6 @@ use std::path::{Path, PathBuf}; use std::io; +use std::ptr; use tempdir::TempDir; use url::Url; @@ -48,7 +49,7 @@ pub fn realpath(original: &Path) -> io::Result { } unsafe { let cstr = try!(CString::new(original.as_os_str().as_bytes())); - let ptr = realpath(cstr.as_ptr(), 0 as *mut _); + let ptr = realpath(cstr.as_ptr(), ptr::null_mut()); if ptr.is_null() { return Err(io::Error::last_os_error()) } diff --git a/src/transport.rs b/src/transport.rs index 92fe3ad267..02b8c0d5cf 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -5,6 +5,7 @@ use std::io::prelude::*; use std::io; use std::mem; use std::slice; +use std::ptr; use std::str; use libc::{c_int, c_void, c_uint, c_char, size_t}; @@ -134,7 +135,7 @@ impl Transport { subtransport: S) -> Result where S: SmartSubtransport { - let mut ret = 0 as *mut _; + let mut ret = ptr::null_mut(); let mut raw = Box::new(RawSmartSubtransport { raw: raw::git_smart_subtransport { diff --git a/src/tree.rs b/src/tree.rs index 27231adc03..3d361ed1c0 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -4,6 +4,7 @@ use std::ffi::CString; use std::ops::Range; use std::marker; use std::path::Path; +use std::ptr; use std::str; use libc; @@ -90,7 +91,7 @@ impl<'repo> Tree<'repo> { /// given its relative path. pub fn get_path(&self, path: &Path) -> Result, Error> { let path = try!(path.into_c_string()); - let mut ret = 0 as *mut raw::git_tree_entry; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_tree_entry_bypath(&mut ret, &*self.raw(), path)); Ok(Binding::from_raw(ret)) @@ -172,7 +173,7 @@ impl<'tree> TreeEntry<'tree> { /// Convert a tree entry to the object it points to. pub fn to_object<'a>(&self, repo: &'a Repository) -> Result, Error> { - let mut ret = 0 as *mut raw::git_object; + let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_tree_entry_to_object(&mut ret, repo.raw(), &*self.raw())); @@ -221,7 +222,7 @@ impl<'a> Binding for TreeEntry<'a> { impl<'a> Clone for TreeEntry<'a> { fn clone(&self) -> TreeEntry<'a> { - let mut ret = 0 as *mut raw::git_tree_entry; + let mut ret = ptr::null_mut(); unsafe { assert_eq!(raw::git_tree_entry_dup(&mut ret, &*self.raw()), 0); Binding::from_raw(ret) diff --git a/src/treebuilder.rs b/src/treebuilder.rs index f8446cdab8..779f6f30f2 100644 --- a/src/treebuilder.rs +++ b/src/treebuilder.rs @@ -1,4 +1,5 @@ use std::marker; +use std::ptr; use libc::{c_int, c_void}; @@ -49,7 +50,7 @@ impl<'repo> TreeBuilder<'repo> { let filename = try!(filename.into_c_string()); let filemode = filemode as raw::git_filemode_t; - let mut ret = 0 as *const raw::git_tree_entry; + let mut ret = ptr::null(); unsafe { try_call!(raw::git_treebuilder_insert(&mut ret, self.raw, filename, oid.raw(), filemode)); From d8ece6695f3503cd0010d7e0bd200cc64ecc34fb Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 12:37:09 -0700 Subject: [PATCH 114/860] clippy: new_without_default --- src/blame.rs | 7 +++++++ src/buf.rs | 6 ++++++ src/build.rs | 13 +++++++++++++ src/describe.rs | 12 ++++++++++++ src/diff.rs | 12 ++++++++++++ src/merge.rs | 6 ++++++ src/remote.rs | 13 +++++++++++++ src/remote_callbacks.rs | 6 ++++++ src/stash.rs | 8 +++++++- src/status.rs | 6 ++++++ 10 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/blame.rs b/src/blame.rs index c3e1209c5c..60c23f9c0c 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -140,6 +140,13 @@ impl<'blame> BlameHunk<'blame> { } } + +impl Default for BlameOptions { + fn default() -> Self { + Self::new() + } +} + impl BlameOptions { /// Initialize options diff --git a/src/buf.rs b/src/buf.rs index 384720ac63..78e958e2e2 100644 --- a/src/buf.rs +++ b/src/buf.rs @@ -14,6 +14,12 @@ pub struct Buf { raw: raw::git_buf, } +impl Default for Buf { + fn default() -> Self { + Self::new() + } +} + impl Buf { /// Creates a new empty buffer. pub fn new() -> Buf { diff --git a/src/build.rs b/src/build.rs index 33b9c2c9e3..148a83b32f 100644 --- a/src/build.rs +++ b/src/build.rs @@ -54,6 +54,13 @@ pub type Progress<'a> = FnMut(Option<&Path>, usize, usize) + 'a; pub type Notify<'a> = FnMut(CheckoutNotificationType, Option<&Path>, DiffFile, DiffFile, DiffFile) -> bool + 'a; + +impl<'cb> Default for RepoBuilder<'cb> { + fn default() -> Self { + Self::new() + } +} + impl<'cb> RepoBuilder<'cb> { /// Creates a new repository builder with all of the default configuration. /// @@ -166,6 +173,12 @@ impl<'cb> RepoBuilder<'cb> { } } +impl<'cb> Default for CheckoutBuilder<'cb> { + fn default() -> Self { + Self::new() + } +} + impl<'cb> CheckoutBuilder<'cb> { /// Creates a new builder for checkouts with all of its default /// configuration. diff --git a/src/describe.rs b/src/describe.rs index db75221ec0..e950eb8aba 100644 --- a/src/describe.rs +++ b/src/describe.rs @@ -55,6 +55,12 @@ impl<'repo> Drop for Describe<'repo> { } } +impl Default for DescribeFormatOptions { + fn default() -> Self { + Self::new() + } +} + impl DescribeFormatOptions { /// Creates a new blank set of formatting options for a description. pub fn new() -> DescribeFormatOptions { @@ -92,6 +98,12 @@ impl DescribeFormatOptions { } } +impl Default for DescribeOptions { + fn default() -> Self { + Self::new() + } +} + impl DescribeOptions { /// Creates a new blank set of formatting options for a description. pub fn new() -> DescribeOptions { diff --git a/src/diff.rs b/src/diff.rs index ff78a0626a..5fd12342d4 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -433,6 +433,12 @@ impl<'a> Binding for DiffFile<'a> { fn raw(&self) -> *const raw::git_diff_file { self.raw } } +impl Default for DiffOptions { + fn default() -> Self { + Self::new() + } +} + impl DiffOptions { /// Creates a new set of empty diff options. /// @@ -957,6 +963,12 @@ impl Binding for DiffBinaryKind { } } +impl Default for DiffFindOptions { + fn default() -> Self { + Self::new() + } +} + impl DiffFindOptions { /// Creates a new set of empty diff find options. /// diff --git a/src/merge.rs b/src/merge.rs index 045e9faf86..15089403e5 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -28,6 +28,12 @@ impl<'repo> AnnotatedCommit<'repo> { } } +impl Default for MergeOptions { + fn default() -> Self { + Self::new() + } +} + impl MergeOptions { /// Creates a default set of merge options. pub fn new() -> MergeOptions { diff --git a/src/remote.rs b/src/remote.rs index 7b6493cb3e..17b4e1c5a6 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -371,6 +371,12 @@ impl<'remote> RemoteHead<'remote> { } } +impl<'cb> Default for FetchOptions<'cb> { + fn default() -> Self { + Self::new() + } +} + impl<'cb> FetchOptions<'cb> { /// Creates a new blank set of fetch options pub fn new() -> FetchOptions<'cb> { @@ -444,6 +450,13 @@ impl<'cb> Binding for FetchOptions<'cb> { } } + +impl<'cb> Default for PushOptions<'cb> { + fn default() -> Self { + Self::new() + } +} + impl<'cb> PushOptions<'cb> { /// Creates a new blank set of push options pub fn new() -> PushOptions<'cb> { diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 494c0110a1..3339d2e749 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -77,6 +77,12 @@ pub type CertificateCheck<'a> = FnMut(&Cert, &str) -> bool + 'a; /// was rejected by the remote server with a reason why. pub type PushUpdateReference<'a> = FnMut(&str, Option<&str>) -> Result<(), Error> + 'a; +impl<'a> Default for RemoteCallbacks<'a> { + fn default() -> Self { + Self::new() + } +} + impl<'a> RemoteCallbacks<'a> { /// Creates a new set of empty callbacks pub fn new() -> RemoteCallbacks<'a> { diff --git a/src/stash.rs b/src/stash.rs index ca61c53355..b1d04f1aae 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -23,6 +23,12 @@ pub struct StashApplyOptions<'cb> { raw_opts: raw::git_stash_apply_options } +impl<'cb> Default for StashApplyOptions<'cb> { + fn default() -> Self { + Self::new() + } +} + impl<'cb> StashApplyOptions<'cb> { /// Creates a default set of merge options. pub fn new() -> StashApplyOptions<'cb> { @@ -201,4 +207,4 @@ mod tests { assert!(count_stash(repo) == 1) }) } -} \ No newline at end of file +} diff --git a/src/status.rs b/src/status.rs index 40e47b72d5..8418d72d2e 100644 --- a/src/status.rs +++ b/src/status.rs @@ -58,6 +58,12 @@ pub struct StatusEntry<'statuses> { _marker: marker::PhantomData<&'statuses DiffDelta<'statuses>>, } +impl Default for StatusOptions { + fn default() -> Self { + Self::new() + } +} + impl StatusOptions { /// Creates a new blank set of status options. pub fn new() -> StatusOptions { From 8236f80c38e85d9d5522f817518601c101e86744 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 11:27:44 -0700 Subject: [PATCH 115/860] clippy: new_without_default_derive (unsure) It's not that obvious that raw::git_proxy_t defaults to raw::GIT_PROXY_NONE, so maybe we should keep the `new()` method as it is to make this explicit? --- src/proxy_options.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/proxy_options.rs b/src/proxy_options.rs index a14fd2b81a..e1601749be 100644 --- a/src/proxy_options.rs +++ b/src/proxy_options.rs @@ -6,6 +6,7 @@ use raw; use util::Binding; /// Options which can be specified to various fetch operations. +#[derive(Default)] pub struct ProxyOptions<'a> { url: Option, proxy_kind: raw::git_proxy_t, @@ -15,11 +16,7 @@ pub struct ProxyOptions<'a> { 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, - } + Default::default() } /// Try to auto-detect the proxy from the git configuration. From ff5af8ac5afdee8b6ed2a3bd7b7f19a511cb1a7f Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 12:24:01 -0700 Subject: [PATCH 116/860] clippy: needless_return --- examples/init.rs | 2 +- src/cred.rs | 4 ++-- src/describe.rs | 4 ++-- src/diff.rs | 4 ++-- src/index.rs | 6 +++--- src/panic.rs | 2 +- src/patch.rs | 2 +- src/remote_callbacks.rs | 2 +- src/repo.rs | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/init.rs b/examples/init.rs index 2af3e9657d..29e6de1291 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -116,7 +116,7 @@ fn parse_shared(shared: &str) -> Result { if shared.starts_with("0") { match u32::from_str_radix(&shared[1..], 8).ok() { Some(n) => { - return Ok(RepositoryInitMode::from_bits_truncate(n)) + Ok(RepositoryInitMode::from_bits_truncate(n)) } None => { Err(Error::from_str("invalid octal value for --shared")) diff --git a/src/cred.rs b/src/cred.rs index 32833c6e37..edf50e1684 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -175,7 +175,7 @@ impl CredentialHelper { } ret.protocol = Some(url.scheme().to_string()) } - return ret; + ret } /// Set the username that this credential helper will query with. @@ -318,7 +318,7 @@ impl CredentialHelper { } let output = my_try!(p.wait_with_output()); if !output.status.success() { return (None, None) } - return self.parse_output(output.stdout) + self.parse_output(output.stdout) } // Parse the output of a command into the username/password found diff --git a/src/describe.rs b/src/describe.rs index e950eb8aba..c062088711 100644 --- a/src/describe.rs +++ b/src/describe.rs @@ -70,7 +70,7 @@ impl DescribeFormatOptions { }; opts.raw.version = 1; opts.raw.abbreviated_size = 7; - return opts + opts } /// Sets the size of the abbreviated commit id to use. @@ -113,7 +113,7 @@ impl DescribeOptions { }; opts.raw.version = 1; opts.raw.max_candidates_tags = 10; - return opts + opts } #[allow(missing_docs)] diff --git a/src/diff.rs b/src/diff.rs index 5fd12342d4..5f5c62d3dd 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -162,7 +162,7 @@ impl<'repo> Diff<'repo> { unsafe { try_call!(raw::git_diff_print(self.raw, format, print_cb, ptr as *mut _)); - return Ok(()) + Ok(()) } } @@ -201,7 +201,7 @@ impl<'repo> Diff<'repo> { try_call!(raw::git_diff_foreach(self.raw, file_cb_c, binary_cb_c, hunk_cb_c, line_cb_c, ptr as *mut _)); - return Ok(()) + Ok(()) } } diff --git a/src/index.rs b/src/index.rs index 697a12723b..356505a8c2 100644 --- a/src/index.rs +++ b/src/index.rs @@ -208,7 +208,7 @@ impl Index { .unwrap_or(ptr::null_mut()) as *mut c_void)); } - return Ok(()); + Ok(()) } /// Clear the contents (all the entries) of an index object. @@ -349,7 +349,7 @@ impl Index { .unwrap_or(ptr::null_mut()) as *mut c_void)); } - return Ok(()); + Ok(()) } /// Update all index entries to match the working directory @@ -384,7 +384,7 @@ impl Index { .unwrap_or(ptr::null_mut()) as *mut c_void)); } - return Ok(()); + Ok(()) } /// Write an existing index object from memory back to disk using an atomic diff --git a/src/panic.rs b/src/panic.rs index ad4f3759fa..35f2c09394 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -40,7 +40,7 @@ pub fn wrap T>(f: F) -> Option { let mut bomb = Bomb { enabled: true }; let ret = Some(f()); bomb.enabled = false; - return ret; + ret } pub fn check() { diff --git a/src/patch.rs b/src/patch.rs index eccf83205b..19f774d770 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -187,7 +187,7 @@ impl Patch { let ptr = &mut line_cb as *mut _ as *mut c_void; unsafe { try_call!(raw::git_patch_print(self.raw, print_cb, ptr)); - return Ok(()) + Ok(()) } } diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 3339d2e749..a472609642 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -192,7 +192,7 @@ impl<'a> Binding for RemoteCallbacks<'a> { callbacks.update_tips = Some(f); } callbacks.payload = self as *const _ as *mut _; - return callbacks; + callbacks } } } diff --git a/src/repo.rs b/src/repo.rs index 106fbb5881..e5c9fa8b7b 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1973,7 +1973,7 @@ impl RepositoryInitOptions { opts.template_path = ::call::convert(&self.template_path); opts.initial_head = ::call::convert(&self.initial_head); opts.origin_url = ::call::convert(&self.origin_url); - return opts; + opts } } From dd331a7023485df37d607d9aa28d843d1e5d1cdf Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 12:25:52 -0700 Subject: [PATCH 117/860] clippy: single_match --- src/build.rs | 34 ++++++++++++++-------------------- src/cred.rs | 24 +++++++++--------------- src/repo.rs | 10 ++++------ 3 files changed, 27 insertions(+), 41 deletions(-) diff --git a/src/build.rs b/src/build.rs index 148a83b32f..ca4c8aab7c 100644 --- a/src/build.rs +++ b/src/build.rs @@ -151,16 +151,14 @@ impl<'cb> RepoBuilder<'cb> { opts.checkout_opts.checkout_strategy = raw::GIT_CHECKOUT_SAFE as c_uint; - match self.fetch_opts { - Some(ref mut cbs) => { - opts.fetch_opts = cbs.raw(); - }, - None => {} + if let Some(ref mut cbs) = self.fetch_opts { + opts.fetch_opts = cbs.raw(); } - match self.checkout { - Some(ref mut c) => unsafe { c.configure(&mut opts.checkout_opts) }, - None => {} + if let Some(ref mut c) = self.checkout { + unsafe { + c.configure(&mut opts.checkout_opts); + } } let url = try!(CString::new(url)); @@ -443,21 +441,17 @@ impl<'cb> CheckoutBuilder<'cb> { opts.paths.count = self.path_ptrs.len() as size_t; } - match self.target_dir { - Some(ref c) => opts.target_directory = c.as_ptr(), - None => {} + if let Some(ref c) = self.target_dir { + opts.target_directory = c.as_ptr(); } - match self.ancestor_label { - Some(ref c) => opts.ancestor_label = c.as_ptr(), - None => {} + if let Some(ref c) = self.ancestor_label { + opts.ancestor_label = c.as_ptr(); } - match self.our_label { - Some(ref c) => opts.our_label = c.as_ptr(), - None => {} + if let Some(ref c) = self.our_label { + opts.our_label = c.as_ptr(); } - match self.their_label { - Some(ref c) => opts.their_label = c.as_ptr(), - None => {} + if let Some(ref c) = self.their_label { + opts.their_label = c.as_ptr(); } if self.progress.is_some() { let f: raw::git_checkout_progress_cb = progress_cb; diff --git a/src/cred.rs b/src/cred.rs index edf50e1684..0d0db8d6df 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -217,12 +217,9 @@ impl CredentialHelper { fn config_helper(&mut self, config: &Config) { let exact = config.get_string(&self.exact_key("helper")); self.add_command(exact.as_ref().ok().map(|s| &s[..])); - match self.url_key("helper") { - Some(key) => { - let url = config.get_string(&key); - self.add_command(url.as_ref().ok().map(|s| &s[..])); - } - None => {} + if let Some(key) = self.url_key("helper") { + let url = config.get_string(&key); + self.add_command(url.as_ref().ok().map(|s| &s[..])); } let global = config.get_string("credential.helper"); self.add_command(global.as_ref().ok().map(|s| &s[..])); @@ -303,17 +300,14 @@ impl CredentialHelper { // stdin { let stdin = p.stdin.as_mut().unwrap(); - match self.protocol { - Some(ref p) => { let _ = writeln!(stdin, "protocol={}", p); } - None => {} + if let Some(ref p) = self.protocol { + let _ = writeln!(stdin, "protocol={}", p); } - match self.host { - Some(ref p) => { let _ = writeln!(stdin, "host={}", p); } - None => {} + if let Some(ref p) = self.host { + let _ = writeln!(stdin, "host={}", p); } - match *username { - Some(ref p) => { let _ = writeln!(stdin, "username={}", p); } - None => {} + if let Some(ref p) = *username { + let _ = writeln!(stdin, "username={}", p); } } let output = my_try!(p.wait_with_output()); diff --git a/src/repo.rs b/src/repo.rs index e5c9fa8b7b..f1e64f2a5a 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1240,9 +1240,8 @@ impl Repository { let mut raw_opts = mem::zeroed(); try_call!(raw::git_checkout_init_options(&mut raw_opts, raw::GIT_CHECKOUT_OPTIONS_VERSION)); - match opts { - Some(c) => c.configure(&mut raw_opts), - None => {} + if let Some(c) = opts { + c.configure(&mut raw_opts); } try_call!(raw::git_checkout_index(self.raw, @@ -1261,9 +1260,8 @@ impl Repository { let mut raw_opts = mem::zeroed(); try_call!(raw::git_checkout_init_options(&mut raw_opts, raw::GIT_CHECKOUT_OPTIONS_VERSION)); - match opts { - Some(c) => c.configure(&mut raw_opts), - None => {} + if let Some(c) = opts { + c.configure(&mut raw_opts); } try_call!(raw::git_checkout_tree(self.raw, &*treeish.raw(), From 17c74a3935777e501405f281b578316b439b2dad Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 15:51:26 -0700 Subject: [PATCH 118/860] clippy: single_char_pattern --- examples/init.rs | 2 +- examples/log.rs | 2 +- examples/rev-list.rs | 2 +- src/cred.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/init.rs b/examples/init.rs index 29e6de1291..2f1f28a496 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -113,7 +113,7 @@ fn parse_shared(shared: &str) -> Result { "true" | "group" => Ok(git2::REPOSITORY_INIT_SHARED_GROUP), "all" | "world" => Ok(git2::REPOSITORY_INIT_SHARED_ALL), _ => { - if shared.starts_with("0") { + if shared.starts_with('0') { match u32::from_str_radix(&shared[1..], 8).ok() { Some(n) => { Ok(RepositoryInitMode::from_bits_truncate(n)) diff --git a/examples/log.rs b/examples/log.rs index a679a22626..6f6997b106 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -61,7 +61,7 @@ fn run(args: &Args) -> Result<(), Error> { git2::SORT_NONE }); for commit in args.arg_commit.iter() { - if commit.starts_with("^") { + if commit.starts_with('^') { let obj = try!(repo.revparse_single(&commit[1..])); try!(revwalk.hide(obj.id())); continue diff --git a/examples/rev-list.rs b/examples/rev-list.rs index d42d589e29..56b9123f93 100644 --- a/examples/rev-list.rs +++ b/examples/rev-list.rs @@ -47,7 +47,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { let specs = args.flag_not.iter().map(|s| (s, true)) .chain(args.arg_spec.iter().map(|s| (s, false))) .map(|(spec, hide)| { - if spec.starts_with("^") {(&spec[1..], !hide)} else {(&spec[..], hide)} + if spec.starts_with('^') {(&spec[1..], !hide)} else {(&spec[..], hide)} }); for (spec, hide) in specs { let id = if spec.contains("..") { diff --git a/src/cred.rs b/src/cred.rs index 0d0db8d6df..70a5816892 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -235,9 +235,9 @@ impl CredentialHelper { Some(s) => s, }; - if cmd.starts_with("!") { + if cmd.starts_with('!') { self.commands.push(cmd[1..].to_string()); - } else if cmd.starts_with("/") || cmd.starts_with("\\") || + } else if cmd.starts_with('/') || cmd.starts_with('\\') || cmd[1..].starts_with(":\\") { self.commands.push(format!("\"{}\"", cmd)); } else { From 39ce54d034f049542a13c5a6ce73f9c5b359fb0c Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 16:00:07 -0700 Subject: [PATCH 119/860] clippy: or_fun_call --- examples/clone.rs | 6 ++++-- examples/status.rs | 6 +++--- src/remote.rs | 5 +++-- src/repo.rs | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/examples/clone.rs b/examples/clone.rs index a30abb5da5..8c2bad6f15 100644 --- a/examples/clone.rs +++ b/examples/clone.rs @@ -63,8 +63,10 @@ fn print(state: &mut State) { stats.total_objects(), index_pct, stats.indexed_objects(), stats.total_objects(), co_pct, state.current, state.total, - state.path.as_ref().map(|s| s.to_string_lossy().into_owned()) - .unwrap_or(String::new())); + state.path + .as_ref() + .map(|s| s.to_string_lossy().into_owned()) + .unwrap_or_default()) } io::stdout().flush().unwrap(); } diff --git a/examples/status.rs b/examples/status.rs index f2a0a5723c..9cef064056 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -43,7 +43,7 @@ struct Args { enum Format { Long, Short, Porcelain } fn run(args: &Args) -> Result<(), Error> { - let path = args.flag_git_dir.clone().unwrap_or(".".to_string()); + let path = args.flag_git_dir.clone().unwrap_or_else(|| ".".to_string()); let repo = try!(Repository::open(&path)); if repo.is_bare() { return Err(Error::from_str("cannot report status on bare repository")) @@ -312,8 +312,8 @@ fn print_short(repo: &Repository, statuses: git2::Statuses) { b = diff.new_file().path(); } if let Some(diff) = entry.index_to_workdir() { - a = a.or(diff.old_file().path()); - b = b.or(diff.old_file().path()); + a.or_else(|| diff.old_file().path()); + b.or_else(|| diff.old_file().path()); c = diff.new_file().path(); } diff --git a/src/remote.rs b/src/remote.rs index 17b4e1c5a6..3dd87cee7b 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -500,8 +500,9 @@ impl<'cb> Binding for PushOptions<'cb> { fn raw(&self) -> raw::git_push_options { raw::git_push_options { version: 1, - callbacks: self.callbacks.as_ref().map(|m| m.raw()) - .unwrap_or(RemoteCallbacks::new().raw()), + 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()), pb_parallelism: self.pb_parallelism as libc::c_uint, diff --git a/src/repo.rs b/src/repo.rs index f1e64f2a5a..79c1a56a2f 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1751,7 +1751,7 @@ impl Repository { unsafe { let mut raw_oid = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; let message = try!(CString::new(message)); - let flags = flags.unwrap_or(StashFlags::empty()); + let flags = flags.unwrap_or_else(StashFlags::empty); try_call!(raw::git_stash_save(&mut raw_oid, self.raw(), stasher.raw(), From cfd481ed662e7ac46de853319d16523452ee7586 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 16:01:02 -0700 Subject: [PATCH 120/860] clippy: if_same_then_else --- examples/cat-file.rs | 4 +--- examples/status.rs | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/examples/cat-file.rs b/examples/cat-file.rs index d9be6c068e..030bb967d5 100644 --- a/examples/cat-file.rs +++ b/examples/cat-file.rs @@ -46,9 +46,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { if args.flag_t { println!("{}", obj.kind().unwrap().str()); - } else if args.flag_s { - /* ... */ - } else if args.flag_e { + } else if args.flag_s || args.flag_e { /* ... */ } else if args.flag_p { match obj.kind() { diff --git a/examples/status.rs b/examples/status.rs index 9cef064056..ed70c356d3 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -297,9 +297,7 @@ fn print_short(repo: &Repository, statuses: git2::Statuses) { if let Some(status) = status { if status.contains(git2::SUBMODULE_STATUS_WD_MODIFIED) { extra = " (new commits)"; - } else if status.contains(git2::SUBMODULE_STATUS_WD_INDEX_MODIFIED) { - extra = " (modified content)"; - } else if status.contains(git2::SUBMODULE_STATUS_WD_WD_MODIFIED) { + } else if status.contains(git2::SUBMODULE_STATUS_WD_INDEX_MODIFIED) || status.contains(git2::SUBMODULE_STATUS_WD_WD_MODIFIED) { extra = " (modified content)"; } else if status.contains(git2::SUBMODULE_STATUS_WD_UNTRACKED) { extra = " (untracked content)"; @@ -338,9 +336,7 @@ fn print_short(repo: &Repository, statuses: git2::Statuses) { impl Args { fn format(&self) -> Format { if self.flag_short { Format::Short } - else if self.flag_long { Format::Long } - else if self.flag_porcelain { Format::Porcelain } - else if self.flag_z { Format::Porcelain } + else if self.flag_porcelain || self.flag_z { Format::Porcelain } else { Format::Long } } } From dee3728fa6481df291b4ba7e44332cbb61bb32a7 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 16:09:44 -0700 Subject: [PATCH 121/860] clippy: needless_pass_by_value --- examples/log.rs | 6 +++--- examples/status.rs | 14 +++++++------- src/transport.rs | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/log.rs b/examples/log.rs index 6f6997b106..92f72f0392 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -121,8 +121,8 @@ fn run(args: &Args) -> Result<(), Error> { } } } - if !sig_matches(commit.author(), &args.flag_author) { return None } - if !sig_matches(commit.committer(), &args.flag_committer) { return None } + if !sig_matches(&commit.author(), &args.flag_author) { return None } + if !sig_matches(&commit.committer(), &args.flag_committer) { return None } if !log_message_matches(commit.message(), &args.flag_grep) { return None } Some(Ok(commit)) }).skip(args.flag_skip.unwrap_or(0)).take(args.flag_max_count.unwrap_or(!0)); @@ -154,7 +154,7 @@ fn run(args: &Args) -> Result<(), Error> { Ok(()) } -fn sig_matches(sig: Signature, arg: &Option) -> bool { +fn sig_matches(sig: &Signature, arg: &Option) -> bool { match *arg { Some(ref s) => { sig.name().map(|n| n.contains(s)).unwrap_or(false) || diff --git a/examples/status.rs b/examples/status.rs index ed70c356d3..57494f6ad8 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -78,16 +78,16 @@ fn run(args: &Args) -> Result<(), Error> { let statuses = try!(repo.statuses(Some(&mut opts))); if args.flag_branch { - try!(show_branch(&repo, args.format())); + try!(show_branch(&repo, &args.format())); } if args.flag_list_submodules { try!(print_submodules(&repo)); } if args.format() == Format::Long { - print_long(statuses); + print_long(&statuses); } else { - print_short(&repo, statuses); + print_short(&repo, &statuses); } if args.flag_repeat { @@ -98,7 +98,7 @@ fn run(args: &Args) -> Result<(), Error> { } } -fn show_branch(repo: &Repository, format: Format) -> Result<(), Error> { +fn show_branch(repo: &Repository, format: &Format) -> Result<(), Error> { let head = match repo.head() { Ok(head) => Some(head), Err(ref e) if e.code() == ErrorCode::UnbornBranch || @@ -107,7 +107,7 @@ fn show_branch(repo: &Repository, format: Format) -> Result<(), Error> { }; let head = head.as_ref().and_then(|h| h.shorthand()); - if format == Format::Long { + if format == &Format::Long { println!("# On branch {}", head.unwrap_or("Not currently on any branch")); } else { @@ -128,7 +128,7 @@ fn print_submodules(repo: &Repository) -> Result<(), Error> { // This function print out an output similar to git's status command in long // form, including the command-line hints. -fn print_long(statuses: git2::Statuses) { +fn print_long(statuses: &git2::Statuses) { let mut header = false; let mut rm_in_workdir = false; let mut changes_in_index = false; @@ -256,7 +256,7 @@ fn print_long(statuses: git2::Statuses) { // This version of the output prefixes each path with two status columns and // shows submodule status information. -fn print_short(repo: &Repository, statuses: git2::Statuses) { +fn print_short(repo: &Repository, statuses: &git2::Statuses) { for entry in statuses.iter().filter(|e| e.status() != git2::STATUS_CURRENT) { let mut istatus = match entry.status() { s if s.contains(git2::STATUS_INDEX_NEW) => 'A', diff --git a/src/transport.rs b/src/transport.rs index 02b8c0d5cf..1b9dbd5a5c 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -290,7 +290,7 @@ extern fn stream_read(stream: *mut raw::git_smart_subtransport_stream, }); match ret { Some(Ok(_)) => 0, - Some(Err(e)) => unsafe { set_err(e); -2 }, + Some(Err(e)) => unsafe { set_err(&e); -2 }, None => -1, } } @@ -307,12 +307,12 @@ extern fn stream_write(stream: *mut raw::git_smart_subtransport_stream, }); match ret { Some(Ok(())) => 0, - Some(Err(e)) => unsafe { set_err(e); -2 }, + Some(Err(e)) => unsafe { set_err(&e); -2 }, None => -1, } } -unsafe fn set_err(e: io::Error) { +unsafe fn set_err(e: &io::Error) { let s = CString::new(e.to_string()).unwrap(); raw::giterr_set_str(raw::GITERR_NET as c_int, s.as_ptr()) } From ae0b2b190d9553b610030ec552afa26099495c81 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 16:12:16 -0700 Subject: [PATCH 122/860] clippy: explicit_iter_loop --- examples/log.rs | 4 ++-- examples/status.rs | 4 ++-- src/cred.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/log.rs b/examples/log.rs index 92f72f0392..b39883fccf 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -60,7 +60,7 @@ fn run(args: &Args) -> Result<(), Error> { } else { git2::SORT_NONE }); - for commit in args.arg_commit.iter() { + for commit in &args.arg_commit { if commit.starts_with('^') { let obj = try!(repo.revparse_single(&commit[1..])); try!(revwalk.hide(obj.id())); @@ -87,7 +87,7 @@ fn run(args: &Args) -> Result<(), Error> { // Prepare our diff options and pathspec matcher let (mut diffopts, mut diffopts2) = (DiffOptions::new(), DiffOptions::new()); - for spec in args.arg_spec.iter() { + for spec in &args.arg_spec { diffopts.pathspec(spec); diffopts2.pathspec(spec); } diff --git a/examples/status.rs b/examples/status.rs index 57494f6ad8..175266b2c3 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -66,7 +66,7 @@ fn run(args: &Args) -> Result<(), Error> { None => {} } opts.include_untracked(!args.flag_ignored); - for spec in args.arg_spec.iter() { + for spec in &args.arg_spec { opts.pathspec(spec); } @@ -119,7 +119,7 @@ fn show_branch(repo: &Repository, format: &Format) -> Result<(), Error> { fn print_submodules(repo: &Repository) -> Result<(), Error> { let modules = try!(repo.submodules()); println!("# Submodules"); - for sm in modules.iter() { + for sm in &modules { println!("# - submodule '{}' at {}", sm.name().unwrap(), sm.path().display()); } diff --git a/src/cred.rs b/src/cred.rs index 70a5816892..3848f11d7b 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -265,7 +265,7 @@ impl CredentialHelper { pub fn execute(&self) -> Option<(String, String)> { let mut username = self.username.clone(); let mut password = None; - for cmd in self.commands.iter() { + for cmd in &self.commands { let (u, p) = self.execute_cmd(&cmd, &username); if u.is_some() && username.is_none() { username = u; From 174bdb2da16724017850f70cf0388ab19c9d036e Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 16:15:05 -0700 Subject: [PATCH 123/860] clippy: dead_code --- examples/status.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/status.rs b/examples/status.rs index 175266b2c3..1f0d1f12c6 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -27,7 +27,6 @@ use git2::{Repository, Error, StatusOptions, ErrorCode, SubmoduleIgnore}; struct Args { arg_spec: Vec, flag_short: bool, - flag_long: bool, flag_porcelain: bool, flag_branch: bool, flag_z: bool, From cda8a5cd8fc8bbec783e0185dcdeabb2af9cbcff Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 16:18:29 -0700 Subject: [PATCH 124/860] clippy: assign_op_pattern --- examples/diff.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/diff.rs b/examples/diff.rs index 994404da2f..ddc1cb806b 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -186,16 +186,16 @@ fn print_stats(diff: &Diff, args: &Args) -> Result<(), Error> { let stats = try!(diff.stats()); let mut format = git2::DIFF_STATS_NONE; if args.flag_stat { - format = format | git2::DIFF_STATS_FULL; + format |= git2::DIFF_STATS_FULL; } if args.flag_shortstat { - format = format | git2::DIFF_STATS_SHORT; + format |= git2::DIFF_STATS_SHORT; } if args.flag_numstat { - format = format | git2::DIFF_STATS_NUMBER; + format |= git2::DIFF_STATS_NUMBER; } if args.flag_summary { - format = format | git2::DIFF_STATS_INCLUDE_SUMMARY; + format |= git2::DIFF_STATS_INCLUDE_SUMMARY; } let buf = try!(stats.to_buf(format, 80)); print!("{}", str::from_utf8(&*buf).unwrap()); From a3a8bfc82927d50de0a2ade2c14b17f5083c8916 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 16:16:49 -0700 Subject: [PATCH 125/860] clippy: match_same_arms --- examples/diff.rs | 9 +++------ src/diff.rs | 1 - src/error.rs | 5 ----- src/stash.rs | 1 - 4 files changed, 3 insertions(+), 13 deletions(-) diff --git a/examples/diff.rs b/examples/diff.rs index ddc1cb806b..35c99d072d 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -152,10 +152,8 @@ fn run(args: &Args) -> Result<(), Error> { try!(diff.print(args.diff_format(), |_delta, _hunk, line| { if args.color() { let next = match line.origin() { - '+' => Some(GREEN), - '-' => Some(RED), - '>' => Some(GREEN), - '<' => Some(RED), + '+' | '>' => Some(GREEN), + '-' | '<' => Some(RED), 'F' => Some(BOLD), 'H' => Some(CYAN), _ => None @@ -226,8 +224,7 @@ impl Args { match self.flag_format.as_ref().map(|s| &s[..]) { Some("name") => DiffFormat::NameOnly, Some("name-status") => DiffFormat::NameStatus, - Some("raw") => DiffFormat::Raw, - Some("diff-index") => DiffFormat::Raw, + Some("raw") | Some("diff-index") => DiffFormat::Raw, _ => DiffFormat::Patch, } } diff --git a/src/diff.rs b/src/diff.rs index 5f5c62d3dd..74c45ba78d 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -769,7 +769,6 @@ impl<'a> DiffLine<'a> { /// * `B` - Line binary pub fn origin(&self) -> char { match unsafe { (*self.raw).origin as raw::git_diff_line_t } { - raw::GIT_DIFF_LINE_CONTEXT => ' ', raw::GIT_DIFF_LINE_ADDITION => '+', raw::GIT_DIFF_LINE_DELETION => '-', raw::GIT_DIFF_LINE_CONTEXT_EOFNL => '=', diff --git a/src/error.rs b/src/error.rs index 7d8f42c843..399661ede6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -47,8 +47,6 @@ impl Error { /// Return the error code associated with this error. pub fn code(&self) -> ErrorCode { match self.raw_code() { - raw::GIT_OK => super::ErrorCode::GenericError, - raw::GIT_ERROR => super::ErrorCode::GenericError, raw::GIT_ENOTFOUND => super::ErrorCode::NotFound, raw::GIT_EEXISTS => super::ErrorCode::Exists, raw::GIT_EAMBIGUOUS => super::ErrorCode::Ambiguous, @@ -62,8 +60,6 @@ impl Error { raw::GIT_ECONFLICT => super::ErrorCode::Conflict, raw::GIT_ELOCKED => super::ErrorCode::Locked, raw::GIT_EMODIFIED => super::ErrorCode::Modified, - raw::GIT_PASSTHROUGH => super::ErrorCode::GenericError, - raw::GIT_ITEROVER => super::ErrorCode::GenericError, raw::GIT_EAUTH => super::ErrorCode::Auth, raw::GIT_ECERTIFICATE => super::ErrorCode::Certificate, raw::GIT_EAPPLIED => super::ErrorCode::Applied, @@ -79,7 +75,6 @@ impl Error { /// Return the error class associated with this error. pub fn class(&self) -> ErrorClass { match self.raw_class() { - raw::GITERR_NONE => super::ErrorClass::None, raw::GITERR_NOMEMORY => super::ErrorClass::NoMemory, raw::GITERR_OS => super::ErrorClass::Os, raw::GITERR_INVALID => super::ErrorClass::Invalid, diff --git a/src/stash.rs b/src/stash.rs index b1d04f1aae..ac3c423222 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -106,7 +106,6 @@ pub extern fn stash_cb(index: size_t, fn convert_progress(progress: raw::git_stash_apply_progress_t) -> StashApplyProgress { match progress { - raw::GIT_STASH_APPLY_PROGRESS_NONE => StashApplyProgress::None, raw::GIT_STASH_APPLY_PROGRESS_LOADING_STASH => StashApplyProgress::LoadingStash, raw::GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX => StashApplyProgress::AnalyzeIndex, raw::GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED => StashApplyProgress::AnalyzeModified, From 7c92094b7fad6909595a429007b73e3e1d42c27a Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 16:40:30 -0700 Subject: [PATCH 126/860] clippy: len_zero --- examples/log.rs | 4 ++-- src/build.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/log.rs b/examples/log.rs index b39883fccf..d537e5ffc8 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -81,7 +81,7 @@ fn run(args: &Args) -> Result<(), Error> { try!(revwalk.hide(from)); } } - if args.arg_commit.len() == 0 { + if args.arg_commit.is_empty() { try!(revwalk.push_head()); } @@ -105,7 +105,7 @@ fn run(args: &Args) -> Result<(), Error> { if let Some(n) = args.max_parents() { if parents >= n { return None } } - if args.arg_spec.len() > 0 { + if !args.arg_spec.is_empty() { match commit.parents().len() { 0 => { let tree = filter_try!(commit.tree()); diff --git a/src/build.rs b/src/build.rs index ca4c8aab7c..155b0c5dd7 100644 --- a/src/build.rs +++ b/src/build.rs @@ -436,7 +436,7 @@ impl<'cb> CheckoutBuilder<'cb> { opts.dir_mode = self.dir_perm.unwrap_or(0) as c_uint; opts.file_mode = self.file_perm.unwrap_or(0) as c_uint; - if self.path_ptrs.len() > 0 { + if !self.path_ptrs.is_empty() { opts.paths.strings = self.path_ptrs.as_ptr() as *mut _; opts.paths.count = self.path_ptrs.len() as size_t; } From acd17f996a40470d5495c3cde55007fa5b1e5034 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 16:48:08 -0700 Subject: [PATCH 127/860] clippy: logic_bug (unsure) --- examples/clone.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/clone.rs b/examples/clone.rs index 8c2bad6f15..bef7c3cda1 100644 --- a/examples/clone.rs +++ b/examples/clone.rs @@ -49,7 +49,7 @@ fn print(state: &mut State) { 0 }; let kbytes = stats.received_bytes() / 1024; - if stats.received_objects() == stats.total_objects() && false { + if stats.received_objects() == stats.total_objects() { if !state.newline { println!(""); state.newline = true; From 3a6af7f63818f07219345a7ae99a087b8ca754eb Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 17:03:42 -0700 Subject: [PATCH 128/860] clippy: len_without_is_empty add `.is_empty()` method to TreeBuilder, Tree, Statuses, Reflog, Index, StringArray, Blame. --- src/blame.rs | 5 +++++ src/index.rs | 5 +++++ src/reflog.rs | 5 +++++ src/status.rs | 5 +++++ src/string_array.rs | 3 +++ src/tree.rs | 5 +++++ src/treebuilder.rs | 5 +++++ 7 files changed, 33 insertions(+) diff --git a/src/blame.rs b/src/blame.rs index 60c23f9c0c..9f6b15571c 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -35,6 +35,11 @@ impl<'repo> Blame<'repo> { unsafe { raw::git_blame_get_hunk_count(self.raw) as usize } } + /// Return `true` is there is no hunk in the blame structure. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Gets the blame hunk at the given index. pub fn get_index(&self, index: usize) -> Option { unsafe { diff --git a/src/index.rs b/src/index.rs index 356505a8c2..8d5172e61f 100644 --- a/src/index.rs +++ b/src/index.rs @@ -225,6 +225,11 @@ impl Index { unsafe { raw::git_index_entrycount(&*self.raw) as usize } } + /// Return `true` is there is no entry in the index + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Get one of the entries in the index by its position. pub fn get(&self, n: usize) -> Option { unsafe { diff --git a/src/reflog.rs b/src/reflog.rs index 69e40f8e30..6996a89dae 100644 --- a/src/reflog.rs +++ b/src/reflog.rs @@ -66,6 +66,11 @@ impl Reflog { unsafe { raw::git_reflog_entrycount(self.raw) as usize } } + /// Return `true ` is there is no log entry in a reflog + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Get an iterator to all entries inside of this reflog pub fn iter(&self) -> ReflogIter { ReflogIter { range: 0..self.len(), reflog: self } diff --git a/src/status.rs b/src/status.rs index 8418d72d2e..d8a1abe201 100644 --- a/src/status.rs +++ b/src/status.rs @@ -258,6 +258,11 @@ impl<'repo> Statuses<'repo> { unsafe { raw::git_status_list_entrycount(self.raw) as usize } } + /// Return `true` is there is not status entry in this list. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Returns an iterator over the statuses in this list. pub fn iter(&self) -> StatusIter { StatusIter { diff --git a/src/string_array.rs b/src/string_array.rs index 60a209a0c7..6ed6cc91ff 100644 --- a/src/string_array.rs +++ b/src/string_array.rs @@ -61,6 +61,9 @@ impl StringArray { /// Returns the number of strings in this array. pub fn len(&self) -> usize { self.raw.count as usize } + + /// Return `true` if this array is empty. + pub fn is_empty(&self) -> bool { self.len() == 0 } } impl Binding for StringArray { diff --git a/src/tree.rs b/src/tree.rs index 3d361ed1c0..a7aaed235b 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -44,6 +44,11 @@ impl<'repo> Tree<'repo> { unsafe { raw::git_tree_entrycount(&*self.raw) as usize } } + /// Return `true` if there is not entry + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Returns an iterator over the entries in this tree. pub fn iter(&self) -> TreeIter { TreeIter { range: 0..self.len(), tree: self } diff --git a/src/treebuilder.rs b/src/treebuilder.rs index 779f6f30f2..e8ea1057c4 100644 --- a/src/treebuilder.rs +++ b/src/treebuilder.rs @@ -23,6 +23,11 @@ impl<'repo> TreeBuilder<'repo> { unsafe { raw::git_treebuilder_entrycount(self.raw) as usize } } + /// Return `true` if there is no entry + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Get en entry from the builder from its filename pub fn get

(&self, filename: P) -> Result, Error> where P: IntoCString From dcb1ddf5a28aa1cfba7d37b49e1356222a6d07fa Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 17:21:59 -0700 Subject: [PATCH 129/860] clippy: redundant_closure --- src/remote.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/remote.rs b/src/remote.rs index 3dd87cee7b..2324803f59 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -127,8 +127,8 @@ impl<'repo> Remote<'repo> { proxy_options: Option>) -> Result, Error> { - let cb = Box::new(cb.unwrap_or_else(|| RemoteCallbacks::new())); - let proxy_options = proxy_options.unwrap_or_else(|| ProxyOptions::new()); + let cb = Box::new(cb.unwrap_or_else(RemoteCallbacks::new)); + let proxy_options = proxy_options.unwrap_or_else(ProxyOptions::new); unsafe { try_call!(raw::git_remote_connect(self.raw, dir, &cb.raw(), From 5f0c936e2eca230d639cce720e35deaabbb40344 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 17:28:05 -0700 Subject: [PATCH 130/860] clippy: expl_impl_clone_on_copy (unsure) --- src/oid.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/oid.rs b/src/oid.rs index 4d08b88ca4..26e0cc70c9 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -8,7 +8,7 @@ use {raw, Error}; use util::Binding; /// Unique identity of any object (commit, tree, blob, tag). -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Oid { raw: raw::git_oid, } @@ -116,10 +116,6 @@ impl Ord for Oid { } } -impl Clone for Oid { - fn clone(&self) -> Oid { *self } -} - impl Hash for Oid { fn hash(&self, into: &mut H) { self.raw.id.hash(into) From f0654a557e1fe14db44d0861e4a8b0c285bfdcb9 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 17:29:15 -0700 Subject: [PATCH 131/860] clippy: char_lit_as_u8 --- src/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/message.rs b/src/message.rs index bdfccf6515..1651e8281f 100644 --- a/src/message.rs +++ b/src/message.rs @@ -25,7 +25,7 @@ fn _message_prettify(message: CString, comment_char: Option) } /// The default comment character for message_prettify ('#') -pub const DEFAULT_COMMENT_CHAR: Option = Some('#' as u8); +pub const DEFAULT_COMMENT_CHAR: Option = Some(b'#'); #[cfg(test)] mod tests { From f395212091fcef2190aea4b1263c7ee466b57d83 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 15:52:37 -0700 Subject: [PATCH 132/860] clippy: needless_borrow --- examples/init.rs | 2 +- examples/log.rs | 2 +- examples/status.rs | 4 ++-- examples/tag.rs | 4 ++-- src/cred.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/init.rs b/examples/init.rs index 2f1f28a496..ecff5d9efe 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -55,7 +55,7 @@ fn run(args: &Args) -> Result<(), Error> { } if let Some(ref s) = args.flag_shared { - opts.mode(try!(parse_shared(&s))); + opts.mode(try!(parse_shared(s))); } try!(Repository::init_opts(&path, &opts)) }; diff --git a/examples/log.rs b/examples/log.rs index d537e5ffc8..6036218a08 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -66,7 +66,7 @@ fn run(args: &Args) -> Result<(), Error> { try!(revwalk.hide(obj.id())); continue } - let revspec = try!(repo.revparse(&commit)); + let revspec = try!(repo.revparse(commit)); if revspec.mode().contains(git2::REVPARSE_SINGLE) { try!(revwalk.push(revspec.from().unwrap().id())); } else { diff --git a/examples/status.rs b/examples/status.rs index 1f0d1f12c6..cdf2c2412e 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -157,7 +157,7 @@ fn print_long(statuses: &git2::Statuses) { let old_path = entry.head_to_index().unwrap().old_file().path(); let new_path = entry.head_to_index().unwrap().new_file().path(); match (old_path, new_path) { - (Some(ref old), Some(ref new)) if old != new => { + (Some(old), Some(new)) if old != new => { println!("#\t{} {} -> {}", istatus, old.display(), new.display()); } @@ -204,7 +204,7 @@ fn print_long(statuses: &git2::Statuses) { let old_path = entry.index_to_workdir().unwrap().old_file().path(); let new_path = entry.index_to_workdir().unwrap().new_file().path(); match (old_path, new_path) { - (Some(ref old), Some(ref new)) if old != new => { + (Some(old), Some(new)) if old != new => { println!("#\t{} {} -> {}", istatus, old.display(), new.display()); } diff --git a/examples/tag.rs b/examples/tag.rs index a584908d09..4a8b385e89 100644 --- a/examples/tag.rs +++ b/examples/tag.rs @@ -43,9 +43,9 @@ fn run(args: &Args) -> Result<(), Error> { if let Some(ref message) = args.flag_message { let sig = try!(repo.signature()); - try!(repo.tag(&name, &obj, &sig, &message, args.flag_force)); + try!(repo.tag(name, &obj, &sig, message, args.flag_force)); } else { - try!(repo.tag_lightweight(&name, &obj, args.flag_force)); + try!(repo.tag_lightweight(name, &obj, args.flag_force)); } } else if let Some(ref name) = args.flag_delete { diff --git a/src/cred.rs b/src/cred.rs index 3848f11d7b..61591daae8 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -266,7 +266,7 @@ impl CredentialHelper { let mut username = self.username.clone(); let mut password = None; for cmd in &self.commands { - let (u, p) = self.execute_cmd(&cmd, &username); + let (u, p) = self.execute_cmd(cmd, &username); if u.is_some() && username.is_none() { username = u; } From 7bb584df61b9ff27c817be0a40ffdf10e91038be Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 27 May 2017 18:04:36 -0700 Subject: [PATCH 133/860] clippy: needless_bool --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.rs b/src/config.rs index c1102130ac..32c148cd64 100644 --- a/src/config.rs +++ b/src/config.rs @@ -147,7 +147,7 @@ impl Config { try_call!(raw::git_config_get_bool(&mut out, &*self.raw, name)); } - Ok(if out == 0 {false} else {true}) + Ok(!(out == 0)) } /// Get the value of an integer config variable. From 7d04a224c5e8deafcfe7a96011f62a431293c807 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Tue, 30 May 2017 07:50:42 -0700 Subject: [PATCH 134/860] clippy: doc_markdown --- src/message.rs | 4 ++-- src/oid_array.rs | 2 +- src/packbuilder.rs | 2 +- src/string_array.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/message.rs b/src/message.rs index 1651e8281f..96cdd589cb 100644 --- a/src/message.rs +++ b/src/message.rs @@ -6,7 +6,7 @@ use {raw, Buf, Error, IntoCString}; use util::Binding; /// Clean up a message, removing extraneous whitespace, and ensure that the -/// message ends with a newline. If comment_char is Some, also remove comment +/// message ends with a newline. If `comment_char` is `Some`, also remove comment /// lines starting with that character. pub fn message_prettify(message: T, comment_char: Option) -> Result { @@ -24,7 +24,7 @@ fn _message_prettify(message: CString, comment_char: Option) Ok(ret.as_str().unwrap().to_string()) } -/// The default comment character for message_prettify ('#') +/// The default comment character for `message_prettify` ('#') pub const DEFAULT_COMMENT_CHAR: Option = Some(b'#'); #[cfg(test)] diff --git a/src/oid_array.rs b/src/oid_array.rs index 314753883c..7533357dcd 100644 --- a/src/oid_array.rs +++ b/src/oid_array.rs @@ -1,4 +1,4 @@ -//! Bindings to libgit2's raw git_strarray type +//! Bindings to libgit2's raw `git_strarray` type use std::ops::Deref; diff --git a/src/packbuilder.rs b/src/packbuilder.rs index bfe118eefb..e3ed5132b6 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -6,7 +6,7 @@ use libc::{c_int, c_uint, c_void, size_t}; use {raw, panic, Repository, Error, Oid, Revwalk, Buf}; use util::Binding; -/// Stages that are reported by the PackBuilder progress callback. +/// Stages that are reported by the `PackBuilder` progress callback. pub enum PackBuilderStage { /// Adding objects to the pack AddingObjects, diff --git a/src/string_array.rs b/src/string_array.rs index 6ed6cc91ff..a77269338e 100644 --- a/src/string_array.rs +++ b/src/string_array.rs @@ -1,4 +1,4 @@ -//! Bindings to libgit2's raw git_strarray type +//! Bindings to libgit2's raw `git_strarray` type use std::str; use std::ops::Range; From 59626918423471322303e3043ba498f382ec1a80 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Tue, 30 May 2017 08:39:19 -0700 Subject: [PATCH 135/860] fix unused import on windows --- src/test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test.rs b/src/test.rs index 02cea2d903..4f8813fdad 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,5 +1,6 @@ use std::path::{Path, PathBuf}; use std::io; +#[cfg(unix)] use std::ptr; use tempdir::TempDir; use url::Url; From bdc5fb38a2fb3a0fd598f160dd11b4e51b30952c Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Tue, 30 May 2017 11:01:45 -0700 Subject: [PATCH 136/860] Revert "clippy: match_same_arms" This reverts commit a3a8bfc82927d50de0a2ade2c14b17f5083c8916. --- examples/diff.rs | 9 ++++++--- src/diff.rs | 1 + src/error.rs | 5 +++++ src/stash.rs | 1 + 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/examples/diff.rs b/examples/diff.rs index 35c99d072d..ddc1cb806b 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -152,8 +152,10 @@ fn run(args: &Args) -> Result<(), Error> { try!(diff.print(args.diff_format(), |_delta, _hunk, line| { if args.color() { let next = match line.origin() { - '+' | '>' => Some(GREEN), - '-' | '<' => Some(RED), + '+' => Some(GREEN), + '-' => Some(RED), + '>' => Some(GREEN), + '<' => Some(RED), 'F' => Some(BOLD), 'H' => Some(CYAN), _ => None @@ -224,7 +226,8 @@ impl Args { match self.flag_format.as_ref().map(|s| &s[..]) { Some("name") => DiffFormat::NameOnly, Some("name-status") => DiffFormat::NameStatus, - Some("raw") | Some("diff-index") => DiffFormat::Raw, + Some("raw") => DiffFormat::Raw, + Some("diff-index") => DiffFormat::Raw, _ => DiffFormat::Patch, } } diff --git a/src/diff.rs b/src/diff.rs index 74c45ba78d..5f5c62d3dd 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -769,6 +769,7 @@ impl<'a> DiffLine<'a> { /// * `B` - Line binary pub fn origin(&self) -> char { match unsafe { (*self.raw).origin as raw::git_diff_line_t } { + raw::GIT_DIFF_LINE_CONTEXT => ' ', raw::GIT_DIFF_LINE_ADDITION => '+', raw::GIT_DIFF_LINE_DELETION => '-', raw::GIT_DIFF_LINE_CONTEXT_EOFNL => '=', diff --git a/src/error.rs b/src/error.rs index 399661ede6..7d8f42c843 100644 --- a/src/error.rs +++ b/src/error.rs @@ -47,6 +47,8 @@ impl Error { /// Return the error code associated with this error. pub fn code(&self) -> ErrorCode { match self.raw_code() { + raw::GIT_OK => super::ErrorCode::GenericError, + raw::GIT_ERROR => super::ErrorCode::GenericError, raw::GIT_ENOTFOUND => super::ErrorCode::NotFound, raw::GIT_EEXISTS => super::ErrorCode::Exists, raw::GIT_EAMBIGUOUS => super::ErrorCode::Ambiguous, @@ -60,6 +62,8 @@ impl Error { raw::GIT_ECONFLICT => super::ErrorCode::Conflict, raw::GIT_ELOCKED => super::ErrorCode::Locked, raw::GIT_EMODIFIED => super::ErrorCode::Modified, + raw::GIT_PASSTHROUGH => super::ErrorCode::GenericError, + raw::GIT_ITEROVER => super::ErrorCode::GenericError, raw::GIT_EAUTH => super::ErrorCode::Auth, raw::GIT_ECERTIFICATE => super::ErrorCode::Certificate, raw::GIT_EAPPLIED => super::ErrorCode::Applied, @@ -75,6 +79,7 @@ impl Error { /// Return the error class associated with this error. pub fn class(&self) -> ErrorClass { match self.raw_class() { + raw::GITERR_NONE => super::ErrorClass::None, raw::GITERR_NOMEMORY => super::ErrorClass::NoMemory, raw::GITERR_OS => super::ErrorClass::Os, raw::GITERR_INVALID => super::ErrorClass::Invalid, diff --git a/src/stash.rs b/src/stash.rs index ac3c423222..b1d04f1aae 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -106,6 +106,7 @@ pub extern fn stash_cb(index: size_t, fn convert_progress(progress: raw::git_stash_apply_progress_t) -> StashApplyProgress { match progress { + raw::GIT_STASH_APPLY_PROGRESS_NONE => StashApplyProgress::None, raw::GIT_STASH_APPLY_PROGRESS_LOADING_STASH => StashApplyProgress::LoadingStash, raw::GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX => StashApplyProgress::AnalyzeIndex, raw::GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED => StashApplyProgress::AnalyzeModified, From 81114c6bbe2cd633c7fe7efdd399960574df9bef Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Tue, 30 May 2017 11:03:55 -0700 Subject: [PATCH 137/860] fix 39ce54d034f049542a13c5a6ce73f9c5b359fb0c --- examples/status.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/status.rs b/examples/status.rs index cdf2c2412e..c0b57fcd83 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -309,8 +309,8 @@ fn print_short(repo: &Repository, statuses: &git2::Statuses) { b = diff.new_file().path(); } if let Some(diff) = entry.index_to_workdir() { - a.or_else(|| diff.old_file().path()); - b.or_else(|| diff.old_file().path()); + a = a.or_else(|| diff.old_file().path()); + b = b.or_else(|| diff.old_file().path()); c = diff.new_file().path(); } From dcbd9b8f30780b9eff455d22db64e4760b7d15e2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 31 May 2017 14:20:33 -0700 Subject: [PATCH 138/860] Fix compile on MSVC --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 25e66296f9..dcd2d85bc8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -491,7 +491,7 @@ bitflags! { const MERGE_ANALYSIS_NORMAL = raw::GIT_MERGE_ANALYSIS_NORMAL as u32; /// All given merge inputs are reachable from HEAD, meaning the /// repository is up-to-date and no merge needs to be performed. - const MERGE_ANALYSIS_UP_TO_DATE = raw::GIT_MERGE_ANALYSIS_UP_TO_DATE as u32; + const MERGE_ANALYSIS_UP_TO_DATE = raw::GIT_MERGE_ANALYSIS_UP_TO_DATE as u32; /// The given merge input is a fast-forward from HEAD and no merge /// needs to be performed. Instead, the client can check out the /// given merge input. @@ -508,13 +508,13 @@ bitflags! { pub struct MergePreference: u32 { /// No configuration was found that suggests a preferred behavior for /// merge. - const MERGE_PREFERENCE_NONE = raw::GIT_MERGE_PREFERENCE_NONE; + const MERGE_PREFERENCE_NONE = raw::GIT_MERGE_PREFERENCE_NONE as u32; /// There is a `merge.ff=false` configuration setting, suggesting that /// the user does not want to allow a fast-forward merge. - const MERGE_PREFERENCE_NO_FAST_FORWARD = raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD; + const MERGE_PREFERENCE_NO_FAST_FORWARD = raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD as u32; /// There is a `merge.ff=only` configuration setting, suggesting that /// the user only wants fast-forward merges. - const MERGE_PREFERENCE_FASTFORWARD_ONLY = raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY; + const MERGE_PREFERENCE_FASTFORWARD_ONLY = raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY as u32; } } From c477b3738b6e56c53ebe3fee0a1cde2ec2cdbeb0 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Wed, 7 Jun 2017 08:53:05 +0200 Subject: [PATCH 139/860] libgit2-sys: update libgit2 to fix build with libressl Fixes #212 Signed-off-by: Marc-Antoine Perennou --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index a1023a4302..40139fe6e6 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit a1023a43027207ac7a5df7233bddfe7347bee256 +Subproject commit 40139fe6e62e487e6ccae26df6f9b1ddc9b30b36 From 52a86a1cf5c4cda829266ec4e1a8c7fa817801ed Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Wed, 7 Jun 2017 16:52:36 +0200 Subject: [PATCH 140/860] Fix build with MSVC Signed-off-by: Marc-Antoine Perennou --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 79c1a56a2f..811ec4bd21 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1348,7 +1348,7 @@ impl Repository { self.raw, their_heads.as_mut_ptr() as *mut _, their_heads.len())); - Ok((MergeAnalysis::from_bits_truncate(raw_merge_analysis), MergePreference::from_bits_truncate(raw_merge_preference))) + Ok((MergeAnalysis::from_bits_truncate(raw_merge_analysis as u32), MergePreference::from_bits_truncate(raw_merge_preference as u32))) } } From 50f2a2c6c5df6864a7d8e350b0be1f74ad7c6492 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 7 Jun 2017 12:31:23 -0700 Subject: [PATCH 141/860] Bump to 0.6.12 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index ce516a655b..15814ee9c3 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.11" +version = "0.6.12" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 73b1d8eb147860531d5efe9625b683ff43052875 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 7 Jun 2017 12:32:13 -0700 Subject: [PATCH 142/860] Bump to 0.6.6 --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 655cf087dc..c6313a9239 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.5" +version = "0.6.6" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -24,7 +24,7 @@ appveyor = { repository = "alexcrichton/git2-rs" } url = "1.0" bitflags = "0.9" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.6.10" } +libgit2-sys = { path = "libgit2-sys", version = "0.6.12" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 6f3ae64d7be8bb68c7b019d0383db82b7de25d96 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Mon, 12 Jun 2017 13:01:51 +0200 Subject: [PATCH 143/860] libgit2-sys: update libgit2 to 0.26.0 rc1 Signed-off-by: Marc-Antoine Perennou --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 40139fe6e6..bd6928096d 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 40139fe6e62e487e6ccae26df6f9b1ddc9b30b36 +Subproject commit bd6928096d7a4c8f26b55a1e9ec710faeee7db93 From 139ac353ea166dfe09318e1bbb62fe0e15510b0e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 13 Jun 2017 06:58:44 -0700 Subject: [PATCH 144/860] Use updated curl to fix Windows CI --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 15814ee9c3..56eb158daf 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -14,7 +14,7 @@ name = "libgit2_sys" path = "lib.rs" [dependencies] -curl-sys = { version = "0.3", optional = true } +curl-sys = { git = 'https://github.com/alexcrichton/curl-rust', optional = true } libc = "0.2" libssh2-sys = { version = "0.2.4", optional = true } libz-sys = ">= 0" From 421817e0450e8a708532442b6cb35f4d02820722 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 13 Jun 2017 10:16:44 -0700 Subject: [PATCH 145/860] Curl's now fixed! --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 56eb158daf..d78e95698b 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -14,7 +14,7 @@ name = "libgit2_sys" path = "lib.rs" [dependencies] -curl-sys = { git = 'https://github.com/alexcrichton/curl-rust', optional = true } +curl-sys = { version = "0.3.12", optional = true } libc = "0.2" libssh2-sys = { version = "0.2.4", optional = true } libz-sys = ">= 0" From 4f682bd3a4f7ef0c6546bd9f91e1afe574e24d40 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Wed, 21 Jun 2017 08:55:36 +0200 Subject: [PATCH 146/860] libgit2-sys: update libgit2 to 0.26.0 Signed-off-by: Marc-Antoine Perennou --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index bd6928096d..15e1193750 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit bd6928096d7a4c8f26b55a1e9ec710faeee7db93 +Subproject commit 15e119375018fba121cf58e02a9f17fe22df0df8 From 4e8ed99c5c31f4fffc0a203c8cb36bf82cae52e3 Mon Sep 17 00:00:00 2001 From: Stephane Raux Date: Fri, 23 Jun 2017 23:28:06 -0700 Subject: [PATCH 147/860] Added ability to update a submodule This wraps `git_submodule_update`. --- libgit2-sys/lib.rs | 27 ++++++++++----- src/submodule.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 9 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 79939cd9df..4641c95e85 100755 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -22,6 +22,7 @@ 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; +pub const GIT_SUBMODULE_UPDATE_OPTIONS_VERSION: c_uint = 1; macro_rules! git_enum { (pub enum $name:ident { $($variants:tt)* }) => { @@ -799,6 +800,14 @@ pub type git_submodule_cb = extern fn(*mut git_submodule, *const c_char, *mut c_void) -> c_int; +#[repr(C)] +pub struct git_submodule_update_options { + pub version: c_uint, + pub checkout_opts: git_checkout_options, + pub fetch_opts: git_fetch_options, + pub allow_fetch: c_int, +} + #[repr(C)] pub struct git_cred { pub credtype: git_credtype_t, @@ -1793,10 +1802,12 @@ extern { pub fn git_submodule_sync(submodule: *mut git_submodule) -> c_int; pub fn git_submodule_update_strategy(submodule: *mut git_submodule) -> git_submodule_update_t; - // pub fn git_submodule_update(submodule: *mut git_submodule, - // init: c_int, - // options: *mut git_submodule_update_options) - // -> c_int; + pub fn git_submodule_update(submodule: *mut git_submodule, + init: c_int, + options: *mut git_submodule_update_options) + -> c_int; + pub fn git_submodule_update_init_options(options: *mut git_submodule_update_options, + version: c_uint) -> c_int; pub fn git_submodule_url(/service/submodule: *mut git_submodule) -> *const c_char; pub fn git_submodule_wd_id(submodule: *mut git_submodule) -> *const git_oid; pub fn git_submodule_status(status: *mut c_uint, @@ -2238,10 +2249,10 @@ extern { // merge analysis - pub fn git_merge_analysis(analysis_out: *mut git_merge_analysis_t, - pref_out: *mut git_merge_preference_t, - repo: *mut git_repository, - their_heads: *mut *const git_annotated_commit, + pub fn git_merge_analysis(analysis_out: *mut git_merge_analysis_t, + pref_out: *mut git_merge_preference_t, + repo: *mut git_repository, + their_heads: *mut *const git_annotated_commit, their_heads_len: usize) -> c_int; // notes diff --git a/src/submodule.rs b/src/submodule.rs index 234a8815e9..dfe272a6bd 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -1,9 +1,12 @@ use std::marker; +use std::mem; use std::ptr; use std::str; +use std::os::raw::c_int; use std::path::Path; -use {raw, Oid, Repository, Error}; +use {raw, Oid, Repository, Error, FetchOptions}; +use build::CheckoutBuilder; use util::{self, Binding}; /// A structure to represent a git [submodule][1] @@ -163,6 +166,26 @@ impl<'repo> Submodule<'repo> { unsafe { try_call!(raw::git_submodule_add_finalize(self.raw)); } Ok(()) } + + /// Update submodule. + /// + /// This will clone a missing submodule and check out the subrepository to + /// the commit specified in the index of the containing repository. If + /// the submodule repository doesn't contain the target commit, then the + /// submodule is fetched using the fetch options supplied in `opts`. + /// + /// `init` indicates if the submodule should be initialized first if it has + /// not been initialized yet. + pub fn update(&mut self, init: bool, + opts: Option<&mut SubmoduleUpdateOptions>) + -> Result<(), Error> { + unsafe { + let mut raw_opts = opts.map(|o| o.raw()); + try_call!(raw::git_submodule_update(self.raw, init as c_int, + raw_opts.as_mut().map_or(ptr::null_mut(), |o| o))); + } + Ok(()) + } } impl<'repo> Binding for Submodule<'repo> { @@ -179,6 +202,64 @@ impl<'repo> Drop for Submodule<'repo> { } } +/// Options to update a submodule. +pub struct SubmoduleUpdateOptions<'cb> { + checkout_builder: CheckoutBuilder<'cb>, + fetch_opts: FetchOptions<'cb>, + allow_fetch: bool, +} + +impl<'cb> SubmoduleUpdateOptions<'cb> { + /// Return default options. + pub fn new() -> Self { + SubmoduleUpdateOptions { + checkout_builder: CheckoutBuilder::new(), + fetch_opts: FetchOptions::new(), + allow_fetch: true, + } + } + + unsafe fn raw(&mut self) -> raw::git_submodule_update_options { + let mut checkout_opts: raw::git_checkout_options = mem::zeroed(); + let init_res = raw::git_checkout_init_options(&mut checkout_opts, + raw::GIT_CHECKOUT_OPTIONS_VERSION); + assert_eq!(0, init_res); + self.checkout_builder.configure(&mut checkout_opts); + let opts = raw::git_submodule_update_options { + version: raw::GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, + checkout_opts, + fetch_opts: self.fetch_opts.raw(), + allow_fetch: self.allow_fetch as c_int, + }; + opts + } + + /// Set checkout options. + pub fn checkout(&mut self, opts: CheckoutBuilder<'cb>) -> &mut Self { + self.checkout_builder = opts; + self + } + + /// Set fetch options and allow fetching. + pub fn fetch(&mut self, opts: FetchOptions<'cb>) -> &mut Self { + self.fetch_opts = opts; + self.allow_fetch = true; + self + } + + /// Allow or disallow fetching. + pub fn allow_fetch(&mut self, b: bool) -> &mut Self { + self.allow_fetch = b; + self + } +} + +impl<'cb> Default for SubmoduleUpdateOptions<'cb> { + fn default() -> Self { + Self::new() + } +} + #[cfg(test)] mod tests { use std::path::Path; From 4b21238a8394131448cbdc86040a736e81ef8b1a Mon Sep 17 00:00:00 2001 From: Stephane Raux Date: Sat, 24 Jun 2017 19:28:05 -0700 Subject: [PATCH 148/860] Fixed doc: `finalize` changed to `add_finalize` --- src/repo.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index 811ec4bd21..1c52541f93 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1060,8 +1060,8 @@ impl Repository { /// /// To fully emulate "git submodule add" call this function, then `open()` /// the submodule repo and perform the clone step as needed. Lastly, call - /// `finalize()` to wrap up adding the new submodule and `.gitmodules` to - /// the index to be ready to commit. + /// `add_finalize()` to wrap up adding the new submodule and `.gitmodules` + /// to the index to be ready to commit. pub fn submodule(&self, url: &str, path: &Path, use_gitlink: bool) -> Result { let url = try!(CString::new(url)); From 2a7253d86acfbb762fbc3b4bc619b9927ab752bf Mon Sep 17 00:00:00 2001 From: Stephane Raux Date: Fri, 30 Jun 2017 15:46:12 -0700 Subject: [PATCH 149/860] Added function to clone a repository recursively It is similar to `git clone --recursive`. The current implementation is very simple and limited as it does not allow to customize the fetch and checkout tasks and submodules are processed sequentially (i.e. no option like `--jobs` to process them concurrently). Addressing the limitations described above requires some thought: - `FetchOptions` and `CheckoutBuilder` are not `Send`. - Should different submodules have different options? - Are new options and callbacks needed? --- src/repo.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index 1c52541f93..c2d68e86f9 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -183,6 +183,39 @@ impl Repository { RepoBuilder::new().clone(url, into.as_ref()) } + /// Clone a remote repository, initialize and update its submodules + /// recursively. + /// + /// This is similar to `git clone --recursive`. + pub fn clone_recurse>(url: &str, into: P) + -> Result { + let repo = Repository::clone(url, into)?; + repo.update_submodules()?; + Ok(repo) + } + + /// Update submodules recursively. + /// + /// Uninitialized submodules will be initialized. + pub fn update_submodules(&self) -> Result<(), Error> { + + fn add_subrepos(repo: &Repository, list: &mut Vec) + -> Result<(), Error> { + for mut subm in repo.submodules()? { + subm.update(true, None)?; + list.push(subm.open()?); + } + Ok(()) + } + + let mut repos = Vec::new(); + add_subrepos(self, &mut repos)?; + while let Some(repo) = repos.pop() { + add_subrepos(&repo, &mut repos)?; + } + Ok(()) + } + /// Execute a rev-parse operation against the `spec` listed. /// /// The resulting revision specification is returned, or an error is From db95778cbf0844f90fd758f32620ba1569114734 Mon Sep 17 00:00:00 2001 From: Stephane Raux Date: Wed, 5 Jul 2017 17:20:42 -0700 Subject: [PATCH 150/860] Made `Repository::update_submodules` private --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index c2d68e86f9..a8730fcc8b 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -197,7 +197,7 @@ impl Repository { /// Update submodules recursively. /// /// Uninitialized submodules will be initialized. - pub fn update_submodules(&self) -> Result<(), Error> { + fn update_submodules(&self) -> Result<(), Error> { fn add_subrepos(repo: &Repository, list: &mut Vec) -> Result<(), Error> { From 60a49f46bd7df37221b46f29fb6e2e32822eeed1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 22 Jun 2017 08:11:02 -0700 Subject: [PATCH 151/860] Remove executable bit on lib.rs --- libgit2-sys/lib.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 libgit2-sys/lib.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs old mode 100755 new mode 100644 From de5820d2915ae4a055a57b92b257a91587fbd67f Mon Sep 17 00:00:00 2001 From: cssivision Date: Sat, 5 Aug 2017 11:47:16 +0800 Subject: [PATCH 152/860] Replace rustc-serialize with serde --- Cargo.toml | 5 +++-- examples/add.rs | 7 ++++--- examples/blame.rs | 7 ++++--- examples/cat-file.rs | 7 ++++--- examples/clone.rs | 7 ++++--- examples/diff.rs | 7 ++++--- examples/fetch.rs | 7 ++++--- examples/init.rs | 7 ++++--- examples/log.rs | 7 ++++--- examples/ls-remote.rs | 7 ++++--- examples/rev-list.rs | 7 ++++--- examples/rev-parse.rs | 7 ++++--- examples/status.rs | 7 ++++--- examples/tag.rs | 7 ++++--- 14 files changed, 55 insertions(+), 41 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c6313a9239..b39966f046 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,8 +31,9 @@ openssl-sys = { version = "0.9.0", optional = true } openssl-probe = { version = "0.1", optional = true } [dev-dependencies] -docopt = "0.6" -rustc-serialize = "0.3" +docopt = "0.8" +serde = "1.0" +serde_derive = "1.0" time = "0.1" tempdir = "0.3" diff --git a/examples/add.rs b/examples/add.rs index d4cb718f46..71082d09b3 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -17,13 +17,14 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use std::path::Path; use docopt::Docopt; use git2::Repository; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_spec: Vec, flag_dry_run: bool, @@ -75,7 +76,7 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/blame.rs b/examples/blame.rs index b51e223d9c..fcd890ad9c 100644 --- a/examples/blame.rs +++ b/examples/blame.rs @@ -14,14 +14,15 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use docopt::Docopt; use git2::{Repository, BlameOptions}; use std::path::Path; use std::io::{BufReader, BufRead}; -#[derive(RustcDecodable)] #[allow(non_snake_case)] +#[derive(Deserialize)] #[allow(non_snake_case)] struct Args { arg_path: String, arg_spec: Option, @@ -96,7 +97,7 @@ Options: -F follow only the first parent commits "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/cat-file.rs b/examples/cat-file.rs index 030bb967d5..68117bd88d 100644 --- a/examples/cat-file.rs +++ b/examples/cat-file.rs @@ -16,14 +16,15 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use std::io::{self, Write}; use docopt::Docopt; use git2::{Repository, ObjectType, Blob, Commit, Signature, Tag, Tree}; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_object: String, flag_t: bool, @@ -132,7 +133,7 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/clone.rs b/examples/clone.rs index bef7c3cda1..3bd72bc2eb 100644 --- a/examples/clone.rs +++ b/examples/clone.rs @@ -16,7 +16,8 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use docopt::Docopt; use git2::build::{RepoBuilder, CheckoutBuilder}; @@ -25,7 +26,7 @@ use std::cell::RefCell; use std::io::{self, Write}; use std::path::{Path, PathBuf}; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_url: String, arg_path: String, @@ -113,7 +114,7 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/diff.rs b/examples/diff.rs index ddc1cb806b..a743076925 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -16,7 +16,8 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use std::str; @@ -24,7 +25,7 @@ use docopt::Docopt; use git2::{Repository, Error, Object, ObjectType, DiffOptions, Diff}; use git2::{DiffFindOptions, DiffFormat}; -#[derive(RustcDecodable)] #[allow(non_snake_case)] +#[derive(Deserialize)] #[allow(non_snake_case)] struct Args { arg_from_oid: Option, arg_to_oid: Option, @@ -274,7 +275,7 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/fetch.rs b/examples/fetch.rs index 12719f973f..c667d7b633 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -16,14 +16,15 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use docopt::Docopt; use git2::{Repository, RemoteCallbacks, AutotagOption, FetchOptions}; use std::io::{self, Write}; use std::str; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_remote: Option, } @@ -118,7 +119,7 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/init.rs b/examples/init.rs index ecff5d9efe..ccdef76cc5 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -16,13 +16,14 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use docopt::Docopt; use git2::{Repository, RepositoryInitOptions, RepositoryInitMode, Error}; use std::path::{PathBuf, Path}; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_directory: String, flag_quiet: bool, @@ -142,7 +143,7 @@ Options: --shared permissions to create the repository with "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/log.rs b/examples/log.rs index 6036218a08..835136a55b 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -14,7 +14,8 @@ #![deny(warnings)] -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; extern crate docopt; extern crate git2; extern crate time; @@ -24,7 +25,7 @@ use docopt::Docopt; use git2::{Repository, Signature, Commit, ObjectType, Time, DiffOptions}; use git2::{Pathspec, Error, DiffFormat}; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_commit: Vec, arg_spec: Vec, @@ -253,7 +254,7 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/ls-remote.rs b/examples/ls-remote.rs index 130fa779f2..5da9575f7b 100644 --- a/examples/ls-remote.rs +++ b/examples/ls-remote.rs @@ -16,12 +16,13 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use docopt::Docopt; use git2::{Repository, Direction}; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_remote: String, } @@ -53,7 +54,7 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/rev-list.rs b/examples/rev-list.rs index 56b9123f93..d2a6181979 100644 --- a/examples/rev-list.rs +++ b/examples/rev-list.rs @@ -17,12 +17,13 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use docopt::Docopt; use git2::{Repository, Error, Revwalk, Oid}; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_spec: Vec, flag_topo_order: bool, @@ -86,7 +87,7 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/rev-parse.rs b/examples/rev-parse.rs index 3705099137..f1caf00f09 100644 --- a/examples/rev-parse.rs +++ b/examples/rev-parse.rs @@ -16,12 +16,13 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use docopt::Docopt; use git2::Repository; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_spec: String, flag_git_dir: Option, @@ -60,7 +61,7 @@ Options: --git-dir directory for the git repository to check "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/status.rs b/examples/status.rs index c0b57fcd83..86cbfcb6cd 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -16,14 +16,15 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use std::str; use std::time::Duration; use docopt::Docopt; use git2::{Repository, Error, StatusOptions, ErrorCode, SubmoduleIgnore}; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_spec: Vec, flag_short: bool, @@ -359,7 +360,7 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} diff --git a/examples/tag.rs b/examples/tag.rs index 4a8b385e89..f0ff3a2193 100644 --- a/examples/tag.rs +++ b/examples/tag.rs @@ -16,13 +16,14 @@ extern crate git2; extern crate docopt; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; use std::str; use docopt::Docopt; use git2::{Repository, Error, Tag, Commit}; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Args { arg_tagname: Option, arg_object: Option, @@ -124,7 +125,7 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.decode()) + let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} From 34ad5f9796f8b9eefba62ecc1f9f1eca6e66cadf Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 10 Aug 2017 00:38:22 +0200 Subject: [PATCH 153/860] doc: small status.rs fixes --- src/status.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/status.rs b/src/status.rs index d8a1abe201..b613c0a97a 100644 --- a/src/status.rs +++ b/src/status.rs @@ -35,8 +35,8 @@ pub enum StatusShow { /// A container for a list of status information about a repository. /// -/// Each instances appears as a if it were a collection, having a length and -/// allowing indexing as well as provding an iterator. +/// Each instance appears as if it were a collection, having a length and +/// allowing indexing, as well as providing an iterator. pub struct Statuses<'repo> { raw: *mut raw::git_status_list, @@ -252,13 +252,13 @@ impl<'repo> Statuses<'repo> { /// Gets the count of status entries in this list. /// - /// If there are no changes in status (at least according the options given - /// when the status list was created), this can return 0. + /// If there are no changes in status (according to the options given + /// when the status list was created), this should return 0. pub fn len(&self) -> usize { unsafe { raw::git_status_list_entrycount(self.raw) as usize } } - /// Return `true` is there is not status entry in this list. + /// Return `true` if there is no status entry in this list. pub fn is_empty(&self) -> bool { self.len() == 0 } From 71735db24a19f04dc6724b31c3f2ab5615193b53 Mon Sep 17 00:00:00 2001 From: K Date: Tue, 15 Aug 2017 14:12:41 +0500 Subject: [PATCH 154/860] Added basic support of streamed blobs writing --- libgit2-sys/lib.rs | 14 +++++++++++ src/blob.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 2 +- src/repo.rs | 15 +++++++++++- 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 4641c95e85..c7ce04dcae 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -808,6 +808,15 @@ pub struct git_submodule_update_options { pub allow_fetch: c_int, } +#[repr(C)] +pub struct git_writestream { + pub write: extern fn(*mut git_writestream, + *const c_char, + size_t) -> c_int, + pub close: extern fn(*mut git_writestream) -> c_int, + pub free: extern fn(*mut git_writestream), +} + #[repr(C)] pub struct git_cred { pub credtype: git_credtype_t, @@ -1840,6 +1849,11 @@ extern { pub fn git_blob_create_fromworkdir(id: *mut git_oid, repo: *mut git_repository, relative_path: *const c_char) -> c_int; + pub fn git_blob_create_fromstream(out: *mut *mut git_writestream, + repo: *mut git_repository, + hintpath: *const c_char) -> c_int; + pub fn git_blob_create_fromstream_commit(id: *mut git_oid, + stream: *mut git_writestream) -> c_int; // tree pub fn git_tree_entry_byid(tree: *const git_tree, diff --git a/src/blob.rs b/src/blob.rs index 40a94b5829..608e5e8139 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -1,8 +1,9 @@ use std::marker; use std::mem; use std::slice; +use std::io; -use {raw, Oid, Object}; +use {raw, Oid, Object, Error}; use util::Binding; /// A structure to represent a git [blob][1] @@ -68,10 +69,54 @@ impl<'repo> Drop for Blob<'repo> { } } +/// A structure to represent a git writestream for blobs +pub struct BlobWriter<'repo> { + raw: *mut raw::git_writestream, + _marker: marker::PhantomData>, +} + +impl<'repo> BlobWriter<'repo> { + /// Finalize blob writing stream and write the blob to the object db + pub fn commit(&mut self) -> Result { + let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + unsafe { + try_call!(raw::git_blob_create_fromstream_commit(&mut raw, self.raw)); + Ok(Binding::from_raw(&raw as *const _)) + } + } +} + +impl<'repo> Binding for BlobWriter<'repo> { + type Raw = *mut raw::git_writestream; + + unsafe fn from_raw(raw: *mut raw::git_writestream) -> BlobWriter<'repo> { + BlobWriter { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_writestream { self.raw } +} + +impl<'repo> io::Write for BlobWriter<'repo> { + fn write(&mut self, buf: &[u8]) -> io::Result { + unsafe { + let res = ((*self.raw).write)(self.raw, buf.as_ptr() as *const i8, buf.len()); + if res < 0 { + Err(io::Error::new(io::ErrorKind::Other, "Write error")) + } else { + Ok(buf.len()) + } + } + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + #[cfg(test)] mod tests { use std::io::prelude::*; use std::fs::File; + use std::path::Path; use tempdir::TempDir; use Repository; @@ -101,4 +146,17 @@ mod tests { assert_eq!(blob.content(), [7, 8, 9]); blob.into_object(); } + + #[test] + fn stream() { + let td = TempDir::new("test").unwrap(); + let repo = Repository::init(td.path()).unwrap(); + let mut ws = repo.blob_writer(Some(Path::new("foo"))).unwrap(); + let wl = ws.write(&[10, 11, 12]).unwrap(); + assert_eq!(wl, 3); + let id = ws.commit().unwrap(); + let blob = repo.find_blob(id).unwrap(); + assert_eq!(blob.content(), [10, 11, 12]); + blob.into_object(); + } } diff --git a/src/lib.rs b/src/lib.rs index dcd2d85bc8..e2f460af61 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,7 +80,7 @@ use std::str; use std::sync::{Once, ONCE_INIT}; pub use blame::{Blame, BlameHunk, BlameIter, BlameOptions}; -pub use blob::Blob; +pub use blob::{Blob, BlobWriter}; pub use branch::{Branch, Branches}; pub use buf::Buf; pub use commit::{Commit, Parents}; diff --git a/src/repo.rs b/src/repo.rs index a8730fcc8b..12828b918c 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -9,7 +9,7 @@ use libc::{c_int, c_char, size_t, c_void, c_uint}; use {raw, Revspec, Error, init, Object, RepositoryOpenFlags, RepositoryState, Remote, Buf, StashFlags}; use {ResetType, Signature, Reference, References, Submodule, Blame, BlameOptions}; -use {Branches, BranchType, Index, Config, Oid, Blob, Branch, Commit, Tree}; +use {Branches, BranchType, Index, Config, Oid, Blob, BlobWriter, Branch, Commit, Tree}; use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus, MergeAnalysis, MergePreference}; use {ObjectType, Tag, Note, Notes, StatusOptions, Statuses, Status, Revwalk}; use {RevparseMode, RepositoryInitMode, Reflog, IntoCString, Describe}; @@ -802,6 +802,19 @@ impl Repository { } } + /// Create stream to write blob + pub fn blob_writer(&self, hintpath: Option<&Path>) -> Result { + let path = match hintpath { + Some(path) => try!(path.into_c_string()).into_raw(), + None => ptr::null(), + }; + let mut out = ptr::null_mut(); + unsafe { + try_call!(raw::git_blob_create_fromstream(&mut out, self.raw(), path)); + Ok(BlobWriter::from_raw(out)) + } + } + /// Lookup a reference to one of the objects in a repository. pub fn find_blob(&self, oid: Oid) -> Result { let mut raw = ptr::null_mut(); From 4d3e05bbcfcbc48767f86c1eac3b73d0a030d4d2 Mon Sep 17 00:00:00 2001 From: Kayo Phoenix Date: Wed, 16 Aug 2017 11:06:54 +0500 Subject: [PATCH 155/860] Added proper cleanup for BlobWriter --- src/blob.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/blob.rs b/src/blob.rs index 608e5e8139..e4ccff0649 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -72,12 +72,15 @@ impl<'repo> Drop for Blob<'repo> { /// A structure to represent a git writestream for blobs pub struct BlobWriter<'repo> { raw: *mut raw::git_writestream, + need_cleanup: bool, _marker: marker::PhantomData>, } impl<'repo> BlobWriter<'repo> { /// Finalize blob writing stream and write the blob to the object db pub fn commit(&mut self) -> Result { + // After commit we already doesn't need cleanup on drop + self.need_cleanup = false; let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; unsafe { try_call!(raw::git_blob_create_fromstream_commit(&mut raw, self.raw)); @@ -92,12 +95,22 @@ impl<'repo> Binding for BlobWriter<'repo> { unsafe fn from_raw(raw: *mut raw::git_writestream) -> BlobWriter<'repo> { BlobWriter { raw: raw, + need_cleanup: true, _marker: marker::PhantomData, } } fn raw(&self) -> *mut raw::git_writestream { self.raw } } +impl<'repo> Drop for BlobWriter<'repo> { + fn drop(&mut self) { + // We need cleanup in case the stream has not been committed + if self.need_cleanup { + unsafe { ((*self.raw).free)(self.raw) } + } + } +} + impl<'repo> io::Write for BlobWriter<'repo> { fn write(&mut self, buf: &[u8]) -> io::Result { unsafe { From aa10f03ce501499d5268b37efd317f688b04c874 Mon Sep 17 00:00:00 2001 From: Kayo Phoenix Date: Fri, 25 Aug 2017 17:36:59 +0500 Subject: [PATCH 156/860] Fixed c-string pointer leak in blob_writer() --- src/repo.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index 12828b918c..805f562242 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -804,8 +804,12 @@ impl Repository { /// Create stream to write blob pub fn blob_writer(&self, hintpath: Option<&Path>) -> Result { - let path = match hintpath { - Some(path) => try!(path.into_c_string()).into_raw(), + let path_str = match hintpath { + Some(path) => Some(try!(path.into_c_string())), + None => None, + }; + let path = match path_str { + Some(path) => path.as_ptr(), None => ptr::null(), }; let mut out = ptr::null_mut(); From fbd80f8c4c642721aacec1a1602d33599ee7c9f6 Mon Sep 17 00:00:00 2001 From: Kayo Phoenix Date: Fri, 25 Aug 2017 17:38:03 +0500 Subject: [PATCH 157/860] Updated documentation for blob_writer() --- src/repo.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 805f562242..b6a3de759f 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -802,7 +802,17 @@ impl Repository { } } - /// Create stream to write blob + /// Create a stream to write blob + /// + /// This function may need to buffer the data on disk and will in general + /// not be the right choice if you know the size of the data to write. + /// + /// Use `BlobWriter::commit()` to commit the write to the object db + /// and get the object id. + /// + /// If the `hintpath` parameter is filled, it will be used to determine + /// what git filters should be applied to the object before it is written + /// to the object database. pub fn blob_writer(&self, hintpath: Option<&Path>) -> Result { let path_str = match hintpath { Some(path) => Some(try!(path.into_c_string())), From adc066fe191de7269b546cba1b950c30ab0dc149 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 1 Aug 2017 07:43:16 -0700 Subject: [PATCH 158/860] Bump libgit2-sys to 0.6.13 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index d78e95698b..341cc01dab 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.12" +version = "0.6.13" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 7d4f3a4913f41ff075a6327c13f4ce6810c3384d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 26 Aug 2017 18:52:25 -0700 Subject: [PATCH 159/860] Make `ReferenceNames` memory safe Tie the lifetime of the returned strings to the iterator, not the repository. Fixes #241 --- src/reference.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/reference.rs b/src/reference.rs index 9528ae7588..faf8294549 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -25,8 +25,8 @@ pub struct References<'repo> { } /// An iterator over the names of references in a repository. -pub struct ReferenceNames<'repo> { - inner: References<'repo>, +pub struct ReferenceNames<'repo: 'references, 'references> { + inner: &'references mut References<'repo>, } impl<'repo> Reference<'repo> { @@ -244,7 +244,7 @@ impl<'repo> References<'repo> { /// the references themselves don't have to be allocated and deallocated. /// /// The returned iterator will yield strings as opposed to a `Reference`. - pub fn names(self) -> ReferenceNames<'repo> { + pub fn names<'a>(&'a mut self) -> ReferenceNames<'repo, 'a> { ReferenceNames { inner: self } } } @@ -275,16 +275,16 @@ impl<'repo> Drop for References<'repo> { } } -impl<'repo> Iterator for ReferenceNames<'repo> { - type Item = Result<&'repo str, Error>; - fn next(&mut self) -> Option> { +impl<'repo, 'references> Iterator for ReferenceNames<'repo, 'references> { + type Item = Result<&'references str, Error>; + fn next(&mut self) -> Option> { let mut out = ptr::null(); unsafe { try_call_iter!(raw::git_reference_next_name(&mut out, self.inner.raw)); let bytes = ::opt_bytes(self, out).unwrap(); let s = str::from_utf8(bytes).unwrap(); - Some(Ok(mem::transmute::<&str, &'repo str>(s))) + Some(Ok(mem::transmute::<&str, &'references str>(s))) } } } @@ -340,7 +340,8 @@ mod tests { { assert!(repo.references().unwrap().count() == 1); assert!(repo.references().unwrap().next().unwrap().unwrap() == head); - let mut names = repo.references().unwrap().names(); + let mut names = repo.references().unwrap(); + let mut names = names.names(); assert_eq!(names.next().unwrap().unwrap(), "refs/heads/master"); assert!(names.next().is_none()); assert!(repo.references_glob("foo").unwrap().count() == 0); From 9ed202d88e15b34f14896406accc139353181688 Mon Sep 17 00:00:00 2001 From: K Date: Sun, 27 Aug 2017 11:18:59 +0500 Subject: [PATCH 160/860] Proposed fixes for streaming blob writer --- src/blob.rs | 2 +- src/repo.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/blob.rs b/src/blob.rs index e4ccff0649..e2b8a41cfd 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -78,7 +78,7 @@ pub struct BlobWriter<'repo> { impl<'repo> BlobWriter<'repo> { /// Finalize blob writing stream and write the blob to the object db - pub fn commit(&mut self) -> Result { + pub fn commit(mut self) -> Result { // After commit we already doesn't need cleanup on drop self.need_cleanup = false; let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; diff --git a/src/repo.rs b/src/repo.rs index b6a3de759f..ad128bebac 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -819,7 +819,7 @@ impl Repository { None => None, }; let path = match path_str { - Some(path) => path.as_ptr(), + Some(ref path) => path.as_ptr(), None => ptr::null(), }; let mut out = ptr::null_mut(); From a46c2069ffd5856944b3f5b92bc8e8bca700569b Mon Sep 17 00:00:00 2001 From: Kayo Phoenix Date: Wed, 16 Aug 2017 23:21:52 +0500 Subject: [PATCH 161/860] Added support ODB streaming API --- libgit2-sys/lib.rs | 25 ++++++++- src/lib.rs | 2 + src/odb.rs | 135 +++++++++++++++++++++++++++++++++++++++++++++ src/repo.rs | 25 +++++++++ 4 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 src/odb.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index c7ce04dcae..8ca6b62d84 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -80,6 +80,8 @@ pub enum git_reflog {} pub enum git_reflog_entry {} pub enum git_describe_result {} pub enum git_packbuilder {} +pub enum git_odb {} +pub enum git_odb_stream {} #[repr(C)] pub struct git_revspec { @@ -1468,7 +1470,7 @@ extern { start_path: *const c_char, across_fs: c_int, ceiling_dirs: *const c_char) -> c_int; - + // revparse pub fn git_revparse(revspec: *mut git_revspec, repo: *mut git_repository, @@ -2648,6 +2650,27 @@ extern { progress_cb: Option, progress_cb_payload: *mut c_void) -> c_int; pub fn git_packbuilder_free(pb: *mut git_packbuilder); + + // odb + pub fn git_repository_odb(out: *mut *mut git_odb, + repo: *mut git_repository) -> c_int; + pub fn git_odb_free(db: *mut git_odb); + pub fn git_odb_open_rstream(out: *mut *mut git_odb_stream, + db: *mut git_odb, + oid: *const git_oid) -> c_int; + pub fn git_odb_stream_read(stream: *mut git_odb_stream, + buffer: *mut c_char, + len: size_t) -> c_int; + pub fn git_odb_open_wstream(out: *mut *mut git_odb_stream, + db: *mut git_odb, + size: git_off_t, + obj_type: git_otype) -> c_int; + pub fn git_odb_stream_write(stream: *mut git_odb_stream, + buffer: *const c_char, + len: size_t) -> c_int; + pub fn git_odb_stream_finalize_write(id: *mut git_oid, + stream: *mut git_odb_stream) -> c_int; + pub fn git_odb_stream_free(stream: *mut git_odb_stream); } pub fn init() { diff --git a/src/lib.rs b/src/lib.rs index e2f460af61..d139741420 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,6 +119,7 @@ pub use tag::Tag; pub use time::{Time, IndexTime}; pub use tree::{Tree, TreeEntry, TreeIter}; pub use treebuilder::TreeBuilder; +pub use odb::{OdbReader, OdbWriter}; pub use util::IntoCString; /// An enumeration of possible errors that can happen when working with a git @@ -565,6 +566,7 @@ mod tag; mod time; mod tree; mod treebuilder; +mod odb; fn init() { static INIT: Once = ONCE_INIT; diff --git a/src/odb.rs b/src/odb.rs new file mode 100644 index 0000000000..64f0406424 --- /dev/null +++ b/src/odb.rs @@ -0,0 +1,135 @@ +use std::marker; +use std::io; +use libc::{c_char}; + +use {raw, Oid, Object, Error}; +use util::Binding; + +/// A structure to represent a git ODB rstream +pub struct OdbReader<'repo> { + raw: *mut raw::git_odb_stream, + _marker: marker::PhantomData>, +} + +impl<'repo> Binding for OdbReader<'repo> { + type Raw = *mut raw::git_odb_stream; + + unsafe fn from_raw(raw: *mut raw::git_odb_stream) -> OdbReader<'repo> { + OdbReader { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_odb_stream { self.raw } +} + +impl<'repo> Drop for OdbReader<'repo> { + fn drop(&mut self) { + unsafe { raw::git_odb_stream_free(self.raw) } + } +} + +impl<'repo> io::Read for OdbReader<'repo> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + unsafe { + let ptr = buf.as_ptr() as *mut c_char; + let len = buf.len(); + let res = raw::git_odb_stream_read(self.raw, ptr, len); + if res < 0 { + Err(io::Error::new(io::ErrorKind::Other, "Read error")) + } else { + Ok(len) + } + } + } +} + +/// A structure to represent a git ODB wstream +pub struct OdbWriter<'repo> { + raw: *mut raw::git_odb_stream, + _marker: marker::PhantomData>, +} + +impl<'repo> OdbWriter<'repo> { + /// Finalize ODB writing stream and write the object to the object database + pub fn finalize(&mut self) -> Result { + let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + unsafe { + try_call!(raw::git_odb_stream_finalize_write(&mut raw, self.raw)); + Ok(Binding::from_raw(&raw as *const _)) + } + } +} + +impl<'repo> Binding for OdbWriter<'repo> { + type Raw = *mut raw::git_odb_stream; + + unsafe fn from_raw(raw: *mut raw::git_odb_stream) -> OdbWriter<'repo> { + OdbWriter { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_odb_stream { self.raw } +} + +impl<'repo> Drop for OdbWriter<'repo> { + fn drop(&mut self) { + unsafe { raw::git_odb_stream_free(self.raw) } + } +} + +impl<'repo> io::Write for OdbWriter<'repo> { + fn write(&mut self, buf: &[u8]) -> io::Result { + unsafe { + let ptr = buf.as_ptr() as *const c_char; + let len = buf.len(); + let res = raw::git_odb_stream_write(self.raw, ptr, len); + if res < 0 { + Err(io::Error::new(io::ErrorKind::Other, "Write error")) + } else { + Ok(buf.len()) + } + } + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +#[cfg(test)] +mod tests { + use std::io::prelude::*; + use tempdir::TempDir; + use {Repository, ObjectType}; + + #[test] + #[ignore] + fn reader() { + let td = TempDir::new("test").unwrap(); + let repo = Repository::init(td.path()).unwrap(); + let dat = [4, 3, 5, 6, 9]; + let id = repo.blob(&dat).unwrap(); + let mut rs = repo.odb_reader(id).unwrap(); + let mut buf = [3]; + let rl = rs.read(&mut buf).unwrap(); + assert_eq!(rl, 3); + assert_eq!(buf, &dat[0..3]); + let rl = rs.read(&mut buf).unwrap(); + assert_eq!(rl, 2); + assert_eq!(buf, &dat[3..5]); + } + + #[test] + fn writer() { + let td = TempDir::new("test").unwrap(); + let repo = Repository::init(td.path()).unwrap(); + let dat = [4, 3, 5, 6, 9]; + let mut ws = repo.odb_writer(dat.len(), ObjectType::Blob).unwrap(); + let wl = ws.write(&dat[0..3]).unwrap(); + assert_eq!(wl, 3); + let wl = ws.write(&dat[3..5]).unwrap(); + assert_eq!(wl, 2); + let id = ws.finalize().unwrap(); + let blob = repo.find_blob(id).unwrap(); + assert_eq!(blob.content(), dat); + } +} diff --git a/src/repo.rs b/src/repo.rs index ad128bebac..df38f5b329 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -14,6 +14,7 @@ use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus, MergeAnaly use {ObjectType, Tag, Note, Notes, StatusOptions, Statuses, Status, Revwalk}; use {RevparseMode, RepositoryInitMode, Reflog, IntoCString, Describe}; use {DescribeOptions, TreeBuilder, Diff, DiffOptions, PackBuilder}; +use {OdbReader, OdbWriter}; use build::{RepoBuilder, CheckoutBuilder}; use stash::{StashApplyOptions, StashCbData, stash_cb}; use string_array::StringArray; @@ -838,6 +839,30 @@ impl Repository { } } + /// Create object database reading stream + pub fn odb_reader(&self, oid: Oid) -> Result { + let mut out = ptr::null_mut(); + unsafe { + let mut db = ptr::null_mut(); + try_call!(raw::git_repository_odb(&mut db, self.raw())); + try_call!(raw::git_odb_open_rstream(&mut out, db, oid.raw())); + raw::git_odb_free(db); + Ok(OdbReader::from_raw(out)) + } + } + + /// Create object database writing stream + pub fn odb_writer(&self, size: usize, obj_type: ObjectType) -> Result { + let mut out = ptr::null_mut(); + unsafe { + let mut db = ptr::null_mut(); + try_call!(raw::git_repository_odb(&mut db, self.raw())); + try_call!(raw::git_odb_open_wstream(&mut out, db, size as raw::git_off_t, obj_type.raw())); + raw::git_odb_free(db); + Ok(OdbWriter::from_raw(out)) + } + } + /// Create a new branch pointing at a target commit /// /// A new direct reference will be created pointing to this target commit. From 87d182268bbbd8c3f0aa1289916d24f356360bb0 Mon Sep 17 00:00:00 2001 From: K Date: Fri, 25 Aug 2017 21:53:09 +0500 Subject: [PATCH 162/860] Fixed pointer leakage in odb_reader(), odb_writer() --- src/repo.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index df38f5b329..1326a8c65c 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -845,8 +845,11 @@ impl Repository { unsafe { let mut db = ptr::null_mut(); try_call!(raw::git_repository_odb(&mut db, self.raw())); - try_call!(raw::git_odb_open_rstream(&mut out, db, oid.raw())); + let res = ::call::try(raw::git_odb_open_rstream(&mut out, db, oid.raw())); raw::git_odb_free(db); + if let Err(err) = res { + return Err(err); + } Ok(OdbReader::from_raw(out)) } } @@ -857,8 +860,11 @@ impl Repository { unsafe { let mut db = ptr::null_mut(); try_call!(raw::git_repository_odb(&mut db, self.raw())); - try_call!(raw::git_odb_open_wstream(&mut out, db, size as raw::git_off_t, obj_type.raw())); + let res = ::call::try(raw::git_odb_open_wstream(&mut out, db, size as raw::git_off_t, obj_type.raw())); raw::git_odb_free(db); + if let Err(err) = res { + return Err(err); + } Ok(OdbWriter::from_raw(out)) } } From 3d0f6027edfec8f1a7e99b4439187bf6a767530d Mon Sep 17 00:00:00 2001 From: K Date: Fri, 25 Aug 2017 22:10:13 +0500 Subject: [PATCH 163/860] Updated documentation for OdbWriter::finalize() --- src/odb.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/odb.rs b/src/odb.rs index 64f0406424..6c60fda185 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -51,7 +51,12 @@ pub struct OdbWriter<'repo> { } impl<'repo> OdbWriter<'repo> { - /// Finalize ODB writing stream and write the object to the object database + /// Finish writing to an ODB stream + /// + /// This method can be used to finalize writing object to the database and get an identifier. + /// The object will take its final name and will be available to the odb. + /// This method will fail if the total number of received bytes differs from the size declared with odb_writer() + /// Attepting write after finishing will be ignored. pub fn finalize(&mut self) -> Result { let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; unsafe { From 58474ffbf1bdc46b4fe88ffcd883f7a1029ec36e Mon Sep 17 00:00:00 2001 From: K Date: Fri, 25 Aug 2017 23:18:59 +0500 Subject: [PATCH 164/860] Added Odb object to deal with ODB APIs --- src/lib.rs | 2 +- src/odb.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++--- src/repo.rs | 33 ++++++------------------------- 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d139741420..e546f87b9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,7 +119,7 @@ pub use tag::Tag; pub use time::{Time, IndexTime}; pub use tree::{Tree, TreeEntry, TreeIter}; pub use treebuilder::TreeBuilder; -pub use odb::{OdbReader, OdbWriter}; +pub use odb::{Odb, OdbReader, OdbWriter}; pub use util::IntoCString; /// An enumeration of possible errors that can happen when working with a git diff --git a/src/odb.rs b/src/odb.rs index 6c60fda185..3b08bb7b4d 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -1,10 +1,59 @@ use std::marker; use std::io; +use std::ptr; use libc::{c_char}; -use {raw, Oid, Object, Error}; +use {raw, Oid, Object, ObjectType, Error}; use util::Binding; +/// A structure to represent a git object database +pub struct Odb<'repo> { + raw: *mut raw::git_odb, + _marker: marker::PhantomData>, +} + +impl<'repo> Binding for Odb<'repo> { + type Raw = *mut raw::git_odb; + + unsafe fn from_raw(raw: *mut raw::git_odb) -> Odb<'repo> { + Odb { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_odb { self.raw } +} + +impl<'repo> Drop for Odb<'repo> { + fn drop(&mut self) { + unsafe { raw::git_odb_free(self.raw) } + } +} + +impl<'repo> Odb<'repo> { + /// Create object database reading stream + /// + /// Note that most backends do not support streaming reads because they store their objects as compressed/delta'ed blobs. + pub fn reader(&self, oid: Oid) -> Result { + let mut out = ptr::null_mut(); + unsafe { + try_call!(raw::git_odb_open_rstream(&mut out, self.raw, oid.raw())); + Ok(OdbReader::from_raw(out)) + } + } + + /// Create object database writing stream + /// + /// The type and final length of the object must be specified when opening the stream. + pub fn writer(&self, size: usize, obj_type: ObjectType) -> Result { + let mut out = ptr::null_mut(); + unsafe { + try_call!(raw::git_odb_open_wstream(&mut out, self.raw, size as raw::git_off_t, obj_type.raw())); + Ok(OdbWriter::from_raw(out)) + } + } +} + /// A structure to represent a git ODB rstream pub struct OdbReader<'repo> { raw: *mut raw::git_odb_stream, @@ -113,7 +162,8 @@ mod tests { let repo = Repository::init(td.path()).unwrap(); let dat = [4, 3, 5, 6, 9]; let id = repo.blob(&dat).unwrap(); - let mut rs = repo.odb_reader(id).unwrap(); + let db = repo.odb().unwrap(); + let mut rs = db.reader(id).unwrap(); let mut buf = [3]; let rl = rs.read(&mut buf).unwrap(); assert_eq!(rl, 3); @@ -128,7 +178,8 @@ mod tests { let td = TempDir::new("test").unwrap(); let repo = Repository::init(td.path()).unwrap(); let dat = [4, 3, 5, 6, 9]; - let mut ws = repo.odb_writer(dat.len(), ObjectType::Blob).unwrap(); + let db = repo.odb().unwrap(); + let mut ws = db.writer(dat.len(), ObjectType::Blob).unwrap(); let wl = ws.write(&dat[0..3]).unwrap(); assert_eq!(wl, 3); let wl = ws.write(&dat[3..5]).unwrap(); diff --git a/src/repo.rs b/src/repo.rs index 1326a8c65c..d36feaf108 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -14,7 +14,7 @@ use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus, MergeAnaly use {ObjectType, Tag, Note, Notes, StatusOptions, Statuses, Status, Revwalk}; use {RevparseMode, RepositoryInitMode, Reflog, IntoCString, Describe}; use {DescribeOptions, TreeBuilder, Diff, DiffOptions, PackBuilder}; -use {OdbReader, OdbWriter}; +use {Odb}; use build::{RepoBuilder, CheckoutBuilder}; use stash::{StashApplyOptions, StashCbData, stash_cb}; use string_array::StringArray; @@ -839,33 +839,12 @@ impl Repository { } } - /// Create object database reading stream - pub fn odb_reader(&self, oid: Oid) -> Result { - let mut out = ptr::null_mut(); - unsafe { - let mut db = ptr::null_mut(); - try_call!(raw::git_repository_odb(&mut db, self.raw())); - let res = ::call::try(raw::git_odb_open_rstream(&mut out, db, oid.raw())); - raw::git_odb_free(db); - if let Err(err) = res { - return Err(err); - } - Ok(OdbReader::from_raw(out)) - } - } - - /// Create object database writing stream - pub fn odb_writer(&self, size: usize, obj_type: ObjectType) -> Result { - let mut out = ptr::null_mut(); + /// Get the object database for this repository + pub fn odb(&self) -> Result { + let mut odb = ptr::null_mut(); unsafe { - let mut db = ptr::null_mut(); - try_call!(raw::git_repository_odb(&mut db, self.raw())); - let res = ::call::try(raw::git_odb_open_wstream(&mut out, db, size as raw::git_off_t, obj_type.raw())); - raw::git_odb_free(db); - if let Err(err) = res { - return Err(err); - } - Ok(OdbWriter::from_raw(out)) + try_call!(raw::git_repository_odb(&mut odb, self.raw())); + Ok(Odb::from_raw(odb)) } } From 56b8fff5436128136725542ce777843ced177ee1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 29 Aug 2017 09:00:45 -0700 Subject: [PATCH 165/860] Bump to 0.6.7 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b39966f046..1d1304fdf5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.6" +version = "0.6.7" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From d018b1eba756427122d9312aa2a20cf9a7cf43b6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 29 Aug 2017 09:02:18 -0700 Subject: [PATCH 166/860] Bump libgit2-sys to 0.6.14 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 341cc01dab..5941088fa3 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libgit2-sys" -version = "0.6.13" +version = "0.6.14" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From c13976402e37e77bd0f8ea2a689774542e568ccf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 29 Aug 2017 09:02:53 -0700 Subject: [PATCH 167/860] Bump dep on libgit2-sys --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1d1304fdf5..b080eca1f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ appveyor = { repository = "alexcrichton/git2-rs" } url = "1.0" bitflags = "0.9" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.6.12" } +libgit2-sys = { path = "libgit2-sys", version = "0.6.14" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 5f9cac61283219ed1bdf9a55758268727270fa2c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 1 Sep 2017 07:55:04 -0700 Subject: [PATCH 168/860] Fix compilation on other architectures --- src/blob.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blob.rs b/src/blob.rs index e2b8a41cfd..d6a388e160 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -114,7 +114,7 @@ impl<'repo> Drop for BlobWriter<'repo> { impl<'repo> io::Write for BlobWriter<'repo> { fn write(&mut self, buf: &[u8]) -> io::Result { unsafe { - let res = ((*self.raw).write)(self.raw, buf.as_ptr() as *const i8, buf.len()); + let res = ((*self.raw).write)(self.raw, buf.as_ptr() as *const _, buf.len()); if res < 0 { Err(io::Error::new(io::ErrorKind::Other, "Write error")) } else { From 82aac562a2cdc77d496c62e22a437d292349849f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 1 Sep 2017 07:55:20 -0700 Subject: [PATCH 169/860] Bump to 0.6.8 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b080eca1f7..65c2e08ef5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.7" +version = "0.6.8" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 527008a6221eee2d3929f0adb0505f2a4b5be79c Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Sun, 3 Sep 2017 23:05:26 +0200 Subject: [PATCH 170/860] doc: be more clear about meaning of Branch::wrap --- src/branch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/branch.rs b/src/branch.rs index 75edd2b30a..3f035ed0d3 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -23,7 +23,7 @@ pub struct Branches<'repo> { } impl<'repo> Branch<'repo> { - /// Creates a new branch from a reference + /// Creates Branch type from a Reference pub fn wrap(reference: Reference) -> Branch { Branch { inner: reference } } /// Gain access to the reference that is this branch From cc65b3637eda3aad9096852c022c92cb849e90e5 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Fri, 8 Sep 2017 22:30:18 -0400 Subject: [PATCH 171/860] oid_array doc typo. --- src/oid_array.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oid_array.rs b/src/oid_array.rs index 7533357dcd..e04fe7cd05 100644 --- a/src/oid_array.rs +++ b/src/oid_array.rs @@ -1,4 +1,4 @@ -//! Bindings to libgit2's raw `git_strarray` type +//! Bindings to libgit2's raw `git_oidarray` type use std::ops::Deref; From 00e51bcb078053c45106e12dc018d083fbf9d061 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 19 Sep 2017 11:10:48 -0700 Subject: [PATCH 172/860] Bump dep on gcc --- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 5941088fa3..dfc8e9cb37 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -22,7 +22,7 @@ libz-sys = ">= 0" [build-dependencies] pkg-config = "0.3" cmake = "0.1.2" -gcc = "0.3" +cc = "1.0" [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9", optional = true } diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index a89eef4390..c7545c2eb0 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -1,5 +1,5 @@ extern crate cmake; -extern crate gcc; +extern crate cc; extern crate pkg_config; use std::env; @@ -85,7 +85,7 @@ fn main() { // When cross-compiling, we're pretty unlikely to find a `dlltool` binary // lying around, so try to find another if it exists if windows && !host.contains("windows") { - let c_compiler = gcc::Config::new().cargo_metadata(false) + let c_compiler = cc::Build::new().cargo_metadata(false) .get_compiler(); let exe = c_compiler.path(); let path = env::var_os("PATH").unwrap_or(OsString::new()); From 2c20641dde77aaf598a470cb35a12dec3c859a13 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 19 Sep 2017 11:11:01 -0700 Subject: [PATCH 173/860] Bump libgit2-sys to 0.6.15 --- libgit2-sys/Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index dfc8e9cb37..d8f6242104 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,7 +1,6 @@ [package] - name = "libgit2-sys" -version = "0.6.14" +version = "0.6.15" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 9653052865e419bcb09c2921a6ed4e0b82d69071 Mon Sep 17 00:00:00 2001 From: Maciej Piechotka Date: Tue, 19 Sep 2017 23:05:03 -0700 Subject: [PATCH 174/860] Implement Clone for Blob, Commit, Tag and Tree --- src/blob.rs | 5 +++++ src/commit.rs | 6 ++++++ src/tag.rs | 6 ++++++ src/tree.rs | 6 ++++++ 4 files changed, 23 insertions(+) diff --git a/src/blob.rs b/src/blob.rs index d6a388e160..024086d161 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -62,6 +62,11 @@ impl<'repo> Binding for Blob<'repo> { fn raw(&self) -> *mut raw::git_blob { self.raw } } +impl<'repo> Clone for Blob<'repo> { + fn clone(&self) -> Self { + self.as_object().clone().into_blob().ok().unwrap() + } +} impl<'repo> Drop for Blob<'repo> { fn drop(&mut self) { diff --git a/src/commit.rs b/src/commit.rs index 891c1b0f29..b5ff08e305 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -295,6 +295,12 @@ impl<'commit> DoubleEndedIterator for ParentIds<'commit> { impl<'commit> ExactSizeIterator for ParentIds<'commit> {} +impl<'repo> Clone for Commit<'repo> { + fn clone(&self) -> Self { + self.as_object().clone().into_commit().ok().unwrap() + } +} + impl<'repo> Drop for Commit<'repo> { fn drop(&mut self) { unsafe { raw::git_commit_free(self.raw) } diff --git a/src/tag.rs b/src/tag.rs index 2b2716de97..55a66a4f75 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -115,6 +115,12 @@ impl<'repo> Binding for Tag<'repo> { fn raw(&self) -> *mut raw::git_tag { self.raw } } +impl<'repo> Clone for Tag<'repo> { + fn clone(&self) -> Self { + self.as_object().clone().into_tag().ok().unwrap() + } +} + impl<'repo> Drop for Tag<'repo> { fn drop(&mut self) { unsafe { raw::git_tag_free(self.raw) } diff --git a/src/tree.rs b/src/tree.rs index a7aaed235b..535e6a4894 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -128,6 +128,12 @@ impl<'repo> Binding for Tree<'repo> { fn raw(&self) -> *mut raw::git_tree { self.raw } } +impl<'repo> Clone for Tree<'repo> { + fn clone(&self) -> Self { + self.as_object().clone().into_tree().ok().unwrap() + } +} + impl<'repo> Drop for Tree<'repo> { fn drop(&mut self) { unsafe { raw::git_tree_free(self.raw) } From 5709d4681ffd185be6a2ca0a2a2513ee358a2f6c Mon Sep 17 00:00:00 2001 From: Maciej Piechotka Date: Tue, 19 Sep 2017 23:53:09 -0700 Subject: [PATCH 175/860] Implement IntoIter for StringArray --- src/string_array.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/string_array.rs b/src/string_array.rs index a77269338e..97af2090e1 100644 --- a/src/string_array.rs +++ b/src/string_array.rs @@ -74,6 +74,14 @@ impl Binding for StringArray { fn raw(&self) -> raw::git_strarray { self.raw } } +impl<'a> IntoIterator for &'a StringArray { + type Item = Option<&'a str>; + type IntoIter = Iter<'a>; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + impl<'a> Iterator for Iter<'a> { type Item = Option<&'a str>; fn next(&mut self) -> Option> { From 45b4d88c24ed3dbbfb18dda7f722f6eb8f514006 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Mon, 11 Sep 2017 15:56:23 +0200 Subject: [PATCH 176/860] Odb foreach bindings --- libgit2-sys/lib.rs | 5 ++++- src/lib.rs | 2 +- src/odb.rs | 37 ++++++++++++++++++++++++++++++++++++- src/repo.rs | 3 +-- 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 8ca6b62d84..5d8b62eca4 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1419,6 +1419,8 @@ pub type git_stash_cb = extern fn(index: size_t, pub type git_packbuilder_foreach_cb = extern fn(*const c_void, size_t, *mut c_void) -> c_int; +pub type git_odb_foreach_cb = extern fn(id: *const git_oid, payload: *mut c_void) -> c_int; + extern { // threads pub fn git_libgit2_init() -> c_int; @@ -1470,7 +1472,7 @@ extern { start_path: *const c_char, across_fs: c_int, ceiling_dirs: *const c_char) -> c_int; - + // revparse pub fn git_revparse(revspec: *mut git_revspec, repo: *mut git_repository, @@ -2671,6 +2673,7 @@ extern { pub fn git_odb_stream_finalize_write(id: *mut git_oid, stream: *mut git_odb_stream) -> c_int; pub fn git_odb_stream_free(stream: *mut git_odb_stream); + pub fn git_odb_foreach(db: *mut git_odb, cb: git_odb_foreach_cb, payload: *mut c_void) -> c_int; } pub fn init() { diff --git a/src/lib.rs b/src/lib.rs index e546f87b9a..e5eec04049 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -545,6 +545,7 @@ mod merge; mod message; mod note; mod object; +mod odb; mod oid; mod packbuilder; mod pathspec; @@ -566,7 +567,6 @@ mod tag; mod time; mod tree; mod treebuilder; -mod odb; fn init() { static INIT: Once = ONCE_INIT; diff --git a/src/odb.rs b/src/odb.rs index 3b08bb7b4d..6ac30c372f 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -1,9 +1,10 @@ use std::marker; use std::io; use std::ptr; -use libc::{c_char}; +use libc::{c_char, c_int, c_void}; use {raw, Oid, Object, ObjectType, Error}; +use panic; use util::Binding; /// A structure to represent a git object database @@ -52,6 +53,19 @@ impl<'repo> Odb<'repo> { Ok(OdbWriter::from_raw(out)) } } + + /// Iterate over all objects in the object database + pub fn foreach(&self, mut callback: C) -> Result<(), Error> + where C: FnMut(&Oid) -> bool + { + unsafe { + let mut data = ForeachCbData { callback: &mut callback }; + try_call!(raw::git_odb_foreach(self.raw(), + foreach_cb, + &mut data as *mut _ as *mut _)); + Ok(()) + } + } } /// A structure to represent a git ODB rstream @@ -149,6 +163,27 @@ impl<'repo> io::Write for OdbWriter<'repo> { fn flush(&mut self) -> io::Result<()> { Ok(()) } } +pub type ForeachCb<'a> = FnMut(&Oid) -> bool + 'a; + +struct ForeachCbData<'a> { + pub callback: &'a mut ForeachCb<'a> +} + +extern fn foreach_cb(id: *const raw::git_oid, + payload: *mut c_void) + -> c_int +{ + panic::wrap(|| unsafe { + let mut data = &mut *(payload as *mut ForeachCbData); + let res = { + let mut callback = &mut data.callback; + callback(&Binding::from_raw(id)) + }; + + if res { 0 } else { 1 } + }).unwrap_or(1) +} + #[cfg(test)] mod tests { use std::io::prelude::*; diff --git a/src/repo.rs b/src/repo.rs index d36feaf108..47595662b4 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -13,8 +13,7 @@ use {Branches, BranchType, Index, Config, Oid, Blob, BlobWriter, Branch, Commit, use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus, MergeAnalysis, MergePreference}; use {ObjectType, Tag, Note, Notes, StatusOptions, Statuses, Status, Revwalk}; use {RevparseMode, RepositoryInitMode, Reflog, IntoCString, Describe}; -use {DescribeOptions, TreeBuilder, Diff, DiffOptions, PackBuilder}; -use {Odb}; +use {DescribeOptions, TreeBuilder, Diff, DiffOptions, PackBuilder, Odb}; use build::{RepoBuilder, CheckoutBuilder}; use stash::{StashApplyOptions, StashCbData, stash_cb}; use string_array::StringArray; From 0806bf89dfb42132b8e0e5fd520fb22ffb461365 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Sep 2017 15:25:12 -0700 Subject: [PATCH 177/860] Squash some nightly warnings --- libgit2-sys/lib.rs | 2 +- src/odb.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5d8b62eca4..9bdf1e35d7 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,5 +1,5 @@ #![doc(html_root_url = "http://alexcrichton.com/git2-rs")] -#![allow(non_camel_case_types)] +#![allow(non_camel_case_types, unused_extern_crates)] extern crate libc; #[cfg(feature = "ssh")] diff --git a/src/odb.rs b/src/odb.rs index 6ac30c372f..48702b7d2f 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -174,9 +174,9 @@ extern fn foreach_cb(id: *const raw::git_oid, -> c_int { panic::wrap(|| unsafe { - let mut data = &mut *(payload as *mut ForeachCbData); + let data = &mut *(payload as *mut ForeachCbData); let res = { - let mut callback = &mut data.callback; + let callback = &mut data.callback; callback(&Binding::from_raw(id)) }; From ddf6f17b3a9dd986a6b311fc2c87140f57326ece Mon Sep 17 00:00:00 2001 From: Maciej Piechotka Date: Thu, 21 Sep 2017 19:34:22 -0700 Subject: [PATCH 178/860] Add utility methods for peeling when type is statically known --- src/object.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/reference.rs | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/object.rs b/src/object.rs index 4af5ee71cb..6b8145ac87 100644 --- a/src/object.rs +++ b/src/object.rs @@ -42,6 +42,26 @@ impl<'repo> Object<'repo> { } } + /// Recursively peel an object until a blob is found + pub fn peel_to_blob(&self) -> Result { + self.peel(ObjectType::Blob).map(|o| o.cast_or_panic(ObjectType::Blob)) + } + + /// Recursively peel an object until a commit is found + pub fn peel_to_commit(&self) -> Result { + self.peel(ObjectType::Commit).map(|o| o.cast_or_panic(ObjectType::Commit)) + } + + /// Recursively peel an object until a tag is found + pub fn peel_to_tag(&self) -> Result { + self.peel(ObjectType::Tag).map(|o| o.cast_or_panic(ObjectType::Tag)) + } + + /// Recursively peel an object until a tree is found + pub fn peel_to_tree(&self) -> Result { + self.peel(ObjectType::Tree).map(|o| o.cast_or_panic(ObjectType::Tree)) + } + /// Get a short abbreviated OID string for the object /// /// This starts at the "core.abbrev" length (default 7 characters) and @@ -147,6 +167,34 @@ impl<'repo> Object<'repo> { } } +/// This trait is useful to export cast_or_panic into crate but not outside +pub trait CastOrPanic { + fn cast_or_panic(self, kind: ObjectType) -> T; +} + +impl<'repo> CastOrPanic for Object<'repo> { + fn cast_or_panic(self, kind: ObjectType) -> T { + assert_eq!(mem::size_of_val(&self), mem::size_of::()); + if self.kind() == Some(kind) { + unsafe { + let other = ptr::read(&self as *const _ as *const T); + mem::forget(self); + other + } + } else { + let buf; + let akind = match self.kind() { + Some(akind) => akind.str(), + None => { + buf = format!("unknown ({})", unsafe { raw::git_object_type(&*self.raw) }); + &buf + } + }; + panic!("Expected object {} to be {} but it is {}", self.id(), kind.str(), akind) + } + } +} + impl<'repo> Clone for Object<'repo> { fn clone(&self) -> Object<'repo> { let mut raw = ptr::null_mut(); diff --git a/src/reference.rs b/src/reference.rs index faf8294549..ad2ea45579 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -5,7 +5,8 @@ use std::mem; use std::ptr; use std::str; -use {raw, Error, Oid, Repository, Object, ObjectType}; +use {raw, Error, Oid, Repository, Object, ObjectType, Blob, Commit, Tree, Tag}; +use object::CastOrPanic; use util::Binding; struct Refdb<'repo>(&'repo Repository); @@ -161,6 +162,38 @@ impl<'repo> Reference<'repo> { } } + /// Peel a reference to a blob + /// + /// This method recursively peels the reference until it reaches + /// a blob. + pub fn peel_to_blob(&self) -> Result, Error> { + try!(self.peel(ObjectType::Blob)).cast_or_panic(ObjectType::Blob) + } + + /// Peel a reference to a commit + /// + /// This method recursively peels the reference until it reaches + /// a blob. + pub fn peel_to_commit(&self) -> Result, Error> { + try!(self.peel(ObjectType::Commit)).cast_or_panic(ObjectType::Commit) + } + + /// Peel a reference to a tree + /// + /// This method recursively peels the reference until it reaches + /// a blob. + pub fn peel_to_tree(&self) -> Result, Error> { + try!(self.peel(ObjectType::Tree)).cast_or_panic(ObjectType::Tree) + } + + /// Peel a reference to a tag + /// + /// This method recursively peels the reference until it reaches + /// a tag. + pub fn peel_to_tag(&self) -> Result, Error> { + try!(self.peel(ObjectType::Tag)).cast_or_panic(ObjectType::Tag) + } + /// Rename an existing reference. /// /// This method works for both direct and symbolic references. From 3f394e5817ed05662ce3d76605644d7a1d453f88 Mon Sep 17 00:00:00 2001 From: Maciej Piechotka Date: Thu, 21 Sep 2017 19:56:08 -0700 Subject: [PATCH 179/860] Add git_merge_trees bindings --- libgit2-sys/lib.rs | 6 ++++++ src/repo.rs | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 9bdf1e35d7..d1300236fa 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2263,6 +2263,12 @@ extern { our_commit: *const git_commit, their_commit: *const git_commit, opts: *const git_merge_options) -> c_int; + pub fn git_merge_trees(out: *mut *mut git_index, + repo: *mut git_repository, + ancestor_tree: *const git_tree, + our_tree: *const git_tree, + their_tree: *const git_tree, + opts: *const git_merge_options) -> c_int; pub fn git_repository_state_cleanup(repo: *mut git_repository) -> c_int; // merge analysis diff --git a/src/repo.rs b/src/repo.rs index 47595662b4..6df21938af 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1391,6 +1391,21 @@ impl Repository { } } + /// Merge two trees, producing an index that reflects the result of + /// the merge. The index may be written as-is to the working directory or + /// checked out. If the index is to be converted to a tree, the caller + /// should resolve any conflicts that arose as part of the merge. + pub fn merge_trees(&self, ancestor_tree: &Tree, our_tree: &Tree, + their_tree: &Tree, opts: Option<&MergeOptions>) -> Result { + let mut raw = ptr::null_mut(); + unsafe { + try_call!(raw::git_merge_trees(&mut raw, self.raw, ancestor_tree.raw(), + our_tree.raw(), their_tree.raw(), + opts.map(|o| o.raw()))); + Ok(Binding::from_raw(raw)) + } + } + /// Remove all the metadata associated with an ongoing command like merge, /// revert, cherry-pick, etc. For example: MERGE_HEAD, MERGE_MSG, etc. pub fn cleanup_state(&self) -> Result<(), Error> { From 627b3ad61226edea1baa5cef9fdf2d8cf4814d33 Mon Sep 17 00:00:00 2001 From: Maciej Piechotka Date: Fri, 22 Sep 2017 09:15:51 -0700 Subject: [PATCH 180/860] Change Object.summary() to take an immutable reference As all other methods do so I presume this is a mistake --- src/commit.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commit.rs b/src/commit.rs index b5ff08e305..6727ce60d2 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -119,7 +119,7 @@ impl<'repo> Commit<'repo> { /// /// `None` may be returned if an error occurs or if the summary is not valid /// utf-8. - pub fn summary(&mut self) -> Option<&str> { + pub fn summary(&self) -> Option<&str> { self.summary_bytes().and_then(|s| str::from_utf8(s).ok()) } @@ -129,7 +129,7 @@ impl<'repo> Commit<'repo> { /// paragraph of the message with whitespace trimmed and squashed. /// /// `None` may be returned if an error occurs - pub fn summary_bytes(&mut self) -> Option<&[u8]> { + pub fn summary_bytes(&self) -> Option<&[u8]> { unsafe { ::opt_bytes(self, raw::git_commit_summary(self.raw)) } } @@ -314,7 +314,7 @@ mod tests { let (_td, repo) = ::test::repo_init(); let head = repo.head().unwrap(); let target = head.target().unwrap(); - let mut commit = repo.find_commit(target).unwrap(); + let commit = repo.find_commit(target).unwrap(); assert_eq!(commit.message(), Some("initial")); assert_eq!(commit.id(), target); commit.message_raw().unwrap(); From edc900d61cd766152f411de0582c1fe5df10ee32 Mon Sep 17 00:00:00 2001 From: Maciej Piechotka Date: Thu, 21 Sep 2017 18:39:48 -0700 Subject: [PATCH 181/860] Add Debug implementation for bunch of objects --- src/blob.rs | 6 ++++++ src/commit.rs | 10 ++++++++++ src/note.rs | 5 +++++ src/object.rs | 12 ++++++++++++ src/oid_array.rs | 6 ++++++ src/tag.rs | 11 +++++++++++ src/tree.rs | 6 ++++++ 7 files changed, 56 insertions(+) diff --git a/src/blob.rs b/src/blob.rs index 024086d161..5e255eb6dc 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -62,6 +62,12 @@ impl<'repo> Binding for Blob<'repo> { fn raw(&self) -> *mut raw::git_blob { self.raw } } +impl<'repo> ::std::fmt::Debug for Blob<'repo> { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + f.debug_struct("Blob").field("id", &self.id()).finish() + } +} + impl<'repo> Clone for Blob<'repo> { fn clone(&self) -> Self { self.as_object().clone().into_blob().ok().unwrap() diff --git a/src/commit.rs b/src/commit.rs index 6727ce60d2..c4e657fb71 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -262,6 +262,16 @@ impl<'repo> Binding for Commit<'repo> { fn raw(&self) -> *mut raw::git_commit { self.raw } } +impl<'repo> ::std::fmt::Debug for Commit<'repo> { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + let mut ds = f.debug_struct("Commit"); + ds.field("id", &self.id()); + if let Some(summary) = self.summary() { + ds.field("summary", &summary); + } + ds.finish() + } +} impl<'repo, 'commit> Iterator for Parents<'commit, 'repo> { type Item = Commit<'repo>; diff --git a/src/note.rs b/src/note.rs index bbd94a517b..5295e5988f 100644 --- a/src/note.rs +++ b/src/note.rs @@ -61,6 +61,11 @@ impl<'repo> Binding for Note<'repo> { fn raw(&self) -> *mut raw::git_note { self.raw } } +impl<'repo> ::std::fmt::Debug for Note<'repo> { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + f.debug_struct("Note").field("id", &self.id()).finish() + } +} impl<'repo> Drop for Note<'repo> { fn drop(&mut self) { diff --git a/src/object.rs b/src/object.rs index 6b8145ac87..6bf524c321 100644 --- a/src/object.rs +++ b/src/object.rs @@ -206,6 +206,18 @@ impl<'repo> Clone for Object<'repo> { } } +impl<'repo> ::std::fmt::Debug for Object<'repo> { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + let mut ds = f.debug_struct("Object"); + match self.kind() { + Some(kind) => ds.field("kind", &kind), + None => ds.field("kind", &format!("Unknow ({})", unsafe { raw::git_object_type(&*self.raw) })) + }; + ds.field("id", &self.id()); + ds.finish() + } +} + impl<'repo> Binding for Object<'repo> { type Raw = *mut raw::git_object; diff --git a/src/oid_array.rs b/src/oid_array.rs index e04fe7cd05..d1108e6c55 100644 --- a/src/oid_array.rs +++ b/src/oid_array.rs @@ -37,6 +37,12 @@ impl Binding for OidArray { fn raw(&self) -> raw::git_oidarray { self.raw } } +impl<'repo> ::std::fmt::Debug for OidArray { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + f.debug_tuple("OidArray").field(&self.deref()).finish() + } +} + impl Drop for OidArray { fn drop(&mut self) { unsafe { raw::git_oidarray_free(&mut self.raw) } diff --git a/src/tag.rs b/src/tag.rs index 55a66a4f75..8041f3546a 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -107,6 +107,17 @@ impl<'repo> Tag<'repo> { } } +impl<'repo> ::std::fmt::Debug for Tag<'repo> { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + let mut ds = f.debug_struct("Tag"); + if let Some(name) = self.name() { + ds.field("name", &name); + } + ds.field("id", &self.id()); + ds.finish() + } +} + impl<'repo> Binding for Tag<'repo> { type Raw = *mut raw::git_tag; unsafe fn from_raw(raw: *mut raw::git_tag) -> Tag<'repo> { diff --git a/src/tree.rs b/src/tree.rs index 535e6a4894..a2006f3c5e 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -128,6 +128,12 @@ impl<'repo> Binding for Tree<'repo> { fn raw(&self) -> *mut raw::git_tree { self.raw } } +impl<'repo> ::std::fmt::Debug for Tree<'repo> { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + f.debug_struct("Tree").field("id", &self.id()).finish() + } +} + impl<'repo> Clone for Tree<'repo> { fn clone(&self) -> Self { self.as_object().clone().into_tree().ok().unwrap() From c332e2e0fd146e4aef4f2841dcdaee18a02eee72 Mon Sep 17 00:00:00 2001 From: Maciej Piechotka Date: Fri, 22 Sep 2017 16:37:35 -0700 Subject: [PATCH 182/860] Fix incorrect cast resulting in panic --- src/reference.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/reference.rs b/src/reference.rs index ad2ea45579..57fb2cdc75 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -167,7 +167,7 @@ impl<'repo> Reference<'repo> { /// This method recursively peels the reference until it reaches /// a blob. pub fn peel_to_blob(&self) -> Result, Error> { - try!(self.peel(ObjectType::Blob)).cast_or_panic(ObjectType::Blob) + Ok(try!(self.peel(ObjectType::Blob)).cast_or_panic(ObjectType::Blob)) } /// Peel a reference to a commit @@ -175,7 +175,7 @@ impl<'repo> Reference<'repo> { /// This method recursively peels the reference until it reaches /// a blob. pub fn peel_to_commit(&self) -> Result, Error> { - try!(self.peel(ObjectType::Commit)).cast_or_panic(ObjectType::Commit) + Ok(try!(self.peel(ObjectType::Commit)).cast_or_panic(ObjectType::Commit)) } /// Peel a reference to a tree @@ -183,7 +183,7 @@ impl<'repo> Reference<'repo> { /// This method recursively peels the reference until it reaches /// a blob. pub fn peel_to_tree(&self) -> Result, Error> { - try!(self.peel(ObjectType::Tree)).cast_or_panic(ObjectType::Tree) + Ok(try!(self.peel(ObjectType::Tree)).cast_or_panic(ObjectType::Tree)) } /// Peel a reference to a tag @@ -191,7 +191,7 @@ impl<'repo> Reference<'repo> { /// This method recursively peels the reference until it reaches /// a tag. pub fn peel_to_tag(&self) -> Result, Error> { - try!(self.peel(ObjectType::Tag)).cast_or_panic(ObjectType::Tag) + Ok(try!(self.peel(ObjectType::Tag)).cast_or_panic(ObjectType::Tag)) } /// Rename an existing reference. From aee3b6f82292c1fce03ee49187fa165394cbac9a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Oct 2017 02:44:43 -0700 Subject: [PATCH 183/860] Fix build on OSX 10.13 Depend on openssl-sys even on OSX because libssh2 uses it and libgit2 will probe for pkg-config dependencies of libssh2 Closes #257 --- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/lib.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index d8f6242104..90bc9f1a55 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -23,7 +23,7 @@ pkg-config = "0.3" cmake = "0.1.2" cc = "1.0" -[target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] +[target.'cfg(unix)'.dependencies] openssl-sys = { version = "0.9", optional = true } [features] diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index d1300236fa..64be6cb92f 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -6,7 +6,7 @@ extern crate libc; extern crate libssh2_sys as libssh2; #[cfg(feature = "curl")] extern crate curl_sys; -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] +#[cfg(all(unix, feature = "https"))] extern crate openssl_sys; extern crate libz_sys as libz; @@ -2699,13 +2699,13 @@ pub fn init() { } } -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] +#[cfg(all(unix, feature = "https"))] #[doc(hidden)] pub fn openssl_init() { openssl_sys::init(); } -#[cfg(any(windows, target_os = "macos", target_os = "ios", not(feature = "https")))] +#[cfg(any(windows, not(feature = "https")))] #[doc(hidden)] pub fn openssl_init() {} From 5ac1dd694e3db2fa70eeb5f2fbc667446de4dabf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Oct 2017 02:45:26 -0700 Subject: [PATCH 184/860] Bump libgit2-sys to 0.6.16 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 90bc9f1a55..503e73c5e7 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.6.15" +version = "0.6.16" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From ba7a04c9e154e6185ca2130f0dac59032ee47bc5 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Mon, 9 Oct 2017 19:33:49 -0400 Subject: [PATCH 185/860] Add test `update_submodule()` This is a test reproducing issue #260; compilation should fail. --- src/submodule.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/submodule.rs b/src/submodule.rs index dfe272a6bd..9cdb3566f9 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -268,6 +268,7 @@ mod tests { use url::Url; use Repository; + use SubmoduleUpdateOptions; #[test] fn smoke() { @@ -312,4 +313,32 @@ mod tests { t!(s.add_to_index(false)); t!(s.add_finalize()); } + + #[test] + fn update_submodule() { + // ----------------------------------- + // Same as `add_a_submodule()` + let (_td, repo1) = ::test::repo_init(); + let (td, repo2) = ::test::repo_init(); + + let url = Url::from_file_path(&repo1.workdir().unwrap()).unwrap(); + let mut s = repo2.submodule(&url.to_string(), Path::new("bar"), + true).unwrap(); + t!(fs::remove_dir_all(td.path().join("bar"))); + t!(Repository::clone(&url.to_string(), + td.path().join("bar"))); + t!(s.add_to_index(false)); + t!(s.add_finalize()); + // ----------------------------------- + + // Attempt to update submodule + let submodules = t!(repo1.submodules()); + for mut submodule in submodules { + let mut submodule_options = SubmoduleUpdateOptions::new(); + let init = true; + let opts = Some(&mut submodule_options); + + t!(submodule.update(init, opts)); + } + } } From 1ec34bbb26ed7b040404208444a3167f6a3d4190 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Mon, 9 Oct 2017 19:45:32 -0400 Subject: [PATCH 186/860] Re-export `SubmoduleUpdateOptions` --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index e5eec04049..10d0ab5e68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,7 +114,7 @@ pub use revwalk::Revwalk; pub use signature::Signature; pub use status::{StatusOptions, Statuses, StatusIter, StatusEntry, StatusShow}; pub use stash::{StashApplyOptions, StashCb, StashApplyProgressCb}; -pub use submodule::Submodule; +pub use submodule::{Submodule, SubmoduleUpdateOptions}; pub use tag::Tag; pub use time::{Time, IndexTime}; pub use tree::{Tree, TreeEntry, TreeIter}; From 721400f884e1216de27073a95760f4100f3688f1 Mon Sep 17 00:00:00 2001 From: Taryn Hill Date: Mon, 16 Oct 2017 22:12:48 -0500 Subject: [PATCH 187/860] Fix 'attemptstempt' typo in commit module --- src/commit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commit.rs b/src/commit.rs index c4e657fb71..f6086309c8 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -220,7 +220,7 @@ impl<'repo> Commit<'repo> { /// Get the specified parent id of the commit. /// - /// This is different from `parent`, which will attemptstempt to load the + /// This is different from `parent`, which will attempt to load the /// parent commit from the ODB. /// /// Use the `parent_ids` iterator to return an iterator over all parents. From 5a443ee1be8bfdb5070358a3a7c8a9eb54e371a7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 30 Oct 2017 14:11:32 -0700 Subject: [PATCH 188/860] Fix copy/paste error --- README.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1d32bf8f55..45e28e35fd 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,20 @@ been removed, but if you're using Homebrew you can install them via: brew install openssl ``` + # License -`git2-rs` is primarily distributed under the terms of both the MIT license and -the Apache License (Version 2.0), with portions covered by various BSD-like -licenses. +This project is licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + http://opensource.org/licenses/MIT) + +at your option. + +### Contribution -See LICENSE-APACHE, and LICENSE-MIT for details. +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. From b285301587cd1becd47cf9346701834ad781ab41 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Fri, 10 Nov 2017 06:11:09 -0800 Subject: [PATCH 189/860] reference: Expose ReferenceType This adds a `kind()` method to `Reference` which uses [`git_reference_type`][1] to get the type of the reference and converts it to the enum `ReferenceType`. [1]: https://libgit2.github.com/libgit2/#HEAD/group/reference/git_reference_type --- src/lib.rs | 35 +++++++++++++++++++++++++++++++++++ src/reference.rs | 17 +++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 10d0ab5e68..c45cf89673 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -294,6 +294,16 @@ pub enum ObjectType { Tag, } +/// An enumeration of all possile kinds of references. +#[derive(PartialEq, Eq, Copy, Clone, Debug)] +pub enum ReferenceType { + /// A reference which points at an object id. + Oid, + + /// A reference which points at another reference. + Symbolic, +} + /// An enumeration for the possible types of branches #[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum BranchType { @@ -760,6 +770,31 @@ impl fmt::Display for ObjectType { } } +impl ReferenceType { + /// Convert an object type to its string representation. + pub fn str(&self) -> &'static str { + match self { + &ReferenceType::Oid => "oid", + &ReferenceType::Symbolic => "symbolic", + } + } + + /// Convert a raw git_ref_t to a ReferenceType. + pub fn from_raw(raw: raw::git_ref_t) -> Option { + match raw { + raw::GIT_REF_OID => Some(ReferenceType::Oid), + raw::GIT_REF_SYMBOLIC => Some(ReferenceType::Symbolic), + _ => None, + } + } +} + +impl fmt::Display for ReferenceType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.str().fmt(f) + } +} + impl ConfigLevel { /// Converts a raw configuration level to a ConfigLevel pub fn from_raw(raw: raw::git_config_level_t) -> ConfigLevel { diff --git a/src/reference.rs b/src/reference.rs index 57fb2cdc75..265d766148 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -5,7 +5,7 @@ use std::mem; use std::ptr; use std::str; -use {raw, Error, Oid, Repository, Object, ObjectType, Blob, Commit, Tree, Tag}; +use {raw, Error, Oid, Repository, ReferenceType, Object, ObjectType, Blob, Commit, Tree, Tag}; use object::CastOrPanic; use util::Binding; @@ -73,6 +73,13 @@ impl<'repo> Reference<'repo> { unsafe { raw::git_reference_is_tag(&*self.raw) == 1 } } + /// Get the reference type of a reference. + /// + /// If the type is unknown, then `None` is returned. + pub fn kind(&self) -> Option { + ReferenceType::from_raw(unsafe { raw::git_reference_type(&*self.raw) }) + } + /// Get the full name of a reference. /// /// Returns `None` if the name is not valid utf-8. @@ -324,7 +331,7 @@ impl<'repo, 'references> Iterator for ReferenceNames<'repo, 'references> { #[cfg(test)] mod tests { - use {Reference, ObjectType}; + use {Reference, ObjectType, ReferenceType}; #[test] fn smoke() { @@ -341,6 +348,10 @@ mod tests { assert!(!head.is_tag()); assert!(!head.is_note()); + // HEAD is a symbolic reference but git_repository_head resolves it + // so it is a GIT_REF_OID. + assert_eq!(head.kind().unwrap(), ReferenceType::Oid); + assert!(head == repo.head().unwrap()); assert_eq!(head.name(), Some("refs/heads/master")); @@ -358,6 +369,7 @@ mod tests { head.target().unwrap(), false, "test").unwrap(); assert!(tag1.is_tag()); + assert_eq!(tag1.kind().unwrap(), ReferenceType::Oid); let peeled_commit = tag1.peel(ObjectType::Commit).unwrap(); assert_eq!(ObjectType::Commit, peeled_commit.kind().unwrap()); @@ -368,6 +380,7 @@ mod tests { let mut sym1 = repo.reference_symbolic("refs/tags/tag1", "refs/heads/master", false, "test").unwrap(); + assert_eq!(sym1.kind().unwrap(), ReferenceType::Symbolic); sym1.delete().unwrap(); { From 1320365aefdccd7e10585b0a5114ba24426fd8af Mon Sep 17 00:00:00 2001 From: Geoff Shannon Date: Wed, 15 Nov 2017 07:31:25 -0800 Subject: [PATCH 190/860] Correct project name in readme contribution section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 45e28e35fd..508932f382 100644 --- a/README.md +++ b/README.md @@ -53,5 +53,5 @@ at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be +for inclusion in git2-rs by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. From 21ab44d421ba3560a728e0b1f0c7d71601cd5bee Mon Sep 17 00:00:00 2001 From: Taryn Hill Date: Thu, 16 Nov 2017 19:24:15 -0600 Subject: [PATCH 191/860] Fix typo in Delta::Renamed's docstring --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index c45cf89673..f0b34521c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -880,7 +880,7 @@ pub enum Delta { Deleted, /// Entry content changed between old and new Modified, - /// Entry was renamed wbetween old and new + /// Entry was renamed between old and new Renamed, /// Entry was copied from another old entry Copied, From bb705a6b32ec86af69e5e48e40d205d315cfd48a Mon Sep 17 00:00:00 2001 From: Igor Gnatenko Date: Sun, 26 Nov 2017 12:19:13 +0100 Subject: [PATCH 192/860] include LICENSE-* to libgit2-sys Signed-off-by: Igor Gnatenko --- libgit2-sys/LICENSE-APACHE | 1 + libgit2-sys/LICENSE-MIT | 1 + 2 files changed, 2 insertions(+) create mode 120000 libgit2-sys/LICENSE-APACHE create mode 120000 libgit2-sys/LICENSE-MIT diff --git a/libgit2-sys/LICENSE-APACHE b/libgit2-sys/LICENSE-APACHE new file mode 120000 index 0000000000..965b606f33 --- /dev/null +++ b/libgit2-sys/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/libgit2-sys/LICENSE-MIT b/libgit2-sys/LICENSE-MIT new file mode 120000 index 0000000000..76219eb72e --- /dev/null +++ b/libgit2-sys/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file From 8b142508bc98180a1943e1f5014e1a7bdd08a5f0 Mon Sep 17 00:00:00 2001 From: Taryn Hill Date: Wed, 29 Nov 2017 08:22:16 -0600 Subject: [PATCH 193/860] Fix typos in the transport module --- src/transport.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/transport.rs b/src/transport.rs index 1b9dbd5a5c..d34db9f88b 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -23,7 +23,7 @@ pub struct Transport { owned: bool, } -/// Interfaced used by smart transports. +/// Interface used by smart transports. /// /// The full-fledged definiton of transports has to deal with lots of /// nitty-gritty details of the git protocol, but "smart transports" largely @@ -45,7 +45,7 @@ pub trait SmartSubtransport: Send + 'static { /// Terminates a connection with the remote. /// /// Each subtransport is guaranteed a call to close() between calls to - /// action(), except for the following tow natural progressions of actions + /// action(), except for the following two natural progressions of actions /// against a constant URL. /// /// 1. UploadPackLs -> UploadPack @@ -151,7 +151,7 @@ impl Transport { param: &mut *raw as *mut _ as *mut _, }; - // Currently there's no way to pass a paload via the + // Currently there's no way to pass a payload via the // git_smart_subtransport_definition structure, but it's only used as a // configuration for the initial creation of the smart transport (verified // by reading the current code, hopefully it doesn't change!). From 047c984d3b934e536fd4cdd54a691ceb233ce92a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 3 Dec 2017 11:13:37 -0800 Subject: [PATCH 194/860] Tweak travis config --- .travis.yml | 51 +++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index c62fb4d7f4..10e97eafb0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,30 @@ language: rust -rust: - - stable - - beta - - nightly sudo: false git: submodules: false -before_script: - - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH + +matrix: + include: + - rust: 1.21.0 + - rust: stable + - os: osx + rust: stable + before_install: + - export OPENSSL_INCLUDE_DIR=`brew --prefix openssl`/include + - export OPENSSL_LIB_DIR=`brew --prefix openssl`/lib + - rust: beta + - rust: nightly + + - rust: nightly + before_script: + - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH + script: + - cargo doc --no-deps + - cargo doc --manifest-path=git2-curl/Cargo.toml --no-deps + - cargo doc --manifest-path=libgit2-sys/Cargo.toml --no-deps + after_success: + - travis-cargo --only nightly doc-upload + script: - git submodule update --init - cargo test --no-default-features @@ -17,22 +34,15 @@ script: cargo test --features unstable; cargo test --manifest-path git2-curl/Cargo.toml; fi - - cargo doc --no-deps - - cargo doc --manifest-path=git2-curl/Cargo.toml --no-deps - - cargo doc --manifest-path=libgit2-sys/Cargo.toml --no-deps -after_success: - - travis-cargo --only nightly doc-upload - - travis-cargo coveralls --no-sudo + +env: + global: + secure: "SVk5cv4VnBQAoaBXt9pIHk+FQ7Z58zT5EaPo7Ac81LltKztwHovhN/R1otKzgrAJqFsZ/nKR4cGyQGbYtfVJcsqweQVM75LI6Oh6lYyEdfX211ZI3SWQ50JO93CmwLtanC5UpECdXvJLCgXrHGJXuL1oi7hySGy47/yQlKH6eaM=" + notifications: email: on_success: never -matrix: - include: - - os: osx - rust: stable - before_install: - - export OPENSSL_INCLUDE_DIR=`brew --prefix openssl`/include - - export OPENSSL_LIB_DIR=`brew --prefix openssl`/lib + addons: apt: sources: @@ -42,6 +52,3 @@ addons: - libcurl4-openssl-dev - libelf-dev - libdw-dev -env: - global: - secure: "SVk5cv4VnBQAoaBXt9pIHk+FQ7Z58zT5EaPo7Ac81LltKztwHovhN/R1otKzgrAJqFsZ/nKR4cGyQGbYtfVJcsqweQVM75LI6Oh6lYyEdfX211ZI3SWQ50JO93CmwLtanC5UpECdXvJLCgXrHGJXuL1oi7hySGy47/yQlKH6eaM=" From 75e7c4e3a6655580cc04a3e2592c6735ca17e1ee Mon Sep 17 00:00:00 2001 From: Hiroki Noda Date: Sun, 10 Dec 2017 14:19:32 +0900 Subject: [PATCH 195/860] Add some ignore rules APIs --- libgit2-sys/lib.rs | 6 ++++++ src/repo.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 64be6cb92f..6dc20276e7 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1472,6 +1472,12 @@ extern { start_path: *const c_char, across_fs: c_int, ceiling_dirs: *const c_char) -> c_int; + pub fn git_ignore_add_rule(repo: *mut git_repository, + rules: *const c_char) -> c_int; + pub fn git_ignore_clear_internal_rules(repo: *mut git_repository) -> c_int; + pub fn git_ignore_path_is_ignored(ignored: *mut c_int, + repo: *mut git_repository, + path: *const c_char) -> c_int; // revparse pub fn git_revparse(revspec: *mut git_revspec, diff --git a/src/repo.rs b/src/repo.rs index 6df21938af..c7679b4641 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1891,6 +1891,42 @@ impl Repository { Ok(()) } } + + /// Add an ignore rule for a repository. + pub fn add_ignore_rule(&self, rule: &str) -> Result<(), Error> { + let rules = CString::new(rule)?; + unsafe { + try_call!(raw::git_ignore_add_rule(self.raw, rules)); + } + Ok(()) + } + + /// Add ignore rules for a repository. + pub fn add_ignore_rules(&self, rules: &Vec<&str>) -> Result<(), Error> { + let rules = CString::new(rules.join("\n"))?; + unsafe { + try_call!(raw::git_ignore_add_rule(self.raw, rules)); + } + Ok(()) + } + + /// Clear ignore rules that were explicitly added. + pub fn clear_ignore_rules(&self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_ignore_clear_internal_rules(self.raw)); + } + Ok(()) + } + + /// Test if the ignore rules apply to a given path. + pub fn is_path_ignored>(&self, path: P) -> Result { + let path = try!(path.as_ref().into_c_string()); + let mut ignored: c_int = 0; + unsafe { + try_call!(raw::git_ignore_path_is_ignored(&mut ignored, self.raw, path)); + } + Ok(ignored == 1) + } } impl Binding for Repository { @@ -2367,4 +2403,17 @@ mod tests { assert!(reference.is_none()); } } + + #[test] + fn smoke_is_path_ignored() { + let (_td, repo) = graph_repo_init(); + + assert!(!repo.is_path_ignored(Path::new("/foo")).unwrap()); + + let _ = repo.add_ignore_rule("/foo"); + assert!(repo.is_path_ignored(Path::new("/foo")).unwrap()); + + let _ = repo.clear_ignore_rules(); + assert!(!repo.is_path_ignored(Path::new("/foo")).unwrap()); + } } From 762c85292cf57fe894df11eb104fb65a4f8599aa Mon Sep 17 00:00:00 2001 From: Hiroki Noda Date: Mon, 11 Dec 2017 00:25:34 +0900 Subject: [PATCH 196/860] Omit for adding a single ignore rule function --- src/repo.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index c7679b4641..2979c2fcce 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1892,18 +1892,9 @@ impl Repository { } } - /// Add an ignore rule for a repository. - pub fn add_ignore_rule(&self, rule: &str) -> Result<(), Error> { - let rules = CString::new(rule)?; - unsafe { - try_call!(raw::git_ignore_add_rule(self.raw, rules)); - } - Ok(()) - } - /// Add ignore rules for a repository. - pub fn add_ignore_rules(&self, rules: &Vec<&str>) -> Result<(), Error> { - let rules = CString::new(rules.join("\n"))?; + pub fn add_ignore_rule(&self, rules: &str) -> Result<(), Error> { + let rules = CString::new(rules)?; unsafe { try_call!(raw::git_ignore_add_rule(self.raw, rules)); } From f4d3958882e051e4450234ce57767c942a283d25 Mon Sep 17 00:00:00 2001 From: Hiroki Noda Date: Mon, 11 Dec 2017 01:03:21 +0900 Subject: [PATCH 197/860] Mention to the format of the ignore rules --- src/repo.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index 2979c2fcce..b0bf693f9c 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1893,6 +1893,8 @@ impl Repository { } /// Add ignore rules for a repository. + /// + /// The format of the rules is the same one of the .gitignore file. pub fn add_ignore_rule(&self, rules: &str) -> Result<(), Error> { let rules = CString::new(rules)?; unsafe { From 557fff62b55584be4768b91fc727ef616a79b187 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 10 Dec 2017 09:31:14 -0800 Subject: [PATCH 198/860] Improve error handling in a few ways This commit improves the error handling strategy slightly with a few techniques: * The `Error::last_error` function now always returns an error which preserves the `code` passed in. This means that at least the code won't be lost! * During `Error::last_error` the underlying `giterr_clear` function is unconditionally called. This is done in an attempt to prevent error contexts leaking from one API call to the next. * The `Display` implementation for `Error` is updated to be a bit more useful, displaying human-readable names instead of error codes. --- src/call.rs | 8 +++----- src/error.rs | 46 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/call.rs b/src/call.rs index ba5a1d5656..3367275bff 100644 --- a/src/call.rs +++ b/src/call.rs @@ -43,11 +43,9 @@ pub fn try(ret: libc::c_int) -> Result { } pub fn last_error(code: libc::c_int) -> Error { - // Apparently libgit2 isn't necessarily guaranteed to set the last error - // whenever a function returns a negative value! - Error::last_error(code).unwrap_or_else(|| { - Error::from_str("an unknown error occurred") - }) + // nowadays this unwrap is safe as `Error::last_error` always returns + // `Some`. + Error::last_error(code).unwrap() } mod impls { diff --git a/src/error.rs b/src/error.rs index 7d8f42c843..b0b9748a9b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -16,16 +16,40 @@ pub struct Error { } impl Error { - /// Returns the last error, or `None` if one is not available. + /// Returns the last error that happened with the code specified by `code`. + /// + /// Historically this function returned `Some` or `None` based on the return + /// value of `giterr_last` but nowadays it always returns `Some` so it's + /// safe to unwrap the return value. This API will change in the next major + /// version. pub fn last_error(code: c_int) -> Option { ::init(); unsafe { + // Note that whenever libgit2 returns an error any negative value + // indicates that an error happened. Auxiliary information is + // *usually* in `giterr_last` but unfortunately that's not always + // the case. Sometimes a negative error code is returned from + // libgit2 *without* calling `giterr_set` internally to configure + // the error. + // + // To handle this case and hopefully provide better error messages + // on our end we unconditionally call `giterr_clear` when we're done + // with an error. This is an attempt to clear it as aggressively as + // possible when we can to ensure that error information from one + // api invocation doesn't leak over to the next api invocation. + // + // Additionally if `giterr_last` returns null then we returned a + // canned error out. let ptr = raw::giterr_last(); - if ptr.is_null() { - None + let err = if ptr.is_null() { + let mut error = Error::from_str("an unknown git error occurred"); + error.code = code; + error } else { - Some(Error::from_raw(code, ptr)) - } + Error::from_raw(code, ptr) + }; + raw::giterr_clear(); + Some(err) } } @@ -203,8 +227,16 @@ impl error::Error for Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "[{}/{}] ", self.klass, self.code)); - f.write_str(&self.message) + write!(f, "{}", self.message)?; + match self.class() { + ErrorClass::None => {} + other => write!(f, "; class={:?} ({})", other, self.klass)?, + } + match self.code() { + ErrorCode::GenericError => {} + other => write!(f, "; code={:?} ({})", other, self.code)?, + } + Ok(()) } } From 7aad5b5ec44fdf1ddf1acfbd979f130204644bac Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 10 Dec 2017 09:37:43 -0800 Subject: [PATCH 199/860] Bump to 0.6.9 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 65c2e08ef5..3605ddc28b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.8" +version = "0.6.9" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 74d6850beffe72e8e5a6a4192c328c301125f5eb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 10 Dec 2017 09:40:11 -0800 Subject: [PATCH 200/860] Bump libgit2-sys to 0.6.17 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 503e73c5e7..039f049dff 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.6.16" +version = "0.6.17" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 6450ca8d1018ec3247d6d72b9c390ba0e82978d7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 10 Dec 2017 09:41:18 -0800 Subject: [PATCH 201/860] Update libgit2-sys dep --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3605ddc28b..0db5af542e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ appveyor = { repository = "alexcrichton/git2-rs" } url = "1.0" bitflags = "0.9" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.6.14" } +libgit2-sys = { path = "libgit2-sys", version = "0.6.17" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 2e153a29cbe5ef1e0db50e40be356aaf52d04cb2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 12 Dec 2017 21:26:40 -0800 Subject: [PATCH 202/860] Touch up error docs --- src/error.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/error.rs b/src/error.rs index b0b9748a9b..b5d9943361 100644 --- a/src/error.rs +++ b/src/error.rs @@ -18,6 +18,9 @@ pub struct Error { impl Error { /// Returns the last error that happened with the code specified by `code`. /// + /// The `code` argument typically comes from the return value of a function + /// call. This code will later be returned from the `code` function. + /// /// Historically this function returned `Some` or `None` based on the return /// value of `giterr_last` but nowadays it always returns `Some` so it's /// safe to unwrap the return value. This API will change in the next major @@ -60,6 +63,9 @@ impl Error { } /// Creates a new error from the given string as the error. + /// + /// The error returned will have the code `GIT_ERROR` and the class + /// `GITERR_NONE`. pub fn from_str(s: &str) -> Error { Error { code: raw::GIT_ERROR as c_int, @@ -69,6 +75,11 @@ impl Error { } /// Return the error code associated with this error. + /// + /// An error code is intended to be programmatically actionable most of the + /// time. For example the code `GIT_EAGAIN` indicates that an error could be + /// fixed by trying again, while the code `GIT_ERROR` is more bland and + /// doesn't convey anything in particular. pub fn code(&self) -> ErrorCode { match self.raw_code() { raw::GIT_OK => super::ErrorCode::GenericError, @@ -101,6 +112,10 @@ impl Error { } /// Return the error class associated with this error. + /// + /// Error classes are in general mostly just informative. For example the + /// class will show up in the error message but otherwise an error class is + /// typically not directly actionable. pub fn class(&self) -> ErrorClass { match self.raw_class() { raw::GITERR_NONE => super::ErrorClass::None, From cd9a0b8defbe7db3b0beaf86faf1a9981362ef16 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 20 Dec 2017 12:27:47 -0800 Subject: [PATCH 203/860] Don't shutdown libgit2 at exit atexit handlers can be run while other threads are still alive, and in particular still using git2 types. This can manifest as hitting this assert, for example: https://github.com/libgit2/libgit2/blob/master/src/mwindow.c#L106 --- libgit2-sys/lib.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 6dc20276e7..33feb73a41 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2698,11 +2698,7 @@ pub fn init() { let r = git_libgit2_init(); assert!(r >= 0, "couldn't initialize the libgit2 library: {}", r); - assert_eq!(libc::atexit(shutdown), 0); }); - extern fn shutdown() { - unsafe { git_libgit2_shutdown(); } - } } #[cfg(all(unix, feature = "https"))] From 3318d7007dac4e0f820a6bcdb0d61d42c1275e60 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 20 Dec 2017 12:41:11 -0800 Subject: [PATCH 204/860] Comment as to why shutdown is avoided --- libgit2-sys/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 33feb73a41..93938275e5 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2698,6 +2698,10 @@ pub fn init() { let r = git_libgit2_init(); assert!(r >= 0, "couldn't initialize the libgit2 library: {}", r); + + // Note that we intentionally never schedule `git_libgit2_shutdown` to + // get called. There's not really a great tiem to call that and #276 has + // some more info about how automatically doing it can cause problems. }); } From 5243f4edb68b7458b6c6b385651dfba41a3c402b Mon Sep 17 00:00:00 2001 From: Kenneth Endfinger Date: Sun, 24 Dec 2017 22:43:44 -0600 Subject: [PATCH 205/860] Implement reading an object from the object database. --- libgit2-sys/lib.rs | 10 +++++++ src/lib.rs | 2 +- src/odb.rs | 75 ++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 93938275e5..168f8d3a2f 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -82,6 +82,7 @@ pub enum git_describe_result {} pub enum git_packbuilder {} pub enum git_odb {} pub enum git_odb_stream {} +pub enum git_odb_object {} #[repr(C)] pub struct git_revspec { @@ -2686,6 +2687,15 @@ extern { stream: *mut git_odb_stream) -> c_int; pub fn git_odb_stream_free(stream: *mut git_odb_stream); pub fn git_odb_foreach(db: *mut git_odb, cb: git_odb_foreach_cb, payload: *mut c_void) -> c_int; + + pub fn git_odb_read(out: *mut *mut git_odb_object, + odb: *mut git_odb, + oid: *const git_oid) -> c_int; + + pub fn git_odb_object_size(obj: *mut git_odb_object) -> size_t; + pub fn git_odb_object_type(obj: *mut git_odb_object) -> git_otype; + pub fn git_odb_object_data(obj: *mut git_odb_object) -> *const u8; + pub fn git_odb_object_free(obj: *mut git_odb_object); } pub fn init() { diff --git a/src/lib.rs b/src/lib.rs index f0b34521c5..2a1ca3dab9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,7 +119,7 @@ pub use tag::Tag; pub use time::{Time, IndexTime}; pub use tree::{Tree, TreeEntry, TreeIter}; pub use treebuilder::TreeBuilder; -pub use odb::{Odb, OdbReader, OdbWriter}; +pub use odb::{Odb, OdbObject, OdbReader, OdbWriter}; pub use util::IntoCString; /// An enumeration of possible errors that can happen when working with a git diff --git a/src/odb.rs b/src/odb.rs index 48702b7d2f..42dfa9e8a0 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -1,6 +1,8 @@ use std::marker; use std::io; use std::ptr; +use std::slice; + use libc::{c_char, c_int, c_void}; use {raw, Oid, Object, ObjectType, Error}; @@ -66,6 +68,65 @@ impl<'repo> Odb<'repo> { Ok(()) } } + + /// Read object from the database. + pub fn read(&self, oid: Oid) -> Result { + let mut out = ptr::null_mut(); + unsafe { + try_call!(raw::git_odb_read(&mut out, self.raw, oid.raw())); + Ok(OdbObject::from_raw(out)) + } + } +} + +/// An object from the Object Database. +pub struct OdbObject<'a> { + raw: *mut raw::git_odb_object, + _marker: marker::PhantomData>, +} + +impl<'a> Binding for OdbObject<'a> { + type Raw = *mut raw::git_odb_object; + + unsafe fn from_raw(raw: *mut raw::git_odb_object) -> OdbObject<'a> { + OdbObject { + raw: raw, + _marker: marker::PhantomData, + } + } + + fn raw(&self) -> *mut raw::git_odb_object { self.raw } +} + +impl<'a> Drop for OdbObject<'a> { + fn drop(&mut self) { + unsafe { raw::git_odb_object_free(self.raw) } + } +} + +impl<'a> OdbObject<'a> { + /// Get the object type. + pub fn get_type(&self) -> Result { + unsafe { Ok(ObjectType::from_raw(raw::git_odb_object_type(self.raw)).unwrap()) } + } + + /// Get the object size. + pub fn len(&self) -> Result { + unsafe { Ok(raw::git_odb_object_size(self.raw)) } + } + + /// Get the object data. + pub fn data(&self) -> Result<&[u8], Error> { + unsafe { + let result = self.len(); + if result.is_err() { + return Err(result.err().unwrap()); + } + let ptr : *const u8 = raw::git_odb_object_data(self.raw); + let buffer = slice::from_raw_parts(ptr, result.unwrap()); + return Ok(buffer); + } + } } /// A structure to represent a git ODB rstream @@ -191,21 +252,17 @@ mod tests { use {Repository, ObjectType}; #[test] - #[ignore] fn reader() { let td = TempDir::new("test").unwrap(); let repo = Repository::init(td.path()).unwrap(); let dat = [4, 3, 5, 6, 9]; let id = repo.blob(&dat).unwrap(); let db = repo.odb().unwrap(); - let mut rs = db.reader(id).unwrap(); - let mut buf = [3]; - let rl = rs.read(&mut buf).unwrap(); - assert_eq!(rl, 3); - assert_eq!(buf, &dat[0..3]); - let rl = rs.read(&mut buf).unwrap(); - assert_eq!(rl, 2); - assert_eq!(buf, &dat[3..5]); + let obj = db.read(id).unwrap(); + let data = obj.data().unwrap(); + let size = obj.len().unwrap(); + assert_eq!(size, 5); + assert_eq!(dat, data); } #[test] From 0a72a8d577094bf08da9e5da00ccd2f0d0c988cd Mon Sep 17 00:00:00 2001 From: Kenneth Endfinger Date: Sun, 24 Dec 2017 23:18:35 -0600 Subject: [PATCH 206/860] Fix the type signature of git_odb_object_data() --- libgit2-sys/lib.rs | 2 +- src/odb.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 168f8d3a2f..2656666d43 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2694,7 +2694,7 @@ extern { pub fn git_odb_object_size(obj: *mut git_odb_object) -> size_t; pub fn git_odb_object_type(obj: *mut git_odb_object) -> git_otype; - pub fn git_odb_object_data(obj: *mut git_odb_object) -> *const u8; + pub fn git_odb_object_data(obj: *mut git_odb_object) -> *const c_void; pub fn git_odb_object_free(obj: *mut git_odb_object); } diff --git a/src/odb.rs b/src/odb.rs index 42dfa9e8a0..8203056071 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -122,7 +122,7 @@ impl<'a> OdbObject<'a> { if result.is_err() { return Err(result.err().unwrap()); } - let ptr : *const u8 = raw::git_odb_object_data(self.raw); + let ptr : *const u8 = raw::git_odb_object_data(self.raw) as *const u8; let buffer = slice::from_raw_parts(ptr, result.unwrap()); return Ok(buffer); } From 2f0210fa7ad415a1b8e50a93cfc079064754ac39 Mon Sep 17 00:00:00 2001 From: Kenneth Endfinger Date: Mon, 25 Dec 2017 00:10:43 -0600 Subject: [PATCH 207/860] Add a binding for git_odb_exists() --- libgit2-sys/lib.rs | 3 +++ src/odb.rs | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 2656666d43..926c9839a7 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2692,6 +2692,9 @@ extern { odb: *mut git_odb, oid: *const git_oid) -> c_int; + pub fn git_odb_exists(odb: *mut git_odb, + oid: *const git_oid) -> c_int; + pub fn git_odb_object_size(obj: *mut git_odb_object) -> size_t; pub fn git_odb_object_type(obj: *mut git_odb_object) -> git_otype; pub fn git_odb_object_data(obj: *mut git_odb_object) -> *const c_void; diff --git a/src/odb.rs b/src/odb.rs index 8203056071..7368367f11 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -77,6 +77,11 @@ impl<'repo> Odb<'repo> { Ok(OdbObject::from_raw(out)) } } + + /// Checks if the object database has an object. + pub fn exists(&self, oid: Oid) -> Result { + unsafe { Ok(raw::git_odb_exists(self.raw, oid.raw()) != -1) } + } } /// An object from the Object Database. From 7fc41c1c9209b9fcec88792b5b05d0df20556fac Mon Sep 17 00:00:00 2001 From: Kenneth Endfinger Date: Mon, 25 Dec 2017 11:54:38 -0600 Subject: [PATCH 208/860] Fix the issues in the code review. --- src/odb.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/odb.rs b/src/odb.rs index 7368367f11..a7caf21f43 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -79,8 +79,8 @@ impl<'repo> Odb<'repo> { } /// Checks if the object database has an object. - pub fn exists(&self, oid: Oid) -> Result { - unsafe { Ok(raw::git_odb_exists(self.raw, oid.raw()) != -1) } + pub fn exists(&self, oid: Oid) -> bool { + unsafe { raw::git_odb_exists(self.raw, oid.raw()) != -1 } } } @@ -111,24 +111,21 @@ impl<'a> Drop for OdbObject<'a> { impl<'a> OdbObject<'a> { /// Get the object type. - pub fn get_type(&self) -> Result { - unsafe { Ok(ObjectType::from_raw(raw::git_odb_object_type(self.raw)).unwrap()) } + pub fn kind(&self) -> ObjectType { + unsafe { ObjectType::from_raw(raw::git_odb_object_type(self.raw)).unwrap() } } /// Get the object size. - pub fn len(&self) -> Result { - unsafe { Ok(raw::git_odb_object_size(self.raw)) } + pub fn len(&self) -> usize { + unsafe { raw::git_odb_object_size(self.raw) } } /// Get the object data. pub fn data(&self) -> Result<&[u8], Error> { unsafe { - let result = self.len(); - if result.is_err() { - return Err(result.err().unwrap()); - } + let size = self.len(); let ptr : *const u8 = raw::git_odb_object_data(self.raw) as *const u8; - let buffer = slice::from_raw_parts(ptr, result.unwrap()); + let buffer = slice::from_raw_parts(ptr, size); return Ok(buffer); } } @@ -265,7 +262,7 @@ mod tests { let db = repo.odb().unwrap(); let obj = db.read(id).unwrap(); let data = obj.data().unwrap(); - let size = obj.len().unwrap(); + let size = obj.len(); assert_eq!(size, 5); assert_eq!(dat, data); } From 9c7e20039bc36316506b5045630dde69c8dbf57f Mon Sep 17 00:00:00 2001 From: Kenneth Endfinger Date: Mon, 25 Dec 2017 12:41:50 -0600 Subject: [PATCH 209/860] Fix another redundant usage of Result. --- src/odb.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/odb.rs b/src/odb.rs index a7caf21f43..754a63d087 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -121,12 +121,12 @@ impl<'a> OdbObject<'a> { } /// Get the object data. - pub fn data(&self) -> Result<&[u8], Error> { + pub fn data(&self) -> &[u8] { unsafe { let size = self.len(); let ptr : *const u8 = raw::git_odb_object_data(self.raw) as *const u8; let buffer = slice::from_raw_parts(ptr, size); - return Ok(buffer); + return buffer; } } } @@ -261,7 +261,7 @@ mod tests { let id = repo.blob(&dat).unwrap(); let db = repo.odb().unwrap(); let obj = db.read(id).unwrap(); - let data = obj.data().unwrap(); + let data = obj.data(); let size = obj.len(); assert_eq!(size, 5); assert_eq!(dat, data); From 1cac5363b32514c8c3942533d3c56b2c4e130181 Mon Sep 17 00:00:00 2001 From: Igor Gnatenko Date: Sun, 7 Jan 2018 20:43:26 +0100 Subject: [PATCH 210/860] deps: update curl-sys to 0.4 Signed-off-by: Igor Gnatenko --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 039f049dff..1220ba642c 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -13,7 +13,7 @@ name = "libgit2_sys" path = "lib.rs" [dependencies] -curl-sys = { version = "0.3.12", optional = true } +curl-sys = { version = "0.4", optional = true } libc = "0.2" libssh2-sys = { version = "0.2.4", optional = true } libz-sys = ">= 0" From f5b237286de9e60b32994426b3e6f3fdca09e608 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 20 Dec 2017 12:41:25 -0800 Subject: [PATCH 211/860] Bump to 0.6.10 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 0db5af542e..17126f395a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.9" +version = "0.6.10" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 279cd83828528de45e08936ef1699c500ba378a3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 20 Dec 2017 12:47:08 -0800 Subject: [PATCH 212/860] Bump libgit2-sys to 0.6.18 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 1220ba642c..e9720977d4 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.6.17" +version = "0.6.18" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 7bdf54a9b1f932f13fe98975770d4cdc43810253 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 8 Jan 2018 09:06:41 -0800 Subject: [PATCH 213/860] Add a few more options to `RepoBuilder` * Bind the `local` field more faithfully * Bind `remote_create` callback --- src/build.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++------ src/remote.rs | 8 +++- 2 files changed, 102 insertions(+), 14 deletions(-) diff --git a/src/build.rs b/src/build.rs index 155b0c5dd7..4e4d2959a3 100644 --- a/src/build.rs +++ b/src/build.rs @@ -7,7 +7,7 @@ use std::ptr; use libc::{c_char, size_t, c_void, c_uint, c_int}; use {raw, panic, Error, Repository, FetchOptions, IntoCString}; -use {CheckoutNotificationType, DiffFile}; +use {CheckoutNotificationType, DiffFile, Remote}; use util::{self, Binding}; /// A builder struct which is used to build configuration for cloning a new git @@ -19,8 +19,16 @@ pub struct RepoBuilder<'cb> { hardlinks: bool, checkout: Option>, fetch_opts: Option>, + clone_local: Option, + remote_create: Option>>, } +/// Type of callback passed to `RepoBuilder::remote_create`. +/// +/// The second and third arguments are the remote's name and the remote's url. +pub type RemoteCreate<'cb> = for<'a> FnMut(&'a Repository, &str, &str) + -> Result, Error> + 'cb; + /// A builder struct for configuring checkouts of a repository. pub struct CheckoutBuilder<'cb> { their_label: Option, @@ -61,6 +69,28 @@ impl<'cb> Default for RepoBuilder<'cb> { } } +/// Options that can be passed to `RepoBuilder::clone_local`. +#[derive(Clone, Copy)] +pub enum CloneLocal { + /// Auto-detect (default) + /// + /// Here libgit2 will bypass the git-aware transport for local paths, but + /// use a normal fetch for `file://` urls. + Auto = raw::GIT_CLONE_LOCAL_AUTO as isize, + + /// Bypass the git-aware transport even for `file://` urls. + Local = raw::GIT_CLONE_LOCAL as isize, + + /// Never bypass the git-aware transport + None = raw::GIT_CLONE_NO_LOCAL as isize, + + /// Bypass the git-aware transport, but don't try to use hardlinks. + NoLinks = raw::GIT_CLONE_LOCAL_NO_LINKS as isize, + + #[doc(hidden)] + __Nonexhaustive = 0xff, +} + impl<'cb> RepoBuilder<'cb> { /// Creates a new repository builder with all of the default configuration. /// @@ -72,9 +102,11 @@ impl<'cb> RepoBuilder<'cb> { bare: false, branch: None, local: true, + clone_local: None, hardlinks: true, checkout: None, fetch_opts: None, + remote_create: None, } } @@ -93,11 +125,23 @@ impl<'cb> RepoBuilder<'cb> { self } + /// Configures options for bypassing the git-aware transport on clone. + /// + /// Bypassing it means that instead of a fetch libgit2 will copy the object + /// database directory instead of figuring out what it needs, which is + /// faster. If possible, it will hardlink the files to save space. + pub fn clone_local(&mut self, clone_local: CloneLocal) -> &mut RepoBuilder<'cb> { + self.clone_local = Some(clone_local); + self + } + /// Set the flag for bypassing the git aware transport mechanism for local /// paths. /// /// If `true`, the git-aware transport will be bypassed for local paths. If /// `false`, the git-aware transport will not be bypassed. + #[deprecated(note = "use `clone_local` instead")] + #[doc(hidden)] pub fn local(&mut self, local: bool) -> &mut RepoBuilder<'cb> { self.local = local; self @@ -105,6 +149,8 @@ impl<'cb> RepoBuilder<'cb> { /// Set the flag for whether hardlinks are used when using a local git-aware /// transport mechanism. + #[deprecated(note = "use `clone_local` instead")] + #[doc(hidden)] pub fn hardlinks(&mut self, links: bool) -> &mut RepoBuilder<'cb> { self.hardlinks = links; self @@ -128,6 +174,16 @@ impl<'cb> RepoBuilder<'cb> { self } + /// Configures a callback used to create the git remote, prior to its being + /// used to perform the clone operation. + pub fn remote_create(&mut self, f: F) -> &mut RepoBuilder<'cb> + where F: for<'a> FnMut(&'a Repository, &str, &str) + -> Result, Error> + 'cb, + { + self.remote_create = Some(Box::new(f)); + self + } + /// Clone a remote repository. /// /// This will use the options configured so far to clone the specified url @@ -143,13 +199,15 @@ impl<'cb> RepoBuilder<'cb> { s.as_ptr() }).unwrap_or(ptr::null()); - opts.local = match (self.local, self.hardlinks) { - (true, false) => raw::GIT_CLONE_LOCAL_NO_LINKS, - (false, _) => raw::GIT_CLONE_NO_LOCAL, - (true, _) => raw::GIT_CLONE_LOCAL_AUTO, - }; - opts.checkout_opts.checkout_strategy = - raw::GIT_CHECKOUT_SAFE as c_uint; + if let Some(ref local) = self.clone_local { + opts.local = *local as raw::git_clone_local_t; + } else { + opts.local = match (self.local, self.hardlinks) { + (true, false) => raw::GIT_CLONE_LOCAL_NO_LINKS, + (false, _) => raw::GIT_CLONE_NO_LOCAL, + (true, _) => raw::GIT_CLONE_LOCAL_AUTO, + }; + } if let Some(ref mut cbs) = self.fetch_opts { opts.fetch_opts = cbs.raw(); @@ -161,6 +219,11 @@ impl<'cb> RepoBuilder<'cb> { } } + if let Some(ref mut callback) = self.remote_create { + opts.remote_cb = Some(remote_create_cb); + opts.remote_cb_payload = callback as *mut _ as *mut _; + } + let url = try!(CString::new(url)); let into = try!(into.into_c_string()); let mut raw = ptr::null_mut(); @@ -171,6 +234,30 @@ impl<'cb> RepoBuilder<'cb> { } } +extern fn remote_create_cb(out: *mut *mut raw::git_remote, + repo: *mut raw::git_repository, + name: *const c_char, + url: *const c_char, + payload: *mut c_void) -> c_int { + unsafe { + let repo = Repository::from_raw(repo); + let code = panic::wrap(|| { + let name = CStr::from_ptr(name).to_str().unwrap(); + let url = CStr::from_ptr(url).to_str().unwrap(); + let f = payload as *mut Box; + match (*f)(&repo, name, url) { + Ok(remote) => { + *out = ::remote::remote_into_raw(remote); + 0 + } + Err(e) => e.raw_code(), + } + }); + mem::forget(repo); + code.unwrap_or(-1) + } +} + impl<'cb> Default for CheckoutBuilder<'cb> { fn default() -> Self { Self::new() @@ -544,11 +631,6 @@ mod tests { let dst = td.path().join("foo"); RepoBuilder::new().clone(&url, &dst).unwrap(); fs::remove_dir_all(&dst).unwrap(); - RepoBuilder::new().local(false).clone(&url, &dst).unwrap(); - fs::remove_dir_all(&dst).unwrap(); - RepoBuilder::new().local(false).hardlinks(false).bare(true) - .clone(&url, &dst).unwrap(); - fs::remove_dir_all(&dst).unwrap(); assert!(RepoBuilder::new().branch("foo") .clone(&url, &dst).is_err()); } diff --git a/src/remote.rs b/src/remote.rs index 2324803f59..9e1704c40e 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -59,6 +59,12 @@ pub struct RemoteConnection<'repo, 'connection, 'cb> where 'repo: 'connection { remote: &'connection mut Remote<'repo>, } +pub fn remote_into_raw(remote: Remote) -> *mut raw::git_remote { + let ret = remote.raw; + mem::forget(remote); + return ret +} + impl<'repo> Remote<'repo> { /// Ensure the remote name is well-formed. pub fn is_valid_name(remote_name: &str) -> bool { @@ -282,7 +288,7 @@ impl<'repo> Remote<'repo> { &[RemoteHead]>(slice)) } } - + /// Get the remote's list of fetch refspecs pub fn fetch_refspecs(&self) -> Result { unsafe { From a5e0bd8a0d301dc17979451a102f570ffe3d9ab1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 8 Jan 2018 09:35:29 -0800 Subject: [PATCH 214/860] Bump to 0.6.11 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 17126f395a..03132f5142 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.10" +version = "0.6.11" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 4f168b30ddf9bbbb5643fece652f8150995b965e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 8 Jan 2018 09:36:12 -0800 Subject: [PATCH 215/860] Bump libgit2-sys to 0.6.19 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index e9720977d4..ce4d09169a 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.6.18" +version = "0.6.19" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From b3d789cb7c0e24fd6007520c3a4e6a322aa49f40 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 8 Jan 2018 09:36:47 -0800 Subject: [PATCH 216/860] Bump dep on libgit2-sys --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 03132f5142..c645fdbe45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ appveyor = { repository = "alexcrichton/git2-rs" } url = "1.0" bitflags = "0.9" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.6.17" } +libgit2-sys = { path = "libgit2-sys", version = "0.6.19" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 3968c83425d700777149150542c8e47da2770074 Mon Sep 17 00:00:00 2001 From: technetos Date: Tue, 9 Jan 2018 21:46:44 -0500 Subject: [PATCH 217/860] fixed typo in no_dotgit_dir documentation --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index b0bf693f9c..b685aa0493 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1970,7 +1970,7 @@ impl RepositoryInitOptions { self.flag(raw::GIT_REPOSITORY_INIT_NO_REINIT, enabled) } - /// Normally a '/.git/' will be appended to the repo apth for non-bare repos + /// Normally a '/.git/' will be appended to the repo path for non-bare repos /// (if it is not already there), but passing this flag prevents that /// behavior. /// From d3385ecd006b756323113cf79fa8e317104a4326 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Wed, 17 Jan 2018 20:53:51 +0100 Subject: [PATCH 218/860] Include license files in git2-curl package --- git2-curl/LICENSE-APACHE | 1 + git2-curl/LICENSE-MIT | 1 + 2 files changed, 2 insertions(+) create mode 120000 git2-curl/LICENSE-APACHE create mode 120000 git2-curl/LICENSE-MIT diff --git a/git2-curl/LICENSE-APACHE b/git2-curl/LICENSE-APACHE new file mode 120000 index 0000000000..965b606f33 --- /dev/null +++ b/git2-curl/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/git2-curl/LICENSE-MIT b/git2-curl/LICENSE-MIT new file mode 120000 index 0000000000..76219eb72e --- /dev/null +++ b/git2-curl/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file From 29294310fd8ffc3edeb51484b19448d3a42014b0 Mon Sep 17 00:00:00 2001 From: Kenneth Endfinger Date: Wed, 17 Jan 2018 15:32:45 -0500 Subject: [PATCH 219/860] Expand Bindings (#278) * Ongoing work on porting more functions. * Implementing more features. * Implement wrapping the ODB as a repository. * Implement basic OdbBackend wrapper. * Add libgit2-sys bindings for ODB/RefDB backends. * Add a binding for git_odb_init_backend to libgit2-sys * Rename 'OdbBackend' to 'OdbBackendHolder' for future custom OdbBackend support. * Fix some raw bindings for refdb. * Binding more functions. * Implement bindings for consuming ODB backends. * Implement full mempack support. * Bind more functions for Repository. * Fix review comments for binding expansion. * Remove ODB Backend Support --- libgit2-sys/lib.rs | 237 ++++++++++++++++++++++++++++++++++++++++++++- src/odb.rs | 146 ++++++++++++++++++++++++++-- src/oid.rs | 74 +++++++++++++- src/repo.rs | 83 +++++++++++++++- systest/build.rs | 4 + 5 files changed, 533 insertions(+), 11 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 926c9839a7..0fc4ca8d30 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -23,6 +23,8 @@ 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; pub const GIT_SUBMODULE_UPDATE_OPTIONS_VERSION: c_uint = 1; +pub const GIT_ODB_BACKEND_VERSION: c_uint = 1; +pub const GIT_REFDB_BACKEND_VERSION: c_uint = 1; macro_rules! git_enum { (pub enum $name:ident { $($variants:tt)* }) => { @@ -58,6 +60,7 @@ pub enum git_object {} pub enum git_reference {} pub enum git_reference_iterator {} pub enum git_annotated_commit {} +pub enum git_refdb {} pub enum git_refspec {} pub enum git_remote {} pub enum git_repository {} @@ -83,6 +86,8 @@ pub enum git_packbuilder {} pub enum git_odb {} pub enum git_odb_stream {} pub enum git_odb_object {} +pub enum git_odb_writepack {} +pub enum git_worktree {} #[repr(C)] pub struct git_revspec { @@ -1277,6 +1282,127 @@ pub struct git_transport { pub free: extern fn(*mut git_transport), } +#[repr(C)] +pub struct git_odb_backend { + pub version: c_uint, + pub odb: *mut git_odb, + pub read: extern fn(*mut *mut c_void, + *mut size_t, + *mut git_otype, + *mut git_odb_backend, + *const git_oid) -> c_int, + + pub read_prefix: extern fn(*mut git_oid, + *mut *mut c_void, + *mut size_t, + *mut git_otype, + *mut git_odb_backend, + *const git_oid, + size_t) -> c_int, + pub read_header: extern fn(*mut size_t, + *mut git_otype, + *mut git_odb_backend, + *const git_oid) -> c_int, + + pub write: extern fn(*mut git_odb_backend, + *const git_oid, + *const c_void, + size_t, + git_otype) -> c_int, + + pub writestream: extern fn(*mut *mut git_odb_stream, + *mut git_odb_backend, + git_off_t, + git_otype) -> c_int, + + pub readstream: extern fn(*mut *mut git_odb_stream, + *mut git_odb_backend, + *const git_oid) -> c_int, + + pub exists: extern fn(*mut git_odb_backend, + *const git_oid) -> c_int, + + pub exists_prefix: extern fn(*mut git_oid, + *mut git_odb_backend, + *const git_oid, + size_t) -> c_int, + + pub refresh: extern fn(*mut git_odb_backend) -> c_int, + + pub foreach: extern fn(*mut git_odb_backend, + git_odb_foreach_cb, + *mut c_void) -> c_int, + + pub writepack: extern fn(*mut *mut git_odb_writepack, + *mut git_odb_backend, + *mut git_odb, + git_transfer_progress_cb, + *mut c_void) -> c_int, + + pub freshen: extern fn(*mut git_odb_backend, + *const git_oid) -> c_int, + + pub free: extern fn(*mut git_odb_backend), +} + +#[repr(C)] +pub struct git_refdb_backend { + pub version: c_uint, + pub exists: extern fn(*mut c_int, + *mut git_refdb_backend, + *const c_char) -> c_int, + pub lookup: extern fn(*mut *mut git_reference, + *mut git_refdb_backend, + *const c_char) -> c_int, + pub iterator: extern fn(*mut *mut git_reference_iterator, + *mut git_refdb_backend, + *const c_char) -> c_int, + pub write: extern fn(*mut git_refdb_backend, + *const git_reference, + c_int, + *const git_signature, + *const c_char, + *const git_oid, + *const c_char) -> c_int, + pub rename: extern fn(*mut *mut git_reference, + *mut git_refdb_backend, + *const c_char, + *const c_char, + c_int, + *const git_signature, + *const c_char) -> c_int, + pub del: extern fn(*mut git_refdb_backend, + *const c_char, + *const git_oid, + *const c_char) -> c_int, + pub compress: extern fn(*mut git_refdb_backend) -> c_int, + pub has_log: extern fn(*mut git_refdb_backend, + *const c_char) -> c_int, + pub ensure_log: extern fn(*mut git_refdb_backend, + *const c_char) -> c_int, + pub free: extern fn(*mut git_refdb_backend), + pub reflog_read: extern fn(*mut *mut git_reflog, + *mut git_refdb_backend, + *const c_char) -> c_int, + pub reflog_write: extern fn(*mut git_refdb_backend, + *mut git_reflog) -> c_int, + pub reflog_rename: extern fn(*mut git_refdb_backend, + *const c_char, + *const c_char) -> c_int, + pub reflog_delete: extern fn(*mut git_refdb_backend, + *const c_char) -> c_int, + pub lock: extern fn(*mut *mut c_void, + *mut git_refdb_backend, + *const c_char) -> c_int, + pub unlock: extern fn(*mut git_refdb_backend, + *mut c_void, + c_int, + c_int, + *const git_reference, + *const git_signature, + *const c_char) -> c_int +} + #[repr(C)] pub struct git_proxy_options { pub version: c_uint, @@ -1428,13 +1554,20 @@ extern { pub fn git_libgit2_shutdown() -> c_int; // repository + pub fn git_repository_new(out: *mut *mut git_repository) -> c_int; 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_bare(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_open_from_worktree(repo: *mut *mut git_repository, + worktree: *mut git_worktree) -> c_int; + pub fn git_repository_wrap_odb(repo: *mut *mut git_repository, + odb: *mut git_odb) -> c_int; pub fn git_repository_init(repo: *mut *mut git_repository, path: *const c_char, is_bare: c_uint) -> c_int; @@ -1446,15 +1579,21 @@ extern { version: c_uint) -> c_int; pub fn git_repository_get_namespace(repo: *mut git_repository) -> *const c_char; + pub fn git_repository_set_namespace(repo: *mut git_repository, + namespace: *const c_char) -> c_int; pub fn git_repository_head(out: *mut *mut git_reference, repo: *mut git_repository) -> c_int; pub fn git_repository_set_head(repo: *mut git_repository, refname: *const c_char) -> c_int; + + pub fn git_repository_head_detached(repo: *mut git_repository) -> c_int; pub fn git_repository_set_head_detached(repo: *mut git_repository, commitish: *const git_oid) -> c_int; + pub fn git_repository_set_bare(repo: *mut git_repository) -> c_int; pub fn git_repository_is_bare(repo: *mut git_repository) -> c_int; pub fn git_repository_is_empty(repo: *mut git_repository) -> c_int; pub fn git_repository_is_shallow(repo: *mut git_repository) -> c_int; + pub fn git_repository_is_worktree(repo: *mut git_repository) -> c_int; pub fn git_repository_path(repo: *mut git_repository) -> *const c_char; pub fn git_repository_state(repo: *mut git_repository) -> c_int; pub fn git_repository_workdir(repo: *mut git_repository) -> *const c_char; @@ -1465,14 +1604,31 @@ extern { repo: *mut git_repository) -> c_int; pub fn git_repository_set_index(repo: *mut git_repository, index: *mut git_index); + + pub fn git_repository_message(buf: *mut git_buf, + repo: *mut git_repository) -> c_int; + + pub fn git_repository_message_remove(repo: *mut git_repository) -> c_int; pub fn git_repository_config(out: *mut *mut git_config, repo: *mut git_repository) -> c_int; + pub fn git_repository_set_config(repo: *mut git_repository, + config: *mut git_config); pub fn git_repository_config_snapshot(out: *mut *mut git_config, repo: *mut git_repository) -> c_int; pub fn git_repository_discover(out: *mut git_buf, start_path: *const c_char, across_fs: c_int, ceiling_dirs: *const c_char) -> c_int; + pub fn git_repository_set_odb(repo: *mut git_repository, + odb: *mut git_odb); + + pub fn git_repository_refdb(out: *mut *mut git_refdb, + repo: *mut git_repository) -> c_int; + pub fn git_repository_set_refdb(repo: *mut git_repository, + refdb: *mut git_refdb); + + pub fn git_repository_reinit_filesystem(repo: *mut git_repository, + recurse_submodules: c_int) -> c_int; pub fn git_ignore_add_rule(repo: *mut git_repository, rules: *const c_char) -> c_int; pub fn git_ignore_clear_internal_rules(repo: *mut git_repository) -> c_int; @@ -2669,6 +2825,7 @@ extern { // odb pub fn git_repository_odb(out: *mut *mut git_odb, repo: *mut git_repository) -> c_int; + pub fn git_odb_new(db: *mut *mut git_odb) -> c_int; pub fn git_odb_free(db: *mut git_odb); pub fn git_odb_open_rstream(out: *mut *mut git_odb_stream, db: *mut git_odb, @@ -2692,13 +2849,91 @@ extern { odb: *mut git_odb, oid: *const git_oid) -> c_int; + pub fn git_odb_read_header(len_out: *mut size_t, + type_out: *mut git_otype, + odb: *mut git_odb, + oid: *const git_oid) -> c_int; + + pub fn git_odb_write(out: *mut git_oid, + odb: *mut git_odb, + data: *const c_void, + len: size_t, + otype: git_otype) -> c_int; + + pub fn git_odb_hash(out: *mut git_oid, + data: *const c_void, + len: size_t, + otype: git_otype) -> c_int; + + pub fn git_odb_hashfile(out: *mut git_oid, + path: *const c_char, + otype: git_otype) -> c_int; + + pub fn git_odb_exists_prefix(out: *mut git_oid, + odb: *mut git_odb, + short_oid: *const git_oid, + len: size_t) -> c_int; + pub fn git_odb_exists(odb: *mut git_odb, oid: *const git_oid) -> c_int; + pub fn git_odb_refresh(odb: *mut git_odb) -> c_int; + + pub fn git_odb_object_id(obj: *mut git_odb_object) -> *const git_oid; pub fn git_odb_object_size(obj: *mut git_odb_object) -> size_t; pub fn git_odb_object_type(obj: *mut git_odb_object) -> git_otype; pub fn git_odb_object_data(obj: *mut git_odb_object) -> *const c_void; + pub fn git_odb_object_dup(out: *mut *mut git_odb_object, + obj: *mut git_odb_object) -> c_int; pub fn git_odb_object_free(obj: *mut git_odb_object); + + pub fn git_odb_init_backend(odb: *mut git_odb_backend, + version: c_uint) -> c_int; + + pub fn git_odb_add_backend(odb: *mut git_odb, + backend: *mut git_odb_backend, + priority: c_int) -> c_int; + + pub fn git_odb_backend_pack(out: *mut *mut git_odb_backend, + objects_dir: *const c_char) -> c_int; + + pub fn git_odb_backend_one_pack(out: *mut *mut git_odb_backend, + objects_dir: *const c_char) -> c_int; + + pub fn git_odb_add_disk_alternate(odb: *mut git_odb, + path: *const c_char) -> c_int; + + pub fn git_odb_backend_loose(out: *mut *mut git_odb_backend, + objects_dir: *const c_char, + compression_level: c_int, + do_fsync: c_int, + dir_mode: c_uint, + file_mode: c_uint) -> c_int; + + pub fn git_odb_add_alternate(odb: *mut git_odb, + backend: *mut git_odb_backend, + priority: c_int) -> c_int; + + pub fn git_odb_num_backends(odb: *mut git_odb) -> size_t; + pub fn git_odb_get_backend(backend: *mut *mut git_odb_backend, + odb: *mut git_odb, + position: size_t) -> c_int; + + // mempack + pub fn git_mempack_new(out: *mut *mut git_odb_backend) -> c_int; + pub fn git_mempack_reset(backend: *mut git_odb_backend); + pub fn git_mempack_dump(pack: *mut git_buf, + repo: *mut git_repository, + backend: *mut git_odb_backend) -> c_int; + + // refdb + pub fn git_refdb_new(out: *mut *mut git_refdb, repo: *mut git_repository) -> c_int; + pub fn git_refdb_open(out: *mut *mut git_refdb, repo: *mut git_repository) -> c_int; + pub fn git_refdb_backend_fs(out: *mut *mut git_refdb_backend, repo: *mut git_repository) -> c_int; + pub fn git_refdb_init_backend(backend: *mut git_refdb_backend, version: c_uint) -> c_int; + pub fn git_refdb_set_backend(refdb: *mut git_refdb, backend: *mut git_refdb_backend) -> c_int; + pub fn git_refdb_compress(refdb: *mut git_refdb) -> c_int; + pub fn git_refdb_free(refdb: *mut git_refdb); } pub fn init() { @@ -2713,7 +2948,7 @@ pub fn init() { "couldn't initialize the libgit2 library: {}", r); // Note that we intentionally never schedule `git_libgit2_shutdown` to - // get called. There's not really a great tiem to call that and #276 has + // get called. There's not really a great time to call that and #276 has // some more info about how automatically doing it can cause problems. }); } diff --git a/src/odb.rs b/src/odb.rs index 754a63d087..471236ac88 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -3,7 +3,9 @@ use std::io; use std::ptr; use std::slice; -use libc::{c_char, c_int, c_void}; +use std::ffi::CString; + +use libc::{c_char, c_int, c_void, size_t}; use {raw, Oid, Object, ObjectType, Error}; use panic; @@ -34,9 +36,19 @@ impl<'repo> Drop for Odb<'repo> { } impl<'repo> Odb<'repo> { - /// Create object database reading stream + /// Creates an object database without any backends. + pub fn new<'a>() -> Result, Error> { + unsafe { + let mut out = ptr::null_mut(); + try_call!(raw::git_odb_new(&mut out)); + Ok(Odb::from_raw(out)) + } + } + + /// Create object database reading stream. /// /// Note that most backends do not support streaming reads because they store their objects as compressed/delta'ed blobs. + /// If the backend does not support streaming reads, use the `read` method instead. pub fn reader(&self, oid: Oid) -> Result { let mut out = ptr::null_mut(); unsafe { @@ -45,9 +57,10 @@ impl<'repo> Odb<'repo> { } } - /// Create object database writing stream + /// Create object database writing stream. /// /// The type and final length of the object must be specified when opening the stream. + /// If the backend does not support streaming writes, use the `write` method instead. pub fn writer(&self, size: usize, obj_type: ObjectType) -> Result { let mut out = ptr::null_mut(); unsafe { @@ -56,7 +69,7 @@ impl<'repo> Odb<'repo> { } } - /// Iterate over all objects in the object database + /// Iterate over all objects in the object database.s pub fn foreach(&self, mut callback: C) -> Result<(), Error> where C: FnMut(&Oid) -> bool { @@ -69,7 +82,7 @@ impl<'repo> Odb<'repo> { } } - /// Read object from the database. + /// Read an object from the database. pub fn read(&self, oid: Oid) -> Result { let mut out = ptr::null_mut(); unsafe { @@ -78,10 +91,76 @@ impl<'repo> Odb<'repo> { } } + /// Reads the header of an object from the database + /// without reading the full content. + pub fn read_header(&self, oid: Oid) -> Result<(usize, ObjectType), Error> { + let mut size: usize = 0; + let mut kind_id: i32 = ObjectType::Any.raw(); + + unsafe { + try_call!(raw::git_odb_read_header(&mut size + as *mut size_t, + &mut kind_id + as *mut raw::git_otype, + self.raw, + oid.raw())); + + Ok((size, ObjectType::from_raw(kind_id).unwrap())) + } + } + + /// Write an object to the database. + pub fn write(&self, kind: ObjectType, data: &[u8]) -> Result { + unsafe { + let mut out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + try_call!(raw::git_odb_write(&mut out, + self.raw, + data.as_ptr() + as *const c_void, + data.len(), + kind.raw())); + Ok(Oid::from_raw(&mut out)) + } + } + /// Checks if the object database has an object. pub fn exists(&self, oid: Oid) -> bool { unsafe { raw::git_odb_exists(self.raw, oid.raw()) != -1 } } + + /// Potentially finds an object that starts with the given prefix. + pub fn exists_prefix(&self, short_oid: Oid, len: usize) -> Result { + unsafe { + let mut out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + try_call!(raw::git_odb_exists_prefix(&mut out, + self.raw, + short_oid.raw(), + len)); + Ok(Oid::from_raw(&out)) + } + } + + /// Refresh the object database. + /// This should never be needed, and is + /// provided purely for convenience. + /// The object database will automatically + /// refresh when an object is not found when + /// requested. + pub fn refresh(&self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_odb_refresh(self.raw)); + Ok(()) + } + } + + /// Adds an alternate disk backend to the object database. + pub fn add_disk_alternate(&self, path: &str) -> Result<(), Error> { + unsafe { + let path = try!(CString::new(path)); + try_call!(raw::git_odb_add_disk_alternate(self.raw, path)); + Ok(()) + } + } } /// An object from the Object Database. @@ -129,6 +208,11 @@ impl<'a> OdbObject<'a> { return buffer; } } + + /// Get the object id. + pub fn id(&self) -> Oid { + unsafe { Oid::from_raw(raw::git_odb_object_id(self.raw)) } + } } /// A structure to represent a git ODB rstream @@ -251,10 +335,10 @@ extern fn foreach_cb(id: *const raw::git_oid, mod tests { use std::io::prelude::*; use tempdir::TempDir; - use {Repository, ObjectType}; + use {Repository, ObjectType, Oid}; #[test] - fn reader() { + fn read() { let td = TempDir::new("test").unwrap(); let repo = Repository::init(td.path()).unwrap(); let dat = [4, 3, 5, 6, 9]; @@ -265,6 +349,31 @@ mod tests { let size = obj.len(); assert_eq!(size, 5); assert_eq!(dat, data); + assert_eq!(id, obj.id()); + } + + #[test] + fn read_header() { + let td = TempDir::new("test").unwrap(); + let repo = Repository::init(td.path()).unwrap(); + let dat = [4, 3, 5, 6, 9]; + let id = repo.blob(&dat).unwrap(); + let db = repo.odb().unwrap(); + let (size, kind) = db.read_header(id).unwrap(); + + assert_eq!(size, 5); + assert_eq!(kind, ObjectType::Blob); + } + + #[test] + fn write() { + let td = TempDir::new("test").unwrap(); + let repo = Repository::init(td.path()).unwrap(); + let dat = [4, 3, 5, 6, 9]; + let db = repo.odb().unwrap(); + let id = db.write(ObjectType::Blob, &dat).unwrap(); + let blob = repo.find_blob(id).unwrap(); + assert_eq!(blob.content(), dat); } #[test] @@ -282,4 +391,27 @@ mod tests { let blob = repo.find_blob(id).unwrap(); assert_eq!(blob.content(), dat); } + + #[test] + fn exists() { + let td = TempDir::new("test").unwrap(); + let repo = Repository::init(td.path()).unwrap(); + let dat = [4, 3, 5, 6, 9]; + let db = repo.odb().unwrap(); + let id = db.write(ObjectType::Blob, &dat).unwrap(); + assert!(db.exists(id)); + } + + #[test] + fn exists_prefix() { + let td = TempDir::new("test").unwrap(); + let repo = Repository::init(td.path()).unwrap(); + let dat = [4, 3, 5, 6, 9]; + let db = repo.odb().unwrap(); + let id = db.write(ObjectType::Blob, &dat).unwrap(); + let id_prefix_str = &id.to_string()[0..10]; + let id_prefix = Oid::from_str(id_prefix_str).unwrap(); + let found_oid = db.exists_prefix(id_prefix, 10).unwrap(); + assert_eq!(found_oid, id); + } } diff --git a/src/oid.rs b/src/oid.rs index 26e0cc70c9..acd6d67e63 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -2,15 +2,17 @@ use std::fmt; use std::cmp::Ordering; use std::hash::{Hasher, Hash}; use std::str; +use std::path::Path; use libc; -use {raw, Error}; +use {raw, Error, ObjectType, IntoCString}; + use util::Binding; /// Unique identity of any object (commit, tree, blob, tag). #[derive(Copy, Clone)] pub struct Oid { - raw: raw::git_oid, + raw: raw::git_oid } impl Oid { @@ -44,6 +46,48 @@ impl Oid { } } + /// Creates an all zero Oid structure. + pub fn zero() -> Oid { + let out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + Oid { raw: out } + } + + /// Hashes the provided data as an object of the provided type, and returns + /// an Oid corresponding to the result. This does not store the object + /// inside any object database or repository. + pub fn hash_object(kind: ObjectType, bytes: &[u8]) -> Result { + ::init(); + + let mut out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + unsafe { + try_call!(raw::git_odb_hash(&mut out, + bytes.as_ptr() + as *const libc::c_void, + bytes.len(), + kind.raw())); + } + + Ok(Oid { raw: out }) + } + + /// Hashes the content of the provided file as an object of the provided type, + /// and returns an Oid corresponding to the result. This does not store the object + /// inside any object database or repository. + pub fn hash_file>(kind: ObjectType, path: P) -> Result { + ::init(); + + let rpath = try!(path.as_ref().into_c_string()); + + let mut out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + unsafe { + try_call!(raw::git_odb_hashfile(&mut out, + rpath, + kind.raw())); + } + + Ok(Oid { raw: out }) + } + /// View this OID as a byte-slice 20 bytes in length. pub fn as_bytes(&self) -> &[u8] { &self.raw.id } @@ -128,6 +172,11 @@ impl AsRef<[u8]> for Oid { #[cfg(test)] mod tests { + use std::io::prelude::*; + use std::fs::File; + + use tempdir::TempDir; + use {ObjectType}; use super::Oid; #[test] @@ -137,4 +186,25 @@ mod tests { assert!(Oid::from_bytes(b"foo").is_err()); assert!(Oid::from_bytes(b"00000000000000000000").is_ok()); } + + #[test] + fn zero_is_zero() { + assert!(Oid::zero().is_zero()); + } + + #[test] + fn hash_object() { + let bytes = "Hello".as_bytes(); + assert!(Oid::hash_object(ObjectType::Blob, bytes).is_ok()); + } + + #[test] + fn hash_file() { + let td = TempDir::new("test").unwrap(); + let path = td.path().join("hello.txt"); + let mut file = File::create(&path).unwrap(); + file.write_all("Hello".as_bytes()).unwrap(); + assert!(Oid::hash_file(ObjectType::Blob, &path).is_ok()); + } } + diff --git a/src/repo.rs b/src/repo.rs index b685aa0493..119e3fbd1e 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -62,6 +62,19 @@ impl Repository { } } + /// Attempt to open an already-existing bare repository at `path`. + /// + /// The path can point to only a bare repository. + pub fn open_bare>(path: P) -> Result { + init(); + let path = try!(path.as_ref().into_c_string()); + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_repository_open_bare(&mut ret, path)); + Ok(Binding::from_raw(ret)) + } + } + /// Find and open an existing repository, respecting git environment /// variables. This acts like `open_ext` with the /// `REPOSITORY_OPEN_FROM_ENV` flag, but additionally respects `$GIT_DIR`. @@ -194,6 +207,16 @@ impl Repository { Ok(repo) } + /// Attempt to wrap an object database as a repository. + pub fn from_odb(odb: Odb) -> Result { + init(); + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_repository_wrap_odb(&mut ret, odb.raw())); + Ok(Binding::from_raw(ret)) + } + } + /// Update submodules recursively. /// /// Uninitialized submodules will be initialized. @@ -279,6 +302,11 @@ impl Repository { unsafe { raw::git_repository_is_shallow(self.raw) == 1 } } + /// Tests whether this repository is a worktree. + pub fn is_worktree(&self) -> bool { + unsafe { raw::git_repository_is_worktree(self.raw) == 1 } + } + /// Tests whether this repository is empty. pub fn is_empty(&self) -> Result { let empty = unsafe { @@ -368,6 +396,48 @@ impl Repository { unsafe { ::opt_bytes(self, raw::git_repository_get_namespace(self.raw)) } } + /// Set the active namespace for this repository. + pub fn set_namespace(&self, namespace: &str) -> Result<(), Error> { + self.set_namespace_bytes(namespace.as_bytes()) + } + + /// Set the active namespace for this repository as a byte array. + pub fn set_namespace_bytes(&self, namespace: &[u8]) -> Result<(), Error> { + unsafe { + let namespace = try!(CString::new(namespace)); + try_call!(raw::git_repository_set_namespace(self.raw, + namespace)); + Ok(()) + } + } + + /// Remove the active namespace for this repository. + pub fn remove_namespace(&self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_repository_set_namespace(self.raw, + ptr::null())); + Ok(()) + } + } + + /// Retrieves the Git merge message. + /// Remember to remove the message when finished. + pub fn message(&self) -> Result { + unsafe { + let buf = Buf::new(); + try_call!(raw::git_repository_message(buf.raw(), self.raw)); + Ok(str::from_utf8(&buf).unwrap().to_string()) + } + } + + /// Remove the Git merge message. + pub fn remove_message(&self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_repository_message_remove(self.raw)); + Ok(()) + } + } + /// List all remotes for a given repository pub fn remotes(&self) -> Result { let mut arr = raw::git_strarray { @@ -594,6 +664,18 @@ impl Repository { Ok(()) } + /// Determines whether the repository HEAD is detached. + pub fn head_detached(&self) -> Result { + unsafe { + let value = raw::git_repository_head_detached(self.raw); + match value { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(Error::last_error(value).unwrap()) + } + } + } + /// Make the repository HEAD directly point to the commit. /// /// If the provided committish cannot be found in the repository, the HEAD @@ -1573,7 +1655,6 @@ impl Repository { } } - /// Count the number of unique commits between two commit objects /// /// There is no need for branches containing the commits to have any diff --git a/systest/build.rs b/systest/build.rs index e68803897b..fad3e55739 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -9,6 +9,10 @@ fn main() { let mut cfg = ctest::TestGenerator::new(); cfg.header("git2.h") .header("git2/sys/transport.h") + .header("git2/sys/refs.h") + .header("git2/sys/refdb_backend.h") + .header("git2/sys/odb_backend.h") + .header("git2/sys/mempack.h") .header("git2/sys/repository.h") .header("git2/cred_helpers.h") .include(root.join("include")) From 5fe422e7eec3448bb967df2dfabe82e87748750d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 18 Jan 2018 19:42:05 +0000 Subject: [PATCH 220/860] Update to libgit2 f1323d9c (#286) * Updte to libgit2 668fa071ff * Update libgit2 to fd1492e82 * Update libgit2 to f1323d9c * Let us enable the indent heuristic in diffs * Expose the sign in Time * Tweaks to fix compile and pass systest * Flags are unsigned now! --- libgit2-sys/build.rs | 5 ++- libgit2-sys/lib.rs | 91 ++++++++++++++++++++++++-------------------- libgit2-sys/libgit2 | 2 +- src/config.rs | 2 +- src/diff.rs | 10 ++++- src/patch.rs | 6 +-- src/time.rs | 7 +++- 7 files changed, 72 insertions(+), 51 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index c7545c2eb0..1f0e97aae4 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -110,6 +110,7 @@ fn main() { cfg.register_dep("OPENSSL"); } else { cfg.define("USE_OPENSSL", "OFF"); + cfg.define("USE_HTTPS", "OFF"); } if curl { cfg.register_dep("CURL"); @@ -130,10 +131,10 @@ fn main() { // Make sure libssh2 was detected on unix systems, because it definitely // should have been! if ssh && !msvc { - let flags = dst.join("build/CMakeFiles/git2.dir/flags.make"); + let flags = dst.join("build/src/git2/sys/features.h"); let mut contents = String::new(); t!(t!(File::open(flags)).read_to_string(&mut contents)); - if !contents.contains("-DGIT_SSH") { + if !contents.contains("#define GIT_SSH 1") { panic!("libgit2 failed to find libssh2, and SSH support is required"); } } diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 0fc4ca8d30..b60275668e 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -140,6 +140,7 @@ pub struct git_signature { pub struct git_time { pub time: git_time_t, pub offset: c_int, + pub sign: c_char, } pub type git_off_t = i64; @@ -328,9 +329,7 @@ pub struct git_remote_callbacks { *mut c_void) -> c_int>, pub pack_progress: Option, pub push_transfer_progress: Option, - pub push_update_reference: Option c_int>, + pub push_update_reference: Option, pub push_negotiation: Option, pub transport: Option, pub payload: *mut c_void, @@ -391,6 +390,10 @@ pub type git_push_negotiation = extern fn(*mut *const git_push_update, size_t, *mut c_void) -> c_int; +pub type git_push_update_reference_cb = extern fn(*const c_char, + *const c_char, + *mut c_void) -> c_int; + #[repr(C)] pub struct git_push_update { pub src_refname: *mut c_char, @@ -551,6 +554,7 @@ pub struct git_status_options { pub show: git_status_show_t, pub flags: c_uint, pub pathspec: git_strarray, + pub baseline: *mut git_tree, } #[repr(C)] @@ -1076,34 +1080,36 @@ pub type git_diff_progress_cb = extern fn (*const git_diff, *const c_char, *mut c_void) -> c_int; -pub const GIT_DIFF_NORMAL: u32 = 0; -pub const GIT_DIFF_REVERSE: u32 = 1 << 0; -pub const GIT_DIFF_INCLUDE_IGNORED: u32 = 1 << 1; -pub const GIT_DIFF_RECURSE_IGNORED_DIRS: u32 = 1 << 2; -pub const GIT_DIFF_INCLUDE_UNTRACKED: u32 = 1 << 3; -pub const GIT_DIFF_RECURSE_UNTRACKED_DIRS: u32 = 1 << 4; -pub const GIT_DIFF_INCLUDE_UNMODIFIED: u32 = 1 << 5; -pub const GIT_DIFF_INCLUDE_TYPECHANGE: u32 = 1 << 6; -pub const GIT_DIFF_INCLUDE_TYPECHANGE_TREES: u32 = 1 << 7; -pub const GIT_DIFF_IGNORE_FILEMODE: u32 = 1 << 8; -pub const GIT_DIFF_IGNORE_SUBMODULES: u32 = 1 << 9; -pub const GIT_DIFF_IGNORE_CASE: u32 = 1 << 10; -pub const GIT_DIFF_DISABLE_PATHSPEC_MATCH: u32 = 1 << 12; -pub const GIT_DIFF_SKIP_BINARY_CHECK: u32 = 1 << 13; -pub const GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS: u32 = 1 << 14; -pub const GIT_DIFF_UPDATE_INDEX: u32 = 1 << 15; -pub const GIT_DIFF_INCLUDE_UNREADABLE: u32 = 1 << 16; -pub const GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED: u32 = 1 << 17; -pub const GIT_DIFF_FORCE_TEXT: u32 = 1 << 20; -pub const GIT_DIFF_FORCE_BINARY: u32 = 1 << 21; -pub const GIT_DIFF_IGNORE_WHITESPACE: u32 = 1 << 22; -pub const GIT_DIFF_IGNORE_WHITESPACE_CHANGE: u32 = 1 << 23; -pub const GIT_DIFF_IGNORE_WHITESPACE_EOL: u32 = 1 << 24; -pub const GIT_DIFF_SHOW_UNTRACKED_CONTENT: u32 = 1 << 25; -pub const GIT_DIFF_SHOW_UNMODIFIED: u32 = 1 << 26; -pub const GIT_DIFF_PATIENCE: u32 = 1 << 28; -pub const GIT_DIFF_MINIMAL: u32 = 1 << 29; -pub const GIT_DIFF_SHOW_BINARY: u32 = 1 << 30; +pub type git_diff_option_t = i32; +pub const GIT_DIFF_NORMAL: git_diff_option_t = 0; +pub const GIT_DIFF_REVERSE: git_diff_option_t = 1 << 0; +pub const GIT_DIFF_INCLUDE_IGNORED: git_diff_option_t = 1 << 1; +pub const GIT_DIFF_RECURSE_IGNORED_DIRS: git_diff_option_t = 1 << 2; +pub const GIT_DIFF_INCLUDE_UNTRACKED: git_diff_option_t = 1 << 3; +pub const GIT_DIFF_RECURSE_UNTRACKED_DIRS: git_diff_option_t = 1 << 4; +pub const GIT_DIFF_INCLUDE_UNMODIFIED: git_diff_option_t = 1 << 5; +pub const GIT_DIFF_INCLUDE_TYPECHANGE: git_diff_option_t = 1 << 6; +pub const GIT_DIFF_INCLUDE_TYPECHANGE_TREES: git_diff_option_t = 1 << 7; +pub const GIT_DIFF_IGNORE_FILEMODE: git_diff_option_t = 1 << 8; +pub const GIT_DIFF_IGNORE_SUBMODULES: git_diff_option_t = 1 << 9; +pub const GIT_DIFF_IGNORE_CASE: git_diff_option_t = 1 << 10; +pub const GIT_DIFF_DISABLE_PATHSPEC_MATCH: git_diff_option_t = 1 << 12; +pub const GIT_DIFF_SKIP_BINARY_CHECK: git_diff_option_t = 1 << 13; +pub const GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS: git_diff_option_t = 1 << 14; +pub const GIT_DIFF_UPDATE_INDEX: git_diff_option_t = 1 << 15; +pub const GIT_DIFF_INCLUDE_UNREADABLE: git_diff_option_t = 1 << 16; +pub const GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED: git_diff_option_t = 1 << 17; +pub const GIT_DIFF_FORCE_TEXT: git_diff_option_t = 1 << 20; +pub const GIT_DIFF_FORCE_BINARY: git_diff_option_t = 1 << 21; +pub const GIT_DIFF_IGNORE_WHITESPACE: git_diff_option_t = 1 << 22; +pub const GIT_DIFF_IGNORE_WHITESPACE_CHANGE: git_diff_option_t = 1 << 23; +pub const GIT_DIFF_IGNORE_WHITESPACE_EOL: git_diff_option_t = 1 << 24; +pub const GIT_DIFF_SHOW_UNTRACKED_CONTENT: git_diff_option_t = 1 << 25; +pub const GIT_DIFF_SHOW_UNMODIFIED: git_diff_option_t = 1 << 26; +pub const GIT_DIFF_PATIENCE: git_diff_option_t = 1 << 28; +pub const GIT_DIFF_MINIMAL: git_diff_option_t = 1 << 29; +pub const GIT_DIFF_SHOW_BINARY: git_diff_option_t = 1 << 30; +pub const GIT_DIFF_INDENT_HEURISTIC: git_diff_option_t = 1 << 31; #[repr(C)] pub struct git_diff_find_options { @@ -1590,13 +1596,13 @@ extern { pub fn git_repository_set_head_detached(repo: *mut git_repository, commitish: *const git_oid) -> c_int; pub fn git_repository_set_bare(repo: *mut git_repository) -> c_int; - pub fn git_repository_is_bare(repo: *mut git_repository) -> c_int; + pub fn git_repository_is_worktree(repo: *const git_repository) -> c_int; + pub fn git_repository_is_bare(repo: *const git_repository) -> c_int; pub fn git_repository_is_empty(repo: *mut git_repository) -> c_int; pub fn git_repository_is_shallow(repo: *mut git_repository) -> c_int; - pub fn git_repository_is_worktree(repo: *mut git_repository) -> c_int; - pub fn git_repository_path(repo: *mut git_repository) -> *const c_char; + pub fn git_repository_path(repo: *const git_repository) -> *const c_char; pub fn git_repository_state(repo: *mut git_repository) -> c_int; - pub fn git_repository_workdir(repo: *mut git_repository) -> *const c_char; + pub fn git_repository_workdir(repo: *const git_repository) -> *const c_char; pub fn git_repository_set_workdir(repo: *mut git_repository, workdir: *const c_char, update_gitlink: c_int) -> c_int; @@ -1608,7 +1614,7 @@ extern { pub fn git_repository_message(buf: *mut git_buf, repo: *mut git_repository) -> c_int; - pub fn git_repository_message_remove(repo: *mut git_repository) -> c_int; + pub fn git_repository_message_remove(repo: *mut git_repository) -> c_int; pub fn git_repository_config(out: *mut *mut git_config, repo: *mut git_repository) -> c_int; pub fn git_repository_set_config(repo: *mut git_repository, @@ -1825,12 +1831,12 @@ extern { // reset pub fn git_reset(repo: *mut git_repository, - target: *mut git_object, + target: *const git_object, reset_type: git_reset_t, checkout_opts: *const git_checkout_options) -> c_int; pub fn git_reset_default(repo: *mut git_repository, - target: *mut git_object, - pathspecs: *mut git_strarray) -> c_int; + target: *const git_object, + pathspecs: *const git_strarray) -> c_int; // reference pub fn git_reference_cmp(ref1: *const git_reference, @@ -2231,6 +2237,7 @@ extern { pub fn git_config_add_file_ondisk(cfg: *mut git_config, path: *const c_char, level: git_config_level_t, + repo: *const git_repository, force: c_int) -> c_int; pub fn git_config_delete_entry(cfg: *mut git_config, name: *const c_char) -> c_int; @@ -2691,7 +2698,7 @@ extern { pub fn git_patch_from_blob_and_buffer(out: *mut *mut git_patch, old_blob: *const git_blob, old_as_path: *const c_char, - buffer: *const c_char, + buffer: *const c_void, buffer_len: size_t, buffer_as_path: *const c_char, opts: *const git_diff_options) -> c_int; @@ -2699,7 +2706,7 @@ extern { old_buffer: *const c_void, old_len: size_t, old_as_path: *const c_char, - new_buffer: *const c_char, + new_buffer: *const c_void, new_len: size_t, new_as_path: *const c_char, opts: *const git_diff_options) -> c_int; @@ -2864,7 +2871,7 @@ extern { data: *const c_void, len: size_t, otype: git_otype) -> c_int; - + pub fn git_odb_hashfile(out: *mut git_oid, path: *const c_char, otype: git_otype) -> c_int; diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 15e1193750..f1323d9c16 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 15e119375018fba121cf58e02a9f17fe22df0df8 +Subproject commit f1323d9c161aeeada190fd9615a8b5a9fb8a7f3e diff --git a/src/config.rs b/src/config.rs index 32c148cd64..732e67655c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -120,7 +120,7 @@ impl Config { let path = try!(path.into_c_string()); unsafe { try_call!(raw::git_config_add_file_ondisk(self.raw, path, level, - force)); + ptr::null(), force)); Ok(()) } } diff --git a/src/diff.rs b/src/diff.rs index 5f5c62d3dd..dffd6117c4 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -458,7 +458,8 @@ impl DiffOptions { opts } - fn flag(&mut self, opt: u32, val: bool) -> &mut DiffOptions { + fn flag(&mut self, opt: i32, val: bool) -> &mut DiffOptions { + let opt = opt as u32; if val { self.raw.flags |= opt; } else { @@ -630,6 +631,13 @@ impl DiffOptions { self.flag(raw::GIT_DIFF_SHOW_BINARY, show) } + /// Use a heuristic that takes indentation and whitespace into account + /// which generally can produce better diffs when dealing with ambiguous + /// diff hunks. + pub fn indent_heuristic(&mut self, heuristic: bool) -> &mut DiffOptions { + self.flag(raw::GIT_DIFF_INDENT_HEURISTIC, heuristic) + } + /// Set the number of unchanged lines that define the boundary of a hunk /// (and to display before and after). /// diff --git a/src/patch.rs b/src/patch.rs index 19f774d770..dbd4655d3e 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -1,6 +1,6 @@ use std::path::Path; use std::ptr; -use libc::{c_char, c_int, c_void}; +use libc::{c_int, c_void}; use {raw, Blob, Buf, Diff, DiffDelta, DiffHunk, DiffLine, DiffOptions, Error}; use diff::{LineCb, print_cb}; @@ -78,7 +78,7 @@ impl Patch { try_call!(raw::git_patch_from_blob_and_buffer(&mut ret, old_blob.raw(), old_path, - new_buffer.as_ptr() as *const c_char, + new_buffer.as_ptr() as *const c_void, new_buffer.len(), new_path, opts.map(|s| s.raw()))); @@ -102,7 +102,7 @@ impl Patch { old_buffer.as_ptr() as *const c_void, old_buffer.len(), old_path, - new_buffer.as_ptr() as *const c_char, + new_buffer.as_ptr() as *const c_void, new_buffer.len(), new_path, opts.map(|s| s.raw()))); diff --git a/src/time.rs b/src/time.rs index e344aa3b14..57a5a70a39 100644 --- a/src/time.rs +++ b/src/time.rs @@ -1,6 +1,6 @@ use std::cmp::Ordering; -use libc::c_int; +use libc::{c_int, c_char}; use raw; use util::Binding; @@ -24,6 +24,7 @@ impl Time { Binding::from_raw(raw::git_time { time: time as raw::git_time_t, offset: offset as c_int, + sign: if offset < 0 { '-' } else { '+' } as c_char, }) } } @@ -33,6 +34,10 @@ impl Time { /// Return the timezone offset, in minutes pub fn offset_minutes(&self) -> i32 { self.raw.offset as i32 } + + /// Return whether the offset was positive or negative. Primarily useful + /// in case the offset is specified as a negative zero. + pub fn sign(&self) -> char { self.raw.offset as u8 as char } } impl PartialOrd for Time { From 35b11b7f71e3f53a412e9f7d1e233c05b6898ed0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 18 Jan 2018 11:42:44 -0800 Subject: [PATCH 221/860] Prevent libgit2-sys publishing for now --- libgit2-sys/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index ce4d09169a..6c2e9eb486 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -7,6 +7,7 @@ build = "build.rs" repository = "https://github.com/alexcrichton/git2-rs" license = "MIT/Apache-2.0" description = "Native bindings to the libgit2 library" +publish = false # needs a major version bump [lib] name = "libgit2_sys" From 6b04f6bb3641f9fefc33f4426df9a732623b20fc Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Mon, 22 Jan 2018 05:46:38 +0100 Subject: [PATCH 222/860] Bump bitflags to 1.0 (#289) --- Cargo.toml | 2 +- examples/add.rs | 6 +- examples/blame.rs | 4 +- examples/diff.rs | 10 +-- examples/init.rs | 6 +- examples/log.rs | 14 +-- examples/rev-list.rs | 10 +-- examples/rev-parse.rs | 6 +- examples/status.rs | 62 ++++++------- src/index.rs | 2 +- src/lib.rs | 200 +++++++++++++++++++----------------------- src/pathspec.rs | 14 +-- src/repo.rs | 4 +- src/stash.rs | 6 +- src/status.rs | 6 +- 15 files changed, 168 insertions(+), 184 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c645fdbe45..9707ef2324 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ appveyor = { repository = "alexcrichton/git2-rs" } [dependencies] url = "1.0" -bitflags = "0.9" +bitflags = "1.0" libc = "0.2" libgit2-sys = { path = "libgit2-sys", version = "0.6.19" } diff --git a/examples/add.rs b/examples/add.rs index 71082d09b3..3167cb074e 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -39,8 +39,8 @@ fn run(args: &Args) -> Result<(), git2::Error> { let cb = &mut |path: &Path, _matched_spec: &[u8]| -> i32 { let status = repo.status_file(path).unwrap(); - let ret = if status.contains(git2::STATUS_WT_MODIFIED) || - status.contains(git2::STATUS_WT_NEW) { + let ret = if status.contains(git2::Status::WT_MODIFIED) || + status.contains(git2::Status::WT_NEW) { println!("add '{}'", path.display()); 0 } else { @@ -58,7 +58,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { if args.flag_update { try!(index.update_all(args.arg_spec.iter(), cb)); } else { - try!(index.add_all(args.arg_spec.iter(), git2::ADD_DEFAULT, cb)); + try!(index.add_all(args.arg_spec.iter(), git2::IndexAddOption::DEFAULT, cb)); } try!(index.write()); diff --git a/examples/blame.rs b/examples/blame.rs index fcd890ad9c..5f7bee3680 100644 --- a/examples/blame.rs +++ b/examples/blame.rs @@ -48,9 +48,9 @@ fn run(args: &Args) -> Result<(), git2::Error> { let revspec = try!(repo.revparse(spec)); - let (oldest, newest) = if revspec.mode().contains(git2::REVPARSE_SINGLE) { + let (oldest, newest) = if revspec.mode().contains(git2::RevparseMode::SINGLE) { (None, revspec.from()) - } else if revspec.mode().contains(git2::REVPARSE_RANGE) { + } else if revspec.mode().contains(git2::RevparseMode::RANGE) { (revspec.from(), revspec.to()) } else { (None, None) diff --git a/examples/diff.rs b/examples/diff.rs index a743076925..8664a0e304 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -185,18 +185,18 @@ fn run(args: &Args) -> Result<(), Error> { fn print_stats(diff: &Diff, args: &Args) -> Result<(), Error> { let stats = try!(diff.stats()); - let mut format = git2::DIFF_STATS_NONE; + let mut format = git2::DiffStatsFormat::NONE; if args.flag_stat { - format |= git2::DIFF_STATS_FULL; + format |= git2::DiffStatsFormat::FULL; } if args.flag_shortstat { - format |= git2::DIFF_STATS_SHORT; + format |= git2::DiffStatsFormat::SHORT; } if args.flag_numstat { - format |= git2::DIFF_STATS_NUMBER; + format |= git2::DiffStatsFormat::NUMBER; } if args.flag_summary { - format |= git2::DIFF_STATS_INCLUDE_SUMMARY; + format |= git2::DiffStatsFormat::INCLUDE_SUMMARY; } let buf = try!(stats.to_buf(format, 80)); print!("{}", str::from_utf8(&*buf).unwrap()); diff --git a/examples/init.rs b/examples/init.rs index ccdef76cc5..0f6b838098 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -110,9 +110,9 @@ fn create_initial_commit(repo: &Repository) -> Result<(), Error> { fn parse_shared(shared: &str) -> Result { match shared { - "false" | "umask" => Ok(git2::REPOSITORY_INIT_SHARED_UMASK), - "true" | "group" => Ok(git2::REPOSITORY_INIT_SHARED_GROUP), - "all" | "world" => Ok(git2::REPOSITORY_INIT_SHARED_ALL), + "false" | "umask" => Ok(git2::RepositoryInitMode::SHARED_UMASK), + "true" | "group" => Ok(git2::RepositoryInitMode::SHARED_GROUP), + "all" | "world" => Ok(git2::RepositoryInitMode::SHARED_ALL), _ => { if shared.starts_with('0') { match u32::from_str_radix(&shared[1..], 8).ok() { diff --git a/examples/log.rs b/examples/log.rs index 835136a55b..70e8145da2 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -53,13 +53,13 @@ fn run(args: &Args) -> Result<(), Error> { let mut revwalk = try!(repo.revwalk()); // Prepare the revwalk based on CLI parameters - let base = if args.flag_reverse {git2::SORT_REVERSE} else {git2::SORT_NONE}; + let base = if args.flag_reverse {git2::Sort::REVERSE} else {git2::Sort::NONE}; revwalk.set_sorting(base | if args.flag_topo_order { - git2::SORT_TOPOLOGICAL + git2::Sort::TOPOLOGICAL } else if args.flag_date_order { - git2::SORT_TIME + git2::Sort::TIME } else { - git2::SORT_NONE + git2::Sort::NONE }); for commit in &args.arg_commit { if commit.starts_with('^') { @@ -68,13 +68,13 @@ fn run(args: &Args) -> Result<(), Error> { continue } let revspec = try!(repo.revparse(commit)); - if revspec.mode().contains(git2::REVPARSE_SINGLE) { + if revspec.mode().contains(git2::RevparseMode::SINGLE) { try!(revwalk.push(revspec.from().unwrap().id())); } else { let from = revspec.from().unwrap().id(); let to = revspec.to().unwrap().id(); try!(revwalk.push(to)); - if revspec.mode().contains(git2::REVPARSE_MERGE_BASE) { + if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { let base = try!(repo.merge_base(from, to)); let o = try!(repo.find_object(base, Some(ObjectType::Commit))); try!(revwalk.push(o.id())); @@ -110,7 +110,7 @@ fn run(args: &Args) -> Result<(), Error> { match commit.parents().len() { 0 => { let tree = filter_try!(commit.tree()); - let flags = git2::PATHSPEC_NO_MATCH_ERROR; + let flags = git2::PathspecFlags::NO_MATCH_ERROR; if ps.match_tree(&tree, flags).is_err() { return None } } _ => { diff --git a/examples/rev-list.rs b/examples/rev-list.rs index d2a6181979..db9bd82cad 100644 --- a/examples/rev-list.rs +++ b/examples/rev-list.rs @@ -36,13 +36,13 @@ fn run(args: &Args) -> Result<(), git2::Error> { let repo = try!(Repository::open(".")); let mut revwalk = try!(repo.revwalk()); - let base = if args.flag_reverse {git2::SORT_REVERSE} else {git2::SORT_NONE}; + let base = if args.flag_reverse {git2::Sort::REVERSE} else {git2::Sort::NONE}; revwalk.set_sorting(base | if args.flag_topo_order { - git2::SORT_TOPOLOGICAL + git2::Sort::TOPOLOGICAL } else if args.flag_date_order { - git2::SORT_TIME + git2::Sort::TIME } else { - git2::SORT_NONE + git2::Sort::NONE }); let specs = args.flag_not.iter().map(|s| (s, true)) @@ -53,7 +53,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { for (spec, hide) in specs { let id = if spec.contains("..") { let revspec = try!(repo.revparse(spec)); - if revspec.mode().contains(git2::REVPARSE_MERGE_BASE) { + if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { return Err(Error::from_str("merge bases not implemented")) } try!(push(&mut revwalk, revspec.from().unwrap().id(), !hide)); diff --git a/examples/rev-parse.rs b/examples/rev-parse.rs index f1caf00f09..f2416f7b40 100644 --- a/examples/rev-parse.rs +++ b/examples/rev-parse.rs @@ -34,14 +34,14 @@ fn run(args: &Args) -> Result<(), git2::Error> { let revspec = try!(repo.revparse(&args.arg_spec)); - if revspec.mode().contains(git2::REVPARSE_SINGLE) { + if revspec.mode().contains(git2::RevparseMode::SINGLE) { println!("{}", revspec.from().unwrap().id()); - } else if revspec.mode().contains(git2::REVPARSE_RANGE) { + } else if revspec.mode().contains(git2::RevparseMode::RANGE) { let to = revspec.to().unwrap(); let from = revspec.from().unwrap(); println!("{}", to.id()); - if revspec.mode().contains(git2::REVPARSE_MERGE_BASE) { + if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { let base = try!(repo.merge_base(from.id(), to.id())); println!("{}", base); } diff --git a/examples/status.rs b/examples/status.rs index 86cbfcb6cd..87ca6ec315 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -135,16 +135,16 @@ fn print_long(statuses: &git2::Statuses) { let mut changed_in_workdir = false; // Print index changes - for entry in statuses.iter().filter(|e| e.status() != git2::STATUS_CURRENT) { - if entry.status().contains(git2::STATUS_WT_DELETED) { + for entry in statuses.iter().filter(|e| e.status() != git2::Status::CURRENT) { + if entry.status().contains(git2::Status::WT_DELETED) { rm_in_workdir = true; } let istatus = match entry.status() { - s if s.contains(git2::STATUS_INDEX_NEW) => "new file: ", - s if s.contains(git2::STATUS_INDEX_MODIFIED) => "modified: ", - s if s.contains(git2::STATUS_INDEX_DELETED) => "deleted: ", - s if s.contains(git2::STATUS_INDEX_RENAMED) => "renamed: ", - s if s.contains(git2::STATUS_INDEX_TYPECHANGE) => "typechange:", + s if s.contains(git2::Status::INDEX_NEW) => "new file: ", + s if s.contains(git2::Status::INDEX_MODIFIED) => "modified: ", + s if s.contains(git2::Status::INDEX_DELETED) => "deleted: ", + s if s.contains(git2::Status::INDEX_RENAMED) => "renamed: ", + s if s.contains(git2::Status::INDEX_TYPECHANGE) => "typechange:", _ => continue, }; if !header { @@ -176,19 +176,19 @@ fn print_long(statuses: &git2::Statuses) { // Print workdir changes to tracked files for entry in statuses.iter() { - // With `STATUS_OPT_INCLUDE_UNMODIFIED` (not used in this example) + // With `Status::OPT_INCLUDE_UNMODIFIED` (not used in this example) // `index_to_workdir` may not be `None` even if there are no differences, // in which case it will be a `Delta::Unmodified`. - if entry.status() == git2::STATUS_CURRENT || + if entry.status() == git2::Status::CURRENT || entry.index_to_workdir().is_none() { continue } let istatus = match entry.status() { - s if s.contains(git2::STATUS_WT_MODIFIED) => "modified: ", - s if s.contains(git2::STATUS_WT_DELETED) => "deleted: ", - s if s.contains(git2::STATUS_WT_RENAMED) => "renamed: ", - s if s.contains(git2::STATUS_WT_TYPECHANGE) => "typechange:", + s if s.contains(git2::Status::WT_MODIFIED) => "modified: ", + s if s.contains(git2::Status::WT_DELETED) => "deleted: ", + s if s.contains(git2::Status::WT_RENAMED) => "renamed: ", + s if s.contains(git2::Status::WT_TYPECHANGE) => "typechange:", _ => continue, }; @@ -222,7 +222,7 @@ fn print_long(statuses: &git2::Statuses) { header = false; // Print untracked files - for entry in statuses.iter().filter(|e| e.status() == git2::STATUS_WT_NEW) { + for entry in statuses.iter().filter(|e| e.status() == git2::Status::WT_NEW) { if !header { println!("\ # Untracked files @@ -236,7 +236,7 @@ fn print_long(statuses: &git2::Statuses) { header = false; // Print ignored files - for entry in statuses.iter().filter(|e| e.status() == git2::STATUS_IGNORED) { + for entry in statuses.iter().filter(|e| e.status() == git2::Status::IGNORED) { if !header { println!("\ # Ignored files @@ -257,27 +257,27 @@ fn print_long(statuses: &git2::Statuses) { // This version of the output prefixes each path with two status columns and // shows submodule status information. fn print_short(repo: &Repository, statuses: &git2::Statuses) { - for entry in statuses.iter().filter(|e| e.status() != git2::STATUS_CURRENT) { + for entry in statuses.iter().filter(|e| e.status() != git2::Status::CURRENT) { let mut istatus = match entry.status() { - s if s.contains(git2::STATUS_INDEX_NEW) => 'A', - s if s.contains(git2::STATUS_INDEX_MODIFIED) => 'M', - s if s.contains(git2::STATUS_INDEX_DELETED) => 'D', - s if s.contains(git2::STATUS_INDEX_RENAMED) => 'R', - s if s.contains(git2::STATUS_INDEX_TYPECHANGE) => 'T', + s if s.contains(git2::Status::INDEX_NEW) => 'A', + s if s.contains(git2::Status::INDEX_MODIFIED) => 'M', + s if s.contains(git2::Status::INDEX_DELETED) => 'D', + s if s.contains(git2::Status::INDEX_RENAMED) => 'R', + s if s.contains(git2::Status::INDEX_TYPECHANGE) => 'T', _ => ' ', }; let mut wstatus = match entry.status() { - s if s.contains(git2::STATUS_WT_NEW) => { + s if s.contains(git2::Status::WT_NEW) => { if istatus == ' ' { istatus = '?'; } '?' } - s if s.contains(git2::STATUS_WT_MODIFIED) => 'M', - s if s.contains(git2::STATUS_WT_DELETED) => 'D', - s if s.contains(git2::STATUS_WT_RENAMED) => 'R', - s if s.contains(git2::STATUS_WT_TYPECHANGE) => 'T', + s if s.contains(git2::Status::WT_MODIFIED) => 'M', + s if s.contains(git2::Status::WT_DELETED) => 'D', + s if s.contains(git2::Status::WT_RENAMED) => 'R', + s if s.contains(git2::Status::WT_TYPECHANGE) => 'T', _ => ' ', }; - if entry.status().contains(git2::STATUS_IGNORED) { + if entry.status().contains(git2::Status::IGNORED) { istatus = '!'; wstatus = '!'; } @@ -295,11 +295,11 @@ fn print_short(repo: &Repository, statuses: &git2::Statuses) { .and_then(|name| repo.submodule_status(name, ignore).ok()) }); if let Some(status) = status { - if status.contains(git2::SUBMODULE_STATUS_WD_MODIFIED) { + if status.contains(git2::SubmoduleStatus::WD_MODIFIED) { extra = " (new commits)"; - } else if status.contains(git2::SUBMODULE_STATUS_WD_INDEX_MODIFIED) || status.contains(git2::SUBMODULE_STATUS_WD_WD_MODIFIED) { + } else if status.contains(git2::SubmoduleStatus::WD_INDEX_MODIFIED) || status.contains(git2::SubmoduleStatus::WD_WD_MODIFIED) { extra = " (modified content)"; - } else if status.contains(git2::SUBMODULE_STATUS_WD_UNTRACKED) { + } else if status.contains(git2::SubmoduleStatus::WD_UNTRACKED) { extra = " (untracked content)"; } } @@ -327,7 +327,7 @@ fn print_short(repo: &Repository, statuses: &git2::Statuses) { } } - for entry in statuses.iter().filter(|e| e.status() == git2::STATUS_WT_NEW) { + for entry in statuses.iter().filter(|e| e.status() == git2::Status::WT_NEW) { println!("?? {}", entry.index_to_workdir().unwrap().old_file() .path().unwrap().display()); } diff --git a/src/index.rs b/src/index.rs index 8d5172e61f..0f603a5b07 100644 --- a/src/index.rs +++ b/src/index.rs @@ -551,7 +551,7 @@ mod tests { fs::create_dir(&root.join("foo")).unwrap(); File::create(&root.join("foo/bar")).unwrap(); let mut called = false; - index.add_all(["foo"].iter(), ::ADD_DEFAULT, + index.add_all(["foo"].iter(), ::IndexAddOption::DEFAULT, Some(&mut |a: &Path, b: &[u8]| { assert!(!called); called = true; diff --git a/src/lib.rs b/src/lib.rs index 2a1ca3dab9..f0764dabdc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -364,23 +364,23 @@ bitflags! { /// /// This sorting is arbitrary, implementation-specific, and subject to /// change at any time. This is the default sorting for new walkers. - const SORT_NONE = raw::GIT_SORT_NONE as u32; + const NONE = raw::GIT_SORT_NONE as u32; /// Sort the repository contents in topological order (parents before /// children). /// /// This sorting mode can be combined with time sorting. - const SORT_TOPOLOGICAL = raw::GIT_SORT_TOPOLOGICAL as u32; + const TOPOLOGICAL = raw::GIT_SORT_TOPOLOGICAL as u32; /// Sort the repository contents by commit time. /// /// This sorting mode can be combined with topological sorting. - const SORT_TIME = raw::GIT_SORT_TIME as u32; + const TIME = raw::GIT_SORT_TIME as u32; /// Iterate through the repository contents in reverse order. /// /// This sorting mode can be combined with any others. - const SORT_REVERSE = raw::GIT_SORT_REVERSE as u32; + const REVERSE = raw::GIT_SORT_REVERSE as u32; } } @@ -408,9 +408,9 @@ bitflags! { /// Flags for the `flags` field of an IndexEntry. pub struct IndexEntryFlag: u16 { /// Set when the `extended_flags` field is valid. - const IDXENTRY_EXTENDED = raw::GIT_IDXENTRY_EXTENDED as u16; + const EXTENDED = raw::GIT_IDXENTRY_EXTENDED as u16; /// "Assume valid" flag - const IDXENTRY_VALID = raw::GIT_IDXENTRY_VALID as u16; + const VALID = raw::GIT_IDXENTRY_VALID as u16; } } @@ -418,34 +418,34 @@ bitflags! { /// Flags for the `extended_flags` field of an IndexEntry. pub struct IndexEntryExtendedFlag: u16 { /// An "intent to add" entry from "git add -N" - const IDXENTRY_INTENT_TO_ADD = raw::GIT_IDXENTRY_INTENT_TO_ADD as u16; + const INTENT_TO_ADD = raw::GIT_IDXENTRY_INTENT_TO_ADD as u16; /// Skip the associated worktree file, for sparse checkouts - const IDXENTRY_SKIP_WORKTREE = raw::GIT_IDXENTRY_SKIP_WORKTREE as u16; + const SKIP_WORKTREE = raw::GIT_IDXENTRY_SKIP_WORKTREE as u16; /// Reserved for a future on-disk extended flag - const IDXENTRY_EXTENDED2 = raw::GIT_IDXENTRY_EXTENDED2 as u16; + const EXTENDED2 = raw::GIT_IDXENTRY_EXTENDED2 as u16; #[allow(missing_docs)] - const IDXENTRY_UPDATE = raw::GIT_IDXENTRY_UPDATE as u16; + const UPDATE = raw::GIT_IDXENTRY_UPDATE as u16; #[allow(missing_docs)] - const IDXENTRY_REMOVE = raw::GIT_IDXENTRY_REMOVE as u16; + const REMOVE = raw::GIT_IDXENTRY_REMOVE as u16; #[allow(missing_docs)] - const IDXENTRY_UPTODATE = raw::GIT_IDXENTRY_UPTODATE as u16; + const UPTODATE = raw::GIT_IDXENTRY_UPTODATE as u16; #[allow(missing_docs)] - const IDXENTRY_ADDED = raw::GIT_IDXENTRY_ADDED as u16; + const ADDED = raw::GIT_IDXENTRY_ADDED as u16; #[allow(missing_docs)] - const IDXENTRY_HASHED = raw::GIT_IDXENTRY_HASHED as u16; + const HASHED = raw::GIT_IDXENTRY_HASHED as u16; #[allow(missing_docs)] - const IDXENTRY_UNHASHED = raw::GIT_IDXENTRY_UNHASHED as u16; + const UNHASHED = raw::GIT_IDXENTRY_UNHASHED as u16; #[allow(missing_docs)] - const IDXENTRY_WT_REMOVE = raw::GIT_IDXENTRY_WT_REMOVE as u16; + const WT_REMOVE = raw::GIT_IDXENTRY_WT_REMOVE as u16; #[allow(missing_docs)] - const IDXENTRY_CONFLICTED = raw::GIT_IDXENTRY_CONFLICTED as u16; + const CONFLICTED = raw::GIT_IDXENTRY_CONFLICTED as u16; #[allow(missing_docs)] - const IDXENTRY_UNPACKED = raw::GIT_IDXENTRY_UNPACKED as u16; + const UNPACKED = raw::GIT_IDXENTRY_UNPACKED as u16; #[allow(missing_docs)] - const IDXENTRY_NEW_SKIP_WORKTREE = raw::GIT_IDXENTRY_NEW_SKIP_WORKTREE as u16; + const NEW_SKIP_WORKTREE = raw::GIT_IDXENTRY_NEW_SKIP_WORKTREE as u16; } } @@ -453,14 +453,14 @@ bitflags! { /// Flags for APIs that add files matching pathspec pub struct IndexAddOption: u32 { #[allow(missing_docs)] - const ADD_DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32; + const DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32; #[allow(missing_docs)] - const ADD_FORCE = raw::GIT_INDEX_ADD_FORCE as u32; + const FORCE = raw::GIT_INDEX_ADD_FORCE as u32; #[allow(missing_docs)] - const ADD_DISABLE_PATHSPEC_MATCH = + const DISABLE_PATHSPEC_MATCH = raw::GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH as u32; #[allow(missing_docs)] - const ADD_CHECK_PATHSPEC = raw::GIT_INDEX_ADD_CHECK_PATHSPEC as u32; + const CHECK_PATHSPEC = raw::GIT_INDEX_ADD_CHECK_PATHSPEC as u32; } } @@ -468,15 +468,15 @@ bitflags! { /// Flags for `Repository::open_ext` pub struct 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; + const 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; + const 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; + const BARE = raw::GIT_REPOSITORY_OPEN_BARE as u32; /// Don't try appending `/.git` to the specified repository path. - const REPOSITORY_OPEN_NO_DOTGIT = raw::GIT_REPOSITORY_OPEN_NO_DOTGIT as u32; + const NO_DOTGIT = raw::GIT_REPOSITORY_OPEN_NO_DOTGIT as u32; /// Respect environment variables like `$GIT_DIR`. - const REPOSITORY_OPEN_FROM_ENV = raw::GIT_REPOSITORY_OPEN_FROM_ENV as u32; + const FROM_ENV = raw::GIT_REPOSITORY_OPEN_FROM_ENV as u32; } } @@ -484,11 +484,11 @@ bitflags! { /// Flags for the return value of `Repository::revparse` pub struct RevparseMode: u32 { /// The spec targeted a single object - const REVPARSE_SINGLE = raw::GIT_REVPARSE_SINGLE as u32; + const SINGLE = raw::GIT_REVPARSE_SINGLE as u32; /// The spec targeted a range of commits - const REVPARSE_RANGE = raw::GIT_REVPARSE_RANGE as u32; + const RANGE = raw::GIT_REVPARSE_RANGE as u32; /// The spec used the `...` operator, which invokes special semantics. - const REVPARSE_MERGE_BASE = raw::GIT_REVPARSE_MERGE_BASE as u32; + const MERGE_BASE = raw::GIT_REVPARSE_MERGE_BASE as u32; } } @@ -496,21 +496,21 @@ bitflags! { /// The results of `merge_analysis` indicating the merge opportunities. pub struct MergeAnalysis: u32 { /// No merge is possible. - const MERGE_ANALYSIS_NONE = raw::GIT_MERGE_ANALYSIS_NONE as u32; + const ANALYSIS_NONE = raw::GIT_MERGE_ANALYSIS_NONE as u32; /// A "normal" merge; both HEAD and the given merge input have diverged /// from their common ancestor. The divergent commits must be merged. - const MERGE_ANALYSIS_NORMAL = raw::GIT_MERGE_ANALYSIS_NORMAL as u32; + const ANALYSIS_NORMAL = raw::GIT_MERGE_ANALYSIS_NORMAL as u32; /// All given merge inputs are reachable from HEAD, meaning the /// repository is up-to-date and no merge needs to be performed. - const MERGE_ANALYSIS_UP_TO_DATE = raw::GIT_MERGE_ANALYSIS_UP_TO_DATE as u32; + const ANALYSIS_UP_TO_DATE = raw::GIT_MERGE_ANALYSIS_UP_TO_DATE as u32; /// The given merge input is a fast-forward from HEAD and no merge /// needs to be performed. Instead, the client can check out the /// given merge input. - const MERGE_ANALYSIS_FASTFORWARD = raw::GIT_MERGE_ANALYSIS_FASTFORWARD as u32; + const ANALYSIS_FASTFORWARD = raw::GIT_MERGE_ANALYSIS_FASTFORWARD as u32; /// The HEAD of the current repository is "unborn" and does not point to /// a valid commit. No merge can be performed, but the caller may wish /// to simply set HEAD to the target commit(s). - const MERGE_ANALYSIS_UNBORN = raw::GIT_MERGE_ANALYSIS_UNBORN as u32; + const ANALYSIS_UNBORN = raw::GIT_MERGE_ANALYSIS_UNBORN as u32; } } @@ -519,13 +519,13 @@ bitflags! { pub struct MergePreference: u32 { /// No configuration was found that suggests a preferred behavior for /// merge. - const MERGE_PREFERENCE_NONE = raw::GIT_MERGE_PREFERENCE_NONE as u32; + const NONE = raw::GIT_MERGE_PREFERENCE_NONE as u32; /// There is a `merge.ff=false` configuration setting, suggesting that /// the user does not want to allow a fast-forward merge. - const MERGE_PREFERENCE_NO_FAST_FORWARD = raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD as u32; + const NO_FAST_FORWARD = raw::GIT_MERGE_PREFERENCE_NO_FASTFORWARD as u32; /// There is a `merge.ff=only` configuration setting, suggesting that /// the user only wants fast-forward merges. - const MERGE_PREFERENCE_FASTFORWARD_ONLY = raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY as u32; + const FASTFORWARD_ONLY = raw::GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY as u32; } } @@ -822,34 +822,34 @@ bitflags! { /// working directory relative to the index. pub struct Status: u32 { #[allow(missing_docs)] - const STATUS_CURRENT = raw::GIT_STATUS_CURRENT as u32; + const CURRENT = raw::GIT_STATUS_CURRENT as u32; #[allow(missing_docs)] - const STATUS_INDEX_NEW = raw::GIT_STATUS_INDEX_NEW as u32; + const INDEX_NEW = raw::GIT_STATUS_INDEX_NEW as u32; #[allow(missing_docs)] - const STATUS_INDEX_MODIFIED = raw::GIT_STATUS_INDEX_MODIFIED as u32; + const INDEX_MODIFIED = raw::GIT_STATUS_INDEX_MODIFIED as u32; #[allow(missing_docs)] - const STATUS_INDEX_DELETED = raw::GIT_STATUS_INDEX_DELETED as u32; + const INDEX_DELETED = raw::GIT_STATUS_INDEX_DELETED as u32; #[allow(missing_docs)] - const STATUS_INDEX_RENAMED = raw::GIT_STATUS_INDEX_RENAMED as u32; + const INDEX_RENAMED = raw::GIT_STATUS_INDEX_RENAMED as u32; #[allow(missing_docs)] - const STATUS_INDEX_TYPECHANGE = raw::GIT_STATUS_INDEX_TYPECHANGE as u32; + const INDEX_TYPECHANGE = raw::GIT_STATUS_INDEX_TYPECHANGE as u32; #[allow(missing_docs)] - const STATUS_WT_NEW = raw::GIT_STATUS_WT_NEW as u32; + const WT_NEW = raw::GIT_STATUS_WT_NEW as u32; #[allow(missing_docs)] - const STATUS_WT_MODIFIED = raw::GIT_STATUS_WT_MODIFIED as u32; + const WT_MODIFIED = raw::GIT_STATUS_WT_MODIFIED as u32; #[allow(missing_docs)] - const STATUS_WT_DELETED = raw::GIT_STATUS_WT_DELETED as u32; + const WT_DELETED = raw::GIT_STATUS_WT_DELETED as u32; #[allow(missing_docs)] - const STATUS_WT_TYPECHANGE = raw::GIT_STATUS_WT_TYPECHANGE as u32; + const WT_TYPECHANGE = raw::GIT_STATUS_WT_TYPECHANGE as u32; #[allow(missing_docs)] - const STATUS_WT_RENAMED = raw::GIT_STATUS_WT_RENAMED as u32; + const WT_RENAMED = raw::GIT_STATUS_WT_RENAMED as u32; #[allow(missing_docs)] - const STATUS_IGNORED = raw::GIT_STATUS_IGNORED as u32; + const IGNORED = raw::GIT_STATUS_IGNORED as u32; #[allow(missing_docs)] - const STATUS_CONFLICTED = raw::GIT_STATUS_CONFLICTED as u32; + const CONFLICTED = raw::GIT_STATUS_CONFLICTED as u32; } } @@ -857,15 +857,12 @@ bitflags! { /// Mode options for RepositoryInitOptions pub struct RepositoryInitMode: u32 { /// Use permissions configured by umask - the default - const REPOSITORY_INIT_SHARED_UMASK = - raw::GIT_REPOSITORY_INIT_SHARED_UMASK as u32; + const SHARED_UMASK = raw::GIT_REPOSITORY_INIT_SHARED_UMASK as u32; /// Use `--shared=group` behavior, chmod'ing the new repo to be /// group writable and \"g+sx\" for sticky group assignment - const REPOSITORY_INIT_SHARED_GROUP = - raw::GIT_REPOSITORY_INIT_SHARED_GROUP as u32; + const SHARED_GROUP = raw::GIT_REPOSITORY_INIT_SHARED_GROUP as u32; /// Use `--shared=all` behavior, adding world readability. - const REPOSITORY_INIT_SHARED_ALL = - raw::GIT_REPOSITORY_INIT_SHARED_ALL as u32; + const SHARED_ALL = raw::GIT_REPOSITORY_INIT_SHARED_ALL as u32; } } @@ -939,47 +936,35 @@ bitflags! { /// * WD_UNTRACKED - wd contains untracked files pub struct SubmoduleStatus: u32 { #[allow(missing_docs)] - const SUBMODULE_STATUS_IN_HEAD = - raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32; + const IN_HEAD = raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_IN_INDEX = - raw::GIT_SUBMODULE_STATUS_IN_INDEX as u32; + const IN_INDEX = raw::GIT_SUBMODULE_STATUS_IN_INDEX as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_IN_CONFIG = - raw::GIT_SUBMODULE_STATUS_IN_CONFIG as u32; + const IN_CONFIG = raw::GIT_SUBMODULE_STATUS_IN_CONFIG as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_IN_WD = - raw::GIT_SUBMODULE_STATUS_IN_WD as u32; + const IN_WD = raw::GIT_SUBMODULE_STATUS_IN_WD as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_INDEX_ADDED = - raw::GIT_SUBMODULE_STATUS_INDEX_ADDED as u32; + const INDEX_ADDED = raw::GIT_SUBMODULE_STATUS_INDEX_ADDED as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_INDEX_DELETED = - raw::GIT_SUBMODULE_STATUS_INDEX_DELETED as u32; + const INDEX_DELETED = raw::GIT_SUBMODULE_STATUS_INDEX_DELETED as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_INDEX_MODIFIED = - raw::GIT_SUBMODULE_STATUS_INDEX_MODIFIED as u32; + const INDEX_MODIFIED = raw::GIT_SUBMODULE_STATUS_INDEX_MODIFIED as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_WD_UNINITIALIZED = + const WD_UNINITIALIZED = raw::GIT_SUBMODULE_STATUS_WD_UNINITIALIZED as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_WD_ADDED = - raw::GIT_SUBMODULE_STATUS_WD_ADDED as u32; + const WD_ADDED = raw::GIT_SUBMODULE_STATUS_WD_ADDED as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_WD_DELETED = - raw::GIT_SUBMODULE_STATUS_WD_DELETED as u32; + const WD_DELETED = raw::GIT_SUBMODULE_STATUS_WD_DELETED as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_WD_MODIFIED = - raw::GIT_SUBMODULE_STATUS_WD_MODIFIED as u32; + const WD_MODIFIED = raw::GIT_SUBMODULE_STATUS_WD_MODIFIED as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_WD_INDEX_MODIFIED = + const WD_INDEX_MODIFIED = raw::GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_WD_WD_MODIFIED = - raw::GIT_SUBMODULE_STATUS_WD_WD_MODIFIED as u32; + const WD_WD_MODIFIED = raw::GIT_SUBMODULE_STATUS_WD_WD_MODIFIED as u32; #[allow(missing_docs)] - const SUBMODULE_STATUS_WD_UNTRACKED = - raw::GIT_SUBMODULE_STATUS_WD_UNTRACKED as u32; + const WD_UNTRACKED = raw::GIT_SUBMODULE_STATUS_WD_UNTRACKED as u32; } } @@ -1006,28 +991,28 @@ bitflags! { /// ... pub struct PathspecFlags: u32 { /// Use the default pathspec matching configuration. - const PATHSPEC_DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32; + const DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32; /// Force matching to ignore case, otherwise matching will use native /// case sensitivity fo the platform filesystem. - const PATHSPEC_IGNORE_CASE = raw::GIT_PATHSPEC_IGNORE_CASE as u32; + const IGNORE_CASE = raw::GIT_PATHSPEC_IGNORE_CASE as u32; /// Force case sensitive matches, otherwise match will use the native /// case sensitivity of the platform filesystem. - const PATHSPEC_USE_CASE = raw::GIT_PATHSPEC_USE_CASE as u32; + const USE_CASE = raw::GIT_PATHSPEC_USE_CASE as u32; /// Disable glob patterns and just use simple string comparison for /// matching. - const PATHSPEC_NO_GLOB = raw::GIT_PATHSPEC_NO_GLOB as u32; + const NO_GLOB = raw::GIT_PATHSPEC_NO_GLOB as u32; /// Means that match functions return the error code `NotFound` if no /// matches are found. By default no matches is a success. - const PATHSPEC_NO_MATCH_ERROR = raw::GIT_PATHSPEC_NO_MATCH_ERROR as u32; + const NO_MATCH_ERROR = raw::GIT_PATHSPEC_NO_MATCH_ERROR as u32; /// Means that the list returned should track which patterns matched /// which files so that at the end of the match we can identify patterns /// that did not match any files. - const PATHSPEC_FIND_FAILURES = raw::GIT_PATHSPEC_FIND_FAILURES as u32; + const FIND_FAILURES = raw::GIT_PATHSPEC_FIND_FAILURES as u32; /// Means that the list returned does not need to keep the actual /// matching filenames. Use this to just test if there were any matches /// at all or in combination with `PATHSPEC_FAILURES` to validate a /// pathspec. - const PATHSPEC_FAILURES_ONLY = raw::GIT_PATHSPEC_FAILURES_ONLY as u32; + const FAILURES_ONLY = raw::GIT_PATHSPEC_FAILURES_ONLY as u32; } } @@ -1035,15 +1020,15 @@ bitflags! { /// Types of notifications emitted from checkouts. pub struct CheckoutNotificationType: u32 { /// Notification about a conflict. - const CHECKOUT_NOTIFICATION_CONFLICT = raw::GIT_CHECKOUT_NOTIFY_CONFLICT as u32; + const CONFLICT = raw::GIT_CHECKOUT_NOTIFY_CONFLICT as u32; /// Notification about a dirty file. - const CHECKOUT_NOTIFICATION_DIRTY = raw::GIT_CHECKOUT_NOTIFY_DIRTY as u32; + const DIRTY = raw::GIT_CHECKOUT_NOTIFY_DIRTY as u32; /// Notification about an updated file. - const CHECKOUT_NOTIFICATION_UPDATED = raw::GIT_CHECKOUT_NOTIFY_UPDATED as u32; + const UPDATED = raw::GIT_CHECKOUT_NOTIFY_UPDATED as u32; /// Notification about an untracked file. - const CHECKOUT_NOTIFICATION_UNTRACKED = raw::GIT_CHECKOUT_NOTIFY_UNTRACKED as u32; + const UNTRACKED = raw::GIT_CHECKOUT_NOTIFY_UNTRACKED as u32; /// Notification about an ignored file. - const CHECKOUT_NOTIFICATION_IGNORED = raw::GIT_CHECKOUT_NOTIFY_IGNORED as u32; + const IGNORED = raw::GIT_CHECKOUT_NOTIFY_IGNORED as u32; } } @@ -1066,17 +1051,16 @@ bitflags! { /// Formatting options for diff stats pub struct DiffStatsFormat: raw::git_diff_stats_format_t { /// Don't generate any stats - const DIFF_STATS_NONE = raw::GIT_DIFF_STATS_NONE; + const NONE = raw::GIT_DIFF_STATS_NONE; /// Equivalent of `--stat` in git - const DIFF_STATS_FULL = raw::GIT_DIFF_STATS_FULL; + const FULL = raw::GIT_DIFF_STATS_FULL; /// Equivalent of `--shortstat` in git - const DIFF_STATS_SHORT = raw::GIT_DIFF_STATS_SHORT; + const SHORT = raw::GIT_DIFF_STATS_SHORT; /// Equivalent of `--numstat` in git - const DIFF_STATS_NUMBER = raw::GIT_DIFF_STATS_NUMBER; + const NUMBER = raw::GIT_DIFF_STATS_NUMBER; /// Extended header information such as creations, renames and mode /// changes, equivalent of `--summary` in git - const DIFF_STATS_INCLUDE_SUMMARY = - raw::GIT_DIFF_STATS_INCLUDE_SUMMARY; + const INCLUDE_SUMMARY = raw::GIT_DIFF_STATS_INCLUDE_SUMMARY; } } @@ -1127,10 +1111,10 @@ bitflags! { #[allow(missing_docs)] pub struct StashApplyFlags: u32 { #[allow(missing_docs)] - const STASH_APPLY_DEFAULT = raw::GIT_STASH_APPLY_DEFAULT as u32; + const DEFAULT = raw::GIT_STASH_APPLY_DEFAULT as u32; /// Try to reinstate not only the working tree's changes, /// but also the index's changes. - const STASH_APPLY_REINSTATE_INDEX = raw::GIT_STASH_APPLY_REINSTATE_INDEX as u32; + const REINSTATE_INDEX = raw::GIT_STASH_APPLY_REINSTATE_INDEX as u32; } } @@ -1138,16 +1122,16 @@ bitflags! { #[allow(missing_docs)] pub struct StashFlags: u32 { #[allow(missing_docs)] - const STASH_DEFAULT = raw::GIT_STASH_DEFAULT as u32; + const DEFAULT = raw::GIT_STASH_DEFAULT as u32; /// All changes already added to the index are left intact in /// the working directory - const STASH_KEEP_INDEX = raw::GIT_STASH_KEEP_INDEX as u32; + const KEEP_INDEX = raw::GIT_STASH_KEEP_INDEX as u32; /// All untracked files are also stashed and then cleaned up /// from the working directory - const STASH_INCLUDE_UNTRACKED = raw::GIT_STASH_INCLUDE_UNTRACKED as u32; + const INCLUDE_UNTRACKED = raw::GIT_STASH_INCLUDE_UNTRACKED as u32; /// All ignored files are also stashed and then cleaned up from /// the working directory - const STASH_INCLUDE_IGNORED = raw::GIT_STASH_INCLUDE_IGNORED as u32; + const INCLUDE_IGNORED = raw::GIT_STASH_INCLUDE_IGNORED as u32; } } diff --git a/src/pathspec.rs b/src/pathspec.rs index e1ee3d2250..5cc03ab3b8 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -273,7 +273,7 @@ impl<'list> ExactSizeIterator for PathspecFailedEntries<'list> {} #[cfg(test)] mod tests { - use PATHSPEC_DEFAULT; + use PathspecFlags; use super::Pathspec; use std::fs::File; use std::path::Path; @@ -281,20 +281,20 @@ mod tests { #[test] fn smoke() { let ps = Pathspec::new(["a"].iter()).unwrap(); - assert!(ps.matches_path(Path::new("a"), PATHSPEC_DEFAULT)); - assert!(ps.matches_path(Path::new("a/b"), PATHSPEC_DEFAULT)); - assert!(!ps.matches_path(Path::new("b"), PATHSPEC_DEFAULT)); - assert!(!ps.matches_path(Path::new("ab/c"), PATHSPEC_DEFAULT)); + assert!(ps.matches_path(Path::new("a"), PathspecFlags::DEFAULT)); + assert!(ps.matches_path(Path::new("a/b"), PathspecFlags::DEFAULT)); + assert!(!ps.matches_path(Path::new("b"), PathspecFlags::DEFAULT)); + assert!(!ps.matches_path(Path::new("ab/c"), PathspecFlags::DEFAULT)); let (td, repo) = ::test::repo_init(); - let list = ps.match_workdir(&repo, PATHSPEC_DEFAULT).unwrap(); + let list = ps.match_workdir(&repo, PathspecFlags::DEFAULT).unwrap(); assert_eq!(list.entries().len(), 0); assert_eq!(list.diff_entries().len(), 0); assert_eq!(list.failed_entries().len(), 0); File::create(&td.path().join("a")).unwrap(); - let list = ps.match_workdir(&repo, ::PATHSPEC_FIND_FAILURES).unwrap(); + let list = ps.match_workdir(&repo, ::PathspecFlags::FIND_FAILURES).unwrap(); assert_eq!(list.entries().len(), 1); assert_eq!(list.entries().next(), Some("a".as_bytes())); } diff --git a/src/repo.rs b/src/repo.rs index 119e3fbd1e..1723e6348c 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2275,12 +2275,12 @@ mod tests { 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(); + let repo = Repository::open_ext(&subdir, ::RepositoryOpenFlags::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(); + let err = Repository::open_ext(&subdir, ::RepositoryOpenFlags::NO_SEARCH, &[] as &[&OsStr]).err().unwrap(); assert_eq!(err.code(), ::ErrorCode::NotFound); assert!(Repository::open_ext(&subdir, diff --git a/src/stash.rs b/src/stash.rs index b1d04f1aae..3d07465a3e 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -142,7 +142,7 @@ mod tests { use std::fs; use std::path::Path; use test::{repo_init}; - use {Repository, STATUS_WT_NEW, STASH_INCLUDE_UNTRACKED}; + use {Repository, Status, StashFlags}; fn make_stash(next: C) where C: FnOnce(&mut Repository) { let (_td, mut repo) = repo_init(); @@ -154,9 +154,9 @@ mod tests { .write("data".as_bytes()).unwrap(); let rel_p = Path::new("file_b.txt"); - assert!(repo.status_file(&rel_p).unwrap() == STATUS_WT_NEW); + assert!(repo.status_file(&rel_p).unwrap() == Status::WT_NEW); - repo.stash_save(&signature, "msg1", Some(STASH_INCLUDE_UNTRACKED)).unwrap(); + repo.stash_save(&signature, "msg1", Some(StashFlags::INCLUDE_UNTRACKED)).unwrap(); assert!(repo.status_file(&rel_p).is_err()); diff --git a/src/status.rs b/src/status.rs index b613c0a97a..dc1dbd76dd 100644 --- a/src/status.rs +++ b/src/status.rs @@ -365,8 +365,8 @@ mod tests { assert_eq!(statuses.iter().count(), 1); let status = statuses.iter().next().unwrap(); assert_eq!(status.path(), Some("foo")); - assert!(status.status().contains(::STATUS_WT_NEW)); - assert!(!status.status().contains(::STATUS_INDEX_NEW)); + assert!(status.status().contains(::Status::WT_NEW)); + assert!(!status.status().contains(::Status::INDEX_NEW)); assert!(status.head_to_index().is_none()); let diff = status.index_to_workdir().unwrap(); assert_eq!(diff.old_file().path_bytes().unwrap(), b"foo"); @@ -402,6 +402,6 @@ mod tests { assert!(repo.status_file(Path::new("foo")).is_err()); t!(File::create(td.path().join("foo"))); let status = t!(repo.status_file(Path::new("foo"))); - assert!(status.contains(::STATUS_WT_NEW)); + assert!(status.contains(::Status::WT_NEW)); } } From 00da6900bc4f4150a3198962a8f52b61837ba722 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 4 Feb 2018 09:27:51 -0500 Subject: [PATCH 223/860] oid: Correct documentation of errors on from_str (#292) The `from_str` implementation just calls the libgit2 function `git_oid_fromstrn`, which accepts any non-empty hex-string with length less than 40: https://github.com/libgit2/libgit2/blob/8abd514c270ba3b3fc42c6d5feefedc4cc65dd9b/src/oid.c#L31-L42 --- src/oid.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/oid.rs b/src/oid.rs index acd6d67e63..b63fe34510 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -18,8 +18,10 @@ pub struct Oid { impl Oid { /// Parse a hex-formatted object id into an Oid structure. /// - /// If the string is not a valid 40-character hex string, an error is - /// returned. + /// # Errors + /// + /// Returns an error if the string is empty, is longer than 40 hex + /// characters, or contains any non-hex characters. pub fn from_str(s: &str) -> Result { ::init(); let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; @@ -130,8 +132,10 @@ impl str::FromStr for Oid { /// Parse a hex-formatted object id into an Oid structure. /// - /// If the string is not a valid 40-character hex string, an error is - /// returned. + /// # Errors + /// + /// Returns an error if the string is empty, is longer than 40 hex + /// characters, or contains any non-hex characters. fn from_str(s: &str) -> Result { Oid::from_str(s) } From 06891e00f0452374628e099d2465244a0a1aa3fb Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 4 Feb 2018 17:29:39 -0500 Subject: [PATCH 224/860] libgit2-sys: Add missing git_odb_backend_malloc This function is meant to be used by backends when they need to allocate memory: https://github.com/libgit2/libgit2/blob/26f5d36d2f14dc1d711ed0a2c844ef4d7887a9b3/include/git2/sys/odb_backend.h refs #222 --- libgit2-sys/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index b60275668e..8bcef9fe12 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2921,6 +2921,9 @@ extern { backend: *mut git_odb_backend, priority: c_int) -> c_int; + pub fn git_odb_backend_malloc(backend: *mut git_odb_backend, + len: size_t) -> *mut c_void; + pub fn git_odb_num_backends(odb: *mut git_odb) -> size_t; pub fn git_odb_get_backend(backend: *mut *mut git_odb_backend, odb: *mut git_odb, From 96695e90a66a4326b4d296d62ab504d35199cb77 Mon Sep 17 00:00:00 2001 From: Uri Baghin Date: Sun, 11 Feb 2018 18:34:18 +1100 Subject: [PATCH 225/860] Forward error from credential callback. --- src/remote_callbacks.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index a472609642..fdeaa83f63 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -1,4 +1,4 @@ -use std::ffi::CStr; +use std::ffi::{CStr, CString}; use std::marker; use std::mem; use std::slice; @@ -279,6 +279,8 @@ extern fn credentials_cb(ret: *mut *mut raw::git_cred, let cred_type = CredentialType::from_bits_truncate(allowed_types as u32); callback(url, username_from_url, cred_type).map_err(|e| { + let s = CString::new(e.to_string()).unwrap(); + raw::giterr_set_str(e.raw_code() as c_int, s.as_ptr()); e.raw_code() as c_int }) }); From 20e8556709a72888feb7cebd371fd2c609bd8d53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 22 Feb 2018 09:35:55 +0100 Subject: [PATCH 226/860] libgit2-sys: bump vendored version to v0.27.0-rc1 --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index f1323d9c16..809b0ca6b9 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit f1323d9c161aeeada190fd9615a8b5a9fb8a7f3e +Subproject commit 809b0ca6b9b6a5648b8e802a9f0c6a0821257595 From 4179624f934ff974e05ceb34563af26c50421398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 22 Feb 2018 10:33:52 +0100 Subject: [PATCH 227/860] odb: adjust to changes in the git_odb_open_rstream signature --- libgit2-sys/lib.rs | 4 ++++ src/odb.rs | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 8bcef9fe12..270be40378 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1322,6 +1322,8 @@ pub struct git_odb_backend { git_otype) -> c_int, pub readstream: extern fn(*mut *mut git_odb_stream, + *mut size_t, + *mut git_otype, *mut git_odb_backend, *const git_oid) -> c_int, @@ -2835,6 +2837,8 @@ extern { pub fn git_odb_new(db: *mut *mut git_odb) -> c_int; pub fn git_odb_free(db: *mut git_odb); pub fn git_odb_open_rstream(out: *mut *mut git_odb_stream, + len: *mut size_t, + otype: *mut git_otype, db: *mut git_odb, oid: *const git_oid) -> c_int; pub fn git_odb_stream_read(stream: *mut git_odb_stream, diff --git a/src/odb.rs b/src/odb.rs index 471236ac88..c3a07a4743 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -49,11 +49,13 @@ impl<'repo> Odb<'repo> { /// /// Note that most backends do not support streaming reads because they store their objects as compressed/delta'ed blobs. /// If the backend does not support streaming reads, use the `read` method instead. - pub fn reader(&self, oid: Oid) -> Result { + pub fn reader(&self, oid: Oid) -> Result<(OdbReader, usize, ObjectType), Error> { let mut out = ptr::null_mut(); + let mut size = 0usize; + let mut otype: raw::git_otype = ObjectType::Any.raw(); unsafe { - try_call!(raw::git_odb_open_rstream(&mut out, self.raw, oid.raw())); - Ok(OdbReader::from_raw(out)) + try_call!(raw::git_odb_open_rstream(&mut out, &mut size, &mut otype, self.raw, oid.raw())); + Ok((OdbReader::from_raw(out), size, ObjectType::from_raw(otype).unwrap())) } } From 708f3775452129669a41288a4a98cd86e1ff7394 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 22 Feb 2018 19:31:27 +0100 Subject: [PATCH 228/860] Fix lifetime of Object::peel_to_* result The peeled object lives as long as the repo. Fixes #299. --- src/object.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/object.rs b/src/object.rs index 6bf524c321..725e4c77fd 100644 --- a/src/object.rs +++ b/src/object.rs @@ -43,22 +43,22 @@ impl<'repo> Object<'repo> { } /// Recursively peel an object until a blob is found - pub fn peel_to_blob(&self) -> Result { + pub fn peel_to_blob(&self) -> Result, Error> { self.peel(ObjectType::Blob).map(|o| o.cast_or_panic(ObjectType::Blob)) } /// Recursively peel an object until a commit is found - pub fn peel_to_commit(&self) -> Result { + pub fn peel_to_commit(&self) -> Result, Error> { self.peel(ObjectType::Commit).map(|o| o.cast_or_panic(ObjectType::Commit)) } /// Recursively peel an object until a tag is found - pub fn peel_to_tag(&self) -> Result { + pub fn peel_to_tag(&self) -> Result, Error> { self.peel(ObjectType::Tag).map(|o| o.cast_or_panic(ObjectType::Tag)) } /// Recursively peel an object until a tree is found - pub fn peel_to_tree(&self) -> Result { + pub fn peel_to_tree(&self) -> Result, Error> { self.peel(ObjectType::Tree).map(|o| o.cast_or_panic(ObjectType::Tree)) } From c97e1193db1ed763c7c28a11eb280b740b814d97 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 27 Feb 2018 15:59:55 +0300 Subject: [PATCH 229/860] Update libgit2 to the next rc The rc notably includes a fix for the tls error on windows 7: https://github.com/libgit2/libgit2/pull/4550 --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 809b0ca6b9..c9d59c6140 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 809b0ca6b9b6a5648b8e802a9f0c6a0821257595 +Subproject commit c9d59c6140fc365eb7ab950fb1a33187a949d403 From a5a67bea21e198265159b6c0e6c1a192023ce1d8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 27 Feb 2018 05:10:04 -0800 Subject: [PATCH 230/860] Bump crates to 0.7.0 --- Cargo.toml | 4 ++-- git2-curl/Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9707ef2324..34bcef25a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.6.11" +version = "0.7.0" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -24,7 +24,7 @@ appveyor = { repository = "alexcrichton/git2-rs" } url = "1.0" bitflags = "1.0" libc = "0.2" -libgit2-sys = { path = "libgit2-sys", version = "0.6.19" } +libgit2-sys = { path = "libgit2-sys", version = "0.7.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index a9bf353901..8234a580c0 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.7.0" +version = "0.8.0" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/git2-rs" @@ -17,7 +17,7 @@ Intended to be used with the git2 crate. curl = "0.4" url = "1.0" log = "0.3" -git2 = { path = "..", version = "0.6", default-features = false } +git2 = { path = "..", version = "0.7", default-features = false } [dev-dependencies] civet = "0.8" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 6c2e9eb486..5e7ec56651 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,13 +1,12 @@ [package] name = "libgit2-sys" -version = "0.6.19" +version = "0.7.0" authors = ["Alex Crichton "] links = "git2" build = "build.rs" repository = "https://github.com/alexcrichton/git2-rs" license = "MIT/Apache-2.0" description = "Native bindings to the libgit2 library" -publish = false # needs a major version bump [lib] name = "libgit2_sys" From b7a6b9e9b4e2f1998ca4e43227362f379e2f35c0 Mon Sep 17 00:00:00 2001 From: Gabriella Chronis Date: Wed, 21 Feb 2018 17:06:00 -0800 Subject: [PATCH 231/860] Add bindings for creating and extracting GPG signatures These were added in libgit2 v24 --- libgit2-sys/lib.rs | 10 ++++++++++ src/repo.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 8bcef9fe12..8e169790f3 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2141,6 +2141,16 @@ extern { pub fn git_annotated_commit_lookup(out: *mut *mut git_annotated_commit, repo: *mut git_repository, id: *const git_oid) -> c_int; + pub fn git_commit_create_with_signature(id: *mut git_oid, + repo: *mut git_repository, + commit_content: *const c_char, + signature: *const c_char, + signature_field: *const c_char) -> c_int; + pub fn git_commit_extract_signature(signature: *mut git_buf, + signed_data: *mut git_buf, + repo: *mut git_repository, + commit_id: *mut git_oid, + field: *const c_char) -> c_int; // branch pub fn git_branch_create(out: *mut *mut git_reference, diff --git a/src/repo.rs b/src/repo.rs index 1723e6348c..4edc5f3616 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -998,6 +998,56 @@ impl Repository { } } + /// Create a commit object from the given buffer and signature + /// + /// Given the unsigned commit object's contents, its signature and the + /// header field in which to store the signature, attach the signature to + /// the commit and write it into the given repository. + /// + /// Use `None` in `signature_field` to use the default of `gpgsig`, which is + /// almost certainly what you want. + /// + /// Returns the resulting (signed) commit id. + pub fn commit_signed(&self, + commit_content: &str, + signature: &str, + signature_field: Option<&str>) -> Result { + let commit_content = try!(CString::new(commit_content)); + let signature = try!(CString::new(signature)); + let signature_field = try!(::opt_cstr(signature_field)); + let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + unsafe { + try_call!(raw::git_commit_create_with_signature(&mut raw, + self.raw(), + commit_content, + signature, + signature_field)); + Ok(Binding::from_raw(&raw as *const _)) + } + } + + + /// Extract the signature from a commit + /// + /// Returns a tuple containing the signature in the first value and the + /// signed data in the second. + pub fn extract_signature(&self, + commit_id: &Oid, + signature_field: Option<&str>) + -> Result<(Buf, Buf), Error> { + let signature_field = try!(::opt_cstr(signature_field)); + let signature = Buf::new(); + let content = Buf::new(); + unsafe { + try_call!(raw::git_commit_extract_signature(signature.raw(), + content.raw(), + self.raw(), + commit_id.raw() as *mut _, + signature_field)); + Ok((signature, content)) + } + } + /// Lookup a reference to one of the commits in a repository. pub fn find_commit(&self, oid: Oid) -> Result { From 04c1b914a2e96a50677c54ab3ee2233221c1ebd2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 7 Mar 2018 11:06:07 -0800 Subject: [PATCH 232/860] Fix MinGW builds on Windows without pkg-config --- libgit2-sys/build.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 1f0e97aae4..845a85f1cb 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -70,13 +70,15 @@ fn main() { // windows as libssh2 doesn't come with a libssh2.pc file in that install // (or when pkg-config isn't found). As a result we just manually turn on // SSH support in libgit2 (a little jankily) here... + let mut ssh_forced = false; if ssh && (windows || !has_pkgconfig) { if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") { + ssh_forced = true; if msvc { cfg.cflag(format!("/I{}", libssh2_include)) .cflag("/DGIT_SSH"); } else { - cfg.cflag(format!("-I{}", libssh2_include)) + cfg.cflag(format!("-I{}", sanitize_sh(libssh2_include.as_ref()))) .cflag("-DGIT_SSH"); } } @@ -130,7 +132,7 @@ fn main() { // Make sure libssh2 was detected on unix systems, because it definitely // should have been! - if ssh && !msvc { + if ssh && !ssh_forced { let flags = dst.join("build/src/git2/sys/features.h"); let mut contents = String::new(); t!(t!(File::open(flags)).read_to_string(&mut contents)); @@ -197,3 +199,20 @@ fn prepend(var: &str, val: PathBuf) { v.extend(env::split_paths(&prefix)); env::set_var(var, &env::join_paths(v).unwrap()); } + +fn sanitize_sh(path: &Path) -> String { + let path = path.to_str().unwrap().replace("\\", "/"); + return change_drive(&path).unwrap_or(path); + + fn change_drive(s: &str) -> Option { + let mut ch = s.chars(); + let drive = ch.next().unwrap_or('C'); + if ch.next() != Some(':') { + return None + } + if ch.next() != Some('/') { + return None + } + Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..])) + } +} From 951886c7e82f9296a7215f327eb0b7ff8cd4919e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 7 Mar 2018 11:06:23 -0800 Subject: [PATCH 233/860] Bump libgit2-sys to 0.7.1 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 5e7ec56651..574cdad6f4 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.0" +version = "0.7.1" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From b6f1bfd212e5d1bba61e8bec4f6d8e957a7a6075 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 14 Mar 2018 18:19:22 -0700 Subject: [PATCH 234/860] Update log to 0.4 --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 8234a580c0..576531c5e5 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -16,7 +16,7 @@ Intended to be used with the git2 crate. [dependencies] curl = "0.4" url = "1.0" -log = "0.3" +log = "0.4" git2 = { path = "..", version = "0.7", default-features = false } [dev-dependencies] From 374850f32c8d0a5dcea48e6dec8d1afdb1d83013 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 14 Mar 2018 18:20:03 -0700 Subject: [PATCH 235/860] Bump git2-curl to 0.8.1 --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 576531c5e5..85c1c77f80 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.8.0" +version = "0.8.1" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/git2-rs" From bef6464ca714f0764a3ae99b083f500760bad50f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 22 Mar 2018 12:50:51 -0700 Subject: [PATCH 236/860] Add debug logging for failed credential helpers --- Cargo.toml | 1 + src/cred.rs | 16 ++++++++++++++-- src/lib.rs | 1 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 34bcef25a1..1cc9ae2cfc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ appveyor = { repository = "alexcrichton/git2-rs" } url = "1.0" bitflags = "1.0" libc = "0.2" +log = "0.4" libgit2-sys = { path = "libgit2-sys", version = "0.7.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] diff --git a/src/cred.rs b/src/cred.rs index 61591daae8..58564c3569 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -287,7 +287,13 @@ impl CredentialHelper { fn execute_cmd(&self, cmd: &str, username: &Option) -> (Option, Option) { macro_rules! my_try( ($e:expr) => ( - match $e { Ok(e) => e, Err(..) => return (None, None) } + match $e { + Ok(e) => e, + Err(e) => { + debug!("{} failed with {}", stringify!($e), e); + return (None, None) + } + } ) ); let mut p = my_try!(Command::new("sh").arg("-c") @@ -311,7 +317,13 @@ impl CredentialHelper { } } let output = my_try!(p.wait_with_output()); - if !output.status.success() { return (None, None) } + if !output.status.success() { + debug!("credential helper failed: {}\nstdout ---\n{}\nstdout ---\n{}", + output.status, + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr)); + return (None, None) + } self.parse_output(output.stdout) } diff --git a/src/lib.rs b/src/lib.rs index f0764dabdc..0a5ddef45d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,6 +72,7 @@ extern crate libc; extern crate url; extern crate libgit2_sys as raw; #[macro_use] extern crate bitflags; +#[macro_use] extern crate log; #[cfg(test)] extern crate tempdir; use std::ffi::{CStr, CString}; From 4ecfcdb6708802756a0b22bd901e5d854ca503e2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 22 Mar 2018 12:53:21 -0700 Subject: [PATCH 237/860] Trace more output of the credential helper --- src/cred.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cred.rs b/src/cred.rs index 58564c3569..6e7d2ce3bf 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -324,6 +324,8 @@ impl CredentialHelper { String::from_utf8_lossy(&output.stderr)); return (None, None) } + trace!("credential helper stderr ---\n{}", + String::from_utf8_lossy(&output.stderr)); self.parse_output(output.stdout) } @@ -335,7 +337,13 @@ impl CredentialHelper { for line in output.split(|t| *t == b'\n') { let mut parts = line.splitn(2, |t| *t == b'='); let key = parts.next().unwrap(); - let value = match parts.next() { Some(s) => s, None => continue }; + let value = match parts.next() { + Some(s) => s, + None => { + trace!("ignoring output line: {}", String::from_utf8_lossy(line)); + continue + } + }; let value = match String::from_utf8(value.to_vec()) { Ok(s) => s, Err(..) => continue, From 256f12b15250d77ba9b79c4cda605ca3f490f022 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 22 Mar 2018 13:12:43 -0700 Subject: [PATCH 238/860] Implement a fallback for missing `sh` Closes #274 --- src/cred.rs | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/src/cred.rs b/src/cred.rs index 6e7d2ce3bf..5de8cf22f1 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -296,12 +296,44 @@ impl CredentialHelper { } ) ); - let mut p = my_try!(Command::new("sh").arg("-c") - .arg(&format!("{} get", cmd)) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn()); + // It looks like the `cmd` specification is typically bourne-shell-like + // syntax, so try that first. If that fails, though, we may be on a + // Windows machine for example where `sh` isn't actually available by + // default. Most credential helper configurations though are pretty + // simple (aka one or two space-separated strings) so also try to invoke + // the process directly. + // + // If that fails then it's up to the user to put `sh` in path and make + // sure it works. + let mut c = Command::new("sh"); + c.arg("-c") + .arg(&format!("{} get", cmd)) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); + let mut p = match c.spawn() { + Ok(p) => p, + Err(e) => { + debug!("`sh` failed to spawn: {}", e); + let mut parts = cmd.split_whitespace(); + let mut c = Command::new(parts.next().unwrap()); + for arg in parts { + c.arg(arg); + } + c.arg("get") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); + match c.spawn() { + Ok(p) => p, + Err(e) => { + debug!("fallback of {:?} failed with {}", cmd, e); + return (None, None); + } + } + } + }; + // Ignore write errors as the command may not actually be listening for // stdin { From 0c1eb687d6a8d6be61e48277a4be7d982560b052 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 22 Mar 2018 13:13:15 -0700 Subject: [PATCH 239/860] Bump to 0.7.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1cc9ae2cfc..a911cc5dc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.7.0" +version = "0.7.1" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From f5f7834ceebb060f42812f47b048904e9627d810 Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sun, 8 Apr 2018 12:57:50 +0200 Subject: [PATCH 240/860] fix(cargo): Update minimal required dependencies --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 574cdad6f4..83bf44c95e 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -16,7 +16,7 @@ path = "lib.rs" curl-sys = { version = "0.4", optional = true } libc = "0.2" libssh2-sys = { version = "0.2.4", optional = true } -libz-sys = ">= 0" +libz-sys = ">= 0.1.2" [build-dependencies] pkg-config = "0.3" From da8a32425d4eea328f13f0fb7f35f94f1298b96b Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Fri, 20 Apr 2018 18:46:54 +0900 Subject: [PATCH 241/860] Manifest: add excludes Git's test data weighs at about half of the source. Trimming this down reduces package size. --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index a911cc5dc3..6f53735e4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,9 @@ both threadsafe and memory safe and allows both reading and writing git repositories. """ categories = ["api-bindings"] +exclude = [ + "libgit2/tests/*", +] [badges] travis-ci = { repository = "alexcrichton/git2-rs" } From 756a698cf238a27f920b0089eb0b92e3d1320a26 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 20 Apr 2018 07:21:28 -0700 Subject: [PATCH 242/860] Disable MinGW on CI --- appveyor.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 31aaccb0ec..0182bfd8b6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,5 @@ environment: matrix: - - TARGET: x86_64-pc-windows-gnu - MSYS_BITS: 64 - - TARGET: i686-pc-windows-gnu - MSYS_BITS: 32 - TARGET: x86_64-pc-windows-msvc - TARGET: i686-pc-windows-msvc install: From d90163af06e3e19f5c2c651c7e69760c357dc618 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 20 Apr 2018 07:26:58 -0700 Subject: [PATCH 243/860] Move exclude to the right location --- Cargo.toml | 3 --- libgit2-sys/Cargo.toml | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6f53735e4f..a911cc5dc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,9 +15,6 @@ both threadsafe and memory safe and allows both reading and writing git repositories. """ categories = ["api-bindings"] -exclude = [ - "libgit2/tests/*", -] [badges] travis-ci = { repository = "alexcrichton/git2-rs" } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 83bf44c95e..fa73107993 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -7,6 +7,9 @@ build = "build.rs" repository = "https://github.com/alexcrichton/git2-rs" license = "MIT/Apache-2.0" description = "Native bindings to the libgit2 library" +exclude = [ + "libgit2/tests/*", +] [lib] name = "libgit2_sys" From 2a8a4fda6fb51d0265b1e13ebf7dc420f035c18a Mon Sep 17 00:00:00 2001 From: lukaslueg Date: Sun, 22 Apr 2018 19:24:42 +0200 Subject: [PATCH 244/860] Update README.md I guess not bumping this was an oversight? 0.7.1 is stable. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 508932f382..49fe300de4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ libgit2 bindings for Rust ```toml [dependencies] -git2 = "0.6" +git2 = "0.7" ``` ## Version of libgit2 From 9bc0eeb64f3ea0d64a0c168e40d58386ed6d4302 Mon Sep 17 00:00:00 2001 From: Daniel Ferguson Date: Thu, 17 May 2018 23:41:02 +0100 Subject: [PATCH 245/860] Add Config.remove_multivar --- src/config.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/config.rs b/src/config.rs index 732e67655c..f45bda6d45 100644 --- a/src/config.rs +++ b/src/config.rs @@ -135,6 +135,17 @@ impl Config { } } + /// Remove multivar config variables in the config file with the highest level (usually the + /// local one). + pub fn remove_multivar(&mut self, name: &str, regexp: &str) -> Result<(), Error> { + let name = try!(CString::new(name)); + let regexp = try!(CString::new(regexp)); + unsafe { + try_call!(raw::git_config_delete_multivar(self.raw, name, regexp)); + } + Ok(()) + } + /// Get the value of a boolean config variable. /// /// All config files will be looked into, in the order of their defined @@ -564,6 +575,10 @@ mod tests { .collect(); values.sort(); assert_eq!(values, ["baz", "qux"]); + + cfg.remove_multivar("foo.bar", ".*").unwrap(); + + assert_eq!(cfg.entries(None).unwrap().count(), 0); } #[test] From 1a16f46fbb031cde347faedc100e61d885f4da98 Mon Sep 17 00:00:00 2001 From: Gwen Lofman Date: Mon, 21 May 2018 00:14:56 -0400 Subject: [PATCH 246/860] Add convinience methods to check bitflags Use a simple macro to create methods which simply check a single flag in a more readable and friendly way. --- src/lib.rs | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 0a5ddef45d..bd55f834dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,6 +123,16 @@ pub use treebuilder::TreeBuilder; pub use odb::{Odb, OdbObject, OdbReader, OdbWriter}; pub use util::IntoCString; +// Create a convinience method on bitflag struct which checks the given flag +macro_rules! is_bit_set { + ($name:ident, $flag:expr) => ( + #[allow(missing_docs)] + pub fn $name(&self) -> bool { + self.intersects($flag) + } + ) +} + /// An enumeration of possible errors that can happen when working with a git /// repository. #[derive(PartialEq, Eq, Clone, Debug, Copy)] @@ -385,6 +395,13 @@ bitflags! { } } +impl Sort { + is_bit_set!(is_none, Sort::NONE); + is_bit_set!(is_topological, Sort::TOPOLOGICAL); + is_bit_set!(is_time, Sort::TIME); + is_bit_set!(is_reverse, Sort::REVERSE); +} + bitflags! { /// Types of credentials that can be requested by a credential callback. pub struct CredentialType: u32 { @@ -405,6 +422,16 @@ bitflags! { } } +impl CredentialType { + is_bit_set!(is_user_pass_plaintext, CredentialType::USER_PASS_PLAINTEXT); + is_bit_set!(is_ssh_key, CredentialType::SSH_KEY); + is_bit_set!(is_ssh_memory, CredentialType::SSH_MEMORY); + is_bit_set!(is_ssh_custom, CredentialType::SSH_CUSTOM); + is_bit_set!(is_default, CredentialType::DEFAULT); + is_bit_set!(is_ssh_interactive, CredentialType::SSH_INTERACTIVE); + is_bit_set!(is_username, CredentialType::USERNAME); +} + bitflags! { /// Flags for the `flags` field of an IndexEntry. pub struct IndexEntryFlag: u16 { @@ -415,6 +442,11 @@ bitflags! { } } +impl IndexEntryFlag { + is_bit_set!(is_extended, IndexEntryFlag::EXTENDED); + is_bit_set!(is_valid, IndexEntryFlag::VALID); +} + bitflags! { /// Flags for the `extended_flags` field of an IndexEntry. pub struct IndexEntryExtendedFlag: u16 { @@ -450,6 +482,22 @@ bitflags! { } } +impl IndexEntryExtendedFlag { + is_bit_set!(is_intent_to_add, IndexEntryExtendedFlag::INTENT_TO_ADD); + is_bit_set!(is_skip_worktree, IndexEntryExtendedFlag::SKIP_WORKTREE); + is_bit_set!(is_extended2, IndexEntryExtendedFlag::EXTENDED2); + is_bit_set!(is_update, IndexEntryExtendedFlag::UPDATE); + is_bit_set!(is_remove, IndexEntryExtendedFlag::REMOVE); + is_bit_set!(is_up_to_date, IndexEntryExtendedFlag::UPTODATE); + is_bit_set!(is_added, IndexEntryExtendedFlag::ADDED); + is_bit_set!(is_hashed, IndexEntryExtendedFlag::HASHED); + is_bit_set!(is_unhashed, IndexEntryExtendedFlag::UNHASHED); + is_bit_set!(is_wt_remove, IndexEntryExtendedFlag::WT_REMOVE); + is_bit_set!(is_conflicted, IndexEntryExtendedFlag::CONFLICTED); + is_bit_set!(is_unpacked, IndexEntryExtendedFlag::UNPACKED); + is_bit_set!(is_new_skip_worktree, IndexEntryExtendedFlag::NEW_SKIP_WORKTREE); +} + bitflags! { /// Flags for APIs that add files matching pathspec pub struct IndexAddOption: u32 { @@ -465,6 +513,13 @@ bitflags! { } } +impl IndexAddOption { + is_bit_set!(is_default, IndexAddOption::DEFAULT); + is_bit_set!(is_force, IndexAddOption::FORCE); + is_bit_set!(is_disable_pathspec_match, IndexAddOption::DISABLE_PATHSPEC_MATCH); + is_bit_set!(is_check_pathspec, IndexAddOption::CHECK_PATHSPEC); +} + bitflags! { /// Flags for `Repository::open_ext` pub struct RepositoryOpenFlags: u32 { @@ -481,6 +536,14 @@ bitflags! { } } +impl RepositoryOpenFlags { + is_bit_set!(is_no_search, RepositoryOpenFlags::NO_SEARCH); + is_bit_set!(is_cross_fs, RepositoryOpenFlags::CROSS_FS); + is_bit_set!(is_bare, RepositoryOpenFlags::BARE); + is_bit_set!(is_no_dotgit, RepositoryOpenFlags::NO_DOTGIT); + is_bit_set!(is_from_env, RepositoryOpenFlags::FROM_ENV); +} + bitflags! { /// Flags for the return value of `Repository::revparse` pub struct RevparseMode: u32 { @@ -493,6 +556,12 @@ bitflags! { } } +impl RevparseMode { + is_bit_set!(is_no_single, RevparseMode::SINGLE); + is_bit_set!(is_range, RevparseMode::RANGE); + is_bit_set!(is_merge_base, RevparseMode::MERGE_BASE); +} + bitflags! { /// The results of `merge_analysis` indicating the merge opportunities. pub struct MergeAnalysis: u32 { @@ -515,6 +584,14 @@ bitflags! { } } +impl MergeAnalysis { + is_bit_set!(is_none, MergeAnalysis::ANALYSIS_NONE); + is_bit_set!(is_normal, MergeAnalysis::ANALYSIS_NORMAL); + is_bit_set!(is_up_to_date, MergeAnalysis::ANALYSIS_UP_TO_DATE); + is_bit_set!(is_fast_forward, MergeAnalysis::ANALYSIS_FASTFORWARD); + is_bit_set!(is_unborn, MergeAnalysis::ANALYSIS_UNBORN); +} + bitflags! { /// The user's stated preference for merges. pub struct MergePreference: u32 { @@ -530,6 +607,12 @@ bitflags! { } } +impl MergePreference { + is_bit_set!(is_none, MergePreference::NONE); + is_bit_set!(is_no_fast_forward, MergePreference::NO_FAST_FORWARD); + is_bit_set!(is_fastforward_only, MergePreference::FASTFORWARD_ONLY); +} + #[cfg(test)] #[macro_use] mod test; #[macro_use] mod panic; mod call; @@ -854,6 +937,20 @@ bitflags! { } } +impl Status { + is_bit_set!(is_index_new, Status::INDEX_NEW); + is_bit_set!(is_index_modified, Status::INDEX_MODIFIED); + is_bit_set!(is_index_deleted, Status::INDEX_DELETED); + is_bit_set!(is_index_renamed, Status::INDEX_RENAMED); + is_bit_set!(is_index_typechange, Status::INDEX_TYPECHANGE); + is_bit_set!(is_wt_new, Status::WT_NEW); + is_bit_set!(is_wt_modified, Status::WT_MODIFIED); + is_bit_set!(is_wt_typechange, Status::WT_TYPECHANGE); + is_bit_set!(is_wt_renamed, Status::WT_RENAMED); + is_bit_set!(is_ignored, Status::IGNORED); + is_bit_set!(is_conflicted, Status::CONFLICTED); +} + bitflags! { /// Mode options for RepositoryInitOptions pub struct RepositoryInitMode: u32 { @@ -867,6 +964,12 @@ bitflags! { } } +impl RepositoryInitMode { + is_bit_set!(is_shared_umask, RepositoryInitMode::SHARED_UMASK); + is_bit_set!(is_shared_group, RepositoryInitMode::SHARED_GROUP); + is_bit_set!(is_shared_all, RepositoryInitMode::SHARED_ALL); +} + /// What type of change is described by a `DiffDelta`? #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Delta { @@ -967,7 +1070,22 @@ bitflags! { #[allow(missing_docs)] const WD_UNTRACKED = raw::GIT_SUBMODULE_STATUS_WD_UNTRACKED as u32; } +} +impl SubmoduleStatus { + is_bit_set!(is_in_head, SubmoduleStatus::IN_HEAD); + is_bit_set!(is_in_index, SubmoduleStatus::IN_INDEX); + is_bit_set!(is_in_config, SubmoduleStatus::IN_CONFIG); + is_bit_set!(is_in_wd, SubmoduleStatus::IN_WD); + is_bit_set!(is_index_added, SubmoduleStatus::INDEX_ADDED); + is_bit_set!(is_index_deleted, SubmoduleStatus::INDEX_DELETED); + is_bit_set!(is_index_modified, SubmoduleStatus::INDEX_MODIFIED); + is_bit_set!(is_wd_uninitialized, SubmoduleStatus::WD_UNINITIALIZED); + is_bit_set!(is_wd_added, SubmoduleStatus::WD_ADDED); + is_bit_set!(is_wd_deleted, SubmoduleStatus::WD_DELETED); + is_bit_set!(is_wd_modified, SubmoduleStatus::WD_MODIFIED); + is_bit_set!(is_wd_wd_modified, SubmoduleStatus::WD_WD_MODIFIED); + is_bit_set!(is_wd_untracked, SubmoduleStatus::WD_UNTRACKED); } /// Submodule ignore values @@ -1017,6 +1135,16 @@ bitflags! { } } +impl PathspecFlags { + is_bit_set!(is_default, PathspecFlags::DEFAULT); + is_bit_set!(is_ignore_case, PathspecFlags::IGNORE_CASE); + is_bit_set!(is_use_case, PathspecFlags::USE_CASE); + is_bit_set!(is_no_glob, PathspecFlags::NO_GLOB); + is_bit_set!(is_no_match_error, PathspecFlags::NO_MATCH_ERROR); + is_bit_set!(is_find_failures, PathspecFlags::FIND_FAILURES); + is_bit_set!(is_failures_only, PathspecFlags::FAILURES_ONLY); +} + bitflags! { /// Types of notifications emitted from checkouts. pub struct CheckoutNotificationType: u32 { @@ -1033,6 +1161,14 @@ bitflags! { } } +impl CheckoutNotificationType { + is_bit_set!(is_conflict, CheckoutNotificationType::CONFLICT); + is_bit_set!(is_dirty, CheckoutNotificationType::DIRTY); + is_bit_set!(is_updated, CheckoutNotificationType::UPDATED); + is_bit_set!(is_untracked, CheckoutNotificationType::UNTRACKED); + is_bit_set!(is_ignored, CheckoutNotificationType::IGNORED); +} + /// Possible output formats for diff data #[derive(Copy, Clone)] pub enum DiffFormat { @@ -1065,6 +1201,14 @@ bitflags! { } } +impl DiffStatsFormat { + is_bit_set!(is_none, DiffStatsFormat::NONE); + is_bit_set!(is_full, DiffStatsFormat::FULL); + is_bit_set!(is_short, DiffStatsFormat::SHORT); + is_bit_set!(is_number, DiffStatsFormat::NUMBER); + is_bit_set!(is_include_summary, DiffStatsFormat::INCLUDE_SUMMARY); +} + /// Automatic tag following options. pub enum AutotagOption { /// Use the setting from the remote's configuration @@ -1119,6 +1263,11 @@ bitflags! { } } +impl StashApplyFlags { + is_bit_set!(is_default, StashApplyFlags::DEFAULT); + is_bit_set!(is_reinstate_index, StashApplyFlags::REINSTATE_INDEX); +} + bitflags! { #[allow(missing_docs)] pub struct StashFlags: u32 { @@ -1136,6 +1285,13 @@ bitflags! { } } +impl StashFlags { + is_bit_set!(is_default, StashFlags::DEFAULT); + is_bit_set!(is_keep_index, StashFlags::KEEP_INDEX); + is_bit_set!(is_include_untracked, StashFlags::INCLUDE_UNTRACKED); + is_bit_set!(is_include_ignored, StashFlags::INCLUDE_IGNORED); +} + #[cfg(test)] mod tests { use super::ObjectType; From 7229e43dc91c60dd14bdf9c375d2579c9ece4171 Mon Sep 17 00:00:00 2001 From: Gwen Lofman Date: Mon, 21 May 2018 00:16:11 -0400 Subject: [PATCH 247/860] Implement Default for all bitflags with a DEFAULT More idomatic Rust pattern would be to use the Default trait, used only when there is a const named DEFAULT. Consider making NONE default for bitflags which have a NONE const but no DEFAULT. --- src/lib.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index bd55f834dc..cfe443b19f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -432,6 +432,12 @@ impl CredentialType { is_bit_set!(is_username, CredentialType::USERNAME); } +impl Default for CredentialType { + fn default() -> Self { + CredentialType::DEFAULT + } +} + bitflags! { /// Flags for the `flags` field of an IndexEntry. pub struct IndexEntryFlag: u16 { @@ -520,6 +526,12 @@ impl IndexAddOption { is_bit_set!(is_check_pathspec, IndexAddOption::CHECK_PATHSPEC); } +impl Default for IndexAddOption { + fn default() -> Self { + IndexAddOption::DEFAULT + } +} + bitflags! { /// Flags for `Repository::open_ext` pub struct RepositoryOpenFlags: u32 { @@ -1145,6 +1157,12 @@ impl PathspecFlags { is_bit_set!(is_failures_only, PathspecFlags::FAILURES_ONLY); } +impl Default for PathspecFlags { + fn default() -> Self { + PathspecFlags::DEFAULT + } +} + bitflags! { /// Types of notifications emitted from checkouts. pub struct CheckoutNotificationType: u32 { @@ -1268,6 +1286,12 @@ impl StashApplyFlags { is_bit_set!(is_reinstate_index, StashApplyFlags::REINSTATE_INDEX); } +impl Default for StashApplyFlags { + fn default() -> Self { + StashApplyFlags::DEFAULT + } +} + bitflags! { #[allow(missing_docs)] pub struct StashFlags: u32 { @@ -1292,6 +1316,12 @@ impl StashFlags { is_bit_set!(is_include_ignored, StashFlags::INCLUDE_IGNORED); } +impl Default for StashFlags { + fn default() -> Self { + StashFlags::DEFAULT + } +} + #[cfg(test)] mod tests { use super::ObjectType; From 050d0e505f7490617466dbc603dff85d55de7c54 Mon Sep 17 00:00:00 2001 From: Gwen Lofman Date: Mon, 21 May 2018 00:32:36 -0400 Subject: [PATCH 248/860] Automate commit testing with proper stashing Add a installation instructions for a git hook to automate testing done on each commit. Promotes proper handling of edge cases related to testing code that will not be in the commit, which masks errors that show up later as a nasty surprise. Fully opt in, links to a gist on github. --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 49fe300de4..b060602d36 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,18 @@ $ cd git2-rs $ cargo build ``` +### Automating Testing + +Running tests and handling all of the associated edge cases on every commit +proves tedious very quickly. To automate tests and handle proper stashing and +unstashing of unstaged changes and thus avoid nasty surprises, use the +pre-commit hook found [here][pre-commit-hook] and place it into the +`.git/hooks/` with the name `pre-commit`. You may need to add execution +permissions with `chmod +x`. + + +To skip tests on a simple commit or doc-fixes, use `git commit --no-verify`. + ## Building on OSX 10.10+ Currently libssh2 requires linking against OpenSSL, and to compile libssh2 it @@ -55,3 +67,5 @@ at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in git2-rs by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + +[pre-commit-hook]: https://gist.github.com/glfmn/0c5e9e2b41b48007ed3497d11e3dbbfa From d38762b51d088f3ccc13016d96296b707df73114 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 29 May 2018 09:36:13 -0700 Subject: [PATCH 249/860] Bump libgit2-sys to 0.7.2 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index fa73107993..222ffe8eaf 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.1" +version = "0.7.2" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 868ccf333530452a7bfa77a515c25b6e715c8fe4 Mon Sep 17 00:00:00 2001 From: Heiko Becker Date: Wed, 30 May 2018 16:16:02 +0200 Subject: [PATCH 250/860] Update libgit2 to include fixes for LibreSSL 2.7 I did not update it to a even newer version to no import that many changes. Nevertheless it contains a few fixes, for a memleak amongst other things. --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index c9d59c6140..83d6327d2e 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit c9d59c6140fc365eb7ab950fb1a33187a949d403 +Subproject commit 83d6327d2e193ec32355fdc9505f792a31cbeff0 From d97950b185c00a9d431efc5dbc512f1cb7abbe34 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 31 May 2018 07:13:31 -0700 Subject: [PATCH 251/860] Tweak systest to ignore git_diff_option_t We'll fix that on the next major update of libgit2-sys --- systest/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/systest/build.rs b/systest/build.rs index fad3e55739..5ee841d468 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -30,6 +30,8 @@ fn main() { "git_push_transfer_progress" | "git_push_negotiation" | "git_packbuilder_progress" => true, + // TODO: fix this on the next major update of libgit2-sys + "git_diff_option_t" => true, _ => false, } }); From 24e3d4d94c9ad0c406dd5efd18b342c3deda168f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 31 May 2018 07:25:43 -0700 Subject: [PATCH 252/860] Update libgit2 submodule again Pull in a fix for CVE 2018-11235 --- libgit2-sys/lib.rs | 1 + libgit2-sys/libgit2 | 2 +- src/config.rs | 5 +++++ src/remote.rs | 4 ++-- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 4034a654e0..5d0e2972f5 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -770,6 +770,7 @@ pub struct git_index_time { pub struct git_config_entry { pub name: *const c_char, pub value: *const c_char, + pub include_depth: c_uint, pub level: git_config_level_t, pub free: extern fn(*mut git_config_entry), pub payload: *mut c_void, diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 83d6327d2e..771dfd1dd1 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 83d6327d2e193ec32355fdc9505f792a31cbeff0 +Subproject commit 771dfd1dd1c27a4693dfdfea521c07e72f456b29 diff --git a/src/config.rs b/src/config.rs index f45bda6d45..b01729aebd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -451,6 +451,11 @@ impl<'cfg> ConfigEntry<'cfg> { pub fn level(&self) -> ConfigLevel { unsafe { ConfigLevel::from_raw((*self.raw).level) } } + + /// Depth of includes where this variable was found + pub fn include_depth(&self) -> u32 { + unsafe { (*self.raw).include_depth as u32 } + } } impl<'cfg> Binding for ConfigEntry<'cfg> { diff --git a/src/remote.rs b/src/remote.rs index 9e1704c40e..b385a1dfa2 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -639,8 +639,8 @@ mod tests { fn rename_remote() { let (_td, repo) = ::test::repo_init(); repo.remote("origin", "foo").unwrap(); - repo.remote_rename("origin", "foo").unwrap(); - repo.remote_delete("foo").unwrap(); + drop(repo.remote_rename("origin", "foo")); + drop(repo.remote_delete("foo")); } #[test] From 2a53469b0db9a01ae3894d3925518c776eccc34a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 31 May 2018 08:02:17 -0700 Subject: [PATCH 253/860] Bump libgit2-sys to 0.7.3 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 222ffe8eaf..a253c6ceb3 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.2" +version = "0.7.3" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 02e4f5059104645c53ed59045bf2c78c5470843b Mon Sep 17 00:00:00 2001 From: Igor Gnatenko Date: Thu, 14 Jun 2018 08:35:51 +0200 Subject: [PATCH 254/860] bump docopt to 1.0 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a911cc5dc3..d1a2628fde 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ openssl-sys = { version = "0.9.0", optional = true } openssl-probe = { version = "0.1", optional = true } [dev-dependencies] -docopt = "0.8" +docopt = "1.0" serde = "1.0" serde_derive = "1.0" time = "0.1" From 06cbbd2b171d9125605fd938ddd4c6b9fb58d8e7 Mon Sep 17 00:00:00 2001 From: Dustin Frisch Date: Wed, 20 Jun 2018 00:40:42 +0200 Subject: [PATCH 255/860] Add Cred::ssh_key_from_memory --- src/cred.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/cred.rs b/src/cred.rs index 5de8cf22f1..24470c80d8 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -68,6 +68,24 @@ impl Cred { } } + /// Create a new ssh key credential object reading the keys from memory. + pub fn ssh_key_from_memory(username: &str, + publickey: Option<&str>, + privatekey: &str, + passphrase: Option<&str>) -> Result { + ::init(); + let username = try!(CString::new(username)); + let publickey = try!(::opt_cstr(publickey)); + let privatekey = try!(CString::new(privatekey)); + let passphrase = try!(::opt_cstr(passphrase)); + let mut out = ptr::null_mut(); + unsafe { + try_call!(raw::git_cred_ssh_key_memory_new(&mut out, username, publickey, + privatekey, passphrase)); + Ok(Binding::from_raw(out)) + } + } + /// Create a new plain-text username and password credential object. pub fn userpass_plaintext(username: &str, password: &str) -> Result { From 9335c76b67ea3c445ade0d554459da53c8736ded Mon Sep 17 00:00:00 2001 From: Dustin Frisch Date: Mon, 2 Jul 2018 23:04:06 +0200 Subject: [PATCH 256/860] fixup! Add Cred::ssh_key_from_memory --- src/cred.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/cred.rs b/src/cred.rs index 24470c80d8..29d514885a 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -522,6 +522,48 @@ echo username=c .execute().is_none()); } + #[test] + fn ssh_key_from_memory() { + let cred = Cred::ssh_key_from_memory( + "test", + Some("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDByAO8uj+kXicj6C2ODMspgmUoVyl5eaw8vR6a1yEnFuJFzevabNlN6Ut+CPT3TRnYk5BW73pyXBtnSL2X95BOnbjMDXc4YIkgs3YYHWnxbqsD4Pj/RoGqhf+gwhOBtL0poh8tT8WqXZYxdJQKLQC7oBqf3ykCEYulE4oeRUmNh4IzEE+skD/zDkaJ+S1HRD8D8YCiTO01qQnSmoDFdmIZTi8MS8Cw+O/Qhym1271ThMlhD6PubSYJXfE6rVbE7A9RzH73A6MmKBlzK8VTb4SlNSrr/DOk+L0uq+wPkv+pm+D9WtxoqQ9yl6FaK1cPawa3+7yRNle3m+72KCtyMkQv"), + r#" + -----BEGIN RSA PRIVATE KEY----- + Proc-Type: 4,ENCRYPTED + DEK-Info: AES-128-CBC,818C7722D3B01F2161C2ACF6A5BBAAE8 + + 3Cht4QB3PcoQ0I55j1B3m2ZzIC/mrh+K5nQeA1Vy2GBTMyM7yqGHqTOv7qLhJscd + H+cB0Pm6yCr3lYuNrcKWOCUto+91P7ikyARruHVwyIxKdNx15uNulOzQJHQWNbA4 + RQHlhjON4atVo2FyJ6n+ujK6QiBg2PR5Vbbw/AtV6zBCFW3PhzDn+qqmHjpBFqj2 + vZUUe+MkDQcaF5J45XMHahhSdo/uKCDhfbylExp/+ACWkvxdPpsvcARM6X434ucD + aPY+4i0/JyLkdbm0GFN9/q3i53qf4kCBhojFl4AYJdGI0AzAgbdTXZ7EJHbAGZHS + os5K0oTwDVXMI0sSE2I/qHxaZZsDP1dOKq6di6SFPUp8liYimm7rNintRX88Gl2L + g1ko9abp/NlgD0YY/3mad+NNAISDL/YfXq2fklH3En3/7ZrOVZFKfZXwQwas5g+p + VQPKi3+ae74iOjLyuPDSc1ePmhUNYeP+9rLSc0wiaiHqls+2blPPDxAGMEo63kbz + YPVjdmuVX4VWnyEsfTxxJdFDYGSNh6rlrrO1RFrex7kJvpg5gTX4M/FT8TfCd7Hn + M6adXsLMqwu5tz8FuDmAtVdq8zdSrgZeAbpJ9D3EDOmZ70xz4XBL19ImxDp+Qqs2 + kQX7kobRzeeP2URfRoGr7XZikQWyQ2UASfPcQULY8R58QoZWWsQ4w51GZHg7TDnw + 1DRo/0OgkK7Gqf215nFmMpB4uyi58cq3WFwWQa1IqslkObpVgBQZcNZb/hKUYPGk + g4zehfIgAfCdnQHwZvQ6Fdzhcs3SZeO+zVyuiZN3Gsi9HU0/1vpAKiuuOzcG02vF + b6Y6hwsAA9yphF3atI+ARD4ZwXdDfzuGb3yJglMT3Fr/xuLwAvdchRo1spANKA0E + tT5okLrK0H4wnHvf2SniVVWRhmJis0lQo9LjGGwRIdsPpVnJSDvaISIVF+fHT90r + HvxN8zXI93x9jcPtwp7puQ1C7ehKJK10sZ71OLIZeuUgwt+5DRunqg6evPco9Go7 + UOGwcVhLY200KT+1k7zWzCS0yVQp2HRm6cxsZXAp4ClBSwIx15eIoLIrjZdJRjCq + COp6pZx1fnvJ9ERIvl5hon+Ty+renMcFKz2HmchC7egpcqIxW9Dsv6zjhHle6pxb + 37GaEKHF2KA3RN+dSV/K8n+C9Yent5tx5Y9a/pMcgRGtgu+G+nyFmkPKn5Zt39yX + qDpyM0LtbRVZPs+MgiqoGIwYc/ujoCq7GL38gezsBQoHaTt79yYBqCp6UR0LMuZ5 + f/7CtWqffgySfJ/0wjGidDAumDv8CK45AURpL/Z+tbFG3M9ar/LZz/Y6EyBcLtGY + Wwb4zs8zXIA0qHrjNTnPqHDvezziArYfgPjxCIHMZzms9Yn8+N02p39uIytqg434 + BAlCqZ7GYdDFfTpWIwX+segTK9ux0KdBqcQv+9Fwwjkq9KySnRKqNl7ZJcefFZJq + c6PA1iinZWBjuaO1HKx3PFulrl0bcpR9Kud1ZIyfnh5rwYN8UQkkcR/wZPla04TY + 8l5dq/LI/3G5sZXwUHKOcuQWTj7Saq7Q6gkKoMfqt0wC5bpZ1m17GHPoMz6GtX9O + -----END RSA PRIVATE KEY----- + "#, + Some("test123")); + assert!(cred.is_ok()); + } + + #[cfg(unix)] fn chmod(path: &Path) { use std::os::unix::prelude::*; From a6dee1a291d182aec90f8243d50057f492950baf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Jul 2018 19:53:33 -0700 Subject: [PATCH 257/860] Don't assume errors are utf-8 Apparently sometimes they aren't! Closes #324 --- src/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/error.rs b/src/error.rs index b5d9943361..1e92b23a08 100644 --- a/src/error.rs +++ b/src/error.rs @@ -58,8 +58,8 @@ impl Error { unsafe fn from_raw(code: c_int, ptr: *const raw::git_error) -> Error { let msg = CStr::from_ptr((*ptr).message as *const _).to_bytes(); - let msg = str::from_utf8(msg).unwrap(); - Error { code: code, klass: (*ptr).klass, message: msg.to_string() } + let msg = String::from_utf8_lossy(msg).into_owned(); + Error { code: code, klass: (*ptr).klass, message: msg } } /// Creates a new error from the given string as the error. From 1b4c155fa840f2c853af87ca40d6929b6aa4a8dd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Jul 2018 19:56:00 -0700 Subject: [PATCH 258/860] Don't change PKG_CONFIG_PATH on MSVC This is basically hopeless. --- libgit2-sys/build.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 845a85f1cb..1e92dbcdc6 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -179,7 +179,9 @@ fn main() { fn register_dep(dep: &str) { if let Some(s) = env::var_os(&format!("DEP_{}_ROOT", dep)) { - prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig")); + if !cfg!(target_env = "msvc") { + prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig")); + } return } if let Some(s) = env::var_os(&format!("DEP_{}_INCLUDE", dep)) { @@ -187,7 +189,9 @@ fn register_dep(dep: &str) { env::set_var(&format!("DEP_{}_ROOT", dep), root); let path = root.join("lib/pkgconfig"); if path.exists() { - prepend("PKG_CONFIG_PATH", path); + if !cfg!(target_env = "msvc") { + prepend("PKG_CONFIG_PATH", path); + } return } } From 7604ead67ef7a76aa0933bf1508237c2c5685fb1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Jul 2018 19:56:25 -0700 Subject: [PATCH 259/860] Bump libgit2-sys to 0.7.4 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index a253c6ceb3..e3179f8ffe 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.3" +version = "0.7.4" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 88ea57a23c40192a3f02116378268a28dba65291 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Jul 2018 19:56:54 -0700 Subject: [PATCH 260/860] Bump to 0.7.2 --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d1a2628fde..981a997072 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.7.1" +version = "0.7.2" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -25,7 +25,7 @@ url = "1.0" bitflags = "1.0" libc = "0.2" log = "0.4" -libgit2-sys = { path = "libgit2-sys", version = "0.7.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.7.4" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 0b919117477dd1f921162cde0e706d205260451b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Jul 2018 15:15:15 -0700 Subject: [PATCH 261/860] Update deps --- git2-curl/Cargo.toml | 8 ++++---- git2-curl/src/lib.rs | 1 - git2-curl/tests/all.rs | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 85c1c77f80..14d9c18c50 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -20,10 +20,10 @@ log = "0.4" git2 = { path = "..", version = "0.7", default-features = false } [dev-dependencies] -civet = "0.8" -conduit = "0.7" -conduit-git-http-backend = "0.7" -tempdir = "0.3" +civet = "0.9" +conduit = "0.8" +conduit-git-http-backend = "0.8" +tempfile = "3.0" [[test]] name = "all" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 555c04baea..677e155667 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -22,7 +22,6 @@ extern crate curl; extern crate url; #[macro_use] extern crate log; -use std::ascii::AsciiExt; use std::error; use std::io::prelude::*; use std::io::{self, Cursor}; diff --git a/git2-curl/tests/all.rs b/git2-curl/tests/all.rs index 7dbc5a8e17..941020e185 100644 --- a/git2-curl/tests/all.rs +++ b/git2-curl/tests/all.rs @@ -4,12 +4,12 @@ extern crate civet; extern crate conduit; extern crate curl; extern crate git2; -extern crate tempdir; +extern crate tempfile; use civet::{Server, Config}; use std::fs::File; use std::path::Path; -use tempdir::TempDir; +use tempfile::TempDir; const PORT: u16 = 7848; @@ -19,7 +19,7 @@ fn main() { } // Spin up a server for git-http-backend - let td = TempDir::new("wut").unwrap(); + let td = TempDir::new().unwrap(); let mut cfg = Config::new(); cfg.port(PORT).threads(1); let _a = Server::start(cfg, git_backend::Serve(td.path().to_path_buf())); @@ -40,7 +40,7 @@ fn main() { } // Clone through the git-http-backend - let td2 = TempDir::new("wut2").unwrap(); + let td2 = TempDir::new().unwrap(); let r = git2::Repository::clone(&format!("http://localhost:{}", PORT), td2.path()).unwrap(); assert!(File::open(&td2.path().join("foo")).is_ok()); From d95fabea63e6d4074cc6556c12049a198ed57ba9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Jul 2018 15:15:53 -0700 Subject: [PATCH 262/860] Upgrade civet --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 14d9c18c50..4afee5942c 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -20,7 +20,7 @@ log = "0.4" git2 = { path = "..", version = "0.7", default-features = false } [dev-dependencies] -civet = "0.9" +civet = "0.11" conduit = "0.8" conduit-git-http-backend = "0.8" tempfile = "3.0" From e362a74a2bccf442d14f2b0b9b97ae11517025d3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 13 Jul 2018 13:38:56 -0700 Subject: [PATCH 263/860] Increase version deps of crates in libgit2-sys --- libgit2-sys/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index e3179f8ffe..26cdc383ce 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -16,10 +16,10 @@ name = "libgit2_sys" path = "lib.rs" [dependencies] -curl-sys = { version = "0.4", optional = true } +curl-sys = { version = "0.4.6", optional = true } libc = "0.2" -libssh2-sys = { version = "0.2.4", optional = true } -libz-sys = ">= 0.1.2" +libssh2-sys = { version = "0.2.8", optional = true } +libz-sys = "1.0.18" [build-dependencies] pkg-config = "0.3" From d935e40af882c4dc7c9546553344d253c7506936 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 13 Jul 2018 13:39:16 -0700 Subject: [PATCH 264/860] Bump libgit2-sys to 0.7.5 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 26cdc383ce..67e643aa62 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.4" +version = "0.7.5" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 8777d90fa6996397fc7c67bf15d09869c1a02f6a Mon Sep 17 00:00:00 2001 From: Charles Hubain Date: Thu, 19 Jul 2018 13:58:29 +0200 Subject: [PATCH 265/860] Added missing is_wt_deleted method --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index cfe443b19f..8a6c64b946 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -957,6 +957,7 @@ impl Status { is_bit_set!(is_index_typechange, Status::INDEX_TYPECHANGE); is_bit_set!(is_wt_new, Status::WT_NEW); is_bit_set!(is_wt_modified, Status::WT_MODIFIED); + is_bit_set!(is_wt_deleted, Status::WT_DELETED); is_bit_set!(is_wt_typechange, Status::WT_TYPECHANGE); is_bit_set!(is_wt_renamed, Status::WT_RENAMED); is_bit_set!(is_ignored, Status::IGNORED); From fa653bc4a06d0163eafad40a8388a6ce8e2a7982 Mon Sep 17 00:00:00 2001 From: Jacob Finkelman Date: Fri, 20 Jul 2018 22:02:15 -0400 Subject: [PATCH 266/860] work around for windows path separator for is_path_ignored (#335) * work around for windows path separator for is_path_ignored * use cfg! --- src/repo.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 4edc5f3616..43421a61da 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2044,7 +2044,13 @@ impl Repository { /// Test if the ignore rules apply to a given path. pub fn is_path_ignored>(&self, path: P) -> Result { - let path = try!(path.as_ref().into_c_string()); + let path = if cfg!(windows) { + // `git_ignore_path_is_ignored` dose not work with windows path separator + // so we convert \ to / + try!(::std::ffi::CString::new(path.as_ref().to_string_lossy().replace('\\', "/"))) + } else { + try!(path.as_ref().into_c_string()) + }; let mut ignored: c_int = 0; unsafe { try_call!(raw::git_ignore_path_is_ignored(&mut ignored, self.raw, path)); @@ -2536,8 +2542,15 @@ mod tests { let _ = repo.add_ignore_rule("/foo"); assert!(repo.is_path_ignored(Path::new("/foo")).unwrap()); + if cfg!(windows){ + assert!(repo.is_path_ignored(Path::new("\\foo\\thing")).unwrap()); + } + let _ = repo.clear_ignore_rules(); assert!(!repo.is_path_ignored(Path::new("/foo")).unwrap()); + if cfg!(windows){ + assert!(!repo.is_path_ignored(Path::new("\\foo\\thing")).unwrap()); + } } } From a3f1a4dd658cb2bd75c40e7911a16029254b3d41 Mon Sep 17 00:00:00 2001 From: Jacob Finkelman Date: Sat, 21 Jul 2018 16:27:19 -0400 Subject: [PATCH 267/860] Minimal versions (#336) * get libgit2-sys working with its minimal-versions * get git2 working with its minimal-versions --- Cargo.toml | 5 +++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 981a997072..d73f6ba1a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,8 +35,9 @@ openssl-probe = { version = "0.1", optional = true } docopt = "1.0" serde = "1.0" serde_derive = "1.0" -time = "0.1" -tempdir = "0.3" +time = "0.1.39" +tempdir = "0.3.7" +thread-id = "3.3.0" # remove when we work with minimal-versions without it [features] unstable = [] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 67e643aa62..3e3b758ec9 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -23,7 +23,7 @@ libz-sys = "1.0.18" [build-dependencies] pkg-config = "0.3" -cmake = "0.1.2" +cmake = "0.1.24" cc = "1.0" [target.'cfg(unix)'.dependencies] From b037736bd0a65cb4db5faa20375e049490c2468c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 21 Jul 2018 21:21:45 -0700 Subject: [PATCH 268/860] Bump to 0.7.3 --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d73f6ba1a7..31c8856dd6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.7.2" +version = "0.7.3" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -25,7 +25,7 @@ url = "1.0" bitflags = "1.0" libc = "0.2" log = "0.4" -libgit2-sys = { path = "libgit2-sys", version = "0.7.4" } +libgit2-sys = { path = "libgit2-sys", version = "0.7.6" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 3e3b758ec9..7e49213cdc 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.5" +version = "0.7.6" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 6259a36d6ab2335e5abdc08f45d6dbfb6f78622e Mon Sep 17 00:00:00 2001 From: Ratzzo Date: Mon, 23 Jul 2018 19:46:23 -0500 Subject: [PATCH 269/860] Force the bundled http-parser if cross compiling (#337) (#338) --- libgit2-sys/build.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 1e92dbcdc6..b06ecfd894 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -120,6 +120,11 @@ fn main() { cfg.define("CURL", "OFF"); } + //Use bundled http-parser if cross compiling + if host != target { + cfg.define("USE_EXT_HTTP_PARSER", "OFF"); + } + let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap()); t!(fs::create_dir_all(env::var("OUT_DIR").unwrap())); From 8ca0e92ed64c2f5f5bed37ed911c1b780df0e20f Mon Sep 17 00:00:00 2001 From: Jean-Marc Le Roux Date: Thu, 26 Jul 2018 22:27:19 +0200 Subject: [PATCH 270/860] Add the ssh_key_from_memory optional feature. (#331) * Add the ssh_key_from_memory optional feature. * Enable the ssh_key_from_memory feature by default. Users with older versions of libssh can still disable it if needed. --- Cargo.toml | 3 ++- libgit2-sys/Cargo.toml | 1 + libgit2-sys/build.rs | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 31c8856dd6..dc6e583175 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,10 +41,11 @@ thread-id = "3.3.0" # remove when we work with minimal-versions without it [features] unstable = [] -default = ["ssh", "https", "curl"] +default = ["ssh", "https", "curl", "ssh_key_from_memory"] ssh = ["libgit2-sys/ssh"] https = ["libgit2-sys/https", "openssl-sys", "openssl-probe"] curl = ["libgit2-sys/curl"] +ssh_key_from_memory = ["libgit2-sys/ssh_key_from_memory"] [workspace] members = ["systest", "git2-curl"] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 7e49213cdc..4eeedfe9e7 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -33,3 +33,4 @@ openssl-sys = { version = "0.9", optional = true } ssh = ["libssh2-sys"] https = ["openssl-sys"] curl = ["curl-sys"] +ssh_key_from_memory = [] diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index b06ecfd894..1141c8aca6 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -48,6 +48,9 @@ fn main() { let msvc = target.contains("msvc"); let mut cfg = cmake::Config::new("libgit2"); + #[cfg(feature = "ssh_key_from_memory")] + cfg.define("GIT_SSH_MEMORY_CREDENTIALS", "1"); + if msvc { // libgit2 passes the /GL flag to enable whole program optimization, but // this requires that the /LTCG flag is passed to the linker later on, From d50bdabd019d15911ceedc83613030292ff9ba6e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 30 Jul 2018 07:31:23 -0700 Subject: [PATCH 271/860] Bump to 0.7.4 and libgit2-sys to 0.7.7 --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dc6e583175..44bef295a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.7.3" +version = "0.7.4" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -25,7 +25,7 @@ url = "1.0" bitflags = "1.0" libc = "0.2" log = "0.4" -libgit2-sys = { path = "libgit2-sys", version = "0.7.6" } +libgit2-sys = { path = "libgit2-sys", version = "0.7.7" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 4eeedfe9e7..60fc27650c 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.6" +version = "0.7.7" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From abe3eafb00b5c58c9890f9b4f9112223de2d8ddb Mon Sep 17 00:00:00 2001 From: Brendan Molloy Date: Tue, 31 Jul 2018 16:33:03 +0200 Subject: [PATCH 272/860] Make some patch functions only require &self (#339) --- src/patch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patch.rs b/src/patch.rs index dbd4655d3e..af7e74ac18 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -139,7 +139,7 @@ impl Patch { } /// Get a DiffHunk and its total line count from the Patch. - pub fn hunk(&mut self, hunk_idx: usize) -> Result<(DiffHunk, usize), Error> { + pub fn hunk(&self, hunk_idx: usize) -> Result<(DiffHunk, usize), Error> { let mut ret = ptr::null(); let mut lines = 0; unsafe { @@ -156,7 +156,7 @@ impl Patch { } /// Get a DiffLine from a hunk of the Patch. - pub fn line_in_hunk(&mut self, + pub fn line_in_hunk(&self, hunk_idx: usize, line_of_hunk: usize) -> Result { let mut ret = ptr::null(); From 30a7076780ad24a77c3e48aa3ed408654f2660f4 Mon Sep 17 00:00:00 2001 From: Jacob Finkelman Date: Thu, 2 Aug 2018 16:08:59 -0400 Subject: [PATCH 273/860] work around for windows path separator for status_file (#341) --- src/repo.rs | 8 +++++++- src/status.rs | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 43421a61da..8b8edf48aa 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -804,7 +804,13 @@ impl Repository { /// through looking for the path that you are interested in. pub fn status_file(&self, path: &Path) -> Result { let mut ret = 0 as c_uint; - let path = try!(path.into_c_string()); + let path = if cfg!(windows) { + // `git_status_file` dose not work with windows path separator + // so we convert \ to / + try!(::std::ffi::CString::new(path.to_string_lossy().replace('\\', "/"))) + } else { + try!(path.into_c_string()) + }; unsafe { try_call!(raw::git_status_file(&mut ret, self.raw, path)); diff --git a/src/status.rs b/src/status.rs index dc1dbd76dd..cb67305e47 100644 --- a/src/status.rs +++ b/src/status.rs @@ -400,8 +400,19 @@ mod tests { fn status_file() { let (td, repo) = ::test::repo_init(); assert!(repo.status_file(Path::new("foo")).is_err()); + if cfg!(windows) { + assert!(repo.status_file(Path::new("bar\\foo.txt")).is_err()); + } t!(File::create(td.path().join("foo"))); + if cfg!(windows) { + t!(::std::fs::create_dir_all(td.path().join("bar"))); + t!(File::create(td.path().join("bar").join("foo.txt"))); + } let status = t!(repo.status_file(Path::new("foo"))); assert!(status.contains(::Status::WT_NEW)); + if cfg!(windows) { + let status = t!(repo.status_file(Path::new("bar\\foo.txt"))); + assert!(status.contains(::Status::WT_NEW)); + } } } From d9a162a965cb75c472e7ae59602d3cad7a43f008 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 2 Aug 2018 13:09:16 -0700 Subject: [PATCH 274/860] Bump to 0.7.5 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 44bef295a3..4cccdb2ad0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.7.4" +version = "0.7.5" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 9e54c373e170481add31579b05886fb0e9ead84a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 13 Aug 2018 17:05:03 -0700 Subject: [PATCH 275/860] Update ctest to 0.2 --- systest/Cargo.toml | 2 +- systest/build.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/systest/Cargo.toml b/systest/Cargo.toml index f43b0cf635..7ed93c9f8c 100644 --- a/systest/Cargo.toml +++ b/systest/Cargo.toml @@ -9,4 +9,4 @@ libgit2-sys = { path = "../libgit2-sys" } libc = "0.2" [build-dependencies] -ctest = "0.1" +ctest = "0.2" diff --git a/systest/build.rs b/systest/build.rs index 5ee841d468..67faeb5637 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -16,7 +16,7 @@ fn main() { .header("git2/sys/repository.h") .header("git2/cred_helpers.h") .include(root.join("include")) - .type_name(|s, _| s.to_string()); + .type_name(|s, _, _| s.to_string()); cfg.field_name(|_, f| { match f { "kind" => "type".to_string(), From ef9c8ed3db8dde5b30da87c807c96375e16b31b1 Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 14 Aug 2018 01:11:40 +0100 Subject: [PATCH 276/860] Don't panic in shallow clones (#346) --- src/commit.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/commit.rs b/src/commit.rs index f6086309c8..1e6de6f480 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -17,12 +17,16 @@ pub struct Commit<'repo> { } /// An iterator over the parent commits of a commit. +/// +/// Aborts iteration when a commit cannot be found pub struct Parents<'commit, 'repo: 'commit> { range: Range, commit: &'commit Commit<'repo>, } /// An iterator over the parent commits' ids of a commit. +/// +/// Aborts iteration when a commit cannot be found pub struct ParentIds<'commit> { range: Range, commit: &'commit Commit<'commit>, @@ -81,7 +85,7 @@ impl<'repo> Commit<'repo> { let bytes = unsafe { ::opt_bytes(self, raw::git_commit_message(&*self.raw)) }; - bytes.map(|b| str::from_utf8(b).unwrap()) + bytes.and_then(|b| str::from_utf8(b).ok()) } /// Get the full raw message of a commit. @@ -273,33 +277,37 @@ impl<'repo> ::std::fmt::Debug for Commit<'repo> { } } +/// Aborts iteration when a commit cannot be found impl<'repo, 'commit> Iterator for Parents<'commit, 'repo> { type Item = Commit<'repo>; fn next(&mut self) -> Option> { - self.range.next().map(|i| self.commit.parent(i).unwrap()) + self.range.next().and_then(|i| self.commit.parent(i).ok()) } fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } } +/// Aborts iteration when a commit cannot be found impl<'repo, 'commit> DoubleEndedIterator for Parents<'commit, 'repo> { fn next_back(&mut self) -> Option> { - self.range.next_back().map(|i| self.commit.parent(i).unwrap()) + self.range.next_back().and_then(|i| self.commit.parent(i).ok()) } } impl<'repo, 'commit> ExactSizeIterator for Parents<'commit, 'repo> {} +/// Aborts iteration when a commit cannot be found impl<'commit> Iterator for ParentIds<'commit> { type Item = Oid; fn next(&mut self) -> Option { - self.range.next().map(|i| self.commit.parent_id(i).unwrap()) + self.range.next().and_then(|i| self.commit.parent_id(i).ok()) } fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } } +/// Aborts iteration when a commit cannot be found impl<'commit> DoubleEndedIterator for ParentIds<'commit> { fn next_back(&mut self) -> Option { - self.range.next_back().map(|i| self.commit.parent_id(i).unwrap()) + self.range.next_back().and_then(|i| self.commit.parent_id(i).ok()) } } From d8d3825f357e781157894377adca9fd20c14f1b6 Mon Sep 17 00:00:00 2001 From: knewt Date: Tue, 14 Aug 2018 01:17:37 +0100 Subject: [PATCH 277/860] Add binding for index_add_frombuffer (already existed in libgit2-sys) (#344) --- src/index.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/src/index.rs b/src/index.rs index 0f603a5b07..6867a3d68d 100644 --- a/src/index.rs +++ b/src/index.rs @@ -127,6 +127,66 @@ impl Index { } } + /// Add or update an index entry from a buffer in memory + /// + /// This method will create a blob in the repository that owns the index and + /// then add the index entry to the index. The path of the entry represents + /// the position of the blob relative to the repository's root folder. + /// + /// If a previous index entry exists that has the same path as the given + /// 'entry', it will be replaced. Otherwise, the 'entry' will be added. + /// The id and the file_size of the 'entry' are updated with the real value + /// of the blob. + /// + /// This forces the file to be added to the index, not looking at gitignore + /// rules. + /// + /// If this file currently is the result of a merge conflict, this file will + /// no longer be marked as conflicting. The data about the conflict will be + /// moved to the "resolve undo" (REUC) section. + pub fn add_frombuffer(&mut self, entry: &IndexEntry, data: &[u8]) -> Result<(), Error> { + let path = try!(CString::new(&entry.path[..])); + + // libgit2 encodes the length of the path in the lower bits of the + // `flags` entry, so mask those out and recalculate here to ensure we + // don't corrupt anything. + let mut flags = entry.flags & !raw::GIT_IDXENTRY_NAMEMASK; + + if entry.path.len() < raw::GIT_IDXENTRY_NAMEMASK as usize { + flags |= entry.path.len() as u16; + } else { + flags |= raw::GIT_IDXENTRY_NAMEMASK; + } + + unsafe { + let raw = raw::git_index_entry { + dev: entry.dev, + ino: entry.ino, + mode: entry.mode, + uid: entry.uid, + gid: entry.gid, + file_size: entry.file_size, + id: *entry.id.raw(), + flags: flags, + flags_extended: entry.flags_extended, + path: path.as_ptr(), + mtime: raw::git_index_time { + seconds: entry.mtime.seconds(), + nanoseconds: entry.mtime.nanoseconds(), + }, + ctime: raw::git_index_time { + seconds: entry.ctime.seconds(), + nanoseconds: entry.ctime.nanoseconds(), + }, + }; + + let ptr = data.as_ptr() as *const c_void; + let len = data.len() as size_t; + try_call!(raw::git_index_add_frombuffer(self.raw, &raw, ptr, len)); + Ok(()) + } + } + /// Add or update an index entry from a file on disk /// /// The file path must be relative to the repository's working folder and @@ -615,6 +675,22 @@ mod tests { assert_eq!(e.path.len(), 6); } + #[test] + fn add_frombuffer_then_read() { + let (_td, repo) = ::test::repo_init(); + let mut index = repo.index().unwrap(); + + let mut e = entry(); + e.path = b"foobar".to_vec(); + let content = b"the contents"; + index.add_frombuffer(&e, content).unwrap(); + let e = index.get(0).unwrap(); + assert_eq!(e.path.len(), 6); + + let b = repo.find_blob(e.id).unwrap(); + assert_eq!(b.content(), content); + } + fn entry() -> IndexEntry { IndexEntry { ctime: IndexTime::new(0, 0), From 27deee915b7b70698e6d359a681700a896186df1 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 21 Aug 2018 11:53:58 -0500 Subject: [PATCH 278/860] Adding tree walk (#343) * Added treewalk function, no tests yet. * hopefully this satisfies msvc * add test for tree_walk * sample implementation using TreeWalkResult enum * documentation * remove unnecessary panic check --- src/lib.rs | 2 +- src/tree.rs | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 130 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8a6c64b946..1c49ba6df9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,7 +118,7 @@ pub use stash::{StashApplyOptions, StashCb, StashApplyProgressCb}; pub use submodule::{Submodule, SubmoduleUpdateOptions}; pub use tag::Tag; pub use time::{Time, IndexTime}; -pub use tree::{Tree, TreeEntry, TreeIter}; +pub use tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult}; pub use treebuilder::TreeBuilder; pub use odb::{Odb, OdbObject, OdbReader, OdbWriter}; pub use util::IntoCString; diff --git a/src/tree.rs b/src/tree.rs index a2006f3c5e..705f181633 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,14 +1,14 @@ use std::mem; use std::cmp::Ordering; -use std::ffi::CString; +use std::ffi::{CStr, CString}; use std::ops::Range; use std::marker; use std::path::Path; use std::ptr; use std::str; -use libc; +use libc::{self, c_int, c_char, c_void}; -use {raw, Oid, Repository, Error, Object, ObjectType}; +use {panic, raw, Oid, Repository, Error, Object, ObjectType}; use util::{Binding, IntoCString}; /// A structure to represent a git [tree][1] @@ -33,6 +33,43 @@ pub struct TreeIter<'tree> { tree: &'tree Tree<'tree>, } +/// A binary indicator of whether a tree walk should be performed in pre-order +/// or post-order. +pub enum TreeWalkMode { + /// Runs the traversal in pre order. + PreOrder = 0, + /// Runs the traversal in post order. + PostOrder = 1, +} + +/// Possible return codes for tree walking callback functions. +#[allow(dead_code)] +pub enum TreeWalkResult { + /// Continue with the traversal as normal. + Ok = 0, + /// Skip the current node (in pre-order mode). + Skip = 1, + /// Completely stop the traversal. + Abort = -1, +} + +impl Into for TreeWalkResult { + fn into(self) -> i32 { + self as i32 + } +} + +impl Into for TreeWalkMode { + #[cfg(target_env = "msvc")] + fn into(self) -> raw::git_treewalk_mode { + self as i32 + } + #[cfg(not(target_env = "msvc"))] + fn into(self) -> raw::git_treewalk_mode { + self as u32 + } +} + impl<'repo> Tree<'repo> { /// Get the id (SHA1) of a repository object pub fn id(&self) -> Oid { @@ -54,6 +91,49 @@ impl<'repo> Tree<'repo> { TreeIter { range: 0..self.len(), tree: self } } + /// Traverse the entries in a tree and its subtrees in post or pre order. + /// The callback function will be run on each node of the tree that's + /// walked. The return code of this function will determine how the walk + /// continues. + /// + /// libgit requires that the callback be an integer, where 0 indicates a + /// successful visit, 1 skips the node, and -1 aborts the traversal completely. + /// You may opt to use the enum [`TreeWalkResult`](TreeWalkResult) instead. + /// + /// ```ignore + /// let mut ct = 0; + /// tree.walk(TreeWalkMode::PreOrder, |_, entry| { + /// assert_eq!(entry.name(), Some("foo")); + /// ct += 1; + /// TreeWalkResult::Ok + /// }).unwrap(); + /// assert_eq!(ct, 1); + /// ``` + /// + /// See [libgit documentation][1] for more information. + /// + /// [1]: https://libgit2.org/libgit2/#HEAD/group/tree/git_tree_walk + pub fn walk(&self, mode: TreeWalkMode, mut callback: C) -> Result<(), Error> + where + C: FnMut(&str, &TreeEntry) -> T, + T: Into, + { + #[allow(unused)] + struct TreeWalkCbData<'a, T: 'a> { + pub callback: &'a mut TreeWalkCb<'a, T> + } + unsafe { + let mut data = TreeWalkCbData { callback: &mut callback }; + raw::git_tree_walk( + self.raw(), + mode.into(), + treewalk_cb, + &mut data as *mut _ as *mut c_void, + ); + Ok(()) + } + } + /// Lookup a tree entry by SHA value. pub fn get_id(&self, id: Oid) -> Option { unsafe { @@ -119,6 +199,23 @@ impl<'repo> Tree<'repo> { } } +type TreeWalkCb<'a, T> = FnMut(&str, &TreeEntry) -> T + 'a; + +extern fn treewalk_cb(root: *const c_char, entry: *const raw::git_tree_entry, payload: *mut c_void) -> c_int { + match panic::wrap(|| unsafe { + let root = match CStr::from_ptr(root).to_str() { + Ok(value) => value, + _ => return -1, + }; + let entry = entry_from_raw_const(entry); + let payload = payload as *mut &mut TreeWalkCb<_>; + (*payload)(root, &entry) + }) { + Some(value) => value, + None => -1, + } +} + impl<'repo> Binding for Tree<'repo> { type Raw = *mut raw::git_tree; @@ -294,6 +391,7 @@ impl<'tree> ExactSizeIterator for TreeIter<'tree> {} #[cfg(test)] mod tests { use {Repository,Tree,TreeEntry,ObjectType,Object}; + use super::{TreeWalkMode, TreeWalkResult}; use tempdir::TempDir; use std::fs::File; use std::io::prelude::*; @@ -403,4 +501,32 @@ mod tests { repo.find_object(commit.tree_id(), None).unwrap().as_tree().unwrap(); repo.find_object(commit.tree_id(), None).unwrap().into_tree().ok().unwrap(); } + + #[test] + fn tree_walk() { + let (td, repo) = ::test::repo_init(); + + setup_repo(&td, &repo); + + let head = repo.head().unwrap(); + let target = head.target().unwrap(); + let commit = repo.find_commit(target).unwrap(); + let tree = repo.find_tree(commit.tree_id()).unwrap(); + + let mut ct = 0; + tree.walk(TreeWalkMode::PreOrder, |_, entry| { + assert_eq!(entry.name(), Some("foo")); + ct += 1; + 0 + }).unwrap(); + assert_eq!(ct, 1); + + let mut ct = 0; + tree.walk(TreeWalkMode::PreOrder, |_, entry| { + assert_eq!(entry.name(), Some("foo")); + ct += 1; + TreeWalkResult::Ok + }).unwrap(); + assert_eq!(ct, 1); + } } From 350da2009cf3f2a1b0ae78875cfe1f2e0ce403e1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 28 Aug 2018 10:36:34 -0700 Subject: [PATCH 279/860] "Fix" the `Submodule::url_bytes` signature Apparently this can legitimately return a null pointer! We'll actually fix the signature on the next major version bump Closes #348 --- src/submodule.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/submodule.rs b/src/submodule.rs index 9cdb3566f9..64c7ec87e7 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -37,13 +37,26 @@ impl<'repo> Submodule<'repo> { /// Get the submodule's url. /// - /// Returns `None` if the url is not valid utf-8 - pub fn url(https://github.com/&self) -> Option<&str> { str::from_utf8(self.url_bytes()).ok() } + /// Returns `None` if the url is not valid utf-8 or if the URL isn't present + pub fn url(https://github.com/&self) -> Option<&str> { + self.opt_url_bytes().and_then(|b| str::from_utf8(b).ok()) + } /// Get the url for the submodule. + #[doc(hidden)] + #[deprecated(note = "renamed to `opt_url_bytes`")] pub fn url_bytes(&self) -> &[u8] { + self.opt_url_bytes().unwrap() + } + + /// Get the url for the submodule. + /// + /// Returns `None` if the URL isn't present + // TODO: delete this method and fix the signature of `url_bytes` on next + // major version bump + pub fn opt_url_bytes(&self) -> Option<&[u8]> { unsafe { - ::opt_bytes(self, raw::git_submodule_url(https://github.com/self.raw)).unwrap() + ::opt_bytes(self, raw::git_submodule_url(https://github.com/self.raw)) } } From 7e180240c991ef0039f4307500c448f789795106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Wed, 5 Sep 2018 23:03:17 +0200 Subject: [PATCH 280/860] Fix typo in documentation --- src/remote_callbacks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index fdeaa83f63..562d3a2d6c 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -115,7 +115,7 @@ impl<'a> RemoteCallbacks<'a> { /// Textual progress from the remote. /// /// Text sent over the progress side-band will be passed to this function - /// (this is the 'counting objects' output. + /// (this is the 'counting objects' output). pub fn sideband_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> where F: FnMut(&[u8]) -> bool + 'a { self.sideband_progress = Some(Box::new(cb) as Box>); From 701e293720c745f2f368a2b0471c20fff11cf5f0 Mon Sep 17 00:00:00 2001 From: Alex Sayers Date: Thu, 13 Sep 2018 00:45:42 +0900 Subject: [PATCH 281/860] tree_walk: Convert callback return value to i32 Currently if T is not 4 bytes long we get undefined behaviour. --- src/tree.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index 705f181633..0e83ade922 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -127,7 +127,7 @@ impl<'repo> Tree<'repo> { raw::git_tree_walk( self.raw(), mode.into(), - treewalk_cb, + treewalk_cb::, &mut data as *mut _ as *mut c_void, ); Ok(()) @@ -201,15 +201,15 @@ impl<'repo> Tree<'repo> { type TreeWalkCb<'a, T> = FnMut(&str, &TreeEntry) -> T + 'a; -extern fn treewalk_cb(root: *const c_char, entry: *const raw::git_tree_entry, payload: *mut c_void) -> c_int { +extern fn treewalk_cb>(root: *const c_char, entry: *const raw::git_tree_entry, payload: *mut c_void) -> c_int { match panic::wrap(|| unsafe { let root = match CStr::from_ptr(root).to_str() { Ok(value) => value, _ => return -1, }; let entry = entry_from_raw_const(entry); - let payload = payload as *mut &mut TreeWalkCb<_>; - (*payload)(root, &entry) + let payload = payload as *mut &mut TreeWalkCb; + (*payload)(root, &entry).into() }) { Some(value) => value, None => -1, From b92038b10dd49fb68ed38bcecba935dc49d71c81 Mon Sep 17 00:00:00 2001 From: Alex Sayers Date: Thu, 13 Sep 2018 00:50:39 +0900 Subject: [PATCH 282/860] tree_walk: Use GIT_EUSER to abort a traversal As per the discussion in https://github.com/libgit2/libgit2/pull/4703. This requires making TreeWalkResult #[repr(i32)], which is fine. Also, remove an unnecessary pragma. --- src/tree.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index 0e83ade922..6a0f4975e4 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -43,14 +43,14 @@ pub enum TreeWalkMode { } /// Possible return codes for tree walking callback functions. -#[allow(dead_code)] +#[repr(i32)] pub enum TreeWalkResult { /// Continue with the traversal as normal. Ok = 0, /// Skip the current node (in pre-order mode). Skip = 1, /// Completely stop the traversal. - Abort = -1, + Abort = raw::GIT_EUSER, } impl Into for TreeWalkResult { @@ -520,7 +520,7 @@ mod tests { 0 }).unwrap(); assert_eq!(ct, 1); - + let mut ct = 0; tree.walk(TreeWalkMode::PreOrder, |_, entry| { assert_eq!(entry.name(), Some("foo")); From 76f4b74aef2bc2a54906ddcbf7fbe0018936a69d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 13 Sep 2018 09:36:03 -0700 Subject: [PATCH 283/860] Remove dependency on `cmake` I've spent too many hours of my life bending over backwards trying to satisfy native libraryies' build systems. The most recent pain is that informing a native build system of its dependencies (such as telling libgit2 where libssh2 is installed) is an absolute never-ending nightmare. The towel is now thrown in as `cmake` is jettisoned and this is now just using the `cc` crate to directly compile all the various C code. For some more info see alexcrichton/curl-rust#225 --- .travis.yml | 12 +- README.md | 13 +- libgit2-sys/Cargo.toml | 1 - libgit2-sys/build.rs | 280 +++++++++++++++++------------------------ systest/Cargo.toml | 2 +- 5 files changed, 120 insertions(+), 188 deletions(-) diff --git a/.travis.yml b/.travis.yml index 10e97eafb0..2855475e48 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ git: matrix: include: - - rust: 1.21.0 + - rust: 1.26.0 - rust: stable - os: osx rust: stable @@ -42,13 +42,3 @@ env: notifications: email: on_success: never - -addons: - apt: - sources: - - kalakris-cmake - packages: - - cmake - - libcurl4-openssl-dev - - libelf-dev - - libdw-dev diff --git a/README.md b/README.md index b060602d36..83c158607f 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,6 @@ library, the libgit2-sys crate will figure that and/or build that for you. ## Building git2-rs -First, you'll need to install _CMake_. Afterwards, just run: - ```sh $ git clone https://github.com/alexcrichton/git2-rs $ cd git2-rs @@ -42,14 +40,9 @@ To skip tests on a simple commit or doc-fixes, use `git commit --no-verify`. ## Building on OSX 10.10+ -Currently libssh2 requires linking against OpenSSL, and to compile libssh2 it -also needs to find the OpenSSL headers. On OSX 10.10+ the OpenSSL headers have -been removed, but if you're using Homebrew you can install them via: - -```sh -brew install openssl -``` - +If the `ssh` feature is enabled (and it is by default) then this library depends +on libssh2 which depends on OpenSSL. To get OpenSSL working follow the +[`openssl` crate's instructions](https://github.com/sfackler/rust-openssl#macos). # License diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 60fc27650c..c1fb68e589 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -23,7 +23,6 @@ libz-sys = "1.0.18" [build-dependencies] pkg-config = "0.3" -cmake = "0.1.24" cc = "1.0" [target.'cfg(unix)'.dependencies] diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 1141c8aca6..619472db28 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -1,35 +1,15 @@ -extern crate cmake; extern crate cc; extern crate pkg_config; use std::env; -use std::ffi::OsString; -use std::fs::{self, File}; -use std::io::prelude::*; +use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; -macro_rules! t { - ($e:expr) => (match $e{ - Ok(e) => e, - Err(e) => panic!("{} failed with {}", stringify!($e), e), - }) -} - fn main() { let https = env::var("CARGO_FEATURE_HTTPS").is_ok(); let ssh = env::var("CARGO_FEATURE_SSH").is_ok(); let curl = env::var("CARGO_FEATURE_CURL").is_ok(); - if ssh { - register_dep("SSH2"); - } - if https { - register_dep("OPENSSL"); - } - if curl { - register_dep("CURL"); - } - let has_pkgconfig = Command::new("pkg-config").output().is_ok(); if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() { if pkg_config::find_library("libgit2").is_ok() { @@ -43,141 +23,128 @@ fn main() { } let target = env::var("TARGET").unwrap(); - let host = env::var("HOST").unwrap(); let windows = target.contains("windows"); - let msvc = target.contains("msvc"); - let mut cfg = cmake::Config::new("libgit2"); - - #[cfg(feature = "ssh_key_from_memory")] - cfg.define("GIT_SSH_MEMORY_CREDENTIALS", "1"); - - if msvc { - // libgit2 passes the /GL flag to enable whole program optimization, but - // this requires that the /LTCG flag is passed to the linker later on, - // and currently the compiler does not do that, so we disable whole - // program optimization entirely. - cfg.cflag("/GL-"); - - // Currently liblibc links to msvcrt which apparently is a dynamic CRT, - // so we need to turn this off to get it to link right. - let features = env::var("CARGO_CFG_TARGET_FEATURE") - .unwrap_or(String::new()); - if features.contains("crt-static") { - cfg.define("STATIC_CRT", "ON"); - } else { - cfg.define("STATIC_CRT", "OFF"); - } + let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let include = dst.join("include"); + let mut cfg = cc::Build::new(); + fs::create_dir_all(&include).unwrap(); + + // Copy over all header files + cp_r("libgit2/include".as_ref(), &include); + + cfg.include(&include) + .include("libgit2/src") + .out_dir(dst.join("build")) + .warnings(false); + + // Include all cross-platform C files + add_c_files(&mut cfg, "libgit2/src".as_ref()); + add_c_files(&mut cfg, "libgit2/src/xdiff".as_ref()); + + // These are activated by feautres, but they're all unconditionally always + // compiled apparently and have internal #define's to make sure they're + // compiled correctly. + add_c_files(&mut cfg, "libgit2/src/transports".as_ref()); + add_c_files(&mut cfg, "libgit2/src/streams".as_ref()); + + // Always use bundled http-parser for now + cfg.include("libgit2/deps/http-parser") + .file("libgit2/deps/http-parser/http_parser.c"); + + // Always use bundled regex for now + cfg.include("libgit2/deps/regex") + .file("libgit2/deps/regex/regex.c"); + + if windows { + add_c_files(&mut cfg, "libgit2/src/win32".as_ref()); + cfg.define("STRSAFE_NO_DEPRECATE", None); + } else { + add_c_files(&mut cfg, "libgit2/src/unix".as_ref()); + cfg.flag("-fvisibility=hidden"); } - // libgit2 uses pkg-config to discover libssh2, but this doesn't work on - // windows as libssh2 doesn't come with a libssh2.pc file in that install - // (or when pkg-config isn't found). As a result we just manually turn on - // SSH support in libgit2 (a little jankily) here... - let mut ssh_forced = false; - if ssh && (windows || !has_pkgconfig) { - if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") { - ssh_forced = true; - if msvc { - cfg.cflag(format!("/I{}", libssh2_include)) - .cflag("/DGIT_SSH"); - } else { - cfg.cflag(format!("-I{}", sanitize_sh(libssh2_include.as_ref()))) - .cflag("-DGIT_SSH"); - } - } + let mut features = String::new(); + + features.push_str("#ifndef INCLUDE_features_h\n"); + features.push_str("#define INCLUDE_features_h\n"); + features.push_str("#define GIT_THREADS 1\n"); + features.push_str("#define GIT_USE_NSEC 1\n"); + + if target.contains("apple") { + features.push_str("#define GIT_USE_STAT_MTIMESPEC 1\n"); + } else { + features.push_str("#define GIT_USE_STAT_MTIM 1\n"); } - // When cross-compiling, we're pretty unlikely to find a `dlltool` binary - // lying around, so try to find another if it exists - if windows && !host.contains("windows") { - let c_compiler = cc::Build::new().cargo_metadata(false) - .get_compiler(); - let exe = c_compiler.path(); - let path = env::var_os("PATH").unwrap_or(OsString::new()); - let exe = env::split_paths(&path) - .map(|p| p.join(&exe)) - .find(|p| p.exists()); - if let Some(exe) = exe { - if let Some(name) = exe.file_name().and_then(|e| e.to_str()) { - let name = name.replace("gcc", "dlltool"); - let dlltool = exe.with_file_name(name); - cfg.define("DLLTOOL", &dlltool); - } - } + if env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap() == "32" { + features.push_str("#define GIT_ARCH_32 1\n"); + } else { + features.push_str("#define GIT_ARCH_64 1\n"); } if ssh { - cfg.register_dep("SSH2"); - } else { - cfg.define("USE_SSH", "OFF"); + if let Some(path) = env::var_os("DEP_SSH2_INCLUDE") { + cfg.include(path); + } + features.push_str("#define GIT_SSH 1\n"); + features.push_str("#define GIT_SSH_MEMORY_CREDENTIALS 1\n"); } if https { - cfg.register_dep("OPENSSL"); + features.push_str("#define GIT_HTTPS 1\n"); + + if windows { + features.push_str("#define GIT_WINHTTP 1\n"); + features.push_str("#define GIT_SHA1_WIN32 1\n"); + cfg.file("libgit2/src/hash/hash_win32.c"); + } else if target.contains("apple") { + features.push_str("#define GIT_SECURE_TRANSPORT 1\n"); + features.push_str("#define GIT_SHA1_COMMON_CRYPTO 1\n"); + } else { + features.push_str("#define GIT_OPENSSL 1\n"); + features.push_str("#define GIT_SHA1_OPENSSL 1\n"); + if let Some(path) = env::var_os("DEP_OPENSSL_INCLUDE") { + cfg.include(path); + } + } } else { - cfg.define("USE_OPENSSL", "OFF"); - cfg.define("USE_HTTPS", "OFF"); + cfg.file("libgit2/src/hash/hash_generic.c"); } + if curl { - cfg.register_dep("CURL"); - } else { - cfg.define("CURL", "OFF"); + features.push_str("#define GIT_CURL 1\n"); + if let Some(path) = env::var_os("DEP_CURL_INCLUDE") { + cfg.include(path); + } + // Handle dllimport/dllexport on windows by making sure that if we built + // curl statically (as told to us by the `curl-sys` crate) we define the + // correct values for curl's header files. + if env::var_os("DEP_CURL_STATIC").is_some() { + cfg.define("CURL_STATICLIB", None); + } } - - //Use bundled http-parser if cross compiling - if host != target { - cfg.define("USE_EXT_HTTP_PARSER", "OFF"); + if let Some(path) = env::var_os("DEP_Z_INCLUDE") { + cfg.include(path); } - let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap()); - t!(fs::create_dir_all(env::var("OUT_DIR").unwrap())); - - // Unset DESTDIR or libgit2.a ends up in it and cargo can't find it - env::remove_var("DESTDIR"); - let dst = cfg.define("BUILD_SHARED_LIBS", "OFF") - .define("BUILD_CLAR", "OFF") - .register_dep("Z") - .build(); - - // Make sure libssh2 was detected on unix systems, because it definitely - // should have been! - if ssh && !ssh_forced { - let flags = dst.join("build/src/git2/sys/features.h"); - let mut contents = String::new(); - t!(t!(File::open(flags)).read_to_string(&mut contents)); - if !contents.contains("#define GIT_SSH 1") { - panic!("libgit2 failed to find libssh2, and SSH support is required"); - } + if target.contains("apple") { + features.push_str("#define GIT_USE_ICONV 1\n"); } - // libgit2 requires the http_parser library for the HTTP transport to be - // implemented, and it will attempt to use the system http_parser if it's - // available. Detect this situation and report using the system http parser - // the same way in this situation. - // - // Note that other dependencies of libgit2 like openssl, libz, and libssh2 - // are tracked via crates instead of this. Ideally this should be a crate as - // well. - let pkgconfig_file = dst.join("lib/pkgconfig/libgit2.pc"); - if let Ok(mut f) = File::open(&pkgconfig_file) { - let mut contents = String::new(); - t!(f.read_to_string(&mut contents)); - if contents.contains("-lhttp_parser") { - println!("cargo:rustc-link-lib=http_parser"); - } - } + features.push_str("#endif\n"); + fs::write(include.join("git2/sys/features.h"), features).unwrap(); + + cfg.compile("git2"); + + println!("cargo:root={}", dst.display()); if target.contains("windows") { println!("cargo:rustc-link-lib=winhttp"); println!("cargo:rustc-link-lib=rpcrt4"); println!("cargo:rustc-link-lib=ole32"); println!("cargo:rustc-link-lib=crypt32"); - println!("cargo:rustc-link-lib=static=git2"); - println!("cargo:rustc-link-search=native={}/lib", dst.display()); return } - println!("cargo:rustc-link-lib=static=git2"); - println!("cargo:rustc-link-search=native={}", dst.join("lib").display()); if target.contains("apple") { println!("cargo:rustc-link-lib=iconv"); println!("cargo:rustc-link-lib=framework=Security"); @@ -185,46 +152,29 @@ fn main() { } } -fn register_dep(dep: &str) { - if let Some(s) = env::var_os(&format!("DEP_{}_ROOT", dep)) { - if !cfg!(target_env = "msvc") { - prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig")); - } - return - } - if let Some(s) = env::var_os(&format!("DEP_{}_INCLUDE", dep)) { - let root = Path::new(&s).parent().unwrap(); - env::set_var(&format!("DEP_{}_ROOT", dep), root); - let path = root.join("lib/pkgconfig"); - if path.exists() { - if !cfg!(target_env = "msvc") { - prepend("PKG_CONFIG_PATH", path); - } - return +fn cp_r(from: &Path, to: &Path) { + for e in from.read_dir().unwrap() { + let e = e.unwrap(); + let from = e.path(); + let to = to.join(e.file_name()); + if e.file_type().unwrap().is_dir() { + fs::create_dir_all(&to).unwrap(); + cp_r(&from, &to); + } else { + println!("{} => {}", from.display(), to.display()); + fs::copy(&from, &to).unwrap(); } } } -fn prepend(var: &str, val: PathBuf) { - let prefix = env::var(var).unwrap_or(String::new()); - let mut v = vec![val]; - v.extend(env::split_paths(&prefix)); - env::set_var(var, &env::join_paths(v).unwrap()); -} - -fn sanitize_sh(path: &Path) -> String { - let path = path.to_str().unwrap().replace("\\", "/"); - return change_drive(&path).unwrap_or(path); - - fn change_drive(s: &str) -> Option { - let mut ch = s.chars(); - let drive = ch.next().unwrap_or('C'); - if ch.next() != Some(':') { - return None - } - if ch.next() != Some('/') { - return None +fn add_c_files(build: &mut cc::Build, path: &Path) { + for e in path.read_dir().unwrap() { + let e = e.unwrap(); + let path = e.path(); + if e.file_type().unwrap().is_dir() { + // skip dirs for now + } else if path.extension().and_then(|s| s.to_str()) == Some("c") { + build.file(&path); } - Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..])) } } diff --git a/systest/Cargo.toml b/systest/Cargo.toml index 7ed93c9f8c..dc60edc46f 100644 --- a/systest/Cargo.toml +++ b/systest/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Alex Crichton "] build = "build.rs" [dependencies] -libgit2-sys = { path = "../libgit2-sys" } +libgit2-sys = { path = "../libgit2-sys", features = ['curl', 'https', 'ssh'] } libc = "0.2" [build-dependencies] From 89c63b87d9bfcfbbc7e0e67231b6ce93b128ce27 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 13 Sep 2018 16:34:38 -0700 Subject: [PATCH 284/860] Bump libgit2-sys to 0.7.8 --- libgit2-sys/Cargo.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index c1fb68e589..5245001e11 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.7" +version = "0.7.8" authors = ["Alex Crichton "] links = "git2" build = "build.rs" @@ -16,14 +16,14 @@ name = "libgit2_sys" path = "lib.rs" [dependencies] -curl-sys = { version = "0.4.6", optional = true } +curl-sys = { version = "0.4.10", optional = true } libc = "0.2" -libssh2-sys = { version = "0.2.8", optional = true } -libz-sys = "1.0.18" +libssh2-sys = { version = "0.2.11", optional = true } +libz-sys = "1.0.22" [build-dependencies] pkg-config = "0.3" -cc = "1.0" +cc = "1.0.25" [target.'cfg(unix)'.dependencies] openssl-sys = { version = "0.9", optional = true } From 6b9708335d39d952a4d7124be2b8cca00ca163bc Mon Sep 17 00:00:00 2001 From: bgermann Date: Thu, 20 Sep 2018 21:56:37 +0200 Subject: [PATCH 285/860] Remove breaking nsec from android --- libgit2-sys/build.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 619472db28..12ad5c383a 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -68,7 +68,10 @@ fn main() { features.push_str("#ifndef INCLUDE_features_h\n"); features.push_str("#define INCLUDE_features_h\n"); features.push_str("#define GIT_THREADS 1\n"); - features.push_str("#define GIT_USE_NSEC 1\n"); + + if !target.contains("android") { + features.push_str("#define GIT_USE_NSEC 1\n"); + } if target.contains("apple") { features.push_str("#define GIT_USE_STAT_MTIMESPEC 1\n"); From 9c1604ef7abbbdf4a2312f18c0e60370961a14b2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 21 Sep 2018 10:20:05 -0700 Subject: [PATCH 286/860] Attempt to fix libgit2's MinGW build --- libgit2-sys/build.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 12ad5c383a..1d23f483ab 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -58,6 +58,13 @@ fn main() { if windows { add_c_files(&mut cfg, "libgit2/src/win32".as_ref()); cfg.define("STRSAFE_NO_DEPRECATE", None); + + // libgit2's build system claims that forks like mingw-w64 of MinGW + // still want this define to use C99 stdio functions automatically. + // Apparently libgit2 breaks at runtime if this isn't here? Who knows! + if target.contains("gnu") { + cfg.define("__USE_MINGW_ANSI_STDIO", "1"); + } } else { add_c_files(&mut cfg, "libgit2/src/unix".as_ref()); cfg.flag("-fvisibility=hidden"); From a051651443897e765330146b80d94ee6788e65b7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 21 Sep 2018 10:20:20 -0700 Subject: [PATCH 287/860] Bump libgit2-sys to 0.7.9 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 5245001e11..301b52c57b 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.8" +version = "0.7.9" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From dcbd08e6be5a2ba04de426e57c5dc2b6af62b6e0 Mon Sep 17 00:00:00 2001 From: bgermann Date: Tue, 25 Sep 2018 14:34:21 +0200 Subject: [PATCH 288/860] Add Solaris compile flags from cmake config --- libgit2-sys/build.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 1d23f483ab..20806c72a4 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -69,6 +69,10 @@ fn main() { add_c_files(&mut cfg, "libgit2/src/unix".as_ref()); cfg.flag("-fvisibility=hidden"); } + if target.contains("solaris") { + cfg.define("_POSIX_C_SOURCE", "200112L"); + cfg.define("__EXTENSIONS__", None); + } let mut features = String::new(); From 3938af1d5a3a7deede10859808396bb4c5d56cd4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 25 Sep 2018 10:06:11 -0700 Subject: [PATCH 289/860] Bump to 0.7.10 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 301b52c57b..d0c5e5f790 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.9" +version = "0.7.10" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From e55f57df81e72221582a1a17866fc8314abd270e Mon Sep 17 00:00:00 2001 From: ppc Date: Wed, 26 Sep 2018 08:17:15 +0800 Subject: [PATCH 290/860] fix id_old --- src/reflog.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reflog.rs b/src/reflog.rs index 6996a89dae..b4ff7a0371 100644 --- a/src/reflog.rs +++ b/src/reflog.rs @@ -115,7 +115,7 @@ impl<'reflog> ReflogEntry<'reflog> { /// Get the old oid pub fn id_old(&self) -> Oid { - unsafe { Binding::from_raw(raw::git_reflog_entry_id_new(self.raw)) } + unsafe { Binding::from_raw(raw::git_reflog_entry_id_old(self.raw)) } } /// Get the log message, returning `None` on invalid UTF-8. From b91893f72ff7c7b9e07189f39805f4c796eeb03e Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 4 Oct 2018 21:54:45 +0200 Subject: [PATCH 291/860] Fix documentation for Sort::TOPOLOGICAL The libgit2 documentation says "no parents before all of its children are shown", which is exactly the opposite of what the rust docstring said. --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1c49ba6df9..2d476ece33 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -377,8 +377,8 @@ bitflags! { /// change at any time. This is the default sorting for new walkers. const NONE = raw::GIT_SORT_NONE as u32; - /// Sort the repository contents in topological order (parents before - /// children). + /// Sort the repository contents in topological order (children before + /// parents). /// /// This sorting mode can be combined with time sorting. const TOPOLOGICAL = raw::GIT_SORT_TOPOLOGICAL as u32; From b84cf7b460237d02debd8fda296e6a0e8a4fd840 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 11 Oct 2018 15:21:40 -0700 Subject: [PATCH 292/860] Support sticky redirects in git2-curl. If you use a gitlab url such as "https://gitlab.com/user/repo", then gitlab will redirect the first GET request to "https://gitlab.com/user/repo.git" (with the `.git` at the end). However, gitlab does not redirect the next POST, causing a 404. This change keeps track of the original redirect so that subsequent actions use the new base url. This roughly mirrors what is done in libgit2's transport. Fixes rust-lang/cargo#6114 --- git2-curl/src/lib.rs | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 677e155667..90fe412b7f 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -36,13 +36,18 @@ use url::Url; struct CurlTransport { handle: Arc>, + /// The URL of the remote server, e.g. "https://github.com/user/repo" + /// + /// This is an empty string until the first action is performed. + /// If there is an HTTP redirect, this will be updated with the new URL. + base_url: Arc> } struct CurlSubtransport { handle: Arc>, service: &'static str, url_path: &'static str, - base_url: String, + base_url: Arc>, method: &'static str, reader: Option>>, sent_request: bool, @@ -81,12 +86,19 @@ pub unsafe fn register(handle: Easy) { fn factory(remote: &git2::Remote, handle: Arc>) -> Result { - Transport::smart(remote, true, CurlTransport { handle: handle }) + Transport::smart(remote, true, CurlTransport { + handle: handle, + base_url: Arc::new(Mutex::new(String::new())) + }) } impl SmartSubtransport for CurlTransport { fn action(&self, url: &str, action: Service) -> Result, Error> { + let mut base_url = self.base_url.lock().unwrap(); + if base_url.len() == 0 { + *base_url = url.to_string(); + } let (service, path, method) = match action { Service::UploadPackLs => { ("upload-pack", "/info/refs?service=git-upload-pack", "GET") @@ -106,7 +118,7 @@ impl SmartSubtransport for CurlTransport { handle: self.handle.clone(), service: service, url_path: path, - base_url: url.to_string(), + base_url: self.base_url.clone(), method: method, reader: None, sent_request: false, @@ -130,7 +142,7 @@ impl CurlSubtransport { let agent = format!("git/1.0 (git2-curl {})", env!("CARGO_PKG_VERSION")); // Parse our input URL to figure out the host - let url = format!("{}{}", self.base_url, self.url_path); + let url = format!("{}{}", self.base_url.lock().unwrap(), self.url_path); let parsed = try!(Url::parse(&url).map_err(|_| { self.err("invalid url, failed to parse") })); @@ -230,6 +242,20 @@ impl CurlSubtransport { // Ok, time to read off some data. let rdr = Cursor::new(data); self.reader = Some(rdr); + + // If there was a redirect, update the `CurlTransport` with the new base. + if let Ok(Some(effective_url)) = h.effective_url() { + let new_base = if effective_url.ends_with(self.url_path) { + // Strip the action from the end. + &effective_url[..effective_url.len() - self.url_path.len()] + } else { + // I'm not sure if this code path makes sense, but it's what + // libgit does. + effective_url + }; + *self.base_url.lock().unwrap() = new_base.to_string(); + } + Ok(()) } } From d5b83fcbd7faa32ea281af626d39e189cbb00b0e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 10 Oct 2018 21:15:31 -0700 Subject: [PATCH 293/860] Try testing on windows --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2855475e48..073e494a16 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: rust -sudo: false git: submodules: false @@ -7,6 +6,7 @@ matrix: include: - rust: 1.26.0 - rust: stable + - os: windows - os: osx rust: stable before_install: From 23d933c97d7c003fc053e2225260d6beac2f8a93 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 11 Oct 2018 15:57:36 -0700 Subject: [PATCH 294/860] Bump git2-curl to 0.8.2 --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 4afee5942c..809e058b3a 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.8.1" +version = "0.8.2" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/git2-rs" From c4a4af77303a1aac93149925872edb071611140d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 11 Oct 2018 16:56:06 -0700 Subject: [PATCH 295/860] Remove accidental addition of windows on travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 073e494a16..2f0fd92518 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ matrix: include: - rust: 1.26.0 - rust: stable - - os: windows - os: osx rust: stable before_install: From a04beba586a841146a020b3f33b749e9c7a67b03 Mon Sep 17 00:00:00 2001 From: Cyril Plisko Date: Wed, 17 Oct 2018 23:58:20 +0300 Subject: [PATCH 296/860] Lapsus clavis --- src/describe.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/describe.rs b/src/describe.rs index c062088711..a894c57425 100644 --- a/src/describe.rs +++ b/src/describe.rs @@ -124,7 +124,7 @@ impl DescribeOptions { /// Sets the reference lookup strategy /// - /// This behaves like the `--tags` option to git-decribe. + /// This behaves like the `--tags` option to git-describe. pub fn describe_tags(&mut self) -> &mut Self { self.raw.describe_strategy = raw::GIT_DESCRIBE_TAGS as c_uint; self @@ -132,7 +132,7 @@ impl DescribeOptions { /// Sets the reference lookup strategy /// - /// This behaves like the `--all` option to git-decribe. + /// This behaves like the `--all` option to git-describe. pub fn describe_all(&mut self) -> &mut Self { self.raw.describe_strategy = raw::GIT_DESCRIBE_ALL as c_uint; self From 6a3b9d85201996728e9b0f5f159d023e96540acb Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 23 Oct 2018 20:24:19 +0200 Subject: [PATCH 297/860] Use Option for DiffFiles in CheckoutBuilder's notify callback --- src/build.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/src/build.rs b/src/build.rs index 4e4d2959a3..29b66d69cf 100644 --- a/src/build.rs +++ b/src/build.rs @@ -59,8 +59,9 @@ pub type Progress<'a> = FnMut(Option<&Path>, usize, usize) + 'a; /// /// The callback must return a bool specifying whether the checkout should /// continue. -pub type Notify<'a> = FnMut(CheckoutNotificationType, Option<&Path>, DiffFile, - DiffFile, DiffFile) -> bool + 'a; +pub type Notify<'a> = FnMut(CheckoutNotificationType, Option<&Path>, + Option, Option, + Option) -> bool + 'a; impl<'cb> Default for RepoBuilder<'cb> { @@ -506,8 +507,8 @@ impl<'cb> CheckoutBuilder<'cb> { /// Callbacks are invoked prior to modifying any files on disk. /// Returning `false` from the callback will cancel the checkout. pub fn notify(&mut self, cb: F) -> &mut CheckoutBuilder<'cb> - where F: FnMut(CheckoutNotificationType, Option<&Path>, DiffFile, - DiffFile, DiffFile) -> bool + 'cb + where F: FnMut(CheckoutNotificationType, Option<&Path>, Option, + Option, Option) -> bool + 'cb { self.notify = Some(Box::new(cb) as Box>); self @@ -593,12 +594,26 @@ extern fn notify_cb(why: raw::git_checkout_notify_t, Some(util::bytes2path(CStr::from_ptr(path).to_bytes())) }; + let baseline = if baseline.is_null() { + None + } else { + Some(DiffFile::from_raw(baseline)) + }; + + let target = if target.is_null() { + None + } else { + Some(DiffFile::from_raw(target)) + }; + + let workdir = if workdir.is_null() { + None + } else { + Some(DiffFile::from_raw(workdir)) + }; + let why = CheckoutNotificationType::from_bits_truncate(why as u32); - let keep_going = callback(why, - path, - DiffFile::from_raw(baseline), - DiffFile::from_raw(target), - DiffFile::from_raw(workdir)); + let keep_going = callback(why, path, baseline, target, workdir); if keep_going {0} else {1} }).unwrap_or(2) } @@ -608,8 +623,8 @@ mod tests { use std::fs; use std::path::Path; use tempdir::TempDir; - use super::RepoBuilder; - use Repository; + use super::{CheckoutBuilder, RepoBuilder}; + use {CheckoutNotificationType, Repository}; #[test] fn smoke() { @@ -635,4 +650,52 @@ mod tests { .clone(&url, &dst).is_err()); } + /// Issue regression test #365 + #[test] + fn notify_callback() { + let td = TempDir::new("test").unwrap(); + let cd = TempDir::new("external-checkout").unwrap(); + + { + let repo = Repository::init(&td.path()).unwrap(); + + let mut config = repo.config().unwrap(); + config.set_str("user.name", "name").unwrap(); + config.set_str("user.email", "email").unwrap(); + + let mut index = repo.index().unwrap(); + let p = Path::new(td.path()).join("file"); + println!("using path {:?}", p); + fs::File::create(&p).unwrap(); + index.add_path(&Path::new("file")).unwrap(); + let id = index.write_tree().unwrap(); + + let tree = repo.find_tree(id).unwrap(); + let sig = repo.signature().unwrap(); + repo.commit(Some("HEAD"), &sig, &sig, "initial", + &tree, &[]).unwrap(); + } + + let repo = Repository::open_bare(&td.path().join(".git")).unwrap(); + let tree = repo + .revparse_single(&"master") + .unwrap() + .peel_to_tree() + .unwrap(); + let mut index = repo.index().unwrap(); + index.read_tree(&tree).unwrap(); + + let mut checkout_opts = CheckoutBuilder::new(); + checkout_opts.target_dir(&cd.path()); + checkout_opts.notify_on(CheckoutNotificationType::all()); + checkout_opts.notify(|_notif, _path, baseline, target, workdir| { + assert!(baseline.is_none()); + assert_eq!(target.unwrap().path(), Some(Path::new("file"))); + assert!(workdir.is_none()); + true + }); + repo.checkout_index(Some(&mut index), Some(&mut checkout_opts)) + .unwrap(); + } + } From c5b7a2474eaacd3b29623ee0d6541ce52ab8c661 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 26 Oct 2018 23:49:23 -0700 Subject: [PATCH 298/860] Bump version so major bump isn't forgotten --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4cccdb2ad0..0410a8d94b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.7.5" +version = "0.8.0" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 846ff199117dd9305bd4f5b3019048e7f1363cae Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 29 Oct 2018 09:28:36 -0700 Subject: [PATCH 299/860] Bump git2-curl's dep on git2 --- git2-curl/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 809e058b3a..707be44a1b 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.8.2" +version = "0.9.2" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/git2-rs" @@ -17,7 +17,7 @@ Intended to be used with the git2 crate. curl = "0.4" url = "1.0" log = "0.4" -git2 = { path = "..", version = "0.7", default-features = false } +git2 = { path = "..", version = "0.8", default-features = false } [dev-dependencies] civet = "0.11" From fbc616ab5e2be038e6c233d7cb0e4dee8907ad06 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sat, 10 Nov 2018 21:20:52 -0500 Subject: [PATCH 300/860] Expose parent count on git2::Commit --- src/commit.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/commit.rs b/src/commit.rs index 1e6de6f480..b44941fc63 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -151,14 +151,12 @@ impl<'repo> Commit<'repo> { /// Creates a new iterator over the parents of this commit. pub fn parents<'a>(&'a self) -> Parents<'a, 'repo> { - let max = unsafe { raw::git_commit_parentcount(&*self.raw) as usize }; - Parents { range: 0..max, commit: self } + Parents { range: 0..self.parent_count(), commit: self } } /// Creates a new iterator over the parents of this commit. pub fn parent_ids(&self) -> ParentIds { - let max = unsafe { raw::git_commit_parentcount(&*self.raw) as usize }; - ParentIds { range: 0..max, commit: self } + ParentIds { range: 0..self.parent_count(), commit: self } } /// Get the author of this commit. @@ -210,6 +208,13 @@ impl<'repo> Commit<'repo> { } } + /// Get the number of parents of this commit. + /// + /// Use the `parents` iterator to return an iterator over all parents. + pub fn parent_count(&self) -> usize { + unsafe { raw::git_commit_parentcount(&*self.raw) as usize } + } + /// Get the specified parent of the commit. /// /// Use the `parents` iterator to return an iterator over all parents. From ea6ac7ad4e0e9a81e356373edc89845078dc187d Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sat, 10 Nov 2018 21:58:07 -0500 Subject: [PATCH 301/860] Return the message_encoding from Commit.message_encoding --- src/commit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commit.rs b/src/commit.rs index 1e6de6f480..aadc288459 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -83,7 +83,7 @@ impl<'repo> Commit<'repo> { /// `None` will be returned if the encoding is not known pub fn message_encoding(&self) -> Option<&str> { let bytes = unsafe { - ::opt_bytes(self, raw::git_commit_message(&*self.raw)) + ::opt_bytes(self, raw::git_commit_message_encoding(&*self.raw)) }; bytes.and_then(|b| str::from_utf8(b).ok()) } From 1379882330c7b588db828b503f952f02f63460e1 Mon Sep 17 00:00:00 2001 From: Sergei Vorobev Date: Fri, 16 Nov 2018 22:32:05 -0800 Subject: [PATCH 302/860] Fix +nightly test compilation Previously an error ``` Compiling git2 v0.8.0 (/home/travis/build/alexcrichton/git2-rs) error: name `cfg` is reserved in macro namespace --> src/cred.rs:421:18 | 421 | macro_rules! cfg( ($($k:expr => $v:expr),*) => ({ | ^^^ error: aborting due to previous error error: Could not compile `git2`. warning: build failed, waiting for other jobs to finish... error: build failed ``` was produced. I replaced `cfg` macro name, which appears to be reserved now, by `test_cfg`. --- src/cred.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cred.rs b/src/cred.rs index 29d514885a..e7cf81c002 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -418,7 +418,7 @@ mod test { use {Cred, Config, CredentialHelper, ConfigLevel}; - macro_rules! cfg( ($($k:expr => $v:expr),*) => ({ + macro_rules! test_cfg( ($($k:expr => $v:expr),*) => ({ let td = TempDir::new("git2-rs").unwrap(); let mut cfg = Config::new().unwrap(); cfg.add_file(&td.path().join("cfg"), ConfigLevel::Highest, false).unwrap(); @@ -433,7 +433,7 @@ mod test { #[test] fn credential_helper1() { - let cfg = cfg! { + let cfg = test_cfg! { "credential.helper" => "!f() { echo username=a; echo password=b; }; f" }; let (u, p) = CredentialHelper::new("https://example.com/foo/bar") @@ -445,7 +445,7 @@ mod test { #[test] fn credential_helper2() { - let cfg = cfg! {}; + let cfg = test_cfg! {}; assert!(CredentialHelper::new("https://example.com/foo/bar") .config(&cfg) .execute().is_none()); @@ -453,7 +453,7 @@ mod test { #[test] fn credential_helper3() { - let cfg = cfg! { + let cfg = test_cfg! { "credential.https://example.com.helper" => "!f() { echo username=c; }; f", "credential.helper" => "!f() { echo username=a; echo password=b; }; f" @@ -474,7 +474,7 @@ mod test { echo username=c ").unwrap(); chmod(&path); - let cfg = cfg! { + let cfg = test_cfg! { "credential.https://example.com.helper" => &path.display().to_string()[..], "credential.helper" => "!f() { echo username=a; echo password=b; }; f" @@ -501,7 +501,7 @@ echo username=c .chain(path.parent().map(|p| p.to_path_buf()).into_iter()); env::set_var("PATH", &env::join_paths(paths).unwrap()); - let cfg = cfg! { + let cfg = test_cfg! { "credential.https://example.com.helper" => "script", "credential.helper" => "!f() { echo username=a; echo password=b; }; f" }; @@ -514,7 +514,7 @@ echo username=c #[test] fn credential_helper6() { - let cfg = cfg! { + let cfg = test_cfg! { "credential.helper" => "" }; assert!(CredentialHelper::new("https://example.com/foo/bar") From c6ff5c9eb98f59a2a2fd18a657b55c254a5ade7a Mon Sep 17 00:00:00 2001 From: Rukai Date: Sat, 17 Nov 2018 23:33:53 +1100 Subject: [PATCH 303/860] Expose openssl vendored feature --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 0410a8d94b..c9ccade036 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ default = ["ssh", "https", "curl", "ssh_key_from_memory"] ssh = ["libgit2-sys/ssh"] https = ["libgit2-sys/https", "openssl-sys", "openssl-probe"] curl = ["libgit2-sys/curl"] +vendored-openssl = ["openssl-sys/vendored"] ssh_key_from_memory = ["libgit2-sys/ssh_key_from_memory"] [workspace] From 6825f0908bbe341aba3784bb82c0065a06252083 Mon Sep 17 00:00:00 2001 From: Marcio Giaxa Date: Thu, 22 Nov 2018 01:02:37 -0200 Subject: [PATCH 304/860] fix doc for Repository::init_opts --- src/repo.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index 8b8edf48aa..784160cbd9 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -171,9 +171,9 @@ impl Repository { Repository::init_opts(path, RepositoryInitOptions::new().bare(true)) } - /// Creates a new `--bare` repository in the specified folder. + /// Creates a new repository in the specified folder with the given options. /// - /// The folder must exist prior to invoking this function. + /// See `RepositoryInitOptions` struct for more information. pub fn init_opts>(path: P, opts: &RepositoryInitOptions) -> Result { init(); From 20ffdabcba7d9521324fcc5fbec5251b9903c965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 20 Sep 2018 04:08:00 +0200 Subject: [PATCH 305/860] rebase: add function definitions --- libgit2-sys/lib.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5d0e2972f5..48f2511fc4 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -79,6 +79,7 @@ pub enum git_pathspec_match_list {} pub enum git_diff {} pub enum git_diff_stats {} pub enum git_patch {} +pub enum git_rebase {} pub enum git_reflog {} pub enum git_reflog_entry {} pub enum git_describe_result {} @@ -1557,6 +1558,36 @@ pub type git_packbuilder_foreach_cb = extern fn(*const c_void, size_t, pub type git_odb_foreach_cb = extern fn(id: *const git_oid, payload: *mut c_void) -> c_int; +pub const GIT_REBASE_NO_OPERATION: usize = usize::max_value(); + +#[repr(C)] +pub struct git_rebase_options { + pub version: c_uint, + pub quiet: c_int, + pub inmemory: c_int, + pub rewrite_notes_ref: *const c_char, + pub merge_options: git_merge_options, + pub checkout_options: git_checkout_options, +} + +git_enum! { + pub enum git_rebase_operation_t { + GIT_REBASE_OPERATION_PICK = 0, + GIT_REBASE_OPERATION_REWORD, + GIT_REBASE_OPERATION_EDIT, + GIT_REBASE_OPERATION_SQUASH, + GIT_REBASE_OPERATION_FIXUP, + GIT_REBASE_OPERATION_EXEC, + } +} + +#[repr(C)] +pub struct git_rebase_operation { + pub _type: git_rebase_operation_t, + pub id: git_oid, + pub exec: *const c_char, +} + extern { // threads pub fn git_libgit2_init() -> c_int; @@ -2959,6 +2990,30 @@ extern { pub fn git_refdb_set_backend(refdb: *mut git_refdb, backend: *mut git_refdb_backend) -> c_int; pub fn git_refdb_compress(refdb: *mut git_refdb) -> c_int; pub fn git_refdb_free(refdb: *mut git_refdb); + + // rebase + pub fn git_rebase_init_options(opts: *mut git_rebase_options, version: c_uint) -> c_int; + pub fn git_rebase_init(out: *mut *mut git_rebase, + repo: *mut git_repository, + branch: *const git_annotated_commit, + upstream: *const git_annotated_commit, + onto: *const git_annotated_commit, + opts: *const git_rebase_options) -> c_int; + pub fn git_rebase_open(out: *mut *mut git_rebase, repo: *mut git_repository, opts: *const git_rebase_options) -> c_int; + pub fn git_rebase_operation_entrycount(rebase: *mut git_rebase) -> size_t; + pub fn git_rebase_operation_current(rebase: *mut git_rebase) -> size_t; + pub fn git_rebase_operation_byindex(rebase: *mut git_rebase, idx: size_t) -> *mut git_rebase_operation; + pub fn git_rebase_next(operation: *mut *mut git_rebase_operation, rebase: *mut git_rebase) -> c_int; + pub fn git_rebase_inmemory_index(index: *mut *mut git_index, rebase: *mut git_rebase) -> c_int; + pub fn git_rebase_commit(id: *mut git_oid, + rebase: *mut git_rebase, + author: *const git_signature, + committer: *const git_signature, + message_encoding: *const c_char, + message: *const c_char) -> c_int; + pub fn git_rebase_abort(rebase: *mut git_rebase) -> c_int; + pub fn git_rebase_finish(rebase: *mut git_rebase, signature: *const git_signature) -> c_int; + pub fn git_rebase_free(rebase: *mut git_rebase); } pub fn init() { From 95db89eb1dbc8c98b282bea6c2090bad67d49d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 20 Sep 2018 12:19:08 +0200 Subject: [PATCH 306/860] rebase: introduce the rebase operations We cover initialising a new rebase operation (optionally in-memory) as well as opening an ongoing one. --- src/lib.rs | 2 + src/rebase.rs | 354 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/repo.rs | 37 ++++++ 3 files changed, 393 insertions(+) create mode 100644 src/rebase.rs diff --git a/src/lib.rs b/src/lib.rs index 2d476ece33..b2c1b09005 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,6 +103,7 @@ pub use pathspec::{Pathspec, PathspecMatchList, PathspecFailedEntries}; pub use pathspec::{PathspecDiffEntries, PathspecEntries}; pub use patch::Patch; pub use proxy_options::ProxyOptions; +pub use rebase::{Rebase, RebaseOptions, RebaseOperation, RebaseOperationType}; pub use reference::{Reference, References, ReferenceNames}; pub use reflog::{Reflog, ReflogEntry, ReflogIter}; pub use refspec::Refspec; @@ -657,6 +658,7 @@ mod packbuilder; mod pathspec; mod patch; mod proxy_options; +mod rebase; mod reference; mod reflog; mod refspec; diff --git a/src/rebase.rs b/src/rebase.rs new file mode 100644 index 0000000000..959ef23405 --- /dev/null +++ b/src/rebase.rs @@ -0,0 +1,354 @@ +use std::{marker, ptr, mem, str}; +use std::ffi::CString; + +use {raw, Oid, Error, Signature, MergeOptions, Index}; +use build::CheckoutBuilder; +use util::Binding; + +/// Rebase options +/// +/// Use to tell the rebase machinery how to operate. +pub struct RebaseOptions<'cb> { + raw: raw::git_rebase_options, + merge_options: Option, + checkout_options: Option>, +} + +impl<'cb> Default for RebaseOptions<'cb> { + fn default() -> Self { + Self::new() + } +} + +impl<'cb> RebaseOptions<'cb> { + /// Creates a new default set of rebase options. + pub fn new() -> RebaseOptions<'cb> { + let mut opts = RebaseOptions { + raw: unsafe { mem::zeroed() }, + merge_options: None, + checkout_options: None, + }; + assert_eq!(unsafe { + raw::git_rebase_init_options(&mut opts.raw, 1) + }, 0); + opts + } + + /// Used by `Repository::rebase`, this will instruct other clients working on this + /// rebase that you want a quiet rebase experience, which they may choose to + /// provide in an application-specific manner. This has no effect upon + /// libgit2 directly, but is provided for interoperability between Git + /// tools. + pub fn quiet(&mut self, quiet: bool) -> &mut RebaseOptions<'cb> { + self.raw.quiet = quiet as i32; + self + } + + /// Used by `Repository::rebase`, this will begin an in-memory rebase, + /// which will allow callers to step through the rebase operations and + /// commit the rebased changes, but will not rewind HEAD or update the + /// repository to be in a rebasing state. This will not interfere with + /// the working directory (if there is one). + pub fn inmemory(&mut self, inmemory: bool) -> &mut RebaseOptions<'cb> { + self.raw.inmemory = inmemory as i32; + self + } + + /// Used by `finish()`, this is the name of the notes reference + /// used to rewrite notes for rebased commits when finishing the rebase; + /// if NULL, the contents of the configuration option `notes.rewriteRef` + /// is examined, unless the configuration option `notes.rewrite.rebase` + /// is set to false. If `notes.rewriteRef` is also NULL, notes will + /// not be rewritten. + pub fn rewrite_notes_ref(&mut self, rewrite_notes_ref: &str) -> &mut RebaseOptions<'cb> { + let s = CString::new(rewrite_notes_ref).unwrap().as_ptr(); + self.raw.rewrite_notes_ref = s; + self + } + + /// Options to control how trees are merged during `next()`. + pub fn merge_options(&mut self, opts: MergeOptions) -> &mut RebaseOptions<'cb> { + self.merge_options = Some(opts); + self + } + + /// Options to control how files are written during `Repository::rebase`, + /// `next()` and `abort()`. Note that a minimum strategy of + /// `GIT_CHECKOUT_SAFE` is defaulted in `init` and `next`, and a minimum + /// strategy of `GIT_CHECKOUT_FORCE` is defaulted in `abort` to match git + /// semantics. + pub fn checkout_options(&mut self, opts: CheckoutBuilder<'cb>) -> &mut RebaseOptions<'cb> { + self.checkout_options = Some(opts); + self + } + + /// Acquire a pointer to the underlying raw options. + pub fn raw(&mut self) -> *const raw::git_rebase_options { + unsafe { + if let Some(opts) = self.merge_options.as_mut().take() { + ptr::copy_nonoverlapping(opts.raw(), &mut self.raw.merge_options, 1); + mem::forget(opts); + } + if let Some(opts) = self.checkout_options.as_mut() { + opts.configure(&mut self.raw.checkout_options); + } + } + &self.raw + } + +} + +/// Representation of a rebase +pub struct Rebase<'repo> { + raw: *mut raw::git_rebase, + _marker: marker::PhantomData<&'repo raw::git_rebase>, +} + +impl <'repo> Rebase<'repo> { + /// Gets the count of rebase operations that are to be applied. + pub fn len(&self) -> usize { + unsafe { raw::git_rebase_operation_entrycount(self.raw) } + } + + /// Gets the rebase operation specified by the given index. + pub fn nth(&mut self, n: usize) -> Option { + unsafe { + let op = raw::git_rebase_operation_byindex(self.raw, n); + if op.is_null() { + None + } else { + Some(RebaseOperation::from_raw(op)) + } + } + } + + /// Gets the index of the rebase operation that is currently being applied. + /// If the first operation has not yet been applied (because you have called + /// `init` but not yet `next`) then this returns None. + pub fn operation_current(&mut self) -> Option { + let cur = unsafe { raw::git_rebase_operation_current(self.raw) }; + if cur == raw::GIT_REBASE_NO_OPERATION { + None + } else { + Some(cur) + } + } + + /// Gets the index produced by the last operation, which is the result of + /// `next()` and which will be committed by the next invocation of + /// `commit()`. This is useful for resolving conflicts in an in-memory + /// rebase before committing them. + /// + /// This is only applicable for in-memory rebases; for rebases within a + /// working directory, the changes were applied to the repository's index. + pub fn inmemory_index(&mut self) -> Result { + let mut idx = ptr::null_mut(); + unsafe { + try_call!(raw::git_rebase_inmemory_index(&mut idx, self.raw)); + Ok(Binding::from_raw(idx)) + } + } + + /// Commits the current patch. You must have resolved any conflicts that + /// were introduced during the patch application from the `git_rebase_next` + /// invocation. + pub fn commit(&mut self, author: &Signature, committer: &Signature, message: &str) -> Result { + let mut id: raw::git_oid = unsafe { mem::zeroed() }; + let message = try!(CString::new(message)); + unsafe { + try_call!(raw::git_rebase_commit(&mut id, self.raw, author.raw(), committer.raw(), ptr::null(), message)); + Ok(Binding::from_raw(&id as *const _)) + } + } + + /// Aborts a rebase that is currently in progress, resetting the repository + /// and working directory to their state before rebase began. + pub fn abort(&mut self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_rebase_abort(self.raw)); + } + + Ok(()) + } + + /// Finishes a rebase that is currently in progress once all patches have + /// been applied. + pub fn finish(&mut self, signature: &Signature) -> Result<(), Error> { + unsafe { + try_call!(raw::git_rebase_finish(self.raw, signature.raw())); + } + + Ok(()) + } +} + +impl <'rebase> Iterator for Rebase<'rebase> { + type Item = Result, Error>; + + /// Performs the next rebase operation and returns the information about it. + /// If the operation is one that applies a patch (which is any operation except + /// GitRebaseOperation::Exec) then the patch will be applied and the index and + /// working directory will be updated with the changes. If there are conflicts, + /// you will need to address those before committing the changes. + fn next(&mut self) -> Option, Error>> { + let mut out = ptr::null_mut(); + unsafe { + try_call_iter!(raw::git_rebase_next(&mut out, self.raw)); + Some(Ok(RebaseOperation::from_raw(out))) + } + } +} + + +impl<'repo> Binding for Rebase<'repo> { + type Raw = *mut raw::git_rebase; + unsafe fn from_raw(raw: *mut raw::git_rebase) + -> Rebase<'repo> { + Rebase { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_rebase { self.raw } +} + + +impl<'repo> Drop for Rebase<'repo> { + fn drop(&mut self) { + unsafe { raw::git_rebase_free(self.raw) } + } +} + +/// A rebase operation +/// +/// Describes a single instruction/operation to be performed during the +/// rebase. +#[derive(Debug, PartialEq)] +pub enum RebaseOperationType { + /// The given commit is to be cherry-picked. The client should commit the + /// changes and continue if there are no conflicts. + Pick, + + /// The given commit is to be cherry-picked, but the client should prompt + /// the user to provide an updated commit message. + Reword, + + /// The given commit is to be cherry-picked, but the client should stop to + /// allow the user to edit the changes before committing them. + Edit, + + /// The given commit is to be squashed into the previous commit. The commit + /// message will be merged with the previous message. + Squash, + + /// The given commit is to be squashed into the previous commit. The commit + /// message from this commit will be discarded. + Fixup, + + /// No commit will be cherry-picked. The client should run the given command + /// and (if successful) continue. + Exec, +} + +impl RebaseOperationType { + /// Convert from the int into an enum. Returns None if invalid. + pub fn from_raw(raw: raw::git_rebase_operation_t) -> Option { + match raw { + raw::GIT_REBASE_OPERATION_PICK => Some(RebaseOperationType::Pick), + raw::GIT_REBASE_OPERATION_REWORD => Some(RebaseOperationType::Reword), + raw::GIT_REBASE_OPERATION_EDIT => Some(RebaseOperationType::Edit), + raw::GIT_REBASE_OPERATION_SQUASH => Some(RebaseOperationType::Squash), + raw::GIT_REBASE_OPERATION_FIXUP => Some(RebaseOperationType::Fixup), + raw::GIT_REBASE_OPERATION_EXEC => Some(RebaseOperationType::Exec), + _ => None, + } + } +} + +/// A rebase operation +/// +/// Describes a single instruction/operation to be performed during the +/// rebase. +#[derive(Debug)] +pub struct RebaseOperation<'rebase> { + raw: *const raw::git_rebase_operation, + _marker: marker::PhantomData>, +} + +impl<'rebase> RebaseOperation<'rebase> { + /// The type of rebase operation + pub fn kind(&self) -> Option { + unsafe { + RebaseOperationType::from_raw((*self.raw)._type) + } + } + + /// The commit ID being cherry-picked. This will be populated for all + /// operations except those of type `GIT_REBASE_OPERATION_EXEC`. + pub fn id(&self) -> Oid { + unsafe { + Binding::from_raw(&(*self.raw).id as *const _) + } + } + + ///The executable the user has requested be run. This will only + /// be populated for operations of type RebaseOperationType::Exec + pub fn exec(&self) -> Option<&str> { + unsafe { + str::from_utf8(::opt_bytes(self, (*self.raw).exec).unwrap()).ok() + } + } +} + +impl<'rebase> Binding for RebaseOperation<'rebase> { + type Raw = *const raw::git_rebase_operation; + unsafe fn from_raw(raw: *const raw::git_rebase_operation) -> RebaseOperation<'rebase> { + RebaseOperation { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *const raw::git_rebase_operation { self.raw } +} + +#[cfg(test)] +mod tests { + use {RebaseOptions, RebaseOperationType}; + + #[test] + fn smoke() { + let (_td, repo) = ::test::repo_init(); + let head_target = repo.head().unwrap().target().unwrap(); + let tip = repo.find_commit(head_target).unwrap(); + let sig = tip.author(); + let tree = tip.tree().unwrap(); + + // We just want to see the iteration work so we can create commits with + // no changes + let c1 = repo.commit(Some("refs/heads/master"), &sig, &sig, "foo", &tree, &[&tip]).unwrap(); + let c1 = repo.find_commit(c1).unwrap(); + let c2 = repo.commit(Some("refs/heads/master"), &sig, &sig, "foo", &tree, &[&c1]).unwrap(); + + let branch = repo.find_annotated_commit(c2).unwrap(); + let upstream = repo .find_annotated_commit(tip.id()).unwrap(); + let mut opts: RebaseOptions = Default::default(); + opts.inmemory(true); + let mut rebase = repo.rebase(Some(&branch), Some(&upstream), None, Some(&mut opts)).unwrap(); + + assert_eq!(rebase.len(), 2); + { + let op = rebase.next().unwrap().unwrap(); + assert_eq!(op.kind(), Some(RebaseOperationType::Pick)); + assert_eq!(op.id(), c1.id()); + } + { + let op = rebase.next().unwrap().unwrap(); + assert_eq!(op.kind(), Some(RebaseOperationType::Pick)); + assert_eq!(op.id(), c2); + } + { + let op = rebase.next(); + assert!(op.is_none()); + } + } +} diff --git a/src/repo.rs b/src/repo.rs index 784160cbd9..a3348bd864 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -14,6 +14,7 @@ use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus, MergeAnaly use {ObjectType, Tag, Note, Notes, StatusOptions, Statuses, Status, Revwalk}; use {RevparseMode, RepositoryInitMode, Reflog, IntoCString, Describe}; use {DescribeOptions, TreeBuilder, Diff, DiffOptions, PackBuilder, Odb}; +use {Rebase, RebaseOptions}; use build::{RepoBuilder, CheckoutBuilder}; use stash::{StashApplyOptions, StashCbData, stash_cb}; use string_array::StringArray; @@ -1574,6 +1575,42 @@ impl Repository { } } + /// Initializes a rebase operation to rebase the changes in `branch` + /// relative to `upstream` onto another branch. To begin the rebase process, + /// call `next()`. + pub fn rebase(&self, + branch: Option<&AnnotatedCommit>, + upstream: Option<&AnnotatedCommit>, + onto: Option<&AnnotatedCommit>, + opts: Option<&mut RebaseOptions>) -> Result { + + let mut rebase: *mut raw::git_rebase = ptr::null_mut(); + unsafe { + try_call!(raw::git_rebase_init( + &mut rebase, + self.raw(), + branch.map(|c| c.raw()), + upstream.map(|c| c.raw()), + onto.map(|c| c.raw()), + opts.map(|o| o.raw()).unwrap_or(ptr::null()))); + + Ok(Rebase::from_raw(rebase)) + } + } + + /// Opens an existing rebase that was previously started by either an + /// invocation of `rebase()` or by another client. + pub fn open_rebase(&self, opts: Option<&mut RebaseOptions>) -> Result { + let mut rebase: *mut raw::git_rebase = ptr::null_mut(); + unsafe { + try_call!(raw::git_rebase_open(&mut rebase, self.raw(), opts.map(|o| o.raw()).unwrap_or(ptr::null()))); + Ok(Rebase::from_raw(rebase)) + + } + } + + + /// Add a note for an object /// /// The `notes_ref` argument is the canonical name of the reference to use, From d8b8a33a9c044e53b5603481f0d266acf1be0407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 8 Dec 2018 17:01:40 +0100 Subject: [PATCH 307/860] merge: rename flag helper to file_flag This matches the field it modifies more closely as there is another field called `flags`. --- src/merge.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/merge.rs b/src/merge.rs index 15089403e5..24484c0920 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -86,7 +86,7 @@ impl MergeOptions { self } - fn flag(&mut self, opt: raw::git_merge_file_flag_t, val: bool) -> &mut MergeOptions { + fn file_flag(&mut self, opt: raw::git_merge_file_flag_t, val: bool) -> &mut MergeOptions { if val { self.raw.file_flags |= opt; } else { @@ -97,42 +97,42 @@ impl MergeOptions { /// Create standard conflicted merge files pub fn standard_style(&mut self, standard: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FILE_STYLE_MERGE, standard) + self.file_flag(raw::GIT_MERGE_FILE_STYLE_MERGE, standard) } /// Create diff3-style file pub fn diff3_style(&mut self, diff3: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FILE_STYLE_DIFF3, diff3) + self.file_flag(raw::GIT_MERGE_FILE_STYLE_DIFF3, diff3) } /// Condense non-alphanumeric regions for simplified diff file pub fn simplify_alnum(&mut self, simplify: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FILE_SIMPLIFY_ALNUM, simplify) + self.file_flag(raw::GIT_MERGE_FILE_SIMPLIFY_ALNUM, simplify) } /// Ignore all whitespace pub fn ignore_whitespace(&mut self, ignore: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE, ignore) + self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE, ignore) } /// Ignore changes in amount of whitespace pub fn ignore_whitespace_change(&mut self, ignore: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE, ignore) + self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE, ignore) } /// Ignore whitespace at end of line pub fn ignore_whitespace_eol(&mut self, ignore: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL, ignore) + self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL, ignore) } /// Use the "patience diff" algorithm pub fn patience(&mut self, patience: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FILE_DIFF_PATIENCE, patience) + self.file_flag(raw::GIT_MERGE_FILE_DIFF_PATIENCE, patience) } /// Take extra time to find minimal diff pub fn minimal(&mut self, minimal: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FILE_DIFF_MINIMAL, minimal) + self.file_flag(raw::GIT_MERGE_FILE_DIFF_MINIMAL, minimal) } /// Acquire a pointer to the underlying raw options. From b261187111e08eccd21a0d5deb8f27bd797c53a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 8 Dec 2018 17:09:45 +0100 Subject: [PATCH 308/860] merge: add methods to enable merge flags --- src/merge.rs | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/merge.rs b/src/merge.rs index 24484c0920..c66ccfd3f2 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -46,16 +46,38 @@ impl MergeOptions { opts } - /// Detect file renames - pub fn find_renames(&mut self, find: bool) -> &mut MergeOptions { - if find { - self.raw.flags |= raw::GIT_MERGE_FIND_RENAMES; + fn flag(&mut self, opt: raw::git_merge_flag_t, val: bool) -> &mut MergeOptions { + if val { + self.raw.flags |= opt; } else { - self.raw.flags &= !raw::GIT_MERGE_FIND_RENAMES; + self.raw.flags &= !opt; } self } + /// Detect file renames + pub fn find_renames(&mut self, find: bool) -> &mut MergeOptions { + self.flag(raw::GIT_MERGE_FIND_RENAMES, find) + } + + /// If a conflict occurs, exit immediately instead of attempting to continue + /// resolving conflicts + pub fn fail_on_conflict(&mut self, fail: bool) -> &mut MergeOptions { + self.flag(raw::GIT_MERGE_FAIL_ON_CONFLICT, fail) + } + + /// Do not write the REUC extension on the generated index + pub fn skip_reuc(&mut self, skip: bool) -> &mut MergeOptions { + self.flag(raw::GIT_MERGE_FAIL_ON_CONFLICT, skip) + } + + /// If the commits being merged have multiple merge bases, do not build a + /// recursive merge base (by merging the multiple merge bases), instead + /// simply use the first base. + pub fn no_recursive(&mut self, disable: bool) -> &mut MergeOptions { + self.flag(raw::GIT_MERGE_NO_RECURSIVE, disable) + } + /// Similarity to consider a file renamed (default 50) pub fn rename_threshold(&mut self, thresh: u32) -> &mut MergeOptions { self.raw.rename_threshold = thresh; From ef549a6fe0df12d537052cb5ec89635dd222171c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 11 Dec 2018 10:00:28 +0100 Subject: [PATCH 309/860] rebase: make ctest happy Rename the `_type` field to `kind` which it knows to convert to `type` in C and tell it to ignore the `id` field as it's marked `const` which triggers an error. --- libgit2-sys/lib.rs | 2 +- src/rebase.rs | 2 +- systest/build.rs | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 48f2511fc4..7bede4e4be 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1583,7 +1583,7 @@ git_enum! { #[repr(C)] pub struct git_rebase_operation { - pub _type: git_rebase_operation_t, + pub kind: git_rebase_operation_t, pub id: git_oid, pub exec: *const c_char, } diff --git a/src/rebase.rs b/src/rebase.rs index 959ef23405..b10ec310f7 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -279,7 +279,7 @@ impl<'rebase> RebaseOperation<'rebase> { /// The type of rebase operation pub fn kind(&self) -> Option { unsafe { - RebaseOperationType::from_raw((*self.raw)._type) + RebaseOperationType::from_raw((*self.raw).kind) } } diff --git a/systest/build.rs b/systest/build.rs index 67faeb5637..25a340ba0b 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -23,6 +23,10 @@ fn main() { _ => f.to_string(), } }); + cfg.skip_field(|struct_, f| { + // this field is marked as const which ctest complains about + struct_ == "git_rebase_operation" && f == "id" + }); cfg.skip_signededness(|s| { match s { s if s.ends_with("_cb") => true, From 702af2d6757ace5cb8e275ecada330d44c85f978 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 13 Dec 2018 11:02:27 -0800 Subject: [PATCH 310/860] Bump libgit2-sys to 0.7.11 --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8f5689058f..5688892c93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ url = "1.0" bitflags = "1.0" libc = "0.2" log = "0.4" -libgit2-sys = { path = "libgit2-sys", version = "0.7.10" } +libgit2-sys = { path = "libgit2-sys", version = "0.7.11" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index d0c5e5f790..686806097b 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.10" +version = "0.7.11" authors = ["Alex Crichton "] links = "git2" build = "build.rs" From 905d596e22b95805024fa7ab171bddcbb45f3cf9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 13 Dec 2018 11:03:58 -0800 Subject: [PATCH 311/860] Bump git2-curl to 0.9.0 --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 707be44a1b..e67911dca2 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.9.2" +version = "0.9.0" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/git2-rs" From c537ef262d95cfc6589597414a719a20408e6747 Mon Sep 17 00:00:00 2001 From: iancormac84 Date: Fri, 14 Dec 2018 20:11:50 -0400 Subject: [PATCH 312/860] Implemented wrapper for git_index_conflict_iterator. --- libgit2-sys/lib.rs | 14 +++++++++++ src/index.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 7bede4e4be..8dfe91b89f 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -56,6 +56,7 @@ pub enum git_commit {} pub enum git_config {} pub enum git_config_iterator {} pub enum git_index {} +pub enum git_index_conflict_iterator {} pub enum git_object {} pub enum git_reference {} pub enum git_reference_iterator {} @@ -2234,6 +2235,19 @@ extern { ancestor_entry: *const git_index_entry, our_entry: *const git_index_entry, their_entry: *const git_index_entry) -> c_int; + pub fn git_index_conflict_remove(index: *mut git_index, path: *const c_char) -> c_int; + pub fn git_index_conflict_get(ancestor_out: *mut *mut git_index_entry, + our_out: *mut *mut git_index_entry, + their_out: *mut *mut git_index_entry, + index: *mut git_index, + path: *const c_char) -> c_int; + pub fn git_index_conflict_iterator_new(iter: *mut *mut git_index_conflict_iterator, + index: *mut git_index) -> c_int; + pub fn git_index_conflict_next(ancestor_out: *mut *mut git_index_entry, + our_out: *mut *mut git_index_entry, + their_out: *mut *mut git_index_entry, + iter: *mut git_index_conflict_iterator) -> c_int; + pub fn git_index_conflict_iterator_free(iter: *mut git_index_conflict_iterator); pub fn git_index_clear(index: *mut git_index) -> c_int; pub fn git_index_entry_stage(entry: *const git_index_entry) -> c_int; pub fn git_index_entrycount(entry: *const git_index) -> size_t; diff --git a/src/index.rs b/src/index.rs index 6867a3d68d..76f023e7fd 100644 --- a/src/index.rs +++ b/src/index.rs @@ -23,6 +23,24 @@ pub struct IndexEntries<'index> { index: &'index Index, } +/// An iterator over the conflicting entries in an index +pub struct IndexConflicts<'index> { + conflict_iter: *mut raw::git_index_conflict_iterator, + _marker: marker::PhantomData<&'index Index>, +} + +/// A structure to represent the information returned when a conflict is detected in an index entry +pub struct IndexConflict { + /// The ancestor index entry of the two conflicting index entries + pub ancestor: IndexEntry, + /// The index entry originating from the user's copy of the repository. + /// Its contents conflict with 'their' index entry + pub our: IndexEntry, + /// The index entry originating from the external repository. + /// Its contents conflict with 'our' index entry + pub their: IndexEntry, +} + /// A callback function to filter index matches. /// /// Used by `Index::{add_all,remove_all,update_all}`. The first argument is the @@ -303,6 +321,16 @@ impl Index { IndexEntries { range: 0..self.len(), index: self } } + /// Get an iterator over the index entries that have conflicts + pub fn conflicts(&self) -> Result { + ::init(); + let mut conflict_iter = ptr::null_mut(); + unsafe { + try_call!(raw::git_index_conflict_iterator_new(&mut conflict_iter, self.raw)); + Ok(Binding::from_raw(conflict_iter)) + } + } + /// Get one of the entries in the index by its path. pub fn get_path(&self, path: &Path, stage: i32) -> Option { let path = path.into_c_string().unwrap(); @@ -500,6 +528,18 @@ impl Binding for Index { fn raw(&self) -> *mut raw::git_index { self.raw } } +impl<'index> Binding for IndexConflicts<'index> { + type Raw = *mut raw::git_index_conflict_iterator; + + unsafe fn from_raw(raw: *mut raw::git_index_conflict_iterator) -> IndexConflicts<'index> { + IndexConflicts { + conflict_iter: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_index_conflict_iterator { self.conflict_iter } +} + extern fn index_matched_path_cb(path: *const c_char, matched_pathspec: *const c_char, payload: *mut c_void) -> c_int { @@ -520,6 +560,12 @@ impl Drop for Index { } } +impl<'index> Drop for IndexConflicts<'index> { + fn drop(&mut self) { + unsafe { raw::git_index_conflict_iterator_free(self.conflict_iter) } + } +} + impl<'index> Iterator for IndexEntries<'index> { type Item = IndexEntry; fn next(&mut self) -> Option { @@ -527,6 +573,19 @@ impl<'index> Iterator for IndexEntries<'index> { } } +impl<'index> Iterator for IndexConflicts<'index> { + type Item = Result; + fn next(&mut self) -> Option> { + let mut ancestor = ptr::null_mut(); + let mut our = ptr::null_mut(); + let mut their = ptr::null_mut(); + unsafe { + try_call_iter!(raw::git_index_conflict_next(&mut ancestor, &mut our, &mut their, self.conflict_iter)); + Some(Ok(IndexConflict { ancestor: IndexEntry::from_raw(*ancestor), our: IndexEntry::from_raw(*our), their: IndexEntry::from_raw(*their) })) + } + } +} + impl Binding for IndexEntry { type Raw = raw::git_index_entry; diff --git a/src/lib.rs b/src/lib.rs index b2c1b09005..7960bd8af0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,7 @@ pub use diff::{Diff, DiffDelta, DiffFile, DiffOptions, Deltas}; pub use diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind}; pub use diff::{DiffLine, DiffHunk, DiffStats, DiffFindOptions}; pub use error::Error; -pub use index::{Index, IndexEntry, IndexEntries, IndexMatchedPath}; +pub use index::{Index, IndexConflict, IndexConflicts, IndexEntry, IndexEntries, IndexMatchedPath}; pub use merge::{AnnotatedCommit, MergeOptions}; pub use message::{message_prettify, DEFAULT_COMMENT_CHAR}; pub use note::{Note, Notes}; From 79896322c1fecb8aac9d4eb7c0aedc6412fcc825 Mon Sep 17 00:00:00 2001 From: iancormac84 Date: Sat, 15 Dec 2018 12:17:25 -0400 Subject: [PATCH 313/860] Add forgotten reference to marker module. --- src/index.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.rs b/src/index.rs index 76f023e7fd..e42aa14a01 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1,4 +1,5 @@ use std::ffi::{CStr, OsString, CString}; +use std::marker; use std::ops::Range; use std::path::Path; use std::ptr; From 2c6ba1cbca2a69207e38b42f0d8c85657da33003 Mon Sep 17 00:00:00 2001 From: iancormac84 Date: Sat, 15 Dec 2018 17:15:01 -0400 Subject: [PATCH 314/860] Changed signatures on git_index_conflict_get and git_index_conflict_next. --- libgit2-sys/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 8dfe91b89f..b1c4bdf5eb 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2236,16 +2236,16 @@ extern { our_entry: *const git_index_entry, their_entry: *const git_index_entry) -> c_int; pub fn git_index_conflict_remove(index: *mut git_index, path: *const c_char) -> c_int; - pub fn git_index_conflict_get(ancestor_out: *mut *mut git_index_entry, - our_out: *mut *mut git_index_entry, - their_out: *mut *mut git_index_entry, + pub fn git_index_conflict_get(ancestor_out: *mut *const git_index_entry, + our_out: *mut *const git_index_entry, + their_out: *mut *const git_index_entry, index: *mut git_index, path: *const c_char) -> c_int; pub fn git_index_conflict_iterator_new(iter: *mut *mut git_index_conflict_iterator, index: *mut git_index) -> c_int; - pub fn git_index_conflict_next(ancestor_out: *mut *mut git_index_entry, - our_out: *mut *mut git_index_entry, - their_out: *mut *mut git_index_entry, + pub fn git_index_conflict_next(ancestor_out: *mut *const git_index_entry, + our_out: *mut *const git_index_entry, + their_out: *mut *const git_index_entry, iter: *mut git_index_conflict_iterator) -> c_int; pub fn git_index_conflict_iterator_free(iter: *mut git_index_conflict_iterator); pub fn git_index_clear(index: *mut git_index) -> c_int; From 2c9269c1fff48e7aed6776ce88bbfa205cff8a75 Mon Sep 17 00:00:00 2001 From: iancormac84 Date: Sat, 15 Dec 2018 17:54:18 -0400 Subject: [PATCH 315/860] Add type annotations to three raw pointers. --- src/index.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/index.rs b/src/index.rs index e42aa14a01..1090ff244c 100644 --- a/src/index.rs +++ b/src/index.rs @@ -577,9 +577,9 @@ impl<'index> Iterator for IndexEntries<'index> { impl<'index> Iterator for IndexConflicts<'index> { type Item = Result; fn next(&mut self) -> Option> { - let mut ancestor = ptr::null_mut(); - let mut our = ptr::null_mut(); - let mut their = ptr::null_mut(); + let mut ancestor: *const raw::git_index_entry = ptr::null_mut(); + let mut our: *const raw::git_index_entry = ptr::null_mut(); + let mut their: *const raw::git_index_entry = ptr::null_mut(); unsafe { try_call_iter!(raw::git_index_conflict_next(&mut ancestor, &mut our, &mut their, self.conflict_iter)); Some(Ok(IndexConflict { ancestor: IndexEntry::from_raw(*ancestor), our: IndexEntry::from_raw(*our), their: IndexEntry::from_raw(*their) })) From 269060c876270a985e2d336b67d746096637acbb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 17 Dec 2018 08:53:34 -0800 Subject: [PATCH 316/860] Touch up some style --- src/index.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/index.rs b/src/index.rs index 1090ff244c..1071db3978 100644 --- a/src/index.rs +++ b/src/index.rs @@ -577,12 +577,21 @@ impl<'index> Iterator for IndexEntries<'index> { impl<'index> Iterator for IndexConflicts<'index> { type Item = Result; fn next(&mut self) -> Option> { - let mut ancestor: *const raw::git_index_entry = ptr::null_mut(); - let mut our: *const raw::git_index_entry = ptr::null_mut(); - let mut their: *const raw::git_index_entry = ptr::null_mut(); + let mut ancestor = ptr::null(); + let mut our = ptr::null(); + let mut their = ptr::null(); unsafe { - try_call_iter!(raw::git_index_conflict_next(&mut ancestor, &mut our, &mut their, self.conflict_iter)); - Some(Ok(IndexConflict { ancestor: IndexEntry::from_raw(*ancestor), our: IndexEntry::from_raw(*our), their: IndexEntry::from_raw(*their) })) + try_call_iter!(raw::git_index_conflict_next( + &mut ancestor, + &mut our, + &mut their, + self.conflict_iter + )); + Some(Ok(IndexConflict { + ancestor: IndexEntry::from_raw(*ancestor), + our: IndexEntry::from_raw(*our), + their: IndexEntry::from_raw(*their), + })) } } } From ad309add69b80227ef6f70e822c6fd708479549b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 20 Dec 2018 13:24:55 -0800 Subject: [PATCH 317/860] Bump minimum version --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2f0fd92518..4f33d83dc1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ git: matrix: include: - - rust: 1.26.0 + - rust: 1.30.0 - rust: stable - os: osx rust: stable From 5bfdfa20e225e67fcf9711d352d17572579a8dc2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 2 Jan 2019 13:50:27 -0800 Subject: [PATCH 318/860] Update travis config --- .travis.yml | 17 ++++++++--------- README.md | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4f33d83dc1..03e0dccea3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,15 +14,18 @@ matrix: - rust: beta - rust: nightly - - rust: nightly - before_script: - - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH + - name: "master doc to gh-pages" + rust: nightly script: - cargo doc --no-deps - cargo doc --manifest-path=git2-curl/Cargo.toml --no-deps - cargo doc --manifest-path=libgit2-sys/Cargo.toml --no-deps - after_success: - - travis-cargo --only nightly doc-upload + deploy: + provider: script + script: curl -LsSf https://git.io/fhJ8n | rustc - && (cd target/doc && ../../rust_out) + skip_cleanup: true + on: + branch: master script: - git submodule update --init @@ -34,10 +37,6 @@ script: cargo test --manifest-path git2-curl/Cargo.toml; fi -env: - global: - secure: "SVk5cv4VnBQAoaBXt9pIHk+FQ7Z58zT5EaPo7Ac81LltKztwHovhN/R1otKzgrAJqFsZ/nKR4cGyQGbYtfVJcsqweQVM75LI6Oh6lYyEdfX211ZI3SWQ50JO93CmwLtanC5UpECdXvJLCgXrHGJXuL1oi7hySGy47/yQlKH6eaM=" - notifications: email: on_success: never diff --git a/README.md b/README.md index 83c158607f..fbc3e0caf8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # git2-rs -[![Build Status](https://travis-ci.org/alexcrichton/git2-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/git2-rs) +[![Build Status](https://travis-ci.com/alexcrichton/git2-rs.svg?branch=master)](https://travis-ci.com/alexcrichton/git2-rs) [![Build Status](https://ci.appveyor.com/api/projects/status/6vem3xgno2kuxnfm?svg=true)](https://ci.appveyor.com/project/alexcrichton/git2-rs) [Documentation](https://docs.rs/git2) From bd04fa73d86ae94ed7266e78ec53818bb2c9b29d Mon Sep 17 00:00:00 2001 From: Akhil kp Date: Sun, 6 Jan 2019 22:39:12 +0530 Subject: [PATCH 319/860] Use Option for author and message in rebase_commit --- src/rebase.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/src/rebase.rs b/src/rebase.rs index b10ec310f7..9aeaf2d2e5 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -151,12 +151,13 @@ impl <'repo> Rebase<'repo> { /// Commits the current patch. You must have resolved any conflicts that /// were introduced during the patch application from the `git_rebase_next` - /// invocation. - pub fn commit(&mut self, author: &Signature, committer: &Signature, message: &str) -> Result { + /// invocation. To keep the author and message from the original commit leave + /// them as None + pub fn commit(&mut self, author: Option<&Signature>, committer: &Signature, message: Option<&str>) -> Result { let mut id: raw::git_oid = unsafe { mem::zeroed() }; - let message = try!(CString::new(message)); + let message = try!(::opt_cstr(message)); unsafe { - try_call!(raw::git_rebase_commit(&mut id, self.raw, author.raw(), committer.raw(), ptr::null(), message)); + try_call!(raw::git_rebase_commit(&mut id, self.raw, author.map(|a| a.raw()), committer.raw(), ptr::null(), message)); Ok(Binding::from_raw(&id as *const _)) } } @@ -313,7 +314,8 @@ impl<'rebase> Binding for RebaseOperation<'rebase> { #[cfg(test)] mod tests { - use {RebaseOptions, RebaseOperationType}; + use std::{fs, path}; + use {RebaseOptions, RebaseOperationType, Signature}; #[test] fn smoke() { @@ -351,4 +353,59 @@ mod tests { assert!(op.is_none()); } } + + #[test] + fn keeping_original_author_msg() { + let (td, repo) = ::test::repo_init(); + let head_target = repo.head().unwrap().target().unwrap(); + let tip = repo.find_commit(head_target).unwrap(); + let sig = Signature::now("testname", "testemail").unwrap(); + let mut index = repo.index().unwrap(); + + fs::File::create(td.path().join("file_a")).unwrap(); + index.add_path(path::Path::new("file_a")).unwrap(); + index.write().unwrap(); + let tree_id_a = index.write_tree().unwrap(); + let tree_a = repo.find_tree(tree_id_a).unwrap(); + let c1 = repo + .commit(Some("refs/heads/master"), &sig, &sig, "A", &tree_a, &[&tip]) + .unwrap(); + let c1 = repo.find_commit(c1).unwrap(); + + fs::File::create(td.path().join("file_b")).unwrap(); + index.add_path(path::Path::new("file_b")).unwrap(); + index.write().unwrap(); + let tree_id_b = index.write_tree().unwrap(); + let tree_b = repo.find_tree(tree_id_b).unwrap(); + let c2 = repo + .commit(Some("refs/heads/master"), &sig, &sig, "B", &tree_b, &[&c1]) + .unwrap(); + + let branch = repo.find_annotated_commit(c2).unwrap(); + let upstream = repo.find_annotated_commit(tip.id()).unwrap(); + let mut opts: RebaseOptions = Default::default(); + let mut rebase = repo + .rebase(Some(&branch), Some(&upstream), None, Some(&mut opts)) + .unwrap(); + + assert_eq!(rebase.len(), 2); + + { + rebase.next().unwrap().unwrap(); + let id = rebase.commit(None, &sig, None).unwrap(); + let commit = repo.find_commit(id).unwrap(); + assert_eq!(commit.message(), Some("A")); + assert_eq!(commit.author().name(), Some("testname")); + assert_eq!(commit.author().email(), Some("testemail")); + } + + { + rebase.next().unwrap().unwrap(); + let id = rebase.commit(None, &sig, None).unwrap(); + let commit = repo.find_commit(id).unwrap(); + assert_eq!(commit.message(), Some("B")); + assert_eq!(commit.author().name(), Some("testname")); + assert_eq!(commit.author().email(), Some("testemail")); + } + } } From d54d1b2cf7460801b85b219cea2b7abfefe1cea0 Mon Sep 17 00:00:00 2001 From: Akhil kp Date: Tue, 8 Jan 2019 21:08:02 +0530 Subject: [PATCH 320/860] signature should be optional in rebase_finish --- src/rebase.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rebase.rs b/src/rebase.rs index 9aeaf2d2e5..ea2344198c 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -174,9 +174,9 @@ impl <'repo> Rebase<'repo> { /// Finishes a rebase that is currently in progress once all patches have /// been applied. - pub fn finish(&mut self, signature: &Signature) -> Result<(), Error> { + pub fn finish(&mut self, signature: Option<&Signature>) -> Result<(), Error> { unsafe { - try_call!(raw::git_rebase_finish(self.raw, signature.raw())); + try_call!(raw::git_rebase_finish(self.raw, signature.map(|s| s.raw()))); } Ok(()) @@ -407,5 +407,6 @@ mod tests { assert_eq!(commit.author().name(), Some("testname")); assert_eq!(commit.author().email(), Some("testemail")); } + rebase.finish(None).unwrap(); } } From 637c20a33cf4171710fe3fd596af277d808513aa Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 17 Jan 2019 22:49:28 +0200 Subject: [PATCH 321/860] readme: show current latest version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fbc3e0caf8..9368115cf2 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ libgit2 bindings for Rust ```toml [dependencies] -git2 = "0.7" +git2 = "0.8" ``` ## Version of libgit2 From 2201885bb6e1ff92efa8ee7d11057a8d3f1a99a4 Mon Sep 17 00:00:00 2001 From: Remy Suen Date: Thu, 24 Jan 2019 21:30:30 -0500 Subject: [PATCH 322/860] Fix spelling typo Signed-off-by: Remy Suen --- libgit2-sys/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 20806c72a4..aad5b9e2ab 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -41,7 +41,7 @@ fn main() { add_c_files(&mut cfg, "libgit2/src".as_ref()); add_c_files(&mut cfg, "libgit2/src/xdiff".as_ref()); - // These are activated by feautres, but they're all unconditionally always + // These are activated by features, but they're all unconditionally always // compiled apparently and have internal #define's to make sure they're // compiled correctly. add_c_files(&mut cfg, "libgit2/src/transports".as_ref()); From 5ef7483bf79d8687179a190500cf9b7179b2ba15 Mon Sep 17 00:00:00 2001 From: Matt Kraai Date: Mon, 11 Feb 2019 14:57:55 -0800 Subject: [PATCH 323/860] Fix misspelling --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index a3348bd864..2ca7541ad0 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2167,7 +2167,7 @@ impl RepositoryInitOptions { self.flag(raw::GIT_REPOSITORY_INIT_MKDIR, enabled) } - /// Recursively make all components of the repo and workdir path sas + /// Recursively make all components of the repo and workdir path as /// necessary. /// /// Defaults to true. From f4b5516a2f2a61baa2e3f357400a9dad56b3c35a Mon Sep 17 00:00:00 2001 From: Emil Lundberg Date: Wed, 13 Feb 2019 01:01:18 +0100 Subject: [PATCH 324/860] Relax self-borrow lifetime in Branch.upstream() The following code currently does not compile: ```rust fn get_upstreams<'repo>(repo: &'repo git2::Repository) -> Vec<(git2::Branch<'repo>, Option>)> { repo .branches(None) // pub fn branches(&self, filter: Option) -> Result .unwrap() // git2::Branches<'a>: Iterator, git2::BranchType), git2::Error>> .flatten() // Iterator, git2::BranchType)> .map(|(branch, _): (git2::Branch<'repo>, _)| { let upstream: Option> = branch .upstream() // pub fn upstream<'a>(&'a self) -> Result, Error> .ok(); (branch, upstream) }) // Iterator, git2::Branch<'repo>)> .collect() } ``` Error: ``` error[E0597]: `branch` does not live long enough --> src/config/data/project.rs:49:55 | 49 | let upstream: Option> = branch.upstream().ok(); | ^^^^^^ borrowed value does not live long enough ... 58 | }) | - borrowed value only lives until here | note: borrowed value must be valid for the lifetime 'repo as defined on the method body at 39:30... --> src/config/data/project.rs:39:30 | 39 | fn local_branches_internal<'repo>(&self, repo: &'repo git2::Repository) -> Result, Option>)>, git2::Error> { ``` This is because the `.upstream()` method is declared with the same self-borrow lifetime as the return value: ```rust pub fn upstream<'a>(&'a self) -> Result, Error> { /* ... */ } ``` which means that the `.upstream()` call is still borrowing `self` even after it returns, even though it returns an owned value and not a reference. Relaxing the self-borrow lifetime allows the above code sample to compile successfully. The lifetime of the (maybe) returned upstream `Branch` will also be that of the repository, but otherwise unrelated to the lifetime of the `Branch` that constructed it. --- src/branch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/branch.rs b/src/branch.rs index 3f035ed0d3..ee95b7e411 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -73,7 +73,7 @@ impl<'repo> Branch<'repo> { /// Return the reference supporting the remote tracking branch, given a /// local branch reference. - pub fn upstream<'a>(&'a self) -> Result, Error> { + pub fn upstream<'a>(&self) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_branch_upstream(&mut ret, &*self.get().raw())); From 16eb917b040204ede89d03f68019439092eecfad Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 15 Feb 2019 13:48:45 -0800 Subject: [PATCH 325/860] Take over maintenance and update URLs to rust-lang/git2-rs Thanks to Alex Crichton for his incredible work on git2-rs over the years. --- Cargo.toml | 8 +++----- README.md | 5 +---- git2-curl/Cargo.toml | 5 ++--- libgit2-sys/Cargo.toml | 4 ++-- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5688892c93..c3b7cb50a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,12 +2,11 @@ name = "git2" version = "0.8.0" -authors = ["Alex Crichton "] +authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" keywords = ["git"] -repository = "https://github.com/alexcrichton/git2-rs" -homepage = "https://github.com/alexcrichton/git2-rs" +repository = "https://github.com/rust-lang/git2-rs" documentation = "https://docs.rs/git2" description = """ Bindings to libgit2 for interoperating with git repositories. This library is @@ -17,8 +16,7 @@ repositories. categories = ["api-bindings"] [badges] -travis-ci = { repository = "alexcrichton/git2-rs" } -appveyor = { repository = "alexcrichton/git2-rs" } +travis-ci = { repository = "rust-lang/git2-rs" } [dependencies] url = "1.0" diff --git a/README.md b/README.md index 9368115cf2..9ce9795057 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ # git2-rs -[![Build Status](https://travis-ci.com/alexcrichton/git2-rs.svg?branch=master)](https://travis-ci.com/alexcrichton/git2-rs) -[![Build Status](https://ci.appveyor.com/api/projects/status/6vem3xgno2kuxnfm?svg=true)](https://ci.appveyor.com/project/alexcrichton/git2-rs) - [Documentation](https://docs.rs/git2) libgit2 bindings for Rust @@ -21,7 +18,7 @@ library, the libgit2-sys crate will figure that and/or build that for you. ## Building git2-rs ```sh -$ git clone https://github.com/alexcrichton/git2-rs +$ git clone https://github.com/rust-lang/git2-rs $ cd git2-rs $ cargo build ``` diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index e67911dca2..d90d8b79ab 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -2,10 +2,9 @@ name = "git2-curl" version = "0.9.0" -authors = ["Alex Crichton "] +authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" -repository = "https://github.com/alexcrichton/git2-rs" -homepage = "https://github.com/alexcrichton/git2-rs" +repository = "https://github.com/rust-lang/git2-rs" documentation = "https://docs.rs/git2-curl" description = """ Backend for an HTTP transport in libgit2 powered by libcurl. diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 686806097b..2626b69a75 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "libgit2-sys" version = "0.7.11" -authors = ["Alex Crichton "] +authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" -repository = "https://github.com/alexcrichton/git2-rs" +repository = "https://github.com/rust-lang/git2-rs" license = "MIT/Apache-2.0" description = "Native bindings to the libgit2 library" exclude = [ From 17ad2451f02b5778395a021b11be71e0ef33d1e0 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 15 Feb 2019 13:49:47 -0800 Subject: [PATCH 326/860] .travis.yml: Drop gh-pages hook in favor of docs.rs --- .travis.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 03e0dccea3..d14cd30e72 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,19 +14,6 @@ matrix: - rust: beta - rust: nightly - - name: "master doc to gh-pages" - rust: nightly - script: - - cargo doc --no-deps - - cargo doc --manifest-path=git2-curl/Cargo.toml --no-deps - - cargo doc --manifest-path=libgit2-sys/Cargo.toml --no-deps - deploy: - provider: script - script: curl -LsSf https://git.io/fhJ8n | rustc - && (cd target/doc && ../../rust_out) - skip_cleanup: true - on: - branch: master - script: - git submodule update --init - cargo test --no-default-features From 718799c265d4e6fea635906cb57379a441021f3c Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 15 Feb 2019 13:57:54 -0800 Subject: [PATCH 327/860] README.md: Document Rust version requirements --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 9ce9795057..462193b331 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,12 @@ libgit2 bindings for Rust git2 = "0.8" ``` +## Rust version requirements + +git2-rs works with stable Rust, and typically works with the most recent prior +stable release as well. Check [.travis.yml](.travis.yml) to see the oldest +version of Rust known to pass tests. + ## Version of libgit2 Currently this library requires libgit2 0.25.1. The source for libgit2 is From fa1dfb6a045fa5e9614e1af30b98005f18c9054a Mon Sep 17 00:00:00 2001 From: Harry Marr Date: Tue, 19 Feb 2019 12:37:11 -0500 Subject: [PATCH 328/860] Don't quote absolute path helper commands Quoting treats the full command as the path to binary, which prevents arguments from being provided. According to the [Git documentation][git-docs] arguments should be accepted. This also [matches the behaviour][git-source] of git itself. [git-docs]: https://git-scm.com/docs/api-credentials#_credential_helpers [git-source]: https://github.com/git/git/blob/ca1b4116483b397e78483376296bcd23916ab553/credential.c#L258-L261 --- src/cred.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/cred.rs b/src/cred.rs index e7cf81c002..37d3a228d4 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -257,7 +257,7 @@ impl CredentialHelper { self.commands.push(cmd[1..].to_string()); } else if cmd.starts_with('/') || cmd.starts_with('\\') || cmd[1..].starts_with(":\\") { - self.commands.push(format!("\"{}\"", cmd)); + self.commands.push(cmd.to_string()); } else { self.commands.push(format!("git credential-{}", cmd)); } @@ -522,6 +522,26 @@ echo username=c .execute().is_none()); } + #[test] + fn credential_helper7() { + let td = TempDir::new("git2-rs").unwrap(); + let path = td.path().join("script"); + File::create(&path).unwrap().write(br"\ +#!/bin/sh +echo username=$1 +echo password=$2 +").unwrap(); + chmod(&path); + let cfg = test_cfg! { + "credential.helper" => &format!("{} a b", path.display()) + }; + let (u, p) = CredentialHelper::new("https://example.com/foo/bar") + .config(&cfg) + .execute().unwrap(); + assert_eq!(u, "a"); + assert_eq!(p, "b"); + } + #[test] fn ssh_key_from_memory() { let cred = Cred::ssh_key_from_memory( From 86b764a932caaceacc861cb2e49384aa0a72556f Mon Sep 17 00:00:00 2001 From: Damian Carrillo Date: Tue, 26 Feb 2019 23:05:06 -0600 Subject: [PATCH 329/860] Fixing misspelling --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 2ca7541ad0..263beb7006 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1484,7 +1484,7 @@ impl Repository { /// after this completes, resolve any conflicts and prepare a commit. /// /// For compatibility with git, the repository is put into a merging state. - /// Once the commit is done (or if the uses wishes to abort), you should + /// Once the commit is done (or if the user wishes to abort), you should /// clear this state by calling git_repository_state_cleanup(). pub fn merge(&self, annotated_commits: &[&AnnotatedCommit], From 43432cd22161149057e661861dbe3f08394f500c Mon Sep 17 00:00:00 2001 From: Ross MacArthur Date: Fri, 15 Mar 2019 13:57:34 +0200 Subject: [PATCH 330/860] Fix git-dir CLI option in rev-parse example --- examples/rev-parse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rev-parse.rs b/examples/rev-parse.rs index f2416f7b40..178cd2d3e2 100644 --- a/examples/rev-parse.rs +++ b/examples/rev-parse.rs @@ -58,7 +58,7 @@ fn main() { usage: rev-parse [options] Options: - --git-dir directory for the git repository to check + --git-dir

directory of the git repository to check "; let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) From 71115e9229f23156db42fde09086ee2664c89168 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Fri, 26 Apr 2019 11:23:56 -0700 Subject: [PATCH 331/860] Fix incorrect method name in Branch doc. There is no `unwrap`. The method is called `into_reference`. --- src/branch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/branch.rs b/src/branch.rs index 3f035ed0d3..9f1e523c0d 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -9,7 +9,7 @@ use util::Binding; /// A structure to represent a git [branch][1] /// /// A branch is currently just a wrapper to an underlying `Reference`. The -/// reference can be accessed through the `get` and `unwrap` methods. +/// reference can be accessed through the `get` and `into_reference` methods. /// /// [1]: http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is pub struct Branch<'repo> { From 228ab8f2c13574cc20d43a26c8d5b1a83d21ba7a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 15 May 2019 17:30:44 -0700 Subject: [PATCH 332/860] Update CI rustc version. Bump minimum version to get CI passing. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d14cd30e72..1ec058b16c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ git: matrix: include: - - rust: 1.30.0 + - rust: 1.32.0 - rust: stable - os: osx rust: stable From ddca4c3694bb3b40dfaee835e2b2dfb6eb51e89f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 15 May 2019 17:47:11 -0700 Subject: [PATCH 333/860] Fix warning starting with 1.35. --- src/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test.rs b/src/test.rs index 4f8813fdad..00b5f46d80 100644 --- a/src/test.rs +++ b/src/test.rs @@ -44,7 +44,7 @@ pub fn realpath(original: &Path) -> io::Result { pub fn realpath(original: &Path) -> io::Result { use std::ffi::{CStr, OsString, CString}; use std::os::unix::prelude::*; - use libc::{self, c_char}; + use libc::c_char; extern { fn realpath(name: *const c_char, resolved: *mut c_char) -> *mut c_char; } From 4c87bf520325a705c4e4508f32e6875f3cd3536c Mon Sep 17 00:00:00 2001 From: Kevin Jackson Date: Fri, 10 May 2019 08:38:42 +0100 Subject: [PATCH 334/860] use ? instead of try! macro --- examples/log.rs | 54 ++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/examples/log.rs b/examples/log.rs index 70e8145da2..4a3912ebfc 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -49,8 +49,8 @@ struct Args { fn run(args: &Args) -> Result<(), Error> { let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); - let repo = try!(Repository::open(path)); - let mut revwalk = try!(repo.revwalk()); + let repo = Repository::open(path)?; + let mut revwalk = repo.revwalk()?; // Prepare the revwalk based on CLI parameters let base = if args.flag_reverse {git2::Sort::REVERSE} else {git2::Sort::NONE}; @@ -63,27 +63,27 @@ fn run(args: &Args) -> Result<(), Error> { }); for commit in &args.arg_commit { if commit.starts_with('^') { - let obj = try!(repo.revparse_single(&commit[1..])); - try!(revwalk.hide(obj.id())); + let obj = repo.revparse_single(&commit[1..])?; + revwalk.hide(obj.id())?; continue } - let revspec = try!(repo.revparse(commit)); + let revspec = repo.revparse(commit)?; if revspec.mode().contains(git2::RevparseMode::SINGLE) { - try!(revwalk.push(revspec.from().unwrap().id())); + revwalk.push(revspec.from().unwrap().id())?; } else { let from = revspec.from().unwrap().id(); let to = revspec.to().unwrap().id(); - try!(revwalk.push(to)); + revwalk.push(to)?; if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { - let base = try!(repo.merge_base(from, to)); - let o = try!(repo.find_object(base, Some(ObjectType::Commit))); - try!(revwalk.push(o.id())); + let base = repo.merge_base(from, to)?; + let o = repo.find_object(base, Some(ObjectType::Commit))?; + revwalk.push(o.id())?; } - try!(revwalk.hide(from)); + revwalk.hide(from)?; } } if args.arg_commit.is_empty() { - try!(revwalk.push_head()); + revwalk.push_head()?; } // Prepare our diff options and pathspec matcher @@ -92,7 +92,7 @@ fn run(args: &Args) -> Result<(), Error> { diffopts.pathspec(spec); diffopts2.pathspec(spec); } - let ps = try!(Pathspec::new(args.arg_spec.iter())); + let ps = Pathspec::new(args.arg_spec.iter())?; // Filter our revwalk based on the CLI parameters macro_rules! filter_try { @@ -130,26 +130,26 @@ fn run(args: &Args) -> Result<(), Error> { // print! for commit in revwalk { - let commit = try!(commit); + let commit = commit?; print_commit(&commit); if !args.flag_patch || commit.parents().len() > 1 { continue } let a = if commit.parents().len() == 1 { - let parent = try!(commit.parent(0)); - Some(try!(parent.tree())) + let parent = commit.parent(0)?; + Some(parent.tree()?) } else { None }; - let b = try!(commit.tree()); - let diff = try!(repo.diff_tree_to_tree(a.as_ref(), Some(&b), - Some(&mut diffopts2))); - try!(diff.print(DiffFormat::Patch, |_delta, _hunk, line| { + let b = commit.tree()?; + let diff = repo.diff_tree_to_tree(a.as_ref(), Some(&b), + Some(&mut diffopts2))?; + diff.print(DiffFormat::Patch, |_delta, _hunk, line| { match line.origin() { ' ' | '+' | '-' => print!("{}", line.origin()), _ => {} } print!("{}", str::from_utf8(line.content()).unwrap()); true - })); + })?; } Ok(()) @@ -181,18 +181,18 @@ fn print_commit(commit: &Commit) { for id in commit.parent_ids() { print!(" {:.8}", id); } - println!(""); + println!(); } let author = commit.author(); println!("Author: {}", author); print_time(&author.when(), "Date: "); - println!(""); + println!(); for line in String::from_utf8_lossy(commit.message_bytes()).lines() { println!(" {}", line); } - println!(""); + println!(); } fn print_time(time: &Time, prefix: &str) { @@ -212,9 +212,9 @@ fn print_time(time: &Time, prefix: &str) { fn match_with_parent(repo: &Repository, commit: &Commit, parent: &Commit, opts: &mut DiffOptions) -> Result { - let a = try!(parent.tree()); - let b = try!(commit.tree()); - let diff = try!(repo.diff_tree_to_tree(Some(&a), Some(&b), Some(opts))); + let a = parent.tree()?; + let b = commit.tree()?; + let diff = repo.diff_tree_to_tree(Some(&a), Some(&b), Some(opts))?; Ok(diff.deltas().len() > 0) } From 1222d37137665feee6e7c3170d236941847c4764 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 16 May 2019 15:15:28 -0500 Subject: [PATCH 335/860] Set up CI with Azure Pipelines --- .travis.yml | 29 ----------------------- README.md | 2 ++ appveyor.yml | 19 --------------- azure-pipelines.yml | 49 +++++++++++++++++++++++++++++++++++++++ ci/azure-install-rust.yml | 23 ++++++++++++++++++ ci/azure-test-all.yml | 11 +++++++++ src/cred.rs | 11 ++++++--- src/panic.rs | 22 ------------------ 8 files changed, 93 insertions(+), 73 deletions(-) delete mode 100644 .travis.yml delete mode 100644 appveyor.yml create mode 100644 azure-pipelines.yml create mode 100644 ci/azure-install-rust.yml create mode 100644 ci/azure-test-all.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1ec058b16c..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -language: rust -git: - submodules: false - -matrix: - include: - - rust: 1.32.0 - - rust: stable - - os: osx - rust: stable - before_install: - - export OPENSSL_INCLUDE_DIR=`brew --prefix openssl`/include - - export OPENSSL_LIB_DIR=`brew --prefix openssl`/lib - - rust: beta - - rust: nightly - -script: - - git submodule update --init - - cargo test --no-default-features - - cargo test - - cargo run --manifest-path systest/Cargo.toml --release - - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then - cargo test --features unstable; - cargo test --manifest-path git2-curl/Cargo.toml; - fi - -notifications: - email: - on_success: never diff --git a/README.md b/README.md index 462193b331..21b43af80a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # git2-rs +[![Build Status](https://dev.azure.com/rust-lang/git2-rs/_apis/build/status/rust-lang.git2-rs?branchName=master)](https://dev.azure.com/rust-lang/git2-rs/_build/latest?definitionId=9&branchName=master) + [Documentation](https://docs.rs/git2) libgit2 bindings for Rust diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 0182bfd8b6..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,19 +0,0 @@ -environment: - matrix: - - TARGET: x86_64-pc-windows-msvc - - TARGET: i686-pc-windows-msvc -install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-$%7Benv:TARGET%7D.exe" - - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - - set PATH=%PATH%;C:\Program Files (x86)\Rust\bin - - if defined MSYS_BITS set PATH=C:\msys64\mingw%MSYS_BITS%\bin;C:\msys64\usr\bin;%PATH% - - set CARGO_TARGET_DIR=%APPVEYOR_BUILD_FOLDER%\target - - rustc -V - - cargo -V - -build: false - -test_script: - - cargo test --target %TARGET% - - cargo test --no-default-features --target %TARGET% - - cargo run --manifest-path systest/Cargo.toml --target %TARGET% diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000000..65091dfc00 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,49 @@ +trigger: + - master + +jobs: + - job: MSRV + pool: + vmImage: ubuntu-16.04 + steps: + - template: ci/azure-install-rust.yml + - script: cargo build + displayName: "Build crate" + variables: + TOOLCHAIN: 1.32.0 + + - job: Linux + pool: + vmImage: ubuntu-16.04 + steps: + - template: ci/azure-test-all.yml + strategy: + matrix: + stable: + TOOLCHAIN: stable + beta: + TOOLCHAIN: beta + nightly: + TOOLCHAIN: nightly + + - job: macOS + pool: + vmImage: macos-10.13 + steps: + - template: ci/azure-test-all.yml + strategy: + matrix: + x86_64: + TARGET: x86_64-apple-darwin + + - job: Windows + pool: + vmImage: vs2017-win2016 + steps: + - template: ci/azure-test-all.yml + strategy: + matrix: + x86_64-msvc: + TARGET: x86_64-pc-windows-msvc + i686-msvc: + TARGET: i686-pc-windows-msvc diff --git a/ci/azure-install-rust.yml b/ci/azure-install-rust.yml new file mode 100644 index 0000000000..fa7eae459b --- /dev/null +++ b/ci/azure-install-rust.yml @@ -0,0 +1,23 @@ +steps: + - bash: | + set -e + toolchain=$TOOLCHAIN + if [ "$toolchain" = "" ]; then + toolchain=stable + fi + curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $toolchain + echo "##vso[task.prependpath]$HOME/.cargo/bin" + displayName: Install rust (unix) + condition: ne( variables['Agent.OS'], 'Windows_NT' ) + + - script: | + curl -sSf -o rustup-init.exe https://win.rustup.rs + rustup-init.exe -y --default-toolchain stable-%TARGET% + echo ##vso[task.prependpath]%USERPROFILE%\.cargo\bin + displayName: Install rust (windows) + condition: eq( variables['Agent.OS'], 'Windows_NT' ) + + - script: | + rustc -Vv + cargo -V + displayName: Query rust and cargo versions diff --git a/ci/azure-test-all.yml b/ci/azure-test-all.yml new file mode 100644 index 0000000000..5f9124c302 --- /dev/null +++ b/ci/azure-test-all.yml @@ -0,0 +1,11 @@ +steps: + - template: azure-install-rust.yml + + - bash: cargo test --no-default-features + displayName: "cargo test --no-default-features" + - bash: cargo test + displayName: "cargo test" + - bash: cargo run --manifest-path systest/Cargo.toml + displayName: "run systest" + - bash: cargo test --manifest-path git2-curl/Cargo.toml + displayName: "test git2-curl" diff --git a/src/cred.rs b/src/cred.rs index 37d3a228d4..12ddcbdbce 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -408,7 +408,7 @@ impl CredentialHelper { } } -#[cfg(all(test, feature = "unstable"))] +#[cfg(test)] mod test { use std::env; use std::fs::File; @@ -467,6 +467,8 @@ mod test { #[test] fn credential_helper4() { + if cfg!(windows) { return } // shell scripts don't work on Windows + let td = TempDir::new("git2-rs").unwrap(); let path = td.path().join("script"); File::create(&path).unwrap().write(br"\ @@ -488,6 +490,7 @@ echo username=c #[test] fn credential_helper5() { + if cfg!(windows) { return } // shell scripts don't work on Windows let td = TempDir::new("git2-rs").unwrap(); let path = td.path().join("git-credential-script"); File::create(&path).unwrap().write(br"\ @@ -524,6 +527,7 @@ echo username=c #[test] fn credential_helper7() { + if cfg!(windows) { return } // shell scripts don't work on Windows let td = TempDir::new("git2-rs").unwrap(); let path = td.path().join("script"); File::create(&path).unwrap().write(br"\ @@ -543,6 +547,7 @@ echo password=$2 } #[test] + #[cfg(feature = "ssh")] fn ssh_key_from_memory() { let cred = Cred::ssh_key_from_memory( "test", @@ -551,7 +556,7 @@ echo password=$2 -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,818C7722D3B01F2161C2ACF6A5BBAAE8 - + 3Cht4QB3PcoQ0I55j1B3m2ZzIC/mrh+K5nQeA1Vy2GBTMyM7yqGHqTOv7qLhJscd H+cB0Pm6yCr3lYuNrcKWOCUto+91P7ikyARruHVwyIxKdNx15uNulOzQJHQWNbA4 RQHlhjON4atVo2FyJ6n+ujK6QiBg2PR5Vbbw/AtV6zBCFW3PhzDn+qqmHjpBFqj2 @@ -582,7 +587,7 @@ echo password=$2 Some("test123")); assert!(cred.is_ok()); } - + #[cfg(unix)] fn chmod(path: &Path) { diff --git a/src/panic.rs b/src/panic.rs index 35f2c09394..7444df1099 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -5,7 +5,6 @@ thread_local!(static LAST_ERROR: RefCell>> = { RefCell::new(None) }); -#[cfg(feature = "unstable")] pub fn wrap T + ::std::panic::UnwindSafe>(f: F) -> Option { use std::panic; if LAST_ERROR.with(|slot| slot.borrow().is_some()) { @@ -22,27 +21,6 @@ pub fn wrap T + ::std::panic::UnwindSafe>(f: F) -> Option { } } -#[cfg(not(feature = "unstable"))] -pub fn wrap T>(f: F) -> Option { - struct Bomb { - enabled: bool, - } - impl Drop for Bomb { - fn drop(&mut self) { - if !self.enabled { - return - } - panic!("callback has panicked, and continuing to unwind into C \ - is not safe, so aborting the process"); - - } - } - let mut bomb = Bomb { enabled: true }; - let ret = Some(f()); - bomb.enabled = false; - ret -} - pub fn check() { let err = LAST_ERROR.with(|slot| slot.borrow_mut().take()); if let Some(err) = err { From 2a1c92d10a62c5da72a5c7fe94be65901ccb9b8f Mon Sep 17 00:00:00 2001 From: iancormac84 Date: Sun, 10 Mar 2019 11:16:44 -0400 Subject: [PATCH 336/860] Amended IndexConflict to make it sensitive to the possibility that git_index_conflict_iterator returns a NULL pointer for one of the trio of IndexEntries. Also added Reference::find_reference_dwim to make it a little easier to find refs. --- libgit2-sys/lib.rs | 3 +++ src/index.rs | 21 +++++++++++++++------ src/repo.rs | 13 +++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index b1c4bdf5eb..d9d692cfb5 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1886,6 +1886,9 @@ extern { pub fn git_reference_lookup(out: *mut *mut git_reference, repo: *mut git_repository, name: *const c_char) -> c_int; + pub fn git_reference_dwim(out: *mut *mut git_reference, + repo: *mut git_repository, + refname: *const c_char) -> c_int; pub fn git_reference_name(r: *const git_reference) -> *const c_char; pub fn git_reference_name_to_id(out: *mut git_oid, repo: *mut git_repository, diff --git a/src/index.rs b/src/index.rs index 1071db3978..765a20c202 100644 --- a/src/index.rs +++ b/src/index.rs @@ -33,13 +33,13 @@ pub struct IndexConflicts<'index> { /// A structure to represent the information returned when a conflict is detected in an index entry pub struct IndexConflict { /// The ancestor index entry of the two conflicting index entries - pub ancestor: IndexEntry, + pub ancestor: Option, /// The index entry originating from the user's copy of the repository. /// Its contents conflict with 'their' index entry - pub our: IndexEntry, + pub our: Option, /// The index entry originating from the external repository. /// Its contents conflict with 'our' index entry - pub their: IndexEntry, + pub their: Option, } /// A callback function to filter index matches. @@ -588,9 +588,18 @@ impl<'index> Iterator for IndexConflicts<'index> { self.conflict_iter )); Some(Ok(IndexConflict { - ancestor: IndexEntry::from_raw(*ancestor), - our: IndexEntry::from_raw(*our), - their: IndexEntry::from_raw(*their), + ancestor: match ancestor.is_null() { + false => Some(IndexEntry::from_raw(*ancestor)), + true => None, + }, + our: match our.is_null() { + false => Some(IndexEntry::from_raw(*our)), + true => None, + }, + their: match their.is_null() { + false => Some(IndexEntry::from_raw(*their)), + true => None, + }, })) } } diff --git a/src/repo.rs b/src/repo.rs index 263beb7006..0972ca12cc 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1218,6 +1218,19 @@ impl Repository { } } + /// Lookup a reference to one of the objects in a repository. + /// `Repository::find_reference` with teeth; give the method your reference in + /// human-readable format e.g. 'master' instead of 'refs/heads/master', and it + /// will do-what-you-mean, returning the `Reference`. + pub fn find_reference_dwim(&self, refname: &str) -> Result { + let refname = try!(CString::new(refname)); + let mut raw = ptr::null_mut(); + unsafe { + try_call!(raw::git_reference_dwim(&mut raw, self.raw(), refname)); + Ok(Binding::from_raw(raw)) + } + } + /// Lookup a reference by name and resolve immediately to OID. /// /// This function provides a quick way to resolve a reference name straight From f35dd8fb8314532164beebc31a8abe878199f7f7 Mon Sep 17 00:00:00 2001 From: iancormac84 Date: Tue, 26 Mar 2019 18:13:41 -0400 Subject: [PATCH 337/860] Changed Repository::find_reference_dwim to Repository::resolve_reference_from_short_name. --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 0972ca12cc..4cb1b9c77b 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1222,7 +1222,7 @@ impl Repository { /// `Repository::find_reference` with teeth; give the method your reference in /// human-readable format e.g. 'master' instead of 'refs/heads/master', and it /// will do-what-you-mean, returning the `Reference`. - pub fn find_reference_dwim(&self, refname: &str) -> Result { + pub fn resolve_reference_from_short_name(&self, refname: &str) -> Result { let refname = try!(CString::new(refname)); let mut raw = ptr::null_mut(); unsafe { From 230262afe0cb1379fc7cfd8d82bb62be597978cd Mon Sep 17 00:00:00 2001 From: Silvus Date: Fri, 17 May 2019 19:50:31 +0200 Subject: [PATCH 338/860] Replaced link to .travis.yml in Readme with azure-pipelines.yml --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21b43af80a..124b209e29 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ git2 = "0.8" ## Rust version requirements git2-rs works with stable Rust, and typically works with the most recent prior -stable release as well. Check [.travis.yml](.travis.yml) to see the oldest +stable release as well. Check [azure-pipelines.yml](azure-pipelines.yml) to see the oldest version of Rust known to pass tests. ## Version of libgit2 From 3d823d3f28087be51fe373124783eea4bcaa9a5a Mon Sep 17 00:00:00 2001 From: Dan Rollo Date: Fri, 17 May 2019 15:34:20 -0400 Subject: [PATCH 339/860] update submodule libgit2 new commit to fix 'Host header omits non-default port numbers' - #405 --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 771dfd1dd1..4ef2b889a4 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 771dfd1dd1c27a4693dfdfea521c07e72f456b29 +Subproject commit 4ef2b889a45496f2afc8df1c5570ffc90e650bfa From 764877b2526856dd238c1f19671598eba79c1f43 Mon Sep 17 00:00:00 2001 From: Dan Rollo Date: Tue, 21 May 2019 15:02:06 -0400 Subject: [PATCH 340/860] change constant GIT_DIFF_INDENT_HEURISTIC in lib.rs to match declaration in libgit2-sys/libgit2/include/git2/diff.h Thanks @ehuss --- libgit2-sys/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index b1c4bdf5eb..5311492ac8 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1112,7 +1112,7 @@ pub const GIT_DIFF_SHOW_UNMODIFIED: git_diff_option_t = 1 << 26; pub const GIT_DIFF_PATIENCE: git_diff_option_t = 1 << 28; pub const GIT_DIFF_MINIMAL: git_diff_option_t = 1 << 29; pub const GIT_DIFF_SHOW_BINARY: git_diff_option_t = 1 << 30; -pub const GIT_DIFF_INDENT_HEURISTIC: git_diff_option_t = 1 << 31; +pub const GIT_DIFF_INDENT_HEURISTIC: git_diff_option_t = 1 << 18; #[repr(C)] pub struct git_diff_find_options { From d475dc9af726e5aa9e83dcdede89cde6532ac9bf Mon Sep 17 00:00:00 2001 From: Dan Rollo Date: Tue, 21 May 2019 16:38:03 -0400 Subject: [PATCH 341/860] attempt to fix seg fault in the `all` test. Thanks again @ehuss --- git2-curl/Cargo.toml | 1 + git2-curl/tests/all.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index d90d8b79ab..cf734b93fa 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -23,6 +23,7 @@ civet = "0.11" conduit = "0.8" conduit-git-http-backend = "0.8" tempfile = "3.0" +libgit2-sys = { path = "../libgit2-sys"} [[test]] name = "all" diff --git a/git2-curl/tests/all.rs b/git2-curl/tests/all.rs index 941020e185..c14db1a268 100644 --- a/git2-curl/tests/all.rs +++ b/git2-curl/tests/all.rs @@ -15,6 +15,7 @@ const PORT: u16 = 7848; fn main() { unsafe { + libgit2_sys::init(); git2_curl::register(curl::easy::Easy::new()); } From 25383888cd832d142b0f272db4b3a4104d9af822 Mon Sep 17 00:00:00 2001 From: Dan Rollo Date: Wed, 22 May 2019 11:45:24 -0400 Subject: [PATCH 342/860] reorder constant location to match sequential values of existing constants --- libgit2-sys/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5311492ac8..7cb1ad055e 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1102,6 +1102,7 @@ pub const GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS: git_diff_option_t = 1 << 14; pub const GIT_DIFF_UPDATE_INDEX: git_diff_option_t = 1 << 15; pub const GIT_DIFF_INCLUDE_UNREADABLE: git_diff_option_t = 1 << 16; pub const GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED: git_diff_option_t = 1 << 17; +pub const GIT_DIFF_INDENT_HEURISTIC: git_diff_option_t = 1 << 18; pub const GIT_DIFF_FORCE_TEXT: git_diff_option_t = 1 << 20; pub const GIT_DIFF_FORCE_BINARY: git_diff_option_t = 1 << 21; pub const GIT_DIFF_IGNORE_WHITESPACE: git_diff_option_t = 1 << 22; @@ -1112,7 +1113,6 @@ pub const GIT_DIFF_SHOW_UNMODIFIED: git_diff_option_t = 1 << 26; pub const GIT_DIFF_PATIENCE: git_diff_option_t = 1 << 28; pub const GIT_DIFF_MINIMAL: git_diff_option_t = 1 << 29; pub const GIT_DIFF_SHOW_BINARY: git_diff_option_t = 1 << 30; -pub const GIT_DIFF_INDENT_HEURISTIC: git_diff_option_t = 1 << 18; #[repr(C)] pub struct git_diff_find_options { From 437e22e8512456df7575c572ddec5eb8f9419015 Mon Sep 17 00:00:00 2001 From: Dan Rollo Date: Wed, 22 May 2019 11:46:47 -0400 Subject: [PATCH 343/860] add version to dev dependency --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index cf734b93fa..00cbebb36b 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -23,7 +23,7 @@ civet = "0.11" conduit = "0.8" conduit-git-http-backend = "0.8" tempfile = "3.0" -libgit2-sys = { path = "../libgit2-sys"} +libgit2-sys = { path = "../libgit2-sys", version = "0.7.11" } [[test]] name = "all" From 69334f85e3c963b06f3b5220042599585eec8503 Mon Sep 17 00:00:00 2001 From: Dan Rollo Date: Wed, 22 May 2019 12:10:48 -0400 Subject: [PATCH 344/860] move init call into `git2_curl::register` --- git2-curl/Cargo.toml | 2 +- git2-curl/src/lib.rs | 1 + git2-curl/tests/all.rs | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 00cbebb36b..e9d75ea2b8 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -17,13 +17,13 @@ curl = "0.4" url = "1.0" log = "0.4" git2 = { path = "..", version = "0.8", default-features = false } +libgit2-sys = { path = "../libgit2-sys", version = "0.7.11" } [dev-dependencies] civet = "0.11" conduit = "0.8" conduit-git-http-backend = "0.8" tempfile = "3.0" -libgit2-sys = { path = "../libgit2-sys", version = "0.7.11" } [[test]] name = "all" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 90fe412b7f..a9ae589945 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -75,6 +75,7 @@ pub unsafe fn register(handle: Easy) { let handle = Arc::new(Mutex::new(handle)); let handle2 = handle.clone(); INIT.call_once(move || { + libgit2_sys::init(); git2::transport::register("http", move |remote| { factory(remote, handle.clone()) }).unwrap(); diff --git a/git2-curl/tests/all.rs b/git2-curl/tests/all.rs index c14db1a268..941020e185 100644 --- a/git2-curl/tests/all.rs +++ b/git2-curl/tests/all.rs @@ -15,7 +15,6 @@ const PORT: u16 = 7848; fn main() { unsafe { - libgit2_sys::init(); git2_curl::register(curl::easy::Easy::new()); } From 85449f10ba4c5d6dddf54721036dc7d3526def12 Mon Sep 17 00:00:00 2001 From: Emil Lundberg Date: Wed, 22 May 2019 19:01:01 +0200 Subject: [PATCH 345/860] Make Branch.upstream return 'repo instead of arbitrary lifetime --- src/branch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/branch.rs b/src/branch.rs index ee95b7e411..81485f0fd6 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -73,7 +73,7 @@ impl<'repo> Branch<'repo> { /// Return the reference supporting the remote tracking branch, given a /// local branch reference. - pub fn upstream<'a>(&self) -> Result, Error> { + pub fn upstream(&self) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_branch_upstream(&mut ret, &*self.get().raw())); From 4b4a1be075f25cabe63c79716f631b7ff1eb581e Mon Sep 17 00:00:00 2001 From: Dan Rollo Date: Thu, 23 May 2019 11:05:59 -0400 Subject: [PATCH 346/860] move libgit2_sys::init() call to transport::register() --- git2-curl/Cargo.toml | 1 - git2-curl/src/lib.rs | 1 - src/transport.rs | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index e9d75ea2b8..d90d8b79ab 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -17,7 +17,6 @@ curl = "0.4" url = "1.0" log = "0.4" git2 = { path = "..", version = "0.8", default-features = false } -libgit2-sys = { path = "../libgit2-sys", version = "0.7.11" } [dev-dependencies] civet = "0.11" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index a9ae589945..90fe412b7f 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -75,7 +75,6 @@ pub unsafe fn register(handle: Easy) { let handle = Arc::new(Mutex::new(handle)); let handle2 = handle.clone(); INIT.call_once(move || { - libgit2_sys::init(); git2::transport::register("http", move |remote| { factory(remote, handle.clone()) }).unwrap(); diff --git a/src/transport.rs b/src/transport.rs index d34db9f88b..4762c38ba5 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -107,6 +107,7 @@ struct RawSmartSubtransportStream { pub unsafe fn register(prefix: &str, factory: F) -> Result<(), Error> where F: Fn(&Remote) -> Result + Send + Sync + 'static { + libgit2_sys::init(); let mut data = Box::new(TransportData { factory: Box::new(factory), }); From 0f667764b8b9de11c5f972e2a4bb13b6f32bf7f4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 23 May 2019 08:23:15 -0700 Subject: [PATCH 347/860] Call crate initialization instead of libgit2 --- src/transport.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transport.rs b/src/transport.rs index 4762c38ba5..360f1dce99 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -107,7 +107,7 @@ struct RawSmartSubtransportStream { pub unsafe fn register(prefix: &str, factory: F) -> Result<(), Error> where F: Fn(&Remote) -> Result + Send + Sync + 'static { - libgit2_sys::init(); + ::init(); let mut data = Box::new(TransportData { factory: Box::new(factory), }); From 50132f5ede84bd8452a2368990d7333212570258 Mon Sep 17 00:00:00 2001 From: Emil Lundberg Date: Sun, 26 May 2019 19:01:32 +0200 Subject: [PATCH 348/860] Add test of Oid comparisons --- src/oid.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/oid.rs b/src/oid.rs index b63fe34510..ad3f308856 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -181,6 +181,7 @@ mod tests { use tempdir::TempDir; use {ObjectType}; + use super::Error; use super::Oid; #[test] @@ -191,6 +192,32 @@ mod tests { assert!(Oid::from_bytes(b"00000000000000000000").is_ok()); } + #[test] + fn comparisons() -> Result<(), Error> { + assert_eq!(Oid::from_str("decbf2b")?, Oid::from_str("decbf2b")?); + assert!(Oid::from_str("decbf2b")? <= Oid::from_str("decbf2b")?); + assert!(Oid::from_str("decbf2b")? >= Oid::from_str("decbf2b")?); + { + let o = Oid::from_str("decbf2b")?; + assert_eq!(o, o); + assert!(o <= o); + assert!(o >= o); + } + assert_eq!( + Oid::from_str("decbf2b")?, + Oid::from_str("decbf2b000000000000000000000000000000000")? + ); + assert!( + Oid::from_bytes(b"00000000000000000000")? < Oid::from_bytes(b"00000000000000000001")? + ); + assert!(Oid::from_bytes(b"00000000000000000000")? < Oid::from_str("decbf2b")?); + assert_eq!( + Oid::from_bytes(b"00000000000000000000")?, + Oid::from_str("3030303030303030303030303030303030303030")? + ); + Ok(()) + } + #[test] fn zero_is_zero() { assert!(Oid::zero().is_zero()); From b50684a614296a6abd985b93b291520fffd5f345 Mon Sep 17 00:00:00 2001 From: Emil Lundberg Date: Sun, 26 May 2019 18:08:34 +0200 Subject: [PATCH 349/860] Extract function util::c_cmp_to_ordering --- src/oid.rs | 8 ++------ src/reference.rs | 8 ++------ src/tree.rs | 8 ++------ src/util.rs | 11 ++++++++++- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/oid.rs b/src/oid.rs index ad3f308856..c7fc658316 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -7,7 +7,7 @@ use libc; use {raw, Error, ObjectType, IntoCString}; -use util::Binding; +use util::{c_cmp_to_ordering, Binding}; /// Unique identity of any object (commit, tree, blob, tag). #[derive(Copy, Clone)] @@ -156,11 +156,7 @@ impl PartialOrd for Oid { impl Ord for Oid { fn cmp(&self, other: &Oid) -> Ordering { - match unsafe { raw::git_oid_cmp(&self.raw, &other.raw) } { - 0 => Ordering::Equal, - n if n < 0 => Ordering::Less, - _ => Ordering::Greater, - } + c_cmp_to_ordering(unsafe { raw::git_oid_cmp(&self.raw, &other.raw) }) } } diff --git a/src/reference.rs b/src/reference.rs index 265d766148..a8683efcb4 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -7,7 +7,7 @@ use std::str; use {raw, Error, Oid, Repository, ReferenceType, Object, ObjectType, Blob, Commit, Tree, Tag}; use object::CastOrPanic; -use util::Binding; +use util::{c_cmp_to_ordering, Binding}; struct Refdb<'repo>(&'repo Repository); @@ -246,11 +246,7 @@ impl<'repo> PartialOrd for Reference<'repo> { impl<'repo> Ord for Reference<'repo> { fn cmp(&self, other: &Reference<'repo>) -> Ordering { - match unsafe { raw::git_reference_cmp(&*self.raw, &*other.raw) } { - 0 => Ordering::Equal, - n if n < 0 => Ordering::Less, - _ => Ordering::Greater, - } + c_cmp_to_ordering(unsafe { raw::git_reference_cmp(&*self.raw, &*other.raw) }) } } diff --git a/src/tree.rs b/src/tree.rs index 6a0f4975e4..e99a0ddffe 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -9,7 +9,7 @@ use std::str; use libc::{self, c_int, c_char, c_void}; use {panic, raw, Oid, Repository, Error, Object, ObjectType}; -use util::{Binding, IntoCString}; +use util::{c_cmp_to_ordering, Binding, IntoCString}; /// A structure to represent a git [tree][1] /// @@ -351,11 +351,7 @@ impl<'a> PartialOrd for TreeEntry<'a> { } impl<'a> Ord for TreeEntry<'a> { fn cmp(&self, other: &TreeEntry<'a>) -> Ordering { - match unsafe { raw::git_tree_entry_cmp(&*self.raw(), &*other.raw()) } { - 0 => Ordering::Equal, - n if n < 0 => Ordering::Less, - _ => Ordering::Greater, - } + c_cmp_to_ordering(unsafe { raw::git_tree_entry_cmp(&*self.raw(), &*other.raw()) }) } } diff --git a/src/util.rs b/src/util.rs index e111628eae..c1b9cde9d9 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,8 @@ +use std::cmp::Ordering; use std::ffi::{CString, OsStr, OsString}; use std::iter::IntoIterator; use std::path::{Path, PathBuf}; -use libc::{c_char, size_t}; +use libc::{c_char, c_int, size_t}; use {raw, Error}; @@ -150,3 +151,11 @@ pub fn into_opt_c_string(opt_s: Option) -> Result, Error> Some(s) => Ok(Some(try!(s.into_c_string()))), } } + +pub fn c_cmp_to_ordering(cmp: c_int) -> Ordering { + match cmp { + 0 => Ordering::Equal, + n if n < 0 => Ordering::Less, + _ => Ordering::Greater, + } +} From 67093fa6bb76e6cc57b3b7c104ce8c9e44ccb2c4 Mon Sep 17 00:00:00 2001 From: Emil Lundberg Date: Tue, 28 May 2019 01:16:43 +0200 Subject: [PATCH 350/860] Fix copypaste oopsies in Reference doc comments --- src/reference.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reference.rs b/src/reference.rs index a8683efcb4..a6fcf469cf 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -180,7 +180,7 @@ impl<'repo> Reference<'repo> { /// Peel a reference to a commit /// /// This method recursively peels the reference until it reaches - /// a blob. + /// a commit. pub fn peel_to_commit(&self) -> Result, Error> { Ok(try!(self.peel(ObjectType::Commit)).cast_or_panic(ObjectType::Commit)) } @@ -188,7 +188,7 @@ impl<'repo> Reference<'repo> { /// Peel a reference to a tree /// /// This method recursively peels the reference until it reaches - /// a blob. + /// a tree. pub fn peel_to_tree(&self) -> Result, Error> { Ok(try!(self.peel(ObjectType::Tree)).cast_or_panic(ObjectType::Tree)) } From 734c0a39688cab6c0027aeb3108ab18118811a18 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 31 May 2019 12:23:56 -0700 Subject: [PATCH 351/860] Update to libgit2 0.28.2 This includes a semver bump for all crates, as a few APIs have been renamed in 0.28. Upstream provides `deprecated.h` aliases, if we'd like to follow suit, but I feel it's better to just move forward. - `giterr_*` -> `git_error_*` - `GITERR_*` -> `GIT_ERROR_*` - `git_otype` -> `git_object_t` - `GIT_OBJ_*` -> `GIT_OBJECT_*` - `git_ref_t` -> `git_reference_t` - `GIT_REF_*` -> `GIT_REFERENCE_*` - `git_idxentry_*` -> `git_index_entry_*` - `GIT_IDXENTRY_*` -> `GIT_INDEX_ENTRY_*` - `git_buf_free` -> `git_buf_dispose` Proxy support is now builtin to `libgit2`, so `libcurl` is no longer a dependency at all. Proxies were also the reason for `git2-curl` to exist, which seems to be unnecessary for a while now, since `libgit2` used `libcurl` itself since 0.23 anyway. Maybe `git2-curl` can just be retired now, but I've updated it just for the sake of compatibility. The minimum pkg-config libgit2 is now documented and tested for 0.28. While it previously claimed support for 0.25.1, this was broken by `git_config_entry`'s `include_depth` field, which was added *after* the 0.27 release branched. --- .gitmodules | 1 + Cargo.toml | 7 +- README.md | 2 +- git2-curl/Cargo.toml | 4 +- libgit2-sys/Cargo.toml | 6 +- libgit2-sys/build.rs | 26 +++--- libgit2-sys/lib.rs | 184 +++++++++++++++++++--------------------- libgit2-sys/libgit2 | 2 +- src/buf.rs | 2 +- src/call.rs | 18 ++-- src/error.rs | 144 +++++++++++++++---------------- src/index.rs | 16 ++-- src/lib.rs | 72 +++++----------- src/odb.rs | 4 +- src/reference.rs | 6 +- src/remote_callbacks.rs | 2 +- src/transport.rs | 2 +- systest/Cargo.toml | 2 +- systest/build.rs | 6 +- 19 files changed, 227 insertions(+), 279 deletions(-) diff --git a/.gitmodules b/.gitmodules index 95c45cce48..f27afa9218 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "libgit2-sys/libgit2"] path = libgit2-sys/libgit2 url = https://github.com/libgit2/libgit2 + branch = maint/v0.28 diff --git a/Cargo.toml b/Cargo.toml index c3b7cb50a9..bf76d2e35b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.8.0" +version = "0.9.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -23,7 +23,7 @@ url = "1.0" bitflags = "1.0" libc = "0.2" log = "0.4" -libgit2-sys = { path = "libgit2-sys", version = "0.7.11" } +libgit2-sys = { path = "libgit2-sys", version = "0.8.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } @@ -39,10 +39,9 @@ thread-id = "3.3.0" # remove when we work with minimal-versions without it [features] unstable = [] -default = ["ssh", "https", "curl", "ssh_key_from_memory"] +default = ["ssh", "https", "ssh_key_from_memory"] ssh = ["libgit2-sys/ssh"] https = ["libgit2-sys/https", "openssl-sys", "openssl-probe"] -curl = ["libgit2-sys/curl"] vendored-openssl = ["openssl-sys/vendored"] ssh_key_from_memory = ["libgit2-sys/ssh_key_from_memory"] diff --git a/README.md b/README.md index 124b209e29..ee9aa8b3ba 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ version of Rust known to pass tests. ## Version of libgit2 -Currently this library requires libgit2 0.25.1. The source for libgit2 is +Currently this library requires libgit2 0.28.0. The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index d90d8b79ab..0acfb14f0a 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.9.0" +version = "0.10.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" @@ -16,7 +16,7 @@ Intended to be used with the git2 crate. curl = "0.4" url = "1.0" log = "0.4" -git2 = { path = "..", version = "0.8", default-features = false } +git2 = { path = "..", version = "0.9", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 2626b69a75..d883debb31 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.7.11" +version = "0.8.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" @@ -16,13 +16,12 @@ name = "libgit2_sys" path = "lib.rs" [dependencies] -curl-sys = { version = "0.4.10", optional = true } libc = "0.2" libssh2-sys = { version = "0.2.11", optional = true } libz-sys = "1.0.22" [build-dependencies] -pkg-config = "0.3" +pkg-config = "0.3.7" cc = "1.0.25" [target.'cfg(unix)'.dependencies] @@ -31,5 +30,4 @@ openssl-sys = { version = "0.9", optional = true } [features] ssh = ["libssh2-sys"] https = ["openssl-sys"] -curl = ["curl-sys"] ssh_key_from_memory = [] diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index aad5b9e2ab..cc76cd46b3 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -9,10 +9,13 @@ use std::process::Command; fn main() { let https = env::var("CARGO_FEATURE_HTTPS").is_ok(); let ssh = env::var("CARGO_FEATURE_SSH").is_ok(); - let curl = env::var("CARGO_FEATURE_CURL").is_ok(); if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() { - if pkg_config::find_library("libgit2").is_ok() { + let mut cfg = pkg_config::Config::new(); + if let Ok(lib) = cfg.atleast_version("0.28.0").probe("libgit2") { + for include in &lib.include_paths { + println!("cargo:root={}", include.display()); + } return } } @@ -121,21 +124,14 @@ fn main() { } } } else { - cfg.file("libgit2/src/hash/hash_generic.c"); + features.push_str("#define GIT_SHA1_COLLISIONDETECT 1\n"); + cfg.define("SHA1DC_NO_STANDARD_INCLUDES", "1"); + cfg.define("SHA1DC_CUSTOM_INCLUDE_SHA1_C", "\"common.h\""); + cfg.define("SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C", "\"common.h\""); + cfg.file("libgit2/src/hash/sha1dc/sha1.c"); + cfg.file("libgit2/src/hash/sha1dc/ubc_check.c"); } - if curl { - features.push_str("#define GIT_CURL 1\n"); - if let Some(path) = env::var_os("DEP_CURL_INCLUDE") { - cfg.include(path); - } - // Handle dllimport/dllexport on windows by making sure that if we built - // curl statically (as told to us by the `curl-sys` crate) we define the - // correct values for curl's header files. - if env::var_os("DEP_CURL_STATIC").is_some() { - cfg.define("CURL_STATICLIB", None); - } - } if let Some(path) = env::var_os("DEP_Z_INCLUDE") { cfg.include(path); } diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 7cb1ad055e..dd1106b7b6 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -190,37 +190,37 @@ git_enum! { git_enum! { pub enum git_error_t { - GITERR_NONE = 0, - GITERR_NOMEMORY, - GITERR_OS, - GITERR_INVALID, - GITERR_REFERENCE, - GITERR_ZLIB, - GITERR_REPOSITORY, - GITERR_CONFIG, - GITERR_REGEX, - GITERR_ODB, - GITERR_INDEX, - GITERR_OBJECT, - GITERR_NET, - GITERR_TAG, - GITERR_TREE, - GITERR_INDEXER, - GITERR_SSL, - GITERR_SUBMODULE, - GITERR_THREAD, - GITERR_STASH, - GITERR_CHECKOUT, - GITERR_FETCHHEAD, - GITERR_MERGE, - GITERR_SSH, - GITERR_FILTER, - GITERR_REVERT, - GITERR_CALLBACK, - GITERR_CHERRYPICK, - GITERR_DESCRIBE, - GITERR_REBASE, - GITERR_FILESYSTEM, + GIT_ERROR_NONE = 0, + GIT_ERROR_NOMEMORY, + GIT_ERROR_OS, + GIT_ERROR_INVALID, + GIT_ERROR_REFERENCE, + GIT_ERROR_ZLIB, + GIT_ERROR_REPOSITORY, + GIT_ERROR_CONFIG, + GIT_ERROR_REGEX, + GIT_ERROR_ODB, + GIT_ERROR_INDEX, + GIT_ERROR_OBJECT, + GIT_ERROR_NET, + GIT_ERROR_TAG, + GIT_ERROR_TREE, + GIT_ERROR_INDEXER, + GIT_ERROR_SSL, + GIT_ERROR_SUBMODULE, + GIT_ERROR_THREAD, + GIT_ERROR_STASH, + GIT_ERROR_CHECKOUT, + GIT_ERROR_FETCHHEAD, + GIT_ERROR_MERGE, + GIT_ERROR_SSH, + GIT_ERROR_FILTER, + GIT_ERROR_REVERT, + GIT_ERROR_CALLBACK, + GIT_ERROR_CHERRYPICK, + GIT_ERROR_DESCRIBE, + GIT_ERROR_REBASE, + GIT_ERROR_FILESYSTEM, } } @@ -611,26 +611,24 @@ git_enum! { } git_enum! { - pub enum git_otype: c_int { - GIT_OBJ_ANY = -2, - GIT_OBJ_BAD = -1, - GIT_OBJ__EXT1 = 0, - GIT_OBJ_COMMIT = 1, - GIT_OBJ_TREE = 2, - GIT_OBJ_BLOB = 3, - GIT_OBJ_TAG = 4, - GIT_OBJ__EXT2 = 5, - GIT_OBJ_OFS_DELTA = 6, - GIT_OBJ_REF_DELTA = 7, + pub enum git_object_t: c_int { + GIT_OBJECT_ANY = -2, + GIT_OBJECT_INVALID = -1, + GIT_OBJECT_COMMIT = 1, + GIT_OBJECT_TREE = 2, + GIT_OBJECT_BLOB = 3, + GIT_OBJECT_TAG = 4, + GIT_OBJECT_OFS_DELTA = 6, + GIT_OBJECT_REF_DELTA = 7, } } git_enum! { - pub enum git_ref_t { - GIT_REF_INVALID = 0, - GIT_REF_OID = 1, - GIT_REF_SYMBOLIC = 2, - GIT_REF_LISTALL = GIT_REF_OID | GIT_REF_SYMBOLIC, + pub enum git_reference_t { + GIT_REFERENCE_INVALID = 0, + GIT_REFERENCE_DIRECT = 1, + GIT_REFERENCE_SYMBOLIC = 2, + GIT_REFERENCE_ALL = GIT_REFERENCE_DIRECT | GIT_REFERENCE_SYMBOLIC, } } @@ -713,30 +711,18 @@ pub type git_index_matched_path_cb = extern fn(*const c_char, *const c_char, *mut c_void) -> c_int; git_enum! { - pub enum git_idxentry_extended_flag_t { - GIT_IDXENTRY_INTENT_TO_ADD = 1 << 13, - GIT_IDXENTRY_SKIP_WORKTREE = 1 << 14, - GIT_IDXENTRY_EXTENDED2 = 1 << 15, - - GIT_IDXENTRY_UPDATE = 1 << 0, - GIT_IDXENTRY_REMOVE = 1 << 1, - GIT_IDXENTRY_UPTODATE = 1 << 2, - GIT_IDXENTRY_ADDED = 1 << 3, - - GIT_IDXENTRY_HASHED = 1 << 4, - GIT_IDXENTRY_UNHASHED = 1 << 5, - GIT_IDXENTRY_WT_REMOVE = 1 << 6, - GIT_IDXENTRY_CONFLICTED = 1 << 7, - - GIT_IDXENTRY_UNPACKED = 1 << 8, - GIT_IDXENTRY_NEW_SKIP_WORKTREE = 1 << 9, + pub enum git_index_entry_extended_flag_t { + GIT_INDEX_ENTRY_INTENT_TO_ADD = 1 << 13, + GIT_INDEX_ENTRY_SKIP_WORKTREE = 1 << 14, + + GIT_INDEX_ENTRY_UPTODATE = 1 << 2, } } git_enum! { - pub enum git_indxentry_flag_t { - GIT_IDXENTRY_EXTENDED = 0x4000, - GIT_IDXENTRY_VALID = 0x8000, + pub enum git_index_entry_flag_t { + GIT_INDEX_ENTRY_EXTENDED = 0x4000, + GIT_INDEX_ENTRY_VALID = 0x8000, } } @@ -757,9 +743,9 @@ pub struct git_index_entry { pub path: *const c_char, } -pub const GIT_IDXENTRY_NAMEMASK: u16 = 0xfff; -pub const GIT_IDXENTRY_STAGEMASK: u16 = 0x3000; -pub const GIT_IDXENTRY_STAGESHIFT: u16 = 12; +pub const GIT_INDEX_ENTRY_NAMEMASK: u16 = 0xfff; +pub const GIT_INDEX_ENTRY_STAGEMASK: u16 = 0x3000; +pub const GIT_INDEX_ENTRY_STAGESHIFT: u16 = 12; #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq)] @@ -1297,19 +1283,19 @@ pub struct git_odb_backend { pub odb: *mut git_odb, pub read: extern fn(*mut *mut c_void, *mut size_t, - *mut git_otype, + *mut git_object_t, *mut git_odb_backend, *const git_oid) -> c_int, pub read_prefix: extern fn(*mut git_oid, *mut *mut c_void, *mut size_t, - *mut git_otype, + *mut git_object_t, *mut git_odb_backend, *const git_oid, size_t) -> c_int, pub read_header: extern fn(*mut size_t, - *mut git_otype, + *mut git_object_t, *mut git_odb_backend, *const git_oid) -> c_int, @@ -1317,16 +1303,16 @@ pub struct git_odb_backend { *const git_oid, *const c_void, size_t, - git_otype) -> c_int, + git_object_t) -> c_int, pub writestream: extern fn(*mut *mut git_odb_stream, *mut git_odb_backend, git_off_t, - git_otype) -> c_int, + git_object_t) -> c_int, pub readstream: extern fn(*mut *mut git_odb_stream, *mut size_t, - *mut git_otype, + *mut git_object_t, *mut git_odb_backend, *const git_oid) -> c_int, @@ -1697,16 +1683,16 @@ extern { pub fn git_object_lookup(dest: *mut *mut git_object, repo: *mut git_repository, id: *const git_oid, - kind: git_otype) -> c_int; - pub fn git_object_type(obj: *const git_object) -> git_otype; + kind: git_object_t) -> c_int; + pub fn git_object_type(obj: *const git_object) -> git_object_t; pub fn git_object_peel(peeled: *mut *mut git_object, object: *const git_object, - target_type: git_otype) -> c_int; + target_type: git_object_t) -> c_int; pub fn git_object_short_id(out: *mut git_buf, obj: *const git_object) -> c_int; - pub fn git_object_type2string(kind: git_otype) -> *const c_char; - pub fn git_object_string2type(s: *const c_char) -> git_otype; - pub fn git_object_typeisloose(kind: git_otype) -> c_int; + pub fn git_object_type2string(kind: git_object_t) -> *const c_char; + pub fn git_object_string2type(s: *const c_char) -> git_object_t; + pub fn git_object_typeisloose(kind: git_object_t) -> c_int; // oid pub fn git_oid_fromraw(out: *mut git_oid, raw: *const c_uchar); @@ -1719,10 +1705,10 @@ extern { pub fn git_oid_streq(id: *const git_oid, str: *const c_char) -> c_int; pub fn git_oid_iszero(id: *const git_oid) -> c_int; - // giterr - pub fn giterr_last() -> *const git_error; - pub fn giterr_clear(); - pub fn giterr_set_str(error_class: c_int, string: *const c_char); + // error + pub fn git_error_last() -> *const git_error; + pub fn git_error_clear(); + pub fn git_error_set_str(error_class: c_int, string: *const c_char); // remote pub fn git_remote_create(out: *mut *mut git_remote, @@ -1891,8 +1877,8 @@ extern { repo: *mut git_repository, name: *const c_char) -> c_int; pub fn git_reference_peel(out: *mut *mut git_object, - r: *mut git_reference, - otype: git_otype) -> c_int; + r: *const git_reference, + otype: git_object_t) -> c_int; pub fn git_reference_rename(new_ref: *mut *mut git_reference, r: *mut git_reference, new_name: *const c_char, @@ -1908,7 +1894,7 @@ extern { r: *mut git_reference, id: *const git_oid, log_message: *const c_char) -> c_int; - pub fn git_reference_type(r: *const git_reference) -> git_ref_t; + pub fn git_reference_type(r: *const git_reference) -> git_reference_t; pub fn git_reference_iterator_new(out: *mut *mut git_reference_iterator, repo: *mut git_repository) -> c_int; pub fn git_reference_iterator_glob_new(out: *mut *mut git_reference_iterator, @@ -2085,7 +2071,7 @@ extern { pub fn git_tree_entry_to_object(out: *mut *mut git_object, repo: *mut git_repository, entry: *const git_tree_entry) -> c_int; - pub fn git_tree_entry_type(entry: *const git_tree_entry) -> git_otype; + pub fn git_tree_entry_type(entry: *const git_tree_entry) -> git_object_t; pub fn git_tree_entrycount(tree: *const git_tree) -> size_t; pub fn git_tree_free(tree: *mut git_tree); pub fn git_tree_id(tree: *const git_tree) -> *const git_oid; @@ -2120,7 +2106,7 @@ extern { bld: *mut git_treebuilder) -> c_int; // buf - pub fn git_buf_free(buffer: *mut git_buf); + pub fn git_buf_dispose(buffer: *mut git_buf); pub fn git_buf_grow(buffer: *mut git_buf, target_size: size_t) -> c_int; pub fn git_buf_set(buffer: *mut git_buf, data: *const c_void, datalen: size_t) -> c_int; @@ -2457,7 +2443,7 @@ extern { pub fn git_tag_target(target_out: *mut *mut git_object, tag: *const git_tag) -> c_int; pub fn git_tag_target_id(tag: *const git_tag) -> *const git_oid; - pub fn git_tag_target_type(tag: *const git_tag) -> git_otype; + pub fn git_tag_target_type(tag: *const git_tag) -> git_object_t; // checkout pub fn git_checkout_head(repo: *mut git_repository, @@ -2894,7 +2880,7 @@ extern { pub fn git_odb_free(db: *mut git_odb); pub fn git_odb_open_rstream(out: *mut *mut git_odb_stream, len: *mut size_t, - otype: *mut git_otype, + otype: *mut git_object_t, db: *mut git_odb, oid: *const git_oid) -> c_int; pub fn git_odb_stream_read(stream: *mut git_odb_stream, @@ -2903,7 +2889,7 @@ extern { pub fn git_odb_open_wstream(out: *mut *mut git_odb_stream, db: *mut git_odb, size: git_off_t, - obj_type: git_otype) -> c_int; + obj_type: git_object_t) -> c_int; pub fn git_odb_stream_write(stream: *mut git_odb_stream, buffer: *const c_char, len: size_t) -> c_int; @@ -2917,7 +2903,7 @@ extern { oid: *const git_oid) -> c_int; pub fn git_odb_read_header(len_out: *mut size_t, - type_out: *mut git_otype, + type_out: *mut git_object_t, odb: *mut git_odb, oid: *const git_oid) -> c_int; @@ -2925,16 +2911,16 @@ extern { odb: *mut git_odb, data: *const c_void, len: size_t, - otype: git_otype) -> c_int; + otype: git_object_t) -> c_int; pub fn git_odb_hash(out: *mut git_oid, data: *const c_void, len: size_t, - otype: git_otype) -> c_int; + otype: git_object_t) -> c_int; pub fn git_odb_hashfile(out: *mut git_oid, path: *const c_char, - otype: git_otype) -> c_int; + otype: git_object_t) -> c_int; pub fn git_odb_exists_prefix(out: *mut git_oid, odb: *mut git_odb, @@ -2948,7 +2934,7 @@ extern { pub fn git_odb_object_id(obj: *mut git_odb_object) -> *const git_oid; pub fn git_odb_object_size(obj: *mut git_odb_object) -> size_t; - pub fn git_odb_object_type(obj: *mut git_odb_object) -> git_otype; + pub fn git_odb_object_type(obj: *mut git_odb_object) -> git_object_t; pub fn git_odb_object_data(obj: *mut git_odb_object) -> *const c_void; pub fn git_odb_object_dup(out: *mut *mut git_odb_object, obj: *mut git_odb_object) -> c_int; diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 4ef2b889a4..b3e1a56ebb 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 4ef2b889a45496f2afc8df1c5570ffc90e650bfa +Subproject commit b3e1a56ebb2b9291e82dc027ba9cbcfc3ead54d3 diff --git a/src/buf.rs b/src/buf.rs index 78e958e2e2..9500443cde 100644 --- a/src/buf.rs +++ b/src/buf.rs @@ -68,6 +68,6 @@ impl Binding for Buf { impl Drop for Buf { fn drop(&mut self) { - unsafe { raw::git_buf_free(&mut self.raw) } + unsafe { raw::git_buf_dispose(&mut self.raw) } } } diff --git a/src/call.rs b/src/call.rs index 3367275bff..2f0f3ff660 100644 --- a/src/call.rs +++ b/src/call.rs @@ -110,20 +110,20 @@ mod impls { } } - impl Convert for ObjectType { - fn convert(&self) -> raw::git_otype { + impl Convert for ObjectType { + fn convert(&self) -> raw::git_object_t { match *self { - ObjectType::Any => raw::GIT_OBJ_ANY, - ObjectType::Commit => raw::GIT_OBJ_COMMIT, - ObjectType::Tree => raw::GIT_OBJ_TREE, - ObjectType::Blob => raw::GIT_OBJ_BLOB, - ObjectType::Tag => raw::GIT_OBJ_TAG, + ObjectType::Any => raw::GIT_OBJECT_ANY, + ObjectType::Commit => raw::GIT_OBJECT_COMMIT, + ObjectType::Tree => raw::GIT_OBJECT_TREE, + ObjectType::Blob => raw::GIT_OBJECT_BLOB, + ObjectType::Tag => raw::GIT_OBJECT_TAG, } } } - impl Convert for Option { - fn convert(&self) -> raw::git_otype { + impl Convert for Option { + fn convert(&self) -> raw::git_object_t { self.unwrap_or(ObjectType::Any).convert() } } diff --git a/src/error.rs b/src/error.rs index 1e92b23a08..e342d6ce0b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -22,7 +22,7 @@ impl Error { /// call. This code will later be returned from the `code` function. /// /// Historically this function returned `Some` or `None` based on the return - /// value of `giterr_last` but nowadays it always returns `Some` so it's + /// value of `git_error_last` but nowadays it always returns `Some` so it's /// safe to unwrap the return value. This API will change in the next major /// version. pub fn last_error(code: c_int) -> Option { @@ -30,20 +30,20 @@ impl Error { unsafe { // Note that whenever libgit2 returns an error any negative value // indicates that an error happened. Auxiliary information is - // *usually* in `giterr_last` but unfortunately that's not always + // *usually* in `git_error_last` but unfortunately that's not always // the case. Sometimes a negative error code is returned from - // libgit2 *without* calling `giterr_set` internally to configure + // libgit2 *without* calling `git_error_set` internally to configure // the error. // // To handle this case and hopefully provide better error messages - // on our end we unconditionally call `giterr_clear` when we're done + // on our end we unconditionally call `git_error_clear` when we're done // with an error. This is an attempt to clear it as aggressively as // possible when we can to ensure that error information from one // api invocation doesn't leak over to the next api invocation. // - // Additionally if `giterr_last` returns null then we returned a + // Additionally if `git_error_last` returns null then we returned a // canned error out. - let ptr = raw::giterr_last(); + let ptr = raw::git_error_last(); let err = if ptr.is_null() { let mut error = Error::from_str("an unknown git error occurred"); error.code = code; @@ -51,7 +51,7 @@ impl Error { } else { Error::from_raw(code, ptr) }; - raw::giterr_clear(); + raw::git_error_clear(); Some(err) } } @@ -65,11 +65,11 @@ impl Error { /// Creates a new error from the given string as the error. /// /// The error returned will have the code `GIT_ERROR` and the class - /// `GITERR_NONE`. + /// `GIT_ERROR_NONE`. pub fn from_str(s: &str) -> Error { Error { code: raw::GIT_ERROR as c_int, - klass: raw::GITERR_NONE as c_int, + klass: raw::GIT_ERROR_NONE as c_int, message: s.to_string(), } } @@ -118,37 +118,37 @@ impl Error { /// typically not directly actionable. pub fn class(&self) -> ErrorClass { match self.raw_class() { - raw::GITERR_NONE => super::ErrorClass::None, - raw::GITERR_NOMEMORY => super::ErrorClass::NoMemory, - raw::GITERR_OS => super::ErrorClass::Os, - raw::GITERR_INVALID => super::ErrorClass::Invalid, - raw::GITERR_REFERENCE => super::ErrorClass::Reference, - raw::GITERR_ZLIB => super::ErrorClass::Zlib, - raw::GITERR_REPOSITORY => super::ErrorClass::Repository, - raw::GITERR_CONFIG => super::ErrorClass::Config, - raw::GITERR_REGEX => super::ErrorClass::Regex, - raw::GITERR_ODB => super::ErrorClass::Odb, - raw::GITERR_INDEX => super::ErrorClass::Index, - raw::GITERR_OBJECT => super::ErrorClass::Object, - raw::GITERR_NET => super::ErrorClass::Net, - raw::GITERR_TAG => super::ErrorClass::Tag, - raw::GITERR_TREE => super::ErrorClass::Tree, - raw::GITERR_INDEXER => super::ErrorClass::Indexer, - raw::GITERR_SSL => super::ErrorClass::Ssl, - raw::GITERR_SUBMODULE => super::ErrorClass::Submodule, - raw::GITERR_THREAD => super::ErrorClass::Thread, - raw::GITERR_STASH => super::ErrorClass::Stash, - raw::GITERR_CHECKOUT => super::ErrorClass::Checkout, - raw::GITERR_FETCHHEAD => super::ErrorClass::FetchHead, - raw::GITERR_MERGE => super::ErrorClass::Merge, - raw::GITERR_SSH => super::ErrorClass::Ssh, - raw::GITERR_FILTER => super::ErrorClass::Filter, - raw::GITERR_REVERT => super::ErrorClass::Revert, - raw::GITERR_CALLBACK => super::ErrorClass::Callback, - raw::GITERR_CHERRYPICK => super::ErrorClass::CherryPick, - raw::GITERR_DESCRIBE => super::ErrorClass::Describe, - raw::GITERR_REBASE => super::ErrorClass::Rebase, - raw::GITERR_FILESYSTEM => super::ErrorClass::Filesystem, + raw::GIT_ERROR_NONE => super::ErrorClass::None, + raw::GIT_ERROR_NOMEMORY => super::ErrorClass::NoMemory, + raw::GIT_ERROR_OS => super::ErrorClass::Os, + raw::GIT_ERROR_INVALID => super::ErrorClass::Invalid, + raw::GIT_ERROR_REFERENCE => super::ErrorClass::Reference, + raw::GIT_ERROR_ZLIB => super::ErrorClass::Zlib, + raw::GIT_ERROR_REPOSITORY => super::ErrorClass::Repository, + raw::GIT_ERROR_CONFIG => super::ErrorClass::Config, + raw::GIT_ERROR_REGEX => super::ErrorClass::Regex, + raw::GIT_ERROR_ODB => super::ErrorClass::Odb, + raw::GIT_ERROR_INDEX => super::ErrorClass::Index, + raw::GIT_ERROR_OBJECT => super::ErrorClass::Object, + raw::GIT_ERROR_NET => super::ErrorClass::Net, + raw::GIT_ERROR_TAG => super::ErrorClass::Tag, + raw::GIT_ERROR_TREE => super::ErrorClass::Tree, + raw::GIT_ERROR_INDEXER => super::ErrorClass::Indexer, + raw::GIT_ERROR_SSL => super::ErrorClass::Ssl, + raw::GIT_ERROR_SUBMODULE => super::ErrorClass::Submodule, + raw::GIT_ERROR_THREAD => super::ErrorClass::Thread, + raw::GIT_ERROR_STASH => super::ErrorClass::Stash, + raw::GIT_ERROR_CHECKOUT => super::ErrorClass::Checkout, + raw::GIT_ERROR_FETCHHEAD => super::ErrorClass::FetchHead, + raw::GIT_ERROR_MERGE => super::ErrorClass::Merge, + raw::GIT_ERROR_SSH => super::ErrorClass::Ssh, + raw::GIT_ERROR_FILTER => super::ErrorClass::Filter, + raw::GIT_ERROR_REVERT => super::ErrorClass::Revert, + raw::GIT_ERROR_CALLBACK => super::ErrorClass::Callback, + raw::GIT_ERROR_CHERRYPICK => super::ErrorClass::CherryPick, + raw::GIT_ERROR_DESCRIBE => super::ErrorClass::Describe, + raw::GIT_ERROR_REBASE => super::ErrorClass::Rebase, + raw::GIT_ERROR_FILESYSTEM => super::ErrorClass::Filesystem, _ => super::ErrorClass::None, } } @@ -194,41 +194,41 @@ impl Error { macro_rules! check( ($($e:ident,)*) => ( $(if self.klass == raw::$e as c_int { raw::$e }) else * else { - raw::GITERR_NONE + raw::GIT_ERROR_NONE } ) ); check!( - GITERR_NONE, - GITERR_NOMEMORY, - GITERR_OS, - GITERR_INVALID, - GITERR_REFERENCE, - GITERR_ZLIB, - GITERR_REPOSITORY, - GITERR_CONFIG, - GITERR_REGEX, - GITERR_ODB, - GITERR_INDEX, - GITERR_OBJECT, - GITERR_NET, - GITERR_TAG, - GITERR_TREE, - GITERR_INDEXER, - GITERR_SSL, - GITERR_SUBMODULE, - GITERR_THREAD, - GITERR_STASH, - GITERR_CHECKOUT, - GITERR_FETCHHEAD, - GITERR_MERGE, - GITERR_SSH, - GITERR_FILTER, - GITERR_REVERT, - GITERR_CALLBACK, - GITERR_CHERRYPICK, - GITERR_DESCRIBE, - GITERR_REBASE, - GITERR_FILESYSTEM, + GIT_ERROR_NONE, + GIT_ERROR_NOMEMORY, + GIT_ERROR_OS, + GIT_ERROR_INVALID, + GIT_ERROR_REFERENCE, + GIT_ERROR_ZLIB, + GIT_ERROR_REPOSITORY, + GIT_ERROR_CONFIG, + GIT_ERROR_REGEX, + GIT_ERROR_ODB, + GIT_ERROR_INDEX, + GIT_ERROR_OBJECT, + GIT_ERROR_NET, + GIT_ERROR_TAG, + GIT_ERROR_TREE, + GIT_ERROR_INDEXER, + GIT_ERROR_SSL, + GIT_ERROR_SUBMODULE, + GIT_ERROR_THREAD, + GIT_ERROR_STASH, + GIT_ERROR_CHECKOUT, + GIT_ERROR_FETCHHEAD, + GIT_ERROR_MERGE, + GIT_ERROR_SSH, + GIT_ERROR_FILTER, + GIT_ERROR_REVERT, + GIT_ERROR_CALLBACK, + GIT_ERROR_CHERRYPICK, + GIT_ERROR_DESCRIBE, + GIT_ERROR_REBASE, + GIT_ERROR_FILESYSTEM, ) } diff --git a/src/index.rs b/src/index.rs index 1071db3978..9c618c7ef0 100644 --- a/src/index.rs +++ b/src/index.rs @@ -112,12 +112,12 @@ impl Index { // libgit2 encodes the length of the path in the lower bits of the // `flags` entry, so mask those out and recalculate here to ensure we // don't corrupt anything. - let mut flags = entry.flags & !raw::GIT_IDXENTRY_NAMEMASK; + let mut flags = entry.flags & !raw::GIT_INDEX_ENTRY_NAMEMASK; - if entry.path.len() < raw::GIT_IDXENTRY_NAMEMASK as usize { + if entry.path.len() < raw::GIT_INDEX_ENTRY_NAMEMASK as usize { flags |= entry.path.len() as u16; } else { - flags |= raw::GIT_IDXENTRY_NAMEMASK; + flags |= raw::GIT_INDEX_ENTRY_NAMEMASK; } unsafe { @@ -169,12 +169,12 @@ impl Index { // libgit2 encodes the length of the path in the lower bits of the // `flags` entry, so mask those out and recalculate here to ensure we // don't corrupt anything. - let mut flags = entry.flags & !raw::GIT_IDXENTRY_NAMEMASK; + let mut flags = entry.flags & !raw::GIT_INDEX_ENTRY_NAMEMASK; - if entry.path.len() < raw::GIT_IDXENTRY_NAMEMASK as usize { + if entry.path.len() < raw::GIT_INDEX_ENTRY_NAMEMASK as usize { flags |= entry.path.len() as u16; } else { - flags |= raw::GIT_IDXENTRY_NAMEMASK; + flags |= raw::GIT_INDEX_ENTRY_NAMEMASK; } unsafe { @@ -608,8 +608,8 @@ impl Binding for IndexEntry { // libgit2 encodes the length of the path in the lower bits of `flags`, // but if the length exceeds the number of bits then the path is // nul-terminated. - let mut pathlen = (flags & raw::GIT_IDXENTRY_NAMEMASK) as usize; - if pathlen == raw::GIT_IDXENTRY_NAMEMASK as usize { + let mut pathlen = (flags & raw::GIT_INDEX_ENTRY_NAMEMASK) as usize; + if pathlen == raw::GIT_INDEX_ENTRY_NAMEMASK as usize { pathlen = CStr::from_ptr(path).to_bytes().len(); } diff --git a/src/lib.rs b/src/lib.rs index 7960bd8af0..873a16cb36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -310,7 +310,7 @@ pub enum ObjectType { #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum ReferenceType { /// A reference which points at an object id. - Oid, + Direct, /// A reference which points at another reference. Symbolic, @@ -443,9 +443,9 @@ bitflags! { /// Flags for the `flags` field of an IndexEntry. pub struct IndexEntryFlag: u16 { /// Set when the `extended_flags` field is valid. - const EXTENDED = raw::GIT_IDXENTRY_EXTENDED as u16; + const EXTENDED = raw::GIT_INDEX_ENTRY_EXTENDED as u16; /// "Assume valid" flag - const VALID = raw::GIT_IDXENTRY_VALID as u16; + const VALID = raw::GIT_INDEX_ENTRY_VALID as u16; } } @@ -458,51 +458,19 @@ bitflags! { /// Flags for the `extended_flags` field of an IndexEntry. pub struct IndexEntryExtendedFlag: u16 { /// An "intent to add" entry from "git add -N" - const INTENT_TO_ADD = raw::GIT_IDXENTRY_INTENT_TO_ADD as u16; + const INTENT_TO_ADD = raw::GIT_INDEX_ENTRY_INTENT_TO_ADD as u16; /// Skip the associated worktree file, for sparse checkouts - const SKIP_WORKTREE = raw::GIT_IDXENTRY_SKIP_WORKTREE as u16; - /// Reserved for a future on-disk extended flag - const EXTENDED2 = raw::GIT_IDXENTRY_EXTENDED2 as u16; + const SKIP_WORKTREE = raw::GIT_INDEX_ENTRY_SKIP_WORKTREE as u16; #[allow(missing_docs)] - const UPDATE = raw::GIT_IDXENTRY_UPDATE as u16; - #[allow(missing_docs)] - const REMOVE = raw::GIT_IDXENTRY_REMOVE as u16; - #[allow(missing_docs)] - const UPTODATE = raw::GIT_IDXENTRY_UPTODATE as u16; - #[allow(missing_docs)] - const ADDED = raw::GIT_IDXENTRY_ADDED as u16; - - #[allow(missing_docs)] - const HASHED = raw::GIT_IDXENTRY_HASHED as u16; - #[allow(missing_docs)] - const UNHASHED = raw::GIT_IDXENTRY_UNHASHED as u16; - #[allow(missing_docs)] - const WT_REMOVE = raw::GIT_IDXENTRY_WT_REMOVE as u16; - #[allow(missing_docs)] - const CONFLICTED = raw::GIT_IDXENTRY_CONFLICTED as u16; - - #[allow(missing_docs)] - const UNPACKED = raw::GIT_IDXENTRY_UNPACKED as u16; - #[allow(missing_docs)] - const NEW_SKIP_WORKTREE = raw::GIT_IDXENTRY_NEW_SKIP_WORKTREE as u16; + const UPTODATE = raw::GIT_INDEX_ENTRY_UPTODATE as u16; } } impl IndexEntryExtendedFlag { is_bit_set!(is_intent_to_add, IndexEntryExtendedFlag::INTENT_TO_ADD); is_bit_set!(is_skip_worktree, IndexEntryExtendedFlag::SKIP_WORKTREE); - is_bit_set!(is_extended2, IndexEntryExtendedFlag::EXTENDED2); - is_bit_set!(is_update, IndexEntryExtendedFlag::UPDATE); - is_bit_set!(is_remove, IndexEntryExtendedFlag::REMOVE); is_bit_set!(is_up_to_date, IndexEntryExtendedFlag::UPTODATE); - is_bit_set!(is_added, IndexEntryExtendedFlag::ADDED); - is_bit_set!(is_hashed, IndexEntryExtendedFlag::HASHED); - is_bit_set!(is_unhashed, IndexEntryExtendedFlag::UNHASHED); - is_bit_set!(is_wt_remove, IndexEntryExtendedFlag::WT_REMOVE); - is_bit_set!(is_conflicted, IndexEntryExtendedFlag::CONFLICTED); - is_bit_set!(is_unpacked, IndexEntryExtendedFlag::UNPACKED); - is_bit_set!(is_new_skip_worktree, IndexEntryExtendedFlag::NEW_SKIP_WORKTREE); } bitflags! { @@ -833,25 +801,25 @@ impl ObjectType { } } - /// Determine if the given git_otype is a valid loose object type. + /// Determine if the given git_object_t is a valid loose object type. pub fn is_loose(&self) -> bool { unsafe { (call!(raw::git_object_typeisloose(*self)) == 1) } } - /// Convert a raw git_otype to an ObjectType - pub fn from_raw(raw: raw::git_otype) -> Option { + /// Convert a raw git_object_t to an ObjectType + pub fn from_raw(raw: raw::git_object_t) -> Option { match raw { - raw::GIT_OBJ_ANY => Some(ObjectType::Any), - raw::GIT_OBJ_COMMIT => Some(ObjectType::Commit), - raw::GIT_OBJ_TREE => Some(ObjectType::Tree), - raw::GIT_OBJ_BLOB => Some(ObjectType::Blob), - raw::GIT_OBJ_TAG => Some(ObjectType::Tag), + raw::GIT_OBJECT_ANY => Some(ObjectType::Any), + raw::GIT_OBJECT_COMMIT => Some(ObjectType::Commit), + raw::GIT_OBJECT_TREE => Some(ObjectType::Tree), + raw::GIT_OBJECT_BLOB => Some(ObjectType::Blob), + raw::GIT_OBJECT_TAG => Some(ObjectType::Tag), _ => None, } } /// Convert this kind into its raw representation - pub fn raw(&self) -> raw::git_otype { + pub fn raw(&self) -> raw::git_object_t { call::convert(self) } @@ -872,16 +840,16 @@ impl ReferenceType { /// Convert an object type to its string representation. pub fn str(&self) -> &'static str { match self { - &ReferenceType::Oid => "oid", + &ReferenceType::Direct => "direct", &ReferenceType::Symbolic => "symbolic", } } - /// Convert a raw git_ref_t to a ReferenceType. - pub fn from_raw(raw: raw::git_ref_t) -> Option { + /// Convert a raw git_reference_t to a ReferenceType. + pub fn from_raw(raw: raw::git_reference_t) -> Option { match raw { - raw::GIT_REF_OID => Some(ReferenceType::Oid), - raw::GIT_REF_SYMBOLIC => Some(ReferenceType::Symbolic), + raw::GIT_REFERENCE_DIRECT => Some(ReferenceType::Direct), + raw::GIT_REFERENCE_SYMBOLIC => Some(ReferenceType::Symbolic), _ => None, } } diff --git a/src/odb.rs b/src/odb.rs index c3a07a4743..1a14323815 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -52,7 +52,7 @@ impl<'repo> Odb<'repo> { pub fn reader(&self, oid: Oid) -> Result<(OdbReader, usize, ObjectType), Error> { let mut out = ptr::null_mut(); let mut size = 0usize; - let mut otype: raw::git_otype = ObjectType::Any.raw(); + let mut otype: raw::git_object_t = ObjectType::Any.raw(); unsafe { try_call!(raw::git_odb_open_rstream(&mut out, &mut size, &mut otype, self.raw, oid.raw())); Ok((OdbReader::from_raw(out), size, ObjectType::from_raw(otype).unwrap())) @@ -103,7 +103,7 @@ impl<'repo> Odb<'repo> { try_call!(raw::git_odb_read_header(&mut size as *mut size_t, &mut kind_id - as *mut raw::git_otype, + as *mut raw::git_object_t, self.raw, oid.raw())); diff --git a/src/reference.rs b/src/reference.rs index a6fcf469cf..f9d2f5b8da 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -345,8 +345,8 @@ mod tests { assert!(!head.is_note()); // HEAD is a symbolic reference but git_repository_head resolves it - // so it is a GIT_REF_OID. - assert_eq!(head.kind().unwrap(), ReferenceType::Oid); + // so it is a GIT_REFERENCE_DIRECT. + assert_eq!(head.kind().unwrap(), ReferenceType::Direct); assert!(head == repo.head().unwrap()); assert_eq!(head.name(), Some("refs/heads/master")); @@ -365,7 +365,7 @@ mod tests { head.target().unwrap(), false, "test").unwrap(); assert!(tag1.is_tag()); - assert_eq!(tag1.kind().unwrap(), ReferenceType::Oid); + assert_eq!(tag1.kind().unwrap(), ReferenceType::Direct); let peeled_commit = tag1.peel(ObjectType::Commit).unwrap(); assert_eq!(ObjectType::Commit, peeled_commit.kind().unwrap()); diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 562d3a2d6c..72e61a4091 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -280,7 +280,7 @@ extern fn credentials_cb(ret: *mut *mut raw::git_cred, callback(url, username_from_url, cred_type).map_err(|e| { let s = CString::new(e.to_string()).unwrap(); - raw::giterr_set_str(e.raw_code() as c_int, s.as_ptr()); + raw::git_error_set_str(e.raw_code() as c_int, s.as_ptr()); e.raw_code() as c_int }) }); diff --git a/src/transport.rs b/src/transport.rs index 360f1dce99..20b462bb1b 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -315,7 +315,7 @@ extern fn stream_write(stream: *mut raw::git_smart_subtransport_stream, unsafe fn set_err(e: &io::Error) { let s = CString::new(e.to_string()).unwrap(); - raw::giterr_set_str(raw::GITERR_NET as c_int, s.as_ptr()) + raw::git_error_set_str(raw::GIT_ERROR_NET as c_int, s.as_ptr()) } // callback used by smart transports to free a `SmartSubtransportStream` diff --git a/systest/Cargo.toml b/systest/Cargo.toml index dc60edc46f..3507d85e6d 100644 --- a/systest/Cargo.toml +++ b/systest/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Alex Crichton "] build = "build.rs" [dependencies] -libgit2-sys = { path = "../libgit2-sys", features = ['curl', 'https', 'ssh'] } +libgit2-sys = { path = "../libgit2-sys", features = ['https', 'ssh'] } libc = "0.2" [build-dependencies] diff --git a/systest/build.rs b/systest/build.rs index 25a340ba0b..fbe3c156b1 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -4,9 +4,10 @@ use std::env; use std::path::PathBuf; fn main() { - let root = PathBuf::from(env::var_os("DEP_GIT2_ROOT").unwrap()); - let mut cfg = ctest::TestGenerator::new(); + if let Some(root) = env::var_os("DEP_GIT2_ROOT") { + cfg.include(PathBuf::from(root).join("include")); + } cfg.header("git2.h") .header("git2/sys/transport.h") .header("git2/sys/refs.h") @@ -15,7 +16,6 @@ fn main() { .header("git2/sys/mempack.h") .header("git2/sys/repository.h") .header("git2/cred_helpers.h") - .include(root.join("include")) .type_name(|s, _, _| s.to_string()); cfg.field_name(|_, f| { match f { From 38dcc326d0620049941ff53cb1cd1ab7b9ebbc97 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 2 Jun 2019 13:09:31 -0700 Subject: [PATCH 352/860] Fix `bare_trait_objects` warning. --- git2-curl/src/lib.rs | 4 ++-- src/build.rs | 6 +++--- src/diff.rs | 10 +++++----- src/index.rs | 2 +- src/odb.rs | 2 +- src/packbuilder.rs | 4 ++-- src/panic.rs | 2 +- src/remote_callbacks.rs | 12 ++++++------ src/stash.rs | 4 ++-- src/transport.rs | 8 ++++---- src/tree.rs | 2 +- src/treebuilder.rs | 2 +- 12 files changed, 29 insertions(+), 29 deletions(-) diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 90fe412b7f..bbf25ac83e 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -94,7 +94,7 @@ fn factory(remote: &git2::Remote, handle: Arc>) impl SmartSubtransport for CurlTransport { fn action(&self, url: &str, action: Service) - -> Result, Error> { + -> Result, Error> { let mut base_url = self.base_url.lock().unwrap(); if base_url.len() == 0 { *base_url = url.to_string(); @@ -131,7 +131,7 @@ impl SmartSubtransport for CurlTransport { } impl CurlSubtransport { - fn err>>(&self, err: E) -> io::Error { + fn err>>(&self, err: E) -> io::Error { io::Error::new(io::ErrorKind::Other, err) } diff --git a/src/build.rs b/src/build.rs index 29b66d69cf..ad23bc7db7 100644 --- a/src/build.rs +++ b/src/build.rs @@ -26,7 +26,7 @@ pub struct RepoBuilder<'cb> { /// Type of callback passed to `RepoBuilder::remote_create`. /// /// The second and third arguments are the remote's name and the remote's url. -pub type RemoteCreate<'cb> = for<'a> FnMut(&'a Repository, &str, &str) +pub type RemoteCreate<'cb> = dyn for<'a> FnMut(&'a Repository, &str, &str) -> Result, Error> + 'cb; /// A builder struct for configuring checkouts of a repository. @@ -50,7 +50,7 @@ pub struct CheckoutBuilder<'cb> { /// /// The first argument is the path for the notification, the next is the numver /// of completed steps so far, and the final is the total number of steps. -pub type Progress<'a> = FnMut(Option<&Path>, usize, usize) + 'a; +pub type Progress<'a> = dyn FnMut(Option<&Path>, usize, usize) + 'a; /// Checkout notifications callback. /// @@ -59,7 +59,7 @@ pub type Progress<'a> = FnMut(Option<&Path>, usize, usize) + 'a; /// /// The callback must return a bool specifying whether the checkout should /// continue. -pub type Notify<'a> = FnMut(CheckoutNotificationType, Option<&Path>, +pub type Notify<'a> = dyn FnMut(CheckoutNotificationType, Option<&Path>, Option, Option, Option) -> bool + 'a; diff --git a/src/diff.rs b/src/diff.rs index dffd6117c4..291266608d 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -102,12 +102,12 @@ pub enum DiffBinaryKind { Delta, } -type PrintCb<'a> = FnMut(DiffDelta, Option, DiffLine) -> bool + 'a; +type PrintCb<'a> = dyn FnMut(DiffDelta, Option, DiffLine) -> bool + 'a; -pub type FileCb<'a> = FnMut(DiffDelta, f32) -> bool + 'a; -pub type BinaryCb<'a> = FnMut(DiffDelta, DiffBinary) -> bool + 'a; -pub type HunkCb<'a> = FnMut(DiffDelta, DiffHunk) -> bool + 'a; -pub type LineCb<'a> = FnMut(DiffDelta, Option, DiffLine) -> bool + 'a; +pub type FileCb<'a> = dyn FnMut(DiffDelta, f32) -> bool + 'a; +pub type BinaryCb<'a> = dyn FnMut(DiffDelta, DiffBinary) -> bool + 'a; +pub type HunkCb<'a> = dyn FnMut(DiffDelta, DiffHunk) -> bool + 'a; +pub type LineCb<'a> = dyn FnMut(DiffDelta, Option, DiffLine) -> bool + 'a; struct ForeachCallbacks<'a, 'b: 'a, 'c, 'd: 'c, 'e, 'f: 'e, 'g, 'h: 'g> { file: &'a mut FileCb<'b>, diff --git a/src/index.rs b/src/index.rs index 1071db3978..02ed977495 100644 --- a/src/index.rs +++ b/src/index.rs @@ -47,7 +47,7 @@ pub struct IndexConflict { /// Used by `Index::{add_all,remove_all,update_all}`. The first argument is the /// path, and the second is the patchspec that matched it. Return 0 to confirm /// the operation on the item, > 0 to skip the item, and < 0 to abort the scan. -pub type IndexMatchedPath<'a> = FnMut(&Path, &[u8]) -> i32 + 'a; +pub type IndexMatchedPath<'a> = dyn FnMut(&Path, &[u8]) -> i32 + 'a; /// A structure to represent an entry or a file inside of an index. /// diff --git a/src/odb.rs b/src/odb.rs index c3a07a4743..8feab12413 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -312,7 +312,7 @@ impl<'repo> io::Write for OdbWriter<'repo> { fn flush(&mut self) -> io::Result<()> { Ok(()) } } -pub type ForeachCb<'a> = FnMut(&Oid) -> bool + 'a; +pub type ForeachCb<'a> = dyn FnMut(&Oid) -> bool + 'a; struct ForeachCbData<'a> { pub callback: &'a mut ForeachCb<'a> diff --git a/src/packbuilder.rs b/src/packbuilder.rs index e3ed5132b6..1d03fbed44 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -14,8 +14,8 @@ pub enum PackBuilderStage { Deltafication, } -pub type ProgressCb<'a> = FnMut(PackBuilderStage, u32, u32) -> bool + 'a; -pub type ForEachCb<'a> = FnMut(&[u8]) -> bool + 'a; +pub type ProgressCb<'a> = dyn FnMut(PackBuilderStage, u32, u32) -> bool + 'a; +pub type ForEachCb<'a> = dyn FnMut(&[u8]) -> bool + 'a; /// A builder for creating a packfile pub struct PackBuilder<'repo> { diff --git a/src/panic.rs b/src/panic.rs index 7444df1099..c11de3a6f8 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -1,7 +1,7 @@ use std::any::Any; use std::cell::RefCell; -thread_local!(static LAST_ERROR: RefCell>> = { +thread_local!(static LAST_ERROR: RefCell>> = { RefCell::new(None) }); diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 562d3a2d6c..2167c83ac5 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -41,7 +41,7 @@ enum ProgressState { /// * `username_from_url` - the username that was embedded in the url, or `None` /// if it was not included. /// * `allowed_types` - a bitmask stating which cred types are ok to return. -pub type Credentials<'a> = FnMut(&str, Option<&str>, CredentialType) +pub type Credentials<'a> = dyn FnMut(&str, Option<&str>, CredentialType) -> Result + 'a; /// Callback to be invoked while a transfer is in progress. @@ -51,15 +51,15 @@ pub type Credentials<'a> = FnMut(&str, Option<&str>, CredentialType) /// continue. A return value of `false` will cancel the transfer. /// /// * `progress` - the progress being made so far. -pub type TransferProgress<'a> = FnMut(Progress) -> bool + 'a; +pub type TransferProgress<'a> = dyn FnMut(Progress) -> bool + 'a; /// Callback for receiving messages delivered by the transport. /// /// The return value indicates whether the network operation should continue. -pub type TransportMessage<'a> = FnMut(&[u8]) -> bool + 'a; +pub type TransportMessage<'a> = dyn FnMut(&[u8]) -> bool + 'a; /// Callback for whenever a reference is updated locally. -pub type UpdateTips<'a> = FnMut(&str, Oid, Oid) -> bool + 'a; +pub type UpdateTips<'a> = dyn FnMut(&str, Oid, Oid) -> bool + 'a; /// Callback for a custom certificate check. /// @@ -68,14 +68,14 @@ pub type UpdateTips<'a> = FnMut(&str, Oid, Oid) -> bool + 'a; /// /// The second argument is the hostname for the connection is passed as the last /// argument. -pub type CertificateCheck<'a> = FnMut(&Cert, &str) -> bool + 'a; +pub type CertificateCheck<'a> = dyn FnMut(&Cert, &str) -> bool + 'a; /// Callback for each updated reference on push. /// /// The first argument here is the `refname` of the reference, and the second is /// the status message sent by a server. If the status is `Some` then the update /// was rejected by the remote server with a reason why. -pub type PushUpdateReference<'a> = FnMut(&str, Option<&str>) -> Result<(), Error> + 'a; +pub type PushUpdateReference<'a> = dyn FnMut(&str, Option<&str>) -> Result<(), Error> + 'a; impl<'a> Default for RemoteCallbacks<'a> { fn default() -> Self { diff --git a/src/stash.rs b/src/stash.rs index 3d07465a3e..fffcb2329b 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -9,11 +9,11 @@ use std::mem; /// /// Return `true` to continue processing, or `false` to /// abort the stash application. -pub type StashApplyProgressCb<'a> = FnMut(StashApplyProgress) -> bool + 'a; +pub type StashApplyProgressCb<'a> = dyn FnMut(StashApplyProgress) -> bool + 'a; /// This is a callback function you can provide to iterate over all the /// stashed states that will be invoked per entry. -pub type StashCb<'a> = FnMut(usize, &str, &Oid) -> bool + 'a; +pub type StashCb<'a> = dyn FnMut(usize, &str, &Oid) -> bool + 'a; #[allow(unused)] /// Stash application options structure diff --git a/src/transport.rs b/src/transport.rs index 360f1dce99..f8d544ae63 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -40,7 +40,7 @@ pub trait SmartSubtransport: Send + 'static { /// returns a stream which can be read and written from in order to /// negotiate the git protocol. fn action(&self, url: &str, action: Service) - -> Result, Error>; + -> Result, Error>; /// Terminates a connection with the remote. /// @@ -73,7 +73,7 @@ pub trait SmartSubtransportStream: Read + Write + Send + 'static {} impl SmartSubtransportStream for T {} -type TransportFactory = Fn(&Remote) -> Result + Send + Sync + +type TransportFactory = dyn Fn(&Remote) -> Result + Send + Sync + 'static; /// Boxed data payload used for registering new transports. @@ -88,7 +88,7 @@ struct TransportData { #[repr(C)] struct RawSmartSubtransport { raw: raw::git_smart_subtransport, - obj: Box, + obj: Box, } /// Instance of a `git_smart_subtransport_stream`, must use `#[repr(C)]` to @@ -96,7 +96,7 @@ struct RawSmartSubtransport { #[repr(C)] struct RawSmartSubtransportStream { raw: raw::git_smart_subtransport_stream, - obj: Box, + obj: Box, } /// Add a custom transport definition, to be used in addition to the built-in diff --git a/src/tree.rs b/src/tree.rs index e99a0ddffe..62be5a8674 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -199,7 +199,7 @@ impl<'repo> Tree<'repo> { } } -type TreeWalkCb<'a, T> = FnMut(&str, &TreeEntry) -> T + 'a; +type TreeWalkCb<'a, T> = dyn FnMut(&str, &TreeEntry) -> T + 'a; extern fn treewalk_cb>(root: *const c_char, entry: *const raw::git_tree_entry, payload: *mut c_void) -> c_int { match panic::wrap(|| unsafe { diff --git a/src/treebuilder.rs b/src/treebuilder.rs index e8ea1057c4..8a5600ac85 100644 --- a/src/treebuilder.rs +++ b/src/treebuilder.rs @@ -98,7 +98,7 @@ impl<'repo> TreeBuilder<'repo> { } } -type FilterCb<'a> = FnMut(&TreeEntry) -> bool + 'a; +type FilterCb<'a> = dyn FnMut(&TreeEntry) -> bool + 'a; extern fn filter_cb(entry: *const raw::git_tree_entry, payload: *mut c_void) -> c_int { From 9f1f9d8875de057596a0e108f0db560f619bb885 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 4 Jun 2019 08:26:31 -0700 Subject: [PATCH 353/860] cargo fmt --- examples/add.rs | 20 +- examples/blame.rs | 28 +- examples/cat-file.rs | 48 +- examples/clone.rs | 54 +- examples/diff.rs | 106 +- examples/fetch.rs | 58 +- examples/init.rs | 27 +- examples/log.rs | 156 +- examples/ls-remote.rs | 15 +- examples/rev-list.rs | 53 +- examples/rev-parse.rs | 9 +- examples/status.rs | 184 ++- examples/tag.rs | 25 +- git2-curl/src/lib.rs | 114 +- git2-curl/tests/all.rs | 37 +- libgit2-sys/build.rs | 9 +- libgit2-sys/lib.rs | 3175 +++++++++++++++++++++------------------ src/blame.rs | 66 +- src/blob.rs | 38 +- src/branch.rs | 41 +- src/buf.rs | 22 +- src/build.rs | 148 +- src/call.rs | 42 +- src/cert.rs | 14 +- src/commit.rs | 146 +- src/config.rs | 82 +- src/cred.rs | 208 ++- src/describe.rs | 24 +- src/diff.rs | 302 ++-- src/error.rs | 27 +- src/index.rs | 270 ++-- src/lib.rs | 78 +- src/merge.rs | 17 +- src/message.rs | 49 +- src/note.rs | 53 +- src/object.rs | 44 +- src/odb.rs | 131 +- src/oid.rs | 82 +- src/oid_array.rs | 12 +- src/packbuilder.rs | 98 +- src/panic.rs | 2 +- src/patch.rs | 160 +- src/pathspec.rs | 151 +- src/rebase.rs | 70 +- src/reference.rs | 99 +- src/reflog.rs | 62 +- src/refspec.rs | 11 +- src/remote.rs | 192 ++- src/remote_callbacks.rs | 156 +- src/repo.rs | 1255 ++++++++++------ src/revspec.rs | 26 +- src/revwalk.rs | 26 +- src/signature.rs | 38 +- src/stash.rs | 103 +- src/status.rs | 93 +- src/string_array.rs | 32 +- src/submodule.rs | 102 +- src/tag.rs | 25 +- src/test.rs | 24 +- src/time.rs | 30 +- src/transport.rs | 130 +- src/tree.rs | 117 +- src/treebuilder.rs | 50 +- src/util.rs | 28 +- systest/build.rs | 32 +- systest/src/main.rs | 2 +- 66 files changed, 5392 insertions(+), 3736 deletions(-) diff --git a/examples/add.rs b/examples/add.rs index 3167cb074e..b4440ca5d8 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -15,14 +15,14 @@ #![deny(warnings)] #![allow(trivial_casts)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; -use std::path::Path; use docopt::Docopt; use git2::Repository; +use std::path::Path; #[derive(Deserialize)] struct Args { @@ -39,15 +39,20 @@ fn run(args: &Args) -> Result<(), git2::Error> { let cb = &mut |path: &Path, _matched_spec: &[u8]| -> i32 { let status = repo.status_file(path).unwrap(); - let ret = if status.contains(git2::Status::WT_MODIFIED) || - status.contains(git2::Status::WT_NEW) { + let ret = if status.contains(git2::Status::WT_MODIFIED) + || status.contains(git2::Status::WT_NEW) + { println!("add '{}'", path.display()); 0 } else { 1 }; - if args.flag_dry_run {1} else {ret} + if args.flag_dry_run { + 1 + } else { + ret + } }; let cb = if args.flag_verbose || args.flag_update { Some(cb as &mut git2::IndexMatchedPath) @@ -76,8 +81,9 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/blame.rs b/examples/blame.rs index 5f7bee3680..07452dde8d 100644 --- a/examples/blame.rs +++ b/examples/blame.rs @@ -12,17 +12,18 @@ * . */ -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; use docopt::Docopt; -use git2::{Repository, BlameOptions}; +use git2::{BlameOptions, Repository}; +use std::io::{BufRead, BufReader}; use std::path::Path; -use std::io::{BufReader, BufRead}; -#[derive(Deserialize)] #[allow(non_snake_case)] +#[derive(Deserialize)] +#[allow(non_snake_case)] struct Args { arg_path: String, arg_spec: Option, @@ -45,7 +46,6 @@ fn run(args: &Args) -> Result<(), git2::Error> { // Parse spec if let Some(spec) = args.arg_spec.as_ref() { - let revspec = try!(repo.revparse(spec)); let (oldest, newest) = if revspec.mode().contains(git2::RevparseMode::SINGLE) { @@ -66,7 +66,6 @@ fn run(args: &Args) -> Result<(), git2::Error> { commit_id = format!("{}", commit.id()) } } - } let spec = format!("{}:{}", commit_id, path.display()); @@ -76,11 +75,15 @@ fn run(args: &Args) -> Result<(), git2::Error> { let reader = BufReader::new(blob.content()); for (i, line) in reader.lines().enumerate() { - if let (Ok(line), Some(hunk)) = (line, blame.get_line(i+1)) { + if let (Ok(line), Some(hunk)) = (line, blame.get_line(i + 1)) { let sig = hunk.final_signature(); - println!("{} {} <{}> {}", hunk.final_commit_id(), - String::from_utf8_lossy(sig.name_bytes()), - String::from_utf8_lossy(sig.email_bytes()), line); + println!( + "{} {} <{}> {}", + hunk.final_commit_id(), + String::from_utf8_lossy(sig.name_bytes()), + String::from_utf8_lossy(sig.email_bytes()), + line + ); } } @@ -97,8 +100,9 @@ Options: -F follow only the first parent commits "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/cat-file.rs b/examples/cat-file.rs index 68117bd88d..ae7de5d179 100644 --- a/examples/cat-file.rs +++ b/examples/cat-file.rs @@ -14,15 +14,15 @@ #![deny(warnings)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; use std::io::{self, Write}; use docopt::Docopt; -use git2::{Repository, ObjectType, Blob, Commit, Signature, Tag, Tree}; +use git2::{Blob, Commit, ObjectType, Repository, Signature, Tag, Tree}; #[derive(Deserialize)] struct Args { @@ -63,9 +63,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { Some(ObjectType::Tree) => { show_tree(obj.as_tree().unwrap()); } - Some(ObjectType::Any) | None => { - println!("unknown {}", obj.id()) - } + Some(ObjectType::Any) | None => println!("unknown {}", obj.id()), } } Ok(()) @@ -100,22 +98,37 @@ fn show_tag(tag: &Tag) { fn show_tree(tree: &Tree) { for entry in tree.iter() { - println!("{:06o} {} {}\t{}", - entry.filemode(), - entry.kind().unwrap().str(), - entry.id(), - entry.name().unwrap()); + println!( + "{:06o} {} {}\t{}", + entry.filemode(), + entry.kind().unwrap().str(), + entry.id(), + entry.name().unwrap() + ); } } fn show_sig(header: &str, sig: Option) { - let sig = match sig { Some(s) => s, None => return }; + let sig = match sig { + Some(s) => s, + None => return, + }; let offset = sig.when().offset_minutes(); - let (sign, offset) = if offset < 0 {('-', -offset)} else {('+', offset)}; + let (sign, offset) = if offset < 0 { + ('-', -offset) + } else { + ('+', offset) + }; let (hours, minutes) = (offset / 60, offset % 60); - println!("{} {} {} {}{:02}{:02}", - header, sig, sig.when().seconds(), sign, hours, minutes); - + println!( + "{} {} {} {}{:02}{:02}", + header, + sig, + sig.when().seconds(), + sign, + hours, + minutes + ); } fn main() { @@ -133,8 +146,9 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/clone.rs b/examples/clone.rs index 3bd72bc2eb..86553b2d30 100644 --- a/examples/clone.rs +++ b/examples/clone.rs @@ -14,14 +14,14 @@ #![deny(warnings)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; use docopt::Docopt; -use git2::build::{RepoBuilder, CheckoutBuilder}; -use git2::{RemoteCallbacks, Progress, FetchOptions}; +use git2::build::{CheckoutBuilder, RepoBuilder}; +use git2::{FetchOptions, Progress, RemoteCallbacks}; use std::cell::RefCell; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -55,19 +55,31 @@ fn print(state: &mut State) { println!(""); state.newline = true; } - print!("Resolving deltas {}/{}\r", stats.indexed_deltas(), - stats.total_deltas()); + print!( + "Resolving deltas {}/{}\r", + stats.indexed_deltas(), + stats.total_deltas() + ); } else { - print!("net {:3}% ({:4} kb, {:5}/{:5}) / idx {:3}% ({:5}/{:5}) \ - / chk {:3}% ({:4}/{:4}) {}\r", - network_pct, kbytes, stats.received_objects(), - stats.total_objects(), - index_pct, stats.indexed_objects(), stats.total_objects(), - co_pct, state.current, state.total, - state.path - .as_ref() - .map(|s| s.to_string_lossy().into_owned()) - .unwrap_or_default()) + print!( + "net {:3}% ({:4} kb, {:5}/{:5}) / idx {:3}% ({:5}/{:5}) \ + / chk {:3}% ({:4}/{:4}) {}\r", + network_pct, + kbytes, + stats.received_objects(), + stats.total_objects(), + index_pct, + stats.indexed_objects(), + stats.total_objects(), + co_pct, + state.current, + state.total, + state + .path + .as_ref() + .map(|s| s.to_string_lossy().into_owned()) + .unwrap_or_default() + ) } io::stdout().flush().unwrap(); } @@ -99,8 +111,10 @@ fn run(args: &Args) -> Result<(), git2::Error> { let mut fo = FetchOptions::new(); fo.remote_callbacks(cb); - try!(RepoBuilder::new().fetch_options(fo).with_checkout(co) - .clone(&args.arg_url, Path::new(&args.arg_path))); + try!(RepoBuilder::new() + .fetch_options(fo) + .with_checkout(co) + .clone(&args.arg_url, Path::new(&args.arg_path))); println!(""); Ok(()) @@ -114,11 +128,11 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), } } - diff --git a/examples/diff.rs b/examples/diff.rs index 8664a0e304..e4dee88aa1 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -14,18 +14,19 @@ #![deny(warnings)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; use std::str; use docopt::Docopt; -use git2::{Repository, Error, Object, ObjectType, DiffOptions, Diff}; +use git2::{Diff, DiffOptions, Error, Object, ObjectType, Repository}; use git2::{DiffFindOptions, DiffFormat}; -#[derive(Deserialize)] #[allow(non_snake_case)] +#[derive(Deserialize)] +#[allow(non_snake_case)] struct Args { arg_from_oid: Option, arg_to_oid: Option, @@ -70,7 +71,11 @@ const GREEN: &'static str = "\u{1b}[32m"; const CYAN: &'static str = "\u{1b}[36m"; #[derive(PartialEq, Eq, Copy, Clone)] -enum Cache { Normal, Only, None } +enum Cache { + Normal, + Only, + None, +} fn run(args: &Args) -> Result<(), Error> { let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); @@ -87,11 +92,21 @@ fn run(args: &Args) -> Result<(), Error> { .include_untracked(args.flag_untracked) .patience(args.flag_patience) .minimal(args.flag_minimal); - if let Some(amt) = args.flag_unified { opts.context_lines(amt); } - if let Some(amt) = args.flag_inter_hunk_context { opts.interhunk_lines(amt); } - if let Some(amt) = args.flag_abbrev { opts.id_abbrev(amt); } - if let Some(ref s) = args.flag_src_prefix { opts.old_prefix(&s); } - if let Some(ref s) = args.flag_dst_prefix { opts.new_prefix(&s); } + if let Some(amt) = args.flag_unified { + opts.context_lines(amt); + } + if let Some(amt) = args.flag_inter_hunk_context { + opts.interhunk_lines(amt); + } + if let Some(amt) = args.flag_abbrev { + opts.id_abbrev(amt); + } + if let Some(ref s) = args.flag_src_prefix { + opts.old_prefix(&s); + } + if let Some(ref s) = args.flag_dst_prefix { + opts.new_prefix(&s); + } if let Some("diff-index") = args.flag_format.as_ref().map(|s| &s[..]) { opts.id_abbrev(40); } @@ -102,8 +117,7 @@ fn run(args: &Args) -> Result<(), Error> { let head = try!(tree_to_treeish(&repo, Some(&"HEAD".to_string()))).unwrap(); let mut diff = match (t1, t2, args.cache()) { (Some(t1), Some(t2), _) => { - try!(repo.diff_tree_to_tree(t1.as_tree(), t2.as_tree(), - Some(&mut opts))) + try!(repo.diff_tree_to_tree(t1.as_tree(), t2.as_tree(), Some(&mut opts))) } (t1, None, Cache::None) => { let t1 = t1.unwrap_or(head); @@ -114,18 +128,17 @@ fn run(args: &Args) -> Result<(), Error> { try!(repo.diff_tree_to_index(t1.as_tree(), None, Some(&mut opts))) } (Some(t1), None, _) => { - try!(repo.diff_tree_to_workdir_with_index(t1.as_tree(), - Some(&mut opts))) - } - (None, None, _) => { - try!(repo.diff_index_to_workdir(None, Some(&mut opts))) + try!(repo.diff_tree_to_workdir_with_index(t1.as_tree(), Some(&mut opts))) } + (None, None, _) => try!(repo.diff_index_to_workdir(None, Some(&mut opts))), (None, Some(_), _) => unreachable!(), }; // Apply rename and copy detection if requested - if args.flag_break_rewrites || args.flag_find_copies_harder || - args.flag_find_renames.is_some() || args.flag_find_copies.is_some() + if args.flag_break_rewrites + || args.flag_find_copies_harder + || args.flag_find_renames.is_some() + || args.flag_find_copies.is_some() { let mut opts = DiffFindOptions::new(); if let Some(t) = args.flag_find_renames { @@ -142,13 +155,14 @@ fn run(args: &Args) -> Result<(), Error> { } // Generate simple output - let stats = args.flag_stat | args.flag_numstat | args.flag_shortstat | - args.flag_summary; + let stats = args.flag_stat | args.flag_numstat | args.flag_shortstat | args.flag_summary; if stats { try!(print_stats(&diff, args)); } if args.flag_patch || !stats { - if args.color() { print!("{}", RESET); } + if args.color() { + print!("{}", RESET); + } let mut last_color = None; try!(diff.print(args.diff_format(), |_delta, _hunk, line| { if args.color() { @@ -159,7 +173,7 @@ fn run(args: &Args) -> Result<(), Error> { '<' => Some(RED), 'F' => Some(BOLD), 'H' => Some(CYAN), - _ => None + _ => None, }; if args.color() && next != last_color { if last_color == Some(BOLD) || next == Some(BOLD) { @@ -177,7 +191,9 @@ fn run(args: &Args) -> Result<(), Error> { print!("{}", str::from_utf8(line.content()).unwrap()); true })); - if args.color() { print!("{}", RESET); } + if args.color() { + print!("{}", RESET); + } } Ok(()) @@ -203,9 +219,14 @@ fn print_stats(diff: &Diff, args: &Args) -> Result<(), Error> { Ok(()) } -fn tree_to_treeish<'a>(repo: &'a Repository, arg: Option<&String>) - -> Result>, Error> { - let arg = match arg { Some(s) => s, None => return Ok(None) }; +fn tree_to_treeish<'a>( + repo: &'a Repository, + arg: Option<&String>, +) -> Result>, Error> { + let arg = match arg { + Some(s) => s, + None => return Ok(None), + }; let obj = try!(repo.revparse_single(arg)); let tree = try!(obj.peel(ObjectType::Tree)); Ok(Some(tree)) @@ -213,17 +234,27 @@ fn tree_to_treeish<'a>(repo: &'a Repository, arg: Option<&String>) impl Args { fn cache(&self) -> Cache { - if self.flag_cached {Cache::Only} - else if self.flag_nocached {Cache::None} - else {Cache::Normal} + if self.flag_cached { + Cache::Only + } else if self.flag_nocached { + Cache::None + } else { + Cache::Normal + } + } + fn color(&self) -> bool { + self.flag_color && !self.flag_no_color } - fn color(&self) -> bool { self.flag_color && !self.flag_no_color } fn diff_format(&self) -> DiffFormat { - if self.flag_patch {DiffFormat::Patch} - else if self.flag_name_only {DiffFormat::NameOnly} - else if self.flag_name_status {DiffFormat::NameStatus} - else if self.flag_raw {DiffFormat::Raw} - else { + if self.flag_patch { + DiffFormat::Patch + } else if self.flag_name_only { + DiffFormat::NameOnly + } else if self.flag_name_status { + DiffFormat::NameStatus + } else if self.flag_raw { + DiffFormat::Raw + } else { match self.flag_format.as_ref().map(|s| &s[..]) { Some("name") => DiffFormat::NameOnly, Some("name-status") => DiffFormat::NameStatus, @@ -275,8 +306,9 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/fetch.rs b/examples/fetch.rs index c667d7b633..a4d36e8e76 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -14,13 +14,13 @@ #![deny(warnings)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; use docopt::Docopt; -use git2::{Repository, RemoteCallbacks, AutotagOption, FetchOptions}; +use git2::{AutotagOption, FetchOptions, RemoteCallbacks, Repository}; use std::io::{self, Write}; use std::str; @@ -36,9 +36,9 @@ fn run(args: &Args) -> Result<(), git2::Error> { // Figure out whether it's a named remote or a URL println!("Fetching {} for repo", remote); let mut cb = RemoteCallbacks::new(); - let mut remote = try!(repo.find_remote(remote).or_else(|_| { - repo.remote_anonymous(remote) - })); + let mut remote = try!(repo + .find_remote(remote) + .or_else(|_| { repo.remote_anonymous(remote) })); cb.sideband_progress(|data| { print!("remote: {}", str::from_utf8(data).unwrap()); io::stdout().flush().unwrap(); @@ -62,14 +62,19 @@ fn run(args: &Args) -> Result<(), git2::Error> { // the download rate. cb.transfer_progress(|stats| { if stats.received_objects() == stats.total_objects() { - print!("Resolving deltas {}/{}\r", stats.indexed_deltas(), - stats.total_deltas()); + print!( + "Resolving deltas {}/{}\r", + stats.indexed_deltas(), + stats.total_deltas() + ); } else if stats.total_objects() > 0 { - print!("Received {}/{} objects ({}) in {} bytes\r", - stats.received_objects(), - stats.total_objects(), - stats.indexed_objects(), - stats.received_bytes()); + print!( + "Received {}/{} objects ({}) in {} bytes\r", + stats.received_objects(), + stats.total_objects(), + stats.indexed_objects(), + stats.received_bytes() + ); } io::stdout().flush().unwrap(); true @@ -87,14 +92,21 @@ fn run(args: &Args) -> Result<(), git2::Error> { // how many objects we saved from having to cross the network. let stats = remote.stats(); if stats.local_objects() > 0 { - println!("\rReceived {}/{} objects in {} bytes (used {} local \ - objects)", stats.indexed_objects(), - stats.total_objects(), stats.received_bytes(), - stats.local_objects()); + println!( + "\rReceived {}/{} objects in {} bytes (used {} local \ + objects)", + stats.indexed_objects(), + stats.total_objects(), + stats.received_bytes(), + stats.local_objects() + ); } else { - println!("\rReceived {}/{} objects in {} bytes", - stats.indexed_objects(), stats.total_objects(), - stats.received_bytes()); + println!( + "\rReceived {}/{} objects in {} bytes", + stats.indexed_objects(), + stats.total_objects(), + stats.received_bytes() + ); } } @@ -105,8 +117,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { // commits. This may be needed even if there was no packfile to download, // which can happen e.g. when the branches have been changed but all the // needed objects are available locally. - try!(remote.update_tips(None, true, - AutotagOption::Unspecified, None)); + try!(remote.update_tips(None, true, AutotagOption::Unspecified, None)); Ok(()) } @@ -119,8 +130,9 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/init.rs b/examples/init.rs index 0f6b838098..b547efff83 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -14,14 +14,14 @@ #![deny(warnings)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; use docopt::Docopt; -use git2::{Repository, RepositoryInitOptions, RepositoryInitMode, Error}; -use std::path::{PathBuf, Path}; +use git2::{Error, Repository, RepositoryInitMode, RepositoryInitOptions}; +use std::path::{Path, PathBuf}; #[derive(Deserialize)] struct Args { @@ -36,9 +36,11 @@ struct Args { fn run(args: &Args) -> Result<(), Error> { let mut path = PathBuf::from(&args.arg_directory); - let repo = if !args.flag_bare && args.flag_template.is_none() && - args.flag_shared.is_none() && - args.flag_separate_git_dir.is_none() { + let repo = if !args.flag_bare + && args.flag_template.is_none() + && args.flag_shared.is_none() + && args.flag_separate_git_dir.is_none() + { try!(Repository::init(&path)) } else { let mut opts = RepositoryInitOptions::new(); @@ -116,12 +118,8 @@ fn parse_shared(shared: &str) -> Result { _ => { if shared.starts_with('0') { match u32::from_str_radix(&shared[1..], 8).ok() { - Some(n) => { - Ok(RepositoryInitMode::from_bits_truncate(n)) - } - None => { - Err(Error::from_str("invalid octal value for --shared")) - } + Some(n) => Ok(RepositoryInitMode::from_bits_truncate(n)), + None => Err(Error::from_str("invalid octal value for --shared")), } } else { Err(Error::from_str("unknown value for --shared")) @@ -143,8 +141,9 @@ Options: --shared permissions to create the repository with "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/log.rs b/examples/log.rs index 4a3912ebfc..141766c59b 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -20,10 +20,10 @@ extern crate docopt; extern crate git2; extern crate time; -use std::str; use docopt::Docopt; -use git2::{Repository, Signature, Commit, ObjectType, Time, DiffOptions}; -use git2::{Pathspec, Error, DiffFormat}; +use git2::{Commit, DiffOptions, ObjectType, Repository, Signature, Time}; +use git2::{DiffFormat, Error, Pathspec}; +use std::str; #[derive(Deserialize)] struct Args { @@ -53,19 +53,25 @@ fn run(args: &Args) -> Result<(), Error> { let mut revwalk = repo.revwalk()?; // Prepare the revwalk based on CLI parameters - let base = if args.flag_reverse {git2::Sort::REVERSE} else {git2::Sort::NONE}; - revwalk.set_sorting(base | if args.flag_topo_order { - git2::Sort::TOPOLOGICAL - } else if args.flag_date_order { - git2::Sort::TIME + let base = if args.flag_reverse { + git2::Sort::REVERSE } else { git2::Sort::NONE - }); + }; + revwalk.set_sorting( + base | if args.flag_topo_order { + git2::Sort::TOPOLOGICAL + } else if args.flag_date_order { + git2::Sort::TIME + } else { + git2::Sort::NONE + }, + ); for commit in &args.arg_commit { if commit.starts_with('^') { let obj = repo.revparse_single(&commit[1..])?; revwalk.hide(obj.id())?; - continue + continue; } let revspec = repo.revparse(commit)?; if revspec.mode().contains(git2::RevparseMode::SINGLE) { @@ -96,43 +102,67 @@ fn run(args: &Args) -> Result<(), Error> { // Filter our revwalk based on the CLI parameters macro_rules! filter_try { - ($e:expr) => (match $e { Ok(t) => t, Err(e) => return Some(Err(e)) }) + ($e:expr) => { + match $e { + Ok(t) => t, + Err(e) => return Some(Err(e)), + } + }; } - let revwalk = revwalk.filter_map(|id| { - let id = filter_try!(id); - let commit = filter_try!(repo.find_commit(id)); - let parents = commit.parents().len(); - if parents < args.min_parents() { return None } - if let Some(n) = args.max_parents() { - if parents >= n { return None } - } - if !args.arg_spec.is_empty() { - match commit.parents().len() { - 0 => { - let tree = filter_try!(commit.tree()); - let flags = git2::PathspecFlags::NO_MATCH_ERROR; - if ps.match_tree(&tree, flags).is_err() { return None } + let revwalk = revwalk + .filter_map(|id| { + let id = filter_try!(id); + let commit = filter_try!(repo.find_commit(id)); + let parents = commit.parents().len(); + if parents < args.min_parents() { + return None; + } + if let Some(n) = args.max_parents() { + if parents >= n { + return None; } - _ => { - let m = commit.parents().all(|parent| { - match_with_parent(&repo, &commit, &parent, &mut diffopts) - .unwrap_or(false) - }); - if !m { return None } + } + if !args.arg_spec.is_empty() { + match commit.parents().len() { + 0 => { + let tree = filter_try!(commit.tree()); + let flags = git2::PathspecFlags::NO_MATCH_ERROR; + if ps.match_tree(&tree, flags).is_err() { + return None; + } + } + _ => { + let m = commit.parents().all(|parent| { + match_with_parent(&repo, &commit, &parent, &mut diffopts) + .unwrap_or(false) + }); + if !m { + return None; + } + } } } - } - if !sig_matches(&commit.author(), &args.flag_author) { return None } - if !sig_matches(&commit.committer(), &args.flag_committer) { return None } - if !log_message_matches(commit.message(), &args.flag_grep) { return None } - Some(Ok(commit)) - }).skip(args.flag_skip.unwrap_or(0)).take(args.flag_max_count.unwrap_or(!0)); + if !sig_matches(&commit.author(), &args.flag_author) { + return None; + } + if !sig_matches(&commit.committer(), &args.flag_committer) { + return None; + } + if !log_message_matches(commit.message(), &args.flag_grep) { + return None; + } + Some(Ok(commit)) + }) + .skip(args.flag_skip.unwrap_or(0)) + .take(args.flag_max_count.unwrap_or(!0)); // print! for commit in revwalk { let commit = commit?; print_commit(&commit); - if !args.flag_patch || commit.parents().len() > 1 { continue } + if !args.flag_patch || commit.parents().len() > 1 { + continue; + } let a = if commit.parents().len() == 1 { let parent = commit.parent(0)?; Some(parent.tree()?) @@ -140,8 +170,7 @@ fn run(args: &Args) -> Result<(), Error> { None }; let b = commit.tree()?; - let diff = repo.diff_tree_to_tree(a.as_ref(), Some(&b), - Some(&mut diffopts2))?; + let diff = repo.diff_tree_to_tree(a.as_ref(), Some(&b), Some(&mut diffopts2))?; diff.print(DiffFormat::Patch, |_delta, _hunk, line| { match line.origin() { ' ' | '+' | '-' => print!("{}", line.origin()), @@ -158,10 +187,10 @@ fn run(args: &Args) -> Result<(), Error> { fn sig_matches(sig: &Signature, arg: &Option) -> bool { match *arg { Some(ref s) => { - sig.name().map(|n| n.contains(s)).unwrap_or(false) || - sig.email().map(|n| n.contains(s)).unwrap_or(false) + sig.name().map(|n| n.contains(s)).unwrap_or(false) + || sig.email().map(|n| n.contains(s)).unwrap_or(false) } - None => true + None => true, } } @@ -201,17 +230,25 @@ fn print_time(time: &Time, prefix: &str) { n => (n, '+'), }; let (hours, minutes) = (offset / 60, offset % 60); - let ts = time::Timespec::new(time.seconds() + - (time.offset_minutes() as i64) * 60, 0); + let ts = time::Timespec::new(time.seconds() + (time.offset_minutes() as i64) * 60, 0); let time = time::at(ts); - println!("{}{} {}{:02}{:02}", prefix, - time.strftime("%a %b %e %T %Y").unwrap(), sign, hours, minutes); - + println!( + "{}{} {}{:02}{:02}", + prefix, + time.strftime("%a %b %e %T %Y").unwrap(), + sign, + hours, + minutes + ); } -fn match_with_parent(repo: &Repository, commit: &Commit, parent: &Commit, - opts: &mut DiffOptions) -> Result { +fn match_with_parent( + repo: &Repository, + commit: &Commit, + parent: &Commit, + opts: &mut DiffOptions, +) -> Result { let a = parent.tree()?; let b = commit.tree()?; let diff = repo.diff_tree_to_tree(Some(&a), Some(&b), Some(opts))?; @@ -220,13 +257,19 @@ fn match_with_parent(repo: &Repository, commit: &Commit, parent: &Commit, impl Args { fn min_parents(&self) -> usize { - if self.flag_no_min_parents { return 0 } - self.flag_min_parents.unwrap_or(if self.flag_merges {2} else {0}) + if self.flag_no_min_parents { + return 0; + } + self.flag_min_parents + .unwrap_or(if self.flag_merges { 2 } else { 0 }) } fn max_parents(&self) -> Option { - if self.flag_no_max_parents { return None } - self.flag_max_parents.or(if self.flag_no_merges {Some(1)} else {None}) + if self.flag_no_max_parents { + return None; + } + self.flag_max_parents + .or(if self.flag_no_merges { Some(1) } else { None }) } } @@ -254,8 +297,9 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/ls-remote.rs b/examples/ls-remote.rs index 5da9575f7b..4d66099ba9 100644 --- a/examples/ls-remote.rs +++ b/examples/ls-remote.rs @@ -14,13 +14,13 @@ #![deny(warnings)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; use docopt::Docopt; -use git2::{Repository, Direction}; +use git2::{Direction, Repository}; #[derive(Deserialize)] struct Args { @@ -30,9 +30,9 @@ struct Args { fn run(args: &Args) -> Result<(), git2::Error> { let repo = try!(Repository::open(".")); let remote = &args.arg_remote; - let mut remote = try!(repo.find_remote(remote).or_else(|_| { - repo.remote_anonymous(remote) - })); + let mut remote = try!(repo + .find_remote(remote) + .or_else(|_| { repo.remote_anonymous(remote) })); // Connect to the remote and call the printing function for each of the // remote references. @@ -54,8 +54,9 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/rev-list.rs b/examples/rev-list.rs index db9bd82cad..84a409e200 100644 --- a/examples/rev-list.rs +++ b/examples/rev-list.rs @@ -15,13 +15,13 @@ #![deny(warnings)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; use docopt::Docopt; -use git2::{Repository, Error, Revwalk, Oid}; +use git2::{Error, Oid, Repository, Revwalk}; #[derive(Deserialize)] struct Args { @@ -36,25 +36,38 @@ fn run(args: &Args) -> Result<(), git2::Error> { let repo = try!(Repository::open(".")); let mut revwalk = try!(repo.revwalk()); - let base = if args.flag_reverse {git2::Sort::REVERSE} else {git2::Sort::NONE}; - revwalk.set_sorting(base | if args.flag_topo_order { - git2::Sort::TOPOLOGICAL - } else if args.flag_date_order { - git2::Sort::TIME + let base = if args.flag_reverse { + git2::Sort::REVERSE } else { git2::Sort::NONE - }); + }; + revwalk.set_sorting( + base | if args.flag_topo_order { + git2::Sort::TOPOLOGICAL + } else if args.flag_date_order { + git2::Sort::TIME + } else { + git2::Sort::NONE + }, + ); - let specs = args.flag_not.iter().map(|s| (s, true)) - .chain(args.arg_spec.iter().map(|s| (s, false))) - .map(|(spec, hide)| { - if spec.starts_with('^') {(&spec[1..], !hide)} else {(&spec[..], hide)} - }); + let specs = args + .flag_not + .iter() + .map(|s| (s, true)) + .chain(args.arg_spec.iter().map(|s| (s, false))) + .map(|(spec, hide)| { + if spec.starts_with('^') { + (&spec[1..], !hide) + } else { + (&spec[..], hide) + } + }); for (spec, hide) in specs { let id = if spec.contains("..") { let revspec = try!(repo.revparse(spec)); if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { - return Err(Error::from_str("merge bases not implemented")) + return Err(Error::from_str("merge bases not implemented")); } try!(push(&mut revwalk, revspec.from().unwrap().id(), !hide)); revspec.to().unwrap().id() @@ -72,7 +85,11 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn push(revwalk: &mut Revwalk, id: Oid, hide: bool) -> Result<(), Error> { - if hide {revwalk.hide(id)} else {revwalk.push(id)} + if hide { + revwalk.hide(id) + } else { + revwalk.push(id) + } } fn main() { @@ -87,11 +104,11 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), } } - diff --git a/examples/rev-parse.rs b/examples/rev-parse.rs index 178cd2d3e2..f0642f0416 100644 --- a/examples/rev-parse.rs +++ b/examples/rev-parse.rs @@ -14,8 +14,8 @@ #![deny(warnings)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; @@ -48,7 +48,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { println!("^{}", from.id()); } else { - return Err(git2::Error::from_str("invalid results from revparse")) + return Err(git2::Error::from_str("invalid results from revparse")); } Ok(()) } @@ -61,8 +61,9 @@ Options: --git-dir directory of the git repository to check "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/status.rs b/examples/status.rs index 87ca6ec315..f5104d6584 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -14,15 +14,15 @@ #![deny(warnings)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; +use docopt::Docopt; +use git2::{Error, ErrorCode, Repository, StatusOptions, SubmoduleIgnore}; use std::str; use std::time::Duration; -use docopt::Docopt; -use git2::{Repository, Error, StatusOptions, ErrorCode, SubmoduleIgnore}; #[derive(Deserialize)] struct Args { @@ -40,20 +40,28 @@ struct Args { } #[derive(Eq, PartialEq)] -enum Format { Long, Short, Porcelain } +enum Format { + Long, + Short, + Porcelain, +} fn run(args: &Args) -> Result<(), Error> { let path = args.flag_git_dir.clone().unwrap_or_else(|| ".".to_string()); let repo = try!(Repository::open(&path)); if repo.is_bare() { - return Err(Error::from_str("cannot report status on bare repository")) + return Err(Error::from_str("cannot report status on bare repository")); } let mut opts = StatusOptions::new(); opts.include_ignored(args.flag_ignored); match args.flag_untracked_files.as_ref().map(|s| &s[..]) { - Some("no") => { opts.include_untracked(false); } - Some("normal") => { opts.include_untracked(true); } + Some("no") => { + opts.include_untracked(false); + } + Some("normal") => { + opts.include_untracked(true); + } Some("all") => { opts.include_untracked(true).recurse_untracked_dirs(true); } @@ -61,7 +69,9 @@ fn run(args: &Args) -> Result<(), Error> { None => {} } match args.flag_ignore_submodules.as_ref().map(|s| &s[..]) { - Some("all") => { opts.exclude_submodules(true); } + Some("all") => { + opts.exclude_submodules(true); + } Some(_) => return Err(Error::from_str("invalid ignore-submodules value")), None => {} } @@ -93,7 +103,7 @@ fn run(args: &Args) -> Result<(), Error> { if args.flag_repeat { std::thread::sleep(Duration::new(10, 0)); } else { - return Ok(()) + return Ok(()); } } } @@ -101,15 +111,18 @@ fn run(args: &Args) -> Result<(), Error> { fn show_branch(repo: &Repository, format: &Format) -> Result<(), Error> { let head = match repo.head() { Ok(head) => Some(head), - Err(ref e) if e.code() == ErrorCode::UnbornBranch || - e.code() == ErrorCode::NotFound => None, + Err(ref e) if e.code() == ErrorCode::UnbornBranch || e.code() == ErrorCode::NotFound => { + None + } Err(e) => return Err(e), }; let head = head.as_ref().and_then(|h| h.shorthand()); if format == &Format::Long { - println!("# On branch {}", - head.unwrap_or("Not currently on any branch")); + println!( + "# On branch {}", + head.unwrap_or("Not currently on any branch") + ); } else { println!("## {}", head.unwrap_or("HEAD (no branch)")); } @@ -120,8 +133,11 @@ fn print_submodules(repo: &Repository) -> Result<(), Error> { let modules = try!(repo.submodules()); println!("# Submodules"); for sm in &modules { - println!("# - submodule '{}' at {}", sm.name().unwrap(), - sm.path().display()); + println!( + "# - submodule '{}' at {}", + sm.name().unwrap(), + sm.path().display() + ); } Ok(()) } @@ -135,7 +151,10 @@ fn print_long(statuses: &git2::Statuses) { let mut changed_in_workdir = false; // Print index changes - for entry in statuses.iter().filter(|e| e.status() != git2::Status::CURRENT) { + for entry in statuses + .iter() + .filter(|e| e.status() != git2::Status::CURRENT) + { if entry.status().contains(git2::Status::WT_DELETED) { rm_in_workdir = true; } @@ -148,10 +167,12 @@ fn print_long(statuses: &git2::Statuses) { _ => continue, }; if !header { - println!("\ + println!( + "\ # Changes to be committed: # (use \"git reset HEAD ...\" to unstage) -#"); +#" + ); header = true; } @@ -159,8 +180,7 @@ fn print_long(statuses: &git2::Statuses) { let new_path = entry.head_to_index().unwrap().new_file().path(); match (old_path, new_path) { (Some(old), Some(new)) if old != new => { - println!("#\t{} {} -> {}", istatus, old.display(), - new.display()); + println!("#\t{} {} -> {}", istatus, old.display(), new.display()); } (old, new) => { println!("#\t{} {}", istatus, old.or(new).unwrap().display()); @@ -179,9 +199,8 @@ fn print_long(statuses: &git2::Statuses) { // With `Status::OPT_INCLUDE_UNMODIFIED` (not used in this example) // `index_to_workdir` may not be `None` even if there are no differences, // in which case it will be a `Delta::Unmodified`. - if entry.status() == git2::Status::CURRENT || - entry.index_to_workdir().is_none() { - continue + if entry.status() == git2::Status::CURRENT || entry.index_to_workdir().is_none() { + continue; } let istatus = match entry.status() { @@ -193,12 +212,15 @@ fn print_long(statuses: &git2::Statuses) { }; if !header { - println!("\ + println!( + "\ # Changes not staged for commit: # (use \"git add{} ...\" to update what will be committed) # (use \"git checkout -- ...\" to discard changes in working directory) #\ - ", if rm_in_workdir {"/rm"} else {""}); + ", + if rm_in_workdir { "/rm" } else { "" } + ); header = true; } @@ -206,8 +228,7 @@ fn print_long(statuses: &git2::Statuses) { let new_path = entry.index_to_workdir().unwrap().new_file().path(); match (old_path, new_path) { (Some(old), Some(new)) if old != new => { - println!("#\t{} {} -> {}", istatus, old.display(), - new.display()); + println!("#\t{} {} -> {}", istatus, old.display(), new.display()); } (old, new) => { println!("#\t{} {}", istatus, old.or(new).unwrap().display()); @@ -222,12 +243,17 @@ fn print_long(statuses: &git2::Statuses) { header = false; // Print untracked files - for entry in statuses.iter().filter(|e| e.status() == git2::Status::WT_NEW) { + for entry in statuses + .iter() + .filter(|e| e.status() == git2::Status::WT_NEW) + { if !header { - println!("\ + println!( + "\ # Untracked files # (use \"git add ...\" to include in what will be committed) -#"); +#" + ); header = true; } let file = entry.index_to_workdir().unwrap().old_file().path().unwrap(); @@ -236,12 +262,17 @@ fn print_long(statuses: &git2::Statuses) { header = false; // Print ignored files - for entry in statuses.iter().filter(|e| e.status() == git2::Status::IGNORED) { + for entry in statuses + .iter() + .filter(|e| e.status() == git2::Status::IGNORED) + { if !header { - println!("\ + println!( + "\ # Ignored files # (use \"git add -f ...\" to include in what will be committed) -#"); +#" + ); header = true; } let file = entry.index_to_workdir().unwrap().old_file().path().unwrap(); @@ -249,15 +280,20 @@ fn print_long(statuses: &git2::Statuses) { } if !changes_in_index && changed_in_workdir { - println!("no changes added to commit (use \"git add\" and/or \ - \"git commit -a\")"); + println!( + "no changes added to commit (use \"git add\" and/or \ + \"git commit -a\")" + ); } } // This version of the output prefixes each path with two status columns and // shows submodule status information. fn print_short(repo: &Repository, statuses: &git2::Statuses) { - for entry in statuses.iter().filter(|e| e.status() != git2::Status::CURRENT) { + for entry in statuses + .iter() + .filter(|e| e.status() != git2::Status::CURRENT) + { let mut istatus = match entry.status() { s if s.contains(git2::Status::INDEX_NEW) => 'A', s if s.contains(git2::Status::INDEX_MODIFIED) => 'M', @@ -268,7 +304,10 @@ fn print_short(repo: &Repository, statuses: &git2::Statuses) { }; let mut wstatus = match entry.status() { s if s.contains(git2::Status::WT_NEW) => { - if istatus == ' ' { istatus = '?'; } '?' + if istatus == ' ' { + istatus = '?'; + } + '?' } s if s.contains(git2::Status::WT_MODIFIED) => 'M', s if s.contains(git2::Status::WT_DELETED) => 'D', @@ -281,7 +320,9 @@ fn print_short(repo: &Repository, statuses: &git2::Statuses) { istatus = '!'; wstatus = '!'; } - if istatus == '?' && wstatus == '?' { continue } + if istatus == '?' && wstatus == '?' { + continue; + } let mut extra = ""; // A commit in a tree is how submodules are stored, so let's go take a @@ -290,14 +331,17 @@ fn print_short(repo: &Repository, statuses: &git2::Statuses) { // TODO: check for GIT_FILEMODE_COMMIT let status = entry.index_to_workdir().and_then(|diff| { let ignore = SubmoduleIgnore::Unspecified; - diff.new_file().path_bytes() + diff.new_file() + .path_bytes() .and_then(|s| str::from_utf8(s).ok()) .and_then(|name| repo.submodule_status(name, ignore).ok()) }); if let Some(status) = status { if status.contains(git2::SubmoduleStatus::WD_MODIFIED) { extra = " (new commits)"; - } else if status.contains(git2::SubmoduleStatus::WD_INDEX_MODIFIED) || status.contains(git2::SubmoduleStatus::WD_WD_MODIFIED) { + } else if status.contains(git2::SubmoduleStatus::WD_INDEX_MODIFIED) + || status.contains(git2::SubmoduleStatus::WD_WD_MODIFIED) + { extra = " (modified content)"; } else if status.contains(git2::SubmoduleStatus::WD_UNTRACKED) { extra = " (untracked content)"; @@ -316,28 +360,57 @@ fn print_short(repo: &Repository, statuses: &git2::Statuses) { } match (istatus, wstatus) { - ('R', 'R') => println!("RR {} {} {}{}", a.unwrap().display(), - b.unwrap().display(), c.unwrap().display(), - extra), - ('R', w) => println!("R{} {} {}{}", w, a.unwrap().display(), - b.unwrap().display(), extra), - (i, 'R') => println!("{}R {} {}{}", i, a.unwrap().display(), - c.unwrap().display(), extra), + ('R', 'R') => println!( + "RR {} {} {}{}", + a.unwrap().display(), + b.unwrap().display(), + c.unwrap().display(), + extra + ), + ('R', w) => println!( + "R{} {} {}{}", + w, + a.unwrap().display(), + b.unwrap().display(), + extra + ), + (i, 'R') => println!( + "{}R {} {}{}", + i, + a.unwrap().display(), + c.unwrap().display(), + extra + ), (i, w) => println!("{}{} {}{}", i, w, a.unwrap().display(), extra), } } - for entry in statuses.iter().filter(|e| e.status() == git2::Status::WT_NEW) { - println!("?? {}", entry.index_to_workdir().unwrap().old_file() - .path().unwrap().display()); + for entry in statuses + .iter() + .filter(|e| e.status() == git2::Status::WT_NEW) + { + println!( + "?? {}", + entry + .index_to_workdir() + .unwrap() + .old_file() + .path() + .unwrap() + .display() + ); } } impl Args { fn format(&self) -> Format { - if self.flag_short { Format::Short } - else if self.flag_porcelain || self.flag_z { Format::Porcelain } - else { Format::Long } + if self.flag_short { + Format::Short + } else if self.flag_porcelain || self.flag_z { + Format::Porcelain + } else { + Format::Long + } } } @@ -360,8 +433,9 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/tag.rs b/examples/tag.rs index f0ff3a2193..c95e5a5d27 100644 --- a/examples/tag.rs +++ b/examples/tag.rs @@ -14,14 +14,14 @@ #![deny(warnings)] -extern crate git2; extern crate docopt; +extern crate git2; #[macro_use] extern crate serde_derive; -use std::str; use docopt::Docopt; -use git2::{Repository, Error, Tag, Commit}; +use git2::{Commit, Error, Repository, Tag}; +use std::str; #[derive(Deserialize)] struct Args { @@ -48,14 +48,15 @@ fn run(args: &Args) -> Result<(), Error> { } else { try!(repo.tag_lightweight(name, &obj, args.flag_force)); } - } else if let Some(ref name) = args.flag_delete { let obj = try!(repo.revparse_single(name)); let id = try!(obj.short_id()); try!(repo.tag_delete(name)); - println!("Deleted tag '{}' (was {})", name, - str::from_utf8(&*id).unwrap()); - + println!( + "Deleted tag '{}' (was {})", + name, + str::from_utf8(&*id).unwrap() + ); } else if args.flag_list { let pattern = args.arg_pattern.as_ref().map(|s| &s[..]).unwrap_or("*"); for name in try!(repo.tag_names(Some(pattern))).iter() { @@ -97,7 +98,10 @@ fn print_name(name: &str) { } fn print_list_lines(message: Option<&str>, args: &Args) { - let message = match message { Some(s) => s, None => return }; + let message = match message { + Some(s) => s, + None => return, + }; let mut lines = message.lines().filter(|l| !l.trim().is_empty()); if let Some(first) = lines.next() { print!("{}", first); @@ -125,8 +129,9 @@ Options: -h, --help show this message "; - let args = Docopt::new(USAGE).and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Docopt::new(USAGE) + .and_then(|d| d.deserialize()) + .unwrap_or_else(|e| e.exit()); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index bbf25ac83e..81cf6546a7 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -17,21 +17,22 @@ #![doc(html_root_url = "http://alexcrichton.com/git2-rs")] -extern crate git2; extern crate curl; +extern crate git2; extern crate url; -#[macro_use] extern crate log; +#[macro_use] +extern crate log; use std::error; use std::io::prelude::*; use std::io::{self, Cursor}; use std::str; -use std::sync::{Once, ONCE_INIT, Arc, Mutex}; +use std::sync::{Arc, Mutex, Once, ONCE_INIT}; use curl::easy::{Easy, List}; +use git2::transport::SmartSubtransportStream; +use git2::transport::{Service, SmartSubtransport, Transport}; use git2::Error; -use git2::transport::{SmartSubtransportStream}; -use git2::transport::{Transport, SmartSubtransport, Service}; use url::Url; struct CurlTransport { @@ -40,7 +41,7 @@ struct CurlTransport { /// /// This is an empty string until the first action is performed. /// If there is an HTTP redirect, this will be updated with the new URL. - base_url: Arc> + base_url: Arc>, } struct CurlSubtransport { @@ -75,43 +76,39 @@ pub unsafe fn register(handle: Easy) { let handle = Arc::new(Mutex::new(handle)); let handle2 = handle.clone(); INIT.call_once(move || { - git2::transport::register("http", move |remote| { - factory(remote, handle.clone()) - }).unwrap(); - git2::transport::register("https", move |remote| { - factory(remote, handle2.clone()) - }).unwrap(); + git2::transport::register("http", move |remote| factory(remote, handle.clone())).unwrap(); + git2::transport::register("https", move |remote| factory(remote, handle2.clone())).unwrap(); }); } -fn factory(remote: &git2::Remote, handle: Arc>) - -> Result { - Transport::smart(remote, true, CurlTransport { - handle: handle, - base_url: Arc::new(Mutex::new(String::new())) - }) +fn factory(remote: &git2::Remote, handle: Arc>) -> Result { + Transport::smart( + remote, + true, + CurlTransport { + handle: handle, + base_url: Arc::new(Mutex::new(String::new())), + }, + ) } impl SmartSubtransport for CurlTransport { - fn action(&self, url: &str, action: Service) - -> Result, Error> { + fn action( + &self, + url: &str, + action: Service, + ) -> Result, Error> { let mut base_url = self.base_url.lock().unwrap(); if base_url.len() == 0 { *base_url = url.to_string(); } let (service, path, method) = match action { - Service::UploadPackLs => { - ("upload-pack", "/info/refs?service=git-upload-pack", "GET") - } - Service::UploadPack => { - ("upload-pack", "/git-upload-pack", "POST") - } + Service::UploadPackLs => ("upload-pack", "/info/refs?service=git-upload-pack", "GET"), + Service::UploadPack => ("upload-pack", "/git-upload-pack", "POST"), Service::ReceivePackLs => { ("receive-pack", "/info/refs?service=git-receive-pack", "GET") } - Service::ReceivePack => { - ("receive-pack", "/git-receive-pack", "POST") - } + Service::ReceivePack => ("receive-pack", "/git-receive-pack", "POST"), }; info!("action {} {}", service, path); Ok(Box::new(CurlSubtransport { @@ -131,21 +128,20 @@ impl SmartSubtransport for CurlTransport { } impl CurlSubtransport { - fn err>>(&self, err: E) -> io::Error { + fn err>>(&self, err: E) -> io::Error { io::Error::new(io::ErrorKind::Other, err) } fn execute(&mut self, data: &[u8]) -> io::Result<()> { if self.sent_request { - return Err(self.err("already sent HTTP request")) + return Err(self.err("already sent HTTP request")); } let agent = format!("git/1.0 (git2-curl {})", env!("CARGO_PKG_VERSION")); // Parse our input URL to figure out the host let url = format!("{}{}", self.base_url.lock().unwrap(), self.url_path); - let parsed = try!(Url::parse(&url).map_err(|_| { - self.err("invalid url, failed to parse") - })); + let parsed = + try!(Url::parse(&url).map_err(|_| { self.err("invalid url, failed to parse") })); let host = match parsed.host_str() { Some(host) => host, None => return Err(self.err("invalid url, did not have a host")), @@ -168,11 +164,15 @@ impl CurlSubtransport { try!(headers.append(&format!("Host: {}", host))); if data.len() > 0 { try!(h.post_fields_copy(data)); - try!(headers.append(&format!("Accept: application/x-git-{}-result", - self.service))); - try!(headers.append(&format!("Content-Type: \ - application/x-git-{}-request", - self.service))); + try!(headers.append(&format!( + "Accept: application/x-git-{}-result", + self.service + ))); + try!(headers.append(&format!( + "Content-Type: \ + application/x-git-{}-request", + self.service + ))); } else { try!(headers.append("Accept: */*")); } @@ -215,27 +215,39 @@ impl CurlSubtransport { let code = try!(h.response_code()); if code != 200 { - return Err(self.err(&format!("failed to receive HTTP 200 response: \ - got {}", code)[..])) + return Err(self.err( + &format!( + "failed to receive HTTP 200 response: \ + got {}", + code + )[..], + )); } // Check returned headers let expected = match self.method { - "GET" => format!("application/x-git-{}-advertisement", - self.service), + "GET" => format!("application/x-git-{}-advertisement", self.service), _ => format!("application/x-git-{}-result", self.service), }; match content_type { Some(ref content_type) if *content_type != expected => { - return Err(self.err(&format!("expected a Content-Type header \ - with `{}` but found `{}`", - expected, content_type)[..])) + return Err(self.err( + &format!( + "expected a Content-Type header \ + with `{}` but found `{}`", + expected, content_type + )[..], + )) } Some(..) => {} None => { - return Err(self.err(&format!("expected a Content-Type header \ - with `{}` but didn't find one", - expected)[..])) + return Err(self.err( + &format!( + "expected a Content-Type header \ + with `{}` but didn't find one", + expected + )[..], + )) } } @@ -276,5 +288,7 @@ impl Write for CurlSubtransport { } Ok(data.len()) } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } diff --git a/git2-curl/tests/all.rs b/git2-curl/tests/all.rs index 941020e185..7673143e3b 100644 --- a/git2-curl/tests/all.rs +++ b/git2-curl/tests/all.rs @@ -1,12 +1,12 @@ -extern crate conduit_git_http_backend as git_backend; -extern crate git2_curl; extern crate civet; extern crate conduit; +extern crate conduit_git_http_backend as git_backend; extern crate curl; extern crate git2; +extern crate git2_curl; extern crate tempfile; -use civet::{Server, Config}; +use civet::{Config, Server}; use std::fs::File; use std::path::Path; use tempfile::TempDir; @@ -34,15 +34,20 @@ fn main() { index.add_path(Path::new("foo")).unwrap(); index.write().unwrap(); let tree_id = index.write_tree().unwrap(); - r1.commit(Some("HEAD"), &sig, &sig, "test", - &r1.find_tree(tree_id).unwrap(), - &[]).unwrap(); + r1.commit( + Some("HEAD"), + &sig, + &sig, + "test", + &r1.find_tree(tree_id).unwrap(), + &[], + ) + .unwrap(); } // Clone through the git-http-backend let td2 = TempDir::new().unwrap(); - let r = git2::Repository::clone(&format!("http://localhost:{}", PORT), - td2.path()).unwrap(); + let r = git2::Repository::clone(&format!("http://localhost:{}", PORT), td2.path()).unwrap(); assert!(File::open(&td2.path().join("foo")).is_ok()); { File::create(&td.path().join("bar")).unwrap(); @@ -52,13 +57,21 @@ fn main() { let tree_id = index.write_tree().unwrap(); let parent = r1.head().ok().and_then(|h| h.target()).unwrap(); let parent = r1.find_commit(parent).unwrap(); - r1.commit(Some("HEAD"), &sig, &sig, "test", - &r1.find_tree(tree_id).unwrap(), - &[&parent]).unwrap(); + r1.commit( + Some("HEAD"), + &sig, + &sig, + "test", + &r1.find_tree(tree_id).unwrap(), + &[&parent], + ) + .unwrap(); } let mut remote = r.find_remote("origin").unwrap(); - remote.fetch(&["refs/heads/*:refs/heads/*"], None, None).unwrap(); + remote + .fetch(&["refs/heads/*:refs/heads/*"], None, None) + .unwrap(); let b = r.find_branch("master", git2::BranchType::Local).unwrap(); let id = b.get().target().unwrap(); let obj = r.find_object(id, None).unwrap(); diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index cc76cd46b3..8a2848e415 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -16,13 +16,14 @@ fn main() { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } - return + return; } } if !Path::new("libgit2/.git").exists() { - let _ = Command::new("git").args(&["submodule", "update", "--init"]) - .status(); + let _ = Command::new("git") + .args(&["submodule", "update", "--init"]) + .status(); } let target = env::var("TARGET").unwrap(); @@ -152,7 +153,7 @@ fn main() { println!("cargo:rustc-link-lib=rpcrt4"); println!("cargo:rustc-link-lib=ole32"); println!("cargo:rustc-link-lib=crypt32"); - return + return; } if target.contains("apple") { diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 726e852532..563a271d85 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,16 +1,16 @@ #![doc(html_root_url = "http://alexcrichton.com/git2-rs")] #![allow(non_camel_case_types, unused_extern_crates)] +#[cfg(feature = "curl")] +extern crate curl_sys; extern crate libc; #[cfg(feature = "ssh")] extern crate libssh2_sys as libssh2; -#[cfg(feature = "curl")] -extern crate curl_sys; +extern crate libz_sys as libz; #[cfg(all(unix, feature = "https"))] extern crate openssl_sys; -extern crate libz_sys as libz; -use libc::{c_int, c_char, c_uint, size_t, c_uchar, c_void}; +use libc::{c_char, c_int, c_uchar, c_uint, c_void, size_t}; pub const GIT_OID_RAWSZ: usize = 20; pub const GIT_OID_HEXSZ: usize = GIT_OID_RAWSZ * 2; @@ -117,7 +117,9 @@ pub struct git_strarray { pub count: size_t, } impl Clone for git_strarray { - fn clone(&self) -> git_strarray { *self } + fn clone(&self) -> git_strarray { + *self + } } #[repr(C)] @@ -127,7 +129,9 @@ pub struct git_oidarray { pub count: size_t, } impl Clone for git_oidarray { - fn clone(&self) -> git_oidarray { *self } + fn clone(&self) -> git_oidarray { + *self + } } #[repr(C)] @@ -295,19 +299,17 @@ pub struct git_checkout_options { pub perfdata_payload: *mut c_void, } -pub type git_checkout_notify_cb = extern fn(git_checkout_notify_t, - *const c_char, - *const git_diff_file, - *const git_diff_file, - *const git_diff_file, - *mut c_void) -> c_int; -pub type git_checkout_progress_cb = extern fn(*const c_char, - size_t, - size_t, - *mut c_void); +pub type git_checkout_notify_cb = extern "C" fn( + git_checkout_notify_t, + *const c_char, + *const git_diff_file, + *const git_diff_file, + *const git_diff_file, + *mut c_void, +) -> c_int; +pub type git_checkout_progress_cb = extern "C" fn(*const c_char, size_t, size_t, *mut c_void); -pub type git_checkout_perfdata_cb = extern fn(*const git_checkout_perfdata, - *mut c_void); +pub type git_checkout_perfdata_cb = extern "C" fn(*const git_checkout_perfdata, *mut c_void); #[repr(C)] pub struct git_checkout_perfdata { @@ -320,15 +322,12 @@ pub struct git_checkout_perfdata { pub struct git_remote_callbacks { pub version: c_uint, pub sideband_progress: Option, - pub completion: Option c_int>, + pub completion: Option c_int>, pub credentials: Option, pub certificate_check: Option, pub transfer_progress: Option, - pub update_tips: Option c_int>, + pub update_tips: + Option c_int>, pub pack_progress: Option, pub push_transfer_progress: Option, pub push_update_reference: Option, @@ -373,28 +372,21 @@ git_enum! { } } -pub type git_transport_message_cb = extern fn(*const c_char, c_int, - *mut c_void) -> c_int; -pub type git_cred_acquire_cb = extern fn(*mut *mut git_cred, - *const c_char, *const c_char, - c_uint, *mut c_void) -> c_int; -pub type git_transfer_progress_cb = extern fn(*const git_transfer_progress, - *mut c_void) -> c_int; -pub type git_packbuilder_progress = extern fn(git_packbuilder_stage_t, c_uint, - c_uint, *mut c_void) -> c_int; -pub type git_push_transfer_progress = extern fn(c_uint, c_uint, size_t, - *mut c_void) -> c_int; -pub type git_transport_certificate_check_cb = extern fn(*mut git_cert, - c_int, - *const c_char, - *mut c_void) -> c_int; -pub type git_push_negotiation = extern fn(*mut *const git_push_update, - size_t, - *mut c_void) -> c_int; - -pub type git_push_update_reference_cb = extern fn(*const c_char, - *const c_char, - *mut c_void) -> c_int; +pub type git_transport_message_cb = extern "C" fn(*const c_char, c_int, *mut c_void) -> c_int; +pub type git_cred_acquire_cb = + extern "C" fn(*mut *mut git_cred, *const c_char, *const c_char, c_uint, *mut c_void) -> c_int; +pub type git_transfer_progress_cb = + extern "C" fn(*const git_transfer_progress, *mut c_void) -> c_int; +pub type git_packbuilder_progress = + extern "C" fn(git_packbuilder_stage_t, c_uint, c_uint, *mut c_void) -> c_int; +pub type git_push_transfer_progress = extern "C" fn(c_uint, c_uint, size_t, *mut c_void) -> c_int; +pub type git_transport_certificate_check_cb = + extern "C" fn(*mut git_cert, c_int, *const c_char, *mut c_void) -> c_int; +pub type git_push_negotiation = + extern "C" fn(*mut *const git_push_update, size_t, *mut c_void) -> c_int; + +pub type git_push_update_reference_cb = + extern "C" fn(*const c_char, *const c_char, *mut c_void) -> c_int; #[repr(C)] pub struct git_push_update { @@ -460,14 +452,15 @@ pub struct git_diff_file { pub mode: u16, } -pub type git_repository_create_cb = extern fn(*mut *mut git_repository, - *const c_char, - c_int, *mut c_void) -> c_int; -pub type git_remote_create_cb = extern fn(*mut *mut git_remote, - *mut git_repository, - *const c_char, - *const c_char, - *mut c_void) -> c_int; +pub type git_repository_create_cb = + extern "C" fn(*mut *mut git_repository, *const c_char, c_int, *mut c_void) -> c_int; +pub type git_remote_create_cb = extern "C" fn( + *mut *mut git_remote, + *mut git_repository, + *const c_char, + *const c_char, + *mut c_void, +) -> c_int; git_enum! { pub enum git_checkout_notify_t { @@ -573,7 +566,7 @@ pub struct git_diff_delta { pub struct git_status_entry { pub status: git_status_t, pub head_to_index: *mut git_diff_delta, - pub index_to_workdir: *mut git_diff_delta + pub index_to_workdir: *mut git_diff_delta, } git_enum! { @@ -650,12 +643,11 @@ git_enum! { } } -pub type git_treewalk_cb = extern fn(*const c_char, *const git_tree_entry, - *mut c_void) -> c_int; -pub type git_treebuilder_filter_cb = extern fn(*const git_tree_entry, - *mut c_void) -> c_int; +pub type git_treewalk_cb = + extern "C" fn(*const c_char, *const git_tree_entry, *mut c_void) -> c_int; +pub type git_treebuilder_filter_cb = extern "C" fn(*const git_tree_entry, *mut c_void) -> c_int; -pub type git_revwalk_hide_cb = extern fn(*const git_oid, *mut c_void) -> c_int; +pub type git_revwalk_hide_cb = extern "C" fn(*const git_oid, *mut c_void) -> c_int; #[repr(C)] #[derive(Copy, Clone)] @@ -674,11 +666,11 @@ git_enum! { } pub const GIT_BLAME_NORMAL: u32 = 0; -pub const GIT_BLAME_TRACK_COPIES_SAME_FILE: u32 = 1<<0; -pub const GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES: u32 = 1<<1; -pub const GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES: u32 = 1<<2; -pub const GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES: u32 = 1<<3; -pub const GIT_BLAME_FIRST_PARENT: u32 = 1<<4; +pub const GIT_BLAME_TRACK_COPIES_SAME_FILE: u32 = 1 << 0; +pub const GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES: u32 = 1 << 1; +pub const GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES: u32 = 1 << 2; +pub const GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES: u32 = 1 << 3; +pub const GIT_BLAME_FIRST_PARENT: u32 = 1 << 4; #[repr(C)] #[derive(Copy, Clone)] @@ -707,8 +699,8 @@ pub struct git_blame_hunk { pub boundary: c_char, } -pub type git_index_matched_path_cb = extern fn(*const c_char, *const c_char, - *mut c_void) -> c_int; +pub type git_index_matched_path_cb = + extern "C" fn(*const c_char, *const c_char, *mut c_void) -> c_int; git_enum! { pub enum git_index_entry_extended_flag_t { @@ -760,7 +752,7 @@ pub struct git_config_entry { pub value: *const c_char, pub include_depth: c_uint, pub level: git_config_level_t, - pub free: extern fn(*mut git_config_entry), + pub free: extern "C" fn(*mut git_config_entry), pub payload: *mut c_void, } @@ -797,9 +789,7 @@ git_enum! { } } -pub type git_submodule_cb = extern fn(*mut git_submodule, - *const c_char, - *mut c_void) -> c_int; +pub type git_submodule_cb = extern "C" fn(*mut git_submodule, *const c_char, *mut c_void) -> c_int; #[repr(C)] pub struct git_submodule_update_options { @@ -811,17 +801,15 @@ pub struct git_submodule_update_options { #[repr(C)] pub struct git_writestream { - pub write: extern fn(*mut git_writestream, - *const c_char, - size_t) -> c_int, - pub close: extern fn(*mut git_writestream) -> c_int, - pub free: extern fn(*mut git_writestream), + pub write: extern "C" fn(*mut git_writestream, *const c_char, size_t) -> c_int, + pub close: extern "C" fn(*mut git_writestream) -> c_int, + pub free: extern "C" fn(*mut git_writestream), } #[repr(C)] pub struct git_cred { pub credtype: git_credtype_t, - pub free: extern fn(*mut git_cred), + pub free: extern "C" fn(*mut git_cred), } git_enum! { @@ -836,7 +824,7 @@ git_enum! { } } -pub type git_cred_ssh_interactive_callback = extern fn( +pub type git_cred_ssh_interactive_callback = extern "C" fn( name: *const c_char, name_len: c_int, instruction: *const c_char, @@ -844,10 +832,10 @@ pub type git_cred_ssh_interactive_callback = extern fn( num_prompts: c_int, prompts: *const LIBSSH2_USERAUTH_KBDINT_PROMPT, responses: *mut LIBSSH2_USERAUTH_KBDINT_RESPONSE, - abstrakt: *mut *mut c_void + abstrakt: *mut *mut c_void, ); -pub type git_cred_sign_callback = extern fn( +pub type git_cred_sign_callback = extern "C" fn( session: *mut LIBSSH2_SESSION, sig: *mut *mut c_uchar, sig_len: *mut size_t, @@ -869,9 +857,8 @@ pub struct git_push_options { pub custom_headers: git_strarray, } -pub type git_tag_foreach_cb = extern fn(name: *const c_char, - oid: *mut git_oid, - payload: *mut c_void) -> c_int; +pub type git_tag_foreach_cb = + extern "C" fn(name: *const c_char, oid: *mut git_oid, payload: *mut c_void) -> c_int; git_enum! { pub enum git_index_add_option_t { @@ -974,18 +961,17 @@ git_enum! { } } -pub type git_diff_file_cb = extern fn(*const git_diff_delta, f32, *mut c_void) - -> c_int; -pub type git_diff_hunk_cb = extern fn(*const git_diff_delta, - *const git_diff_hunk, - *mut c_void) -> c_int; -pub type git_diff_line_cb = extern fn(*const git_diff_delta, - *const git_diff_hunk, - *const git_diff_line, - *mut c_void) -> c_int; -pub type git_diff_binary_cb = extern fn(*const git_diff_delta, - *const git_diff_binary, - *mut c_void) -> c_int; +pub type git_diff_file_cb = extern "C" fn(*const git_diff_delta, f32, *mut c_void) -> c_int; +pub type git_diff_hunk_cb = + extern "C" fn(*const git_diff_delta, *const git_diff_hunk, *mut c_void) -> c_int; +pub type git_diff_line_cb = extern "C" fn( + *const git_diff_delta, + *const git_diff_hunk, + *const git_diff_line, + *mut c_void, +) -> c_int; +pub type git_diff_binary_cb = + extern "C" fn(*const git_diff_delta, *const git_diff_binary, *mut c_void) -> c_int; #[repr(C)] pub struct git_diff_hunk { @@ -1059,15 +1045,11 @@ git_enum! { } } -pub type git_diff_notify_cb = extern fn(*const git_diff, - *const git_diff_delta, - *const c_char, - *mut c_void) -> c_int; +pub type git_diff_notify_cb = + extern "C" fn(*const git_diff, *const git_diff_delta, *const c_char, *mut c_void) -> c_int; -pub type git_diff_progress_cb = extern fn (*const git_diff, - *const c_char, - *const c_char, - *mut c_void) -> c_int; +pub type git_diff_progress_cb = + extern "C" fn(*const git_diff, *const c_char, *const c_char, *mut c_void) -> c_int; pub type git_diff_option_t = i32; pub const GIT_DIFF_NORMAL: git_diff_option_t = 0; @@ -1114,18 +1096,17 @@ pub struct git_diff_find_options { #[repr(C)] pub struct git_diff_similarity_metric { - pub file_signature: extern fn(*mut *mut c_void, - *const git_diff_file, - *const c_char, - *mut c_void) -> c_int, - pub buffer_signature: extern fn(*mut *mut c_void, - *const git_diff_file, - *const c_char, - size_t, - *mut c_void) -> c_int, - pub free_signature: extern fn(*mut c_void, *mut c_void), - pub similarity: extern fn(*mut c_int, *mut c_void, *mut c_void, - *mut c_void) -> c_int, + pub file_signature: + extern "C" fn(*mut *mut c_void, *const git_diff_file, *const c_char, *mut c_void) -> c_int, + pub buffer_signature: extern "C" fn( + *mut *mut c_void, + *const git_diff_file, + *const c_char, + size_t, + *mut c_void, + ) -> c_int, + pub free_signature: extern "C" fn(*mut c_void, *mut c_void), + pub similarity: extern "C" fn(*mut c_int, *mut c_void, *mut c_void, *mut c_void) -> c_int, pub payload: *mut c_void, } @@ -1138,15 +1119,14 @@ pub const GIT_DIFF_FIND_COPIES: u32 = 1 << 2; pub const GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED: u32 = 1 << 3; pub const GIT_DIFF_FIND_REWRITES: u32 = 1 << 4; pub const GIT_DIFF_BREAK_REWRITES: u32 = 1 << 5; -pub const GIT_DIFF_FIND_AND_BREAK_REWRITES: u32 = - GIT_DIFF_FIND_REWRITES | GIT_DIFF_BREAK_REWRITES; +pub const GIT_DIFF_FIND_AND_BREAK_REWRITES: u32 = GIT_DIFF_FIND_REWRITES | GIT_DIFF_BREAK_REWRITES; pub const GIT_DIFF_FIND_FOR_UNTRACKED: u32 = 1 << 6; pub const GIT_DIFF_FIND_ALL: u32 = 0x0ff; pub const GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE: u32 = 0; pub const GIT_DIFF_FIND_IGNORE_WHITESPACE: u32 = 1 << 12; pub const GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE: u32 = 1 << 13; pub const GIT_DIFF_FIND_EXACT_MATCH_ONLY: u32 = 1 << 14; -pub const GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY : u32 = 1 << 15; +pub const GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY: u32 = 1 << 15; pub const GIT_DIFF_FIND_REMOVE_UNMODIFIED: u32 = 1 << 16; #[repr(C)] @@ -1235,169 +1215,183 @@ git_enum! { } } -pub type git_transport_cb = extern fn(out: *mut *mut git_transport, - owner: *mut git_remote, - param: *mut c_void) -> c_int; +pub type git_transport_cb = extern "C" fn( + out: *mut *mut git_transport, + owner: *mut git_remote, + param: *mut c_void, +) -> c_int; #[repr(C)] pub struct git_transport { pub version: c_uint, - pub set_callbacks: extern fn(*mut git_transport, - git_transport_message_cb, - git_transport_message_cb, - git_transport_certificate_check_cb, - *mut c_void) -> c_int, - pub set_custom_headers: extern fn(*mut git_transport, - *const git_strarray) -> c_int, - pub connect: extern fn(*mut 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, - *mut git_transport) -> c_int, - pub push: extern fn(*mut git_transport, - *mut git_push, - *const git_remote_callbacks) -> c_int, - pub negotiate_fetch: extern fn(*mut git_transport, - *mut git_repository, - *const *const git_remote_head, - size_t) -> c_int, - pub download_pack: extern fn(*mut git_transport, - *mut git_repository, - *mut git_transfer_progress, - git_transfer_progress_cb, - *mut c_void) -> c_int, - pub is_connected: extern fn(*mut git_transport) -> c_int, - pub read_flags: extern fn(*mut git_transport, *mut c_int) -> c_int, - pub cancel: extern fn(*mut git_transport), - pub close: extern fn(*mut git_transport) -> c_int, - pub free: extern fn(*mut git_transport), + pub set_callbacks: extern "C" fn( + *mut git_transport, + git_transport_message_cb, + git_transport_message_cb, + git_transport_certificate_check_cb, + *mut c_void, + ) -> c_int, + pub set_custom_headers: extern "C" fn(*mut git_transport, *const git_strarray) -> c_int, + pub connect: extern "C" fn( + *mut 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 "C" fn(*mut *mut *const git_remote_head, *mut size_t, *mut git_transport) -> c_int, + pub push: + extern "C" fn(*mut git_transport, *mut git_push, *const git_remote_callbacks) -> c_int, + pub negotiate_fetch: extern "C" fn( + *mut git_transport, + *mut git_repository, + *const *const git_remote_head, + size_t, + ) -> c_int, + pub download_pack: extern "C" fn( + *mut git_transport, + *mut git_repository, + *mut git_transfer_progress, + git_transfer_progress_cb, + *mut c_void, + ) -> c_int, + pub is_connected: extern "C" fn(*mut git_transport) -> c_int, + pub read_flags: extern "C" fn(*mut git_transport, *mut c_int) -> c_int, + pub cancel: extern "C" fn(*mut git_transport), + pub close: extern "C" fn(*mut git_transport) -> c_int, + pub free: extern "C" fn(*mut git_transport), } #[repr(C)] pub struct git_odb_backend { pub version: c_uint, pub odb: *mut git_odb, - pub read: extern fn(*mut *mut c_void, - *mut size_t, - *mut git_object_t, - *mut git_odb_backend, - *const git_oid) -> c_int, - - pub read_prefix: extern fn(*mut git_oid, - *mut *mut c_void, - *mut size_t, - *mut git_object_t, - *mut git_odb_backend, - *const git_oid, - size_t) -> c_int, - pub read_header: extern fn(*mut size_t, - *mut git_object_t, - *mut git_odb_backend, - *const git_oid) -> c_int, - - pub write: extern fn(*mut git_odb_backend, - *const git_oid, - *const c_void, - size_t, - git_object_t) -> c_int, - - pub writestream: extern fn(*mut *mut git_odb_stream, - *mut git_odb_backend, - git_off_t, - git_object_t) -> c_int, - - pub readstream: extern fn(*mut *mut git_odb_stream, - *mut size_t, - *mut git_object_t, - *mut git_odb_backend, - *const git_oid) -> c_int, - - pub exists: extern fn(*mut git_odb_backend, - *const git_oid) -> c_int, - - pub exists_prefix: extern fn(*mut git_oid, - *mut git_odb_backend, - *const git_oid, - size_t) -> c_int, - - pub refresh: extern fn(*mut git_odb_backend) -> c_int, - - pub foreach: extern fn(*mut git_odb_backend, - git_odb_foreach_cb, - *mut c_void) -> c_int, - - pub writepack: extern fn(*mut *mut git_odb_writepack, - *mut git_odb_backend, - *mut git_odb, - git_transfer_progress_cb, - *mut c_void) -> c_int, - - pub freshen: extern fn(*mut git_odb_backend, - *const git_oid) -> c_int, - - pub free: extern fn(*mut git_odb_backend), + pub read: extern "C" fn( + *mut *mut c_void, + *mut size_t, + *mut git_object_t, + *mut git_odb_backend, + *const git_oid, + ) -> c_int, + + pub read_prefix: extern "C" fn( + *mut git_oid, + *mut *mut c_void, + *mut size_t, + *mut git_object_t, + *mut git_odb_backend, + *const git_oid, + size_t, + ) -> c_int, + pub read_header: extern "C" fn( + *mut size_t, + *mut git_object_t, + *mut git_odb_backend, + *const git_oid, + ) -> c_int, + + pub write: extern "C" fn( + *mut git_odb_backend, + *const git_oid, + *const c_void, + size_t, + git_object_t, + ) -> c_int, + + pub writestream: extern "C" fn( + *mut *mut git_odb_stream, + *mut git_odb_backend, + git_off_t, + git_object_t, + ) -> c_int, + + pub readstream: extern "C" fn( + *mut *mut git_odb_stream, + *mut size_t, + *mut git_object_t, + *mut git_odb_backend, + *const git_oid, + ) -> c_int, + + pub exists: extern "C" fn(*mut git_odb_backend, *const git_oid) -> c_int, + + pub exists_prefix: + extern "C" fn(*mut git_oid, *mut git_odb_backend, *const git_oid, size_t) -> c_int, + + pub refresh: extern "C" fn(*mut git_odb_backend) -> c_int, + + pub foreach: extern "C" fn(*mut git_odb_backend, git_odb_foreach_cb, *mut c_void) -> c_int, + + pub writepack: extern "C" fn( + *mut *mut git_odb_writepack, + *mut git_odb_backend, + *mut git_odb, + git_transfer_progress_cb, + *mut c_void, + ) -> c_int, + + pub freshen: extern "C" fn(*mut git_odb_backend, *const git_oid) -> c_int, + + pub free: extern "C" fn(*mut git_odb_backend), } #[repr(C)] pub struct git_refdb_backend { pub version: c_uint, - pub exists: extern fn(*mut c_int, - *mut git_refdb_backend, - *const c_char) -> c_int, - pub lookup: extern fn(*mut *mut git_reference, - *mut git_refdb_backend, - *const c_char) -> c_int, - pub iterator: extern fn(*mut *mut git_reference_iterator, - *mut git_refdb_backend, - *const c_char) -> c_int, - pub write: extern fn(*mut git_refdb_backend, - *const git_reference, - c_int, - *const git_signature, - *const c_char, - *const git_oid, - *const c_char) -> c_int, - pub rename: extern fn(*mut *mut git_reference, - *mut git_refdb_backend, - *const c_char, - *const c_char, - c_int, - *const git_signature, - *const c_char) -> c_int, - pub del: extern fn(*mut git_refdb_backend, - *const c_char, - *const git_oid, - *const c_char) -> c_int, - pub compress: extern fn(*mut git_refdb_backend) -> c_int, - pub has_log: extern fn(*mut git_refdb_backend, - *const c_char) -> c_int, - pub ensure_log: extern fn(*mut git_refdb_backend, - *const c_char) -> c_int, - pub free: extern fn(*mut git_refdb_backend), - pub reflog_read: extern fn(*mut *mut git_reflog, - *mut git_refdb_backend, - *const c_char) -> c_int, - pub reflog_write: extern fn(*mut git_refdb_backend, - *mut git_reflog) -> c_int, - pub reflog_rename: extern fn(*mut git_refdb_backend, - *const c_char, - *const c_char) -> c_int, - pub reflog_delete: extern fn(*mut git_refdb_backend, - *const c_char) -> c_int, - pub lock: extern fn(*mut *mut c_void, - *mut git_refdb_backend, - *const c_char) -> c_int, - pub unlock: extern fn(*mut git_refdb_backend, - *mut c_void, - c_int, - c_int, - *const git_reference, - *const git_signature, - *const c_char) -> c_int + pub exists: extern "C" fn(*mut c_int, *mut git_refdb_backend, *const c_char) -> c_int, + pub lookup: + extern "C" fn(*mut *mut git_reference, *mut git_refdb_backend, *const c_char) -> c_int, + pub iterator: extern "C" fn( + *mut *mut git_reference_iterator, + *mut git_refdb_backend, + *const c_char, + ) -> c_int, + pub write: extern "C" fn( + *mut git_refdb_backend, + *const git_reference, + c_int, + *const git_signature, + *const c_char, + *const git_oid, + *const c_char, + ) -> c_int, + pub rename: extern "C" fn( + *mut *mut git_reference, + *mut git_refdb_backend, + *const c_char, + *const c_char, + c_int, + *const git_signature, + *const c_char, + ) -> c_int, + pub del: extern "C" fn( + *mut git_refdb_backend, + *const c_char, + *const git_oid, + *const c_char, + ) -> c_int, + pub compress: extern "C" fn(*mut git_refdb_backend) -> c_int, + pub has_log: extern "C" fn(*mut git_refdb_backend, *const c_char) -> c_int, + pub ensure_log: extern "C" fn(*mut git_refdb_backend, *const c_char) -> c_int, + pub free: extern "C" fn(*mut git_refdb_backend), + pub reflog_read: + extern "C" fn(*mut *mut git_reflog, *mut git_refdb_backend, *const c_char) -> c_int, + pub reflog_write: extern "C" fn(*mut git_refdb_backend, *mut git_reflog) -> c_int, + pub reflog_rename: extern "C" fn(*mut git_refdb_backend, *const c_char, *const c_char) -> c_int, + pub reflog_delete: extern "C" fn(*mut git_refdb_backend, *const c_char) -> c_int, + pub lock: extern "C" fn(*mut *mut c_void, *mut git_refdb_backend, *const c_char) -> c_int, + pub unlock: extern "C" fn( + *mut git_refdb_backend, + *mut c_void, + c_int, + c_int, + *const git_reference, + *const git_signature, + *const c_char, + ) -> c_int, } #[repr(C)] @@ -1430,29 +1424,30 @@ git_enum! { #[repr(C)] pub struct git_smart_subtransport_stream { pub subtransport: *mut git_smart_subtransport, - pub read: extern fn(*mut git_smart_subtransport_stream, - *mut c_char, - size_t, - *mut size_t) -> c_int, - pub write: extern fn(*mut git_smart_subtransport_stream, - *const c_char, - size_t) -> c_int, - pub free: extern fn(*mut git_smart_subtransport_stream), + pub read: extern "C" fn( + *mut git_smart_subtransport_stream, + *mut c_char, + size_t, + *mut size_t, + ) -> c_int, + pub write: extern "C" fn(*mut git_smart_subtransport_stream, *const c_char, size_t) -> c_int, + pub free: extern "C" fn(*mut git_smart_subtransport_stream), } #[repr(C)] pub struct git_smart_subtransport { - pub action: extern fn(*mut *mut git_smart_subtransport_stream, - *mut git_smart_subtransport, - *const c_char, - git_smart_service_t) -> c_int, - pub close: extern fn(*mut git_smart_subtransport) -> c_int, - pub free: extern fn(*mut git_smart_subtransport), + pub action: extern "C" fn( + *mut *mut git_smart_subtransport_stream, + *mut git_smart_subtransport, + *const c_char, + git_smart_service_t, + ) -> c_int, + pub close: extern "C" fn(*mut git_smart_subtransport) -> c_int, + pub free: extern "C" fn(*mut git_smart_subtransport), } -pub type git_smart_subtransport_cb = extern fn(*mut *mut git_smart_subtransport, - *mut git_transport, - *mut c_void) -> c_int; +pub type git_smart_subtransport_cb = + extern "C" fn(*mut *mut git_smart_subtransport, *mut git_transport, *mut c_void) -> c_int; #[repr(C)] pub struct git_smart_subtransport_definition { @@ -1532,18 +1527,19 @@ pub struct git_stash_apply_options { pub progress_payload: *mut c_void, } -pub type git_stash_apply_progress_cb = extern fn(progress: git_stash_apply_progress_t, - payload: *mut c_void) -> c_int; +pub type git_stash_apply_progress_cb = + extern "C" fn(progress: git_stash_apply_progress_t, payload: *mut c_void) -> c_int; -pub type git_stash_cb = extern fn(index: size_t, - message: *const c_char, - stash_id: *const git_oid, - payload: *mut c_void) -> c_int; +pub type git_stash_cb = extern "C" fn( + index: size_t, + message: *const c_char, + stash_id: *const git_oid, + payload: *mut c_void, +) -> c_int; -pub type git_packbuilder_foreach_cb = extern fn(*const c_void, size_t, - *mut c_void) -> c_int; +pub type git_packbuilder_foreach_cb = extern "C" fn(*const c_void, size_t, *mut c_void) -> c_int; -pub type git_odb_foreach_cb = extern fn(id: *const git_oid, payload: *mut c_void) -> c_int; +pub type git_odb_foreach_cb = extern "C" fn(id: *const git_oid, payload: *mut c_void) -> c_int; pub const GIT_REBASE_NO_OPERATION: usize = usize::max_value(); @@ -1575,7 +1571,7 @@ pub struct git_rebase_operation { pub exec: *const c_char, } -extern { +extern "C" { // threads pub fn git_libgit2_init() -> c_int; pub fn git_libgit2_shutdown() -> c_int; @@ -1583,39 +1579,46 @@ extern { // repository pub fn git_repository_new(out: *mut *mut git_repository) -> c_int; 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_bare(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_open_from_worktree(repo: *mut *mut git_repository, - worktree: *mut git_worktree) -> c_int; - pub fn git_repository_wrap_odb(repo: *mut *mut git_repository, - odb: *mut git_odb) -> c_int; - pub fn git_repository_init(repo: *mut *mut git_repository, - path: *const c_char, - is_bare: c_uint) -> c_int; - pub fn git_repository_init_ext(out: *mut *mut git_repository, - repo_path: *const c_char, - opts: *mut git_repository_init_options) - -> c_int; - pub fn git_repository_init_init_options(opts: *mut git_repository_init_options, - version: c_uint) -> c_int; - pub fn git_repository_get_namespace(repo: *mut git_repository) - -> *const c_char; - pub fn git_repository_set_namespace(repo: *mut git_repository, - namespace: *const c_char) -> c_int; - pub fn git_repository_head(out: *mut *mut git_reference, - repo: *mut git_repository) -> c_int; - pub fn git_repository_set_head(repo: *mut git_repository, - refname: *const c_char) -> c_int; + pub fn git_repository_open(repo: *mut *mut git_repository, path: *const c_char) -> c_int; + pub fn git_repository_open_bare(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_open_from_worktree( + repo: *mut *mut git_repository, + worktree: *mut git_worktree, + ) -> c_int; + pub fn git_repository_wrap_odb(repo: *mut *mut git_repository, odb: *mut git_odb) -> c_int; + pub fn git_repository_init( + repo: *mut *mut git_repository, + path: *const c_char, + is_bare: c_uint, + ) -> c_int; + pub fn git_repository_init_ext( + out: *mut *mut git_repository, + repo_path: *const c_char, + opts: *mut git_repository_init_options, + ) -> c_int; + pub fn git_repository_init_init_options( + opts: *mut git_repository_init_options, + version: c_uint, + ) -> c_int; + pub fn git_repository_get_namespace(repo: *mut git_repository) -> *const c_char; + pub fn git_repository_set_namespace( + repo: *mut git_repository, + namespace: *const c_char, + ) -> c_int; + pub fn git_repository_head(out: *mut *mut git_reference, repo: *mut git_repository) -> c_int; + pub fn git_repository_set_head(repo: *mut git_repository, refname: *const c_char) -> c_int; pub fn git_repository_head_detached(repo: *mut git_repository) -> c_int; - pub fn git_repository_set_head_detached(repo: *mut git_repository, - commitish: *const git_oid) -> c_int; + pub fn git_repository_set_head_detached( + repo: *mut git_repository, + commitish: *const git_oid, + ) -> c_int; pub fn git_repository_set_bare(repo: *mut git_repository) -> c_int; pub fn git_repository_is_worktree(repo: *const git_repository) -> c_int; pub fn git_repository_is_bare(repo: *const git_repository) -> c_int; @@ -1624,82 +1627,89 @@ extern { pub fn git_repository_path(repo: *const git_repository) -> *const c_char; pub fn git_repository_state(repo: *mut git_repository) -> c_int; pub fn git_repository_workdir(repo: *const git_repository) -> *const c_char; - pub fn git_repository_set_workdir(repo: *mut git_repository, - workdir: *const c_char, - update_gitlink: c_int) -> c_int; - pub fn git_repository_index(out: *mut *mut git_index, - repo: *mut git_repository) -> c_int; - pub fn git_repository_set_index(repo: *mut git_repository, - index: *mut git_index); + pub fn git_repository_set_workdir( + repo: *mut git_repository, + workdir: *const c_char, + update_gitlink: c_int, + ) -> c_int; + pub fn git_repository_index(out: *mut *mut git_index, repo: *mut git_repository) -> c_int; + pub fn git_repository_set_index(repo: *mut git_repository, index: *mut git_index); - pub fn git_repository_message(buf: *mut git_buf, - repo: *mut git_repository) -> c_int; + pub fn git_repository_message(buf: *mut git_buf, repo: *mut git_repository) -> c_int; pub fn git_repository_message_remove(repo: *mut git_repository) -> c_int; - pub fn git_repository_config(out: *mut *mut git_config, - repo: *mut git_repository) -> c_int; - pub fn git_repository_set_config(repo: *mut git_repository, - config: *mut git_config); - pub fn git_repository_config_snapshot(out: *mut *mut git_config, - repo: *mut git_repository) -> c_int; - pub fn git_repository_discover(out: *mut git_buf, - start_path: *const c_char, - across_fs: c_int, - ceiling_dirs: *const c_char) -> c_int; - pub fn git_repository_set_odb(repo: *mut git_repository, - odb: *mut git_odb); - - pub fn git_repository_refdb(out: *mut *mut git_refdb, - repo: *mut git_repository) -> c_int; - pub fn git_repository_set_refdb(repo: *mut git_repository, - refdb: *mut git_refdb); - - pub fn git_repository_reinit_filesystem(repo: *mut git_repository, - recurse_submodules: c_int) -> c_int; - pub fn git_ignore_add_rule(repo: *mut git_repository, - rules: *const c_char) -> c_int; + pub fn git_repository_config(out: *mut *mut git_config, repo: *mut git_repository) -> c_int; + pub fn git_repository_set_config(repo: *mut git_repository, config: *mut git_config); + pub fn git_repository_config_snapshot( + out: *mut *mut git_config, + repo: *mut git_repository, + ) -> c_int; + pub fn git_repository_discover( + out: *mut git_buf, + start_path: *const c_char, + across_fs: c_int, + ceiling_dirs: *const c_char, + ) -> c_int; + pub fn git_repository_set_odb(repo: *mut git_repository, odb: *mut git_odb); + + pub fn git_repository_refdb(out: *mut *mut git_refdb, repo: *mut git_repository) -> c_int; + pub fn git_repository_set_refdb(repo: *mut git_repository, refdb: *mut git_refdb); + + pub fn git_repository_reinit_filesystem( + repo: *mut git_repository, + recurse_submodules: c_int, + ) -> c_int; + pub fn git_ignore_add_rule(repo: *mut git_repository, rules: *const c_char) -> c_int; pub fn git_ignore_clear_internal_rules(repo: *mut git_repository) -> c_int; - pub fn git_ignore_path_is_ignored(ignored: *mut c_int, - repo: *mut git_repository, - path: *const c_char) -> c_int; + pub fn git_ignore_path_is_ignored( + ignored: *mut c_int, + repo: *mut git_repository, + path: *const c_char, + ) -> c_int; // revparse - pub fn git_revparse(revspec: *mut git_revspec, - repo: *mut git_repository, - spec: *const c_char) -> c_int; - pub fn git_revparse_single(out: *mut *mut git_object, - repo: *mut git_repository, - spec: *const c_char) -> c_int; - pub fn git_revparse_ext(object_out: *mut *mut git_object, - reference_out: *mut *mut git_reference, - repo: *mut git_repository, - spec: *const c_char) -> c_int; + pub fn git_revparse( + revspec: *mut git_revspec, + repo: *mut git_repository, + spec: *const c_char, + ) -> c_int; + pub fn git_revparse_single( + out: *mut *mut git_object, + repo: *mut git_repository, + spec: *const c_char, + ) -> c_int; + pub fn git_revparse_ext( + object_out: *mut *mut git_object, + reference_out: *mut *mut git_reference, + repo: *mut git_repository, + spec: *const c_char, + ) -> c_int; // object - pub fn git_object_dup(dest: *mut *mut git_object, - source: *mut git_object) -> c_int; + pub fn git_object_dup(dest: *mut *mut git_object, source: *mut git_object) -> c_int; pub fn git_object_id(obj: *const git_object) -> *const git_oid; pub fn git_object_free(object: *mut git_object); - pub fn git_object_lookup(dest: *mut *mut git_object, - repo: *mut git_repository, - id: *const git_oid, - kind: git_object_t) -> c_int; + pub fn git_object_lookup( + dest: *mut *mut git_object, + repo: *mut git_repository, + id: *const git_oid, + kind: git_object_t, + ) -> c_int; pub fn git_object_type(obj: *const git_object) -> git_object_t; - pub fn git_object_peel(peeled: *mut *mut git_object, - object: *const git_object, - target_type: git_object_t) -> c_int; - pub fn git_object_short_id(out: *mut git_buf, - obj: *const git_object) -> c_int; + pub fn git_object_peel( + peeled: *mut *mut git_object, + object: *const git_object, + target_type: git_object_t, + ) -> c_int; + pub fn git_object_short_id(out: *mut git_buf, obj: *const git_object) -> c_int; pub fn git_object_type2string(kind: git_object_t) -> *const c_char; pub fn git_object_string2type(s: *const c_char) -> git_object_t; pub fn git_object_typeisloose(kind: git_object_t) -> c_int; // oid pub fn git_oid_fromraw(out: *mut git_oid, raw: *const c_uchar); - pub fn git_oid_fromstrn(out: *mut git_oid, str: *const c_char, - len: size_t) -> c_int; - pub fn git_oid_tostr(out: *mut c_char, n: size_t, - id: *const git_oid) -> *mut c_char; + pub fn git_oid_fromstrn(out: *mut git_oid, str: *const c_char, len: size_t) -> c_int; + pub fn git_oid_tostr(out: *mut c_char, n: size_t, id: *const git_oid) -> *mut c_char; pub fn git_oid_cmp(a: *const git_oid, b: *const git_oid) -> c_int; pub fn git_oid_equal(a: *const git_oid, b: *const git_oid) -> c_int; pub fn git_oid_streq(id: *const git_oid, str: *const c_char) -> c_int; @@ -1711,96 +1721,123 @@ extern { pub fn git_error_set_str(error_class: c_int, string: *const c_char); // remote - pub fn git_remote_create(out: *mut *mut git_remote, - repo: *mut git_repository, - name: *const c_char, - url: *const c_char) -> c_int; - pub fn git_remote_lookup(out: *mut *mut git_remote, - repo: *mut git_repository, - name: *const c_char) -> c_int; - pub fn git_remote_create_anonymous(out: *mut *mut git_remote, - repo: *mut git_repository, - url: *const c_char) -> c_int; - pub fn git_remote_delete(repo: *mut git_repository, - name: *const c_char) -> c_int; + pub fn git_remote_create( + out: *mut *mut git_remote, + repo: *mut git_repository, + name: *const c_char, + url: *const c_char, + ) -> c_int; + pub fn git_remote_lookup( + out: *mut *mut git_remote, + repo: *mut git_repository, + name: *const c_char, + ) -> c_int; + pub fn git_remote_create_anonymous( + out: *mut *mut git_remote, + repo: *mut git_repository, + url: *const c_char, + ) -> c_int; + pub fn git_remote_delete(repo: *mut git_repository, name: *const c_char) -> c_int; pub fn git_remote_free(remote: *mut git_remote); pub fn git_remote_name(remote: *const git_remote) -> *const c_char; pub fn git_remote_pushurl(/service/remote: *const git_remote) -> *const c_char; pub fn git_remote_refspec_count(remote: *const git_remote) -> size_t; pub fn git_remote_url(/service/remote: *const git_remote) -> *const c_char; - 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_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); - pub fn git_remote_add_fetch(repo: *mut git_repository, - remote: *const c_char, - refspec: *const c_char) -> c_int; - pub fn git_remote_add_push(repo: *mut git_repository, - remote: *const c_char, - refspec: *const c_char) -> c_int; - pub fn git_remote_download(remote: *mut git_remote, - refspecs: *const git_strarray, - opts: *const git_fetch_options) -> c_int; + pub fn git_remote_add_fetch( + repo: *mut git_repository, + remote: *const c_char, + refspec: *const c_char, + ) -> c_int; + pub fn git_remote_add_push( + repo: *mut git_repository, + remote: *const c_char, + refspec: *const c_char, + ) -> c_int; + pub fn git_remote_download( + remote: *mut git_remote, + refspecs: *const git_strarray, + opts: *const git_fetch_options, + ) -> c_int; pub fn git_remote_stop(remote: *mut git_remote); - pub fn git_remote_dup(dest: *mut *mut git_remote, - source: *mut git_remote) -> c_int; - pub fn git_remote_get_fetch_refspecs(array: *mut git_strarray, - remote: *const git_remote) -> c_int; - pub fn git_remote_get_push_refspecs(array: *mut git_strarray, - remote: *const git_remote) -> c_int; - pub fn git_remote_get_refspec(remote: *const git_remote, - n: size_t) -> *const git_refspec; + pub fn git_remote_dup(dest: *mut *mut git_remote, source: *mut git_remote) -> c_int; + pub fn git_remote_get_fetch_refspecs( + array: *mut git_strarray, + remote: *const git_remote, + ) -> c_int; + pub fn git_remote_get_push_refspecs( + array: *mut git_strarray, + remote: *const git_remote, + ) -> c_int; + pub fn git_remote_get_refspec(remote: *const git_remote, n: size_t) -> *const git_refspec; pub fn git_remote_is_valid_name(remote_name: *const c_char) -> c_int; - pub fn git_remote_list(out: *mut git_strarray, - repo: *mut git_repository) -> c_int; - pub fn git_remote_rename(problems: *mut git_strarray, - repo: *mut git_repository, - name: *const c_char, - new_name: *const c_char) -> c_int; - pub fn git_remote_fetch(remote: *mut git_remote, - refspecs: *const git_strarray, - opts: *const git_fetch_options, - reflog_message: *const c_char) -> c_int; - pub fn git_remote_push(remote: *mut git_remote, - refspecs: *const git_strarray, - opts: *const git_push_options) -> c_int; - pub fn git_remote_update_tips(remote: *mut git_remote, - callbacks: *const git_remote_callbacks, - update_fetchead: c_int, - download_tags: git_remote_autotag_option_t, - reflog_message: *const c_char) -> c_int; - pub fn git_remote_set_url(repo: *mut git_repository, - remote: *const c_char, - url: *const c_char) -> c_int; - pub fn git_remote_set_pushurl(repo: *mut git_repository, - remote: *const c_char, - pushurl: *const c_char) -> c_int; - pub fn git_remote_init_callbacks(opts: *mut git_remote_callbacks, - version: c_uint) -> c_int; - pub fn git_fetch_init_options(opts: *mut git_fetch_options, - version: c_uint) -> c_int; - pub fn git_remote_stats(remote: *mut git_remote) - -> *const git_transfer_progress; - pub fn git_remote_ls(out: *mut *mut *const git_remote_head, - size: *mut size_t, - remote: *mut git_remote) -> c_int; - pub fn git_remote_set_autotag(repo: *mut git_repository, - remote: *const c_char, - value: git_remote_autotag_option_t) -> c_int; - pub fn git_remote_prune(remote: *mut git_remote, - callbacks: *const git_remote_callbacks) -> c_int; + pub fn git_remote_list(out: *mut git_strarray, repo: *mut git_repository) -> c_int; + pub fn git_remote_rename( + problems: *mut git_strarray, + repo: *mut git_repository, + name: *const c_char, + new_name: *const c_char, + ) -> c_int; + pub fn git_remote_fetch( + remote: *mut git_remote, + refspecs: *const git_strarray, + opts: *const git_fetch_options, + reflog_message: *const c_char, + ) -> c_int; + pub fn git_remote_push( + remote: *mut git_remote, + refspecs: *const git_strarray, + opts: *const git_push_options, + ) -> c_int; + pub fn git_remote_update_tips( + remote: *mut git_remote, + callbacks: *const git_remote_callbacks, + update_fetchead: c_int, + download_tags: git_remote_autotag_option_t, + reflog_message: *const c_char, + ) -> c_int; + pub fn git_remote_set_url( + repo: *mut git_repository, + remote: *const c_char, + url: *const c_char, + ) -> c_int; + pub fn git_remote_set_pushurl( + repo: *mut git_repository, + remote: *const c_char, + pushurl: *const c_char, + ) -> c_int; + pub fn git_remote_init_callbacks(opts: *mut git_remote_callbacks, version: c_uint) -> c_int; + pub fn git_fetch_init_options(opts: *mut git_fetch_options, version: c_uint) -> c_int; + pub fn git_remote_stats(remote: *mut git_remote) -> *const git_transfer_progress; + pub fn git_remote_ls( + out: *mut *mut *const git_remote_head, + size: *mut size_t, + remote: *mut git_remote, + ) -> c_int; + pub fn git_remote_set_autotag( + repo: *mut git_repository, + remote: *const c_char, + value: git_remote_autotag_option_t, + ) -> c_int; + pub fn git_remote_prune( + remote: *mut git_remote, + callbacks: *const git_remote_callbacks, + ) -> c_int; // refspec pub fn git_refspec_direction(spec: *const git_refspec) -> git_direction; pub fn git_refspec_dst(spec: *const git_refspec) -> *const c_char; - pub fn git_refspec_dst_matches(spec: *const git_refspec, - refname: *const c_char) -> c_int; + pub fn git_refspec_dst_matches(spec: *const git_refspec, refname: *const c_char) -> c_int; pub fn git_refspec_src(spec: *const git_refspec) -> *const c_char; - pub fn git_refspec_src_matches(spec: *const git_refspec, - refname: *const c_char) -> c_int; + pub fn git_refspec_src_matches(spec: *const git_refspec, refname: *const c_char) -> c_int; pub fn git_refspec_force(spec: *const git_refspec) -> c_int; pub fn git_refspec_string(spec: *const git_refspec) -> *const c_char; @@ -1811,57 +1848,70 @@ extern { pub fn git_oidarray_free(array: *mut git_oidarray); // signature - pub fn git_signature_default(out: *mut *mut git_signature, - repo: *mut git_repository) -> c_int; + pub fn git_signature_default(out: *mut *mut git_signature, repo: *mut git_repository) -> c_int; pub fn git_signature_free(sig: *mut git_signature); - pub fn git_signature_new(out: *mut *mut git_signature, - name: *const c_char, - email: *const c_char, - time: git_time_t, - offset: c_int) -> c_int; - pub fn git_signature_now(out: *mut *mut git_signature, - name: *const c_char, - email: *const c_char) -> c_int; - pub fn git_signature_dup(dest: *mut *mut git_signature, - sig: *const git_signature) -> c_int; + pub fn git_signature_new( + out: *mut *mut git_signature, + name: *const c_char, + email: *const c_char, + time: git_time_t, + offset: c_int, + ) -> c_int; + pub fn git_signature_now( + out: *mut *mut git_signature, + name: *const c_char, + email: *const c_char, + ) -> c_int; + pub fn git_signature_dup(dest: *mut *mut git_signature, sig: *const git_signature) -> c_int; // status - pub fn git_status_list_new(out: *mut *mut git_status_list, - repo: *mut git_repository, - options: *const git_status_options) -> c_int; + pub fn git_status_list_new( + out: *mut *mut git_status_list, + repo: *mut git_repository, + options: *const git_status_options, + ) -> c_int; pub fn git_status_list_entrycount(list: *mut git_status_list) -> size_t; - pub fn git_status_byindex(statuslist: *mut git_status_list, - idx: size_t) -> *const git_status_entry; + pub fn git_status_byindex( + statuslist: *mut git_status_list, + idx: size_t, + ) -> *const git_status_entry; pub fn git_status_list_free(list: *mut git_status_list); - pub fn git_status_init_options(opts: *mut git_status_options, - version: c_uint) -> c_int; - pub fn git_status_file(status_flags: *mut c_uint, - repo: *mut git_repository, - path: *const c_char) -> c_int; - pub fn git_status_should_ignore(ignored: *mut c_int, - repo: *mut git_repository, - path: *const c_char) -> c_int; + pub fn git_status_init_options(opts: *mut git_status_options, version: c_uint) -> c_int; + pub fn git_status_file( + status_flags: *mut c_uint, + repo: *mut git_repository, + path: *const c_char, + ) -> c_int; + pub fn git_status_should_ignore( + ignored: *mut c_int, + repo: *mut git_repository, + path: *const c_char, + ) -> c_int; // clone - pub fn git_clone(out: *mut *mut git_repository, - url: *const c_char, - local_path: *const c_char, - options: *const git_clone_options) -> c_int; - pub fn git_clone_init_options(opts: *mut git_clone_options, - version: c_uint) -> c_int; + pub fn git_clone( + out: *mut *mut git_repository, + url: *const c_char, + local_path: *const c_char, + options: *const git_clone_options, + ) -> c_int; + pub fn git_clone_init_options(opts: *mut git_clone_options, version: c_uint) -> c_int; // reset - pub fn git_reset(repo: *mut git_repository, - target: *const git_object, - reset_type: git_reset_t, - checkout_opts: *const git_checkout_options) -> c_int; - pub fn git_reset_default(repo: *mut git_repository, - target: *const git_object, - pathspecs: *const git_strarray) -> c_int; + pub fn git_reset( + repo: *mut git_repository, + target: *const git_object, + reset_type: git_reset_t, + checkout_opts: *const git_checkout_options, + ) -> c_int; + pub fn git_reset_default( + repo: *mut git_repository, + target: *const git_object, + pathspecs: *const git_strarray, + ) -> c_int; // reference - pub fn git_reference_cmp(ref1: *const git_reference, - ref2: *const git_reference) -> c_int; + pub fn git_reference_cmp(ref1: *const git_reference, ref2: *const git_reference) -> c_int; pub fn git_reference_delete(r: *mut git_reference) -> c_int; pub fn git_reference_free(r: *mut git_reference); pub fn git_reference_is_branch(r: *const git_reference) -> c_int; @@ -1869,685 +1919,854 @@ extern { pub fn git_reference_is_remote(r: *const git_reference) -> c_int; pub fn git_reference_is_tag(r: *const git_reference) -> c_int; pub fn git_reference_is_valid_name(name: *const c_char) -> c_int; - pub fn git_reference_lookup(out: *mut *mut git_reference, - repo: *mut git_repository, - name: *const c_char) -> c_int; - pub fn git_reference_dwim(out: *mut *mut git_reference, - repo: *mut git_repository, - refname: *const c_char) -> c_int; + pub fn git_reference_lookup( + out: *mut *mut git_reference, + repo: *mut git_repository, + name: *const c_char, + ) -> c_int; + pub fn git_reference_dwim( + out: *mut *mut git_reference, + repo: *mut git_repository, + refname: *const c_char, + ) -> c_int; pub fn git_reference_name(r: *const git_reference) -> *const c_char; - pub fn git_reference_name_to_id(out: *mut git_oid, - repo: *mut git_repository, - name: *const c_char) -> c_int; - pub fn git_reference_peel(out: *mut *mut git_object, - r: *const git_reference, - otype: git_object_t) -> c_int; - pub fn git_reference_rename(new_ref: *mut *mut git_reference, - r: *mut git_reference, - new_name: *const c_char, - force: c_int, - log_message: *const c_char) -> c_int; - pub fn git_reference_resolve(out: *mut *mut git_reference, - r: *const git_reference) -> c_int; + pub fn git_reference_name_to_id( + out: *mut git_oid, + repo: *mut git_repository, + name: *const c_char, + ) -> c_int; + pub fn git_reference_peel( + out: *mut *mut git_object, + r: *const git_reference, + otype: git_object_t, + ) -> c_int; + pub fn git_reference_rename( + new_ref: *mut *mut git_reference, + r: *mut git_reference, + new_name: *const c_char, + force: c_int, + log_message: *const c_char, + ) -> c_int; + pub fn git_reference_resolve(out: *mut *mut git_reference, r: *const git_reference) -> c_int; pub fn git_reference_shorthand(r: *const git_reference) -> *const c_char; pub fn git_reference_symbolic_target(r: *const git_reference) -> *const c_char; pub fn git_reference_target(r: *const git_reference) -> *const git_oid; pub fn git_reference_target_peel(r: *const git_reference) -> *const git_oid; - pub fn git_reference_set_target(out: *mut *mut git_reference, - r: *mut git_reference, - id: *const git_oid, - log_message: *const c_char) -> c_int; + pub fn git_reference_set_target( + out: *mut *mut git_reference, + r: *mut git_reference, + id: *const git_oid, + log_message: *const c_char, + ) -> c_int; pub fn git_reference_type(r: *const git_reference) -> git_reference_t; - pub fn git_reference_iterator_new(out: *mut *mut git_reference_iterator, - repo: *mut git_repository) -> c_int; - pub fn git_reference_iterator_glob_new(out: *mut *mut git_reference_iterator, - repo: *mut git_repository, - glob: *const c_char) -> c_int; + pub fn git_reference_iterator_new( + out: *mut *mut git_reference_iterator, + repo: *mut git_repository, + ) -> c_int; + pub fn git_reference_iterator_glob_new( + out: *mut *mut git_reference_iterator, + repo: *mut git_repository, + glob: *const c_char, + ) -> c_int; pub fn git_reference_iterator_free(iter: *mut git_reference_iterator); - pub fn git_reference_next(out: *mut *mut git_reference, - iter: *mut git_reference_iterator) -> c_int; - pub fn git_reference_next_name(out: *mut *const c_char, - iter: *mut git_reference_iterator) -> c_int; - pub fn git_reference_create(out: *mut *mut git_reference, - repo: *mut git_repository, - name: *const c_char, - id: *const git_oid, - force: c_int, - log_message: *const c_char) -> c_int; - pub fn git_reference_symbolic_create(out: *mut *mut git_reference, - repo: *mut git_repository, - name: *const c_char, - target: *const c_char, - force: c_int, - log_message: *const c_char) -> c_int; - pub fn git_reference_create_matching(out: *mut *mut git_reference, - repo: *mut git_repository, - name: *const c_char, - id: *const git_oid, - force: c_int, - current_id: *const git_oid, - log_message: *const c_char) -> c_int; - pub fn git_reference_symbolic_create_matching(out: *mut *mut git_reference, - repo: *mut git_repository, - name: *const c_char, - target: *const c_char, - force: c_int, - current_id: *const c_char, - log_message: *const c_char) - -> c_int; - pub fn git_reference_has_log(repo: *mut git_repository, - name: *const c_char) -> c_int; - pub fn git_reference_ensure_log(repo: *mut git_repository, - name: *const c_char) -> c_int; + pub fn git_reference_next( + out: *mut *mut git_reference, + iter: *mut git_reference_iterator, + ) -> c_int; + pub fn git_reference_next_name( + out: *mut *const c_char, + iter: *mut git_reference_iterator, + ) -> c_int; + pub fn git_reference_create( + out: *mut *mut git_reference, + repo: *mut git_repository, + name: *const c_char, + id: *const git_oid, + force: c_int, + log_message: *const c_char, + ) -> c_int; + pub fn git_reference_symbolic_create( + out: *mut *mut git_reference, + repo: *mut git_repository, + name: *const c_char, + target: *const c_char, + force: c_int, + log_message: *const c_char, + ) -> c_int; + pub fn git_reference_create_matching( + out: *mut *mut git_reference, + repo: *mut git_repository, + name: *const c_char, + id: *const git_oid, + force: c_int, + current_id: *const git_oid, + log_message: *const c_char, + ) -> c_int; + pub fn git_reference_symbolic_create_matching( + out: *mut *mut git_reference, + repo: *mut git_repository, + name: *const c_char, + target: *const c_char, + force: c_int, + current_id: *const c_char, + log_message: *const c_char, + ) -> c_int; + pub fn git_reference_has_log(repo: *mut git_repository, name: *const c_char) -> c_int; + pub fn git_reference_ensure_log(repo: *mut git_repository, name: *const c_char) -> c_int; // stash - pub fn git_stash_save(out: *mut git_oid, - repo: *mut git_repository, - stasher: *const git_signature, - message: *const c_char, - flags: c_uint) -> c_int; - - pub fn git_stash_apply_init_options(opts: *mut git_stash_apply_options, - version: c_uint) -> c_int; - - pub fn git_stash_apply(repo: *mut git_repository, - index: size_t, - options: *const git_stash_apply_options) -> c_int; - - pub fn git_stash_foreach(repo: *mut git_repository, - callback: git_stash_cb, - payload: *mut c_void) -> c_int; - - pub fn git_stash_drop(repo: *mut git_repository, - index: size_t) -> c_int; - - pub fn git_stash_pop(repo: *mut git_repository, - index: size_t, - options: *const git_stash_apply_options) -> c_int; + pub fn git_stash_save( + out: *mut git_oid, + repo: *mut git_repository, + stasher: *const git_signature, + message: *const c_char, + flags: c_uint, + ) -> c_int; + + pub fn git_stash_apply_init_options( + opts: *mut git_stash_apply_options, + version: c_uint, + ) -> c_int; + + pub fn git_stash_apply( + repo: *mut git_repository, + index: size_t, + options: *const git_stash_apply_options, + ) -> c_int; + + pub fn git_stash_foreach( + repo: *mut git_repository, + callback: git_stash_cb, + payload: *mut c_void, + ) -> c_int; + + pub fn git_stash_drop(repo: *mut git_repository, index: size_t) -> c_int; + + pub fn git_stash_pop( + repo: *mut git_repository, + index: size_t, + options: *const git_stash_apply_options, + ) -> c_int; // submodules pub fn git_submodule_add_finalize(submodule: *mut git_submodule) -> c_int; - pub fn git_submodule_add_setup(submodule: *mut *mut git_submodule, - repo: *mut git_repository, - url: *const c_char, - path: *const c_char, - use_gitlink: c_int) -> c_int; - pub fn git_submodule_add_to_index(submodule: *mut git_submodule, - write_index: c_int) -> c_int; + pub fn git_submodule_add_setup( + submodule: *mut *mut git_submodule, + repo: *mut git_repository, + url: *const c_char, + path: *const c_char, + use_gitlink: c_int, + ) -> c_int; + pub fn git_submodule_add_to_index(submodule: *mut git_submodule, write_index: c_int) -> c_int; pub fn git_submodule_branch(submodule: *mut git_submodule) -> *const c_char; - pub fn git_submodule_foreach(repo: *mut git_repository, - callback: git_submodule_cb, - payload: *mut c_void) -> c_int; + pub fn git_submodule_foreach( + repo: *mut git_repository, + callback: git_submodule_cb, + payload: *mut c_void, + ) -> c_int; pub fn git_submodule_free(submodule: *mut git_submodule); pub fn git_submodule_head_id(submodule: *mut git_submodule) -> *const git_oid; pub fn git_submodule_index_id(submodule: *mut git_submodule) -> *const git_oid; - pub fn git_submodule_init(submodule: *mut git_submodule, - overwrite: c_int) -> c_int; - pub fn git_submodule_location(status: *mut c_uint, - submodule: *mut git_submodule) -> c_int; - pub fn git_submodule_lookup(out: *mut *mut git_submodule, - repo: *mut git_repository, - name: *const c_char) -> c_int; + pub fn git_submodule_init(submodule: *mut git_submodule, overwrite: c_int) -> c_int; + pub fn git_submodule_location(status: *mut c_uint, submodule: *mut git_submodule) -> c_int; + pub fn git_submodule_lookup( + out: *mut *mut git_submodule, + repo: *mut git_repository, + name: *const c_char, + ) -> c_int; pub fn git_submodule_name(submodule: *mut git_submodule) -> *const c_char; - pub fn git_submodule_open(repo: *mut *mut git_repository, - submodule: *mut git_submodule) -> c_int; + pub fn git_submodule_open( + repo: *mut *mut git_repository, + submodule: *mut git_submodule, + ) -> c_int; pub fn git_submodule_path(submodule: *mut git_submodule) -> *const c_char; - pub fn git_submodule_reload(submodule: *mut git_submodule, - force: c_int) -> c_int; - pub fn git_submodule_set_ignore(repo: *mut git_repository, - name: *const c_char, - ignore: git_submodule_ignore_t) - -> c_int; - pub fn git_submodule_set_update(repo: *mut git_repository, - name: *const c_char, - update: git_submodule_update_t) - -> c_int; - pub fn git_submodule_set_url(repo: *mut git_repository, - name: *const c_char, - url: *const c_char) -> c_int; + pub fn git_submodule_reload(submodule: *mut git_submodule, force: c_int) -> c_int; + pub fn git_submodule_set_ignore( + repo: *mut git_repository, + name: *const c_char, + ignore: git_submodule_ignore_t, + ) -> c_int; + pub fn git_submodule_set_update( + repo: *mut git_repository, + name: *const c_char, + update: git_submodule_update_t, + ) -> c_int; + pub fn git_submodule_set_url( + repo: *mut git_repository, + name: *const c_char, + url: *const c_char, + ) -> c_int; pub fn git_submodule_sync(submodule: *mut git_submodule) -> c_int; - pub fn git_submodule_update_strategy(submodule: *mut git_submodule) - -> git_submodule_update_t; - pub fn git_submodule_update(submodule: *mut git_submodule, - init: c_int, - options: *mut git_submodule_update_options) - -> c_int; - pub fn git_submodule_update_init_options(options: *mut git_submodule_update_options, - version: c_uint) -> c_int; + pub fn git_submodule_update_strategy(submodule: *mut git_submodule) -> git_submodule_update_t; + pub fn git_submodule_update( + submodule: *mut git_submodule, + init: c_int, + options: *mut git_submodule_update_options, + ) -> c_int; + pub fn git_submodule_update_init_options( + options: *mut git_submodule_update_options, + version: c_uint, + ) -> c_int; pub fn git_submodule_url(/service/submodule: *mut git_submodule) -> *const c_char; pub fn git_submodule_wd_id(submodule: *mut git_submodule) -> *const git_oid; - pub fn git_submodule_status(status: *mut c_uint, - repo: *mut git_repository, - name: *const c_char, - ignore: git_submodule_ignore_t) -> c_int; - pub fn git_submodule_set_branch(repo: *mut git_repository, - name: *const c_char, - branch: *const c_char) -> c_int; + pub fn git_submodule_status( + status: *mut c_uint, + repo: *mut git_repository, + name: *const c_char, + ignore: git_submodule_ignore_t, + ) -> c_int; + pub fn git_submodule_set_branch( + repo: *mut git_repository, + name: *const c_char, + branch: *const c_char, + ) -> c_int; // blob pub fn git_blob_free(blob: *mut git_blob); pub fn git_blob_id(blob: *const git_blob) -> *const git_oid; pub fn git_blob_is_binary(blob: *const git_blob) -> c_int; - pub fn git_blob_lookup(blob: *mut *mut git_blob, repo: *mut git_repository, - id: *const git_oid) -> c_int; - pub fn git_blob_lookup_prefix(blob: *mut *mut git_blob, - repo: *mut git_repository, - id: *const git_oid, - len: size_t) -> c_int; + pub fn git_blob_lookup( + blob: *mut *mut git_blob, + repo: *mut git_repository, + id: *const git_oid, + ) -> c_int; + pub fn git_blob_lookup_prefix( + blob: *mut *mut git_blob, + repo: *mut git_repository, + id: *const git_oid, + len: size_t, + ) -> c_int; pub fn git_blob_rawcontent(blob: *const git_blob) -> *const c_void; pub fn git_blob_rawsize(blob: *const git_blob) -> git_off_t; - pub fn git_blob_create_frombuffer(id: *mut git_oid, - repo: *mut git_repository, - buffer: *const c_void, - len: size_t) -> c_int; - pub fn git_blob_create_fromdisk(id: *mut git_oid, - repo: *mut git_repository, - path: *const c_char) -> c_int; - pub fn git_blob_create_fromworkdir(id: *mut git_oid, - repo: *mut git_repository, - relative_path: *const c_char) -> c_int; - pub fn git_blob_create_fromstream(out: *mut *mut git_writestream, - repo: *mut git_repository, - hintpath: *const c_char) -> c_int; - pub fn git_blob_create_fromstream_commit(id: *mut git_oid, - stream: *mut git_writestream) -> c_int; + pub fn git_blob_create_frombuffer( + id: *mut git_oid, + repo: *mut git_repository, + buffer: *const c_void, + len: size_t, + ) -> c_int; + pub fn git_blob_create_fromdisk( + id: *mut git_oid, + repo: *mut git_repository, + path: *const c_char, + ) -> c_int; + pub fn git_blob_create_fromworkdir( + id: *mut git_oid, + repo: *mut git_repository, + relative_path: *const c_char, + ) -> c_int; + pub fn git_blob_create_fromstream( + out: *mut *mut git_writestream, + repo: *mut git_repository, + hintpath: *const c_char, + ) -> c_int; + pub fn git_blob_create_fromstream_commit( + id: *mut git_oid, + stream: *mut git_writestream, + ) -> c_int; // tree - pub fn git_tree_entry_byid(tree: *const git_tree, - id: *const git_oid) -> *const git_tree_entry; - pub fn git_tree_entry_byindex(tree: *const git_tree, - idx: size_t) -> *const git_tree_entry; - pub fn git_tree_entry_byname(tree: *const git_tree, - filename: *const c_char) -> *const git_tree_entry; - pub fn git_tree_entry_bypath(out: *mut *mut git_tree_entry, - tree: *const git_tree, - filename: *const c_char) -> c_int; - pub fn git_tree_entry_cmp(e1: *const git_tree_entry, - e2: *const git_tree_entry) -> c_int; - pub fn git_tree_entry_dup(dest: *mut *mut git_tree_entry, - src: *const git_tree_entry) -> c_int; + pub fn git_tree_entry_byid(tree: *const git_tree, id: *const git_oid) -> *const git_tree_entry; + pub fn git_tree_entry_byindex(tree: *const git_tree, idx: size_t) -> *const git_tree_entry; + pub fn git_tree_entry_byname( + tree: *const git_tree, + filename: *const c_char, + ) -> *const git_tree_entry; + pub fn git_tree_entry_bypath( + out: *mut *mut git_tree_entry, + tree: *const git_tree, + filename: *const c_char, + ) -> c_int; + pub fn git_tree_entry_cmp(e1: *const git_tree_entry, e2: *const git_tree_entry) -> c_int; + pub fn git_tree_entry_dup(dest: *mut *mut git_tree_entry, src: *const git_tree_entry) -> c_int; pub fn git_tree_entry_filemode(entry: *const git_tree_entry) -> git_filemode_t; pub fn git_tree_entry_filemode_raw(entry: *const git_tree_entry) -> git_filemode_t; pub fn git_tree_entry_free(entry: *mut git_tree_entry); pub fn git_tree_entry_id(entry: *const git_tree_entry) -> *const git_oid; pub fn git_tree_entry_name(entry: *const git_tree_entry) -> *const c_char; - pub fn git_tree_entry_to_object(out: *mut *mut git_object, - repo: *mut git_repository, - entry: *const git_tree_entry) -> c_int; + pub fn git_tree_entry_to_object( + out: *mut *mut git_object, + repo: *mut git_repository, + entry: *const git_tree_entry, + ) -> c_int; pub fn git_tree_entry_type(entry: *const git_tree_entry) -> git_object_t; pub fn git_tree_entrycount(tree: *const git_tree) -> size_t; pub fn git_tree_free(tree: *mut git_tree); pub fn git_tree_id(tree: *const git_tree) -> *const git_oid; - pub fn git_tree_lookup(tree: *mut *mut git_tree, - repo: *mut git_repository, - id: *const git_oid) -> c_int; - pub fn git_tree_walk(tree: *const git_tree, - mode: git_treewalk_mode, - callback: git_treewalk_cb, - payload: *mut c_void) -> c_int; + pub fn git_tree_lookup( + tree: *mut *mut git_tree, + repo: *mut git_repository, + id: *const git_oid, + ) -> c_int; + pub fn git_tree_walk( + tree: *const git_tree, + mode: git_treewalk_mode, + callback: git_treewalk_cb, + payload: *mut c_void, + ) -> c_int; // treebuilder - pub fn git_treebuilder_new(out: *mut *mut git_treebuilder, - repo: *mut git_repository, - source: *const git_tree) -> c_int; + pub fn git_treebuilder_new( + out: *mut *mut git_treebuilder, + repo: *mut git_repository, + source: *const git_tree, + ) -> c_int; pub fn git_treebuilder_clear(bld: *mut git_treebuilder); pub fn git_treebuilder_entrycount(bld: *mut git_treebuilder) -> c_uint; pub fn git_treebuilder_free(bld: *mut git_treebuilder); - pub fn git_treebuilder_get(bld: *mut git_treebuilder, - filename: *const c_char) -> *const git_tree_entry; - pub fn git_treebuilder_insert(out: *mut *const git_tree_entry, - bld: *mut git_treebuilder, - filename: *const c_char, - id: *const git_oid, - filemode: git_filemode_t) -> c_int; - pub fn git_treebuilder_remove(bld: *mut git_treebuilder, - filename: *const c_char) -> c_int; - pub fn git_treebuilder_filter(bld: *mut git_treebuilder, - filter: git_treebuilder_filter_cb, - payload: *mut c_void); - pub fn git_treebuilder_write(id: *mut git_oid, - bld: *mut git_treebuilder) -> c_int; + pub fn git_treebuilder_get( + bld: *mut git_treebuilder, + filename: *const c_char, + ) -> *const git_tree_entry; + pub fn git_treebuilder_insert( + out: *mut *const git_tree_entry, + bld: *mut git_treebuilder, + filename: *const c_char, + id: *const git_oid, + filemode: git_filemode_t, + ) -> c_int; + pub fn git_treebuilder_remove(bld: *mut git_treebuilder, filename: *const c_char) -> c_int; + pub fn git_treebuilder_filter( + bld: *mut git_treebuilder, + filter: git_treebuilder_filter_cb, + payload: *mut c_void, + ); + pub fn git_treebuilder_write(id: *mut git_oid, bld: *mut git_treebuilder) -> c_int; // buf pub fn git_buf_dispose(buffer: *mut git_buf); pub fn git_buf_grow(buffer: *mut git_buf, target_size: size_t) -> c_int; - pub fn git_buf_set(buffer: *mut git_buf, data: *const c_void, - datalen: size_t) -> c_int; + pub fn git_buf_set(buffer: *mut git_buf, data: *const c_void, datalen: size_t) -> c_int; // commit pub fn git_commit_author(commit: *const git_commit) -> *const git_signature; pub fn git_commit_committer(commit: *const git_commit) -> *const git_signature; pub fn git_commit_free(commit: *mut git_commit); pub fn git_commit_id(commit: *const git_commit) -> *const git_oid; - pub fn git_commit_lookup(commit: *mut *mut git_commit, - repo: *mut git_repository, - id: *const git_oid) -> c_int; + pub fn git_commit_lookup( + commit: *mut *mut git_commit, + repo: *mut git_repository, + id: *const git_oid, + ) -> c_int; pub fn git_commit_message(commit: *const git_commit) -> *const c_char; pub fn git_commit_message_encoding(commit: *const git_commit) -> *const c_char; pub fn git_commit_message_raw(commit: *const git_commit) -> *const c_char; - pub fn git_commit_nth_gen_ancestor(commit: *mut *mut git_commit, - commit: *const git_commit, - n: c_uint) -> c_int; - pub fn git_commit_parent(out: *mut *mut git_commit, - commit: *const git_commit, - n: c_uint) -> c_int; - pub fn git_commit_parent_id(commit: *const git_commit, - n: c_uint) -> *const git_oid; + pub fn git_commit_nth_gen_ancestor( + commit: *mut *mut git_commit, + commit: *const git_commit, + n: c_uint, + ) -> c_int; + pub fn git_commit_parent( + out: *mut *mut git_commit, + commit: *const git_commit, + n: c_uint, + ) -> c_int; + pub fn git_commit_parent_id(commit: *const git_commit, n: c_uint) -> *const git_oid; pub fn git_commit_parentcount(commit: *const git_commit) -> c_uint; pub fn git_commit_raw_header(commit: *const git_commit) -> *const c_char; pub fn git_commit_summary(commit: *mut git_commit) -> *const c_char; pub fn git_commit_time(commit: *const git_commit) -> git_time_t; pub fn git_commit_time_offset(commit: *const git_commit) -> c_int; - pub fn git_commit_tree(tree_out: *mut *mut git_tree, - commit: *const git_commit) -> c_int; + pub fn git_commit_tree(tree_out: *mut *mut git_tree, commit: *const git_commit) -> c_int; pub fn git_commit_tree_id(commit: *const git_commit) -> *const git_oid; - pub fn git_commit_amend(id: *mut git_oid, - commit_to_amend: *const git_commit, - update_ref: *const c_char, - author: *const git_signature, - committer: *const git_signature, - message_encoding: *const c_char, - message: *const c_char, - tree: *const git_tree) -> c_int; - pub fn git_commit_create(id: *mut git_oid, - repo: *mut git_repository, - update_ref: *const c_char, - author: *const git_signature, - committer: *const git_signature, - message_encoding: *const c_char, - message: *const c_char, - tree: *const git_tree, - parent_count: size_t, - parents: *mut *const git_commit) -> c_int; - pub fn git_commit_header_field(out: *mut git_buf, - commit: *const git_commit, - field: *const c_char) -> c_int; - pub fn git_annotated_commit_lookup(out: *mut *mut git_annotated_commit, - repo: *mut git_repository, - id: *const git_oid) -> c_int; - pub fn git_commit_create_with_signature(id: *mut git_oid, - repo: *mut git_repository, - commit_content: *const c_char, - signature: *const c_char, - signature_field: *const c_char) -> c_int; - pub fn git_commit_extract_signature(signature: *mut git_buf, - signed_data: *mut git_buf, - repo: *mut git_repository, - commit_id: *mut git_oid, - field: *const c_char) -> c_int; + pub fn git_commit_amend( + id: *mut git_oid, + commit_to_amend: *const git_commit, + update_ref: *const c_char, + author: *const git_signature, + committer: *const git_signature, + message_encoding: *const c_char, + message: *const c_char, + tree: *const git_tree, + ) -> c_int; + pub fn git_commit_create( + id: *mut git_oid, + repo: *mut git_repository, + update_ref: *const c_char, + author: *const git_signature, + committer: *const git_signature, + message_encoding: *const c_char, + message: *const c_char, + tree: *const git_tree, + parent_count: size_t, + parents: *mut *const git_commit, + ) -> c_int; + pub fn git_commit_header_field( + out: *mut git_buf, + commit: *const git_commit, + field: *const c_char, + ) -> c_int; + pub fn git_annotated_commit_lookup( + out: *mut *mut git_annotated_commit, + repo: *mut git_repository, + id: *const git_oid, + ) -> c_int; + pub fn git_commit_create_with_signature( + id: *mut git_oid, + repo: *mut git_repository, + commit_content: *const c_char, + signature: *const c_char, + signature_field: *const c_char, + ) -> c_int; + pub fn git_commit_extract_signature( + signature: *mut git_buf, + signed_data: *mut git_buf, + repo: *mut git_repository, + commit_id: *mut git_oid, + field: *const c_char, + ) -> c_int; // branch - pub fn git_branch_create(out: *mut *mut git_reference, - repo: *mut git_repository, - branch_name: *const c_char, - target: *const git_commit, - force: c_int) -> c_int; + pub fn git_branch_create( + out: *mut *mut git_reference, + repo: *mut git_repository, + branch_name: *const c_char, + target: *const git_commit, + force: c_int, + ) -> c_int; pub fn git_branch_delete(branch: *mut git_reference) -> c_int; pub fn git_branch_is_head(branch: *const git_reference) -> c_int; pub fn git_branch_iterator_free(iter: *mut git_branch_iterator); - pub fn git_branch_iterator_new(iter: *mut *mut git_branch_iterator, - repo: *mut git_repository, - list_flags: git_branch_t) -> c_int; - pub fn git_branch_lookup(out: *mut *mut git_reference, - repo: *mut git_repository, - branch_name: *const c_char, - branch_type: git_branch_t) -> c_int; - pub fn git_branch_move(out: *mut *mut git_reference, - branch: *mut git_reference, - new_branch_name: *const c_char, - force: c_int) -> c_int; - pub fn git_branch_name(out: *mut *const c_char, - branch: *const git_reference) -> c_int; - pub fn git_branch_next(out: *mut *mut git_reference, - out_type: *mut git_branch_t, - iter: *mut git_branch_iterator) -> c_int; - pub fn git_branch_set_upstream(branch: *mut git_reference, - upstream_name: *const c_char) -> c_int; - pub fn git_branch_upstream(out: *mut *mut git_reference, - branch: *const git_reference) -> c_int; + pub fn git_branch_iterator_new( + iter: *mut *mut git_branch_iterator, + repo: *mut git_repository, + list_flags: git_branch_t, + ) -> c_int; + pub fn git_branch_lookup( + out: *mut *mut git_reference, + repo: *mut git_repository, + branch_name: *const c_char, + branch_type: git_branch_t, + ) -> c_int; + pub fn git_branch_move( + out: *mut *mut git_reference, + branch: *mut git_reference, + new_branch_name: *const c_char, + force: c_int, + ) -> c_int; + pub fn git_branch_name(out: *mut *const c_char, branch: *const git_reference) -> c_int; + pub fn git_branch_next( + out: *mut *mut git_reference, + out_type: *mut git_branch_t, + iter: *mut git_branch_iterator, + ) -> c_int; + pub fn git_branch_set_upstream( + branch: *mut git_reference, + upstream_name: *const c_char, + ) -> c_int; + pub fn git_branch_upstream(out: *mut *mut git_reference, branch: *const git_reference) + -> c_int; // index - pub fn git_index_add(index: *mut git_index, - entry: *const git_index_entry) -> c_int; - pub fn git_index_add_all(index: *mut git_index, - pathspec: *const git_strarray, - flags: c_uint, - callback: Option, - payload: *mut c_void) -> c_int; - pub fn git_index_add_bypath(index: *mut git_index, - path: *const c_char) -> c_int; - pub fn git_index_add_frombuffer(index: *mut git_index, - entry: *const git_index_entry, - buffer: *const c_void, - len: size_t) -> c_int; - pub fn git_index_conflict_add(index: *mut git_index, - ancestor_entry: *const git_index_entry, - our_entry: *const git_index_entry, - their_entry: *const git_index_entry) -> c_int; + pub fn git_index_add(index: *mut git_index, entry: *const git_index_entry) -> c_int; + pub fn git_index_add_all( + index: *mut git_index, + pathspec: *const git_strarray, + flags: c_uint, + callback: Option, + payload: *mut c_void, + ) -> c_int; + pub fn git_index_add_bypath(index: *mut git_index, path: *const c_char) -> c_int; + pub fn git_index_add_frombuffer( + index: *mut git_index, + entry: *const git_index_entry, + buffer: *const c_void, + len: size_t, + ) -> c_int; + pub fn git_index_conflict_add( + index: *mut git_index, + ancestor_entry: *const git_index_entry, + our_entry: *const git_index_entry, + their_entry: *const git_index_entry, + ) -> c_int; pub fn git_index_conflict_remove(index: *mut git_index, path: *const c_char) -> c_int; - pub fn git_index_conflict_get(ancestor_out: *mut *const git_index_entry, - our_out: *mut *const git_index_entry, - their_out: *mut *const git_index_entry, - index: *mut git_index, - path: *const c_char) -> c_int; - pub fn git_index_conflict_iterator_new(iter: *mut *mut git_index_conflict_iterator, - index: *mut git_index) -> c_int; - pub fn git_index_conflict_next(ancestor_out: *mut *const git_index_entry, - our_out: *mut *const git_index_entry, - their_out: *mut *const git_index_entry, - iter: *mut git_index_conflict_iterator) -> c_int; + pub fn git_index_conflict_get( + ancestor_out: *mut *const git_index_entry, + our_out: *mut *const git_index_entry, + their_out: *mut *const git_index_entry, + index: *mut git_index, + path: *const c_char, + ) -> c_int; + pub fn git_index_conflict_iterator_new( + iter: *mut *mut git_index_conflict_iterator, + index: *mut git_index, + ) -> c_int; + pub fn git_index_conflict_next( + ancestor_out: *mut *const git_index_entry, + our_out: *mut *const git_index_entry, + their_out: *mut *const git_index_entry, + iter: *mut git_index_conflict_iterator, + ) -> c_int; pub fn git_index_conflict_iterator_free(iter: *mut git_index_conflict_iterator); pub fn git_index_clear(index: *mut git_index) -> c_int; pub fn git_index_entry_stage(entry: *const git_index_entry) -> c_int; pub fn git_index_entrycount(entry: *const git_index) -> size_t; - pub fn git_index_find(at_pos: *mut size_t, - index: *mut git_index, - path: *const c_char) -> c_int; + pub fn git_index_find(at_pos: *mut size_t, index: *mut git_index, path: *const c_char) + -> c_int; pub fn git_index_free(index: *mut git_index); - pub fn git_index_get_byindex(index: *mut git_index, - n: size_t) -> *const git_index_entry; - pub fn git_index_get_bypath(index: *mut git_index, - path: *const c_char, - stage: c_int) -> *const git_index_entry; + pub fn git_index_get_byindex(index: *mut git_index, n: size_t) -> *const git_index_entry; + pub fn git_index_get_bypath( + index: *mut git_index, + path: *const c_char, + stage: c_int, + ) -> *const git_index_entry; pub fn git_index_has_conflicts(index: *const git_index) -> c_int; pub fn git_index_new(index: *mut *mut git_index) -> c_int; - pub fn git_index_open(index: *mut *mut git_index, - index_path: *const c_char) -> c_int; + pub fn git_index_open(index: *mut *mut git_index, index_path: *const c_char) -> c_int; pub fn git_index_path(index: *const git_index) -> *const c_char; pub fn git_index_read(index: *mut git_index, force: c_int) -> c_int; - pub fn git_index_read_tree(index: *mut git_index, - tree: *const git_tree) -> c_int; - pub fn git_index_remove(index: *mut git_index, - path: *const c_char, - stage: c_int) -> c_int; - pub fn git_index_remove_all(index: *mut git_index, - pathspec: *const git_strarray, - callback: Option, - payload: *mut c_void) -> c_int; - pub fn git_index_remove_bypath(index: *mut git_index, - path: *const c_char) -> c_int; - pub fn git_index_remove_directory(index: *mut git_index, - dir: *const c_char, - stage: c_int) -> c_int; - pub fn git_index_update_all(index: *mut git_index, - pathspec: *const git_strarray, - callback: Option, - payload: *mut c_void) -> c_int; + pub fn git_index_read_tree(index: *mut git_index, tree: *const git_tree) -> c_int; + pub fn git_index_remove(index: *mut git_index, path: *const c_char, stage: c_int) -> c_int; + pub fn git_index_remove_all( + index: *mut git_index, + pathspec: *const git_strarray, + callback: Option, + payload: *mut c_void, + ) -> c_int; + pub fn git_index_remove_bypath(index: *mut git_index, path: *const c_char) -> c_int; + pub fn git_index_remove_directory( + index: *mut git_index, + dir: *const c_char, + stage: c_int, + ) -> c_int; + pub fn git_index_update_all( + index: *mut git_index, + pathspec: *const git_strarray, + callback: Option, + payload: *mut c_void, + ) -> c_int; pub fn git_index_write(index: *mut git_index) -> c_int; - pub fn git_index_write_tree(out: *mut git_oid, - index: *mut git_index) -> c_int; - pub fn git_index_write_tree_to(out: *mut git_oid, - index: *mut git_index, - repo: *mut git_repository) -> c_int; + pub fn git_index_write_tree(out: *mut git_oid, index: *mut git_index) -> c_int; + pub fn git_index_write_tree_to( + out: *mut git_oid, + index: *mut git_index, + repo: *mut git_repository, + ) -> c_int; // config - pub fn git_config_add_file_ondisk(cfg: *mut git_config, - path: *const c_char, - level: git_config_level_t, - repo: *const git_repository, - force: c_int) -> c_int; - pub fn git_config_delete_entry(cfg: *mut git_config, - name: *const c_char) -> c_int; - pub fn git_config_delete_multivar(cfg: *mut git_config, - name: *const c_char, - regexp: *const c_char) -> c_int; + pub fn git_config_add_file_ondisk( + cfg: *mut git_config, + path: *const c_char, + level: git_config_level_t, + repo: *const git_repository, + force: c_int, + ) -> c_int; + pub fn git_config_delete_entry(cfg: *mut git_config, name: *const c_char) -> c_int; + pub fn git_config_delete_multivar( + cfg: *mut git_config, + name: *const c_char, + regexp: *const c_char, + ) -> c_int; pub fn git_config_find_programdata(out: *mut git_buf) -> c_int; pub fn git_config_find_global(out: *mut git_buf) -> c_int; pub fn git_config_find_system(out: *mut git_buf) -> c_int; pub fn git_config_find_xdg(out: *mut git_buf) -> c_int; pub fn git_config_free(cfg: *mut git_config); - pub fn git_config_get_bool(out: *mut c_int, - cfg: *const git_config, - name: *const c_char) -> c_int; - pub fn git_config_get_entry(out: *mut *mut git_config_entry, - cfg: *const git_config, - name: *const c_char) -> c_int; - pub fn git_config_get_int32(out: *mut i32, - cfg: *const git_config, - name: *const c_char) -> c_int; - pub fn git_config_get_int64(out: *mut i64, - cfg: *const git_config, - name: *const c_char) -> c_int; - pub fn git_config_get_string(out: *mut *const c_char, - cfg: *const git_config, - name: *const c_char) -> c_int; - pub fn git_config_get_string_buf(out: *mut git_buf, - cfg: *const git_config, - name: *const c_char) -> c_int; - pub fn git_config_get_path(out: *mut git_buf, - cfg: *const git_config, - name: *const c_char) -> c_int; + pub fn git_config_get_bool( + out: *mut c_int, + cfg: *const git_config, + name: *const c_char, + ) -> c_int; + pub fn git_config_get_entry( + out: *mut *mut git_config_entry, + cfg: *const git_config, + name: *const c_char, + ) -> c_int; + pub fn git_config_get_int32( + out: *mut i32, + cfg: *const git_config, + name: *const c_char, + ) -> c_int; + pub fn git_config_get_int64( + out: *mut i64, + cfg: *const git_config, + name: *const c_char, + ) -> c_int; + pub fn git_config_get_string( + out: *mut *const c_char, + cfg: *const git_config, + name: *const c_char, + ) -> c_int; + pub fn git_config_get_string_buf( + out: *mut git_buf, + cfg: *const git_config, + name: *const c_char, + ) -> c_int; + pub fn git_config_get_path( + out: *mut git_buf, + cfg: *const git_config, + name: *const c_char, + ) -> c_int; pub fn git_config_iterator_free(iter: *mut git_config_iterator); - pub fn git_config_iterator_glob_new(out: *mut *mut git_config_iterator, - cfg: *const git_config, - regexp: *const c_char) -> c_int; - pub fn git_config_iterator_new(out: *mut *mut git_config_iterator, - cfg: *const git_config) -> c_int; + pub fn git_config_iterator_glob_new( + out: *mut *mut git_config_iterator, + cfg: *const git_config, + regexp: *const c_char, + ) -> c_int; + pub fn git_config_iterator_new( + out: *mut *mut git_config_iterator, + cfg: *const git_config, + ) -> c_int; pub fn git_config_new(out: *mut *mut git_config) -> c_int; - pub fn git_config_next(entry: *mut *mut git_config_entry, - iter: *mut git_config_iterator) -> c_int; + pub fn git_config_next( + entry: *mut *mut git_config_entry, + iter: *mut git_config_iterator, + ) -> c_int; pub fn git_config_open_default(out: *mut *mut git_config) -> c_int; - pub fn git_config_open_global(out: *mut *mut git_config, - config: *mut git_config) -> c_int; - pub fn git_config_open_level(out: *mut *mut git_config, - parent: *const git_config, - level: git_config_level_t) -> c_int; - pub fn git_config_open_ondisk(out: *mut *mut git_config, - path: *const c_char) -> c_int; - pub fn git_config_parse_bool(out: *mut c_int, - value: *const c_char) -> c_int; - pub fn git_config_parse_int32(out: *mut i32, - value: *const c_char) -> c_int; - pub fn git_config_parse_int64(out: *mut i64, - value: *const c_char) -> c_int; - pub fn git_config_set_bool(cfg: *mut git_config, - name: *const c_char, - value: c_int) -> c_int; - pub fn git_config_set_int32(cfg: *mut git_config, - name: *const c_char, - value: i32) -> c_int; - pub fn git_config_set_int64(cfg: *mut git_config, - name: *const c_char, - value: i64) -> c_int; - pub fn git_config_set_multivar(cfg: *mut git_config, - name: *const c_char, - regexp: *const c_char, - value: *const c_char) -> c_int; - pub fn git_config_set_string(cfg: *mut git_config, - name: *const c_char, - value: *const c_char) -> c_int; - pub fn git_config_snapshot(out: *mut *mut git_config, - config: *mut git_config) -> c_int; + pub fn git_config_open_global(out: *mut *mut git_config, config: *mut git_config) -> c_int; + pub fn git_config_open_level( + out: *mut *mut git_config, + parent: *const git_config, + level: git_config_level_t, + ) -> c_int; + pub fn git_config_open_ondisk(out: *mut *mut git_config, path: *const c_char) -> c_int; + pub fn git_config_parse_bool(out: *mut c_int, value: *const c_char) -> c_int; + pub fn git_config_parse_int32(out: *mut i32, value: *const c_char) -> c_int; + pub fn git_config_parse_int64(out: *mut i64, value: *const c_char) -> c_int; + pub fn git_config_set_bool(cfg: *mut git_config, name: *const c_char, value: c_int) -> c_int; + pub fn git_config_set_int32(cfg: *mut git_config, name: *const c_char, value: i32) -> c_int; + pub fn git_config_set_int64(cfg: *mut git_config, name: *const c_char, value: i64) -> c_int; + pub fn git_config_set_multivar( + cfg: *mut git_config, + name: *const c_char, + regexp: *const c_char, + value: *const c_char, + ) -> c_int; + pub fn git_config_set_string( + cfg: *mut git_config, + name: *const c_char, + value: *const c_char, + ) -> c_int; + pub fn git_config_snapshot(out: *mut *mut git_config, config: *mut git_config) -> c_int; pub fn git_config_entry_free(entry: *mut git_config_entry); // cred pub fn git_cred_default_new(out: *mut *mut git_cred) -> c_int; pub fn git_cred_has_username(cred: *mut git_cred) -> c_int; - pub fn git_cred_ssh_custom_new(out: *mut *mut git_cred, - username: *const c_char, - publickey: *const c_char, - publickey_len: size_t, - sign_callback: git_cred_sign_callback, - payload: *mut c_void) -> c_int; - pub fn git_cred_ssh_interactive_new(out: *mut *mut git_cred, - username: *const c_char, - prompt_callback: git_cred_ssh_interactive_callback, - payload: *mut c_void) -> c_int; - pub fn git_cred_ssh_key_from_agent(out: *mut *mut git_cred, - username: *const c_char) -> c_int; - pub fn git_cred_ssh_key_new(out: *mut *mut git_cred, - username: *const c_char, - publickey: *const c_char, - privatekey: *const c_char, - passphrase: *const c_char) -> c_int; - pub fn git_cred_ssh_key_memory_new(out: *mut *mut git_cred, - username: *const c_char, - publickey: *const c_char, - privatekey: *const c_char, - passphrase: *const c_char) -> c_int; - pub fn git_cred_userpass(cred: *mut *mut git_cred, - url: *const c_char, - user_from_url: *const c_char, - allowed_types: c_uint, - payload: *mut c_void) -> c_int; - pub fn git_cred_userpass_plaintext_new(out: *mut *mut git_cred, - username: *const c_char, - password: *const c_char) -> c_int; - pub fn git_cred_username_new(cred: *mut *mut git_cred, - username: *const c_char) -> c_int; + pub fn git_cred_ssh_custom_new( + out: *mut *mut git_cred, + username: *const c_char, + publickey: *const c_char, + publickey_len: size_t, + sign_callback: git_cred_sign_callback, + payload: *mut c_void, + ) -> c_int; + pub fn git_cred_ssh_interactive_new( + out: *mut *mut git_cred, + username: *const c_char, + prompt_callback: git_cred_ssh_interactive_callback, + payload: *mut c_void, + ) -> c_int; + pub fn git_cred_ssh_key_from_agent(out: *mut *mut git_cred, username: *const c_char) -> c_int; + pub fn git_cred_ssh_key_new( + out: *mut *mut git_cred, + username: *const c_char, + publickey: *const c_char, + privatekey: *const c_char, + passphrase: *const c_char, + ) -> c_int; + pub fn git_cred_ssh_key_memory_new( + out: *mut *mut git_cred, + username: *const c_char, + publickey: *const c_char, + privatekey: *const c_char, + passphrase: *const c_char, + ) -> c_int; + pub fn git_cred_userpass( + cred: *mut *mut git_cred, + url: *const c_char, + user_from_url: *const c_char, + allowed_types: c_uint, + payload: *mut c_void, + ) -> c_int; + pub fn git_cred_userpass_plaintext_new( + out: *mut *mut git_cred, + username: *const c_char, + password: *const c_char, + ) -> c_int; + pub fn git_cred_username_new(cred: *mut *mut git_cred, username: *const c_char) -> c_int; // tags - pub fn git_tag_annotation_create(oid: *mut git_oid, - repo: *mut git_repository, - tag_name: *const c_char, - target: *const git_object, - tagger: *const git_signature, - message: *const c_char) -> c_int; - pub fn git_tag_create(oid: *mut git_oid, - repo: *mut git_repository, - tag_name: *const c_char, - target: *const git_object, - tagger: *const git_signature, - message: *const c_char, - force: c_int) -> c_int; - pub fn git_tag_create_frombuffer(oid: *mut git_oid, - repo: *mut git_repository, - buffer: *const c_char, - force: c_int) -> c_int; - pub fn git_tag_create_lightweight(oid: *mut git_oid, - repo: *mut git_repository, - tag_name: *const c_char, - target: *const git_object, - force: c_int) -> c_int; - pub fn git_tag_delete(repo: *mut git_repository, - tag_name: *const c_char) -> c_int; - pub fn git_tag_foreach(repo: *mut git_repository, - callback: git_tag_foreach_cb, - payload: *mut c_void) -> c_int; + pub fn git_tag_annotation_create( + oid: *mut git_oid, + repo: *mut git_repository, + tag_name: *const c_char, + target: *const git_object, + tagger: *const git_signature, + message: *const c_char, + ) -> c_int; + pub fn git_tag_create( + oid: *mut git_oid, + repo: *mut git_repository, + tag_name: *const c_char, + target: *const git_object, + tagger: *const git_signature, + message: *const c_char, + force: c_int, + ) -> c_int; + pub fn git_tag_create_frombuffer( + oid: *mut git_oid, + repo: *mut git_repository, + buffer: *const c_char, + force: c_int, + ) -> c_int; + pub fn git_tag_create_lightweight( + oid: *mut git_oid, + repo: *mut git_repository, + tag_name: *const c_char, + target: *const git_object, + force: c_int, + ) -> c_int; + pub fn git_tag_delete(repo: *mut git_repository, tag_name: *const c_char) -> c_int; + pub fn git_tag_foreach( + repo: *mut git_repository, + callback: git_tag_foreach_cb, + payload: *mut c_void, + ) -> c_int; pub fn git_tag_free(tag: *mut git_tag); pub fn git_tag_id(tag: *const git_tag) -> *const git_oid; - pub fn git_tag_list(tag_names: *mut git_strarray, - repo: *mut git_repository) -> c_int; - pub fn git_tag_list_match(tag_names: *mut git_strarray, - pattern: *const c_char, - repo: *mut git_repository) -> c_int; - pub fn git_tag_lookup(out: *mut *mut git_tag, - repo: *mut git_repository, - id: *const git_oid) -> c_int; - pub fn git_tag_lookup_prefix(out: *mut *mut git_tag, - repo: *mut git_repository, - id: *const git_oid, - len: size_t) -> c_int; + pub fn git_tag_list(tag_names: *mut git_strarray, repo: *mut git_repository) -> c_int; + pub fn git_tag_list_match( + tag_names: *mut git_strarray, + pattern: *const c_char, + repo: *mut git_repository, + ) -> c_int; + pub fn git_tag_lookup( + out: *mut *mut git_tag, + repo: *mut git_repository, + id: *const git_oid, + ) -> c_int; + pub fn git_tag_lookup_prefix( + out: *mut *mut git_tag, + repo: *mut git_repository, + id: *const git_oid, + len: size_t, + ) -> c_int; pub fn git_tag_message(tag: *const git_tag) -> *const c_char; pub fn git_tag_name(tag: *const git_tag) -> *const c_char; - pub fn git_tag_peel(tag_target_out: *mut *mut git_object, - tag: *const git_tag) -> c_int; + pub fn git_tag_peel(tag_target_out: *mut *mut git_object, tag: *const git_tag) -> c_int; pub fn git_tag_tagger(tag: *const git_tag) -> *const git_signature; - pub fn git_tag_target(target_out: *mut *mut git_object, - tag: *const git_tag) -> c_int; + pub fn git_tag_target(target_out: *mut *mut git_object, tag: *const git_tag) -> c_int; pub fn git_tag_target_id(tag: *const git_tag) -> *const git_oid; pub fn git_tag_target_type(tag: *const git_tag) -> git_object_t; // checkout - pub fn git_checkout_head(repo: *mut git_repository, - opts: *const git_checkout_options) -> c_int; - pub fn git_checkout_index(repo: *mut git_repository, - index: *mut git_index, - opts: *const git_checkout_options) -> c_int; - pub fn git_checkout_tree(repo: *mut git_repository, - treeish: *const git_object, - opts: *const git_checkout_options) -> c_int; - pub fn git_checkout_init_options(opts: *mut git_checkout_options, - version: c_uint) -> c_int; + pub fn git_checkout_head(repo: *mut git_repository, opts: *const git_checkout_options) + -> c_int; + pub fn git_checkout_index( + repo: *mut git_repository, + index: *mut git_index, + opts: *const git_checkout_options, + ) -> c_int; + pub fn git_checkout_tree( + repo: *mut git_repository, + treeish: *const git_object, + opts: *const git_checkout_options, + ) -> c_int; + pub fn git_checkout_init_options(opts: *mut git_checkout_options, version: c_uint) -> c_int; // merge - pub fn git_annotated_commit_id(commit: *const git_annotated_commit) - -> *const git_oid; - pub fn git_annotated_commit_from_ref(out: *mut *mut git_annotated_commit, - repo: *mut git_repository, - reference: *const git_reference) - -> c_int; + pub fn git_annotated_commit_id(commit: *const git_annotated_commit) -> *const git_oid; + pub fn git_annotated_commit_from_ref( + out: *mut *mut git_annotated_commit, + repo: *mut git_repository, + reference: *const git_reference, + ) -> c_int; pub fn git_annotated_commit_free(commit: *mut git_annotated_commit); - pub fn git_merge_init_options(opts: *mut git_merge_options, - version: c_uint) -> c_int; - pub fn git_merge(repo: *mut git_repository, - their_heads: *mut *const git_annotated_commit, - len: size_t, - merge_opts: *const git_merge_options, - checkout_opts: *const git_checkout_options) -> c_int; - pub fn git_merge_commits(out: *mut *mut git_index, - repo: *mut git_repository, - our_commit: *const git_commit, - their_commit: *const git_commit, - opts: *const git_merge_options) -> c_int; - pub fn git_merge_trees(out: *mut *mut git_index, - repo: *mut git_repository, - ancestor_tree: *const git_tree, - our_tree: *const git_tree, - their_tree: *const git_tree, - opts: *const git_merge_options) -> c_int; + pub fn git_merge_init_options(opts: *mut git_merge_options, version: c_uint) -> c_int; + pub fn git_merge( + repo: *mut git_repository, + their_heads: *mut *const git_annotated_commit, + len: size_t, + merge_opts: *const git_merge_options, + checkout_opts: *const git_checkout_options, + ) -> c_int; + pub fn git_merge_commits( + out: *mut *mut git_index, + repo: *mut git_repository, + our_commit: *const git_commit, + their_commit: *const git_commit, + opts: *const git_merge_options, + ) -> c_int; + pub fn git_merge_trees( + out: *mut *mut git_index, + repo: *mut git_repository, + ancestor_tree: *const git_tree, + our_tree: *const git_tree, + their_tree: *const git_tree, + opts: *const git_merge_options, + ) -> c_int; pub fn git_repository_state_cleanup(repo: *mut git_repository) -> c_int; // merge analysis - pub fn git_merge_analysis(analysis_out: *mut git_merge_analysis_t, - pref_out: *mut git_merge_preference_t, - repo: *mut git_repository, - their_heads: *mut *const git_annotated_commit, - their_heads_len: usize) -> c_int; + pub fn git_merge_analysis( + analysis_out: *mut git_merge_analysis_t, + pref_out: *mut git_merge_preference_t, + repo: *mut git_repository, + their_heads: *mut *const git_annotated_commit, + their_heads_len: usize, + ) -> c_int; // notes pub fn git_note_author(note: *const git_note) -> *const git_signature; pub fn git_note_committer(note: *const git_note) -> *const git_signature; - pub fn git_note_create(out: *mut git_oid, - repo: *mut git_repository, - notes_ref: *const c_char, - author: *const git_signature, - committer: *const git_signature, - oid: *const git_oid, - note: *const c_char, - force: c_int) -> c_int; - pub fn git_note_default_ref(out: *mut git_buf, - repo: *mut git_repository) -> c_int; + pub fn git_note_create( + out: *mut git_oid, + repo: *mut git_repository, + notes_ref: *const c_char, + author: *const git_signature, + committer: *const git_signature, + oid: *const git_oid, + note: *const c_char, + force: c_int, + ) -> c_int; + pub fn git_note_default_ref(out: *mut git_buf, repo: *mut git_repository) -> c_int; pub fn git_note_free(note: *mut git_note); pub fn git_note_id(note: *const git_note) -> *const git_oid; pub fn git_note_iterator_free(it: *mut git_note_iterator); - pub fn git_note_iterator_new(out: *mut *mut git_note_iterator, - repo: *mut git_repository, - notes_ref: *const c_char) -> c_int; + pub fn git_note_iterator_new( + out: *mut *mut git_note_iterator, + repo: *mut git_repository, + notes_ref: *const c_char, + ) -> c_int; pub fn git_note_message(note: *const git_note) -> *const c_char; - pub fn git_note_next(note_id: *mut git_oid, - annotated_id: *mut git_oid, - it: *mut git_note_iterator) -> c_int; - pub fn git_note_read(out: *mut *mut git_note, - repo: *mut git_repository, - notes_ref: *const c_char, - oid: *const git_oid) -> c_int; - pub fn git_note_remove(repo: *mut git_repository, - notes_ref: *const c_char, - author: *const git_signature, - committer: *const git_signature, - oid: *const git_oid) -> c_int; + pub fn git_note_next( + note_id: *mut git_oid, + annotated_id: *mut git_oid, + it: *mut git_note_iterator, + ) -> c_int; + pub fn git_note_read( + out: *mut *mut git_note, + repo: *mut git_repository, + notes_ref: *const c_char, + oid: *const git_oid, + ) -> c_int; + pub fn git_note_remove( + repo: *mut git_repository, + notes_ref: *const c_char, + author: *const git_signature, + committer: *const git_signature, + oid: *const git_oid, + ) -> c_int; // blame - pub fn git_blame_file(out: *mut *mut git_blame, - repo: *mut git_repository, - path: *const c_char, - options: *mut git_blame_options) -> c_int; + pub fn git_blame_file( + out: *mut *mut git_blame, + repo: *mut git_repository, + path: *const c_char, + options: *mut git_blame_options, + ) -> c_int; pub fn git_blame_free(blame: *mut git_blame); - pub fn git_blame_init_options(opts: *mut git_blame_options, - version: c_uint) -> c_int; + pub fn git_blame_init_options(opts: *mut git_blame_options, version: c_uint) -> c_int; pub fn git_blame_get_hunk_count(blame: *mut git_blame) -> u32; - pub fn git_blame_get_hunk_byline(blame: *mut git_blame, - lineno: usize) -> *const git_blame_hunk; - pub fn git_blame_get_hunk_byindex(blame: *mut git_blame, - index: u32) -> *const git_blame_hunk; + pub fn git_blame_get_hunk_byline(blame: *mut git_blame, lineno: usize) + -> *const git_blame_hunk; + pub fn git_blame_get_hunk_byindex(blame: *mut git_blame, index: u32) -> *const git_blame_hunk; // revwalk - pub fn git_revwalk_new(out: *mut *mut git_revwalk, - repo: *mut git_repository) -> c_int; + pub fn git_revwalk_new(out: *mut *mut git_revwalk, repo: *mut git_repository) -> c_int; pub fn git_revwalk_free(walk: *mut git_revwalk); pub fn git_revwalk_reset(walk: *mut git_revwalk); @@ -2555,383 +2774,467 @@ extern { pub fn git_revwalk_sorting(walk: *mut git_revwalk, sort_mode: c_uint); pub fn git_revwalk_push_head(walk: *mut git_revwalk) -> c_int; - pub fn git_revwalk_push(walk: *mut git_revwalk, - oid: *const git_oid) -> c_int; - pub fn git_revwalk_push_ref(walk: *mut git_revwalk, - refname: *const c_char) -> c_int; - pub fn git_revwalk_push_glob(walk: *mut git_revwalk, - glob: *const c_char) -> c_int; - pub fn git_revwalk_push_range(walk: *mut git_revwalk, - range: *const c_char) -> c_int; + pub fn git_revwalk_push(walk: *mut git_revwalk, oid: *const git_oid) -> c_int; + pub fn git_revwalk_push_ref(walk: *mut git_revwalk, refname: *const c_char) -> c_int; + pub fn git_revwalk_push_glob(walk: *mut git_revwalk, glob: *const c_char) -> c_int; + pub fn git_revwalk_push_range(walk: *mut git_revwalk, range: *const c_char) -> c_int; pub fn git_revwalk_simplify_first_parent(walk: *mut git_revwalk); pub fn git_revwalk_hide_head(walk: *mut git_revwalk) -> c_int; - pub fn git_revwalk_hide(walk: *mut git_revwalk, - oid: *const git_oid) -> c_int; - pub fn git_revwalk_hide_ref(walk: *mut git_revwalk, - refname: *const c_char) -> c_int; - pub fn git_revwalk_hide_glob(walk: *mut git_revwalk, - refname: *const c_char) -> c_int; - pub fn git_revwalk_add_hide_cb(walk: *mut git_revwalk, - hide_cb: git_revwalk_hide_cb, - payload: *mut c_void) -> c_int; + pub fn git_revwalk_hide(walk: *mut git_revwalk, oid: *const git_oid) -> c_int; + pub fn git_revwalk_hide_ref(walk: *mut git_revwalk, refname: *const c_char) -> c_int; + pub fn git_revwalk_hide_glob(walk: *mut git_revwalk, refname: *const c_char) -> c_int; + pub fn git_revwalk_add_hide_cb( + walk: *mut git_revwalk, + hide_cb: git_revwalk_hide_cb, + payload: *mut c_void, + ) -> c_int; pub fn git_revwalk_next(out: *mut git_oid, walk: *mut git_revwalk) -> c_int; // merge - pub fn git_merge_base(out: *mut git_oid, - repo: *mut git_repository, - one: *const git_oid, - two: *const git_oid) -> c_int; - - pub fn git_merge_bases(out: *mut git_oidarray, - repo: *mut git_repository, - one: *const git_oid, - two: *const git_oid) -> c_int; + pub fn git_merge_base( + out: *mut git_oid, + repo: *mut git_repository, + one: *const git_oid, + two: *const git_oid, + ) -> c_int; + + pub fn git_merge_bases( + out: *mut git_oidarray, + repo: *mut git_repository, + one: *const git_oid, + two: *const git_oid, + ) -> c_int; // pathspec pub fn git_pathspec_free(ps: *mut git_pathspec); - pub fn git_pathspec_match_diff(out: *mut *mut git_pathspec_match_list, - diff: *mut git_diff, - flags: u32, - ps: *mut git_pathspec) -> c_int; - pub fn git_pathspec_match_index(out: *mut *mut git_pathspec_match_list, - index: *mut git_index, - flags: u32, - ps: *mut git_pathspec) -> c_int; - pub fn git_pathspec_match_list_diff_entry(m: *const git_pathspec_match_list, - pos: size_t) -> *const git_diff_delta; - pub fn git_pathspec_match_list_entry(m: *const git_pathspec_match_list, - pos: size_t) -> *const c_char; - pub fn git_pathspec_match_list_entrycount(m: *const git_pathspec_match_list) - -> size_t; - pub fn git_pathspec_match_list_failed_entry(m: *const git_pathspec_match_list, - pos: size_t) -> *const c_char; - pub fn git_pathspec_match_list_failed_entrycount( - m: *const git_pathspec_match_list) -> size_t; + pub fn git_pathspec_match_diff( + out: *mut *mut git_pathspec_match_list, + diff: *mut git_diff, + flags: u32, + ps: *mut git_pathspec, + ) -> c_int; + pub fn git_pathspec_match_index( + out: *mut *mut git_pathspec_match_list, + index: *mut git_index, + flags: u32, + ps: *mut git_pathspec, + ) -> c_int; + pub fn git_pathspec_match_list_diff_entry( + m: *const git_pathspec_match_list, + pos: size_t, + ) -> *const git_diff_delta; + pub fn git_pathspec_match_list_entry( + m: *const git_pathspec_match_list, + pos: size_t, + ) -> *const c_char; + pub fn git_pathspec_match_list_entrycount(m: *const git_pathspec_match_list) -> size_t; + pub fn git_pathspec_match_list_failed_entry( + m: *const git_pathspec_match_list, + pos: size_t, + ) -> *const c_char; + pub fn git_pathspec_match_list_failed_entrycount(m: *const git_pathspec_match_list) -> size_t; pub fn git_pathspec_match_list_free(m: *mut git_pathspec_match_list); - pub fn git_pathspec_match_tree(out: *mut *mut git_pathspec_match_list, - tree: *mut git_tree, - flags: u32, - ps: *mut git_pathspec) -> c_int; - pub fn git_pathspec_match_workdir(out: *mut *mut git_pathspec_match_list, - repo: *mut git_repository, - flags: u32, - ps: *mut git_pathspec) -> c_int; - pub fn git_pathspec_matches_path(ps: *const git_pathspec, - flags: u32, - path: *const c_char) -> c_int; - pub fn git_pathspec_new(out: *mut *mut git_pathspec, - pathspec: *const git_strarray) -> c_int; + pub fn git_pathspec_match_tree( + out: *mut *mut git_pathspec_match_list, + tree: *mut git_tree, + flags: u32, + ps: *mut git_pathspec, + ) -> c_int; + pub fn git_pathspec_match_workdir( + out: *mut *mut git_pathspec_match_list, + repo: *mut git_repository, + flags: u32, + ps: *mut git_pathspec, + ) -> c_int; + pub fn git_pathspec_matches_path( + ps: *const git_pathspec, + flags: u32, + path: *const c_char, + ) -> c_int; + pub fn git_pathspec_new(out: *mut *mut git_pathspec, pathspec: *const git_strarray) -> c_int; // diff - pub fn git_diff_blob_to_buffer(old_blob: *const git_blob, - old_as_path: *const c_char, - buffer: *const c_char, - buffer_len: size_t, - buffer_as_path: *const c_char, - options: *const git_diff_options, - file_cb: git_diff_file_cb, - binary_cb: git_diff_binary_cb, - hunk_cb: git_diff_hunk_cb, - line_cb: git_diff_line_cb, - payload: *mut c_void) -> c_int; - pub fn git_diff_blobs(old_blob: *const git_blob, - old_as_path: *const c_char, - new_blob: *const git_blob, - new_as_path: *const c_char, - options: *const git_diff_options, - file_cb: git_diff_file_cb, - binary_cb: git_diff_binary_cb, - hunk_cb: git_diff_hunk_cb, - line_cb: git_diff_line_cb, - payload: *mut c_void) -> c_int; - pub fn git_diff_buffers(old_buffer: *const c_void, - old_len: size_t, - old_as_path: *const c_char, - new_buffer: *const c_void, - new_len: size_t, - new_as_path: *const c_char, - options: *const git_diff_options, - file_cb: git_diff_file_cb, - binary_cb: git_diff_binary_cb, - hunk_cb: git_diff_hunk_cb, - line_cb: git_diff_line_cb, - payload: *mut c_void) -> c_int; - pub fn git_diff_find_similar(diff: *mut git_diff, - options: *const git_diff_find_options) -> c_int; - pub fn git_diff_find_init_options(opts: *mut git_diff_find_options, - version: c_uint) -> c_int; - pub fn git_diff_foreach(diff: *mut git_diff, - file_cb: git_diff_file_cb, - binary_cb: Option, - hunk_cb: Option, - line_cb: Option, - payload: *mut c_void) -> c_int; + pub fn git_diff_blob_to_buffer( + old_blob: *const git_blob, + old_as_path: *const c_char, + buffer: *const c_char, + buffer_len: size_t, + buffer_as_path: *const c_char, + options: *const git_diff_options, + file_cb: git_diff_file_cb, + binary_cb: git_diff_binary_cb, + hunk_cb: git_diff_hunk_cb, + line_cb: git_diff_line_cb, + payload: *mut c_void, + ) -> c_int; + pub fn git_diff_blobs( + old_blob: *const git_blob, + old_as_path: *const c_char, + new_blob: *const git_blob, + new_as_path: *const c_char, + options: *const git_diff_options, + file_cb: git_diff_file_cb, + binary_cb: git_diff_binary_cb, + hunk_cb: git_diff_hunk_cb, + line_cb: git_diff_line_cb, + payload: *mut c_void, + ) -> c_int; + pub fn git_diff_buffers( + old_buffer: *const c_void, + old_len: size_t, + old_as_path: *const c_char, + new_buffer: *const c_void, + new_len: size_t, + new_as_path: *const c_char, + options: *const git_diff_options, + file_cb: git_diff_file_cb, + binary_cb: git_diff_binary_cb, + hunk_cb: git_diff_hunk_cb, + line_cb: git_diff_line_cb, + payload: *mut c_void, + ) -> c_int; + pub fn git_diff_find_similar( + diff: *mut git_diff, + options: *const git_diff_find_options, + ) -> c_int; + pub fn git_diff_find_init_options(opts: *mut git_diff_find_options, version: c_uint) -> c_int; + pub fn git_diff_foreach( + diff: *mut git_diff, + file_cb: git_diff_file_cb, + binary_cb: Option, + hunk_cb: Option, + line_cb: Option, + payload: *mut c_void, + ) -> c_int; pub fn git_diff_free(diff: *mut git_diff); - pub fn git_diff_get_delta(diff: *const git_diff, - idx: size_t) -> *const git_diff_delta; - pub fn git_diff_get_stats(out: *mut *mut git_diff_stats, - diff: *mut git_diff) -> c_int; - pub fn git_diff_index_to_index(diff: *mut *mut git_diff, - repo: *mut git_repository, - old_index: *mut git_index, - new_index: *mut git_index, - opts: *const git_diff_options) -> c_int; - pub fn git_diff_index_to_workdir(diff: *mut *mut git_diff, - repo: *mut git_repository, - index: *mut git_index, - opts: *const git_diff_options) -> c_int; - pub fn git_diff_init_options(opts: *mut git_diff_options, - version: c_uint) -> c_int; + pub fn git_diff_get_delta(diff: *const git_diff, idx: size_t) -> *const git_diff_delta; + pub fn git_diff_get_stats(out: *mut *mut git_diff_stats, diff: *mut git_diff) -> c_int; + pub fn git_diff_index_to_index( + diff: *mut *mut git_diff, + repo: *mut git_repository, + old_index: *mut git_index, + new_index: *mut git_index, + opts: *const git_diff_options, + ) -> c_int; + pub fn git_diff_index_to_workdir( + diff: *mut *mut git_diff, + repo: *mut git_repository, + index: *mut git_index, + opts: *const git_diff_options, + ) -> c_int; + pub fn git_diff_init_options(opts: *mut git_diff_options, version: c_uint) -> c_int; pub fn git_diff_is_sorted_icase(diff: *const git_diff) -> c_int; - pub fn git_diff_merge(onto: *mut git_diff, - from: *const git_diff) -> c_int; + pub fn git_diff_merge(onto: *mut git_diff, from: *const git_diff) -> c_int; pub fn git_diff_num_deltas(diff: *const git_diff) -> size_t; - pub fn git_diff_num_deltas_of_type(diff: *const git_diff, - delta: git_delta_t) -> size_t; - pub fn git_diff_print(diff: *mut git_diff, - format: git_diff_format_t, - print_cb: git_diff_line_cb, - payload: *mut c_void) -> c_int; + pub fn git_diff_num_deltas_of_type(diff: *const git_diff, delta: git_delta_t) -> size_t; + pub fn git_diff_print( + diff: *mut git_diff, + format: git_diff_format_t, + print_cb: git_diff_line_cb, + payload: *mut c_void, + ) -> c_int; pub fn git_diff_stats_deletions(stats: *const git_diff_stats) -> size_t; pub fn git_diff_stats_files_changed(stats: *const git_diff_stats) -> size_t; pub fn git_diff_stats_free(stats: *mut git_diff_stats); pub fn git_diff_stats_insertions(stats: *const git_diff_stats) -> size_t; - pub fn git_diff_stats_to_buf(out: *mut git_buf, - stats: *const git_diff_stats, - format: git_diff_stats_format_t, - width: size_t) -> c_int; + pub fn git_diff_stats_to_buf( + out: *mut git_buf, + stats: *const git_diff_stats, + format: git_diff_stats_format_t, + width: size_t, + ) -> c_int; pub fn git_diff_status_char(status: git_delta_t) -> c_char; - pub fn git_diff_tree_to_index(diff: *mut *mut git_diff, - repo: *mut git_repository, - old_tree: *mut git_tree, - index: *mut git_index, - opts: *const git_diff_options) -> c_int; - pub fn git_diff_tree_to_tree(diff: *mut *mut git_diff, - repo: *mut git_repository, - old_tree: *mut git_tree, - new_tree: *mut git_tree, - opts: *const git_diff_options) -> c_int; - pub fn git_diff_tree_to_workdir(diff: *mut *mut git_diff, - repo: *mut git_repository, - old_tree: *mut git_tree, - opts: *const git_diff_options) -> c_int; - pub fn git_diff_tree_to_workdir_with_index(diff: *mut *mut git_diff, - repo: *mut git_repository, - old_tree: *mut git_tree, - opts: *const git_diff_options) - -> c_int; - - pub fn git_graph_ahead_behind(ahead: *mut size_t, behind: *mut size_t, - repo: *mut git_repository, - local: *const git_oid, upstream: *const git_oid) - -> c_int; - - pub fn git_graph_descendant_of(repo: *mut git_repository, - commit: *const git_oid, ancestor: *const git_oid) - -> c_int; + pub fn git_diff_tree_to_index( + diff: *mut *mut git_diff, + repo: *mut git_repository, + old_tree: *mut git_tree, + index: *mut git_index, + opts: *const git_diff_options, + ) -> c_int; + pub fn git_diff_tree_to_tree( + diff: *mut *mut git_diff, + repo: *mut git_repository, + old_tree: *mut git_tree, + new_tree: *mut git_tree, + opts: *const git_diff_options, + ) -> c_int; + pub fn git_diff_tree_to_workdir( + diff: *mut *mut git_diff, + repo: *mut git_repository, + old_tree: *mut git_tree, + opts: *const git_diff_options, + ) -> c_int; + pub fn git_diff_tree_to_workdir_with_index( + diff: *mut *mut git_diff, + repo: *mut git_repository, + old_tree: *mut git_tree, + opts: *const git_diff_options, + ) -> c_int; + + pub fn git_graph_ahead_behind( + ahead: *mut size_t, + behind: *mut size_t, + repo: *mut git_repository, + local: *const git_oid, + upstream: *const git_oid, + ) -> c_int; + + pub fn git_graph_descendant_of( + repo: *mut git_repository, + commit: *const git_oid, + ancestor: *const git_oid, + ) -> c_int; // patch - pub fn git_patch_from_diff(out: *mut *mut git_patch, - diff: *mut git_diff, - idx: size_t) -> c_int; - pub fn git_patch_from_blobs(out: *mut *mut git_patch, - old_blob: *const git_blob, - old_as_path: *const c_char, - new_blob: *const git_blob, - new_as_path: *const c_char, - opts: *const git_diff_options) -> c_int; - pub fn git_patch_from_blob_and_buffer(out: *mut *mut git_patch, - old_blob: *const git_blob, - old_as_path: *const c_char, - buffer: *const c_void, - buffer_len: size_t, - buffer_as_path: *const c_char, - opts: *const git_diff_options) -> c_int; - pub fn git_patch_from_buffers(out: *mut *mut git_patch, - old_buffer: *const c_void, - old_len: size_t, - old_as_path: *const c_char, - new_buffer: *const c_void, - new_len: size_t, - new_as_path: *const c_char, - opts: *const git_diff_options) -> c_int; + pub fn git_patch_from_diff(out: *mut *mut git_patch, diff: *mut git_diff, idx: size_t) + -> c_int; + pub fn git_patch_from_blobs( + out: *mut *mut git_patch, + old_blob: *const git_blob, + old_as_path: *const c_char, + new_blob: *const git_blob, + new_as_path: *const c_char, + opts: *const git_diff_options, + ) -> c_int; + pub fn git_patch_from_blob_and_buffer( + out: *mut *mut git_patch, + old_blob: *const git_blob, + old_as_path: *const c_char, + buffer: *const c_void, + buffer_len: size_t, + buffer_as_path: *const c_char, + opts: *const git_diff_options, + ) -> c_int; + pub fn git_patch_from_buffers( + out: *mut *mut git_patch, + old_buffer: *const c_void, + old_len: size_t, + old_as_path: *const c_char, + new_buffer: *const c_void, + new_len: size_t, + new_as_path: *const c_char, + opts: *const git_diff_options, + ) -> c_int; pub fn git_patch_free(patch: *mut git_patch); pub fn git_patch_get_delta(patch: *const git_patch) -> *const git_diff_delta; pub fn git_patch_num_hunks(patch: *const git_patch) -> size_t; - pub fn git_patch_line_stats(total_context: *mut size_t, - total_additions: *mut size_t, - total_deletions: *mut size_t, - patch: *const git_patch) -> c_int; - pub fn git_patch_get_hunk(out: *mut *const git_diff_hunk, - lines_in_hunk: *mut size_t, - patch: *mut git_patch, - hunk_idx: size_t) -> c_int; - pub fn git_patch_num_lines_in_hunk(patch: *const git_patch, - hunk_idx: size_t) -> c_int; - pub fn git_patch_get_line_in_hunk(out: *mut *const git_diff_line, - patch: *mut git_patch, - hunk_idx: size_t, - line_of_hunk: size_t) -> c_int; - pub fn git_patch_size(patch: *mut git_patch, - include_context: c_int, - include_hunk_headers: c_int, - include_file_headers: c_int) -> size_t; - pub fn git_patch_print(patch: *mut git_patch, - print_cb: git_diff_line_cb, - payload: *mut c_void) -> c_int; - pub fn git_patch_to_buf(buf: *mut git_buf, - patch: *mut git_patch) -> c_int; + pub fn git_patch_line_stats( + total_context: *mut size_t, + total_additions: *mut size_t, + total_deletions: *mut size_t, + patch: *const git_patch, + ) -> c_int; + pub fn git_patch_get_hunk( + out: *mut *const git_diff_hunk, + lines_in_hunk: *mut size_t, + patch: *mut git_patch, + hunk_idx: size_t, + ) -> c_int; + pub fn git_patch_num_lines_in_hunk(patch: *const git_patch, hunk_idx: size_t) -> c_int; + pub fn git_patch_get_line_in_hunk( + out: *mut *const git_diff_line, + patch: *mut git_patch, + hunk_idx: size_t, + line_of_hunk: size_t, + ) -> c_int; + pub fn git_patch_size( + patch: *mut git_patch, + include_context: c_int, + include_hunk_headers: c_int, + include_file_headers: c_int, + ) -> size_t; + pub fn git_patch_print( + patch: *mut git_patch, + print_cb: git_diff_line_cb, + payload: *mut c_void, + ) -> c_int; + pub fn git_patch_to_buf(buf: *mut git_buf, patch: *mut git_patch) -> c_int; // reflog - pub fn git_reflog_append(reflog: *mut git_reflog, - id: *const git_oid, - committer: *const git_signature, - msg: *const c_char) -> c_int; - pub fn git_reflog_delete(repo: *mut git_repository, - name: *const c_char) -> c_int; - pub fn git_reflog_drop(reflog: *mut git_reflog, - idx: size_t, - rewrite_previous_entry: c_int) -> c_int; - pub fn git_reflog_entry_byindex(reflog: *const git_reflog, - idx: size_t) -> *const git_reflog_entry; - pub fn git_reflog_entry_committer(entry: *const git_reflog_entry) - -> *const git_signature; - pub fn git_reflog_entry_id_new(entry: *const git_reflog_entry) - -> *const git_oid; - pub fn git_reflog_entry_id_old(entry: *const git_reflog_entry) - -> *const git_oid; - pub fn git_reflog_entry_message(entry: *const git_reflog_entry) - -> *const c_char; + pub fn git_reflog_append( + reflog: *mut git_reflog, + id: *const git_oid, + committer: *const git_signature, + msg: *const c_char, + ) -> c_int; + pub fn git_reflog_delete(repo: *mut git_repository, name: *const c_char) -> c_int; + pub fn git_reflog_drop( + reflog: *mut git_reflog, + idx: size_t, + rewrite_previous_entry: c_int, + ) -> c_int; + pub fn git_reflog_entry_byindex( + reflog: *const git_reflog, + idx: size_t, + ) -> *const git_reflog_entry; + pub fn git_reflog_entry_committer(entry: *const git_reflog_entry) -> *const git_signature; + pub fn git_reflog_entry_id_new(entry: *const git_reflog_entry) -> *const git_oid; + pub fn git_reflog_entry_id_old(entry: *const git_reflog_entry) -> *const git_oid; + pub fn git_reflog_entry_message(entry: *const git_reflog_entry) -> *const c_char; pub fn git_reflog_entrycount(reflog: *mut git_reflog) -> size_t; pub fn git_reflog_free(reflog: *mut git_reflog); - pub fn git_reflog_read(out: *mut *mut git_reflog, - repo: *mut git_repository, - name: *const c_char) -> c_int; - pub fn git_reflog_rename(repo: *mut git_repository, - old_name: *const c_char, - name: *const c_char) -> c_int; + pub fn git_reflog_read( + out: *mut *mut git_reflog, + repo: *mut git_repository, + name: *const c_char, + ) -> c_int; + pub fn git_reflog_rename( + repo: *mut git_repository, + old_name: *const c_char, + name: *const c_char, + ) -> c_int; pub fn git_reflog_write(reflog: *mut git_reflog) -> c_int; // transport - pub fn git_transport_register(prefix: *const c_char, - cb: git_transport_cb, - param: *mut c_void) -> c_int; + pub fn git_transport_register( + prefix: *const c_char, + cb: git_transport_cb, + param: *mut c_void, + ) -> c_int; pub fn git_transport_unregister(prefix: *const c_char) -> c_int; - pub fn git_transport_smart(out: *mut *mut git_transport, - owner: *mut git_remote, - payload: *mut c_void) -> c_int; + pub fn git_transport_smart( + out: *mut *mut git_transport, + owner: *mut git_remote, + payload: *mut c_void, + ) -> c_int; // describe - pub fn git_describe_commit(result: *mut *mut git_describe_result, - object: *mut git_object, - opts: *mut git_describe_options) -> c_int; - pub fn git_describe_format(buf: *mut git_buf, - result: *const git_describe_result, - opts: *const git_describe_format_options) -> c_int; + pub fn git_describe_commit( + result: *mut *mut git_describe_result, + object: *mut git_object, + opts: *mut git_describe_options, + ) -> c_int; + pub fn git_describe_format( + buf: *mut git_buf, + result: *const git_describe_result, + opts: *const git_describe_format_options, + ) -> c_int; pub fn git_describe_result_free(result: *mut git_describe_result); - pub fn git_describe_workdir(out: *mut *mut git_describe_result, - repo: *mut git_repository, - opts: *mut git_describe_options) -> c_int; + pub fn git_describe_workdir( + out: *mut *mut git_describe_result, + repo: *mut git_repository, + opts: *mut git_describe_options, + ) -> c_int; // message - pub fn git_message_prettify(out: *mut git_buf, - message: *const c_char, - strip_comments: c_int, - comment_char: c_char) -> c_int; + pub fn git_message_prettify( + out: *mut git_buf, + message: *const c_char, + strip_comments: c_int, + comment_char: c_char, + ) -> c_int; // packbuilder - pub fn git_packbuilder_new(out: *mut *mut git_packbuilder, - repo: *mut git_repository) -> c_int; - pub fn git_packbuilder_set_threads(pb: *mut git_packbuilder, - n: c_uint) -> c_uint; - pub fn git_packbuilder_insert(pb: *mut git_packbuilder, - id: *const git_oid, - name: *const c_char) -> c_int; - pub fn git_packbuilder_insert_tree(pb: *mut git_packbuilder, - id: *const git_oid) -> c_int; - pub fn git_packbuilder_insert_commit(pb: *mut git_packbuilder, - id: *const git_oid) -> c_int; - pub fn git_packbuilder_insert_walk(pb: *mut git_packbuilder, - walk: *mut git_revwalk) -> c_int; - pub fn git_packbuilder_insert_recur(pb: *mut git_packbuilder, - id: *const git_oid, - name: *const c_char) -> c_int; - pub fn git_packbuilder_write_buf(buf: *mut git_buf, - pb: *mut git_packbuilder) -> c_int; - pub fn git_packbuilder_write(pb: *mut git_packbuilder, - path: *const c_char, - mode: c_uint, - progress_cb: Option, - progress_cb_payload: *mut c_void) -> c_int; + pub fn git_packbuilder_new(out: *mut *mut git_packbuilder, repo: *mut git_repository) -> c_int; + pub fn git_packbuilder_set_threads(pb: *mut git_packbuilder, n: c_uint) -> c_uint; + pub fn git_packbuilder_insert( + pb: *mut git_packbuilder, + id: *const git_oid, + name: *const c_char, + ) -> c_int; + pub fn git_packbuilder_insert_tree(pb: *mut git_packbuilder, id: *const git_oid) -> c_int; + pub fn git_packbuilder_insert_commit(pb: *mut git_packbuilder, id: *const git_oid) -> c_int; + pub fn git_packbuilder_insert_walk(pb: *mut git_packbuilder, walk: *mut git_revwalk) -> c_int; + pub fn git_packbuilder_insert_recur( + pb: *mut git_packbuilder, + id: *const git_oid, + name: *const c_char, + ) -> c_int; + pub fn git_packbuilder_write_buf(buf: *mut git_buf, pb: *mut git_packbuilder) -> c_int; + pub fn git_packbuilder_write( + pb: *mut git_packbuilder, + path: *const c_char, + mode: c_uint, + progress_cb: Option, + progress_cb_payload: *mut c_void, + ) -> c_int; pub fn git_packbuilder_hash(pb: *mut git_packbuilder) -> *const git_oid; - pub fn git_packbuilder_foreach(pb: *mut git_packbuilder, - cb: git_packbuilder_foreach_cb, - payload: *mut c_void) -> c_int; + 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) -> 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; + pub fn git_packbuilder_set_callbacks( + pb: *mut git_packbuilder, + progress_cb: Option, + progress_cb_payload: *mut c_void, + ) -> c_int; pub fn git_packbuilder_free(pb: *mut git_packbuilder); // odb - pub fn git_repository_odb(out: *mut *mut git_odb, - repo: *mut git_repository) -> c_int; + pub fn git_repository_odb(out: *mut *mut git_odb, repo: *mut git_repository) -> c_int; pub fn git_odb_new(db: *mut *mut git_odb) -> c_int; pub fn git_odb_free(db: *mut git_odb); - pub fn git_odb_open_rstream(out: *mut *mut git_odb_stream, - len: *mut size_t, - otype: *mut git_object_t, - db: *mut git_odb, - oid: *const git_oid) -> c_int; - pub fn git_odb_stream_read(stream: *mut git_odb_stream, - buffer: *mut c_char, - len: size_t) -> c_int; - pub fn git_odb_open_wstream(out: *mut *mut git_odb_stream, - db: *mut git_odb, - size: git_off_t, - obj_type: git_object_t) -> c_int; - pub fn git_odb_stream_write(stream: *mut git_odb_stream, - buffer: *const c_char, - len: size_t) -> c_int; - pub fn git_odb_stream_finalize_write(id: *mut git_oid, - stream: *mut git_odb_stream) -> c_int; + pub fn git_odb_open_rstream( + out: *mut *mut git_odb_stream, + len: *mut size_t, + otype: *mut git_object_t, + db: *mut git_odb, + oid: *const git_oid, + ) -> c_int; + pub fn git_odb_stream_read( + stream: *mut git_odb_stream, + buffer: *mut c_char, + len: size_t, + ) -> c_int; + pub fn git_odb_open_wstream( + out: *mut *mut git_odb_stream, + db: *mut git_odb, + size: git_off_t, + obj_type: git_object_t, + ) -> c_int; + pub fn git_odb_stream_write( + stream: *mut git_odb_stream, + buffer: *const c_char, + len: size_t, + ) -> c_int; + pub fn git_odb_stream_finalize_write(id: *mut git_oid, stream: *mut git_odb_stream) -> c_int; pub fn git_odb_stream_free(stream: *mut git_odb_stream); - pub fn git_odb_foreach(db: *mut git_odb, cb: git_odb_foreach_cb, payload: *mut c_void) -> c_int; - - pub fn git_odb_read(out: *mut *mut git_odb_object, - odb: *mut git_odb, - oid: *const git_oid) -> c_int; - - pub fn git_odb_read_header(len_out: *mut size_t, - type_out: *mut git_object_t, - odb: *mut git_odb, - oid: *const git_oid) -> c_int; - - pub fn git_odb_write(out: *mut git_oid, - odb: *mut git_odb, - data: *const c_void, - len: size_t, - otype: git_object_t) -> c_int; - - pub fn git_odb_hash(out: *mut git_oid, - data: *const c_void, - len: size_t, - otype: git_object_t) -> c_int; - - pub fn git_odb_hashfile(out: *mut git_oid, - path: *const c_char, - otype: git_object_t) -> c_int; - - pub fn git_odb_exists_prefix(out: *mut git_oid, - odb: *mut git_odb, - short_oid: *const git_oid, - len: size_t) -> c_int; - - pub fn git_odb_exists(odb: *mut git_odb, - oid: *const git_oid) -> c_int; + pub fn git_odb_foreach(db: *mut git_odb, cb: git_odb_foreach_cb, payload: *mut c_void) + -> c_int; + + pub fn git_odb_read( + out: *mut *mut git_odb_object, + odb: *mut git_odb, + oid: *const git_oid, + ) -> c_int; + + pub fn git_odb_read_header( + len_out: *mut size_t, + type_out: *mut git_object_t, + odb: *mut git_odb, + oid: *const git_oid, + ) -> c_int; + + pub fn git_odb_write( + out: *mut git_oid, + odb: *mut git_odb, + data: *const c_void, + len: size_t, + otype: git_object_t, + ) -> c_int; + + pub fn git_odb_hash( + out: *mut git_oid, + data: *const c_void, + len: size_t, + otype: git_object_t, + ) -> c_int; + + pub fn git_odb_hashfile(out: *mut git_oid, path: *const c_char, otype: git_object_t) -> c_int; + + pub fn git_odb_exists_prefix( + out: *mut git_oid, + odb: *mut git_odb, + short_oid: *const git_oid, + len: size_t, + ) -> c_int; + + pub fn git_odb_exists(odb: *mut git_odb, oid: *const git_oid) -> c_int; pub fn git_odb_refresh(odb: *mut git_odb) -> c_int; @@ -2939,56 +3242,69 @@ extern { pub fn git_odb_object_size(obj: *mut git_odb_object) -> size_t; pub fn git_odb_object_type(obj: *mut git_odb_object) -> git_object_t; pub fn git_odb_object_data(obj: *mut git_odb_object) -> *const c_void; - pub fn git_odb_object_dup(out: *mut *mut git_odb_object, - obj: *mut git_odb_object) -> c_int; + pub fn git_odb_object_dup(out: *mut *mut git_odb_object, obj: *mut git_odb_object) -> c_int; pub fn git_odb_object_free(obj: *mut git_odb_object); - pub fn git_odb_init_backend(odb: *mut git_odb_backend, - version: c_uint) -> c_int; + pub fn git_odb_init_backend(odb: *mut git_odb_backend, version: c_uint) -> c_int; - pub fn git_odb_add_backend(odb: *mut git_odb, - backend: *mut git_odb_backend, - priority: c_int) -> c_int; + pub fn git_odb_add_backend( + odb: *mut git_odb, + backend: *mut git_odb_backend, + priority: c_int, + ) -> c_int; - pub fn git_odb_backend_pack(out: *mut *mut git_odb_backend, - objects_dir: *const c_char) -> c_int; + pub fn git_odb_backend_pack( + out: *mut *mut git_odb_backend, + objects_dir: *const c_char, + ) -> c_int; - pub fn git_odb_backend_one_pack(out: *mut *mut git_odb_backend, - objects_dir: *const c_char) -> c_int; + pub fn git_odb_backend_one_pack( + out: *mut *mut git_odb_backend, + objects_dir: *const c_char, + ) -> c_int; - pub fn git_odb_add_disk_alternate(odb: *mut git_odb, - path: *const c_char) -> c_int; + pub fn git_odb_add_disk_alternate(odb: *mut git_odb, path: *const c_char) -> c_int; - pub fn git_odb_backend_loose(out: *mut *mut git_odb_backend, - objects_dir: *const c_char, - compression_level: c_int, - do_fsync: c_int, - dir_mode: c_uint, - file_mode: c_uint) -> c_int; + pub fn git_odb_backend_loose( + out: *mut *mut git_odb_backend, + objects_dir: *const c_char, + compression_level: c_int, + do_fsync: c_int, + dir_mode: c_uint, + file_mode: c_uint, + ) -> c_int; - pub fn git_odb_add_alternate(odb: *mut git_odb, - backend: *mut git_odb_backend, - priority: c_int) -> c_int; + pub fn git_odb_add_alternate( + odb: *mut git_odb, + backend: *mut git_odb_backend, + priority: c_int, + ) -> c_int; - pub fn git_odb_backend_malloc(backend: *mut git_odb_backend, - len: size_t) -> *mut c_void; + pub fn git_odb_backend_malloc(backend: *mut git_odb_backend, len: size_t) -> *mut c_void; pub fn git_odb_num_backends(odb: *mut git_odb) -> size_t; - pub fn git_odb_get_backend(backend: *mut *mut git_odb_backend, - odb: *mut git_odb, - position: size_t) -> c_int; + pub fn git_odb_get_backend( + backend: *mut *mut git_odb_backend, + odb: *mut git_odb, + position: size_t, + ) -> c_int; // mempack pub fn git_mempack_new(out: *mut *mut git_odb_backend) -> c_int; pub fn git_mempack_reset(backend: *mut git_odb_backend); - pub fn git_mempack_dump(pack: *mut git_buf, - repo: *mut git_repository, - backend: *mut git_odb_backend) -> c_int; + pub fn git_mempack_dump( + pack: *mut git_buf, + repo: *mut git_repository, + backend: *mut git_odb_backend, + ) -> c_int; // refdb pub fn git_refdb_new(out: *mut *mut git_refdb, repo: *mut git_repository) -> c_int; pub fn git_refdb_open(out: *mut *mut git_refdb, repo: *mut git_repository) -> c_int; - pub fn git_refdb_backend_fs(out: *mut *mut git_refdb_backend, repo: *mut git_repository) -> c_int; + pub fn git_refdb_backend_fs( + out: *mut *mut git_refdb_backend, + repo: *mut git_repository, + ) -> c_int; pub fn git_refdb_init_backend(backend: *mut git_refdb_backend, version: c_uint) -> c_int; pub fn git_refdb_set_backend(refdb: *mut git_refdb, backend: *mut git_refdb_backend) -> c_int; pub fn git_refdb_compress(refdb: *mut git_refdb) -> c_int; @@ -2996,24 +3312,38 @@ extern { // rebase pub fn git_rebase_init_options(opts: *mut git_rebase_options, version: c_uint) -> c_int; - pub fn git_rebase_init(out: *mut *mut git_rebase, - repo: *mut git_repository, - branch: *const git_annotated_commit, - upstream: *const git_annotated_commit, - onto: *const git_annotated_commit, - opts: *const git_rebase_options) -> c_int; - pub fn git_rebase_open(out: *mut *mut git_rebase, repo: *mut git_repository, opts: *const git_rebase_options) -> c_int; + pub fn git_rebase_init( + out: *mut *mut git_rebase, + repo: *mut git_repository, + branch: *const git_annotated_commit, + upstream: *const git_annotated_commit, + onto: *const git_annotated_commit, + opts: *const git_rebase_options, + ) -> c_int; + pub fn git_rebase_open( + out: *mut *mut git_rebase, + repo: *mut git_repository, + opts: *const git_rebase_options, + ) -> c_int; pub fn git_rebase_operation_entrycount(rebase: *mut git_rebase) -> size_t; pub fn git_rebase_operation_current(rebase: *mut git_rebase) -> size_t; - pub fn git_rebase_operation_byindex(rebase: *mut git_rebase, idx: size_t) -> *mut git_rebase_operation; - pub fn git_rebase_next(operation: *mut *mut git_rebase_operation, rebase: *mut git_rebase) -> c_int; + pub fn git_rebase_operation_byindex( + rebase: *mut git_rebase, + idx: size_t, + ) -> *mut git_rebase_operation; + pub fn git_rebase_next( + operation: *mut *mut git_rebase_operation, + rebase: *mut git_rebase, + ) -> c_int; pub fn git_rebase_inmemory_index(index: *mut *mut git_index, rebase: *mut git_rebase) -> c_int; - pub fn git_rebase_commit(id: *mut git_oid, - rebase: *mut git_rebase, - author: *const git_signature, - committer: *const git_signature, - message_encoding: *const c_char, - message: *const c_char) -> c_int; + pub fn git_rebase_commit( + id: *mut git_oid, + rebase: *mut git_rebase, + author: *const git_signature, + committer: *const git_signature, + message_encoding: *const c_char, + message: *const c_char, + ) -> c_int; pub fn git_rebase_abort(rebase: *mut git_rebase) -> c_int; pub fn git_rebase_finish(rebase: *mut git_rebase, signature: *const git_signature) -> c_int; pub fn git_rebase_free(rebase: *mut git_rebase); @@ -3027,8 +3357,7 @@ pub fn init() { openssl_init(); ssh_init(); let r = git_libgit2_init(); - assert!(r >= 0, - "couldn't initialize the libgit2 library: {}", r); + assert!(r >= 0, "couldn't initialize the libgit2 library: {}", r); // Note that we intentionally never schedule `git_libgit2_shutdown` to // get called. There's not really a great time to call that and #276 has diff --git a/src/blame.rs b/src/blame.rs index 9f6b15571c..0dcb6a2c0e 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -1,9 +1,9 @@ use std::marker; -use {raw, Repository, Oid, signature, Signature}; -use util::{self, Binding}; -use std::path::Path; -use std::ops::Range; use std::mem; +use std::ops::Range; +use std::path::Path; +use util::{self, Binding}; +use {raw, signature, Oid, Repository, Signature}; /// Opaque structure to hold blame results. pub struct Blame<'repo> { @@ -29,7 +29,6 @@ pub struct BlameIter<'blame> { } impl<'repo> Blame<'repo> { - /// Gets the number of hunks that exist in the blame structure. pub fn len(&self) -> usize { unsafe { raw::git_blame_get_hunk_count(self.raw) as usize } @@ -67,15 +66,15 @@ impl<'repo> Blame<'repo> { /// Returns an iterator over the hunks in this blame. pub fn iter(&self) -> BlameIter { - BlameIter { range: 0..self.len(), blame: self } + BlameIter { + range: 0..self.len(), + blame: self, + } } - } impl<'blame> BlameHunk<'blame> { - - unsafe fn from_raw_const(raw: *const raw::git_blame_hunk) - -> BlameHunk<'blame> { + unsafe fn from_raw_const(raw: *const raw::git_blame_hunk) -> BlameHunk<'blame> { BlameHunk { raw: raw as *mut raw::git_blame_hunk, _marker: marker::PhantomData, @@ -117,7 +116,7 @@ impl<'blame> BlameHunk<'blame> { /// /// Note that the start line is counting from 1. pub fn orig_start_line(&self) -> usize { - unsafe { (*self.raw).orig_start_line_number} + unsafe { (*self.raw).orig_start_line_number } } /// Returns path to the file where this hunk originated. @@ -145,7 +144,6 @@ impl<'blame> BlameHunk<'blame> { } } - impl Default for BlameOptions { fn default() -> Self { Self::new() @@ -153,15 +151,14 @@ impl Default for BlameOptions { } impl BlameOptions { - /// Initialize options pub fn new() -> BlameOptions { unsafe { let mut raw: raw::git_blame_options = mem::zeroed(); assert_eq!( - raw::git_blame_init_options(&mut raw, - raw::GIT_BLAME_OPTIONS_VERSION) - , 0); + raw::git_blame_init_options(&mut raw, raw::GIT_BLAME_OPTIONS_VERSION), + 0 + ); Binding::from_raw(&raw as *const _ as *mut _) } @@ -206,26 +203,34 @@ impl BlameOptions { /// Setter for the id of the newest commit to consider. pub fn newest_commit(&mut self, id: Oid) -> &mut BlameOptions { - unsafe { self.raw.newest_commit = *id.raw(); } + unsafe { + self.raw.newest_commit = *id.raw(); + } self } /// Setter for the id of the oldest commit to consider. pub fn oldest_commit(&mut self, id: Oid) -> &mut BlameOptions { - unsafe { self.raw.oldest_commit = *id.raw(); } + unsafe { + self.raw.oldest_commit = *id.raw(); + } self } - } impl<'repo> Binding for Blame<'repo> { type Raw = *mut raw::git_blame; unsafe fn from_raw(raw: *mut raw::git_blame) -> Blame<'repo> { - Blame { raw: raw, _marker: marker::PhantomData } + Blame { + raw: raw, + _marker: marker::PhantomData, + } } - fn raw(&self) -> *mut raw::git_blame { self.raw } + fn raw(&self) -> *mut raw::git_blame { + self.raw + } } impl<'repo> Drop for Blame<'repo> { @@ -238,10 +243,15 @@ impl<'blame> Binding for BlameHunk<'blame> { type Raw = *mut raw::git_blame_hunk; unsafe fn from_raw(raw: *mut raw::git_blame_hunk) -> BlameHunk<'blame> { - BlameHunk { raw: raw, _marker: marker::PhantomData } + BlameHunk { + raw: raw, + _marker: marker::PhantomData, + } } - fn raw(&self) -> *mut raw::git_blame_hunk { self.raw } + fn raw(&self) -> *mut raw::git_blame_hunk { + self.raw + } } impl Binding for BlameOptions { @@ -262,7 +272,9 @@ impl<'blame> Iterator for BlameIter<'blame> { self.range.next().and_then(|i| self.blame.get_index(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'blame> DoubleEndedIterator for BlameIter<'blame> { @@ -293,8 +305,9 @@ mod tests { let sig = repo.signature().unwrap(); let id = repo.refname_to_id("HEAD").unwrap(); let parent = repo.find_commit(id).unwrap(); - let commit = repo.commit(Some("HEAD"), &sig, &sig, "commit", - &tree, &[&parent]).unwrap(); + let commit = repo + .commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent]) + .unwrap(); let blame = repo.blame_file(Path::new("foo/bar"), None).unwrap(); @@ -312,4 +325,3 @@ mod tests { } } - diff --git a/src/blob.rs b/src/blob.rs index 5e255eb6dc..ced482bb3a 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -1,10 +1,10 @@ +use std::io; use std::marker; use std::mem; use std::slice; -use std::io; -use {raw, Oid, Object, Error}; use util::Binding; +use {raw, Error, Object, Oid}; /// A structure to represent a git [blob][1] /// @@ -36,17 +36,13 @@ impl<'repo> Blob<'repo> { /// Casts this Blob to be usable as an `Object` pub fn as_object(&self) -> &Object<'repo> { - unsafe { - &*(self as *const _ as *const Object<'repo>) - } + unsafe { &*(self as *const _ as *const Object<'repo>) } } /// Consumes Blob to be returned as an `Object` pub fn into_object(self) -> Object<'repo> { assert_eq!(mem::size_of_val(&self), mem::size_of::()); - unsafe { - mem::transmute(self) - } + unsafe { mem::transmute(self) } } } @@ -59,12 +55,14 @@ impl<'repo> Binding for Blob<'repo> { _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_blob { self.raw } + fn raw(&self) -> *mut raw::git_blob { + self.raw + } } impl<'repo> ::std::fmt::Debug for Blob<'repo> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - f.debug_struct("Blob").field("id", &self.id()).finish() + f.debug_struct("Blob").field("id", &self.id()).finish() } } @@ -92,7 +90,9 @@ impl<'repo> BlobWriter<'repo> { pub fn commit(mut self) -> Result { // After commit we already doesn't need cleanup on drop self.need_cleanup = false; - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { try_call!(raw::git_blob_create_fromstream_commit(&mut raw, self.raw)); Ok(Binding::from_raw(&raw as *const _)) @@ -110,7 +110,9 @@ impl<'repo> Binding for BlobWriter<'repo> { _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_writestream { self.raw } + fn raw(&self) -> *mut raw::git_writestream { + self.raw + } } impl<'repo> Drop for BlobWriter<'repo> { @@ -133,13 +135,15 @@ impl<'repo> io::Write for BlobWriter<'repo> { } } } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } #[cfg(test)] mod tests { - use std::io::prelude::*; use std::fs::File; + use std::io::prelude::*; use std::path::Path; use tempdir::TempDir; use Repository; @@ -156,7 +160,11 @@ mod tests { assert!(blob.is_binary()); repo.find_object(id, None).unwrap().as_blob().unwrap(); - repo.find_object(id, None).unwrap().into_blob().ok().unwrap(); + repo.find_object(id, None) + .unwrap() + .into_blob() + .ok() + .unwrap(); } #[test] diff --git a/src/branch.rs b/src/branch.rs index d285d1e233..b25f0592d5 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -3,8 +3,8 @@ use std::marker; use std::ptr; use std::str; -use {raw, Error, Reference, BranchType, References}; use util::Binding; +use {raw, BranchType, Error, Reference, References}; /// A structure to represent a git [branch][1] /// @@ -24,17 +24,25 @@ pub struct Branches<'repo> { impl<'repo> Branch<'repo> { /// Creates Branch type from a Reference - pub fn wrap(reference: Reference) -> Branch { Branch { inner: reference } } + pub fn wrap(reference: Reference) -> Branch { + Branch { inner: reference } + } /// Gain access to the reference that is this branch - pub fn get(&self) -> &Reference<'repo> { &self.inner } + pub fn get(&self) -> &Reference<'repo> { + &self.inner + } /// Take ownership of the underlying reference. - pub fn into_reference(self) -> Reference<'repo> { self.inner } + pub fn into_reference(self) -> Reference<'repo> { + self.inner + } /// Delete an existing branch reference. pub fn delete(&mut self) -> Result<(), Error> { - unsafe { try_call!(raw::git_branch_delete(self.get().raw())); } + unsafe { + try_call!(raw::git_branch_delete(self.get().raw())); + } Ok(()) } @@ -44,13 +52,16 @@ impl<'repo> Branch<'repo> { } /// Move/rename an existing local branch reference. - pub fn rename(&mut self, new_branch_name: &str, force: bool) - -> Result, Error> { + pub fn rename(&mut self, new_branch_name: &str, force: bool) -> Result, Error> { let mut ret = ptr::null_mut(); let new_branch_name = try!(CString::new(new_branch_name)); unsafe { - try_call!(raw::git_branch_move(&mut ret, self.get().raw(), - new_branch_name, force)); + try_call!(raw::git_branch_move( + &mut ret, + self.get().raw(), + new_branch_name, + force + )); Ok(Branch::wrap(Binding::from_raw(ret))) } } @@ -85,12 +96,13 @@ impl<'repo> Branch<'repo> { /// /// If `None` is specified, then the upstream branch is unset. The name /// provided is the name of the branch to set as upstream. - pub fn set_upstream(&mut self, - upstream_name: Option<&str>) -> Result<(), Error> { + pub fn set_upstream(&mut self, upstream_name: Option<&str>) -> Result<(), Error> { let upstream_name = try!(::opt_cstr(upstream_name)); unsafe { - try_call!(raw::git_branch_set_upstream(self.get().raw(), - upstream_name)); + try_call!(raw::git_branch_set_upstream( + self.get().raw(), + upstream_name + )); Ok(()) } } @@ -101,8 +113,7 @@ impl<'repo> Branches<'repo> { /// /// This function is unsafe as it is not guaranteed that `raw` is a valid /// pointer. - pub unsafe fn from_raw(raw: *mut raw::git_branch_iterator) - -> Branches<'repo> { + pub unsafe fn from_raw(raw: *mut raw::git_branch_iterator) -> Branches<'repo> { Branches { raw: raw, _marker: marker::PhantomData, diff --git a/src/buf.rs b/src/buf.rs index 9500443cde..0e8f3dbc69 100644 --- a/src/buf.rs +++ b/src/buf.rs @@ -1,7 +1,7 @@ +use std::ops::{Deref, DerefMut}; +use std::ptr; use std::slice; use std::str; -use std::ptr; -use std::ops::{Deref, DerefMut}; use raw; use util::Binding; @@ -36,25 +36,21 @@ impl Buf { /// Attempt to view this buffer as a string slice. /// /// Returns `None` if the buffer is not valid utf-8. - pub fn as_str(&self) -> Option<&str> { str::from_utf8(&**self).ok() } + pub fn as_str(&self) -> Option<&str> { + str::from_utf8(&**self).ok() + } } impl Deref for Buf { type Target = [u8]; fn deref(&self) -> &[u8] { - unsafe { - slice::from_raw_parts(self.raw.ptr as *const u8, - self.raw.size as usize) - } + unsafe { slice::from_raw_parts(self.raw.ptr as *const u8, self.raw.size as usize) } } } impl DerefMut for Buf { fn deref_mut(&mut self) -> &mut [u8] { - unsafe { - slice::from_raw_parts_mut(self.raw.ptr as *mut u8, - self.raw.size as usize) - } + unsafe { slice::from_raw_parts_mut(self.raw.ptr as *mut u8, self.raw.size as usize) } } } @@ -63,7 +59,9 @@ impl Binding for Buf { unsafe fn from_raw(raw: *mut raw::git_buf) -> Buf { Buf { raw: *raw } } - fn raw(&self) -> *mut raw::git_buf { &self.raw as *const _ as *mut _ } + fn raw(&self) -> *mut raw::git_buf { + &self.raw as *const _ as *mut _ + } } impl Drop for Buf { diff --git a/src/build.rs b/src/build.rs index ad23bc7db7..bd2b0c87ed 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,14 +1,14 @@ //! Builder-pattern objects for configuration various git operations. +use libc::{c_char, c_int, c_uint, c_void, size_t}; use std::ffi::{CStr, CString}; use std::mem; use std::path::Path; use std::ptr; -use libc::{c_char, size_t, c_void, c_uint, c_int}; -use {raw, panic, Error, Repository, FetchOptions, IntoCString}; -use {CheckoutNotificationType, DiffFile, Remote}; use util::{self, Binding}; +use {panic, raw, Error, FetchOptions, IntoCString, Repository}; +use {CheckoutNotificationType, DiffFile, Remote}; /// A builder struct which is used to build configuration for cloning a new git /// repository. @@ -26,8 +26,8 @@ pub struct RepoBuilder<'cb> { /// Type of callback passed to `RepoBuilder::remote_create`. /// /// The second and third arguments are the remote's name and the remote's url. -pub type RemoteCreate<'cb> = dyn for<'a> FnMut(&'a Repository, &str, &str) - -> Result, Error> + 'cb; +pub type RemoteCreate<'cb> = + dyn for<'a> FnMut(&'a Repository, &str, &str) -> Result, Error> + 'cb; /// A builder struct for configuring checkouts of a repository. pub struct CheckoutBuilder<'cb> { @@ -59,10 +59,14 @@ pub type Progress<'a> = dyn FnMut(Option<&Path>, usize, usize) + 'a; /// /// The callback must return a bool specifying whether the checkout should /// continue. -pub type Notify<'a> = dyn FnMut(CheckoutNotificationType, Option<&Path>, - Option, Option, - Option) -> bool + 'a; - +pub type Notify<'a> = dyn FnMut( + CheckoutNotificationType, + Option<&Path>, + Option, + Option, + Option, + ) -> bool + + 'a; impl<'cb> Default for RepoBuilder<'cb> { fn default() -> Self { @@ -159,8 +163,7 @@ impl<'cb> RepoBuilder<'cb> { /// Configure the checkout which will be performed by consuming a checkout /// builder. - pub fn with_checkout(&mut self, checkout: CheckoutBuilder<'cb>) - -> &mut RepoBuilder<'cb> { + pub fn with_checkout(&mut self, checkout: CheckoutBuilder<'cb>) -> &mut RepoBuilder<'cb> { self.checkout = Some(checkout); self } @@ -169,8 +172,7 @@ impl<'cb> RepoBuilder<'cb> { /// /// The callbacks are used for reporting fetch progress, and for acquiring /// credentials in the event they are needed. - pub fn fetch_options(&mut self, fetch_opts: FetchOptions<'cb>) - -> &mut RepoBuilder<'cb> { + pub fn fetch_options(&mut self, fetch_opts: FetchOptions<'cb>) -> &mut RepoBuilder<'cb> { self.fetch_opts = Some(fetch_opts); self } @@ -178,8 +180,8 @@ impl<'cb> RepoBuilder<'cb> { /// Configures a callback used to create the git remote, prior to its being /// used to perform the clone operation. pub fn remote_create(&mut self, f: F) -> &mut RepoBuilder<'cb> - where F: for<'a> FnMut(&'a Repository, &str, &str) - -> Result, Error> + 'cb, + where + F: for<'a> FnMut(&'a Repository, &str, &str) -> Result, Error> + 'cb, { self.remote_create = Some(Box::new(f)); self @@ -192,13 +194,17 @@ impl<'cb> RepoBuilder<'cb> { pub fn clone(&mut self, url: &str, into: &Path) -> Result { let mut opts: raw::git_clone_options = unsafe { mem::zeroed() }; unsafe { - try_call!(raw::git_clone_init_options(&mut opts, - raw::GIT_CLONE_OPTIONS_VERSION)); + try_call!(raw::git_clone_init_options( + &mut opts, + raw::GIT_CLONE_OPTIONS_VERSION + )); } opts.bare = self.bare as c_int; - opts.checkout_branch = self.branch.as_ref().map(|s| { - s.as_ptr() - }).unwrap_or(ptr::null()); + opts.checkout_branch = self + .branch + .as_ref() + .map(|s| s.as_ptr()) + .unwrap_or(ptr::null()); if let Some(ref local) = self.clone_local { opts.local = *local as raw::git_clone_local_t; @@ -235,11 +241,13 @@ impl<'cb> RepoBuilder<'cb> { } } -extern fn remote_create_cb(out: *mut *mut raw::git_remote, - repo: *mut raw::git_repository, - name: *const c_char, - url: *const c_char, - payload: *mut c_void) -> c_int { +extern "C" fn remote_create_cb( + out: *mut *mut raw::git_remote, + repo: *mut raw::git_repository, + name: *const c_char, + url: *const c_char, + payload: *mut c_void, +) -> c_int { unsafe { let repo = Repository::from_raw(repo); let code = panic::wrap(|| { @@ -313,8 +321,7 @@ impl<'cb> CheckoutBuilder<'cb> { self } - fn flag(&mut self, bit: raw::git_checkout_strategy_t, - on: bool) -> &mut CheckoutBuilder<'cb> { + fn flag(&mut self, bit: raw::git_checkout_strategy_t, on: bool) -> &mut CheckoutBuilder<'cb> { if on { self.checkout_opts |= bit as u32; } else { @@ -341,8 +348,7 @@ impl<'cb> CheckoutBuilder<'cb> { /// Remove untracked files from the working dir. /// /// Defaults to false. - pub fn remove_untracked(&mut self, remove: bool) - -> &mut CheckoutBuilder<'cb> { + pub fn remove_untracked(&mut self, remove: bool) -> &mut CheckoutBuilder<'cb> { self.flag(raw::GIT_CHECKOUT_REMOVE_UNTRACKED, remove) } @@ -404,16 +410,14 @@ impl<'cb> CheckoutBuilder<'cb> { /// Indicate whether ignored files should be overwritten during the checkout. /// /// Defaults to true. - pub fn overwrite_ignored(&mut self, overwrite: bool) - -> &mut CheckoutBuilder<'cb> { + pub fn overwrite_ignored(&mut self, overwrite: bool) -> &mut CheckoutBuilder<'cb> { self.flag(raw::GIT_CHECKOUT_DONT_OVERWRITE_IGNORED, !overwrite) } /// Indicate whether a normal merge file should be written for conflicts. /// /// Defaults to false. - pub fn conflict_style_merge(&mut self, on: bool) - -> &mut CheckoutBuilder<'cb> { + pub fn conflict_style_merge(&mut self, on: bool) -> &mut CheckoutBuilder<'cb> { self.flag(raw::GIT_CHECKOUT_CONFLICT_STYLE_MERGE, on) } @@ -421,8 +425,10 @@ impl<'cb> CheckoutBuilder<'cb> { /// callback. /// /// Defaults to none. - pub fn notify_on(&mut self, notification_types: CheckoutNotificationType) - -> &mut CheckoutBuilder<'cb> { + pub fn notify_on( + &mut self, + notification_types: CheckoutNotificationType, + ) -> &mut CheckoutBuilder<'cb> { self.notify_flags = notification_types; self } @@ -431,14 +437,12 @@ impl<'cb> CheckoutBuilder<'cb> { /// for conflicts. /// /// Defaults to false. - pub fn conflict_style_diff3(&mut self, on: bool) - -> &mut CheckoutBuilder<'cb> { + pub fn conflict_style_diff3(&mut self, on: bool) -> &mut CheckoutBuilder<'cb> { self.flag(raw::GIT_CHECKOUT_CONFLICT_STYLE_DIFF3, on) } /// Indicate whether to apply filters like CRLF conversion. - pub fn disable_filters(&mut self, disable: bool) - -> &mut CheckoutBuilder<'cb> { + pub fn disable_filters(&mut self, disable: bool) -> &mut CheckoutBuilder<'cb> { self.disable_filters = disable; self } @@ -463,8 +467,7 @@ impl<'cb> CheckoutBuilder<'cb> { /// /// If no paths are specified, then all files are checked out. Otherwise /// only these specified paths are checked out. - pub fn path(&mut self, path: T) - -> &mut CheckoutBuilder<'cb> { + pub fn path(&mut self, path: T) -> &mut CheckoutBuilder<'cb> { let path = path.into_c_string().unwrap(); self.path_ptrs.push(path.as_ptr()); self.paths.push(path); @@ -497,7 +500,9 @@ impl<'cb> CheckoutBuilder<'cb> { /// Set a callback to receive notifications of checkout progress. pub fn progress(&mut self, cb: F) -> &mut CheckoutBuilder<'cb> - where F: FnMut(Option<&Path>, usize, usize) + 'cb { + where + F: FnMut(Option<&Path>, usize, usize) + 'cb, + { self.progress = Some(Box::new(cb) as Box>); self } @@ -507,8 +512,15 @@ impl<'cb> CheckoutBuilder<'cb> { /// Callbacks are invoked prior to modifying any files on disk. /// Returning `false` from the callback will cancel the checkout. pub fn notify(&mut self, cb: F) -> &mut CheckoutBuilder<'cb> - where F: FnMut(CheckoutNotificationType, Option<&Path>, Option, - Option, Option) -> bool + 'cb + where + F: FnMut( + CheckoutNotificationType, + Option<&Path>, + Option, + Option, + Option, + ) -> bool + + 'cb, { self.notify = Some(Box::new(cb) as Box>); self @@ -556,10 +568,12 @@ impl<'cb> CheckoutBuilder<'cb> { } } -extern fn progress_cb(path: *const c_char, - completed: size_t, - total: size_t, - data: *mut c_void) { +extern "C" fn progress_cb( + path: *const c_char, + completed: size_t, + total: size_t, + data: *mut c_void, +) { panic::wrap(|| unsafe { let payload = &mut *(data as *mut CheckoutBuilder); let callback = match payload.progress { @@ -575,12 +589,14 @@ extern fn progress_cb(path: *const c_char, }); } -extern fn notify_cb(why: raw::git_checkout_notify_t, - path: *const c_char, - baseline: *const raw::git_diff_file, - target: *const raw::git_diff_file, - workdir: *const raw::git_diff_file, - data: *mut c_void) -> c_int { +extern "C" fn notify_cb( + why: raw::git_checkout_notify_t, + path: *const c_char, + baseline: *const raw::git_diff_file, + target: *const raw::git_diff_file, + workdir: *const raw::git_diff_file, + data: *mut c_void, +) -> c_int { // pack callback etc panic::wrap(|| unsafe { let payload = &mut *(data as *mut CheckoutBuilder); @@ -614,16 +630,21 @@ extern fn notify_cb(why: raw::git_checkout_notify_t, let why = CheckoutNotificationType::from_bits_truncate(why as u32); let keep_going = callback(why, path, baseline, target, workdir); - if keep_going {0} else {1} - }).unwrap_or(2) + if keep_going { + 0 + } else { + 1 + } + }) + .unwrap_or(2) } #[cfg(test)] mod tests { + use super::{CheckoutBuilder, RepoBuilder}; use std::fs; use std::path::Path; use tempdir::TempDir; - use super::{CheckoutBuilder, RepoBuilder}; use {CheckoutNotificationType, Repository}; #[test] @@ -639,15 +660,16 @@ mod tests { let url = if cfg!(unix) { format!("file://{}/bare", td.path().display()) } else { - format!("file:///{}/bare", td.path().display().to_string() - .replace("\\", "/")) + format!( + "file:///{}/bare", + td.path().display().to_string().replace("\\", "/") + ) }; let dst = td.path().join("foo"); RepoBuilder::new().clone(&url, &dst).unwrap(); fs::remove_dir_all(&dst).unwrap(); - assert!(RepoBuilder::new().branch("foo") - .clone(&url, &dst).is_err()); + assert!(RepoBuilder::new().branch("foo").clone(&url, &dst).is_err()); } /// Issue regression test #365 @@ -672,8 +694,8 @@ mod tests { let tree = repo.find_tree(id).unwrap(); let sig = repo.signature().unwrap(); - repo.commit(Some("HEAD"), &sig, &sig, "initial", - &tree, &[]).unwrap(); + repo.commit(Some("HEAD"), &sig, &sig, "initial", &tree, &[]) + .unwrap(); } let repo = Repository::open_bare(&td.path().join(".git")).unwrap(); diff --git a/src/call.rs b/src/call.rs index 2f0f3ff660..565f08d96f 100644 --- a/src/call.rs +++ b/src/call.rs @@ -33,7 +33,9 @@ pub trait Convert { fn convert(&self) -> T; } -pub fn convert>(u: &U) -> T { u.convert() } +pub fn convert>(u: &U) -> T { + u.convert() +} pub fn try(ret: libc::c_int) -> Result { match ret { @@ -54,29 +56,41 @@ mod impls { use libc; - use {raw, ConfigLevel, ResetType, ObjectType, BranchType, Direction}; - use {DiffFormat, FileFavor, SubmoduleIgnore, AutotagOption, FetchPrune}; use call::Convert; + use {raw, BranchType, ConfigLevel, Direction, ObjectType, ResetType}; + use {AutotagOption, DiffFormat, FetchPrune, FileFavor, SubmoduleIgnore}; impl Convert for T { - fn convert(&self) -> T { *self } + fn convert(&self) -> T { + *self + } } impl Convert for bool { - fn convert(&self) -> libc::c_int { *self as libc::c_int } + fn convert(&self) -> libc::c_int { + *self as libc::c_int + } } impl<'a, T> Convert<*const T> for &'a T { - fn convert(&self) -> *const T { *self as *const T } + fn convert(&self) -> *const T { + *self as *const T + } } impl<'a, T> Convert<*mut T> for &'a mut T { - fn convert(&self) -> *mut T { &**self as *const T as *mut T } + fn convert(&self) -> *mut T { + &**self as *const T as *mut T + } } impl Convert<*const T> for *mut T { - fn convert(&self) -> *const T { *self as *const T } + fn convert(&self) -> *const T { + *self as *const T + } } impl Convert<*const libc::c_char> for CString { - fn convert(&self) -> *const libc::c_char { self.as_ptr() } + fn convert(&self) -> *const libc::c_char { + self.as_ptr() + } } impl> Convert<*const T> for Option { @@ -87,7 +101,9 @@ mod impls { impl> Convert<*mut T> for Option { fn convert(&self) -> *mut T { - self.as_ref().map(|s| s.convert()).unwrap_or(ptr::null_mut()) + self.as_ref() + .map(|s| s.convert()) + .unwrap_or(ptr::null_mut()) } } @@ -183,8 +199,7 @@ mod impls { impl Convert for SubmoduleIgnore { fn convert(&self) -> raw::git_submodule_ignore_t { match *self { - SubmoduleIgnore::Unspecified => - raw::GIT_SUBMODULE_IGNORE_UNSPECIFIED, + SubmoduleIgnore::Unspecified => raw::GIT_SUBMODULE_IGNORE_UNSPECIFIED, SubmoduleIgnore::None => raw::GIT_SUBMODULE_IGNORE_NONE, SubmoduleIgnore::Untracked => raw::GIT_SUBMODULE_IGNORE_UNTRACKED, SubmoduleIgnore::Dirty => raw::GIT_SUBMODULE_IGNORE_DIRTY, @@ -196,8 +211,7 @@ mod impls { impl Convert for AutotagOption { fn convert(&self) -> raw::git_remote_autotag_option_t { match *self { - AutotagOption::Unspecified => - raw::GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, + AutotagOption::Unspecified => raw::GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, AutotagOption::None => raw::GIT_REMOTE_DOWNLOAD_TAGS_NONE, AutotagOption::Auto => raw::GIT_REMOTE_DOWNLOAD_TAGS_AUTO, AutotagOption::All => raw::GIT_REMOTE_DOWNLOAD_TAGS_ALL, diff --git a/src/cert.rs b/src/cert.rs index 70ab9498f8..4ca84e58aa 100644 --- a/src/cert.rs +++ b/src/cert.rs @@ -81,17 +81,19 @@ impl<'a> CertHostkey<'a> { impl<'a> CertX509<'a> { /// Return the X.509 certificate data as a byte slice pub fn data(&self) -> &[u8] { - unsafe { - slice::from_raw_parts((*self.raw).data as *const u8, - (*self.raw).len as usize) - } + unsafe { slice::from_raw_parts((*self.raw).data as *const u8, (*self.raw).len as usize) } } } impl<'a> Binding for Cert<'a> { type Raw = *mut raw::git_cert; unsafe fn from_raw(raw: *mut raw::git_cert) -> Cert<'a> { - Cert { raw: raw, _marker: marker::PhantomData } + Cert { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_cert { + self.raw } - fn raw(&self) -> *mut raw::git_cert { self.raw } } diff --git a/src/commit.rs b/src/commit.rs index 4cf52bd6c6..d478178790 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -1,12 +1,12 @@ +use libc; use std::marker; use std::mem; use std::ops::Range; use std::ptr; use std::str; -use libc; -use {raw, signature, Oid, Error, Signature, Tree, Time, Object}; use util::Binding; +use {raw, signature, Error, Object, Oid, Signature, Time, Tree}; /// A structure to represent a git [commit][1] /// @@ -55,7 +55,9 @@ impl<'repo> Commit<'repo> { } /// Get access to the underlying raw pointer. - pub fn raw(&self) -> *mut raw::git_commit { self.raw } + pub fn raw(&self) -> *mut raw::git_commit { + self.raw + } /// Get the full message of a commit. /// @@ -72,9 +74,7 @@ impl<'repo> Commit<'repo> { /// The returned message will be slightly prettified by removing any /// potential leading newlines. pub fn message_bytes(&self) -> &[u8] { - unsafe { - ::opt_bytes(self, raw::git_commit_message(&*self.raw)).unwrap() - } + unsafe { ::opt_bytes(self, raw::git_commit_message(&*self.raw)).unwrap() } } /// Get the encoding for the message of a commit, as a string representing a @@ -82,9 +82,7 @@ impl<'repo> Commit<'repo> { /// /// `None` will be returned if the encoding is not known pub fn message_encoding(&self) -> Option<&str> { - let bytes = unsafe { - ::opt_bytes(self, raw::git_commit_message_encoding(&*self.raw)) - }; + let bytes = unsafe { ::opt_bytes(self, raw::git_commit_message_encoding(&*self.raw)) }; bytes.and_then(|b| str::from_utf8(b).ok()) } @@ -97,9 +95,7 @@ impl<'repo> Commit<'repo> { /// Get the full raw message of a commit. pub fn message_raw_bytes(&self) -> &[u8] { - unsafe { - ::opt_bytes(self, raw::git_commit_message_raw(&*self.raw)).unwrap() - } + unsafe { ::opt_bytes(self, raw::git_commit_message_raw(&*self.raw)).unwrap() } } /// Get the full raw text of the commit header. @@ -111,9 +107,7 @@ impl<'repo> Commit<'repo> { /// Get the full raw text of the commit header. pub fn raw_header_bytes(&self) -> &[u8] { - unsafe { - ::opt_bytes(self, raw::git_commit_raw_header(&*self.raw)).unwrap() - } + unsafe { ::opt_bytes(self, raw::git_commit_raw_header(&*self.raw)).unwrap() } } /// Get the short "summary" of the git commit message. @@ -144,19 +138,27 @@ impl<'repo> Commit<'repo> { /// committer's preferred time zone. pub fn time(&self) -> Time { unsafe { - Time::new(raw::git_commit_time(&*self.raw) as i64, - raw::git_commit_time_offset(&*self.raw) as i32) + Time::new( + raw::git_commit_time(&*self.raw) as i64, + raw::git_commit_time_offset(&*self.raw) as i32, + ) } } /// Creates a new iterator over the parents of this commit. pub fn parents<'a>(&'a self) -> Parents<'a, 'repo> { - Parents { range: 0..self.parent_count(), commit: self } + Parents { + range: 0..self.parent_count(), + commit: self, + } } /// Creates a new iterator over the parents of this commit. pub fn parent_ids(&self) -> ParentIds { - ParentIds { range: 0..self.parent_count(), commit: self } + ParentIds { + range: 0..self.parent_count(), + commit: self, + } } /// Get the author of this commit. @@ -184,26 +186,32 @@ impl<'repo> Commit<'repo> { /// For information about `update_ref`, see [`Repository::commit`]. /// /// [`Repository::commit`]: struct.Repository.html#method.commit - pub fn amend(&self, - update_ref: Option<&str>, - author: Option<&Signature>, - committer: Option<&Signature>, - message_encoding: Option<&str>, - message: Option<&str>, - tree: Option<&Tree<'repo>>) -> Result { - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + pub fn amend( + &self, + update_ref: Option<&str>, + author: Option<&Signature>, + committer: Option<&Signature>, + message_encoding: Option<&str>, + message: Option<&str>, + tree: Option<&Tree<'repo>>, + ) -> Result { + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; let update_ref = try!(::opt_cstr(update_ref)); let encoding = try!(::opt_cstr(message_encoding)); let message = try!(::opt_cstr(message)); unsafe { - try_call!(raw::git_commit_amend(&mut raw, - self.raw(), - update_ref, - author.map(|s| s.raw()), - committer.map(|s| s.raw()), - encoding, - message, - tree.map(|t| t.raw()))); + try_call!(raw::git_commit_amend( + &mut raw, + self.raw(), + update_ref, + author.map(|s| s.raw()), + committer.map(|s| s.raw()), + encoding, + message, + tree.map(|t| t.raw()) + )); Ok(Binding::from_raw(&raw as *const _)) } } @@ -221,8 +229,11 @@ impl<'repo> Commit<'repo> { pub fn parent(&self, i: usize) -> Result, Error> { unsafe { let mut raw = ptr::null_mut(); - try_call!(raw::git_commit_parent(&mut raw, &*self.raw, - i as libc::c_uint)); + try_call!(raw::git_commit_parent( + &mut raw, + &*self.raw, + i as libc::c_uint + )); Ok(Binding::from_raw(raw)) } } @@ -246,17 +257,13 @@ impl<'repo> Commit<'repo> { /// Casts this Commit to be usable as an `Object` pub fn as_object(&self) -> &Object<'repo> { - unsafe { - &*(self as *const _ as *const Object<'repo>) - } + unsafe { &*(self as *const _ as *const Object<'repo>) } } /// Consumes Commit to be returned as an `Object` pub fn into_object(self) -> Object<'repo> { assert_eq!(mem::size_of_val(&self), mem::size_of::()); - unsafe { - mem::transmute(self) - } + unsafe { mem::transmute(self) } } } @@ -268,17 +275,19 @@ impl<'repo> Binding for Commit<'repo> { _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_commit { self.raw } + fn raw(&self) -> *mut raw::git_commit { + self.raw + } } impl<'repo> ::std::fmt::Debug for Commit<'repo> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - let mut ds = f.debug_struct("Commit"); - ds.field("id", &self.id()); - if let Some(summary) = self.summary() { - ds.field("summary", &summary); - } - ds.finish() + let mut ds = f.debug_struct("Commit"); + ds.field("id", &self.id()); + if let Some(summary) = self.summary() { + ds.field("summary", &summary); + } + ds.finish() } } @@ -288,13 +297,17 @@ impl<'repo, 'commit> Iterator for Parents<'commit, 'repo> { fn next(&mut self) -> Option> { self.range.next().and_then(|i| self.commit.parent(i).ok()) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } /// Aborts iteration when a commit cannot be found impl<'repo, 'commit> DoubleEndedIterator for Parents<'commit, 'repo> { fn next_back(&mut self) -> Option> { - self.range.next_back().and_then(|i| self.commit.parent(i).ok()) + self.range + .next_back() + .and_then(|i| self.commit.parent(i).ok()) } } @@ -304,15 +317,21 @@ impl<'repo, 'commit> ExactSizeIterator for Parents<'commit, 'repo> {} impl<'commit> Iterator for ParentIds<'commit> { type Item = Oid; fn next(&mut self) -> Option { - self.range.next().and_then(|i| self.commit.parent_id(i).ok()) + self.range + .next() + .and_then(|i| self.commit.parent_id(i).ok()) + } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } } /// Aborts iteration when a commit cannot be found impl<'commit> DoubleEndedIterator for ParentIds<'commit> { fn next_back(&mut self) -> Option { - self.range.next_back().and_then(|i| self.commit.parent_id(i).ok()) + self.range + .next_back() + .and_then(|i| self.commit.parent_id(i).ok()) } } @@ -355,18 +374,23 @@ mod tests { let sig = repo.signature().unwrap(); let tree = repo.find_tree(commit.tree_id()).unwrap(); - let id = repo.commit(Some("HEAD"), &sig, &sig, "bar", &tree, - &[&commit]).unwrap(); + let id = repo + .commit(Some("HEAD"), &sig, &sig, "bar", &tree, &[&commit]) + .unwrap(); let head = repo.find_commit(id).unwrap(); - let new_head = head.amend(Some("HEAD"), None, None, None, - Some("new message"), None).unwrap(); + let new_head = head + .amend(Some("HEAD"), None, None, None, Some("new message"), None) + .unwrap(); let new_head = repo.find_commit(new_head).unwrap(); assert_eq!(new_head.message(), Some("new message")); new_head.into_object(); repo.find_object(target, None).unwrap().as_commit().unwrap(); - repo.find_object(target, None).unwrap().into_commit().ok().unwrap(); + repo.find_object(target, None) + .unwrap() + .into_commit() + .ok() + .unwrap(); } } - diff --git a/src/config.rs b/src/config.rs index b01729aebd..b5fc72d2e6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,12 +1,12 @@ +use libc; use std::ffi::CString; use std::marker; use std::path::{Path, PathBuf}; use std::ptr; use std::str; -use libc; -use {raw, Error, ConfigLevel, Buf, IntoCString}; use util::{self, Binding}; +use {raw, Buf, ConfigLevel, Error, IntoCString}; /// A structure representing a git configuration key/value store pub struct Config { @@ -81,7 +81,9 @@ impl Config { pub fn find_global() -> Result { ::init(); let buf = Buf::new(); - unsafe { try_call!(raw::git_config_find_global(buf.raw())); } + unsafe { + try_call!(raw::git_config_find_global(buf.raw())); + } Ok(util::bytes2path(&buf).to_path_buf()) } @@ -91,7 +93,9 @@ impl Config { pub fn find_system() -> Result { ::init(); let buf = Buf::new(); - unsafe { try_call!(raw::git_config_find_system(buf.raw())); } + unsafe { + try_call!(raw::git_config_find_system(buf.raw())); + } Ok(util::bytes2path(&buf).to_path_buf()) } @@ -102,7 +106,9 @@ impl Config { pub fn find_xdg() -> Result { ::init(); let buf = Buf::new(); - unsafe { try_call!(raw::git_config_find_xdg(buf.raw())); } + unsafe { + try_call!(raw::git_config_find_xdg(buf.raw())); + } Ok(util::bytes2path(&buf).to_path_buf()) } @@ -115,12 +121,16 @@ impl Config { /// Further queries on this config object will access each of the config /// file instances in order (instances with a higher priority level will be /// accessed first). - pub fn add_file(&mut self, path: &Path, level: ConfigLevel, - force: bool) -> Result<(), Error> { + pub fn add_file(&mut self, path: &Path, level: ConfigLevel, force: bool) -> Result<(), Error> { let path = try!(path.into_c_string()); unsafe { - try_call!(raw::git_config_add_file_ondisk(self.raw, path, level, - ptr::null(), force)); + try_call!(raw::git_config_add_file_ondisk( + self.raw, + path, + level, + ptr::null(), + force + )); Ok(()) } } @@ -156,7 +166,6 @@ impl Config { let name = try!(CString::new(name)); unsafe { try_call!(raw::git_config_get_bool(&mut out, &*self.raw, name)); - } Ok(!(out == 0)) } @@ -171,7 +180,6 @@ impl Config { let name = try!(CString::new(name)); unsafe { try_call!(raw::git_config_get_int32(&mut out, &*self.raw, name)); - } Ok(out) } @@ -195,9 +203,8 @@ impl Config { /// This is the same as `get_bytes` except that it may return `Err` if /// the bytes are not valid utf-8. pub fn get_str(&self, name: &str) -> Result<&str, Error> { - str::from_utf8(try!(self.get_bytes(name))).map_err(|_| { - Error::from_str("configuration value is not valid utf8") - }) + str::from_utf8(try!(self.get_bytes(name))) + .map_err(|_| Error::from_str("configuration value is not valid utf8")) } /// Get the value of a string config variable as a byte slice. @@ -221,9 +228,9 @@ impl Config { unsafe { try_call!(raw::git_config_get_string_buf(ret.raw(), self.raw, name)); } - str::from_utf8(&ret).map(|s| s.to_string()).map_err(|_| { - Error::from_str("configuration value is not valid utf8") - }) + str::from_utf8(&ret) + .map(|s| s.to_string()) + .map_err(|_| Error::from_str("configuration value is not valid utf8")) } /// Get the value of a path config variable as an owned . @@ -270,9 +277,7 @@ impl Config { match glob { Some(s) => { let s = try!(CString::new(s)); - try_call!(raw::git_config_iterator_glob_new(&mut ret, - &*self.raw, - s)); + try_call!(raw::git_config_iterator_glob_new(&mut ret, &*self.raw, s)); } None => { try_call!(raw::git_config_iterator_new(&mut ret, &*self.raw)); @@ -417,7 +422,9 @@ impl Binding for Config { unsafe fn from_raw(raw: *mut raw::git_config) -> Config { Config { raw: raw } } - fn raw(&self) -> *mut raw::git_config { self.raw } + fn raw(&self) -> *mut raw::git_config { + self.raw + } } impl Drop for Config { @@ -430,7 +437,9 @@ impl<'cfg> ConfigEntry<'cfg> { /// Gets the name of this entry. /// /// May return `None` if the name is not valid utf-8 - pub fn name(&self) -> Option<&str> { str::from_utf8(self.name_bytes()).ok() } + pub fn name(&self) -> Option<&str> { + str::from_utf8(self.name_bytes()).ok() + } /// Gets the name of this entry as a byte slice. pub fn name_bytes(&self) -> &[u8] { @@ -440,7 +449,9 @@ impl<'cfg> ConfigEntry<'cfg> { /// Gets the value of this entry. /// /// May return `None` if the value is not valid utf-8 - pub fn value(&self) -> Option<&str> { str::from_utf8(self.value_bytes()).ok() } + pub fn value(&self) -> Option<&str> { + str::from_utf8(self.value_bytes()).ok() + } /// Gets the value of this entry as a byte slice. pub fn value_bytes(&self) -> &[u8] { @@ -452,7 +463,7 @@ impl<'cfg> ConfigEntry<'cfg> { unsafe { ConfigLevel::from_raw((*self.raw).level) } } - /// Depth of includes where this variable was found + /// Depth of includes where this variable was found pub fn include_depth(&self) -> u32 { unsafe { (*self.raw).include_depth as u32 } } @@ -461,28 +472,30 @@ impl<'cfg> ConfigEntry<'cfg> { impl<'cfg> Binding for ConfigEntry<'cfg> { type Raw = *mut raw::git_config_entry; - unsafe fn from_raw(raw: *mut raw::git_config_entry) - -> ConfigEntry<'cfg> { + unsafe fn from_raw(raw: *mut raw::git_config_entry) -> ConfigEntry<'cfg> { ConfigEntry { raw: raw, _marker: marker::PhantomData, owned: true, } } - fn raw(&self) -> *mut raw::git_config_entry { self.raw } + fn raw(&self) -> *mut raw::git_config_entry { + self.raw + } } impl<'cfg> Binding for ConfigEntries<'cfg> { type Raw = *mut raw::git_config_iterator; - unsafe fn from_raw(raw: *mut raw::git_config_iterator) - -> ConfigEntries<'cfg> { + unsafe fn from_raw(raw: *mut raw::git_config_iterator) -> ConfigEntries<'cfg> { ConfigEntries { raw: raw, _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_config_iterator { self.raw } + fn raw(&self) -> *mut raw::git_config_iterator { + self.raw + } } // entries are only valid until the iterator is freed, so this impl is for @@ -573,7 +586,8 @@ mod tests { cfg.set_multivar("foo.bar", "^$", "baz").unwrap(); cfg.set_multivar("foo.bar", "^$", "qux").unwrap(); - let mut values: Vec = cfg.entries(None) + let mut values: Vec = cfg + .entries(None) .unwrap() .into_iter() .map(|entry| entry.unwrap().value().unwrap().into()) @@ -612,7 +626,7 @@ mod tests { assert_eq!(Config::parse_i32("1k").unwrap(), 1024); assert_eq!(Config::parse_i32("4k").unwrap(), 4096); assert_eq!(Config::parse_i32("1M").unwrap(), 1048576); - assert_eq!(Config::parse_i32("1G").unwrap(), 1024*1024*1024); + assert_eq!(Config::parse_i32("1G").unwrap(), 1024 * 1024 * 1024); assert_eq!(Config::parse_i64("0").unwrap(), 0); assert_eq!(Config::parse_i64("1").unwrap(), 1); @@ -622,7 +636,7 @@ mod tests { assert_eq!(Config::parse_i64("1k").unwrap(), 1024); assert_eq!(Config::parse_i64("4k").unwrap(), 4096); assert_eq!(Config::parse_i64("1M").unwrap(), 1048576); - assert_eq!(Config::parse_i64("1G").unwrap(), 1024*1024*1024); - assert_eq!(Config::parse_i64("100G").unwrap(), 100*1024*1024*1024); + assert_eq!(Config::parse_i64("1G").unwrap(), 1024 * 1024 * 1024); + assert_eq!(Config::parse_i64("100G").unwrap(), 100 * 1024 * 1024 * 1024); } } diff --git a/src/cred.rs b/src/cred.rs index 12ddcbdbce..580b4c0dcc 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -6,8 +6,8 @@ use std::process::{Command, Stdio}; use std::ptr; use url; -use {raw, Error, Config, IntoCString}; use util::Binding; +use {raw, Config, Error, IntoCString}; /// A structure to represent git credentials in libgit2. pub struct Cred { @@ -51,10 +51,12 @@ impl Cred { } /// Create a new passphrase-protected ssh key credential object. - pub fn ssh_key(username: &str, - publickey: Option<&Path>, - privatekey: &Path, - passphrase: Option<&str>) -> Result { + pub fn ssh_key( + username: &str, + publickey: Option<&Path>, + privatekey: &Path, + passphrase: Option<&str>, + ) -> Result { ::init(); let username = try!(CString::new(username)); let publickey = try!(::opt_cstr(publickey)); @@ -62,17 +64,20 @@ impl Cred { let passphrase = try!(::opt_cstr(passphrase)); let mut out = ptr::null_mut(); unsafe { - try_call!(raw::git_cred_ssh_key_new(&mut out, username, publickey, - privatekey, passphrase)); + try_call!(raw::git_cred_ssh_key_new( + &mut out, username, publickey, privatekey, passphrase + )); Ok(Binding::from_raw(out)) } } /// Create a new ssh key credential object reading the keys from memory. - pub fn ssh_key_from_memory(username: &str, - publickey: Option<&str>, - privatekey: &str, - passphrase: Option<&str>) -> Result { + pub fn ssh_key_from_memory( + username: &str, + publickey: Option<&str>, + privatekey: &str, + passphrase: Option<&str>, + ) -> Result { ::init(); let username = try!(CString::new(username)); let publickey = try!(::opt_cstr(publickey)); @@ -80,22 +85,23 @@ impl Cred { let passphrase = try!(::opt_cstr(passphrase)); let mut out = ptr::null_mut(); unsafe { - try_call!(raw::git_cred_ssh_key_memory_new(&mut out, username, publickey, - privatekey, passphrase)); + try_call!(raw::git_cred_ssh_key_memory_new( + &mut out, username, publickey, privatekey, passphrase + )); Ok(Binding::from_raw(out)) } } /// Create a new plain-text username and password credential object. - pub fn userpass_plaintext(username: &str, - password: &str) -> Result { + pub fn userpass_plaintext(username: &str, password: &str) -> Result { ::init(); let username = try!(CString::new(username)); let password = try!(CString::new(password)); let mut out = ptr::null_mut(); unsafe { - try_call!(raw::git_cred_userpass_plaintext_new(&mut out, username, - password)); + try_call!(raw::git_cred_userpass_plaintext_new( + &mut out, username, password + )); Ok(Binding::from_raw(out)) } } @@ -110,17 +116,21 @@ impl Cred { /// successful. /// /// [1]: https://www.kernel.org/pub/software/scm/git/docs/gitcredentials.html - pub fn credential_helper(config: &Config, - url: &str, - username: Option<&str>) - -> Result { - match CredentialHelper::new(url).config(config).username(username) - .execute() { - Some((username, password)) => { - Cred::userpass_plaintext(&username, &password) - } - None => Err(Error::from_str("failed to acquire username/password \ - from local configuration")) + pub fn credential_helper( + config: &Config, + url: &str, + username: Option<&str>, + ) -> Result { + match CredentialHelper::new(url) + .config(config) + .username(username) + .execute() + { + Some((username, password)) => Cred::userpass_plaintext(&username, &password), + None => Err(Error::from_str( + "failed to acquire username/password \ + from local configuration", + )), } } @@ -160,7 +170,9 @@ impl Binding for Cred { unsafe fn from_raw(raw: *mut raw::git_cred) -> Cred { Cred { raw: raw } } - fn raw(&self) -> *mut raw::git_cred { self.raw } + fn raw(&self) -> *mut raw::git_cred { + self.raw + } } impl Drop for Cred { @@ -222,13 +234,14 @@ impl CredentialHelper { // Configure the queried username from `config` fn config_username(&mut self, config: &Config) { let key = self.exact_key("username"); - self.username = config.get_string(&key).ok().or_else(|| { - self.url_key("username").and_then(|s| { - config.get_string(&s).ok() + self.username = config + .get_string(&key) + .ok() + .or_else(|| { + self.url_key("username") + .and_then(|s| config.get_string(&s).ok()) }) - }).or_else(|| { - config.get_string("credential.username").ok() - }) + .or_else(|| config.get_string("credential.username").ok()) } // Discover all `helper` directives from `config` @@ -255,8 +268,7 @@ impl CredentialHelper { if cmd.starts_with('!') { self.commands.push(cmd[1..].to_string()); - } else if cmd.starts_with('/') || cmd.starts_with('\\') || - cmd[1..].starts_with(":\\") { + } else if cmd.starts_with('/') || cmd.starts_with('\\') || cmd[1..].starts_with(":\\") { self.commands.push(cmd.to_string()); } else { self.commands.push(format!("git credential-{}", cmd)); @@ -272,7 +284,7 @@ impl CredentialHelper { (&Some(ref host), &Some(ref protocol)) => { Some(format!("credential.{}://{}.{}", protocol, host, name)) } - _ => None + _ => None, } } @@ -291,7 +303,9 @@ impl CredentialHelper { if p.is_some() && password.is_none() { password = p; } - if username.is_some() && password.is_some() { break } + if username.is_some() && password.is_some() { + break; + } } match (username, password) { @@ -302,8 +316,11 @@ impl CredentialHelper { // Execute the given `cmd`, providing the appropriate variables on stdin and // then afterwards parsing the output into the username/password on stdout. - fn execute_cmd(&self, cmd: &str, username: &Option) - -> (Option, Option) { + fn execute_cmd( + &self, + cmd: &str, + username: &Option, + ) -> (Option, Option) { macro_rules! my_try( ($e:expr) => ( match $e { Ok(e) => e, @@ -356,26 +373,30 @@ impl CredentialHelper { // stdin { let stdin = p.stdin.as_mut().unwrap(); - if let Some(ref p) = self.protocol { + if let Some(ref p) = self.protocol { let _ = writeln!(stdin, "protocol={}", p); } - if let Some(ref p) = self.host { + if let Some(ref p) = self.host { let _ = writeln!(stdin, "host={}", p); } - if let Some(ref p) = *username { + if let Some(ref p) = *username { let _ = writeln!(stdin, "username={}", p); } } let output = my_try!(p.wait_with_output()); if !output.status.success() { - debug!("credential helper failed: {}\nstdout ---\n{}\nstdout ---\n{}", - output.status, - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr)); - return (None, None) + debug!( + "credential helper failed: {}\nstdout ---\n{}\nstdout ---\n{}", + output.status, + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + return (None, None); } - trace!("credential helper stderr ---\n{}", - String::from_utf8_lossy(&output.stderr)); + trace!( + "credential helper stderr ---\n{}", + String::from_utf8_lossy(&output.stderr) + ); self.parse_output(output.stdout) } @@ -391,7 +412,7 @@ impl CredentialHelper { Some(s) => s, None => { trace!("ignoring output line: {}", String::from_utf8_lossy(line)); - continue + continue; } }; let value = match String::from_utf8(value.to_vec()) { @@ -416,7 +437,7 @@ mod test { use std::path::Path; use tempdir::TempDir; - use {Cred, Config, CredentialHelper, ConfigLevel}; + use {Config, ConfigLevel, Cred, CredentialHelper}; macro_rules! test_cfg( ($($k:expr => $v:expr),*) => ({ let td = TempDir::new("git2-rs").unwrap(); @@ -437,8 +458,9 @@ mod test { "credential.helper" => "!f() { echo username=a; echo password=b; }; f" }; let (u, p) = CredentialHelper::new("https://example.com/foo/bar") - .config(&cfg) - .execute().unwrap(); + .config(&cfg) + .execute() + .unwrap(); assert_eq!(u, "a"); assert_eq!(p, "b"); } @@ -447,8 +469,9 @@ mod test { fn credential_helper2() { let cfg = test_cfg! {}; assert!(CredentialHelper::new("https://example.com/foo/bar") - .config(&cfg) - .execute().is_none()); + .config(&cfg) + .execute() + .is_none()); } #[test] @@ -459,22 +482,30 @@ mod test { "credential.helper" => "!f() { echo username=a; echo password=b; }; f" }; let (u, p) = CredentialHelper::new("https://example.com/foo/bar") - .config(&cfg) - .execute().unwrap(); + .config(&cfg) + .execute() + .unwrap(); assert_eq!(u, "c"); assert_eq!(p, "b"); } #[test] fn credential_helper4() { - if cfg!(windows) { return } // shell scripts don't work on Windows + if cfg!(windows) { + return; + } // shell scripts don't work on Windows let td = TempDir::new("git2-rs").unwrap(); let path = td.path().join("script"); - File::create(&path).unwrap().write(br"\ + File::create(&path) + .unwrap() + .write( + br"\ #!/bin/sh echo username=c -").unwrap(); +", + ) + .unwrap(); chmod(&path); let cfg = test_cfg! { "credential.https://example.com.helper" => @@ -482,26 +513,34 @@ echo username=c "credential.helper" => "!f() { echo username=a; echo password=b; }; f" }; let (u, p) = CredentialHelper::new("https://example.com/foo/bar") - .config(&cfg) - .execute().unwrap(); + .config(&cfg) + .execute() + .unwrap(); assert_eq!(u, "c"); assert_eq!(p, "b"); } #[test] fn credential_helper5() { - if cfg!(windows) { return } // shell scripts don't work on Windows + if cfg!(windows) { + return; + } // shell scripts don't work on Windows let td = TempDir::new("git2-rs").unwrap(); let path = td.path().join("git-credential-script"); - File::create(&path).unwrap().write(br"\ + File::create(&path) + .unwrap() + .write( + br"\ #!/bin/sh echo username=c -").unwrap(); +", + ) + .unwrap(); chmod(&path); let paths = env::var("PATH").unwrap(); - let paths = env::split_paths(&paths) - .chain(path.parent().map(|p| p.to_path_buf()).into_iter()); + let paths = + env::split_paths(&paths).chain(path.parent().map(|p| p.to_path_buf()).into_iter()); env::set_var("PATH", &env::join_paths(paths).unwrap()); let cfg = test_cfg! { @@ -509,8 +548,9 @@ echo username=c "credential.helper" => "!f() { echo username=a; echo password=b; }; f" }; let (u, p) = CredentialHelper::new("https://example.com/foo/bar") - .config(&cfg) - .execute().unwrap(); + .config(&cfg) + .execute() + .unwrap(); assert_eq!(u, "c"); assert_eq!(p, "b"); } @@ -521,27 +561,36 @@ echo username=c "credential.helper" => "" }; assert!(CredentialHelper::new("https://example.com/foo/bar") - .config(&cfg) - .execute().is_none()); + .config(&cfg) + .execute() + .is_none()); } #[test] fn credential_helper7() { - if cfg!(windows) { return } // shell scripts don't work on Windows + if cfg!(windows) { + return; + } // shell scripts don't work on Windows let td = TempDir::new("git2-rs").unwrap(); let path = td.path().join("script"); - File::create(&path).unwrap().write(br"\ + File::create(&path) + .unwrap() + .write( + br"\ #!/bin/sh echo username=$1 echo password=$2 -").unwrap(); +", + ) + .unwrap(); chmod(&path); let cfg = test_cfg! { "credential.helper" => &format!("{} a b", path.display()) }; let (u, p) = CredentialHelper::new("https://example.com/foo/bar") - .config(&cfg) - .execute().unwrap(); + .config(&cfg) + .execute() + .unwrap(); assert_eq!(u, "a"); assert_eq!(p, "b"); } @@ -588,11 +637,10 @@ echo password=$2 assert!(cred.is_ok()); } - #[cfg(unix)] fn chmod(path: &Path) { - use std::os::unix::prelude::*; use std::fs; + use std::os::unix::prelude::*; let mut perms = fs::metadata(path).unwrap().permissions(); perms.set_mode(0o755); fs::set_permissions(path, perms).unwrap(); diff --git a/src/describe.rs b/src/describe.rs index a894c57425..5e8d1e9391 100644 --- a/src/describe.rs +++ b/src/describe.rs @@ -1,12 +1,12 @@ +use std::ffi::CString; use std::marker; use std::mem; -use std::ffi::CString; use std::ptr; -use libc::{c_uint, c_int}; +use libc::{c_int, c_uint}; -use {raw, Repository, Error, Buf}; use util::Binding; +use {raw, Buf, Error, Repository}; /// The result of a `describe` operation on either an `Describe` or a /// `Repository`. @@ -29,8 +29,7 @@ pub struct DescribeFormatOptions { impl<'repo> Describe<'repo> { /// Prints this describe result, returning the result as a string. - pub fn format(&self, opts: Option<&DescribeFormatOptions>) - -> Result { + pub fn format(&self, opts: Option<&DescribeFormatOptions>) -> Result { let buf = Buf::new(); let opts = opts.map(|o| &o.raw as *const _).unwrap_or(ptr::null()); unsafe { @@ -44,9 +43,14 @@ impl<'repo> Binding for Describe<'repo> { type Raw = *mut raw::git_describe_result; unsafe fn from_raw(raw: *mut raw::git_describe_result) -> Describe<'repo> { - Describe { raw: raw, _marker: marker::PhantomData, } + Describe { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_describe_result { + self.raw } - fn raw(&self) -> *mut raw::git_describe_result { self.raw } } impl<'repo> Drop for Describe<'repo> { @@ -164,8 +168,7 @@ impl DescribeOptions { impl Binding for DescribeOptions { type Raw = *mut raw::git_describe_options; - unsafe fn from_raw(_raw: *mut raw::git_describe_options) - -> DescribeOptions { + unsafe fn from_raw(_raw: *mut raw::git_describe_options) -> DescribeOptions { panic!("unimplemened") } fn raw(&self) -> *mut raw::git_describe_options { @@ -182,8 +185,7 @@ mod tests { let (_td, repo) = ::test::repo_init(); let head = t!(repo.head()).target().unwrap(); - let d = t!(repo.describe(DescribeOptions::new() - .show_commit_oid_as_fallback(true))); + let d = t!(repo.describe(DescribeOptions::new().show_commit_oid_as_fallback(true))); let id = head.to_string(); assert_eq!(t!(d.format(None)), &id[..7]); diff --git a/src/diff.rs b/src/diff.rs index 291266608d..74f81b774d 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -1,3 +1,4 @@ +use libc::{c_char, c_int, c_void, size_t}; use std::ffi::CString; use std::marker; use std::mem; @@ -5,11 +6,10 @@ use std::ops::Range; use std::path::Path; use std::ptr; use std::slice; -use libc::{c_char, size_t, c_void, c_int}; -use {raw, panic, Buf, Delta, Oid, Repository, Error, DiffFormat}; -use {DiffStatsFormat, IntoCString}; use util::{self, Binding}; +use {panic, raw, Buf, Delta, DiffFormat, Error, Oid, Repository}; +use {DiffStatsFormat, IntoCString}; /// The diff object that contains all individual file deltas. /// @@ -126,14 +126,19 @@ impl<'repo> Diff<'repo> { /// is from the "from" list (with the exception that if the item has a /// pending DELETE in the middle, then it will show as deleted). pub fn merge(&mut self, from: &Diff<'repo>) -> Result<(), Error> { - unsafe { try_call!(raw::git_diff_merge(self.raw, &*from.raw)); } + unsafe { + try_call!(raw::git_diff_merge(self.raw, &*from.raw)); + } Ok(()) } /// Returns an iterator over the deltas in this diff. pub fn deltas(&self) -> Deltas { let num_deltas = unsafe { raw::git_diff_num_deltas(&*self.raw) }; - Deltas { range: 0..(num_deltas as usize), diff: self } + Deltas { + range: 0..(num_deltas as usize), + diff: self, + } } /// Return the diff delta for an entry in the diff list. @@ -154,14 +159,18 @@ impl<'repo> Diff<'repo> { /// Returning `false` from the callback will terminate the iteration and /// return an error from this function. pub fn print(&self, format: DiffFormat, mut cb: F) -> Result<(), Error> - where F: FnMut(DiffDelta, - Option, - DiffLine) -> bool { + where + F: FnMut(DiffDelta, Option, DiffLine) -> bool, + { let mut cb: &mut PrintCb = &mut cb; let ptr = &mut cb as *mut _; unsafe { - try_call!(raw::git_diff_print(self.raw, format, print_cb, - ptr as *mut _)); + try_call!(raw::git_diff_print( + self.raw, + format, + print_cb, + ptr as *mut _ + )); Ok(()) } } @@ -170,11 +179,13 @@ impl<'repo> Diff<'repo> { /// /// Returning `false` from any callback will terminate the iteration and /// return an error from this function. - pub fn foreach(&self, - file_cb: &mut FileCb, - binary_cb: Option<&mut BinaryCb>, - hunk_cb: Option<&mut HunkCb>, - line_cb: Option<&mut LineCb>) -> Result<(), Error> { + pub fn foreach( + &self, + file_cb: &mut FileCb, + binary_cb: Option<&mut BinaryCb>, + hunk_cb: Option<&mut HunkCb>, + line_cb: Option<&mut LineCb>, + ) -> Result<(), Error> { let mut cbs = ForeachCallbacks { file: file_cb, binary: binary_cb, @@ -198,9 +209,14 @@ impl<'repo> Diff<'repo> { } else { None }; - try_call!(raw::git_diff_foreach(self.raw, file_cb_c, binary_cb_c, - hunk_cb_c, line_cb_c, - ptr as *mut _)); + try_call!(raw::git_diff_foreach( + self.raw, + file_cb_c, + binary_cb_c, + hunk_cb_c, + line_cb_c, + ptr as *mut _ + )); Ok(()) } } @@ -220,20 +236,23 @@ impl<'repo> Diff<'repo> { /// renames or copies with new entries reflecting those changes. This also /// will, if requested, break modified files into add/remove pairs if the /// amount of change is above a threshold. - pub fn find_similar(&mut self, opts: Option<&mut DiffFindOptions>) - -> Result<(), Error> { + pub fn find_similar(&mut self, opts: Option<&mut DiffFindOptions>) -> Result<(), Error> { let opts = opts.map(|opts| &opts.raw); - unsafe { try_call!(raw::git_diff_find_similar(self.raw, opts)); } + unsafe { + try_call!(raw::git_diff_find_similar(self.raw, opts)); + } Ok(()) } // TODO: num_deltas_of_type, format_email, find_similar } -pub extern fn print_cb(delta: *const raw::git_diff_delta, - hunk: *const raw::git_diff_hunk, - line: *const raw::git_diff_line, - data: *mut c_void) -> c_int { +pub extern "C" fn print_cb( + delta: *const raw::git_diff_delta, + hunk: *const raw::git_diff_hunk, + line: *const raw::git_diff_line, + data: *mut c_void, +) -> c_int { unsafe { let delta = Binding::from_raw(delta as *mut _); let hunk = Binding::from_raw_opt(hunk); @@ -243,13 +262,19 @@ pub extern fn print_cb(delta: *const raw::git_diff_delta, let data = data as *mut &mut PrintCb; (*data)(delta, hunk, line) }); - if r == Some(true) {0} else {-1} + if r == Some(true) { + 0 + } else { + -1 + } } } -extern fn file_cb_c(delta: *const raw::git_diff_delta, - progress: f32, - data: *mut c_void) -> c_int { +extern "C" fn file_cb_c( + delta: *const raw::git_diff_delta, + progress: f32, + data: *mut c_void, +) -> c_int { unsafe { let delta = Binding::from_raw(delta as *mut _); @@ -257,13 +282,19 @@ extern fn file_cb_c(delta: *const raw::git_diff_delta, let cbs = data as *mut ForeachCallbacks; ((*cbs).file)(delta, progress) }); - if r == Some(true) {0} else {-1} + if r == Some(true) { + 0 + } else { + -1 + } } } -extern fn binary_cb_c(delta: *const raw::git_diff_delta, - binary: *const raw::git_diff_binary, - data: *mut c_void) -> c_int { +extern "C" fn binary_cb_c( + delta: *const raw::git_diff_delta, + binary: *const raw::git_diff_binary, + data: *mut c_void, +) -> c_int { unsafe { let delta = Binding::from_raw(delta as *mut _); let binary = Binding::from_raw(binary); @@ -275,13 +306,19 @@ extern fn binary_cb_c(delta: *const raw::git_diff_delta, None => false, } }); - if r == Some(true) {0} else {-1} + if r == Some(true) { + 0 + } else { + -1 + } } } -extern fn hunk_cb_c(delta: *const raw::git_diff_delta, - hunk: *const raw::git_diff_hunk, - data: *mut c_void) -> c_int { +extern "C" fn hunk_cb_c( + delta: *const raw::git_diff_delta, + hunk: *const raw::git_diff_hunk, + data: *mut c_void, +) -> c_int { unsafe { let delta = Binding::from_raw(delta as *mut _); let hunk = Binding::from_raw(hunk); @@ -293,14 +330,20 @@ extern fn hunk_cb_c(delta: *const raw::git_diff_delta, None => false, } }); - if r == Some(true) {0} else {-1} + if r == Some(true) { + 0 + } else { + -1 + } } } -extern fn line_cb_c(delta: *const raw::git_diff_delta, - hunk: *const raw::git_diff_hunk, - line: *const raw::git_diff_line, - data: *mut c_void) -> c_int { +extern "C" fn line_cb_c( + delta: *const raw::git_diff_delta, + hunk: *const raw::git_diff_hunk, + line: *const raw::git_diff_line, + data: *mut c_void, +) -> c_int { unsafe { let delta = Binding::from_raw(delta as *mut _); let hunk = Binding::from_raw_opt(hunk); @@ -313,20 +356,25 @@ extern fn line_cb_c(delta: *const raw::git_diff_delta, None => false, } }); - if r == Some(true) {0} else {-1} + if r == Some(true) { + 0 + } else { + -1 + } } } - impl<'repo> Binding for Diff<'repo> { type Raw = *mut raw::git_diff; unsafe fn from_raw(raw: *mut raw::git_diff) -> Diff<'repo> { Diff { - raw: raw, - _marker: marker::PhantomData, + raw: raw, + _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_diff { self.raw } + fn raw(&self) -> *mut raw::git_diff { + self.raw + } } impl<'repo> Drop for Diff<'repo> { @@ -391,7 +439,9 @@ impl<'a> Binding for DiffDelta<'a> { _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_diff_delta { self.raw } + fn raw(&self) -> *mut raw::git_diff_delta { + self.raw + } } impl<'a> DiffFile<'a> { @@ -417,7 +467,9 @@ impl<'a> DiffFile<'a> { } /// Returns the size of this entry, in bytes - pub fn size(&self) -> u64 { unsafe { (*self.raw).size as u64 } } + pub fn size(&self) -> u64 { + unsafe { (*self.raw).size as u64 } + } // TODO: expose flags/mode } @@ -430,7 +482,9 @@ impl<'a> Binding for DiffFile<'a> { _marker: marker::PhantomData, } } - fn raw(&self) -> *const raw::git_diff_file { self.raw } + fn raw(&self) -> *const raw::git_diff_file { + self.raw + } } impl Default for DiffOptions { @@ -452,9 +506,7 @@ impl DiffOptions { old_prefix: None, new_prefix: None, }; - assert_eq!(unsafe { - raw::git_diff_init_options(&mut opts.raw, 1) - }, 0); + assert_eq!(unsafe { raw::git_diff_init_options(&mut opts.raw, 1) }, 0); opts } @@ -549,8 +601,7 @@ impl DiffOptions { /// /// This flag turns off that scan and immediately labels an untracked /// directory as untracked (changing the behavior to not match core git). - pub fn enable_fast_untracked_dirs(&mut self, enable: bool) - -> &mut DiffOptions { + pub fn enable_fast_untracked_dirs(&mut self, enable: bool) -> &mut DiffOptions { self.flag(raw::GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS, enable) } @@ -568,8 +619,7 @@ impl DiffOptions { } /// Include unreadable files in the diff - pub fn include_unreadable_as_untracked(&mut self, include: bool) - -> &mut DiffOptions { + pub fn include_unreadable_as_untracked(&mut self, include: bool) -> &mut DiffOptions { self.flag(raw::GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED, include) } @@ -690,8 +740,7 @@ impl DiffOptions { } /// Add to the array of paths/fnmatch patterns to constrain the diff. - pub fn pathspec(&mut self, pathspec: T) - -> &mut DiffOptions { + pub fn pathspec(&mut self, pathspec: T) -> &mut DiffOptions { let s = pathspec.into_c_string().unwrap(); self.pathspec_ptrs.push(s.as_ptr()); self.pathspec.push(s); @@ -703,10 +752,16 @@ impl DiffOptions { /// This function is unsafe as the pointer is only valid so long as this /// structure is not moved, modified, or used elsewhere. pub unsafe fn raw(&mut self) -> *const raw::git_diff_options { - self.raw.old_prefix = self.old_prefix.as_ref().map(|s| s.as_ptr()) - .unwrap_or(ptr::null()); - self.raw.new_prefix = self.new_prefix.as_ref().map(|s| s.as_ptr()) - .unwrap_or(ptr::null()); + self.raw.old_prefix = self + .old_prefix + .as_ref() + .map(|s| s.as_ptr()) + .unwrap_or(ptr::null()); + self.raw.new_prefix = self + .new_prefix + .as_ref() + .map(|s| s.as_ptr()) + .unwrap_or(ptr::null()); self.raw.pathspec.count = self.pathspec_ptrs.len() as size_t; self.raw.pathspec.strings = self.pathspec_ptrs.as_ptr() as *mut _; &self.raw as *const _ @@ -720,7 +775,9 @@ impl<'diff> Iterator for Deltas<'diff> { fn next(&mut self) -> Option> { self.range.next().and_then(|i| self.diff.get_delta(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'diff> DoubleEndedIterator for Deltas<'diff> { fn next_back(&mut self) -> Option> { @@ -759,8 +816,10 @@ impl<'a> DiffLine<'a> { /// Content of this line as bytes. pub fn content(&self) -> &[u8] { unsafe { - slice::from_raw_parts((*self.raw).content as *const u8, - (*self.raw).content_len as usize) + slice::from_raw_parts( + (*self.raw).content as *const u8, + (*self.raw).content_len as usize, + ) } } @@ -799,7 +858,9 @@ impl<'a> Binding for DiffLine<'a> { _marker: marker::PhantomData, } } - fn raw(&self) -> *const raw::git_diff_line { self.raw } + fn raw(&self) -> *const raw::git_diff_line { + self.raw + } } impl<'a> DiffHunk<'a> { @@ -826,8 +887,10 @@ impl<'a> DiffHunk<'a> { /// Header text pub fn header(&self) -> &[u8] { unsafe { - slice::from_raw_parts((*self.raw).header.as_ptr() as *const u8, - (*self.raw).header_len as usize) + slice::from_raw_parts( + (*self.raw).header.as_ptr() as *const u8, + (*self.raw).header_len as usize, + ) } } } @@ -840,7 +903,9 @@ impl<'a> Binding for DiffHunk<'a> { _marker: marker::PhantomData, } } - fn raw(&self) -> *const raw::git_diff_hunk { self.raw } + fn raw(&self) -> *const raw::git_diff_hunk { + self.raw + } } impl DiffStats { @@ -860,13 +925,15 @@ impl DiffStats { } /// Print diff statistics to a Buf - pub fn to_buf(&self, format: DiffStatsFormat, width: usize) - -> Result { + pub fn to_buf(&self, format: DiffStatsFormat, width: usize) -> Result { let buf = Buf::new(); unsafe { - try_call!(raw::git_diff_stats_to_buf(buf.raw(), self.raw, - format.bits(), - width as size_t)); + try_call!(raw::git_diff_stats_to_buf( + buf.raw(), + self.raw, + format.bits(), + width as size_t + )); } Ok(buf) } @@ -878,7 +945,9 @@ impl Binding for DiffStats { unsafe fn from_raw(raw: *mut raw::git_diff_stats) -> DiffStats { DiffStats { raw: raw } } - fn raw(&self) -> *mut raw::git_diff_stats { self.raw } + fn raw(&self) -> *mut raw::git_diff_stats { + self.raw + } } impl Drop for DiffStats { @@ -917,7 +986,9 @@ impl<'a> Binding for DiffBinary<'a> { _marker: marker::PhantomData, } } - fn raw(&self) -> *const raw::git_diff_binary { self.raw } + fn raw(&self) -> *const raw::git_diff_binary { + self.raw + } } impl<'a> DiffBinaryFile<'a> { @@ -929,8 +1000,7 @@ impl<'a> DiffBinaryFile<'a> { /// The binary data, deflated pub fn data(&self) -> &[u8] { unsafe { - slice::from_raw_parts((*self.raw).data as *const u8, - (*self.raw).datalen as usize) + slice::from_raw_parts((*self.raw).data as *const u8, (*self.raw).datalen as usize) } } @@ -938,7 +1008,6 @@ impl<'a> DiffBinaryFile<'a> { pub fn inflated_len(&self) -> usize { unsafe { (*self.raw).inflatedlen as usize } } - } impl<'a> Binding for DiffBinaryFile<'a> { @@ -949,7 +1018,9 @@ impl<'a> Binding for DiffBinaryFile<'a> { _marker: marker::PhantomData, } } - fn raw(&self) -> *const raw::git_diff_binary_file { self.raw } + fn raw(&self) -> *const raw::git_diff_binary_file { + self.raw + } } impl Binding for DiffBinaryKind { @@ -986,9 +1057,10 @@ impl DiffFindOptions { let mut opts = DiffFindOptions { raw: unsafe { mem::zeroed() }, }; - assert_eq!(unsafe { - raw::git_diff_find_init_options(&mut opts.raw, 1) - }, 0); + assert_eq!( + unsafe { raw::git_diff_find_init_options(&mut opts.raw, 1) }, + 0 + ); opts } @@ -1027,8 +1099,7 @@ impl DiffFindOptions { /// /// For this to work correctly, use `include_unmodified` when the initial /// diff is being generated. - pub fn copies_from_unmodified(&mut self, find: bool) - -> &mut DiffFindOptions { + pub fn copies_from_unmodified(&mut self, find: bool) -> &mut DiffFindOptions { self.flag(raw::GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED, find) } @@ -1061,8 +1132,7 @@ impl DiffFindOptions { } /// Measure similarity ignoring leading whitespace (default) - pub fn ignore_leading_whitespace(&mut self, ignore: bool) - -> &mut DiffFindOptions { + pub fn ignore_leading_whitespace(&mut self, ignore: bool) -> &mut DiffFindOptions { self.flag(raw::GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE, ignore) } @@ -1091,8 +1161,7 @@ impl DiffFindOptions { /// If you add this flag in and the split pair is not used for an actual /// rename or copy, then the modified record will be restored to a regular /// modified record instead of being split. - pub fn break_rewrites_for_renames_only(&mut self, b: bool) - -> &mut DiffFindOptions { + pub fn break_rewrites_for_renames_only(&mut self, b: bool) -> &mut DiffFindOptions { self.flag(raw::GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY, b) } @@ -1113,8 +1182,7 @@ impl DiffFindOptions { } /// Similarity of modified to be glegible rename source (default 50) - pub fn rename_from_rewrite_threshold(&mut self, thresh: u16) - -> &mut DiffFindOptions { + pub fn rename_from_rewrite_threshold(&mut self, thresh: u16) -> &mut DiffFindOptions { self.raw.rename_from_rewrite_threshold = thresh; self } @@ -1126,8 +1194,7 @@ impl DiffFindOptions { } /// Similarity to split modify into delete/add pair (default 60) - pub fn break_rewrite_threshold(&mut self, thresh: u16) - -> &mut DiffFindOptions { + pub fn break_rewrite_threshold(&mut self, thresh: u16) -> &mut DiffFindOptions { self.raw.break_rewrite_threshold = thresh; self } @@ -1146,11 +1213,11 @@ impl DiffFindOptions { #[cfg(test)] mod tests { - use DiffOptions; - use std::fs::File; - use std::path::Path; use std::borrow::Borrow; + use std::fs::File; use std::io::Write; + use std::path::Path; + use DiffOptions; #[test] fn smoke() { @@ -1168,8 +1235,15 @@ mod tests { let (_td, repo) = ::test::repo_init(); let diff = t!(repo.diff_tree_to_workdir(None, None)); let mut count = 0; - t!(diff.foreach(&mut |_file, _progress| { count = count + 1; true }, - None, None, None)); + t!(diff.foreach( + &mut |_file, _progress| { + count = count + 1; + true + }, + None, + None, + None + )); assert_eq!(count, 0); } @@ -1183,11 +1257,16 @@ mod tests { let diff = t!(repo.diff_tree_to_workdir(None, Some(&mut opts))); let mut count = 0; let mut result = None; - t!(diff.foreach(&mut |file, _progress| { - count = count + 1; - result = file.new_file().path().map(ToOwned::to_owned); - true - }, None, None, None)); + t!(diff.foreach( + &mut |file, _progress| { + count = count + 1; + result = file.new_file().path().map(ToOwned::to_owned); + true + }, + None, + None, + None + )); assert_eq!(result.as_ref().map(Borrow::borrow), Some(path)); assert_eq!(count, 1); } @@ -1201,8 +1280,7 @@ mod tests { t!(index.add_path(path)); let mut opts = DiffOptions::new(); opts.include_untracked(true); - let diff = t!(repo.diff_tree_to_index(None, Some(&index), - Some(&mut opts))); + let diff = t!(repo.diff_tree_to_index(None, Some(&index), Some(&mut opts))); let mut new_lines = 0; t!(diff.foreach( &mut |_file, _progress| { true }, @@ -1211,7 +1289,8 @@ mod tests { new_lines = hunk.new_lines(); true }), - None)); + None + )); assert_eq!(new_lines, 1); } @@ -1220,8 +1299,7 @@ mod tests { let fib = vec![0, 1, 1, 2, 3, 5, 8]; // Verified with a node implementation of deflate, might be worth // adding a deflate lib to do this inline here. - let deflated_fib = vec![120, 156, 99, 96, 100, 100, 98, 102, 229, 0, 0, - 0, 53, 0, 21]; + let deflated_fib = vec![120, 156, 99, 96, 100, 100, 98, 102, 229, 0, 0, 0, 53, 0, 21]; let foo_path = Path::new("foo"); let bin_path = Path::new("bin"); let (td, repo) = ::test::repo_init(); @@ -1232,8 +1310,7 @@ mod tests { t!(index.add_path(bin_path)); let mut opts = DiffOptions::new(); opts.include_untracked(true).show_binary(true); - let diff = t!(repo.diff_tree_to_index(None, Some(&index), - Some(&mut opts))); + let diff = t!(repo.diff_tree_to_index(None, Some(&index), Some(&mut opts))); let mut bin_content = None; let mut new_lines = 0; let mut line_content = None; @@ -1250,7 +1327,8 @@ mod tests { Some(&mut |_file, _hunk, line| { line_content = String::from_utf8(line.content().into()).ok(); true - }))); + }) + )); assert_eq!(bin_content, Some(deflated_fib)); assert_eq!(new_lines, 1); assert_eq!(line_content, Some("bar\n".to_string())); diff --git a/src/error.rs b/src/error.rs index e342d6ce0b..23b601377e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,14 +1,14 @@ +use libc::c_int; use std::env::JoinPathsError; -use std::ffi::{CStr, NulError}; use std::error; +use std::ffi::{CStr, NulError}; use std::fmt; use std::str; -use libc::c_int; use {raw, ErrorClass, ErrorCode}; /// A structure to represent errors coming out of libgit2. -#[derive(Debug,PartialEq)] +#[derive(Debug, PartialEq)] pub struct Error { code: c_int, klass: c_int, @@ -59,7 +59,11 @@ impl Error { unsafe fn from_raw(code: c_int, ptr: *const raw::git_error) -> Error { let msg = CStr::from_ptr((*ptr).message as *const _).to_bytes(); let msg = String::from_utf8_lossy(msg).into_owned(); - Error { code: code, klass: (*ptr).klass, message: msg } + Error { + code: code, + klass: (*ptr).klass, + message: msg, + } } /// Creates a new error from the given string as the error. @@ -233,11 +237,15 @@ impl Error { } /// Return the message associated with this error - pub fn message(&self) -> &str { &self.message } + pub fn message(&self) -> &str { + &self.message + } } impl error::Error for Error { - fn description(&self) -> &str { &self.message } + fn description(&self) -> &str { + &self.message + } } impl fmt::Display for Error { @@ -257,8 +265,10 @@ impl fmt::Display for Error { impl From for Error { fn from(_: NulError) -> Error { - Error::from_str("data contained a nul byte that could not be \ - represented as a string") + Error::from_str( + "data contained a nul byte that could not be \ + represented as a string", + ) } } @@ -268,7 +278,6 @@ impl From for Error { } } - #[cfg(test)] mod tests { use {ErrorClass, ErrorCode}; diff --git a/src/index.rs b/src/index.rs index 4b6d63c0e5..9d5f14054b 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1,15 +1,15 @@ -use std::ffi::{CStr, OsString, CString}; +use std::ffi::{CStr, CString, OsString}; use std::marker; use std::ops::Range; use std::path::Path; use std::ptr; use std::slice; -use libc::{c_int, c_uint, size_t, c_void, c_char}; +use libc::{c_char, c_int, c_uint, c_void, size_t}; -use {raw, panic, Repository, Error, Tree, Oid, IndexAddOption, IndexTime}; -use IntoCString; use util::{self, Binding}; +use IntoCString; +use {panic, raw, Error, IndexAddOption, IndexTime, Oid, Repository, Tree}; /// A structure to represent a git [index][1] /// @@ -164,7 +164,7 @@ impl Index { /// no longer be marked as conflicting. The data about the conflict will be /// moved to the "resolve undo" (REUC) section. pub fn add_frombuffer(&mut self, entry: &IndexEntry, data: &[u8]) -> Result<(), Error> { - let path = try!(CString::new(&entry.path[..])); + let path = try!(CString::new(&entry.path[..])); // libgit2 encodes the length of the path in the lower bits of the // `flags` entry, so mask those out and recalculate here to ensure we @@ -223,7 +223,9 @@ impl Index { // Git apparently expects '/' to be separators for paths let mut posix_path = OsString::new(); for (i, comp) in path.components().enumerate() { - if i != 0 { posix_path.push("/"); } + if i != 0 { + posix_path.push("/"); + } posix_path.push(comp.as_os_str()); } let posix_path = try!(posix_path.into_c_string()); @@ -266,26 +268,29 @@ impl Index { /// updated in the index. Returning zero will add the item to the index, /// greater than zero will skip the item, and less than zero will abort the /// scan an return an error to the caller. - pub fn add_all(&mut self, - pathspecs: I, - flag: IndexAddOption, - mut cb: Option<&mut IndexMatchedPath>) - -> Result<(), Error> - where T: IntoCString, I: IntoIterator, + pub fn add_all( + &mut self, + pathspecs: I, + flag: IndexAddOption, + mut cb: Option<&mut IndexMatchedPath>, + ) -> Result<(), Error> + where + T: IntoCString, + I: IntoIterator, { let (_a, _b, raw_strarray) = try!(::util::iter2cstrs(pathspecs)); let ptr = cb.as_mut(); - let callback = ptr.as_ref().map(|_| { - index_matched_path_cb as raw::git_index_matched_path_cb - }); + let callback = ptr + .as_ref() + .map(|_| index_matched_path_cb as raw::git_index_matched_path_cb); unsafe { - try_call!(raw::git_index_add_all(self.raw, - &raw_strarray, - flag.bits() as c_uint, - callback, - ptr.map(|p| p as *mut _) - .unwrap_or(ptr::null_mut()) - as *mut c_void)); + try_call!(raw::git_index_add_all( + self.raw, + &raw_strarray, + flag.bits() as c_uint, + callback, + ptr.map(|p| p as *mut _).unwrap_or(ptr::null_mut()) as *mut c_void + )); } Ok(()) } @@ -295,7 +300,9 @@ impl Index { /// This clears the index object in memory; changes must be explicitly /// written to disk for them to take effect persistently via `write_*`. pub fn clear(&mut self) -> Result<(), Error> { - unsafe { try_call!(raw::git_index_clear(self.raw)); } + unsafe { + try_call!(raw::git_index_clear(self.raw)); + } Ok(()) } @@ -313,13 +320,20 @@ impl Index { pub fn get(&self, n: usize) -> Option { unsafe { let ptr = raw::git_index_get_byindex(self.raw, n as size_t); - if ptr.is_null() {None} else {Some(Binding::from_raw(*ptr))} + if ptr.is_null() { + None + } else { + Some(Binding::from_raw(*ptr)) + } } } /// Get an iterator over the entries in this index. pub fn iter(&self) -> IndexEntries { - IndexEntries { range: 0..self.len(), index: self } + IndexEntries { + range: 0..self.len(), + index: self, + } } /// Get an iterator over the index entries that have conflicts @@ -327,7 +341,10 @@ impl Index { ::init(); let mut conflict_iter = ptr::null_mut(); unsafe { - try_call!(raw::git_index_conflict_iterator_new(&mut conflict_iter, self.raw)); + try_call!(raw::git_index_conflict_iterator_new( + &mut conflict_iter, + self.raw + )); Ok(Binding::from_raw(conflict_iter)) } } @@ -336,9 +353,12 @@ impl Index { pub fn get_path(&self, path: &Path, stage: i32) -> Option { let path = path.into_c_string().unwrap(); unsafe { - let ptr = call!(raw::git_index_get_bypath(self.raw, path, - stage as c_int)); - if ptr.is_null() {None} else {Some(Binding::from_raw(*ptr))} + let ptr = call!(raw::git_index_get_bypath(self.raw, path, stage as c_int)); + if ptr.is_null() { + None + } else { + Some(Binding::from_raw(*ptr)) + } } } @@ -346,18 +366,14 @@ impl Index { /// /// Returns `true` if the index contains conflicts, `false` if it does not. pub fn has_conflicts(&self) -> bool { - unsafe { - raw::git_index_has_conflicts(self.raw) == 1 - } + unsafe { raw::git_index_has_conflicts(self.raw) == 1 } } /// Get the full path to the index file on disk. /// /// Returns `None` if this is an in-memory index. pub fn path(&self) -> Option<&Path> { - unsafe { - ::opt_bytes(self, raw::git_index_path(&*self.raw)).map(util::bytes2path) - } + unsafe { ::opt_bytes(self, raw::git_index_path(&*self.raw)).map(util::bytes2path) } } /// Update the contents of an existing index object in memory by reading @@ -372,7 +388,9 @@ impl Index { /// Purely in-memory index data will be untouched. Be aware: if there are /// changes on disk, unwritten in-memory changes are discarded. pub fn read(&mut self, force: bool) -> Result<(), Error> { - unsafe { try_call!(raw::git_index_read(self.raw, force)); } + unsafe { + try_call!(raw::git_index_read(self.raw, force)); + } Ok(()) } @@ -380,7 +398,9 @@ impl Index { /// /// The current index contents will be replaced by the specified tree. pub fn read_tree(&mut self, tree: &Tree) -> Result<(), Error> { - unsafe { try_call!(raw::git_index_read_tree(self.raw, &*tree.raw())); } + unsafe { + try_call!(raw::git_index_read_tree(self.raw, &*tree.raw())); + } Ok(()) } @@ -413,8 +433,11 @@ impl Index { pub fn remove_dir(&mut self, path: &Path, stage: i32) -> Result<(), Error> { let path = try!(path.into_c_string()); unsafe { - try_call!(raw::git_index_remove_directory(self.raw, path, - stage as c_int)); + try_call!(raw::git_index_remove_directory( + self.raw, + path, + stage as c_int + )); } Ok(()) } @@ -424,24 +447,27 @@ impl Index { /// If you provide a callback function, it will be invoked on each matching /// item in the index immediately before it is removed. Return 0 to remove /// the item, > 0 to skip the item, and < 0 to abort the scan. - pub fn remove_all(&mut self, - pathspecs: I, - mut cb: Option<&mut IndexMatchedPath>) - -> Result<(), Error> - where T: IntoCString, I: IntoIterator, + pub fn remove_all( + &mut self, + pathspecs: I, + mut cb: Option<&mut IndexMatchedPath>, + ) -> Result<(), Error> + where + T: IntoCString, + I: IntoIterator, { let (_a, _b, raw_strarray) = try!(::util::iter2cstrs(pathspecs)); let ptr = cb.as_mut(); - let callback = ptr.as_ref().map(|_| { - index_matched_path_cb as raw::git_index_matched_path_cb - }); + let callback = ptr + .as_ref() + .map(|_| index_matched_path_cb as raw::git_index_matched_path_cb); unsafe { - try_call!(raw::git_index_remove_all(self.raw, - &raw_strarray, - callback, - ptr.map(|p| p as *mut _) - .unwrap_or(ptr::null_mut()) - as *mut c_void)); + try_call!(raw::git_index_remove_all( + self.raw, + &raw_strarray, + callback, + ptr.map(|p| p as *mut _).unwrap_or(ptr::null_mut()) as *mut c_void + )); } Ok(()) } @@ -459,24 +485,27 @@ impl Index { /// item in the index immediately before it is updated (either refreshed or /// removed depending on working directory state). Return 0 to proceed with /// updating the item, > 0 to skip the item, and < 0 to abort the scan. - pub fn update_all(&mut self, - pathspecs: I, - mut cb: Option<&mut IndexMatchedPath>) - -> Result<(), Error> - where T: IntoCString, I: IntoIterator, + pub fn update_all( + &mut self, + pathspecs: I, + mut cb: Option<&mut IndexMatchedPath>, + ) -> Result<(), Error> + where + T: IntoCString, + I: IntoIterator, { let (_a, _b, raw_strarray) = try!(::util::iter2cstrs(pathspecs)); let ptr = cb.as_mut(); - let callback = ptr.as_ref().map(|_| { - index_matched_path_cb as raw::git_index_matched_path_cb - }); + let callback = ptr + .as_ref() + .map(|_| index_matched_path_cb as raw::git_index_matched_path_cb); unsafe { - try_call!(raw::git_index_update_all(self.raw, - &raw_strarray, - callback, - ptr.map(|p| p as *mut _) - .unwrap_or(ptr::null_mut()) - as *mut c_void)); + try_call!(raw::git_index_update_all( + self.raw, + &raw_strarray, + callback, + ptr.map(|p| p as *mut _).unwrap_or(ptr::null_mut()) as *mut c_void + )); } Ok(()) } @@ -484,7 +513,9 @@ impl Index { /// Write an existing index object from memory back to disk using an atomic /// file lock. pub fn write(&mut self) -> Result<(), Error> { - unsafe { try_call!(raw::git_index_write(self.raw)); } + unsafe { + try_call!(raw::git_index_write(self.raw)); + } Ok(()) } @@ -500,7 +531,9 @@ impl Index { /// /// The index must not contain any file in conflict. pub fn write_tree(&mut self) -> Result { - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { try_call!(raw::git_index_write_tree(&mut raw, self.raw)); Ok(Binding::from_raw(&raw as *const _)) @@ -512,10 +545,11 @@ impl Index { /// This is the same as `write_tree` except that the destination repository /// can be chosen. pub fn write_tree_to(&mut self, repo: &Repository) -> Result { - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { - try_call!(raw::git_index_write_tree_to(&mut raw, self.raw, - repo.raw())); + try_call!(raw::git_index_write_tree_to(&mut raw, self.raw, repo.raw())); Ok(Binding::from_raw(&raw as *const _)) } } @@ -526,7 +560,9 @@ impl Binding for Index { unsafe fn from_raw(raw: *mut raw::git_index) -> Index { Index { raw: raw } } - fn raw(&self) -> *mut raw::git_index { self.raw } + fn raw(&self) -> *mut raw::git_index { + self.raw + } } impl<'index> Binding for IndexConflicts<'index> { @@ -538,12 +574,16 @@ impl<'index> Binding for IndexConflicts<'index> { _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_index_conflict_iterator { self.conflict_iter } + fn raw(&self) -> *mut raw::git_index_conflict_iterator { + self.conflict_iter + } } -extern fn index_matched_path_cb(path: *const c_char, - matched_pathspec: *const c_char, - payload: *mut c_void) -> c_int { +extern "C" fn index_matched_path_cb( + path: *const c_char, + matched_pathspec: *const c_char, + payload: *mut c_void, +) -> c_int { unsafe { let path = CStr::from_ptr(path).to_bytes(); let matched_pathspec = CStr::from_ptr(matched_pathspec).to_bytes(); @@ -551,7 +591,8 @@ extern fn index_matched_path_cb(path: *const c_char, panic::wrap(|| { let payload = payload as *mut &mut IndexMatchedPath; (*payload)(util::bytes2path(path), matched_pathspec) as c_int - }).unwrap_or(-1) + }) + .unwrap_or(-1) } } @@ -590,15 +631,15 @@ impl<'index> Iterator for IndexConflicts<'index> { Some(Ok(IndexConflict { ancestor: match ancestor.is_null() { false => Some(IndexEntry::from_raw(*ancestor)), - true => None, + true => None, }, our: match our.is_null() { false => Some(IndexEntry::from_raw(*our)), - true => None, + true => None, }, their: match their.is_null() { false => Some(IndexEntry::from_raw(*their)), - true => None, + true => None, }, })) } @@ -610,8 +651,18 @@ impl Binding for IndexEntry { unsafe fn from_raw(raw: raw::git_index_entry) -> IndexEntry { let raw::git_index_entry { - ctime, mtime, dev, ino, mode, uid, gid, file_size, id, flags, - flags_extended, path + ctime, + mtime, + dev, + ino, + mode, + uid, + gid, + file_size, + id, + flags, + flags_extended, + path, } = raw; // libgit2 encodes the length of the path in the lower bits of `flags`, @@ -652,7 +703,7 @@ mod tests { use std::path::Path; use tempdir::TempDir; - use {Index, IndexEntry, Repository, ResetType, Oid, IndexTime}; + use {Index, IndexEntry, IndexTime, Oid, Repository, ResetType}; #[test] fn smoke() { @@ -669,8 +720,10 @@ mod tests { fn smoke_from_repo() { let (_td, repo) = ::test::repo_init(); let mut index = repo.index().unwrap(); - assert_eq!(index.path().map(|s| s.to_path_buf()), - Some(repo.path().join("index"))); + assert_eq!( + index.path().map(|s| s.to_path_buf()), + Some(repo.path().join("index")) + ); Index::open(&repo.path().join("index")).unwrap(); index.clear().unwrap(); @@ -689,24 +742,34 @@ mod tests { fs::create_dir(&root.join("foo")).unwrap(); File::create(&root.join("foo/bar")).unwrap(); let mut called = false; - index.add_all(["foo"].iter(), ::IndexAddOption::DEFAULT, - Some(&mut |a: &Path, b: &[u8]| { - assert!(!called); - called = true; - assert_eq!(b, b"foo"); - assert_eq!(a, Path::new("foo/bar")); - 0 - })).unwrap(); + index + .add_all( + ["foo"].iter(), + ::IndexAddOption::DEFAULT, + Some(&mut |a: &Path, b: &[u8]| { + assert!(!called); + called = true; + assert_eq!(b, b"foo"); + assert_eq!(a, Path::new("foo/bar")); + 0 + }), + ) + .unwrap(); assert!(called); called = false; - index.remove_all(["."].iter(), Some(&mut |a: &Path, b: &[u8]| { - assert!(!called); - called = true; - assert_eq!(b, b"."); - assert_eq!(a, Path::new("foo/bar")); - 0 - })).unwrap(); + index + .remove_all( + ["."].iter(), + Some(&mut |a: &Path, b: &[u8]| { + assert!(!called); + called = true; + assert_eq!(b, b"."); + assert_eq!(a, Path::new("foo/bar")); + 0 + }), + ) + .unwrap(); assert!(called); } @@ -728,8 +791,9 @@ mod tests { let sig = repo.signature().unwrap(); let id = repo.refname_to_id("HEAD").unwrap(); let parent = repo.find_commit(id).unwrap(); - let commit = repo.commit(Some("HEAD"), &sig, &sig, "commit", - &tree, &[&parent]).unwrap(); + let commit = repo + .commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent]) + .unwrap(); let obj = repo.find_object(commit, None).unwrap(); repo.reset(&obj, ResetType::Hard, None).unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 873a16cb36..917c9fe14d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,11 +69,14 @@ #![cfg_attr(test, deny(warnings))] extern crate libc; -extern crate url; extern crate libgit2_sys as raw; -#[macro_use] extern crate bitflags; -#[macro_use] extern crate log; -#[cfg(test)] extern crate tempdir; +extern crate url; +#[macro_use] +extern crate bitflags; +#[macro_use] +extern crate log; +#[cfg(test)] +extern crate tempdir; use std::ffi::{CStr, CString}; use std::fmt; @@ -85,43 +88,43 @@ pub use blob::{Blob, BlobWriter}; pub use branch::{Branch, Branches}; pub use buf::Buf; pub use commit::{Commit, Parents}; -pub use config::{Config, ConfigEntry, ConfigEntries}; +pub use config::{Config, ConfigEntries, ConfigEntry}; pub use cred::{Cred, CredentialHelper}; pub use describe::{Describe, DescribeFormatOptions, DescribeOptions}; -pub use diff::{Diff, DiffDelta, DiffFile, DiffOptions, Deltas}; +pub use diff::{Deltas, Diff, DiffDelta, DiffFile, DiffOptions}; pub use diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind}; -pub use diff::{DiffLine, DiffHunk, DiffStats, DiffFindOptions}; +pub use diff::{DiffFindOptions, DiffHunk, DiffLine, DiffStats}; pub use error::Error; -pub use index::{Index, IndexConflict, IndexConflicts, IndexEntry, IndexEntries, IndexMatchedPath}; +pub use index::{Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath}; pub use merge::{AnnotatedCommit, MergeOptions}; pub use message::{message_prettify, DEFAULT_COMMENT_CHAR}; pub use note::{Note, Notes}; pub use object::Object; +pub use odb::{Odb, OdbObject, OdbReader, OdbWriter}; pub use oid::Oid; pub use packbuilder::{PackBuilder, PackBuilderStage}; -pub use pathspec::{Pathspec, PathspecMatchList, PathspecFailedEntries}; -pub use pathspec::{PathspecDiffEntries, PathspecEntries}; pub use patch::Patch; +pub use pathspec::{Pathspec, PathspecFailedEntries, PathspecMatchList}; +pub use pathspec::{PathspecDiffEntries, PathspecEntries}; pub use proxy_options::ProxyOptions; -pub use rebase::{Rebase, RebaseOptions, RebaseOperation, RebaseOperationType}; -pub use reference::{Reference, References, ReferenceNames}; +pub use rebase::{Rebase, RebaseOperation, RebaseOperationType, RebaseOptions}; +pub use reference::{Reference, ReferenceNames, References}; pub use reflog::{Reflog, ReflogEntry, ReflogIter}; pub use refspec::Refspec; -pub use remote::{Remote, RemoteConnection, Refspecs, RemoteHead, FetchOptions, PushOptions}; -pub use remote_callbacks::{RemoteCallbacks, Credentials, TransferProgress}; -pub use remote_callbacks::{TransportMessage, Progress, UpdateTips}; +pub use remote::{FetchOptions, PushOptions, Refspecs, Remote, RemoteConnection, RemoteHead}; +pub use remote_callbacks::{Credentials, RemoteCallbacks, TransferProgress}; +pub use remote_callbacks::{Progress, TransportMessage, UpdateTips}; pub use repo::{Repository, RepositoryInitOptions}; pub use revspec::Revspec; pub use revwalk::Revwalk; pub use signature::Signature; -pub use status::{StatusOptions, Statuses, StatusIter, StatusEntry, StatusShow}; -pub use stash::{StashApplyOptions, StashCb, StashApplyProgressCb}; +pub use stash::{StashApplyOptions, StashApplyProgressCb, StashCb}; +pub use status::{StatusEntry, StatusIter, StatusOptions, StatusShow, Statuses}; pub use submodule::{Submodule, SubmoduleUpdateOptions}; pub use tag::Tag; -pub use time::{Time, IndexTime}; +pub use time::{IndexTime, Time}; pub use tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult}; pub use treebuilder::TreeBuilder; -pub use odb::{Odb, OdbObject, OdbReader, OdbWriter}; pub use util::IntoCString; // Create a convinience method on bitflag struct which checks the given flag @@ -491,7 +494,10 @@ bitflags! { impl IndexAddOption { is_bit_set!(is_default, IndexAddOption::DEFAULT); is_bit_set!(is_force, IndexAddOption::FORCE); - is_bit_set!(is_disable_pathspec_match, IndexAddOption::DISABLE_PATHSPEC_MATCH); + is_bit_set!( + is_disable_pathspec_match, + IndexAddOption::DISABLE_PATHSPEC_MATCH + ); is_bit_set!(is_check_pathspec, IndexAddOption::CHECK_PATHSPEC); } @@ -594,15 +600,18 @@ impl MergePreference { is_bit_set!(is_fastforward_only, MergePreference::FASTFORWARD_ONLY); } -#[cfg(test)] #[macro_use] mod test; -#[macro_use] mod panic; +#[cfg(test)] +#[macro_use] +mod test; +#[macro_use] +mod panic; mod call; mod util; pub mod build; pub mod cert; -pub mod string_array; pub mod oid_array; +pub mod string_array; pub mod transport; mod blame; @@ -623,8 +632,8 @@ mod object; mod odb; mod oid; mod packbuilder; -mod pathspec; mod patch; +mod pathspec; mod proxy_options; mod rebase; mod reference; @@ -636,9 +645,9 @@ mod repo; mod revspec; mod revwalk; mod signature; +mod stash; mod status; mod submodule; -mod stash; mod tag; mod time; mod tree; @@ -654,7 +663,12 @@ fn init() { raw::init(); } -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), feature = "https"))] +#[cfg(all( + unix, + not(target_os = "macos"), + not(target_os = "ios"), + feature = "https" +))] fn openssl_env_init() { extern crate openssl_probe; @@ -772,11 +786,15 @@ fn openssl_env_init() { openssl_probe::init_ssl_cert_env_vars(); } -#[cfg(any(windows, target_os = "macos", target_os = "ios", not(feature = "https")))] +#[cfg(any( + windows, + target_os = "macos", + target_os = "ios", + not(feature = "https") +))] fn openssl_env_init() {} -unsafe fn opt_bytes<'a, T>(_anchor: &'a T, - c: *const libc::c_char) -> Option<&'a [u8]> { +unsafe fn opt_bytes<'a, T>(_anchor: &'a T, c: *const libc::c_char) -> Option<&'a [u8]> { if c.is_null() { None } else { @@ -787,7 +805,7 @@ unsafe fn opt_bytes<'a, T>(_anchor: &'a T, fn opt_cstr(o: Option) -> Result, Error> { match o { Some(s) => s.into_c_string().map(Some), - None => Ok(None) + None => Ok(None), } } diff --git a/src/merge.rs b/src/merge.rs index c66ccfd3f2..27a52c90cc 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -1,10 +1,10 @@ +use libc::c_uint; use std::marker; use std::mem; -use libc::c_uint; -use {raw, Oid, Commit, FileFavor}; -use util::Binding; use call::Convert; +use util::Binding; +use {raw, Commit, FileFavor, Oid}; /// A structure to represent an annotated commit, the input to merge and rebase. /// @@ -40,9 +40,7 @@ impl MergeOptions { let mut opts = MergeOptions { raw: unsafe { mem::zeroed() }, }; - assert_eq!(unsafe { - raw::git_merge_init_options(&mut opts.raw, 1) - }, 0); + assert_eq!(unsafe { raw::git_merge_init_options(&mut opts.raw, 1) }, 0); opts } @@ -165,14 +163,15 @@ impl MergeOptions { impl<'repo> Binding for AnnotatedCommit<'repo> { type Raw = *mut raw::git_annotated_commit; - unsafe fn from_raw(raw: *mut raw::git_annotated_commit) - -> AnnotatedCommit<'repo> { + unsafe fn from_raw(raw: *mut raw::git_annotated_commit) -> AnnotatedCommit<'repo> { AnnotatedCommit { raw: raw, _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_annotated_commit { self.raw } + fn raw(&self) -> *mut raw::git_annotated_commit { + self.raw + } } impl<'repo> Drop for AnnotatedCommit<'repo> { diff --git a/src/message.rs b/src/message.rs index 96cdd589cb..b36419e270 100644 --- a/src/message.rs +++ b/src/message.rs @@ -2,24 +2,28 @@ use std::ffi::CString; use libc::{c_char, c_int}; -use {raw, Buf, Error, IntoCString}; use util::Binding; +use {raw, Buf, Error, IntoCString}; /// Clean up a message, removing extraneous whitespace, and ensure that the /// message ends with a newline. If `comment_char` is `Some`, also remove comment /// lines starting with that character. -pub fn message_prettify(message: T, comment_char: Option) - -> Result { +pub fn message_prettify( + message: T, + comment_char: Option, +) -> Result { _message_prettify(try!(message.into_c_string()), comment_char) } -fn _message_prettify(message: CString, comment_char: Option) - -> Result { +fn _message_prettify(message: CString, comment_char: Option) -> Result { let ret = Buf::new(); unsafe { - try_call!(raw::git_message_prettify(ret.raw(), message, - comment_char.is_some() as c_int, - comment_char.unwrap_or(0) as c_char)); + try_call!(raw::git_message_prettify( + ret.raw(), + message, + comment_char.is_some() as c_int, + comment_char.unwrap_or(0) as c_char + )); } Ok(ret.as_str().unwrap().to_string()) } @@ -36,17 +40,22 @@ mod tests { // This does not attempt to duplicate the extensive tests for // git_message_prettify in libgit2, just a few representative values to // make sure the interface works as expected. - assert_eq!(message_prettify("1\n\n\n2", None).unwrap(), - "1\n\n2\n"); - assert_eq!(message_prettify("1\n\n\n2\n\n\n3", None).unwrap(), - "1\n\n2\n\n3\n"); - assert_eq!(message_prettify("1\n# comment\n# more", None).unwrap(), - "1\n# comment\n# more\n"); - assert_eq!(message_prettify("1\n# comment\n# more", - DEFAULT_COMMENT_CHAR).unwrap(), - "1\n"); - assert_eq!(message_prettify("1\n; comment\n; more", - Some(';' as u8)).unwrap(), - "1\n"); + assert_eq!(message_prettify("1\n\n\n2", None).unwrap(), "1\n\n2\n"); + assert_eq!( + message_prettify("1\n\n\n2\n\n\n3", None).unwrap(), + "1\n\n2\n\n3\n" + ); + assert_eq!( + message_prettify("1\n# comment\n# more", None).unwrap(), + "1\n# comment\n# more\n" + ); + assert_eq!( + message_prettify("1\n# comment\n# more", DEFAULT_COMMENT_CHAR).unwrap(), + "1\n" + ); + assert_eq!( + message_prettify("1\n; comment\n; more", Some(';' as u8)).unwrap(), + "1\n" + ); } } diff --git a/src/note.rs b/src/note.rs index 5295e5988f..8bf8a7f8b4 100644 --- a/src/note.rs +++ b/src/note.rs @@ -1,8 +1,8 @@ use std::marker; use std::str; -use {raw, signature, Signature, Oid, Repository, Error}; use util::Binding; +use {raw, signature, Error, Oid, Repository, Signature}; /// A structure representing a [note][note] in git. /// @@ -25,16 +25,12 @@ pub struct Notes<'repo> { impl<'repo> Note<'repo> { /// Get the note author pub fn author(&self) -> Signature { - unsafe { - signature::from_raw_const(self, raw::git_note_author(&*self.raw)) - } + unsafe { signature::from_raw_const(self, raw::git_note_author(&*self.raw)) } } /// Get the note committer pub fn committer(&self) -> Signature { - unsafe { - signature::from_raw_const(self, raw::git_note_committer(&*self.raw)) - } + unsafe { signature::from_raw_const(self, raw::git_note_committer(&*self.raw)) } } /// Get the note message, in bytes. @@ -56,9 +52,14 @@ impl<'repo> Note<'repo> { impl<'repo> Binding for Note<'repo> { type Raw = *mut raw::git_note; unsafe fn from_raw(raw: *mut raw::git_note) -> Note<'repo> { - Note { raw: raw, _marker: marker::PhantomData, } + Note { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_note { + self.raw } - fn raw(&self) -> *mut raw::git_note { self.raw } } impl<'repo> ::std::fmt::Debug for Note<'repo> { @@ -69,35 +70,51 @@ impl<'repo> ::std::fmt::Debug for Note<'repo> { impl<'repo> Drop for Note<'repo> { fn drop(&mut self) { - unsafe { raw::git_note_free(self.raw); } + unsafe { + raw::git_note_free(self.raw); + } } } impl<'repo> Binding for Notes<'repo> { type Raw = *mut raw::git_note_iterator; unsafe fn from_raw(raw: *mut raw::git_note_iterator) -> Notes<'repo> { - Notes { raw: raw, _marker: marker::PhantomData, } + Notes { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_note_iterator { + self.raw } - fn raw(&self) -> *mut raw::git_note_iterator { self.raw } } impl<'repo> Iterator for Notes<'repo> { type Item = Result<(Oid, Oid), Error>; fn next(&mut self) -> Option> { - let mut note_id = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut note_id = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; let mut annotated_id = note_id; unsafe { - try_call_iter!(raw::git_note_next(&mut note_id, &mut annotated_id, - self.raw)); - Some(Ok((Binding::from_raw(¬e_id as *const _), - Binding::from_raw(&annotated_id as *const _)))) + try_call_iter!(raw::git_note_next( + &mut note_id, + &mut annotated_id, + self.raw + )); + Some(Ok(( + Binding::from_raw(¬e_id as *const _), + Binding::from_raw(&annotated_id as *const _), + ))) } } } impl<'repo> Drop for Notes<'repo> { fn drop(&mut self) { - unsafe { raw::git_note_iterator_free(self.raw); } + unsafe { + raw::git_note_iterator_free(self.raw); + } } } diff --git a/src/object.rs b/src/object.rs index 725e4c77fd..023a4aed96 100644 --- a/src/object.rs +++ b/src/object.rs @@ -2,9 +2,9 @@ use std::marker; use std::mem; use std::ptr; -use {raw, Oid, ObjectType, Error, Buf, Commit, Tag, Blob, Tree, Repository}; -use {Describe, DescribeOptions}; use util::Binding; +use {raw, Blob, Buf, Commit, Error, ObjectType, Oid, Repository, Tag, Tree}; +use {Describe, DescribeOptions}; /// A structure to represent a git [object][1] /// @@ -17,9 +17,7 @@ pub struct Object<'repo> { impl<'repo> Object<'repo> { /// Get the id (SHA1) of a repository object pub fn id(&self) -> Oid { - unsafe { - Binding::from_raw(raw::git_object_id(&*self.raw)) - } + unsafe { Binding::from_raw(raw::git_object_id(&*self.raw)) } } /// Get the object type of an object. @@ -44,22 +42,26 @@ impl<'repo> Object<'repo> { /// Recursively peel an object until a blob is found pub fn peel_to_blob(&self) -> Result, Error> { - self.peel(ObjectType::Blob).map(|o| o.cast_or_panic(ObjectType::Blob)) + self.peel(ObjectType::Blob) + .map(|o| o.cast_or_panic(ObjectType::Blob)) } /// Recursively peel an object until a commit is found pub fn peel_to_commit(&self) -> Result, Error> { - self.peel(ObjectType::Commit).map(|o| o.cast_or_panic(ObjectType::Commit)) + self.peel(ObjectType::Commit) + .map(|o| o.cast_or_panic(ObjectType::Commit)) } /// Recursively peel an object until a tag is found pub fn peel_to_tag(&self) -> Result, Error> { - self.peel(ObjectType::Tag).map(|o| o.cast_or_panic(ObjectType::Tag)) + self.peel(ObjectType::Tag) + .map(|o| o.cast_or_panic(ObjectType::Tag)) } /// Recursively peel an object until a tree is found pub fn peel_to_tree(&self) -> Result, Error> { - self.peel(ObjectType::Tree).map(|o| o.cast_or_panic(ObjectType::Tree)) + self.peel(ObjectType::Tree) + .map(|o| o.cast_or_panic(ObjectType::Tree)) } /// Get a short abbreviated OID string for the object @@ -135,8 +137,7 @@ impl<'repo> Object<'repo> { /// Describes a commit /// /// Performs a describe operation on this commitish object. - pub fn describe(&self, opts: &DescribeOptions) - -> Result { + pub fn describe(&self, opts: &DescribeOptions) -> Result { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_describe_commit(&mut ret, self.raw, opts.raw())); @@ -190,7 +191,12 @@ impl<'repo> CastOrPanic for Object<'repo> { &buf } }; - panic!("Expected object {} to be {} but it is {}", self.id(), kind.str(), akind) + panic!( + "Expected object {} to be {} but it is {}", + self.id(), + kind.str(), + akind + ) } } } @@ -211,7 +217,10 @@ impl<'repo> ::std::fmt::Debug for Object<'repo> { let mut ds = f.debug_struct("Object"); match self.kind() { Some(kind) => ds.field("kind", &kind), - None => ds.field("kind", &format!("Unknow ({})", unsafe { raw::git_object_type(&*self.raw) })) + None => ds.field( + "kind", + &format!("Unknow ({})", unsafe { raw::git_object_type(&*self.raw) }), + ), }; ds.field("id", &self.id()); ds.finish() @@ -222,9 +231,14 @@ impl<'repo> Binding for Object<'repo> { type Raw = *mut raw::git_object; unsafe fn from_raw(raw: *mut raw::git_object) -> Object<'repo> { - Object { raw: raw, _marker: marker::PhantomData, } + Object { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_object { + self.raw } - fn raw(&self) -> *mut raw::git_object { self.raw } } impl<'repo> Drop for Object<'repo> { diff --git a/src/odb.rs b/src/odb.rs index 4904a585a0..353a0778d5 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -1,5 +1,5 @@ -use std::marker; use std::io; +use std::marker; use std::ptr; use std::slice; @@ -7,9 +7,9 @@ use std::ffi::CString; use libc::{c_char, c_int, c_void, size_t}; -use {raw, Oid, Object, ObjectType, Error}; use panic; use util::Binding; +use {raw, Error, Object, ObjectType, Oid}; /// A structure to represent a git object database pub struct Odb<'repo> { @@ -26,7 +26,9 @@ impl<'repo> Binding for Odb<'repo> { _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_odb { self.raw } + fn raw(&self) -> *mut raw::git_odb { + self.raw + } } impl<'repo> Drop for Odb<'repo> { @@ -54,8 +56,18 @@ impl<'repo> Odb<'repo> { let mut size = 0usize; let mut otype: raw::git_object_t = ObjectType::Any.raw(); unsafe { - try_call!(raw::git_odb_open_rstream(&mut out, &mut size, &mut otype, self.raw, oid.raw())); - Ok((OdbReader::from_raw(out), size, ObjectType::from_raw(otype).unwrap())) + try_call!(raw::git_odb_open_rstream( + &mut out, + &mut size, + &mut otype, + self.raw, + oid.raw() + )); + Ok(( + OdbReader::from_raw(out), + size, + ObjectType::from_raw(otype).unwrap(), + )) } } @@ -66,20 +78,30 @@ impl<'repo> Odb<'repo> { pub fn writer(&self, size: usize, obj_type: ObjectType) -> Result { let mut out = ptr::null_mut(); unsafe { - try_call!(raw::git_odb_open_wstream(&mut out, self.raw, size as raw::git_off_t, obj_type.raw())); + try_call!(raw::git_odb_open_wstream( + &mut out, + self.raw, + size as raw::git_off_t, + obj_type.raw() + )); Ok(OdbWriter::from_raw(out)) } } /// Iterate over all objects in the object database.s pub fn foreach(&self, mut callback: C) -> Result<(), Error> - where C: FnMut(&Oid) -> bool + where + C: FnMut(&Oid) -> bool, { unsafe { - let mut data = ForeachCbData { callback: &mut callback }; - try_call!(raw::git_odb_foreach(self.raw(), - foreach_cb, - &mut data as *mut _ as *mut _)); + let mut data = ForeachCbData { + callback: &mut callback, + }; + try_call!(raw::git_odb_foreach( + self.raw(), + foreach_cb, + &mut data as *mut _ as *mut _ + )); Ok(()) } } @@ -100,12 +122,12 @@ impl<'repo> Odb<'repo> { let mut kind_id: i32 = ObjectType::Any.raw(); unsafe { - try_call!(raw::git_odb_read_header(&mut size - as *mut size_t, - &mut kind_id - as *mut raw::git_object_t, - self.raw, - oid.raw())); + try_call!(raw::git_odb_read_header( + &mut size as *mut size_t, + &mut kind_id as *mut raw::git_object_t, + self.raw, + oid.raw() + )); Ok((size, ObjectType::from_raw(kind_id).unwrap())) } @@ -114,13 +136,16 @@ impl<'repo> Odb<'repo> { /// Write an object to the database. pub fn write(&self, kind: ObjectType, data: &[u8]) -> Result { unsafe { - let mut out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; - try_call!(raw::git_odb_write(&mut out, - self.raw, - data.as_ptr() - as *const c_void, - data.len(), - kind.raw())); + let mut out = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; + try_call!(raw::git_odb_write( + &mut out, + self.raw, + data.as_ptr() as *const c_void, + data.len(), + kind.raw() + )); Ok(Oid::from_raw(&mut out)) } } @@ -133,14 +158,18 @@ impl<'repo> Odb<'repo> { /// Potentially finds an object that starts with the given prefix. pub fn exists_prefix(&self, short_oid: Oid, len: usize) -> Result { unsafe { - let mut out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; - try_call!(raw::git_odb_exists_prefix(&mut out, - self.raw, - short_oid.raw(), - len)); + let mut out = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; + try_call!(raw::git_odb_exists_prefix( + &mut out, + self.raw, + short_oid.raw(), + len + )); Ok(Oid::from_raw(&out)) } - } + } /// Refresh the object database. /// This should never be needed, and is @@ -181,7 +210,9 @@ impl<'a> Binding for OdbObject<'a> { } } - fn raw(&self) -> *mut raw::git_odb_object { self.raw } + fn raw(&self) -> *mut raw::git_odb_object { + self.raw + } } impl<'a> Drop for OdbObject<'a> { @@ -205,7 +236,7 @@ impl<'a> OdbObject<'a> { pub fn data(&self) -> &[u8] { unsafe { let size = self.len(); - let ptr : *const u8 = raw::git_odb_object_data(self.raw) as *const u8; + let ptr: *const u8 = raw::git_odb_object_data(self.raw) as *const u8; let buffer = slice::from_raw_parts(ptr, size); return buffer; } @@ -232,7 +263,9 @@ impl<'repo> Binding for OdbReader<'repo> { _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_odb_stream { self.raw } + fn raw(&self) -> *mut raw::git_odb_stream { + self.raw + } } impl<'repo> Drop for OdbReader<'repo> { @@ -270,7 +303,9 @@ impl<'repo> OdbWriter<'repo> { /// This method will fail if the total number of received bytes differs from the size declared with odb_writer() /// Attepting write after finishing will be ignored. pub fn finalize(&mut self) -> Result { - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { try_call!(raw::git_odb_stream_finalize_write(&mut raw, self.raw)); Ok(Binding::from_raw(&raw as *const _)) @@ -287,7 +322,9 @@ impl<'repo> Binding for OdbWriter<'repo> { _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_odb_stream { self.raw } + fn raw(&self) -> *mut raw::git_odb_stream { + self.raw + } } impl<'repo> Drop for OdbWriter<'repo> { @@ -309,19 +346,18 @@ impl<'repo> io::Write for OdbWriter<'repo> { } } } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } pub type ForeachCb<'a> = dyn FnMut(&Oid) -> bool + 'a; struct ForeachCbData<'a> { - pub callback: &'a mut ForeachCb<'a> + pub callback: &'a mut ForeachCb<'a>, } -extern fn foreach_cb(id: *const raw::git_oid, - payload: *mut c_void) - -> c_int -{ +extern "C" fn foreach_cb(id: *const raw::git_oid, payload: *mut c_void) -> c_int { panic::wrap(|| unsafe { let data = &mut *(payload as *mut ForeachCbData); let res = { @@ -329,15 +365,20 @@ extern fn foreach_cb(id: *const raw::git_oid, callback(&Binding::from_raw(id)) }; - if res { 0 } else { 1 } - }).unwrap_or(1) + if res { + 0 + } else { + 1 + } + }) + .unwrap_or(1) } #[cfg(test)] mod tests { use std::io::prelude::*; use tempdir::TempDir; - use {Repository, ObjectType, Oid}; + use {ObjectType, Oid, Repository}; #[test] fn read() { @@ -375,7 +416,7 @@ mod tests { let db = repo.odb().unwrap(); let id = db.write(ObjectType::Blob, &dat).unwrap(); let blob = repo.find_blob(id).unwrap(); - assert_eq!(blob.content(), dat); + assert_eq!(blob.content(), dat); } #[test] diff --git a/src/oid.rs b/src/oid.rs index c7fc658316..6af1296613 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -1,18 +1,18 @@ -use std::fmt; +use libc; use std::cmp::Ordering; -use std::hash::{Hasher, Hash}; -use std::str; +use std::fmt; +use std::hash::{Hash, Hasher}; use std::path::Path; -use libc; +use std::str; -use {raw, Error, ObjectType, IntoCString}; +use {raw, Error, IntoCString, ObjectType}; use util::{c_cmp_to_ordering, Binding}; /// Unique identity of any object (commit, tree, blob, tag). #[derive(Copy, Clone)] pub struct Oid { - raw: raw::git_oid + raw: raw::git_oid, } impl Oid { @@ -24,12 +24,15 @@ impl Oid { /// characters, or contains any non-hex characters. pub fn from_str(s: &str) -> Result { ::init(); - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { - try_call!(raw::git_oid_fromstrn(&mut raw, - s.as_bytes().as_ptr() - as *const libc::c_char, - s.len() as libc::size_t)); + try_call!(raw::git_oid_fromstrn( + &mut raw, + s.as_bytes().as_ptr() as *const libc::c_char, + s.len() as libc::size_t + )); } Ok(Oid { raw: raw }) } @@ -39,7 +42,9 @@ impl Oid { /// If the array given is not 20 bytes in length, an error is returned. pub fn from_bytes(bytes: &[u8]) -> Result { ::init(); - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; if bytes.len() != raw::GIT_OID_RAWSZ { Err(Error::from_str("raw byte array must be 20 bytes")) } else { @@ -50,7 +55,9 @@ impl Oid { /// Creates an all zero Oid structure. pub fn zero() -> Oid { - let out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let out = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; Oid { raw: out } } @@ -60,13 +67,16 @@ impl Oid { pub fn hash_object(kind: ObjectType, bytes: &[u8]) -> Result { ::init(); - let mut out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut out = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { - try_call!(raw::git_odb_hash(&mut out, - bytes.as_ptr() - as *const libc::c_void, - bytes.len(), - kind.raw())); + try_call!(raw::git_odb_hash( + &mut out, + bytes.as_ptr() as *const libc::c_void, + bytes.len(), + kind.raw() + )); } Ok(Oid { raw: out }) @@ -80,18 +90,20 @@ impl Oid { let rpath = try!(path.as_ref().into_c_string()); - let mut out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut out = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { - try_call!(raw::git_odb_hashfile(&mut out, - rpath, - kind.raw())); + try_call!(raw::git_odb_hashfile(&mut out, rpath, kind.raw())); } Ok(Oid { raw: out }) } /// View this OID as a byte-slice 20 bytes in length. - pub fn as_bytes(&self) -> &[u8] { &self.raw.id } + pub fn as_bytes(&self) -> &[u8] { + &self.raw.id + } /// Test if this OID is all zeros. pub fn is_zero(&self) -> bool { @@ -105,7 +117,9 @@ impl Binding for Oid { unsafe fn from_raw(oid: *const raw::git_oid) -> Oid { Oid { raw: *oid } } - fn raw(&self) -> *const raw::git_oid { &self.raw as *const _ } + fn raw(&self) -> *const raw::git_oid { + &self.raw as *const _ + } } impl fmt::Debug for Oid { @@ -119,8 +133,11 @@ impl fmt::Display for Oid { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut dst = [0u8; raw::GIT_OID_HEXSZ + 1]; unsafe { - raw::git_oid_tostr(dst.as_mut_ptr() as *mut libc::c_char, - dst.len() as libc::size_t, &self.raw); + raw::git_oid_tostr( + dst.as_mut_ptr() as *mut libc::c_char, + dst.len() as libc::size_t, + &self.raw, + ); } let s = &dst[..dst.iter().position(|&a| a == 0).unwrap()]; str::from_utf8(s).unwrap().fmt(f) @@ -167,18 +184,20 @@ impl Hash for Oid { } impl AsRef<[u8]> for Oid { - fn as_ref(&self) -> &[u8] { self.as_bytes() } + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } } #[cfg(test)] mod tests { - use std::io::prelude::*; use std::fs::File; + use std::io::prelude::*; - use tempdir::TempDir; - use {ObjectType}; use super::Error; use super::Oid; + use tempdir::TempDir; + use ObjectType; #[test] fn conversions() { @@ -234,4 +253,3 @@ mod tests { assert!(Oid::hash_file(ObjectType::Blob, &path).is_ok()); } } - diff --git a/src/oid_array.rs b/src/oid_array.rs index d1108e6c55..1a369abd07 100644 --- a/src/oid_array.rs +++ b/src/oid_array.rs @@ -4,9 +4,9 @@ use std::ops::Deref; use oid::Oid; use raw; -use util::Binding; -use std::slice; use std::mem; +use std::slice; +use util::Binding; /// An oid array structure used by libgit2 /// @@ -23,7 +23,7 @@ impl Deref for OidArray { fn deref(&self) -> &[Oid] { unsafe { debug_assert_eq!(mem::size_of::(), mem::size_of_val(&*self.raw.ids)); - + slice::from_raw_parts(self.raw.ids as *const Oid, self.raw.count as usize) } } @@ -34,12 +34,14 @@ impl Binding for OidArray { unsafe fn from_raw(raw: raw::git_oidarray) -> OidArray { OidArray { raw: raw } } - fn raw(&self) -> raw::git_oidarray { self.raw } + fn raw(&self) -> raw::git_oidarray { + self.raw + } } impl<'repo> ::std::fmt::Debug for OidArray { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - f.debug_tuple("OidArray").field(&self.deref()).finish() + f.debug_tuple("OidArray").field(&self.deref()).finish() } } diff --git a/src/packbuilder.rs b/src/packbuilder.rs index 1d03fbed44..1890cf9c54 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -1,10 +1,10 @@ +use libc::{c_int, c_uint, c_void, size_t}; use std::marker; use std::ptr; use std::slice; -use libc::{c_int, c_uint, c_void, size_t}; -use {raw, panic, Repository, Error, Oid, Revwalk, Buf}; use util::Binding; +use {panic, raw, Buf, Error, Oid, Repository, Revwalk}; /// Stages that are reported by the `PackBuilder` progress callback. pub enum PackBuilderStage { @@ -27,8 +27,7 @@ pub struct PackBuilder<'repo> { impl<'repo> PackBuilder<'repo> { /// Insert a single object. For an optimal pack it's mandatory to insert /// objects in recency order, commits followed by trees and blobs. - pub fn insert_object(&mut self, id: Oid, name: Option<&str>) - -> Result<(), Error> { + pub fn insert_object(&mut self, id: Oid, name: Option<&str>) -> Result<(), Error> { let name = try!(::opt_cstr(name)); unsafe { try_call!(raw::git_packbuilder_insert(self.raw, id.raw(), name)); @@ -65,13 +64,10 @@ impl<'repo> PackBuilder<'repo> { /// Recursively insert an object and its referenced objects. Insert the /// object as well as any object it references. - pub fn insert_recursive(&mut self, id: Oid, name: Option<&str>) - -> Result<(), Error> { + pub fn insert_recursive(&mut self, id: Oid, name: Option<&str>) -> Result<(), Error> { let name = try!(::opt_cstr(name)); unsafe { - try_call!(raw::git_packbuilder_insert_recur(self.raw, - id.raw(), - name)); + try_call!(raw::git_packbuilder_insert_recur(self.raw, id.raw(), name)); } Ok(()) } @@ -88,14 +84,17 @@ impl<'repo> PackBuilder<'repo> { /// Create the new pack and pass each object to the callback. pub fn foreach(&mut self, mut cb: F) -> Result<(), Error> - where F: FnMut(&[u8]) -> bool + where + F: FnMut(&[u8]) -> bool, { let mut cb = &mut cb as &mut ForEachCb; let ptr = &mut cb as *mut _; unsafe { - try_call!(raw::git_packbuilder_foreach(self.raw, - foreach_c, - ptr as *mut _)); + try_call!(raw::git_packbuilder_foreach( + self.raw, + foreach_c, + ptr as *mut _ + )); } Ok(()) } @@ -108,15 +107,18 @@ impl<'repo> PackBuilder<'repo> { /// existing one. See `unset_progress_callback` to remove the current /// progress callback without attaching a new one. pub fn set_progress_callback(&mut self, progress: F) -> Result<(), Error> - where F: FnMut(PackBuilderStage, u32, u32) -> bool + 'repo + where + F: FnMut(PackBuilderStage, u32, u32) -> bool + 'repo, { let mut progress = Box::new(Box::new(progress) as Box); let ptr = &mut *progress as *mut _; let progress_c = Some(progress_c as raw::git_packbuilder_progress); unsafe { - try_call!(raw::git_packbuilder_set_callbacks(self.raw, - progress_c, - ptr as *mut _)); + try_call!(raw::git_packbuilder_set_callbacks( + self.raw, + progress_c, + ptr as *mut _ + )); } self.progress = Some(progress); Ok(()) @@ -126,9 +128,11 @@ impl<'repo> PackBuilder<'repo> { /// set the progress callback. pub fn unset_progress_callback(&mut self) -> Result<(), Error> { unsafe { - try_call!(raw::git_packbuilder_set_callbacks(self.raw, - None, - ptr::null_mut())); + try_call!(raw::git_packbuilder_set_callbacks( + self.raw, + None, + ptr::null_mut() + )); self.progress = None; } Ok(()) @@ -149,9 +153,7 @@ impl<'repo> PackBuilder<'repo> { /// has been written. pub fn hash(&self) -> Option { if self.object_count() == 0 { - unsafe { - Some(Binding::from_raw(raw::git_packbuilder_hash(self.raw))) - } + unsafe { Some(Binding::from_raw(raw::git_packbuilder_hash(self.raw))) } } else { None } @@ -198,10 +200,7 @@ impl Binding for PackBuilderStage { } } -extern fn foreach_c(buf: *const c_void, - size: size_t, - data: *mut c_void) - -> c_int { +extern "C" fn foreach_c(buf: *const c_void, size: size_t, data: *mut c_void) -> c_int { unsafe { let buf = slice::from_raw_parts(buf as *const u8, size as usize); @@ -217,11 +216,12 @@ extern fn foreach_c(buf: *const c_void, } } -extern fn progress_c(stage: raw::git_packbuilder_stage_t, - current: c_uint, - total: c_uint, - data: *mut c_void) - -> c_int { +extern "C" fn progress_c( + stage: raw::git_packbuilder_stage_t, + current: c_uint, + total: c_uint, + data: *mut c_void, +) -> c_int { unsafe { let stage = Binding::from_raw(stage); @@ -241,7 +241,7 @@ extern fn progress_c(stage: raw::git_packbuilder_stage_t, mod tests { use std::fs::File; use std::path::Path; - use {Buf, Repository, Oid}; + use {Buf, Oid, Repository}; fn commit(repo: &Repository) -> (Oid, Oid) { let mut index = t!(repo.index()); @@ -254,30 +254,30 @@ mod tests { let sig = t!(repo.signature()); let head_id = t!(repo.refname_to_id("HEAD")); let parent = t!(repo.find_commit(head_id)); - let commit = t!(repo.commit(Some("HEAD"), - &sig, - &sig, - "commit", - &tree, - &[&parent])); + let commit = t!(repo.commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent])); (commit, tree_id) } fn pack_header(len: u8) -> Vec { [].into_iter() - .chain(b"PACK") // signature - .chain(&[0, 0, 0, 2]) // version number - .chain(&[0, 0, 0, len]) // number of objects - .cloned().collect::>() + .chain(b"PACK") // signature + .chain(&[0, 0, 0, 2]) // version number + .chain(&[0, 0, 0, len]) // number of objects + .cloned() + .collect::>() } fn empty_pack_header() -> Vec { - pack_header(0).iter() - .chain(&[0x02, 0x9d, 0x08, 0x82, 0x3b, // ^ - 0xd8, 0xa8, 0xea, 0xb5, 0x10, // | SHA-1 of the zero - 0xad, 0x6a, 0xc7, 0x5c, 0x82, // | object pack header - 0x3c, 0xfd, 0x3e, 0xd3, 0x1e]) // v - .cloned().collect::>() + pack_header(0) + .iter() + .chain(&[ + 0x02, 0x9d, 0x08, 0x82, 0x3b, // ^ + 0xd8, 0xa8, 0xea, 0xb5, 0x10, // | SHA-1 of the zero + 0xad, 0x6a, 0xc7, 0x5c, 0x82, // | object pack header + 0x3c, 0xfd, 0x3e, 0xd3, 0x1e, + ]) // v + .cloned() + .collect::>() } #[test] diff --git a/src/panic.rs b/src/panic.rs index c11de3a6f8..3d7c235029 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -8,7 +8,7 @@ thread_local!(static LAST_ERROR: RefCell>> = { pub fn wrap T + ::std::panic::UnwindSafe>(f: F) -> Option { use std::panic; if LAST_ERROR.with(|slot| slot.borrow().is_some()) { - return None + return None; } match panic::catch_unwind(f) { Ok(ret) => Some(ret), diff --git a/src/patch.rs b/src/patch.rs index af7e74ac18..c0ac9af528 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -1,10 +1,10 @@ +use libc::{c_int, c_void}; use std::path::Path; use std::ptr; -use libc::{c_int, c_void}; +use diff::{print_cb, LineCb}; +use util::{into_opt_c_string, Binding}; use {raw, Blob, Buf, Diff, DiffDelta, DiffHunk, DiffLine, DiffOptions, Error}; -use diff::{LineCb, print_cb}; -use util::{Binding, into_opt_c_string}; /// A structure representing the text changes in a single diff delta. /// @@ -20,7 +20,9 @@ impl Binding for Patch { unsafe fn from_raw(raw: Self::Raw) -> Patch { Patch { raw: raw } } - fn raw(&self) -> Self::Raw { self.raw } + fn raw(&self) -> Self::Raw { + self.raw + } } impl Drop for Patch { @@ -42,86 +44,88 @@ impl Patch { } /// Generate a Patch by diffing two blobs. - pub fn from_blobs(old_blob: &Blob, - old_path: Option<&Path>, - new_blob: &Blob, - new_path: Option<&Path>, - opts: Option<&mut DiffOptions>) - -> Result - { + pub fn from_blobs( + old_blob: &Blob, + old_path: Option<&Path>, + new_blob: &Blob, + new_path: Option<&Path>, + opts: Option<&mut DiffOptions>, + ) -> Result { let mut ret = ptr::null_mut(); let old_path = try!(into_opt_c_string(old_path)); let new_path = try!(into_opt_c_string(new_path)); unsafe { - try_call!(raw::git_patch_from_blobs(&mut ret, - old_blob.raw(), - old_path, - new_blob.raw(), - new_path, - opts.map(|s| s.raw()))); + try_call!(raw::git_patch_from_blobs( + &mut ret, + old_blob.raw(), + old_path, + new_blob.raw(), + new_path, + opts.map(|s| s.raw()) + )); Ok(Binding::from_raw(ret)) } } /// Generate a Patch by diffing a blob and a buffer. - pub fn from_blob_and_buffer(old_blob: &Blob, - old_path: Option<&Path>, - new_buffer: &[u8], - new_path: Option<&Path>, - opts: Option<&mut DiffOptions>) - -> Result - { + pub fn from_blob_and_buffer( + old_blob: &Blob, + old_path: Option<&Path>, + new_buffer: &[u8], + new_path: Option<&Path>, + opts: Option<&mut DiffOptions>, + ) -> Result { let mut ret = ptr::null_mut(); let old_path = try!(into_opt_c_string(old_path)); let new_path = try!(into_opt_c_string(new_path)); unsafe { - try_call!(raw::git_patch_from_blob_and_buffer(&mut ret, - old_blob.raw(), - old_path, - new_buffer.as_ptr() as *const c_void, - new_buffer.len(), - new_path, - opts.map(|s| s.raw()))); + try_call!(raw::git_patch_from_blob_and_buffer( + &mut ret, + old_blob.raw(), + old_path, + new_buffer.as_ptr() as *const c_void, + new_buffer.len(), + new_path, + opts.map(|s| s.raw()) + )); Ok(Binding::from_raw(ret)) } } /// Generate a Patch by diffing two buffers. - pub fn from_buffers(old_buffer: &[u8], - old_path: Option<&Path>, - new_buffer: &[u8], - new_path: Option<&Path>, - opts: Option<&mut DiffOptions>) - -> Result - { + pub fn from_buffers( + old_buffer: &[u8], + old_path: Option<&Path>, + new_buffer: &[u8], + new_path: Option<&Path>, + opts: Option<&mut DiffOptions>, + ) -> Result { let mut ret = ptr::null_mut(); let old_path = try!(into_opt_c_string(old_path)); let new_path = try!(into_opt_c_string(new_path)); unsafe { - try_call!(raw::git_patch_from_buffers(&mut ret, - old_buffer.as_ptr() as *const c_void, - old_buffer.len(), - old_path, - new_buffer.as_ptr() as *const c_void, - new_buffer.len(), - new_path, - opts.map(|s| s.raw()))); + try_call!(raw::git_patch_from_buffers( + &mut ret, + old_buffer.as_ptr() as *const c_void, + old_buffer.len(), + old_path, + new_buffer.as_ptr() as *const c_void, + new_buffer.len(), + new_path, + opts.map(|s| s.raw()) + )); Ok(Binding::from_raw(ret)) } } /// Get the DiffDelta associated with the Patch. pub fn delta(&self) -> DiffDelta { - unsafe { - Binding::from_raw(raw::git_patch_get_delta(self.raw) as *mut _) - } + unsafe { Binding::from_raw(raw::git_patch_get_delta(self.raw) as *mut _) } } /// Get the number of hunks in the Patch. pub fn num_hunks(&self) -> usize { - unsafe { - raw::git_patch_num_hunks(self.raw) - } + unsafe { raw::git_patch_num_hunks(self.raw) } } /// Get the number of lines of context, additions, and deletions in the Patch. @@ -130,10 +134,12 @@ impl Patch { let mut additions = 0; let mut deletions = 0; unsafe { - try_call!(raw::git_patch_line_stats(&mut context, - &mut additions, - &mut deletions, - self.raw)); + try_call!(raw::git_patch_line_stats( + &mut context, + &mut additions, + &mut deletions, + self.raw + )); } Ok((context, additions, deletions)) } @@ -143,42 +149,46 @@ impl Patch { let mut ret = ptr::null(); let mut lines = 0; unsafe { - try_call!(raw::git_patch_get_hunk(&mut ret, &mut lines, self.raw, hunk_idx)); + try_call!(raw::git_patch_get_hunk( + &mut ret, &mut lines, self.raw, hunk_idx + )); Ok((Binding::from_raw(ret), lines)) } } /// Get the number of lines in a hunk. pub fn num_lines_in_hunk(&self, hunk_idx: usize) -> Result { - unsafe { - Ok(try_call!(raw::git_patch_num_lines_in_hunk(self.raw, hunk_idx)) as usize) - } + unsafe { Ok(try_call!(raw::git_patch_num_lines_in_hunk(self.raw, hunk_idx)) as usize) } } /// Get a DiffLine from a hunk of the Patch. - pub fn line_in_hunk(&self, - hunk_idx: usize, - line_of_hunk: usize) -> Result { + pub fn line_in_hunk(&self, hunk_idx: usize, line_of_hunk: usize) -> Result { let mut ret = ptr::null(); unsafe { - try_call!(raw::git_patch_get_line_in_hunk(&mut ret, - self.raw, - hunk_idx, - line_of_hunk)); + try_call!(raw::git_patch_get_line_in_hunk( + &mut ret, + self.raw, + hunk_idx, + line_of_hunk + )); Ok(Binding::from_raw(ret)) } } /// Get the size of a Patch's diff data in bytes. - pub fn size(&self, - include_context: bool, - include_hunk_headers: bool, - include_file_headers: bool) -> usize { + pub fn size( + &self, + include_context: bool, + include_hunk_headers: bool, + include_file_headers: bool, + ) -> usize { unsafe { - raw::git_patch_size(self.raw, - include_context as c_int, - include_hunk_headers as c_int, - include_file_headers as c_int) + raw::git_patch_size( + self.raw, + include_context as c_int, + include_hunk_headers as c_int, + include_file_headers as c_int, + ) } } diff --git a/src/pathspec.rs b/src/pathspec.rs index 5cc03ab3b8..26a68afb2e 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -1,12 +1,12 @@ +use libc::size_t; use std::iter::IntoIterator; use std::marker; use std::ops::Range; use std::path::Path; use std::ptr; -use libc::size_t; -use {raw, Error, Diff, Tree, PathspecFlags, Index, Repository, DiffDelta, IntoCString}; use util::Binding; +use {raw, Diff, DiffDelta, Error, Index, IntoCString, PathspecFlags, Repository, Tree}; /// Structure representing a compiled pathspec used for matching against various /// structures. @@ -41,7 +41,10 @@ pub struct PathspecFailedEntries<'list> { impl Pathspec { /// Creates a new pathspec from a list of specs to match against. pub fn new(specs: I) -> Result - where T: IntoCString, I: IntoIterator { + where + T: IntoCString, + I: IntoIterator, + { let (_a, _b, arr) = try!(::util::iter2cstrs(specs)); unsafe { let mut ret = ptr::null_mut(); @@ -56,12 +59,19 @@ impl Pathspec { /// pass `PATHSPEC_FAILURES_ONLY` in the flags) and may also contain the /// list of pathspecs with no match if the `PATHSPEC_FIND_FAILURES` flag is /// specified. - pub fn match_diff(&self, diff: &Diff, flags: PathspecFlags) - -> Result { + pub fn match_diff( + &self, + diff: &Diff, + flags: PathspecFlags, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_pathspec_match_diff(&mut ret, diff.raw(), - flags.bits(), self.raw)); + try_call!(raw::git_pathspec_match_diff( + &mut ret, + diff.raw(), + flags.bits(), + self.raw + )); Ok(Binding::from_raw(ret)) } } @@ -72,12 +82,19 @@ impl Pathspec { /// pass `PATHSPEC_FAILURES_ONLY` in the flags) and may also contain the /// list of pathspecs with no match if the `PATHSPEC_FIND_FAILURES` flag is /// specified. - pub fn match_tree(&self, tree: &Tree, flags: PathspecFlags) - -> Result { + pub fn match_tree( + &self, + tree: &Tree, + flags: PathspecFlags, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_pathspec_match_tree(&mut ret, tree.raw(), - flags.bits(), self.raw)); + try_call!(raw::git_pathspec_match_tree( + &mut ret, + tree.raw(), + flags.bits(), + self.raw + )); Ok(Binding::from_raw(ret)) } } @@ -88,12 +105,19 @@ impl Pathspec { /// pass `PATHSPEC_FAILURES_ONLY` in the flags) and may also contain the /// list of pathspecs with no match if the `PATHSPEC_FIND_FAILURES` flag is /// specified. - pub fn match_index(&self, index: &Index, flags: PathspecFlags) - -> Result { + pub fn match_index( + &self, + index: &Index, + flags: PathspecFlags, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_pathspec_match_index(&mut ret, index.raw(), - flags.bits(), self.raw)); + try_call!(raw::git_pathspec_match_index( + &mut ret, + index.raw(), + flags.bits(), + self.raw + )); Ok(Binding::from_raw(ret)) } } @@ -110,12 +134,19 @@ impl Pathspec { /// pass `PATHSPEC_FAILURES_ONLY` in the flags) and may also contain the /// list of pathspecs with no match if the `PATHSPEC_FIND_FAILURES` flag is /// specified. - pub fn match_workdir(&self, repo: &Repository, flags: PathspecFlags) - -> Result { + pub fn match_workdir( + &self, + repo: &Repository, + flags: PathspecFlags, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_pathspec_match_workdir(&mut ret, repo.raw(), - flags.bits(), self.raw)); + try_call!(raw::git_pathspec_match_workdir( + &mut ret, + repo.raw(), + flags.bits(), + self.raw + )); Ok(Binding::from_raw(ret)) } } @@ -128,10 +159,7 @@ impl Pathspec { /// back on being case sensitive. pub fn matches_path(&self, path: &Path, flags: PathspecFlags) -> bool { let path = path.into_c_string().unwrap(); - unsafe { - raw::git_pathspec_matches_path(&*self.raw, flags.bits(), - path.as_ptr()) == 1 - } + unsafe { raw::git_pathspec_matches_path(&*self.raw, flags.bits(), path.as_ptr()) == 1 } } } @@ -141,7 +169,9 @@ impl Binding for Pathspec { unsafe fn from_raw(raw: *mut raw::git_pathspec) -> Pathspec { Pathspec { raw: raw } } - fn raw(&self) -> *mut raw::git_pathspec { self.raw } + fn raw(&self) -> *mut raw::git_pathspec { + self.raw + } } impl Drop for Pathspec { @@ -162,8 +192,15 @@ impl<'ps> PathspecMatchList<'ps> { /// Returns an iterator over the matching filenames in this list. pub fn entries(&self) -> PathspecEntries { let n = self.entrycount(); - let n = if n > 0 && self.entry(0).is_none() {0} else {n}; - PathspecEntries { range: 0..n, list: self } + let n = if n > 0 && self.entry(0).is_none() { + 0 + } else { + n + }; + PathspecEntries { + range: 0..n, + list: self, + } } /// Get a matching filename by position. @@ -180,8 +217,15 @@ impl<'ps> PathspecMatchList<'ps> { /// Returns an iterator over the matching diff entries in this list. pub fn diff_entries(&self) -> PathspecDiffEntries { let n = self.entrycount(); - let n = if n > 0 && self.diff_entry(0).is_none() {0} else {n}; - PathspecDiffEntries { range: 0..n, list: self } + let n = if n > 0 && self.diff_entry(0).is_none() { + 0 + } else { + n + }; + PathspecDiffEntries { + range: 0..n, + list: self, + } } /// Get a matching diff delta by position. @@ -190,8 +234,7 @@ impl<'ps> PathspecMatchList<'ps> { /// always be `None`. pub fn diff_entry(&self, i: usize) -> Option { unsafe { - let ptr = raw::git_pathspec_match_list_diff_entry(&*self.raw, - i as size_t); + let ptr = raw::git_pathspec_match_list_diff_entry(&*self.raw, i as size_t); Binding::from_raw_opt(ptr as *mut _) } } @@ -199,15 +242,21 @@ impl<'ps> PathspecMatchList<'ps> { /// Returns an iterator over the non-matching entries in this list. pub fn failed_entries(&self) -> PathspecFailedEntries { let n = self.failed_entrycount(); - let n = if n > 0 && self.failed_entry(0).is_none() {0} else {n}; - PathspecFailedEntries { range: 0..n, list: self } + let n = if n > 0 && self.failed_entry(0).is_none() { + 0 + } else { + n + }; + PathspecFailedEntries { + range: 0..n, + list: self, + } } /// Get an original pathspec string that had no matches. pub fn failed_entry(&self, i: usize) -> Option<&[u8]> { unsafe { - let ptr = raw::git_pathspec_match_list_failed_entry(&*self.raw, - i as size_t); + let ptr = raw::git_pathspec_match_list_failed_entry(&*self.raw, i as size_t); ::opt_bytes(self, ptr) } } @@ -216,11 +265,15 @@ impl<'ps> PathspecMatchList<'ps> { impl<'ps> Binding for PathspecMatchList<'ps> { type Raw = *mut raw::git_pathspec_match_list; - unsafe fn from_raw(raw: *mut raw::git_pathspec_match_list) - -> PathspecMatchList<'ps> { - PathspecMatchList { raw: raw, _marker: marker::PhantomData } + unsafe fn from_raw(raw: *mut raw::git_pathspec_match_list) -> PathspecMatchList<'ps> { + PathspecMatchList { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_pathspec_match_list { + self.raw } - fn raw(&self) -> *mut raw::git_pathspec_match_list { self.raw } } impl<'ps> Drop for PathspecMatchList<'ps> { @@ -234,7 +287,9 @@ impl<'list> Iterator for PathspecEntries<'list> { fn next(&mut self) -> Option<&'list [u8]> { self.range.next().and_then(|i| self.list.entry(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'list> DoubleEndedIterator for PathspecEntries<'list> { fn next_back(&mut self) -> Option<&'list [u8]> { @@ -248,7 +303,9 @@ impl<'list> Iterator for PathspecDiffEntries<'list> { fn next(&mut self) -> Option> { self.range.next().and_then(|i| self.list.diff_entry(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'list> DoubleEndedIterator for PathspecDiffEntries<'list> { fn next_back(&mut self) -> Option> { @@ -262,21 +319,25 @@ impl<'list> Iterator for PathspecFailedEntries<'list> { fn next(&mut self) -> Option<&'list [u8]> { self.range.next().and_then(|i| self.list.failed_entry(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'list> DoubleEndedIterator for PathspecFailedEntries<'list> { fn next_back(&mut self) -> Option<&'list [u8]> { - self.range.next_back().and_then(|i| self.list.failed_entry(i)) + self.range + .next_back() + .and_then(|i| self.list.failed_entry(i)) } } impl<'list> ExactSizeIterator for PathspecFailedEntries<'list> {} #[cfg(test)] mod tests { - use PathspecFlags; use super::Pathspec; use std::fs::File; use std::path::Path; + use PathspecFlags; #[test] fn smoke() { @@ -294,7 +355,9 @@ mod tests { File::create(&td.path().join("a")).unwrap(); - let list = ps.match_workdir(&repo, ::PathspecFlags::FIND_FAILURES).unwrap(); + let list = ps + .match_workdir(&repo, ::PathspecFlags::FIND_FAILURES) + .unwrap(); assert_eq!(list.entries().len(), 1); assert_eq!(list.entries().next(), Some("a".as_bytes())); } diff --git a/src/rebase.rs b/src/rebase.rs index ea2344198c..3d9b574905 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -1,9 +1,9 @@ -use std::{marker, ptr, mem, str}; use std::ffi::CString; +use std::{marker, mem, ptr, str}; -use {raw, Oid, Error, Signature, MergeOptions, Index}; use build::CheckoutBuilder; use util::Binding; +use {raw, Error, Index, MergeOptions, Oid, Signature}; /// Rebase options /// @@ -28,9 +28,7 @@ impl<'cb> RebaseOptions<'cb> { merge_options: None, checkout_options: None, }; - assert_eq!(unsafe { - raw::git_rebase_init_options(&mut opts.raw, 1) - }, 0); + assert_eq!(unsafe { raw::git_rebase_init_options(&mut opts.raw, 1) }, 0); opts } @@ -95,7 +93,6 @@ impl<'cb> RebaseOptions<'cb> { } &self.raw } - } /// Representation of a rebase @@ -104,7 +101,7 @@ pub struct Rebase<'repo> { _marker: marker::PhantomData<&'repo raw::git_rebase>, } -impl <'repo> Rebase<'repo> { +impl<'repo> Rebase<'repo> { /// Gets the count of rebase operations that are to be applied. pub fn len(&self) -> usize { unsafe { raw::git_rebase_operation_entrycount(self.raw) } @@ -153,11 +150,23 @@ impl <'repo> Rebase<'repo> { /// were introduced during the patch application from the `git_rebase_next` /// invocation. To keep the author and message from the original commit leave /// them as None - pub fn commit(&mut self, author: Option<&Signature>, committer: &Signature, message: Option<&str>) -> Result { + pub fn commit( + &mut self, + author: Option<&Signature>, + committer: &Signature, + message: Option<&str>, + ) -> Result { let mut id: raw::git_oid = unsafe { mem::zeroed() }; let message = try!(::opt_cstr(message)); unsafe { - try_call!(raw::git_rebase_commit(&mut id, self.raw, author.map(|a| a.raw()), committer.raw(), ptr::null(), message)); + try_call!(raw::git_rebase_commit( + &mut id, + self.raw, + author.map(|a| a.raw()), + committer.raw(), + ptr::null(), + message + )); Ok(Binding::from_raw(&id as *const _)) } } @@ -183,7 +192,7 @@ impl <'repo> Rebase<'repo> { } } -impl <'rebase> Iterator for Rebase<'rebase> { +impl<'rebase> Iterator for Rebase<'rebase> { type Item = Result, Error>; /// Performs the next rebase operation and returns the information about it. @@ -200,20 +209,19 @@ impl <'rebase> Iterator for Rebase<'rebase> { } } - impl<'repo> Binding for Rebase<'repo> { type Raw = *mut raw::git_rebase; - unsafe fn from_raw(raw: *mut raw::git_rebase) - -> Rebase<'repo> { + unsafe fn from_raw(raw: *mut raw::git_rebase) -> Rebase<'repo> { Rebase { raw: raw, _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_rebase { self.raw } + fn raw(&self) -> *mut raw::git_rebase { + self.raw + } } - impl<'repo> Drop for Rebase<'repo> { fn drop(&mut self) { unsafe { raw::git_rebase_free(self.raw) } @@ -279,25 +287,19 @@ pub struct RebaseOperation<'rebase> { impl<'rebase> RebaseOperation<'rebase> { /// The type of rebase operation pub fn kind(&self) -> Option { - unsafe { - RebaseOperationType::from_raw((*self.raw).kind) - } + unsafe { RebaseOperationType::from_raw((*self.raw).kind) } } /// The commit ID being cherry-picked. This will be populated for all /// operations except those of type `GIT_REBASE_OPERATION_EXEC`. pub fn id(&self) -> Oid { - unsafe { - Binding::from_raw(&(*self.raw).id as *const _) - } + unsafe { Binding::from_raw(&(*self.raw).id as *const _) } } ///The executable the user has requested be run. This will only /// be populated for operations of type RebaseOperationType::Exec pub fn exec(&self) -> Option<&str> { - unsafe { - str::from_utf8(::opt_bytes(self, (*self.raw).exec).unwrap()).ok() - } + unsafe { str::from_utf8(::opt_bytes(self, (*self.raw).exec).unwrap()).ok() } } } @@ -309,13 +311,15 @@ impl<'rebase> Binding for RebaseOperation<'rebase> { _marker: marker::PhantomData, } } - fn raw(&self) -> *const raw::git_rebase_operation { self.raw } + fn raw(&self) -> *const raw::git_rebase_operation { + self.raw + } } #[cfg(test)] mod tests { use std::{fs, path}; - use {RebaseOptions, RebaseOperationType, Signature}; + use {RebaseOperationType, RebaseOptions, Signature}; #[test] fn smoke() { @@ -327,15 +331,21 @@ mod tests { // We just want to see the iteration work so we can create commits with // no changes - let c1 = repo.commit(Some("refs/heads/master"), &sig, &sig, "foo", &tree, &[&tip]).unwrap(); + let c1 = repo + .commit(Some("refs/heads/master"), &sig, &sig, "foo", &tree, &[&tip]) + .unwrap(); let c1 = repo.find_commit(c1).unwrap(); - let c2 = repo.commit(Some("refs/heads/master"), &sig, &sig, "foo", &tree, &[&c1]).unwrap(); + let c2 = repo + .commit(Some("refs/heads/master"), &sig, &sig, "foo", &tree, &[&c1]) + .unwrap(); let branch = repo.find_annotated_commit(c2).unwrap(); - let upstream = repo .find_annotated_commit(tip.id()).unwrap(); + let upstream = repo.find_annotated_commit(tip.id()).unwrap(); let mut opts: RebaseOptions = Default::default(); opts.inmemory(true); - let mut rebase = repo.rebase(Some(&branch), Some(&upstream), None, Some(&mut opts)).unwrap(); + let mut rebase = repo + .rebase(Some(&branch), Some(&upstream), None, Some(&mut opts)) + .unwrap(); assert_eq!(rebase.len(), 2); { diff --git a/src/reference.rs b/src/reference.rs index f9d2f5b8da..11e5b30aad 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -5,9 +5,9 @@ use std::mem; use std::ptr; use std::str; -use {raw, Error, Oid, Repository, ReferenceType, Object, ObjectType, Blob, Commit, Tree, Tag}; use object::CastOrPanic; use util::{c_cmp_to_ordering, Binding}; +use {raw, Blob, Commit, Error, Object, ObjectType, Oid, ReferenceType, Repository, Tag, Tree}; struct Refdb<'repo>(&'repo Repository); @@ -39,7 +39,9 @@ impl<'repo> Reference<'repo> { } /// Get access to the underlying raw pointer. - pub fn raw(&self) -> *mut raw::git_reference { self.raw } + pub fn raw(&self) -> *mut raw::git_reference { + self.raw + } /// Delete an existing reference. /// @@ -49,7 +51,9 @@ impl<'repo> Reference<'repo> { /// This function will return an error if the reference has changed from the /// time it was looked up. pub fn delete(&mut self) -> Result<(), Error> { - unsafe { try_call!(raw::git_reference_delete(self.raw)); } + unsafe { + try_call!(raw::git_reference_delete(self.raw)); + } Ok(()) } @@ -83,7 +87,9 @@ impl<'repo> Reference<'repo> { /// Get the full name of a reference. /// /// Returns `None` if the name is not valid utf-8. - pub fn name(&self) -> Option<&str> { str::from_utf8(self.name_bytes()).ok() } + pub fn name(&self) -> Option<&str> { + str::from_utf8(self.name_bytes()).ok() + } /// Get the full name of a reference. pub fn name_bytes(&self) -> &[u8] { @@ -102,9 +108,7 @@ impl<'repo> Reference<'repo> { /// Get the full shorthand of a reference. pub fn shorthand_bytes(&self) -> &[u8] { - unsafe { - ::opt_bytes(self, raw::git_reference_shorthand(&*self.raw)).unwrap() - } + unsafe { ::opt_bytes(self, raw::git_reference_shorthand(&*self.raw)).unwrap() } } /// Get the OID pointed to by a direct reference. @@ -112,9 +116,7 @@ impl<'repo> Reference<'repo> { /// Only available if the reference is direct (i.e. an object id reference, /// not a symbolic one). pub fn target(&self) -> Option { - unsafe { - Binding::from_raw_opt(raw::git_reference_target(&*self.raw)) - } + unsafe { Binding::from_raw_opt(raw::git_reference_target(&*self.raw)) } } /// Return the peeled OID target of this reference. @@ -122,9 +124,7 @@ impl<'repo> Reference<'repo> { /// This peeled OID only applies to direct references that point to a hard /// Tag object: it is the result of peeling such Tag. pub fn target_peel(&self) -> Option { - unsafe { - Binding::from_raw_opt(raw::git_reference_target_peel(&*self.raw)) - } + unsafe { Binding::from_raw_opt(raw::git_reference_target_peel(&*self.raw)) } } /// Get full name to the reference pointed to by a symbolic reference. @@ -132,7 +132,8 @@ impl<'repo> Reference<'repo> { /// May return `None` if the reference is either not symbolic or not a /// valid utf-8 string. pub fn symbolic_target(&self) -> Option<&str> { - self.symbolic_target_bytes().and_then(|s| str::from_utf8(s).ok()) + self.symbolic_target_bytes() + .and_then(|s| str::from_utf8(s).ok()) } /// Get full name to the reference pointed to by a symbolic reference. @@ -207,14 +208,19 @@ impl<'repo> Reference<'repo> { /// /// If the force flag is not enabled, and there's already a reference with /// the given name, the renaming will fail. - pub fn rename(&mut self, new_name: &str, force: bool, - msg: &str) -> Result, Error> { + pub fn rename( + &mut self, + new_name: &str, + force: bool, + msg: &str, + ) -> Result, Error> { let mut raw = ptr::null_mut(); let new_name = try!(CString::new(new_name)); let msg = try!(CString::new(msg)); unsafe { - try_call!(raw::git_reference_rename(&mut raw, self.raw, new_name, - force, msg)); + try_call!(raw::git_reference_rename( + &mut raw, self.raw, new_name, force, msg + )); Ok(Binding::from_raw(raw)) } } @@ -225,17 +231,19 @@ impl<'repo> Reference<'repo> { /// /// The new reference will be written to disk, overwriting the given /// reference. - pub fn set_target(&mut self, id: Oid, reflog_msg: &str) - -> Result, Error> { + pub fn set_target(&mut self, id: Oid, reflog_msg: &str) -> Result, Error> { let mut raw = ptr::null_mut(); let msg = try!(CString::new(reflog_msg)); unsafe { - try_call!(raw::git_reference_set_target(&mut raw, self.raw, - id.raw(), msg)); + try_call!(raw::git_reference_set_target( + &mut raw, + self.raw, + id.raw(), + msg + )); Ok(Binding::from_raw(raw)) } } - } impl<'repo> PartialOrd for Reference<'repo> { @@ -261,9 +269,14 @@ impl<'repo> Eq for Reference<'repo> {} impl<'repo> Binding for Reference<'repo> { type Raw = *mut raw::git_reference; unsafe fn from_raw(raw: *mut raw::git_reference) -> Reference<'repo> { - Reference { raw: raw, _marker: marker::PhantomData } + Reference { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_reference { + self.raw } - fn raw(&self) -> *mut raw::git_reference { self.raw } } impl<'repo> Drop for Reference<'repo> { @@ -287,11 +300,15 @@ impl<'repo> References<'repo> { impl<'repo> Binding for References<'repo> { type Raw = *mut raw::git_reference_iterator; - unsafe fn from_raw(raw: *mut raw::git_reference_iterator) - -> References<'repo> { - References { raw: raw, _marker: marker::PhantomData } + unsafe fn from_raw(raw: *mut raw::git_reference_iterator) -> References<'repo> { + References { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_reference_iterator { + self.raw } - fn raw(&self) -> *mut raw::git_reference_iterator { self.raw } } impl<'repo> Iterator for References<'repo> { @@ -316,8 +333,7 @@ impl<'repo, 'references> Iterator for ReferenceNames<'repo, 'references> { fn next(&mut self) -> Option> { let mut out = ptr::null(); unsafe { - try_call_iter!(raw::git_reference_next_name(&mut out, - self.inner.raw)); + try_call_iter!(raw::git_reference_next_name(&mut out, self.inner.raw)); let bytes = ::opt_bytes(self, out).unwrap(); let s = str::from_utf8(bytes).unwrap(); Some(Ok(mem::transmute::<&str, &'references str>(s))) @@ -327,7 +343,7 @@ impl<'repo, 'references> Iterator for ReferenceNames<'repo, 'references> { #[cfg(test)] mod tests { - use {Reference, ObjectType, ReferenceType}; + use {ObjectType, Reference, ReferenceType}; #[test] fn smoke() { @@ -352,8 +368,10 @@ mod tests { assert_eq!(head.name(), Some("refs/heads/master")); assert!(head == repo.find_reference("refs/heads/master").unwrap()); - assert_eq!(repo.refname_to_id("refs/heads/master").unwrap(), - head.target().unwrap()); + assert_eq!( + repo.refname_to_id("refs/heads/master").unwrap(), + head.target().unwrap() + ); assert!(head.symbolic_target().is_none()); assert!(head.target_peel().is_none()); @@ -361,9 +379,9 @@ mod tests { assert_eq!(head.shorthand(), Some("master")); assert!(head.resolve().unwrap() == head); - let mut tag1 = repo.reference("refs/tags/tag1", - head.target().unwrap(), - false, "test").unwrap(); + let mut tag1 = repo + .reference("refs/tags/tag1", head.target().unwrap(), false, "test") + .unwrap(); assert!(tag1.is_tag()); assert_eq!(tag1.kind().unwrap(), ReferenceType::Direct); @@ -373,9 +391,9 @@ mod tests { tag1.delete().unwrap(); - let mut sym1 = repo.reference_symbolic("refs/tags/tag1", - "refs/heads/master", false, - "test").unwrap(); + let mut sym1 = repo + .reference_symbolic("refs/tags/tag1", "refs/heads/master", false, "test") + .unwrap(); assert_eq!(sym1.kind().unwrap(), ReferenceType::Symbolic); sym1.delete().unwrap(); @@ -392,6 +410,5 @@ mod tests { let mut head = head.rename("refs/foo", true, "test").unwrap(); head.delete().unwrap(); - } } diff --git a/src/reflog.rs b/src/reflog.rs index b4ff7a0371..4e0acfba5d 100644 --- a/src/reflog.rs +++ b/src/reflog.rs @@ -1,10 +1,10 @@ -use std::ops::Range; +use libc::size_t; use std::marker; +use std::ops::Range; use std::str; -use libc::size_t; -use {raw, signature, Oid, Error, Signature}; use util::Binding; +use {raw, signature, Error, Oid, Signature}; /// A reference log of a git repository. pub struct Reflog { @@ -25,12 +25,20 @@ pub struct ReflogIter<'reflog> { impl Reflog { /// Add a new entry to the in-memory reflog. - pub fn append(&mut self, new_oid: Oid, committer: &Signature, - msg: Option<&str>) -> Result<(), Error> { + pub fn append( + &mut self, + new_oid: Oid, + committer: &Signature, + msg: Option<&str>, + ) -> Result<(), Error> { let msg = try!(::opt_cstr(msg)); unsafe { - try_call!(raw::git_reflog_append(self.raw, new_oid.raw(), - committer.raw(), msg)); + try_call!(raw::git_reflog_append( + self.raw, + new_oid.raw(), + committer.raw(), + msg + )); } Ok(()) } @@ -41,11 +49,13 @@ impl Reflog { /// param value to `true`. When deleting entry n, member old_oid of entry /// n-1 (if any) will be updated with the value of member new_oid of entry /// n+1. - pub fn remove(&mut self, i: usize, rewrite_previous_entry: bool) - -> Result<(), Error> { + pub fn remove(&mut self, i: usize, rewrite_previous_entry: bool) -> Result<(), Error> { unsafe { - try_call!(raw::git_reflog_drop(self.raw, i as size_t, - rewrite_previous_entry)); + try_call!(raw::git_reflog_drop( + self.raw, + i as size_t, + rewrite_previous_entry + )); } Ok(()) } @@ -73,13 +83,18 @@ impl Reflog { /// Get an iterator to all entries inside of this reflog pub fn iter(&self) -> ReflogIter { - ReflogIter { range: 0..self.len(), reflog: self } + ReflogIter { + range: 0..self.len(), + reflog: self, + } } /// Write an existing in-memory reflog object back to disk using an atomic /// file lock. pub fn write(&mut self) -> Result<(), Error> { - unsafe { try_call!(raw::git_reflog_write(self.raw)); } + unsafe { + try_call!(raw::git_reflog_write(self.raw)); + } Ok(()) } } @@ -90,7 +105,9 @@ impl Binding for Reflog { unsafe fn from_raw(raw: *mut raw::git_reflog) -> Reflog { Reflog { raw: raw } } - fn raw(&self) -> *mut raw::git_reflog { self.raw } + fn raw(&self) -> *mut raw::git_reflog { + self.raw + } } impl Drop for Reflog { @@ -125,9 +142,7 @@ impl<'reflog> ReflogEntry<'reflog> { /// Get the log message as a byte array. pub fn message_bytes(&self) -> Option<&[u8]> { - unsafe { - ::opt_bytes(self, raw::git_reflog_entry_message(self.raw)) - } + unsafe { ::opt_bytes(self, raw::git_reflog_entry_message(self.raw)) } } } @@ -135,9 +150,14 @@ impl<'reflog> Binding for ReflogEntry<'reflog> { type Raw = *const raw::git_reflog_entry; unsafe fn from_raw(raw: *const raw::git_reflog_entry) -> ReflogEntry<'reflog> { - ReflogEntry { raw: raw, _marker: marker::PhantomData } + ReflogEntry { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *const raw::git_reflog_entry { + self.raw } - fn raw(&self) -> *const raw::git_reflog_entry { self.raw } } impl<'reflog> Iterator for ReflogIter<'reflog> { @@ -145,7 +165,9 @@ impl<'reflog> Iterator for ReflogIter<'reflog> { fn next(&mut self) -> Option> { self.range.next().and_then(|i| self.reflog.get(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'reflog> DoubleEndedIterator for ReflogIter<'reflog> { fn next_back(&mut self) -> Option> { diff --git a/src/refspec.rs b/src/refspec.rs index c814d23e5b..61654a6762 100644 --- a/src/refspec.rs +++ b/src/refspec.rs @@ -2,8 +2,8 @@ use std::ffi::CString; use std::marker; use std::str; -use {raw, Direction}; use util::Binding; +use {raw, Direction}; /// A structure to represent a git [refspec][1]. /// @@ -83,7 +83,12 @@ impl<'remote> Binding for Refspec<'remote> { type Raw = *const raw::git_refspec; unsafe fn from_raw(raw: *const raw::git_refspec) -> Refspec<'remote> { - Refspec { raw: raw, _marker: marker::PhantomData } + Refspec { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *const raw::git_refspec { + self.raw } - fn raw(&self) -> *const raw::git_refspec { self.raw } } diff --git a/src/remote.rs b/src/remote.rs index b385a1dfa2..e723155c42 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -1,16 +1,16 @@ +use libc; use std::ffi::CString; -use std::ops::Range; use std::marker; use std::mem; +use std::ops::Range; use std::ptr; use std::slice; use std::str; -use libc; -use {raw, Direction, Error, Refspec, Oid, FetchPrune, ProxyOptions}; -use {RemoteCallbacks, Progress, Repository, AutotagOption}; use string_array::StringArray; use util::Binding; +use {raw, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec}; +use {AutotagOption, Progress, RemoteCallbacks, Repository}; /// A structure representing a [remote][1] of a git repository. /// @@ -53,7 +53,10 @@ pub struct PushOptions<'cb> { } /// Holds callbacks for a connection to a `Remote`. Disconnects when dropped -pub struct RemoteConnection<'repo, 'connection, 'cb> where 'repo: 'connection { +pub struct RemoteConnection<'repo, 'connection, 'cb> +where + 'repo: 'connection, +{ _callbacks: Box>, _proxy: ProxyOptions<'cb>, remote: &'connection mut Remote<'repo>, @@ -62,7 +65,7 @@ pub struct RemoteConnection<'repo, 'connection, 'cb> where 'repo: 'connection { pub fn remote_into_raw(remote: Remote) -> *mut raw::git_remote { let ret = remote.raw; mem::forget(remote); - return ret + return ret; } impl<'repo> Remote<'repo> { @@ -116,10 +119,13 @@ impl<'repo> Remote<'repo> { pub fn connect(&mut self, dir: Direction) -> Result<(), Error> { // TODO: can callbacks be exposed safely? unsafe { - try_call!(raw::git_remote_connect(self.raw, dir, - ptr::null(), - ptr::null(), - ptr::null())); + try_call!(raw::git_remote_connect( + self.raw, + dir, + ptr::null(), + ptr::null(), + ptr::null() + )); } Ok(()) } @@ -127,19 +133,22 @@ impl<'repo> Remote<'repo> { /// Open a connection to a remote with callbacks and proxy settings /// /// Returns a `RemoteConnection` that will disconnect once dropped - pub fn connect_auth<'connection, 'cb>(&'connection mut self, - dir: Direction, - cb: Option>, - proxy_options: Option>) - -> Result, Error> { - + pub fn connect_auth<'connection, 'cb>( + &'connection mut self, + dir: Direction, + cb: Option>, + proxy_options: Option>, + ) -> Result, Error> { let cb = Box::new(cb.unwrap_or_else(RemoteCallbacks::new)); let proxy_options = proxy_options.unwrap_or_else(ProxyOptions::new); unsafe { - try_call!(raw::git_remote_connect(self.raw, dir, - &cb.raw(), - &proxy_options.raw(), - ptr::null())); + try_call!(raw::git_remote_connect( + self.raw, + dir, + &cb.raw(), + &proxy_options.raw(), + ptr::null() + )); } Ok(RemoteConnection { @@ -169,8 +178,11 @@ impl<'repo> Remote<'repo> { /// /// The `specs` argument is a list of refspecs to use for this negotiation /// and download. Use an empty array to use the base refspecs. - pub fn download(&mut self, specs: &[&str], opts: Option<&mut FetchOptions>) - -> Result<(), Error> { + pub fn download( + &mut self, + specs: &[&str], + opts: Option<&mut FetchOptions>, + ) -> Result<(), Error> { let (_a, _b, arr) = try!(::util::iter2cstrs(specs.iter())); let raw = opts.map(|o| o.raw()); unsafe { @@ -182,7 +194,10 @@ impl<'repo> Remote<'repo> { /// Get the number of refspecs for a remote pub fn refspecs<'a>(&'a self) -> Refspecs<'a> { let cnt = unsafe { raw::git_remote_refspec_count(&*self.raw) as usize }; - Refspecs { range: 0..cnt, remote: self } + Refspecs { + range: 0..cnt, + remote: self, + } } /// Get the `nth` refspec from this remote. @@ -190,8 +205,7 @@ impl<'repo> Remote<'repo> { /// The `refspecs` iterator can be used to iterate over all refspecs. pub fn get_refspec(&self, i: usize) -> Option> { unsafe { - let ptr = raw::git_remote_get_refspec(&*self.raw, - i as libc::size_t); + let ptr = raw::git_remote_get_refspec(&*self.raw, i as libc::size_t); Binding::from_raw_opt(ptr) } } @@ -213,10 +227,12 @@ impl<'repo> Remote<'repo> { /// let repo = git2::Repository::discover("rust").unwrap(); /// fetch_origin_master(repo).unwrap(); /// ``` - pub fn fetch(&mut self, - refspecs: &[&str], - opts: Option<&mut FetchOptions>, - reflog_msg: Option<&str>) -> Result<(), Error> { + pub fn fetch( + &mut self, + refspecs: &[&str], + opts: Option<&mut FetchOptions>, + reflog_msg: Option<&str>, + ) -> Result<(), Error> { let (_a, _b, arr) = try!(::util::iter2cstrs(refspecs.iter())); let msg = try!(::opt_cstr(reflog_msg)); let raw = opts.map(|o| o.raw()); @@ -227,17 +243,23 @@ impl<'repo> Remote<'repo> { } /// Update the tips to the new state - pub fn update_tips(&mut self, - callbacks: Option<&mut RemoteCallbacks>, - update_fetchhead: bool, - download_tags: AutotagOption, - msg: Option<&str>) -> Result<(), Error> { + pub fn update_tips( + &mut self, + callbacks: Option<&mut RemoteCallbacks>, + update_fetchhead: bool, + download_tags: AutotagOption, + msg: Option<&str>, + ) -> Result<(), Error> { let msg = try!(::opt_cstr(msg)); let cbs = callbacks.map(|cb| cb.raw()); unsafe { - try_call!(raw::git_remote_update_tips(self.raw, cbs.as_ref(), - update_fetchhead, - download_tags, msg)); + try_call!(raw::git_remote_update_tips( + self.raw, + cbs.as_ref(), + update_fetchhead, + download_tags, + msg + )); } Ok(()) } @@ -250,9 +272,7 @@ impl<'repo> Remote<'repo> { /// Note that you'll likely want to use `RemoteCallbacks` and set /// `push_update_reference` to test whether all the references were pushed /// successfully. - pub fn push(&mut self, - refspecs: &[&str], - opts: Option<&mut PushOptions>) -> Result<(), Error> { + pub fn push(&mut self, refspecs: &[&str], opts: Option<&mut PushOptions>) -> Result<(), Error> { let (_a, _b, arr) = try!(::util::iter2cstrs(refspecs.iter())); let raw = opts.map(|o| o.raw()); unsafe { @@ -263,9 +283,7 @@ impl<'repo> Remote<'repo> { /// Get the statistics structure that is filled in by the fetch operation. pub fn stats(&self) -> Progress { - unsafe { - Binding::from_raw(raw::git_remote_stats(self.raw)) - } + unsafe { Binding::from_raw(raw::git_remote_stats(self.raw)) } } /// Get the remote repository's reference advertisement list. @@ -281,11 +299,15 @@ impl<'repo> Remote<'repo> { let mut base = ptr::null_mut(); unsafe { try_call!(raw::git_remote_ls(&mut base, &mut size, self.raw)); - assert_eq!(mem::size_of::(), - mem::size_of::<*const raw::git_remote_head>()); + assert_eq!( + mem::size_of::(), + mem::size_of::<*const raw::git_remote_head>() + ); let slice = slice::from_raw_parts(base as *const _, size as usize); - Ok(mem::transmute::<&[*const raw::git_remote_head], - &[RemoteHead]>(slice)) + Ok(mem::transmute::< + &[*const raw::git_remote_head], + &[RemoteHead], + >(slice)) } } @@ -329,7 +351,9 @@ impl<'repo> Binding for Remote<'repo> { _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_remote { self.raw } + fn raw(&self) -> *mut raw::git_remote { + self.raw + } } impl<'repo> Drop for Remote<'repo> { @@ -343,11 +367,15 @@ impl<'repo> Iterator for Refspecs<'repo> { fn next(&mut self) -> Option> { self.range.next().and_then(|i| self.remote.get_refspec(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'repo> DoubleEndedIterator for Refspecs<'repo> { fn next_back(&mut self) -> Option> { - self.range.next_back().and_then(|i| self.remote.get_refspec(i)) + self.range + .next_back() + .and_then(|i| self.remote.get_refspec(i)) } } impl<'repo> ExactSizeIterator for Refspecs<'repo> {} @@ -440,10 +468,16 @@ impl<'cb> Binding for FetchOptions<'cb> { fn raw(&self) -> raw::git_fetch_options { raw::git_fetch_options { 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()), + 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), @@ -456,7 +490,6 @@ impl<'cb> Binding for FetchOptions<'cb> { } } - impl<'cb> Default for PushOptions<'cb> { fn default() -> Self { Self::new() @@ -506,11 +539,16 @@ impl<'cb> Binding for PushOptions<'cb> { fn raw(&self) -> raw::git_push_options { raw::git_push_options { 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()), + 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()), pb_parallelism: self.pb_parallelism as libc::c_uint, // TODO: expose this as a builder option custom_headers: raw::git_strarray { @@ -546,8 +584,8 @@ impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb> mod tests { use std::cell::Cell; use tempdir::TempDir; - use {Repository, Remote, RemoteCallbacks, Direction, FetchOptions}; use {AutotagOption, PushOptions}; + use {Direction, FetchOptions, Remote, RemoteCallbacks, Repository}; #[test] fn smoke() { @@ -578,8 +616,10 @@ mod tests { let url = if cfg!(unix) { format!("file://{}", remote.display()) } else { - format!("file:///{}", remote.display().to_string() - .replace("\\", "/")) + format!( + "file:///{}", + remote.display().to_string().replace("\\", "/") + ) }; let mut origin = repo.remote("origin", &url).unwrap(); @@ -628,8 +668,12 @@ mod tests { origin.fetch(&[], None, None).unwrap(); origin.fetch(&[], None, Some("foo")).unwrap(); - origin.update_tips(None, true, AutotagOption::Unspecified, None).unwrap(); - origin.update_tips(None, true, AutotagOption::All, Some("foo")).unwrap(); + origin + .update_tips(None, true, AutotagOption::Unspecified, None) + .unwrap(); + origin + .update_tips(None, true, AutotagOption::All, Some("foo")) + .unwrap(); t!(repo.remote_add_fetch("https://github.com/origin", "foo")); t!(repo.remote_add_fetch("https://github.com/origin", "bar")); @@ -675,9 +719,13 @@ mod tests { progress_hit.set(true); true }); - origin.fetch(&[], - Some(FetchOptions::new().remote_callbacks(callbacks)), - None).unwrap(); + origin + .fetch( + &[], + Some(FetchOptions::new().remote_callbacks(callbacks)), + None, + ) + .unwrap(); let list = t!(origin.list()); assert_eq!(list.len(), 2); @@ -707,7 +755,9 @@ mod tests { let mut origin = repo.remote("origin", &url).unwrap(); { - let mut connection = origin.connect_auth(Direction::Fetch, Some(callbacks), None).unwrap(); + let mut connection = origin + .connect_auth(Direction::Fetch, Some(callbacks), None) + .unwrap(); assert!(connection.connected()); let list = t!(connection.list()); @@ -741,7 +791,9 @@ mod tests { }); let mut options = PushOptions::new(); options.remote_callbacks(callbacks); - remote.push(&["refs/heads/master"], Some(&mut options)).unwrap(); + remote + .push(&["refs/heads/master"], Some(&mut options)) + .unwrap(); } assert!(updated); diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index cf813c2f56..fdadd77a18 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -1,14 +1,14 @@ +use libc::{c_char, c_int, c_uint, c_void}; use std::ffi::{CStr, CString}; use std::marker; use std::mem; -use std::slice; use std::ptr; +use std::slice; use std::str; -use libc::{c_void, c_int, c_char, c_uint}; -use {raw, panic, Error, Cred, CredentialType, Oid}; use cert::Cert; use util::Binding; +use {panic, raw, Cred, CredentialType, Error, Oid}; /// A structure to contain the callbacks which are invoked when a repository is /// being updated or downloaded. @@ -41,8 +41,8 @@ enum ProgressState { /// * `username_from_url` - the username that was embedded in the url, or `None` /// if it was not included. /// * `allowed_types` - a bitmask stating which cred types are ok to return. -pub type Credentials<'a> = dyn FnMut(&str, Option<&str>, CredentialType) - -> Result + 'a; +pub type Credentials<'a> = + dyn FnMut(&str, Option<&str>, CredentialType) -> Result + 'a; /// Callback to be invoked while a transfer is in progress. /// @@ -98,8 +98,8 @@ impl<'a> RemoteCallbacks<'a> { /// The callback through which to fetch credentials if required. pub fn credentials(&mut self, cb: F) -> &mut RemoteCallbacks<'a> - where F: FnMut(&str, Option<&str>, CredentialType) - -> Result + 'a + where + F: FnMut(&str, Option<&str>, CredentialType) -> Result + 'a, { self.credentials = Some(Box::new(cb) as Box>); self @@ -107,7 +107,9 @@ impl<'a> RemoteCallbacks<'a> { /// The callback through which progress is monitored. pub fn transfer_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> - where F: FnMut(Progress) -> bool + 'a { + where + F: FnMut(Progress) -> bool + 'a, + { self.progress = Some(Box::new(cb) as Box>); self } @@ -117,7 +119,9 @@ impl<'a> RemoteCallbacks<'a> { /// Text sent over the progress side-band will be passed to this function /// (this is the 'counting objects' output). pub fn sideband_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> - where F: FnMut(&[u8]) -> bool + 'a { + where + F: FnMut(&[u8]) -> bool + 'a, + { self.sideband_progress = Some(Box::new(cb) as Box>); self } @@ -125,7 +129,9 @@ impl<'a> RemoteCallbacks<'a> { /// Each time a reference is updated locally, the callback will be called /// with information about it. pub fn update_tips(&mut self, cb: F) -> &mut RemoteCallbacks<'a> - where F: FnMut(&str, Oid, Oid) -> bool + 'a { + where + F: FnMut(&str, Oid, Oid) -> bool + 'a, + { self.update_tips = Some(Box::new(cb) as Box>); self } @@ -134,7 +140,8 @@ impl<'a> RemoteCallbacks<'a> { /// let the caller make the final decision of whether to allow the /// connection to proceed. pub fn certificate_check(&mut self, cb: F) -> &mut RemoteCallbacks<'a> - where F: FnMut(&Cert, &str) -> bool + 'a + where + F: FnMut(&Cert, &str) -> bool + 'a, { self.certificate_check = Some(Box::new(cb) as Box>); self @@ -146,7 +153,8 @@ impl<'a> RemoteCallbacks<'a> { /// second is a status message sent by the server. If the status is `Some` /// then the push was rejected. pub fn push_update_reference(&mut self, cb: F) -> &mut RemoteCallbacks<'a> - where F: FnMut(&str, Option<&str>) -> Result<(), Error> + 'a, + where + F: FnMut(&str, Option<&str>) -> Result<(), Error> + 'a, { self.push_update_reference = Some(Box::new(cb) as Box>); self @@ -162,8 +170,10 @@ impl<'a> Binding for RemoteCallbacks<'a> { fn raw(&self) -> raw::git_remote_callbacks { unsafe { let mut callbacks: raw::git_remote_callbacks = mem::zeroed(); - assert_eq!(raw::git_remote_init_callbacks(&mut callbacks, - raw::GIT_REMOTE_CALLBACKS_VERSION), 0); + assert_eq!( + raw::git_remote_init_callbacks(&mut callbacks, raw::GIT_REMOTE_CALLBACKS_VERSION), + 0 + ); if self.progress.is_some() { let f: raw::git_transfer_progress_cb = transfer_progress_cb; callbacks.transfer_progress = Some(f); @@ -177,18 +187,20 @@ impl<'a> Binding for RemoteCallbacks<'a> { callbacks.sideband_progress = Some(f); } if self.certificate_check.is_some() { - let f: raw::git_transport_certificate_check_cb = - certificate_check_cb; + let f: raw::git_transport_certificate_check_cb = certificate_check_cb; callbacks.certificate_check = Some(f); } if self.push_update_reference.is_some() { - let f: extern fn(_, _, _) -> c_int = push_update_reference_cb; + let f: extern "C" fn(_, _, _) -> c_int = push_update_reference_cb; callbacks.push_update_reference = Some(f); } if self.update_tips.is_some() { - let f: extern fn(*const c_char, *const raw::git_oid, - *const raw::git_oid, *mut c_void) -> c_int - = update_tips_cb; + let f: extern "C" fn( + *const c_char, + *const raw::git_oid, + *const raw::git_oid, + *mut c_void, + ) -> c_int = update_tips_cb; callbacks.update_tips = Some(f); } callbacks.payload = self as *const _ as *mut _; @@ -239,8 +251,7 @@ impl<'a> Progress<'a> { impl<'a> Binding for Progress<'a> { type Raw = *const raw::git_transfer_progress; - unsafe fn from_raw(raw: *const raw::git_transfer_progress) - -> Progress<'a> { + unsafe fn from_raw(raw: *const raw::git_transfer_progress) -> Progress<'a> { Progress { raw: ProgressState::Borrowed(raw), _marker: marker::PhantomData, @@ -255,24 +266,27 @@ impl<'a> Binding for Progress<'a> { } } -extern fn credentials_cb(ret: *mut *mut raw::git_cred, - url: *const c_char, - username_from_url: *const c_char, - allowed_types: c_uint, - payload: *mut c_void) -> c_int { +extern "C" fn credentials_cb( + ret: *mut *mut raw::git_cred, + url: *const c_char, + username_from_url: *const c_char, + allowed_types: c_uint, + payload: *mut c_void, +) -> c_int { unsafe { let ok = panic::wrap(|| { let payload = &mut *(payload as *mut RemoteCallbacks); - let callback = try!(payload.credentials.as_mut() - .ok_or(raw::GIT_PASSTHROUGH as c_int)); + let callback = try!(payload + .credentials + .as_mut() + .ok_or(raw::GIT_PASSTHROUGH as c_int)); *ret = ptr::null_mut(); let url = try!(str::from_utf8(CStr::from_ptr(url).to_bytes()) - .map_err(|_| raw::GIT_PASSTHROUGH as c_int)); + .map_err(|_| raw::GIT_PASSTHROUGH as c_int)); let username_from_url = match ::opt_bytes(&url, username_from_url) { - Some(username) => { - Some(try!(str::from_utf8(username) - .map_err(|_| raw::GIT_PASSTHROUGH as c_int))) - } + Some(username) => Some(try!( + str::from_utf8(username).map_err(|_| raw::GIT_PASSTHROUGH as c_int) + )), None => None, }; @@ -301,8 +315,10 @@ extern fn credentials_cb(ret: *mut *mut raw::git_cred, } } -extern fn transfer_progress_cb(stats: *const raw::git_transfer_progress, - payload: *mut c_void) -> c_int { +extern "C" fn transfer_progress_cb( + stats: *const raw::git_transfer_progress, + payload: *mut c_void, +) -> c_int { let ok = panic::wrap(|| unsafe { let payload = &mut *(payload as *mut RemoteCallbacks); let callback = match payload.progress { @@ -312,12 +328,14 @@ extern fn transfer_progress_cb(stats: *const raw::git_transfer_progress, let progress = Binding::from_raw(stats); callback(progress) }); - if ok == Some(true) {0} else {-1} + if ok == Some(true) { + 0 + } else { + -1 + } } -extern fn sideband_progress_cb(str: *const c_char, - len: c_int, - payload: *mut c_void) -> c_int { +extern "C" fn sideband_progress_cb(str: *const c_char, len: c_int, payload: *mut c_void) -> c_int { let ok = panic::wrap(|| unsafe { let payload = &mut *(payload as *mut RemoteCallbacks); let callback = match payload.sideband_progress { @@ -327,32 +345,43 @@ extern fn sideband_progress_cb(str: *const c_char, let buf = slice::from_raw_parts(str as *const u8, len as usize); callback(buf) }); - if ok == Some(true) {0} else {-1} + if ok == Some(true) { + 0 + } else { + -1 + } } -extern fn update_tips_cb(refname: *const c_char, - a: *const raw::git_oid, - b: *const raw::git_oid, - data: *mut c_void) -> c_int { +extern "C" fn update_tips_cb( + refname: *const c_char, + a: *const raw::git_oid, + b: *const raw::git_oid, + data: *mut c_void, +) -> c_int { let ok = panic::wrap(|| unsafe { let payload = &mut *(data as *mut RemoteCallbacks); let callback = match payload.update_tips { Some(ref mut c) => c, None => return true, }; - let refname = str::from_utf8(CStr::from_ptr(refname).to_bytes()) - .unwrap(); + let refname = str::from_utf8(CStr::from_ptr(refname).to_bytes()).unwrap(); let a = Binding::from_raw(a); let b = Binding::from_raw(b); callback(refname, a, b) }); - if ok == Some(true) {0} else {-1} + if ok == Some(true) { + 0 + } else { + -1 + } } -extern fn certificate_check_cb(cert: *mut raw::git_cert, - _valid: c_int, - hostname: *const c_char, - data: *mut c_void) -> c_int { +extern "C" fn certificate_check_cb( + cert: *mut raw::git_cert, + _valid: c_int, + hostname: *const c_char, + data: *mut c_void, +) -> c_int { let ok = panic::wrap(|| unsafe { let payload = &mut *(data as *mut RemoteCallbacks); let callback = match payload.certificate_check { @@ -360,24 +389,28 @@ extern fn certificate_check_cb(cert: *mut raw::git_cert, None => return true, }; let cert = Binding::from_raw(cert); - let hostname = str::from_utf8(CStr::from_ptr(hostname).to_bytes()) - .unwrap(); + let hostname = str::from_utf8(CStr::from_ptr(hostname).to_bytes()).unwrap(); callback(&cert, hostname) }); - if ok == Some(true) {0} else {-1} + if ok == Some(true) { + 0 + } else { + -1 + } } -extern fn push_update_reference_cb(refname: *const c_char, - status: *const c_char, - data: *mut c_void) -> c_int { +extern "C" fn push_update_reference_cb( + refname: *const c_char, + status: *const c_char, + data: *mut c_void, +) -> c_int { panic::wrap(|| unsafe { let payload = &mut *(data as *mut RemoteCallbacks); let callback = match payload.push_update_reference { Some(ref mut c) => c, None => return 0, }; - let refname = str::from_utf8(CStr::from_ptr(refname).to_bytes()) - .unwrap(); + let refname = str::from_utf8(CStr::from_ptr(refname).to_bytes()).unwrap(); let status = if status.is_null() { None } else { @@ -387,5 +420,6 @@ extern fn push_update_reference_cb(refname: *const c_char, Ok(()) => 0, Err(e) => e.raw_code(), } - }).unwrap_or(-1) + }) + .unwrap_or(-1) } diff --git a/src/repo.rs b/src/repo.rs index 4cb1b9c77b..2135354f22 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1,3 +1,4 @@ +use libc::{c_char, c_int, c_uint, c_void, size_t}; use std::env; use std::ffi::{CStr, CString, OsStr}; use std::iter::IntoIterator; @@ -5,21 +6,25 @@ use std::mem; use std::path::Path; use std::ptr; use std::str; -use libc::{c_int, c_char, size_t, c_void, c_uint}; - -use {raw, Revspec, Error, init, Object, RepositoryOpenFlags, RepositoryState, Remote, Buf, StashFlags}; -use {ResetType, Signature, Reference, References, Submodule, Blame, BlameOptions}; -use {Branches, BranchType, Index, Config, Oid, Blob, BlobWriter, Branch, Commit, Tree}; -use {AnnotatedCommit, MergeOptions, SubmoduleIgnore, SubmoduleStatus, MergeAnalysis, MergePreference}; -use {ObjectType, Tag, Note, Notes, StatusOptions, Statuses, Status, Revwalk}; -use {RevparseMode, RepositoryInitMode, Reflog, IntoCString, Describe}; -use {DescribeOptions, TreeBuilder, Diff, DiffOptions, PackBuilder, Odb}; -use {Rebase, RebaseOptions}; -use build::{RepoBuilder, CheckoutBuilder}; -use stash::{StashApplyOptions, StashCbData, stash_cb}; -use string_array::StringArray; + +use build::{CheckoutBuilder, RepoBuilder}; use oid_array::OidArray; +use stash::{stash_cb, StashApplyOptions, StashCbData}; +use string_array::StringArray; use util::{self, Binding}; +use { + init, raw, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, Revspec, + StashFlags, +}; +use { + AnnotatedCommit, MergeAnalysis, MergeOptions, MergePreference, SubmoduleIgnore, SubmoduleStatus, +}; +use {Blame, BlameOptions, Reference, References, ResetType, Signature, Submodule}; +use {Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, Oid, Tree}; +use {Describe, IntoCString, Reflog, RepositoryInitMode, RevparseMode}; +use {DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder}; +use {Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag}; +use {Rebase, RebaseOptions}; /// An owned git repository, representing all state associated with the /// underlying filesystem. @@ -86,10 +91,12 @@ impl Repository { let mut ret = ptr::null_mut(); let flags = raw::GIT_REPOSITORY_OPEN_FROM_ENV; unsafe { - try_call!(raw::git_repository_open_ext(&mut ret, - ptr::null(), - flags as c_uint, - ptr::null())); + try_call!(raw::git_repository_open_ext( + &mut ret, + ptr::null(), + flags as c_uint, + ptr::null() + )); Ok(Binding::from_raw(ret)) } } @@ -120,11 +127,15 @@ impl Repository { /// 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(path: P, - flags: RepositoryOpenFlags, - ceiling_dirs: I) - -> Result - where P: AsRef, O: AsRef, I: IntoIterator + pub fn open_ext( + path: P, + flags: RepositoryOpenFlags, + ceiling_dirs: I, + ) -> Result + where + P: AsRef, + O: AsRef, + I: IntoIterator, { init(); let path = try!(path.as_ref().into_c_string()); @@ -132,10 +143,12 @@ impl Repository { let ceiling_dirs = try!(ceiling_dirs_os.into_c_string()); let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_repository_open_ext(&mut ret, - path, - flags.bits() as c_uint, - ceiling_dirs)); + try_call!(raw::git_repository_open_ext( + &mut ret, + path, + flags.bits() as c_uint, + ceiling_dirs + )); Ok(Binding::from_raw(ret)) } } @@ -150,8 +163,12 @@ impl Repository { let buf = Buf::new(); let path = try!(path.as_ref().into_c_string()); unsafe { - try_call!(raw::git_repository_discover(buf.raw(), path, 1, - ptr::null())); + try_call!(raw::git_repository_discover( + buf.raw(), + path, + 1, + ptr::null() + )); } Repository::open(util::bytes2path(&*buf)) } @@ -175,8 +192,10 @@ impl Repository { /// Creates a new repository in the specified folder with the given options. /// /// See `RepositoryInitOptions` struct for more information. - pub fn init_opts>(path: P, opts: &RepositoryInitOptions) - -> Result { + pub fn init_opts>( + path: P, + opts: &RepositoryInitOptions, + ) -> Result { init(); let path = try!(path.as_ref().into_c_string()); let mut ret = ptr::null_mut(); @@ -191,8 +210,7 @@ impl Repository { /// /// See the `RepoBuilder` struct for more information. This function will /// delegate to a fresh `RepoBuilder` - pub fn clone>(url: &str, into: P) - -> Result { + pub fn clone>(url: &str, into: P) -> Result { ::init(); RepoBuilder::new().clone(url, into.as_ref()) } @@ -201,8 +219,7 @@ impl Repository { /// recursively. /// /// This is similar to `git clone --recursive`. - pub fn clone_recurse>(url: &str, into: P) - -> Result { + pub fn clone_recurse>(url: &str, into: P) -> Result { let repo = Repository::clone(url, into)?; repo.update_submodules()?; Ok(repo) @@ -222,9 +239,7 @@ impl Repository { /// /// Uninitialized submodules will be initialized. fn update_submodules(&self) -> Result<(), Error> { - - fn add_subrepos(repo: &Repository, list: &mut Vec) - -> Result<(), Error> { + fn add_subrepos(repo: &Repository, list: &mut Vec) -> Result<(), Error> { for mut subm in repo.submodules()? { subm.update(true, None)?; list.push(subm.open()?); @@ -280,14 +295,17 @@ impl Repository { /// In some cases (`@{<-n>}` or `@{upstream}`), the expression /// may point to an intermediate reference. When such expressions are being /// passed in, this intermediate reference is returned. - pub fn revparse_ext(&self, spec: &str) - -> Result<(Object, Option), Error> { + pub fn revparse_ext(&self, spec: &str) -> Result<(Object, Option), Error> { let spec = try!(CString::new(spec)); let mut git_obj = ptr::null_mut(); let mut git_ref = ptr::null_mut(); unsafe { - try_call!(raw::git_revparse_ext(&mut git_obj, &mut git_ref, - self.raw, spec)); + try_call!(raw::git_revparse_ext( + &mut git_obj, + &mut git_ref, + self.raw, + spec + )); assert!(!git_obj.is_null()); Ok((Binding::from_raw(git_obj), Binding::from_raw_opt(git_ref))) } @@ -310,9 +328,7 @@ impl Repository { /// Tests whether this repository is empty. pub fn is_empty(&self) -> Result { - let empty = unsafe { - try_call!(raw::git_repository_is_empty(self.raw)) - }; + let empty = unsafe { try_call!(raw::git_repository_is_empty(self.raw)) }; Ok(empty == 1) } @@ -372,12 +388,14 @@ impl Repository { /// If `update_link` is true, create/update the gitlink file in the workdir /// and set config "core.worktree" (if workdir is not the parent of the .git /// directory). - pub fn set_workdir(&self, path: &Path, update_gitlink: bool) - -> Result<(), Error> { + pub fn set_workdir(&self, path: &Path, update_gitlink: bool) -> Result<(), Error> { let path = try!(path.into_c_string()); unsafe { - try_call!(raw::git_repository_set_workdir(self.raw(), path, - update_gitlink)); + try_call!(raw::git_repository_set_workdir( + self.raw(), + path, + update_gitlink + )); } Ok(()) } @@ -406,8 +424,7 @@ impl Repository { pub fn set_namespace_bytes(&self, namespace: &[u8]) -> Result<(), Error> { unsafe { let namespace = try!(CString::new(namespace)); - try_call!(raw::git_repository_set_namespace(self.raw, - namespace)); + try_call!(raw::git_repository_set_namespace(self.raw, namespace)); Ok(()) } } @@ -415,8 +432,7 @@ impl Repository { /// Remove the active namespace for this repository. pub fn remove_namespace(&self) -> Result<(), Error> { unsafe { - try_call!(raw::git_repository_set_namespace(self.raw, - ptr::null())); + try_call!(raw::git_repository_set_namespace(self.raw, ptr::null())); Ok(()) } } @@ -500,8 +516,7 @@ impl Repository { /// The returned array of strings is a list of the non-default refspecs /// which cannot be renamed and are returned for further processing by the /// caller. - pub fn remote_rename(&self, name: &str, - new_name: &str) -> Result { + pub fn remote_rename(&self, name: &str, new_name: &str) -> Result { let name = try!(CString::new(name)); let new_name = try!(CString::new(new_name)); let mut problems = raw::git_strarray { @@ -509,8 +524,12 @@ impl Repository { strings: 0 as *mut *mut c_char, }; unsafe { - try_call!(raw::git_remote_rename(&mut problems, self.raw, name, - new_name)); + try_call!(raw::git_remote_rename( + &mut problems, + self.raw, + name, + new_name + )); Ok(Binding::from_raw(problems)) } } @@ -521,7 +540,9 @@ impl Repository { /// will be removed. pub fn remote_delete(&self, name: &str) -> Result<(), Error> { let name = try!(CString::new(name)); - unsafe { try_call!(raw::git_remote_delete(self.raw, name)); } + unsafe { + try_call!(raw::git_remote_delete(self.raw, name)); + } Ok(()) } @@ -529,8 +550,7 @@ impl Repository { /// /// Add the given refspec to the fetch list in the configuration. No loaded /// remote instances will be affected. - pub fn remote_add_fetch(&self, name: &str, spec: &str) - -> Result<(), Error> { + pub fn remote_add_fetch(&self, name: &str, spec: &str) -> Result<(), Error> { let name = try!(CString::new(name)); let spec = try!(CString::new(spec)); unsafe { @@ -543,8 +563,7 @@ impl Repository { /// /// Add the given refspec to the push list in the configuration. No /// loaded remote instances will be affected. - pub fn remote_add_push(&self, name: &str, spec: &str) - -> Result<(), Error> { + pub fn remote_add_push(&self, name: &str, spec: &str) -> Result<(), Error> { let name = try!(CString::new(name)); let spec = try!(CString::new(spec)); unsafe { @@ -561,7 +580,9 @@ impl Repository { pub fn remote_set_url(https://github.com/&self,%20name:%20&str,%20url:%20&str) -> Result<(), Error> { let name = try!(CString::new(name)); let url = try!(CString::new(url)); - unsafe { try_call!(raw::git_remote_set_url(https://github.com/self.raw,%20name,%20url)); } + unsafe { + try_call!(raw::git_remote_set_url(https://github.com/self.raw,%20name,%20url)); + } Ok(()) } @@ -572,8 +593,7 @@ impl Repository { /// error. /// /// `None` indicates that it should be cleared. - pub fn remote_set_pushurl(https://github.com/&self,%20name:%20&str,%20pushurl:%20Option%3C&str%3E) - -> Result<(), Error> { + pub fn remote_set_pushurl(https://github.com/&self,%20name:%20&str,%20pushurl:%20Option%3C&str%3E) -> Result<(), Error> { let name = try!(CString::new(name)); let pushurl = try!(::opt_cstr(pushurl)); unsafe { @@ -599,17 +619,21 @@ impl Repository { /// to a commit. /// /// The `checkout` options will only be used for a hard reset. - pub fn reset(&self, - target: &Object, - kind: ResetType, - checkout: Option<&mut CheckoutBuilder>) - -> Result<(), Error> { + pub fn reset( + &self, + target: &Object, + kind: ResetType, + checkout: Option<&mut CheckoutBuilder>, + ) -> Result<(), Error> { unsafe { let mut opts: raw::git_checkout_options = mem::zeroed(); - try_call!(raw::git_checkout_init_options(&mut opts, - raw::GIT_CHECKOUT_OPTIONS_VERSION)); + try_call!(raw::git_checkout_init_options( + &mut opts, + raw::GIT_CHECKOUT_OPTIONS_VERSION + )); let opts = checkout.map(|c| { - c.configure(&mut opts); &mut opts + c.configure(&mut opts); + &mut opts }); try_call!(raw::git_reset(self.raw, target.raw(), kind, opts)); } @@ -623,10 +647,10 @@ impl Repository { /// /// Passing a `None` target will result in removing entries in the index /// matching the provided pathspecs. - pub fn reset_default(&self, - target: Option<&Object>, - paths: I) -> Result<(), Error> - where T: IntoCString, I: IntoIterator, + pub fn reset_default(&self, target: Option<&Object>, paths: I) -> Result<(), Error> + where + T: IntoCString, + I: IntoIterator, { let (_a, _b, mut arr) = try!(::util::iter2cstrs(paths)); let target = target.map(|t| t.raw()); @@ -672,7 +696,7 @@ impl Repository { match value { 0 => Ok(false), 1 => Ok(true), - _ => Err(Error::last_error(value).unwrap()) + _ => Err(Error::last_error(value).unwrap()), } } } @@ -689,8 +713,10 @@ impl Repository { /// to the peeled commit. pub fn set_head_detached(&self, commitish: Oid) -> Result<(), Error> { unsafe { - try_call!(raw::git_repository_set_head_detached(self.raw, - commitish.raw())); + try_call!(raw::git_repository_set_head_detached( + self.raw, + commitish.raw() + )); } Ok(()) } @@ -710,8 +736,9 @@ impl Repository { let mut ret = ptr::null_mut(); let glob = try!(CString::new(glob)); unsafe { - try_call!(raw::git_reference_iterator_glob_new(&mut ret, self.raw, - glob)); + try_call!(raw::git_reference_iterator_glob_new( + &mut ret, self.raw, glob + )); Ok(Binding::from_raw(ret)) } @@ -719,7 +746,7 @@ impl Repository { /// Load all submodules for this repository and return them. pub fn submodules(&self) -> Result, Error> { - struct Data<'a, 'b:'a> { + struct Data<'a, 'b: 'a> { repo: &'b Repository, ret: &'a mut Vec>, } @@ -730,21 +757,24 @@ impl Repository { repo: self, ret: &mut ret, }; - try_call!(raw::git_submodule_foreach(self.raw, append, - &mut data as *mut _ - as *mut c_void)); + try_call!(raw::git_submodule_foreach( + self.raw, + append, + &mut data as *mut _ as *mut c_void + )); } return Ok(ret); - extern fn append(_repo: *mut raw::git_submodule, - name: *const c_char, - data: *mut c_void) -> c_int { + extern "C" fn append( + _repo: *mut raw::git_submodule, + name: *const c_char, + data: *mut c_void, + ) -> c_int { unsafe { let data = &mut *(data as *mut Data); let mut raw = ptr::null_mut(); - let rc = raw::git_submodule_lookup(&mut raw, data.repo.raw(), - name); + let rc = raw::git_submodule_lookup(&mut raw, data.repo.raw(), name); assert_eq!(rc, 0); data.ret.push(Binding::from_raw(raw)); } @@ -758,13 +788,14 @@ impl Repository { /// status, then the results from rename detection (if you enable it) may /// not be accurate. To do rename detection properly, this must be called /// with no pathspec so that all files can be considered. - pub fn statuses(&self, options: Option<&mut StatusOptions>) - -> Result { + pub fn statuses(&self, options: Option<&mut StatusOptions>) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_status_list_new(&mut ret, self.raw, - options.map(|s| s.raw()) - .unwrap_or(ptr::null()))); + try_call!(raw::git_status_list_new( + &mut ret, + self.raw, + options.map(|s| s.raw()).unwrap_or(ptr::null()) + )); Ok(Binding::from_raw(ret)) } } @@ -781,8 +812,7 @@ impl Repository { let mut ret = 0 as c_int; let path = try!(path.into_c_string()); unsafe { - try_call!(raw::git_status_should_ignore(&mut ret, self.raw, - path)); + try_call!(raw::git_status_should_ignore(&mut ret, self.raw, path)); } Ok(ret != 0) } @@ -808,20 +838,20 @@ impl Repository { let path = if cfg!(windows) { // `git_status_file` dose not work with windows path separator // so we convert \ to / - try!(::std::ffi::CString::new(path.to_string_lossy().replace('\\', "/"))) + try!(::std::ffi::CString::new( + path.to_string_lossy().replace('\\', "/") + )) } else { try!(path.into_c_string()) }; unsafe { - try_call!(raw::git_status_file(&mut ret, self.raw, - path)); + try_call!(raw::git_status_file(&mut ret, self.raw, path)); } Ok(Status::from_bits_truncate(ret as u32)) } /// Create an iterator which loops over the requested branches. - pub fn branches(&self, filter: Option) - -> Result { + pub fn branches(&self, filter: Option) -> Result { let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_branch_iterator_new(&mut raw, self.raw(), filter)); @@ -866,12 +896,18 @@ impl Repository { /// The Oid returned can in turn be passed to `find_blob` to get a handle to /// the blob. pub fn blob(&self, data: &[u8]) -> Result { - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { let ptr = data.as_ptr() as *const c_void; let len = data.len() as size_t; - try_call!(raw::git_blob_create_frombuffer(&mut raw, self.raw(), - ptr, len)); + try_call!(raw::git_blob_create_frombuffer( + &mut raw, + self.raw(), + ptr, + len + )); Ok(Binding::from_raw(&raw as *const _)) } } @@ -883,10 +919,11 @@ impl Repository { /// the blob. pub fn blob_path(&self, path: &Path) -> Result { let path = try!(path.into_c_string()); - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { - try_call!(raw::git_blob_create_fromdisk(&mut raw, self.raw(), - path)); + try_call!(raw::git_blob_create_fromdisk(&mut raw, self.raw(), path)); Ok(Binding::from_raw(&raw as *const _)) } } @@ -941,30 +978,32 @@ impl Repository { /// A new direct reference will be created pointing to this target commit. /// If `force` is true and a reference already exists with the given name, /// it'll be replaced. - pub fn branch(&self, - branch_name: &str, - target: &Commit, - force: bool) -> Result { + pub fn branch(&self, branch_name: &str, target: &Commit, force: bool) -> Result { let branch_name = try!(CString::new(branch_name)); let mut raw = ptr::null_mut(); unsafe { - try_call!(raw::git_branch_create(&mut raw, - self.raw(), - branch_name, - target.raw(), - force)); + try_call!(raw::git_branch_create( + &mut raw, + self.raw(), + branch_name, + target.raw(), + force + )); Ok(Branch::wrap(Binding::from_raw(raw))) } } /// Lookup a branch by its name in a repository. - pub fn find_branch(&self, name: &str, branch_type: BranchType) - -> Result { + pub fn find_branch(&self, name: &str, branch_type: BranchType) -> Result { let name = try!(CString::new(name)); let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_branch_lookup(&mut ret, self.raw(), name, - branch_type)); + try_call!(raw::git_branch_lookup( + &mut ret, + self.raw(), + name, + branch_type + )); Ok(Branch::wrap(Binding::from_raw(ret))) } } @@ -977,30 +1016,37 @@ impl Repository { /// current branch and make it point to this commit. If the reference /// doesn't exist yet, it will be created. If it does exist, the first /// parent must be the tip of this branch. - pub fn commit(&self, - update_ref: Option<&str>, - author: &Signature, - committer: &Signature, - message: &str, - tree: &Tree, - parents: &[&Commit]) -> Result { + pub fn commit( + &self, + update_ref: Option<&str>, + author: &Signature, + committer: &Signature, + message: &str, + tree: &Tree, + parents: &[&Commit], + ) -> Result { let update_ref = try!(::opt_cstr(update_ref)); - let mut parent_ptrs = parents.iter().map(|p| { - p.raw() as *const raw::git_commit - }).collect::>(); + let mut parent_ptrs = parents + .iter() + .map(|p| p.raw() as *const raw::git_commit) + .collect::>(); let message = try!(CString::new(message)); - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; - unsafe { - try_call!(raw::git_commit_create(&mut raw, - self.raw(), - update_ref, - author.raw(), - committer.raw(), - ptr::null(), - message, - tree.raw(), - parents.len() as size_t, - parent_ptrs.as_mut_ptr())); + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; + unsafe { + try_call!(raw::git_commit_create( + &mut raw, + self.raw(), + update_ref, + author.raw(), + committer.raw(), + ptr::null(), + message, + tree.raw(), + parents.len() as size_t, + parent_ptrs.as_mut_ptr() + )); Ok(Binding::from_raw(&raw as *const _)) } } @@ -1015,47 +1061,54 @@ impl Repository { /// almost certainly what you want. /// /// Returns the resulting (signed) commit id. - pub fn commit_signed(&self, - commit_content: &str, - signature: &str, - signature_field: Option<&str>) -> Result { + pub fn commit_signed( + &self, + commit_content: &str, + signature: &str, + signature_field: Option<&str>, + ) -> Result { let commit_content = try!(CString::new(commit_content)); let signature = try!(CString::new(signature)); let signature_field = try!(::opt_cstr(signature_field)); - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { - try_call!(raw::git_commit_create_with_signature(&mut raw, - self.raw(), - commit_content, - signature, - signature_field)); + try_call!(raw::git_commit_create_with_signature( + &mut raw, + self.raw(), + commit_content, + signature, + signature_field + )); Ok(Binding::from_raw(&raw as *const _)) } } - /// Extract the signature from a commit /// /// Returns a tuple containing the signature in the first value and the /// signed data in the second. - pub fn extract_signature(&self, - commit_id: &Oid, - signature_field: Option<&str>) - -> Result<(Buf, Buf), Error> { + pub fn extract_signature( + &self, + commit_id: &Oid, + signature_field: Option<&str>, + ) -> Result<(Buf, Buf), Error> { let signature_field = try!(::opt_cstr(signature_field)); let signature = Buf::new(); let content = Buf::new(); unsafe { - try_call!(raw::git_commit_extract_signature(signature.raw(), - content.raw(), - self.raw(), - commit_id.raw() as *mut _, - signature_field)); + try_call!(raw::git_commit_extract_signature( + signature.raw(), + content.raw(), + self.raw(), + commit_id.raw() as *mut _, + signature_field + )); Ok((signature, content)) } } - /// Lookup a reference to one of the commits in a repository. pub fn find_commit(&self, oid: Oid) -> Result { let mut raw = ptr::null_mut(); @@ -1069,18 +1122,25 @@ impl Repository { pub fn find_annotated_commit(&self, id: Oid) -> Result { unsafe { let mut raw = 0 as *mut raw::git_annotated_commit; - try_call!(raw::git_annotated_commit_lookup(&mut raw, self.raw(), id.raw())); + try_call!(raw::git_annotated_commit_lookup( + &mut raw, + self.raw(), + id.raw() + )); Ok(Binding::from_raw(raw)) } } /// Lookup a reference to one of the objects in a repository. - pub fn find_object(&self, oid: Oid, - kind: Option) -> Result { + pub fn find_object(&self, oid: Oid, kind: Option) -> Result { let mut raw = ptr::null_mut(); unsafe { - try_call!(raw::git_object_lookup(&mut raw, self.raw(), oid.raw(), - kind)); + try_call!(raw::git_object_lookup( + &mut raw, + self.raw(), + oid.raw(), + kind + )); Ok(Binding::from_raw(raw)) } } @@ -1090,15 +1150,25 @@ impl Repository { /// This function will return an error if a reference already exists with /// the given name unless force is true, in which case it will be /// overwritten. - pub fn reference(&self, name: &str, id: Oid, force: bool, - log_message: &str) -> Result { + pub fn reference( + &self, + name: &str, + id: Oid, + force: bool, + log_message: &str, + ) -> Result { let name = try!(CString::new(name)); let log_message = try!(CString::new(log_message)); let mut raw = ptr::null_mut(); unsafe { - try_call!(raw::git_reference_create(&mut raw, self.raw(), name, - id.raw(), force, - log_message)); + try_call!(raw::git_reference_create( + &mut raw, + self.raw(), + name, + id.raw(), + force, + log_message + )); Ok(Binding::from_raw(raw)) } } @@ -1133,23 +1203,27 @@ impl Repository { /// It will return GIT_EMODIFIED if the reference's value at the time of /// updating does not match the one passed through `current_id` (i.e. if the /// ref has changed since the user read it). - pub fn reference_matching(&self, - name: &str, - id: Oid, - force: bool, - current_id: Oid, - log_message: &str) -> Result { + pub fn reference_matching( + &self, + name: &str, + id: Oid, + force: bool, + current_id: Oid, + log_message: &str, + ) -> Result { let name = try!(CString::new(name)); let log_message = try!(CString::new(log_message)); let mut raw = ptr::null_mut(); unsafe { - try_call!(raw::git_reference_create_matching(&mut raw, - self.raw(), - name, - id.raw(), - force, - current_id.raw(), - log_message)); + try_call!(raw::git_reference_create_matching( + &mut raw, + self.raw(), + name, + id.raw(), + force, + current_id.raw(), + log_message + )); Ok(Binding::from_raw(raw)) } } @@ -1159,18 +1233,26 @@ impl Repository { /// This function will return an error if a reference already exists with /// the given name unless force is true, in which case it will be /// overwritten. - pub fn reference_symbolic(&self, name: &str, target: &str, - force: bool, - log_message: &str) - -> Result { + pub fn reference_symbolic( + &self, + name: &str, + target: &str, + force: bool, + log_message: &str, + ) -> Result { let name = try!(CString::new(name)); let target = try!(CString::new(target)); let log_message = try!(CString::new(log_message)); let mut raw = ptr::null_mut(); unsafe { - try_call!(raw::git_reference_symbolic_create(&mut raw, self.raw(), - name, target, force, - log_message)); + try_call!(raw::git_reference_symbolic_create( + &mut raw, + self.raw(), + name, + target, + force, + log_message + )); Ok(Binding::from_raw(raw)) } } @@ -1184,26 +1266,29 @@ impl Repository { /// It will return GIT_EMODIFIED if the reference's value at the time of /// updating does not match the one passed through current_value (i.e. if /// the ref has changed since the user read it). - pub fn reference_symbolic_matching(&self, - name: &str, - target: &str, - force: bool, - current_value: &str, - log_message: &str) - -> Result { + pub fn reference_symbolic_matching( + &self, + name: &str, + target: &str, + force: bool, + current_value: &str, + log_message: &str, + ) -> Result { let name = try!(CString::new(name)); let target = try!(CString::new(target)); let current_value = try!(CString::new(current_value)); let log_message = try!(CString::new(log_message)); let mut raw = ptr::null_mut(); unsafe { - try_call!(raw::git_reference_symbolic_create_matching(&mut raw, - self.raw(), - name, - target, - force, - current_value, - log_message)); + try_call!(raw::git_reference_symbolic_create_matching( + &mut raw, + self.raw(), + name, + target, + force, + current_value, + log_message + )); Ok(Binding::from_raw(raw)) } } @@ -1238,7 +1323,9 @@ impl Repository { /// allocate or free any `Reference` objects for simple situations. pub fn refname_to_id(&self, name: &str) -> Result { let name = try!(CString::new(name)); - let mut ret = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut ret = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { try_call!(raw::git_reference_name_to_id(&mut ret, self.raw(), name)); Ok(Binding::from_raw(&ret as *const _)) @@ -1246,13 +1333,17 @@ impl Repository { } /// Creates a git_annotated_commit from the given reference. - pub fn reference_to_annotated_commit(&self, reference: &Reference) - -> Result { + pub fn reference_to_annotated_commit( + &self, + reference: &Reference, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_annotated_commit_from_ref(&mut ret, - self.raw(), - reference.raw())); + try_call!(raw::git_annotated_commit_from_ref( + &mut ret, + self.raw(), + reference.raw() + )); Ok(AnnotatedCommit::from_raw(ret)) } } @@ -1283,14 +1374,18 @@ impl Repository { /// the submodule repo and perform the clone step as needed. Lastly, call /// `add_finalize()` to wrap up adding the new submodule and `.gitmodules` /// to the index to be ready to commit. - pub fn submodule(&self, url: &str, path: &Path, - use_gitlink: bool) -> Result { + pub fn submodule(&self, url: &str, path: &Path, use_gitlink: bool) -> Result { let url = try!(CString::new(url)); let path = try!(path.into_c_string()); let mut raw = ptr::null_mut(); unsafe { - try_call!(raw::git_submodule_add_setup(&mut raw, self.raw(), - url, path, use_gitlink)); + try_call!(raw::git_submodule_add_setup( + &mut raw, + self.raw(), + url, + path, + use_gitlink + )); Ok(Binding::from_raw(raw)) } } @@ -1312,13 +1407,15 @@ impl Repository { /// /// This looks at a submodule and tries to determine the status. It /// will return a combination of the `SubmoduleStatus` values. - pub fn submodule_status(&self, name: &str, ignore: SubmoduleIgnore) - -> Result { + pub fn submodule_status( + &self, + name: &str, + ignore: SubmoduleIgnore, + ) -> Result { let mut ret = 0; let name = try!(CString::new(name)); unsafe { - try_call!(raw::git_submodule_status(&mut ret, self.raw, name, - ignore)); + try_call!(raw::git_submodule_status(&mut ret, self.raw, name, ignore)); } Ok(SubmoduleStatus::from_bits_truncate(ret as u32)) } @@ -1349,7 +1446,6 @@ impl Repository { } } - /// Create a new tag in the repository from an object /// /// A new reference will also be created pointing to this tag object. If @@ -1361,16 +1457,29 @@ impl Repository { /// The tag name will be checked for validity. You must avoid the characters /// '~', '^', ':', ' \ ', '?', '[', and '*', and the sequences ".." and " @ /// {" which have special meaning to revparse. - pub fn tag(&self, name: &str, target: &Object, - tagger: &Signature, message: &str, - force: bool) -> Result { + pub fn tag( + &self, + name: &str, + target: &Object, + tagger: &Signature, + message: &str, + force: bool, + ) -> Result { let name = try!(CString::new(name)); let message = try!(CString::new(message)); - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { - try_call!(raw::git_tag_create(&mut raw, self.raw, name, - target.raw(), tagger.raw(), - message, force)); + try_call!(raw::git_tag_create( + &mut raw, + self.raw, + name, + target.raw(), + tagger.raw(), + message, + force + )); Ok(Binding::from_raw(&raw as *const _)) } } @@ -1380,15 +1489,19 @@ impl Repository { /// A new direct reference will be created pointing to this target object. /// If force is true and a reference already exists with the given name, /// it'll be replaced. - pub fn tag_lightweight(&self, - name: &str, - target: &Object, - force: bool) -> Result { + pub fn tag_lightweight(&self, name: &str, target: &Object, force: bool) -> Result { let name = try!(CString::new(name)); - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { - try_call!(raw::git_tag_create_lightweight(&mut raw, self.raw, name, - target.raw(), force)); + try_call!(raw::git_tag_create_lightweight( + &mut raw, + self.raw, + name, + target.raw(), + force + )); Ok(Binding::from_raw(&raw as *const _)) } } @@ -1428,7 +1541,9 @@ impl Repository { let s = try!(CString::new(s)); try_call!(raw::git_tag_list_match(&mut arr, s, self.raw)); } - None => { try_call!(raw::git_tag_list(&mut arr, self.raw)); } + None => { + try_call!(raw::git_tag_list(&mut arr, self.raw)); + } } Ok(Binding::from_raw(arr)) } @@ -1436,12 +1551,13 @@ impl Repository { /// Updates files in the index and the working tree to match the content of /// the commit pointed at by HEAD. - pub fn checkout_head(&self, opts: Option<&mut CheckoutBuilder>) - -> Result<(), Error> { + pub fn checkout_head(&self, opts: Option<&mut CheckoutBuilder>) -> Result<(), Error> { unsafe { let mut raw_opts = mem::zeroed(); - try_call!(raw::git_checkout_init_options(&mut raw_opts, - raw::GIT_CHECKOUT_OPTIONS_VERSION)); + try_call!(raw::git_checkout_init_options( + &mut raw_opts, + raw::GIT_CHECKOUT_OPTIONS_VERSION + )); if let Some(c) = opts { c.configure(&mut raw_opts); } @@ -1454,39 +1570,48 @@ impl Repository { /// Updates files in the working tree to match the content of the index. /// /// If the index is `None`, the repository's index will be used. - pub fn checkout_index(&self, - index: Option<&mut Index>, - opts: Option<&mut CheckoutBuilder>) -> Result<(), Error> { + pub fn checkout_index( + &self, + index: Option<&mut Index>, + opts: Option<&mut CheckoutBuilder>, + ) -> Result<(), Error> { unsafe { let mut raw_opts = mem::zeroed(); - try_call!(raw::git_checkout_init_options(&mut raw_opts, - raw::GIT_CHECKOUT_OPTIONS_VERSION)); + try_call!(raw::git_checkout_init_options( + &mut raw_opts, + raw::GIT_CHECKOUT_OPTIONS_VERSION + )); if let Some(c) = opts { c.configure(&mut raw_opts); } - try_call!(raw::git_checkout_index(self.raw, - index.map(|i| &mut *i.raw()), - &raw_opts)); + try_call!(raw::git_checkout_index( + self.raw, + index.map(|i| &mut *i.raw()), + &raw_opts + )); } Ok(()) } /// Updates files in the index and working tree to match the content of the /// tree pointed at by the treeish. - pub fn checkout_tree(&self, - treeish: &Object, - opts: Option<&mut CheckoutBuilder>) -> Result<(), Error> { + pub fn checkout_tree( + &self, + treeish: &Object, + opts: Option<&mut CheckoutBuilder>, + ) -> Result<(), Error> { unsafe { let mut raw_opts = mem::zeroed(); - try_call!(raw::git_checkout_init_options(&mut raw_opts, - raw::GIT_CHECKOUT_OPTIONS_VERSION)); + try_call!(raw::git_checkout_init_options( + &mut raw_opts, + raw::GIT_CHECKOUT_OPTIONS_VERSION + )); if let Some(c) = opts { c.configure(&mut raw_opts); } - try_call!(raw::git_checkout_tree(self.raw, &*treeish.raw(), - &raw_opts)); + try_call!(raw::git_checkout_tree(self.raw, &*treeish.raw(), &raw_opts)); } Ok(()) } @@ -1499,30 +1624,34 @@ impl Repository { /// For compatibility with git, the repository is put into a merging state. /// Once the commit is done (or if the user wishes to abort), you should /// clear this state by calling git_repository_state_cleanup(). - pub fn merge(&self, - annotated_commits: &[&AnnotatedCommit], - merge_opts: Option<&mut MergeOptions>, - checkout_opts: Option<&mut CheckoutBuilder>) - -> Result<(), Error> - { + pub fn merge( + &self, + annotated_commits: &[&AnnotatedCommit], + merge_opts: Option<&mut MergeOptions>, + checkout_opts: Option<&mut CheckoutBuilder>, + ) -> Result<(), Error> { unsafe { let mut raw_checkout_opts = mem::zeroed(); - try_call!(raw::git_checkout_init_options(&mut raw_checkout_opts, - raw::GIT_CHECKOUT_OPTIONS_VERSION)); + try_call!(raw::git_checkout_init_options( + &mut raw_checkout_opts, + raw::GIT_CHECKOUT_OPTIONS_VERSION + )); if let Some(c) = checkout_opts { c.configure(&mut raw_checkout_opts); } - let mut commit_ptrs = annotated_commits.iter().map(|c| { - c.raw() as *const raw::git_annotated_commit - }).collect::>(); + let mut commit_ptrs = annotated_commits + .iter() + .map(|c| c.raw() as *const raw::git_annotated_commit) + .collect::>(); - try_call!(raw::git_merge(self.raw, - commit_ptrs.as_mut_ptr(), - annotated_commits.len() as size_t, - merge_opts.map(|o| o.raw()) - .unwrap_or(ptr::null()), - &raw_checkout_opts)); + try_call!(raw::git_merge( + self.raw, + commit_ptrs.as_mut_ptr(), + annotated_commits.len() as size_t, + merge_opts.map(|o| o.raw()).unwrap_or(ptr::null()), + &raw_checkout_opts + )); } Ok(()) } @@ -1531,14 +1660,21 @@ impl Repository { /// the merge. The index may be written as-is to the working directory or /// checked out. If the index is to be converted to a tree, the caller /// should resolve any conflicts that arose as part of the merge. - pub fn merge_commits(&self, our_commit: &Commit, their_commit: &Commit, - opts: Option<&MergeOptions>) -> Result { - let mut raw = ptr::null_mut(); - unsafe { - try_call!(raw::git_merge_commits(&mut raw, self.raw, - our_commit.raw(), - their_commit.raw(), - opts.map(|o| o.raw()))); + pub fn merge_commits( + &self, + our_commit: &Commit, + their_commit: &Commit, + opts: Option<&MergeOptions>, + ) -> Result { + let mut raw = ptr::null_mut(); + unsafe { + try_call!(raw::git_merge_commits( + &mut raw, + self.raw, + our_commit.raw(), + their_commit.raw(), + opts.map(|o| o.raw()) + )); Ok(Binding::from_raw(raw)) } } @@ -1547,13 +1683,23 @@ impl Repository { /// the merge. The index may be written as-is to the working directory or /// checked out. If the index is to be converted to a tree, the caller /// should resolve any conflicts that arose as part of the merge. - pub fn merge_trees(&self, ancestor_tree: &Tree, our_tree: &Tree, - their_tree: &Tree, opts: Option<&MergeOptions>) -> Result { + pub fn merge_trees( + &self, + ancestor_tree: &Tree, + our_tree: &Tree, + their_tree: &Tree, + opts: Option<&MergeOptions>, + ) -> Result { let mut raw = ptr::null_mut(); unsafe { - try_call!(raw::git_merge_trees(&mut raw, self.raw, ancestor_tree.raw(), - our_tree.raw(), their_tree.raw(), - opts.map(|o| o.raw()))); + try_call!(raw::git_merge_trees( + &mut raw, + self.raw, + ancestor_tree.raw(), + our_tree.raw(), + their_tree.raw(), + opts.map(|o| o.raw()) + )); Ok(Binding::from_raw(raw)) } } @@ -1569,9 +1715,10 @@ impl Repository { /// Analyzes the given branch(es) and determines the opportunities for /// merging them into the HEAD of the repository. - pub fn merge_analysis(&self, - their_heads: &[&AnnotatedCommit]) - -> Result<(MergeAnalysis, MergePreference), Error> { + pub fn merge_analysis( + &self, + their_heads: &[&AnnotatedCommit], + ) -> Result<(MergeAnalysis, MergePreference), Error> { unsafe { let mut raw_merge_analysis = 0 as raw::git_merge_analysis_t; let mut raw_merge_preference = 0 as raw::git_merge_preference_t; @@ -1579,24 +1726,30 @@ impl Repository { .iter() .map(|v| v.raw() as *const _) .collect::>(); - try_call!(raw::git_merge_analysis(&mut raw_merge_analysis, - &mut raw_merge_preference, - self.raw, - their_heads.as_mut_ptr() as *mut _, - their_heads.len())); - Ok((MergeAnalysis::from_bits_truncate(raw_merge_analysis as u32), MergePreference::from_bits_truncate(raw_merge_preference as u32))) + try_call!(raw::git_merge_analysis( + &mut raw_merge_analysis, + &mut raw_merge_preference, + self.raw, + their_heads.as_mut_ptr() as *mut _, + their_heads.len() + )); + Ok(( + MergeAnalysis::from_bits_truncate(raw_merge_analysis as u32), + MergePreference::from_bits_truncate(raw_merge_preference as u32), + )) } } /// Initializes a rebase operation to rebase the changes in `branch` /// relative to `upstream` onto another branch. To begin the rebase process, /// call `next()`. - pub fn rebase(&self, - branch: Option<&AnnotatedCommit>, - upstream: Option<&AnnotatedCommit>, - onto: Option<&AnnotatedCommit>, - opts: Option<&mut RebaseOptions>) -> Result { - + pub fn rebase( + &self, + branch: Option<&AnnotatedCommit>, + upstream: Option<&AnnotatedCommit>, + onto: Option<&AnnotatedCommit>, + opts: Option<&mut RebaseOptions>, + ) -> Result { let mut rebase: *mut raw::git_rebase = ptr::null_mut(); unsafe { try_call!(raw::git_rebase_init( @@ -1605,9 +1758,10 @@ impl Repository { branch.map(|c| c.raw()), upstream.map(|c| c.raw()), onto.map(|c| c.raw()), - opts.map(|o| o.raw()).unwrap_or(ptr::null()))); + opts.map(|o| o.raw()).unwrap_or(ptr::null()) + )); - Ok(Rebase::from_raw(rebase)) + Ok(Rebase::from_raw(rebase)) } } @@ -1616,38 +1770,45 @@ impl Repository { pub fn open_rebase(&self, opts: Option<&mut RebaseOptions>) -> Result { let mut rebase: *mut raw::git_rebase = ptr::null_mut(); unsafe { - try_call!(raw::git_rebase_open(&mut rebase, self.raw(), opts.map(|o| o.raw()).unwrap_or(ptr::null()))); + try_call!(raw::git_rebase_open( + &mut rebase, + self.raw(), + opts.map(|o| o.raw()).unwrap_or(ptr::null()) + )); Ok(Rebase::from_raw(rebase)) - } } - - /// Add a note for an object /// /// The `notes_ref` argument is the canonical name of the reference to use, /// defaulting to "refs/notes/commits". If `force` is specified then /// previous notes are overwritten. - pub fn note(&self, - author: &Signature, - committer: &Signature, - notes_ref: Option<&str>, - oid: Oid, - note: &str, - force: bool) -> Result { + pub fn note( + &self, + author: &Signature, + committer: &Signature, + notes_ref: Option<&str>, + oid: Oid, + note: &str, + force: bool, + ) -> Result { let notes_ref = try!(::opt_cstr(notes_ref)); let note = try!(CString::new(note)); - let mut ret = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; - unsafe { - try_call!(raw::git_note_create(&mut ret, - self.raw, - notes_ref, - author.raw(), - committer.raw(), - oid.raw(), - note, - force)); + let mut ret = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; + unsafe { + try_call!(raw::git_note_create( + &mut ret, + self.raw, + notes_ref, + author.raw(), + committer.raw(), + oid.raw(), + note, + force + )); Ok(Binding::from_raw(&ret as *const _)) } } @@ -1684,13 +1845,11 @@ impl Repository { /// defaulting to "refs/notes/commits". /// /// The id specified is the Oid of the git object to read the note from. - pub fn find_note(&self, notes_ref: Option<&str>, id: Oid) - -> Result { + pub fn find_note(&self, notes_ref: Option<&str>, id: Oid) -> Result { let notes_ref = try!(::opt_cstr(notes_ref)); let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_note_read(&mut ret, self.raw, notes_ref, - id.raw())); + try_call!(raw::git_note_read(&mut ret, self.raw, notes_ref, id.raw())); Ok(Binding::from_raw(ret)) } } @@ -1701,15 +1860,22 @@ impl Repository { /// defaulting to "refs/notes/commits". /// /// The id specified is the Oid of the git object to remove the note from. - pub fn note_delete(&self, - id: Oid, - notes_ref: Option<&str>, - author: &Signature, - committer: &Signature) -> Result<(), Error> { + pub fn note_delete( + &self, + id: Oid, + notes_ref: Option<&str>, + author: &Signature, + committer: &Signature, + ) -> Result<(), Error> { let notes_ref = try!(::opt_cstr(notes_ref)); unsafe { - try_call!(raw::git_note_remove(self.raw, notes_ref, author.raw(), - committer.raw(), id.raw())); + try_call!(raw::git_note_remove( + self.raw, + notes_ref, + author.raw(), + committer.raw(), + id.raw() + )); Ok(()) } } @@ -1724,26 +1890,33 @@ impl Repository { } /// Get the blame for a single file. - pub fn blame_file(&self, path: &Path, opts: Option<&mut BlameOptions>) - -> Result { + pub fn blame_file(&self, path: &Path, opts: Option<&mut BlameOptions>) -> Result { let path = try!(path.into_c_string()); let mut raw = ptr::null_mut(); unsafe { - try_call!(raw::git_blame_file(&mut raw, - self.raw(), - path, - opts.map(|s| s.raw()))); + try_call!(raw::git_blame_file( + &mut raw, + self.raw(), + path, + opts.map(|s| s.raw()) + )); Ok(Binding::from_raw(raw)) } } /// Find a merge base between two commits pub fn merge_base(&self, one: Oid, two: Oid) -> Result { - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { - try_call!(raw::git_merge_base(&mut raw, self.raw, - one.raw(), two.raw())); + try_call!(raw::git_merge_base( + &mut raw, + self.raw, + one.raw(), + two.raw() + )); Ok(Binding::from_raw(&raw as *const _)) } } @@ -1755,8 +1928,12 @@ impl Repository { count: 0, }; unsafe { - try_call!(raw::git_merge_bases(&mut arr, self.raw, - one.raw(), two.raw())); + try_call!(raw::git_merge_bases( + &mut arr, + self.raw, + one.raw(), + two.raw() + )); Ok(Binding::from_raw(arr)) } } @@ -1767,25 +1944,29 @@ impl Repository { /// upstream relationship, but it helps to think of one as a branch and the /// other as its upstream, the ahead and behind values will be what git /// would report for the branches. - pub fn graph_ahead_behind(&self, local: Oid, upstream: Oid) - -> Result<(usize, usize), Error> { + pub fn graph_ahead_behind(&self, local: Oid, upstream: Oid) -> Result<(usize, usize), Error> { unsafe { let mut ahead: size_t = 0; let mut behind: size_t = 0; - try_call!(raw::git_graph_ahead_behind(&mut ahead, &mut behind, - self.raw(), local.raw(), - upstream.raw())); + try_call!(raw::git_graph_ahead_behind( + &mut ahead, + &mut behind, + self.raw(), + local.raw(), + upstream.raw() + )); Ok((ahead as usize, behind as usize)) } } /// Determine if a commit is the descendant of another commit - pub fn graph_descendant_of(&self, commit: Oid, ancestor: Oid) - -> Result { + pub fn graph_descendant_of(&self, commit: Oid, ancestor: Oid) -> Result { unsafe { - let rv = try_call!(raw::git_graph_descendant_of(self.raw(), - commit.raw(), - ancestor.raw())); + let rv = try_call!(raw::git_graph_descendant_of( + self.raw(), + commit.raw(), + ancestor.raw() + )); Ok(rv != 0) } } @@ -1806,15 +1987,16 @@ impl Repository { /// Delete the reflog for the given reference pub fn reflog_delete(&self, name: &str) -> Result<(), Error> { let name = try!(CString::new(name)); - unsafe { try_call!(raw::git_reflog_delete(self.raw, name)); } + unsafe { + try_call!(raw::git_reflog_delete(self.raw, name)); + } Ok(()) } /// Rename a reflog /// /// The reflog to be renamed is expected to already exist. - pub fn reflog_rename(&self, old_name: &str, new_name: &str) - -> Result<(), Error> { + pub fn reflog_rename(&self, old_name: &str, new_name: &str) -> Result<(), Error> { let old_name = try!(CString::new(old_name)); let new_name = try!(CString::new(new_name)); unsafe { @@ -1826,9 +2008,7 @@ impl Repository { /// Check if the given reference has a reflog. pub fn reference_has_log(&self, name: &str) -> Result { let name = try!(CString::new(name)); - let ret = unsafe { - try_call!(raw::git_reference_has_log(self.raw, name)) - }; + let ret = unsafe { try_call!(raw::git_reference_has_log(self.raw, name)) }; Ok(ret != 0) } @@ -1862,18 +2042,21 @@ impl Repository { /// second tree will be used for the "new_file" side of the delta. You can /// pass `None` to indicate an empty tree, although it is an error to pass /// `None` for both the `old_tree` and `new_tree`. - pub fn diff_tree_to_tree(&self, - old_tree: Option<&Tree>, - new_tree: Option<&Tree>, - opts: Option<&mut DiffOptions>) - -> Result { + pub fn diff_tree_to_tree( + &self, + old_tree: Option<&Tree>, + new_tree: Option<&Tree>, + opts: Option<&mut DiffOptions>, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_diff_tree_to_tree(&mut ret, - self.raw(), - old_tree.map(|s| s.raw()), - new_tree.map(|s| s.raw()), - opts.map(|s| s.raw()))); + try_call!(raw::git_diff_tree_to_tree( + &mut ret, + self.raw(), + old_tree.map(|s| s.raw()), + new_tree.map(|s| s.raw()), + opts.map(|s| s.raw()) + )); Ok(Binding::from_raw(ret)) } } @@ -1891,18 +2074,21 @@ impl Repository { /// (if it has changed) before the diff is generated. /// /// If the tree is `None`, then it is considered an empty tree. - pub fn diff_tree_to_index(&self, - old_tree: Option<&Tree>, - index: Option<&Index>, - opts: Option<&mut DiffOptions>) - -> Result { + pub fn diff_tree_to_index( + &self, + old_tree: Option<&Tree>, + index: Option<&Index>, + opts: Option<&mut DiffOptions>, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_diff_tree_to_index(&mut ret, - self.raw(), - old_tree.map(|s| s.raw()), - index.map(|s| s.raw()), - opts.map(|s| s.raw()))); + try_call!(raw::git_diff_tree_to_index( + &mut ret, + self.raw(), + old_tree.map(|s| s.raw()), + index.map(|s| s.raw()), + opts.map(|s| s.raw()) + )); Ok(Binding::from_raw(ret)) } } @@ -1911,18 +2097,21 @@ impl Repository { /// /// The first index will be used for the "old_file" side of the delta, and /// the second index will be used for the "new_file" side of the delta. - pub fn diff_index_to_index(&self, - old_index: &Index, - new_index: &Index, - opts: Option<&mut DiffOptions>) - -> Result { + pub fn diff_index_to_index( + &self, + old_index: &Index, + new_index: &Index, + opts: Option<&mut DiffOptions>, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_diff_index_to_index(&mut ret, - self.raw(), - old_index.raw(), - new_index.raw(), - opts.map(|s| s.raw()))); + try_call!(raw::git_diff_index_to_index( + &mut ret, + self.raw(), + old_index.raw(), + new_index.raw(), + opts.map(|s| s.raw()) + )); Ok(Binding::from_raw(ret)) } } @@ -1940,16 +2129,19 @@ impl Repository { /// If you pass `None` for the index, then the existing index of the `repo` /// will be used. In this case, the index will be refreshed from disk /// (if it has changed) before the diff is generated. - pub fn diff_index_to_workdir(&self, - index: Option<&Index>, - opts: Option<&mut DiffOptions>) - -> Result { + pub fn diff_index_to_workdir( + &self, + index: Option<&Index>, + opts: Option<&mut DiffOptions>, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_diff_index_to_workdir(&mut ret, - self.raw(), - index.map(|s| s.raw()), - opts.map(|s| s.raw()))); + try_call!(raw::git_diff_index_to_workdir( + &mut ret, + self.raw(), + index.map(|s| s.raw()), + opts.map(|s| s.raw()) + )); Ok(Binding::from_raw(ret)) } } @@ -1972,16 +2164,19 @@ impl Repository { /// show status 'deleted' since there is a staged delete. /// /// If `None` is passed for `tree`, then an empty tree is used. - pub fn diff_tree_to_workdir(&self, - old_tree: Option<&Tree>, - opts: Option<&mut DiffOptions>) - -> Result { + pub fn diff_tree_to_workdir( + &self, + old_tree: Option<&Tree>, + opts: Option<&mut DiffOptions>, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_diff_tree_to_workdir(&mut ret, - self.raw(), - old_tree.map(|s| s.raw()), - opts.map(|s| s.raw()))); + try_call!(raw::git_diff_tree_to_workdir( + &mut ret, + self.raw(), + old_tree.map(|s| s.raw()), + opts.map(|s| s.raw()) + )); Ok(Binding::from_raw(ret)) } } @@ -1992,14 +2187,19 @@ impl Repository { /// This emulates `git diff ` by diffing the tree to the index and /// the index to the working directory and blending the results into a /// single diff that includes staged deleted, etc. - pub fn diff_tree_to_workdir_with_index(&self, - old_tree: Option<&Tree>, - opts: Option<&mut DiffOptions>) - -> Result { + pub fn diff_tree_to_workdir_with_index( + &self, + old_tree: Option<&Tree>, + opts: Option<&mut DiffOptions>, + ) -> Result { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_diff_tree_to_workdir_with_index(&mut ret, - self.raw(), old_tree.map(|s| s.raw()), opts.map(|s| s.raw()))); + try_call!(raw::git_diff_tree_to_workdir_with_index( + &mut ret, + self.raw(), + old_tree.map(|s| s.raw()), + opts.map(|s| s.raw()) + )); Ok(Binding::from_raw(ret)) } } @@ -2014,29 +2214,35 @@ impl Repository { } /// Save the local modifications to a new stash. - pub fn stash_save(&mut self, - stasher: &Signature, - message: &str, - flags: Option) - -> Result { - unsafe { - let mut raw_oid = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + pub fn stash_save( + &mut self, + stasher: &Signature, + message: &str, + flags: Option, + ) -> Result { + unsafe { + let mut raw_oid = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; let message = try!(CString::new(message)); let flags = flags.unwrap_or_else(StashFlags::empty); - try_call!(raw::git_stash_save(&mut raw_oid, - self.raw(), - stasher.raw(), - message, - flags.bits() as c_uint)); + try_call!(raw::git_stash_save( + &mut raw_oid, + self.raw(), + stasher.raw(), + message, + flags.bits() as c_uint + )); Ok(Binding::from_raw(&raw_oid as *const _)) } } /// Apply a single stashed state from the stash list. - pub fn stash_apply(&mut self, - index: usize, - opts: Option<&mut StashApplyOptions>) - -> Result<(), Error> { + pub fn stash_apply( + &mut self, + index: usize, + opts: Option<&mut StashApplyOptions>, + ) -> Result<(), Error> { unsafe { let opts = opts.map(|opts| opts.raw()); try_call!(raw::git_stash_apply(self.raw(), index, opts)); @@ -2048,13 +2254,18 @@ impl Repository { /// /// Return `true` to continue iterating or `false` to stop. pub fn stash_foreach(&mut self, mut callback: C) -> Result<(), Error> - where C: FnMut(usize, &str, &Oid) -> bool + where + C: FnMut(usize, &str, &Oid) -> bool, { unsafe { - let mut data = StashCbData { callback: &mut callback }; - try_call!(raw::git_stash_foreach(self.raw(), - stash_cb, - &mut data as *mut _ as *mut _)); + let mut data = StashCbData { + callback: &mut callback, + }; + try_call!(raw::git_stash_foreach( + self.raw(), + stash_cb, + &mut data as *mut _ as *mut _ + )); Ok(()) } } @@ -2068,10 +2279,11 @@ impl Repository { } /// Apply a single stashed state from the stash list and remove it from the list if successful. - pub fn stash_pop(&mut self, - index: usize, - opts: Option<&mut StashApplyOptions>) - -> Result<(), Error> { + pub fn stash_pop( + &mut self, + index: usize, + opts: Option<&mut StashApplyOptions>, + ) -> Result<(), Error> { unsafe { let opts = opts.map(|opts| opts.raw()); try_call!(raw::git_stash_pop(self.raw(), index, opts)); @@ -2103,13 +2315,19 @@ impl Repository { let path = if cfg!(windows) { // `git_ignore_path_is_ignored` dose not work with windows path separator // so we convert \ to / - try!(::std::ffi::CString::new(path.as_ref().to_string_lossy().replace('\\', "/"))) + try!(::std::ffi::CString::new( + path.as_ref().to_string_lossy().replace('\\', "/") + )) } else { try!(path.as_ref().into_c_string()) }; let mut ignored: c_int = 0; unsafe { - try_call!(raw::git_ignore_path_is_ignored(&mut ignored, self.raw, path)); + try_call!(raw::git_ignore_path_is_ignored( + &mut ignored, + self.raw, + path + )); } Ok(ignored == 1) } @@ -2120,7 +2338,9 @@ impl Binding for Repository { unsafe fn from_raw(ptr: *mut raw::git_repository) -> Repository { Repository { raw: ptr } } - fn raw(&self) -> *mut raw::git_repository { self.raw } + fn raw(&self) -> *mut raw::git_repository { + self.raw + } } impl Drop for Repository { @@ -2136,9 +2356,9 @@ impl RepositoryInitOptions { /// and initializing a directory from the user-configured templates path. pub fn new() -> RepositoryInitOptions { RepositoryInitOptions { - flags: raw::GIT_REPOSITORY_INIT_MKDIR as u32 | - raw::GIT_REPOSITORY_INIT_MKPATH as u32 | - raw::GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE as u32, + flags: raw::GIT_REPOSITORY_INIT_MKDIR as u32 + | raw::GIT_REPOSITORY_INIT_MKPATH as u32 + | raw::GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE as u32, mode: 0, workdir_path: None, description: None, @@ -2189,8 +2409,7 @@ impl RepositoryInitOptions { } /// Set to one of the `RepositoryInit` constants, or a custom value. - pub fn mode(&mut self, mode: RepositoryInitMode) - -> &mut RepositoryInitOptions { + pub fn mode(&mut self, mode: RepositoryInitMode) -> &mut RepositoryInitOptions { self.mode = mode.bits(); self } @@ -2202,13 +2421,15 @@ impl RepositoryInitOptions { /// `/usr/share/git-core-templates` will be used (if it exists). /// /// Defaults to true. - pub fn external_template(&mut self, enabled: bool) - -> &mut RepositoryInitOptions { + pub fn external_template(&mut self, enabled: bool) -> &mut RepositoryInitOptions { self.flag(raw::GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE, enabled) } - fn flag(&mut self, flag: raw::git_repository_init_flag_t, on: bool) - -> &mut RepositoryInitOptions { + fn flag( + &mut self, + flag: raw::git_repository_init_flag_t, + on: bool, + ) -> &mut RepositoryInitOptions { if on { self.flags |= flag as u32; } else { @@ -2268,8 +2489,13 @@ impl RepositoryInitOptions { /// interior of this structure. pub unsafe fn raw(&self) -> raw::git_repository_init_options { let mut opts = mem::zeroed(); - assert_eq!(raw::git_repository_init_init_options(&mut opts, - raw::GIT_REPOSITORY_INIT_OPTIONS_VERSION), 0); + assert_eq!( + raw::git_repository_init_init_options( + &mut opts, + raw::GIT_REPOSITORY_INIT_OPTIONS_VERSION + ), + 0 + ); opts.flags = self.flags; opts.mode = self.mode; opts.workdir_path = ::call::convert(&self.workdir_path); @@ -2283,12 +2509,12 @@ impl RepositoryInitOptions { #[cfg(test)] mod tests { + use build::CheckoutBuilder; use std::ffi::OsStr; use std::fs; use std::path::Path; use tempdir::TempDir; - use {Repository, Oid, ObjectType, ResetType}; - use build::CheckoutBuilder; + use {ObjectType, Oid, Repository, ResetType}; #[test] fn smoke_init() { @@ -2318,8 +2544,10 @@ mod tests { assert!(!repo.is_bare()); assert!(!repo.is_shallow()); assert!(repo.is_empty().unwrap()); - assert_eq!(::test::realpath(&repo.path()).unwrap(), - ::test::realpath(&td.path().join(".git/")).unwrap()); + assert_eq!( + ::test::realpath(&repo.path()).unwrap(), + ::test::realpath(&td.path().join(".git/")).unwrap() + ); assert_eq!(repo.state(), ::RepositoryState::Clean); } @@ -2331,8 +2559,10 @@ mod tests { let repo = Repository::open(path).unwrap(); assert!(repo.is_bare()); - assert_eq!(::test::realpath(&repo.path()).unwrap(), - ::test::realpath(&td.path().join("")).unwrap()); + assert_eq!( + ::test::realpath(&repo.path()).unwrap(), + ::test::realpath(&td.path().join("")).unwrap() + ); } #[test] @@ -2371,8 +2601,10 @@ mod tests { fs::create_dir(&subdir).unwrap(); Repository::init_bare(td.path()).unwrap(); let repo = Repository::discover(&subdir).unwrap(); - assert_eq!(::test::realpath(&repo.path()).unwrap(), - ::test::realpath(&td.path().join("")).unwrap()); + assert_eq!( + ::test::realpath(&repo.path()).unwrap(), + ::test::realpath(&td.path().join("")).unwrap() + ); } #[test] @@ -2382,22 +2614,28 @@ mod tests { fs::create_dir(&subdir).unwrap(); Repository::init(td.path()).unwrap(); - let repo = Repository::open_ext(&subdir, ::RepositoryOpenFlags::empty(), &[] as &[&OsStr]).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()); + assert_eq!( + ::test::realpath(&repo.path()).unwrap(), + ::test::realpath(&td.path().join(".git")).unwrap() + ); - let repo = Repository::open_ext(&subdir, ::RepositoryOpenFlags::BARE, &[] as &[&OsStr]).unwrap(); + let repo = + Repository::open_ext(&subdir, ::RepositoryOpenFlags::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, ::RepositoryOpenFlags::NO_SEARCH, &[] as &[&OsStr]).err().unwrap(); + assert_eq!( + ::test::realpath(&repo.path()).unwrap(), + ::test::realpath(&td.path().join(".git")).unwrap() + ); + + let err = Repository::open_ext(&subdir, ::RepositoryOpenFlags::NO_SEARCH, &[] as &[&OsStr]) + .err() + .unwrap(); assert_eq!(err.code(), ::ErrorCode::NotFound); - assert!(Repository::open_ext(&subdir, - ::RepositoryOpenFlags::empty(), - &[&subdir]).is_ok()); + assert!(Repository::open_ext(&subdir, ::RepositoryOpenFlags::empty(), &[&subdir]).is_ok()); } fn graph_repo_init() -> (TempDir, Repository) { @@ -2411,8 +2649,8 @@ mod tests { let tree = repo.find_tree(id).unwrap(); let sig = repo.signature().unwrap(); - repo.commit(Some("HEAD"), &sig, &sig, "second", - &tree, &[&head]).unwrap(); + repo.commit(Some("HEAD"), &sig, &sig, "second", &tree, &[&head]) + .unwrap(); } (_td, repo) } @@ -2424,12 +2662,10 @@ mod tests { let head = repo.find_commit(head).unwrap(); let head_id = head.id(); let head_parent_id = head.parent(0).unwrap().id(); - let (ahead, behind) = repo.graph_ahead_behind(head_id, - head_parent_id).unwrap(); + let (ahead, behind) = repo.graph_ahead_behind(head_id, head_parent_id).unwrap(); assert_eq!(ahead, 1); assert_eq!(behind, 0); - let (ahead, behind) = repo.graph_ahead_behind(head_parent_id, - head_id).unwrap(); + let (ahead, behind) = repo.graph_ahead_behind(head_parent_id, head_id).unwrap(); assert_eq!(ahead, 0); assert_eq!(behind, 1); } @@ -2453,7 +2689,9 @@ mod tests { assert_eq!(repo.reference_has_log("refs/heads/master").unwrap(), true); assert_eq!(repo.reference_has_log("NOT_HEAD").unwrap(), false); let master_oid = repo.revparse_single("master").unwrap().id(); - assert!(repo.reference("NOT_HEAD", master_oid, false, "creating a new branch").is_ok()); + assert!(repo + .reference("NOT_HEAD", master_oid, false, "creating a new branch") + .is_ok()); assert_eq!(repo.reference_has_log("NOT_HEAD").unwrap(), false); assert!(repo.reference_ensure_log("NOT_HEAD").is_ok()); assert_eq!(repo.reference_has_log("NOT_HEAD").unwrap(), true); @@ -2510,8 +2748,16 @@ mod tests { index.add_path(Path::new("file_a")).unwrap(); let id_a = index.write_tree().unwrap(); let tree_a = repo.find_tree(id_a).unwrap(); - let oid2 = repo.commit(Some("refs/heads/branch_a"), &sig, &sig, - "commit 2", &tree_a, &[&commit1]).unwrap(); + let oid2 = repo + .commit( + Some("refs/heads/branch_a"), + &sig, + &sig, + "commit 2", + &tree_a, + &[&commit1], + ) + .unwrap(); let commit2 = repo.find_commit(oid2).unwrap(); println!("created oid2 {:?}", oid2); @@ -2524,8 +2770,16 @@ mod tests { index.add_path(Path::new("file_b")).unwrap(); let id_b = index.write_tree().unwrap(); let tree_b = repo.find_tree(id_b).unwrap(); - let oid3 = repo.commit(Some("refs/heads/branch_b"), &sig, &sig, - "commit 3", &tree_b, &[&commit1]).unwrap(); + let oid3 = repo + .commit( + Some("refs/heads/branch_b"), + &sig, + &sig, + "commit 3", + &tree_b, + &[&commit1], + ) + .unwrap(); let commit3 = repo.find_commit(oid3).unwrap(); println!("created oid3 {:?}", oid3); @@ -2533,9 +2787,16 @@ mod tests { //let mut index4 = repo.merge_commits(&commit2, &commit3, None).unwrap(); repo.set_head("refs/heads/branch_a").unwrap(); repo.checkout_head(None).unwrap(); - let oid4 = repo.commit(Some("refs/heads/branch_a"), &sig, &sig, - "commit 4", &tree_a, - &[&commit2, &commit3]).unwrap(); + let oid4 = repo + .commit( + Some("refs/heads/branch_a"), + &sig, + &sig, + "commit 4", + &tree_a, + &[&commit2, &commit3], + ) + .unwrap(); //index4.write_tree_to(&repo).unwrap(); println!("created oid4 {:?}", oid4); @@ -2543,9 +2804,16 @@ mod tests { //let mut index5 = repo.merge_commits(&commit3, &commit2, None).unwrap(); repo.set_head("refs/heads/branch_b").unwrap(); repo.checkout_head(None).unwrap(); - let oid5 = repo.commit(Some("refs/heads/branch_b"), &sig, &sig, - "commit 5", &tree_a, - &[&commit3, &commit2]).unwrap(); + let oid5 = repo + .commit( + Some("refs/heads/branch_b"), + &sig, + &sig, + "commit 5", + &tree_a, + &[&commit3, &commit2], + ) + .unwrap(); //index5.write_tree_to(&repo).unwrap(); println!("created oid5 {:?}", oid5); @@ -2565,7 +2833,7 @@ mod tests { } assert!(found_oid2); assert!(found_oid3); - assert_eq!(merge_bases.len(), 2); + assert_eq!(merge_bases.len(), 2); } #[test] @@ -2598,14 +2866,13 @@ mod tests { let _ = repo.add_ignore_rule("/foo"); assert!(repo.is_path_ignored(Path::new("/foo")).unwrap()); - if cfg!(windows){ + if cfg!(windows) { assert!(repo.is_path_ignored(Path::new("\\foo\\thing")).unwrap()); } - let _ = repo.clear_ignore_rules(); assert!(!repo.is_path_ignored(Path::new("/foo")).unwrap()); - if cfg!(windows){ + if cfg!(windows) { assert!(!repo.is_path_ignored(Path::new("\\foo\\thing")).unwrap()); } } diff --git a/src/revspec.rs b/src/revspec.rs index eb18492efe..de6cf01076 100644 --- a/src/revspec.rs +++ b/src/revspec.rs @@ -9,18 +9,30 @@ pub struct Revspec<'repo> { impl<'repo> Revspec<'repo> { /// Assembles a new revspec from the from/to components. - pub fn from_objects(from: Option>, - to: Option>, - mode: RevparseMode) -> Revspec<'repo> { - Revspec { from: from, to: to, mode: mode } + pub fn from_objects( + from: Option>, + to: Option>, + mode: RevparseMode, + ) -> Revspec<'repo> { + Revspec { + from: from, + to: to, + mode: mode, + } } /// Access the `from` range of this revspec. - pub fn from(&self) -> Option<&Object<'repo>> { self.from.as_ref() } + pub fn from(&self) -> Option<&Object<'repo>> { + self.from.as_ref() + } /// Access the `to` range of this revspec. - pub fn to(&self) -> Option<&Object<'repo>> { self.to.as_ref() } + pub fn to(&self) -> Option<&Object<'repo>> { + self.to.as_ref() + } /// Returns the intent of the revspec. - pub fn mode(&self) -> RevparseMode { self.mode } + pub fn mode(&self) -> RevparseMode { + self.mode + } } diff --git a/src/revwalk.rs b/src/revwalk.rs index 1e661db526..fe33fddab8 100644 --- a/src/revwalk.rs +++ b/src/revwalk.rs @@ -1,9 +1,9 @@ -use std::marker; -use std::ffi::CString; use libc::c_uint; +use std::ffi::CString; +use std::marker; -use {raw, Error, Sort, Oid, Repository}; use util::Binding; +use {raw, Error, Oid, Repository, Sort}; /// A revwalk allows traversal of the commit graph defined by including one or /// more leaves and excluding one or more roots. @@ -23,9 +23,7 @@ impl<'repo> Revwalk<'repo> { /// Set the order in which commits are visited. pub fn set_sorting(&mut self, sort_mode: Sort) { - unsafe { - raw::git_revwalk_sorting(self.raw(), sort_mode.bits() as c_uint) - } + unsafe { raw::git_revwalk_sorting(self.raw(), sort_mode.bits() as c_uint) } } /// Simplify the history by first-parent @@ -152,9 +150,14 @@ impl<'repo> Revwalk<'repo> { impl<'repo> Binding for Revwalk<'repo> { type Raw = *mut raw::git_revwalk; unsafe fn from_raw(raw: *mut raw::git_revwalk) -> Revwalk<'repo> { - Revwalk { raw: raw, _marker: marker::PhantomData } + Revwalk { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_revwalk { + self.raw } - fn raw(&self) -> *mut raw::git_revwalk { self.raw } } impl<'repo> Drop for Revwalk<'repo> { @@ -166,7 +169,9 @@ impl<'repo> Drop for Revwalk<'repo> { impl<'repo> Iterator for Revwalk<'repo> { type Item = Result; fn next(&mut self) -> Option> { - let mut out: raw::git_oid = raw::git_oid{ id: [0; raw::GIT_OID_RAWSZ] }; + let mut out: raw::git_oid = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { try_call_iter!(raw::git_revwalk_next(&mut out, self.raw())); Some(Ok(Binding::from_raw(&out as *const _))) @@ -185,8 +190,7 @@ mod tests { let mut walk = repo.revwalk().unwrap(); walk.push(target).unwrap(); - let oids: Vec<::Oid> = walk.by_ref().collect::, _>>() - .unwrap(); + let oids: Vec<::Oid> = walk.by_ref().collect::, _>>().unwrap(); assert_eq!(oids.len(), 1); assert_eq!(oids[0], target); diff --git a/src/signature.rs b/src/signature.rs index 61e7a8948a..a915b2dcb4 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -1,13 +1,13 @@ +use libc; use std::ffi::CString; +use std::fmt; use std::marker; use std::mem; use std::ptr; use std::str; -use std::fmt; -use libc; -use {raw, Error, Time}; use util::Binding; +use {raw, Error, Time}; /// A Signature is used to indicate authorship of various actions throughout the /// library. @@ -45,16 +45,19 @@ impl<'a> Signature<'a> { /// the time zone offset in minutes. /// /// Returns error if either `name` or `email` contain angle brackets. - pub fn new(name: &str, email: &str, time: &Time) - -> Result, Error> { + pub fn new(name: &str, email: &str, time: &Time) -> Result, Error> { ::init(); let mut ret = ptr::null_mut(); let name = try!(CString::new(name)); let email = try!(CString::new(email)); unsafe { - try_call!(raw::git_signature_new(&mut ret, name, email, - time.seconds() as raw::git_time_t, - time.offset_minutes() as libc::c_int)); + try_call!(raw::git_signature_new( + &mut ret, + name, + email, + time.seconds() as raw::git_time_t, + time.offset_minutes() as libc::c_int + )); Ok(Binding::from_raw(ret)) } } @@ -107,7 +110,9 @@ impl<'a> Binding for Signature<'a> { owned: true, } } - fn raw(&self) -> *mut raw::git_signature { self.raw } + fn raw(&self) -> *mut raw::git_signature { + self.raw + } } /// Creates a new signature from the give raw pointer, tied to the lifetime @@ -115,9 +120,7 @@ impl<'a> Binding for Signature<'a> { /// /// This function is unsafe as there is no guarantee that `raw` is valid for /// `'a` nor if it's a valid pointer. -pub unsafe fn from_raw_const<'b, T>(_lt: &'b T, - raw: *const raw::git_signature) - -> Signature<'b> { +pub unsafe fn from_raw_const<'b, T>(_lt: &'b T, raw: *const raw::git_signature) -> Signature<'b> { Signature { raw: raw as *mut raw::git_signature, _marker: marker::PhantomData, @@ -145,13 +148,14 @@ impl<'a> Drop for Signature<'a> { } impl<'a> fmt::Display for Signature<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} <{}>", - String::from_utf8_lossy(self.name_bytes()), - String::from_utf8_lossy(self.email_bytes())) + write!( + f, + "{} <{}>", + String::from_utf8_lossy(self.name_bytes()), + String::from_utf8_lossy(self.email_bytes()) + ) } - } #[cfg(test)] diff --git a/src/stash.rs b/src/stash.rs index fffcb2329b..6881f2d246 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -1,9 +1,9 @@ -use {raw, panic, Oid, StashApplyProgress}; -use std::ffi::{CStr}; -use util::{Binding}; -use libc::{c_int, c_char, size_t, c_void}; -use build::{CheckoutBuilder}; +use build::CheckoutBuilder; +use libc::{c_char, c_int, c_void, size_t}; +use std::ffi::CStr; use std::mem; +use util::Binding; +use {panic, raw, Oid, StashApplyProgress}; /// Stash application progress notification function. /// @@ -20,7 +20,7 @@ pub type StashCb<'a> = dyn FnMut(usize, &str, &Oid) -> bool + 'a; pub struct StashApplyOptions<'cb> { progress: Option>>, checkout_options: Option>, - raw_opts: raw::git_stash_apply_options + raw_opts: raw::git_stash_apply_options, } impl<'cb> Default for StashApplyOptions<'cb> { @@ -37,9 +37,10 @@ impl<'cb> StashApplyOptions<'cb> { checkout_options: None, raw_opts: unsafe { mem::zeroed() }, }; - assert_eq!(unsafe { - raw::git_stash_apply_init_options(&mut opts.raw_opts, 1) - }, 0); + assert_eq!( + unsafe { raw::git_stash_apply_init_options(&mut opts.raw_opts, 1) }, + 0 + ); opts } @@ -60,7 +61,8 @@ impl<'cb> StashApplyOptions<'cb> { /// Return `true` to continue processing, or `false` to /// abort the stash application. pub fn progress_cb(&mut self, callback: C) -> &mut StashApplyOptions<'cb> - where C: FnMut(StashApplyProgress) -> bool + 'cb + where + C: FnMut(StashApplyProgress) -> bool + 'cb, { self.progress = Some(Box::new(callback) as Box>); self.raw_opts.progress_cb = stash_apply_progress_cb; @@ -81,27 +83,34 @@ impl<'cb> StashApplyOptions<'cb> { #[allow(unused)] pub struct StashCbData<'a> { - pub callback: &'a mut StashCb<'a> + pub callback: &'a mut StashCb<'a>, } #[allow(unused)] -pub extern fn stash_cb(index: size_t, - message: *const c_char, - stash_id: *const raw::git_oid, - payload: *mut c_void) - -> c_int -{ +pub extern "C" fn stash_cb( + index: size_t, + message: *const c_char, + stash_id: *const raw::git_oid, + payload: *mut c_void, +) -> c_int { panic::wrap(|| unsafe { let mut data = &mut *(payload as *mut StashCbData); let res = { let mut callback = &mut data.callback; - callback(index, - CStr::from_ptr(message).to_str().unwrap(), - &Binding::from_raw(stash_id)) + callback( + index, + CStr::from_ptr(message).to_str().unwrap(), + &Binding::from_raw(stash_id), + ) }; - if res { 0 } else { 1 } - }).unwrap_or(1) + if res { + 0 + } else { + 1 + } + }) + .unwrap_or(1) } fn convert_progress(progress: raw::git_stash_apply_progress_t) -> StashApplyProgress { @@ -115,15 +124,15 @@ fn convert_progress(progress: raw::git_stash_apply_progress_t) -> StashApplyProg raw::GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED => StashApplyProgress::CheckoutModified, raw::GIT_STASH_APPLY_PROGRESS_DONE => StashApplyProgress::Done, - _ => StashApplyProgress::None + _ => StashApplyProgress::None, } } #[allow(unused)] -extern fn stash_apply_progress_cb(progress: raw::git_stash_apply_progress_t, - payload: *mut c_void) - -> c_int -{ +extern "C" fn stash_apply_progress_cb( + progress: raw::git_stash_apply_progress_t, + payload: *mut c_void, +) -> c_int { panic::wrap(|| unsafe { let mut options = &mut *(payload as *mut StashApplyOptions); let res = { @@ -131,32 +140,43 @@ extern fn stash_apply_progress_cb(progress: raw::git_stash_apply_progress_t, callback(convert_progress(progress)) }; - if res { 0 } else { -1 } - }).unwrap_or(-1) + if res { + 0 + } else { + -1 + } + }) + .unwrap_or(-1) } #[cfg(test)] mod tests { - use stash::{StashApplyOptions}; - use std::io::{Write}; + use stash::StashApplyOptions; use std::fs; + use std::io::Write; use std::path::Path; - use test::{repo_init}; - use {Repository, Status, StashFlags}; + use test::repo_init; + use {Repository, StashFlags, Status}; - fn make_stash(next: C) where C: FnOnce(&mut Repository) { + fn make_stash(next: C) + where + C: FnOnce(&mut Repository), + { let (_td, mut repo) = repo_init(); let signature = repo.signature().unwrap(); let p = Path::new(repo.workdir().unwrap()).join("file_b.txt"); println!("using path {:?}", p); - fs::File::create(&p).unwrap() - .write("data".as_bytes()).unwrap(); + fs::File::create(&p) + .unwrap() + .write("data".as_bytes()) + .unwrap(); let rel_p = Path::new("file_b.txt"); assert!(repo.status_file(&rel_p).unwrap() == Status::WT_NEW); - repo.stash_save(&signature, "msg1", Some(StashFlags::INCLUDE_UNTRACKED)).unwrap(); + repo.stash_save(&signature, "msg1", Some(StashFlags::INCLUDE_UNTRACKED)) + .unwrap(); assert!(repo.status_file(&rel_p).is_err()); @@ -166,7 +186,8 @@ mod tests { assert!(index == 0); assert!(name == "On master: msg1"); true - }).unwrap(); + }) + .unwrap(); assert!(count == 1); next(&mut repo); @@ -174,7 +195,11 @@ mod tests { fn count_stash(repo: &mut Repository) -> usize { let mut count = 0; - repo.stash_foreach(|_, _, _| { count += 1; true }).unwrap(); + repo.stash_foreach(|_, _, _| { + count += 1; + true + }) + .unwrap(); count } diff --git a/src/status.rs b/src/status.rs index cb67305e47..baef097eb5 100644 --- a/src/status.rs +++ b/src/status.rs @@ -1,12 +1,12 @@ +use libc::{c_char, c_uint, size_t}; use std::ffi::CString; -use std::ops::Range; use std::marker; use std::mem; +use std::ops::Range; use std::str; -use libc::{c_char, size_t, c_uint}; -use {raw, Status, DiffDelta, IntoCString, Repository}; use util::Binding; +use {raw, DiffDelta, IntoCString, Repository, Status}; /// Options that can be provided to `repo.statuses()` to control how the status /// information is gathered. @@ -69,8 +69,7 @@ impl StatusOptions { pub fn new() -> StatusOptions { unsafe { let mut raw = mem::zeroed(); - let r = raw::git_status_init_options(&mut raw, - raw::GIT_STATUS_OPTIONS_VERSION); + let r = raw::git_status_init_options(&mut raw, raw::GIT_STATUS_OPTIONS_VERSION); assert_eq!(r, 0); StatusOptions { raw: raw, @@ -98,16 +97,14 @@ impl StatusOptions { /// If the `disable_pathspec_match` option is given, then this is a literal /// path to match. If this is not called, then there will be no patterns to /// match and the entire directory will be used. - pub fn pathspec(&mut self, pathspec: T) - -> &mut StatusOptions { + pub fn pathspec(&mut self, pathspec: T) -> &mut StatusOptions { let s = pathspec.into_c_string().unwrap(); self.ptrs.push(s.as_ptr()); self.pathspec.push(s); self } - fn flag(&mut self, flag: raw::git_status_opt_t, val: bool) - -> &mut StatusOptions { + fn flag(&mut self, flag: raw::git_status_opt_t, val: bool) -> &mut StatusOptions { if val { self.raw.flags |= flag as c_uint; } else { @@ -149,55 +146,47 @@ impl StatusOptions { /// /// Normally if an entire directory is new then just the top-level directory /// is included (with a trailing slash on the entry name). - pub fn recurse_untracked_dirs(&mut self, include: bool) - -> &mut StatusOptions { + pub fn recurse_untracked_dirs(&mut self, include: bool) -> &mut StatusOptions { self.flag(raw::GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS, include) } /// Indicates that the given paths should be treated as literals paths, note /// patterns. - pub fn disable_pathspec_match(&mut self, include: bool) - -> &mut StatusOptions { + pub fn disable_pathspec_match(&mut self, include: bool) -> &mut StatusOptions { self.flag(raw::GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH, include) } /// Indicates that the contents of ignored directories should be included in /// the status. - pub fn recurse_ignored_dirs(&mut self, include: bool) - -> &mut StatusOptions { + pub fn recurse_ignored_dirs(&mut self, include: bool) -> &mut StatusOptions { self.flag(raw::GIT_STATUS_OPT_RECURSE_IGNORED_DIRS, include) } /// Indicates that rename detection should be processed between the head. - pub fn renames_head_to_index(&mut self, include: bool) - -> &mut StatusOptions { + pub fn renames_head_to_index(&mut self, include: bool) -> &mut StatusOptions { self.flag(raw::GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX, include) } /// Indicates that rename detection should be run between the index and the /// working directory. - pub fn renames_index_to_workdir(&mut self, include: bool) - -> &mut StatusOptions { + pub fn renames_index_to_workdir(&mut self, include: bool) -> &mut StatusOptions { self.flag(raw::GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR, include) } /// Override the native case sensitivity for the file system and force the /// output to be in case sensitive order. - pub fn sort_case_sensitively(&mut self, include: bool) - -> &mut StatusOptions { + pub fn sort_case_sensitively(&mut self, include: bool) -> &mut StatusOptions { self.flag(raw::GIT_STATUS_OPT_SORT_CASE_SENSITIVELY, include) } /// Override the native case sensitivity for the file system and force the /// output to be in case-insensitive order. - pub fn sort_case_insensitively(&mut self, include: bool) - -> &mut StatusOptions { + pub fn sort_case_insensitively(&mut self, include: bool) -> &mut StatusOptions { self.flag(raw::GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY, include) } /// Indicates that rename detection should include rewritten files. - pub fn renames_from_rewrites(&mut self, include: bool) - -> &mut StatusOptions { + pub fn renames_from_rewrites(&mut self, include: bool) -> &mut StatusOptions { self.flag(raw::GIT_STATUS_OPT_RENAMES_FROM_REWRITES, include) } @@ -223,8 +212,7 @@ impl StatusOptions { // erm... #[allow(missing_docs)] - pub fn include_unreadable_as_untracked(&mut self, include: bool) - -> &mut StatusOptions { + pub fn include_unreadable_as_untracked(&mut self, include: bool) -> &mut StatusOptions { self.flag(raw::GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED, include) } @@ -275,14 +263,21 @@ impl<'repo> Statuses<'repo> { impl<'repo> Binding for Statuses<'repo> { type Raw = *mut raw::git_status_list; unsafe fn from_raw(raw: *mut raw::git_status_list) -> Statuses<'repo> { - Statuses { raw: raw, _marker: marker::PhantomData } + Statuses { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_status_list { + self.raw } - fn raw(&self) -> *mut raw::git_status_list { self.raw } } impl<'repo> Drop for Statuses<'repo> { fn drop(&mut self) { - unsafe { raw::git_status_list_free(self.raw); } + unsafe { + raw::git_status_list_free(self.raw); + } } } @@ -291,7 +286,9 @@ impl<'a> Iterator for StatusIter<'a> { fn next(&mut self) -> Option> { self.range.next().and_then(|i| self.statuses.get(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'a> DoubleEndedIterator for StatusIter<'a> { fn next_back(&mut self) -> Option> { @@ -308,14 +305,17 @@ impl<'statuses> StatusEntry<'statuses> { ::opt_bytes(self, (*(*self.raw).index_to_workdir).old_file.path) } else { ::opt_bytes(self, (*(*self.raw).head_to_index).old_file.path) - }.unwrap() + } + .unwrap() } } /// Access this entry's path name as a string. /// /// Returns `None` if the path is not valid utf-8. - pub fn path(&self) -> Option<&str> { str::from_utf8(self.path_bytes()).ok() } + pub fn path(&self) -> Option<&str> { + str::from_utf8(self.path_bytes()).ok() + } /// Access the status flags for this file pub fn status(&self) -> Status { @@ -325,36 +325,36 @@ impl<'statuses> StatusEntry<'statuses> { /// Access detailed information about the differences between the file in /// HEAD and the file in the index. pub fn head_to_index(&self) -> Option> { - unsafe { - Binding::from_raw_opt((*self.raw).head_to_index) - } + unsafe { Binding::from_raw_opt((*self.raw).head_to_index) } } /// Access detailed information about the differences between the file in /// the index and the file in the working directory. pub fn index_to_workdir(&self) -> Option> { - unsafe { - Binding::from_raw_opt((*self.raw).index_to_workdir) - } + unsafe { Binding::from_raw_opt((*self.raw).index_to_workdir) } } } impl<'statuses> Binding for StatusEntry<'statuses> { type Raw = *const raw::git_status_entry; - unsafe fn from_raw(raw: *const raw::git_status_entry) - -> StatusEntry<'statuses> { - StatusEntry { raw: raw, _marker: marker::PhantomData } + unsafe fn from_raw(raw: *const raw::git_status_entry) -> StatusEntry<'statuses> { + StatusEntry { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *const raw::git_status_entry { + self.raw } - fn raw(&self) -> *const raw::git_status_entry { self.raw } } #[cfg(test)] mod tests { + use super::StatusOptions; use std::fs::File; - use std::path::Path; use std::io::prelude::*; - use super::StatusOptions; + use std::path::Path; #[test] fn smoke() { @@ -379,8 +379,7 @@ mod tests { t!(File::create(&td.path().join("foo"))); t!(File::create(&td.path().join("bar"))); let mut opts = StatusOptions::new(); - opts.include_untracked(true) - .pathspec("foo"); + opts.include_untracked(true).pathspec("foo"); let statuses = t!(repo.statuses(Some(&mut opts))); assert_eq!(statuses.iter().count(), 1); diff --git a/src/string_array.rs b/src/string_array.rs index 97af2090e1..8c23b0cb32 100644 --- a/src/string_array.rs +++ b/src/string_array.rs @@ -1,7 +1,7 @@ //! Bindings to libgit2's raw `git_strarray` type -use std::str; use std::ops::Range; +use std::str; use raw; use util::Binding; @@ -50,20 +50,30 @@ impl StringArray { /// The iterator yields `Option<&str>` as it is unknown whether the contents /// are utf-8 or not. pub fn iter(&self) -> Iter { - Iter { range: 0..self.len(), arr: self } + Iter { + range: 0..self.len(), + arr: self, + } } /// Returns an iterator over the strings contained within this array, /// yielding byte slices. pub fn iter_bytes(&self) -> IterBytes { - IterBytes { range: 0..self.len(), arr: self } + IterBytes { + range: 0..self.len(), + arr: self, + } } /// Returns the number of strings in this array. - pub fn len(&self) -> usize { self.raw.count as usize } + pub fn len(&self) -> usize { + self.raw.count as usize + } /// Return `true` if this array is empty. - pub fn is_empty(&self) -> bool { self.len() == 0 } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl Binding for StringArray { @@ -71,7 +81,9 @@ impl Binding for StringArray { unsafe fn from_raw(raw: raw::git_strarray) -> StringArray { StringArray { raw: raw } } - fn raw(&self) -> raw::git_strarray { self.raw } + fn raw(&self) -> raw::git_strarray { + self.raw + } } impl<'a> IntoIterator for &'a StringArray { @@ -87,7 +99,9 @@ impl<'a> Iterator for Iter<'a> { fn next(&mut self) -> Option> { self.range.next().map(|i| self.arr.get(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'a> DoubleEndedIterator for Iter<'a> { fn next_back(&mut self) -> Option> { @@ -101,7 +115,9 @@ impl<'a> Iterator for IterBytes<'a> { fn next(&mut self) -> Option<&'a [u8]> { self.range.next().and_then(|i| self.arr.get_bytes(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'a> DoubleEndedIterator for IterBytes<'a> { fn next_back(&mut self) -> Option<&'a [u8]> { diff --git a/src/submodule.rs b/src/submodule.rs index 64c7ec87e7..26e6224ea2 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -1,13 +1,13 @@ use std::marker; use std::mem; -use std::ptr; -use std::str; use std::os::raw::c_int; use std::path::Path; +use std::ptr; +use std::str; -use {raw, Oid, Repository, Error, FetchOptions}; use build::CheckoutBuilder; use util::{self, Binding}; +use {raw, Error, FetchOptions, Oid, Repository}; /// A structure to represent a git [submodule][1] /// @@ -30,9 +30,7 @@ impl<'repo> Submodule<'repo> { /// /// Returns `None` if the branch is not yet available. pub fn branch_bytes(&self) -> Option<&[u8]> { - unsafe { - ::opt_bytes(self, raw::git_submodule_branch(self.raw)) - } + unsafe { ::opt_bytes(self, raw::git_submodule_branch(self.raw)) } } /// Get the submodule's url. @@ -55,42 +53,34 @@ impl<'repo> Submodule<'repo> { // TODO: delete this method and fix the signature of `url_bytes` on next // major version bump pub fn opt_url_bytes(&self) -> Option<&[u8]> { - unsafe { - ::opt_bytes(self, raw::git_submodule_url(https://github.com/self.raw)) - } + unsafe { ::opt_bytes(self, raw::git_submodule_url(https://github.com/self.raw)) } } /// Get the submodule's name. /// /// Returns `None` if the name is not valid utf-8 - pub fn name(&self) -> Option<&str> { str::from_utf8(self.name_bytes()).ok() } + pub fn name(&self) -> Option<&str> { + str::from_utf8(self.name_bytes()).ok() + } /// Get the name for the submodule. pub fn name_bytes(&self) -> &[u8] { - unsafe { - ::opt_bytes(self, raw::git_submodule_name(self.raw)).unwrap() - } + unsafe { ::opt_bytes(self, raw::git_submodule_name(self.raw)).unwrap() } } /// Get the path for the submodule. pub fn path(&self) -> &Path { - util::bytes2path(unsafe { - ::opt_bytes(self, raw::git_submodule_path(self.raw)).unwrap() - }) + util::bytes2path(unsafe { ::opt_bytes(self, raw::git_submodule_path(self.raw)).unwrap() }) } /// Get the OID for the submodule in the current HEAD tree. pub fn head_id(&self) -> Option { - unsafe { - Binding::from_raw_opt(raw::git_submodule_head_id(self.raw)) - } + unsafe { Binding::from_raw_opt(raw::git_submodule_head_id(self.raw)) } } /// Get the OID for the submodule in the index. pub fn index_id(&self) -> Option { - unsafe { - Binding::from_raw_opt(raw::git_submodule_index_id(self.raw)) - } + unsafe { Binding::from_raw_opt(raw::git_submodule_index_id(self.raw)) } } /// Get the OID for the submodule in the current working directory. @@ -99,9 +89,7 @@ impl<'repo> Submodule<'repo> { /// checked out submodule. If there are pending changes in the index or /// anything else, this won't notice that. pub fn workdir_id(&self) -> Option { - unsafe { - Binding::from_raw_opt(raw::git_submodule_wd_id(self.raw)) - } + unsafe { Binding::from_raw_opt(raw::git_submodule_wd_id(self.raw)) } } /// Copy submodule info into ".git/config" file. @@ -153,7 +141,9 @@ impl<'repo> Submodule<'repo> { /// if you have altered the URL for the submodule (or it has been altered /// by a fetch of upstream changes) and you need to update your local repo. pub fn sync(&mut self) -> Result<(), Error> { - unsafe { try_call!(raw::git_submodule_sync(self.raw)); } + unsafe { + try_call!(raw::git_submodule_sync(self.raw)); + } Ok(()) } @@ -176,7 +166,9 @@ impl<'repo> Submodule<'repo> { /// newly cloned submodule to the index to be ready to be committed (but /// doesn't actually do the commit). pub fn add_finalize(&mut self) -> Result<(), Error> { - unsafe { try_call!(raw::git_submodule_add_finalize(self.raw)); } + unsafe { + try_call!(raw::git_submodule_add_finalize(self.raw)); + } Ok(()) } @@ -189,13 +181,18 @@ impl<'repo> Submodule<'repo> { /// /// `init` indicates if the submodule should be initialized first if it has /// not been initialized yet. - pub fn update(&mut self, init: bool, - opts: Option<&mut SubmoduleUpdateOptions>) - -> Result<(), Error> { + pub fn update( + &mut self, + init: bool, + opts: Option<&mut SubmoduleUpdateOptions>, + ) -> Result<(), Error> { unsafe { let mut raw_opts = opts.map(|o| o.raw()); - try_call!(raw::git_submodule_update(self.raw, init as c_int, - raw_opts.as_mut().map_or(ptr::null_mut(), |o| o))); + try_call!(raw::git_submodule_update( + self.raw, + init as c_int, + raw_opts.as_mut().map_or(ptr::null_mut(), |o| o) + )); } Ok(()) } @@ -204,9 +201,14 @@ impl<'repo> Submodule<'repo> { impl<'repo> Binding for Submodule<'repo> { type Raw = *mut raw::git_submodule; unsafe fn from_raw(raw: *mut raw::git_submodule) -> Submodule<'repo> { - Submodule { raw: raw, _marker: marker::PhantomData } + Submodule { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_submodule { + self.raw } - fn raw(&self) -> *mut raw::git_submodule { self.raw } } impl<'repo> Drop for Submodule<'repo> { @@ -234,8 +236,8 @@ impl<'cb> SubmoduleUpdateOptions<'cb> { unsafe fn raw(&mut self) -> raw::git_submodule_update_options { let mut checkout_opts: raw::git_checkout_options = mem::zeroed(); - let init_res = raw::git_checkout_init_options(&mut checkout_opts, - raw::GIT_CHECKOUT_OPTIONS_VERSION); + let init_res = + raw::git_checkout_init_options(&mut checkout_opts, raw::GIT_CHECKOUT_OPTIONS_VERSION); assert_eq!(0, init_res); self.checkout_builder.configure(&mut checkout_opts); let opts = raw::git_submodule_update_options { @@ -275,8 +277,8 @@ impl<'cb> Default for SubmoduleUpdateOptions<'cb> { #[cfg(test)] mod tests { - use std::path::Path; use std::fs; + use std::path::Path; use tempdir::TempDir; use url::Url; @@ -287,13 +289,15 @@ mod tests { fn smoke() { let td = TempDir::new("test").unwrap(); let repo = Repository::init(td.path()).unwrap(); - let mut s1 = repo.submodule("/path/to/nowhere", - Path::new("foo"), true).unwrap(); + let mut s1 = repo + .submodule("/path/to/nowhere", Path::new("foo"), true) + .unwrap(); s1.init(false).unwrap(); s1.sync().unwrap(); - let s2 = repo.submodule("/path/to/nowhere", - Path::new("bar"), true).unwrap(); + let s2 = repo + .submodule("/path/to/nowhere", Path::new("bar"), true) + .unwrap(); drop((s1, s2)); let mut submodules = repo.submodules().unwrap(); @@ -318,11 +322,11 @@ mod tests { let (td, repo2) = ::test::repo_init(); let url = Url::from_file_path(&repo1.workdir().unwrap()).unwrap(); - let mut s = repo2.submodule(&url.to_string(), Path::new("bar"), - true).unwrap(); + let mut s = repo2 + .submodule(&url.to_string(), Path::new("bar"), true) + .unwrap(); t!(fs::remove_dir_all(td.path().join("bar"))); - t!(Repository::clone(&url.to_string(), - td.path().join("bar"))); + t!(Repository::clone(&url.to_string(), td.path().join("bar"))); t!(s.add_to_index(false)); t!(s.add_finalize()); } @@ -335,11 +339,11 @@ mod tests { let (td, repo2) = ::test::repo_init(); let url = Url::from_file_path(&repo1.workdir().unwrap()).unwrap(); - let mut s = repo2.submodule(&url.to_string(), Path::new("bar"), - true).unwrap(); + let mut s = repo2 + .submodule(&url.to_string(), Path::new("bar"), true) + .unwrap(); t!(fs::remove_dir_all(td.path().join("bar"))); - t!(Repository::clone(&url.to_string(), - td.path().join("bar"))); + t!(Repository::clone(&url.to_string(), td.path().join("bar"))); t!(s.add_to_index(false)); t!(s.add_finalize()); // ----------------------------------- diff --git a/src/tag.rs b/src/tag.rs index 8041f3546a..2442a8b30a 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -3,8 +3,8 @@ use std::mem; use std::ptr; use std::str; -use {raw, signature, Error, Oid, Object, Signature, ObjectType}; use util::Binding; +use {raw, signature, Error, Object, ObjectType, Oid, Signature}; /// A structure to represent a git [tag][1] /// @@ -93,17 +93,13 @@ impl<'repo> Tag<'repo> { /// Casts this Tag to be usable as an `Object` pub fn as_object(&self) -> &Object<'repo> { - unsafe { - &*(self as *const _ as *const Object<'repo>) - } + unsafe { &*(self as *const _ as *const Object<'repo>) } } /// Consumes Tag to be returned as an `Object` pub fn into_object(self) -> Object<'repo> { assert_eq!(mem::size_of_val(&self), mem::size_of::()); - unsafe { - mem::transmute(self) - } + unsafe { mem::transmute(self) } } } @@ -121,9 +117,14 @@ impl<'repo> ::std::fmt::Debug for Tag<'repo> { impl<'repo> Binding for Tag<'repo> { type Raw = *mut raw::git_tag; unsafe fn from_raw(raw: *mut raw::git_tag) -> Tag<'repo> { - Tag { raw: raw, _marker: marker::PhantomData } + Tag { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_tag { + self.raw } - fn raw(&self) -> *mut raw::git_tag { self.raw } } impl<'repo> Clone for Tag<'repo> { @@ -168,7 +169,11 @@ mod tests { tag.into_object(); repo.find_object(tag_id, None).unwrap().as_tag().unwrap(); - repo.find_object(tag_id, None).unwrap().into_tag().ok().unwrap(); + repo.find_object(tag_id, None) + .unwrap() + .into_tag() + .ok() + .unwrap(); repo.tag_delete("foo").unwrap(); } diff --git a/src/test.rs b/src/test.rs index 00b5f46d80..5fed0a7882 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,5 +1,5 @@ -use std::path::{Path, PathBuf}; use std::io; +use std::path::{Path, PathBuf}; #[cfg(unix)] use std::ptr; use tempdir::TempDir; @@ -8,10 +8,12 @@ use url::Url; use Repository; macro_rules! t { - ($e:expr) => (match $e { - Ok(e) => e, - Err(e) => panic!("{} failed with {}", stringify!($e), e), - }) + ($e:expr) => { + match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + } + }; } pub fn repo_init() -> (TempDir, Repository) { @@ -26,8 +28,8 @@ pub fn repo_init() -> (TempDir, Repository) { let tree = repo.find_tree(id).unwrap(); let sig = repo.signature().unwrap(); - repo.commit(Some("HEAD"), &sig, &sig, "initial", - &tree, &[]).unwrap(); + repo.commit(Some("HEAD"), &sig, &sig, "initial", &tree, &[]) + .unwrap(); } (td, repo) } @@ -42,17 +44,17 @@ pub fn realpath(original: &Path) -> io::Result { } #[cfg(unix)] pub fn realpath(original: &Path) -> io::Result { - use std::ffi::{CStr, OsString, CString}; - use std::os::unix::prelude::*; use libc::c_char; - extern { + use std::ffi::{CStr, CString, OsString}; + use std::os::unix::prelude::*; + extern "C" { fn realpath(name: *const c_char, resolved: *mut c_char) -> *mut c_char; } unsafe { let cstr = try!(CString::new(original.as_os_str().as_bytes())); let ptr = realpath(cstr.as_ptr(), ptr::null_mut()); if ptr.is_null() { - return Err(io::Error::last_os_error()) + return Err(io::Error::last_os_error()); } let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); libc::free(ptr as *mut _); diff --git a/src/time.rs b/src/time.rs index 57a5a70a39..69508e37e0 100644 --- a/src/time.rs +++ b/src/time.rs @@ -1,6 +1,6 @@ use std::cmp::Ordering; -use libc::{c_int, c_char}; +use libc::{c_char, c_int}; use raw; use util::Binding; @@ -30,14 +30,20 @@ impl Time { } /// Return the time, in seconds, from epoch - pub fn seconds(&self) -> i64 { self.raw.time as i64 } + pub fn seconds(&self) -> i64 { + self.raw.time as i64 + } /// Return the timezone offset, in minutes - pub fn offset_minutes(&self) -> i32 { self.raw.offset as i32 } + pub fn offset_minutes(&self) -> i32 { + self.raw.offset as i32 + } /// Return whether the offset was positive or negative. Primarily useful /// in case the offset is specified as a negative zero. - pub fn sign(&self) -> char { self.raw.offset as u8 as char } + pub fn sign(&self) -> char { + self.raw.offset as u8 as char + } } impl PartialOrd for Time { @@ -57,7 +63,9 @@ impl Binding for Time { unsafe fn from_raw(raw: raw::git_time) -> Time { Time { raw: raw } } - fn raw(&self) -> raw::git_time { self.raw } + fn raw(&self) -> raw::git_time { + self.raw + } } impl IndexTime { @@ -72,9 +80,13 @@ impl IndexTime { } /// Returns the number of seconds in the second component of this time. - pub fn seconds(&self) -> i32 { self.raw.seconds } + pub fn seconds(&self) -> i32 { + self.raw.seconds + } /// Returns the nanosecond component of this time. - pub fn nanoseconds(&self) -> u32 { self.raw.nanoseconds } + pub fn nanoseconds(&self) -> u32 { + self.raw.nanoseconds + } } impl Binding for IndexTime { @@ -82,7 +94,9 @@ impl Binding for IndexTime { unsafe fn from_raw(raw: raw::git_index_time) -> IndexTime { IndexTime { raw: raw } } - fn raw(&self) -> raw::git_index_time { self.raw } + fn raw(&self) -> raw::git_index_time { + self.raw + } } impl PartialOrd for IndexTime { diff --git a/src/transport.rs b/src/transport.rs index 52d39b8a84..53e2e13208 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -1,16 +1,16 @@ //! Interfaces for adding custom transports to libgit2 +use libc::{c_char, c_int, c_uint, c_void, size_t}; use std::ffi::{CStr, CString}; -use std::io::prelude::*; use std::io; +use std::io::prelude::*; use std::mem; -use std::slice; use std::ptr; +use std::slice; use std::str; -use libc::{c_int, c_void, c_uint, c_char, size_t}; -use {raw, panic, Error, Remote}; use util::Binding; +use {panic, raw, Error, Remote}; /// A transport is a structure which knows how to transfer data to and from a /// remote. @@ -40,7 +40,7 @@ pub trait SmartSubtransport: Send + 'static { /// returns a stream which can be read and written from in order to /// negotiate the git protocol. fn action(&self, url: &str, action: Service) - -> Result, Error>; + -> Result, Error>; /// Terminates a connection with the remote. /// @@ -73,8 +73,7 @@ pub trait SmartSubtransportStream: Read + Write + Send + 'static {} impl SmartSubtransportStream for T {} -type TransportFactory = dyn Fn(&Remote) -> Result + Send + Sync + - 'static; +type TransportFactory = dyn Fn(&Remote) -> Result + Send + Sync + 'static; /// Boxed data payload used for registering new transports. /// @@ -105,7 +104,8 @@ struct RawSmartSubtransportStream { /// This function is unsafe as it needs to be externally synchronized with calls /// to creation of other transports. pub unsafe fn register(prefix: &str, factory: F) -> Result<(), Error> - where F: Fn(&Remote) -> Result + Send + Sync + 'static +where + F: Fn(&Remote) -> Result + Send + Sync + 'static, { ::init(); let mut data = Box::new(TransportData { @@ -113,9 +113,11 @@ pub unsafe fn register(prefix: &str, factory: F) -> Result<(), Error> }); let prefix = try!(CString::new(prefix)); let datap = (&mut *data) as *mut TransportData as *mut c_void; - try_call!(raw::git_transport_register(prefix, - transport_factory, - datap)); + try_call!(raw::git_transport_register( + prefix, + transport_factory, + datap + )); mem::forget(data); Ok(()) } @@ -131,10 +133,9 @@ impl Transport { /// /// The `rpc` argument is `true` if the protocol is stateless, false /// otherwise. For example `http://` is stateless but `git://` is not. - pub fn smart(remote: &Remote, - rpc: bool, - subtransport: S) -> Result - where S: SmartSubtransport + pub fn smart(remote: &Remote, rpc: bool, subtransport: S) -> Result + where + S: SmartSubtransport, { let mut ret = ptr::null_mut(); @@ -161,15 +162,23 @@ impl Transport { // `RawSmartSubtransport`). This also means that this block must be // entirely synchronized with a lock (boo!) unsafe { - try_call!(raw::git_transport_smart(&mut ret, remote.raw(), - &mut defn as *mut _ as *mut _)); + try_call!(raw::git_transport_smart( + &mut ret, + remote.raw(), + &mut defn as *mut _ as *mut _ + )); mem::forget(raw); // ownership transport to `ret` } - return Ok(Transport { raw: ret, owned: true }); + return Ok(Transport { + raw: ret, + owned: true, + }); - extern fn smart_factory(out: *mut *mut raw::git_smart_subtransport, - _owner: *mut raw::git_transport, - ptr: *mut c_void) -> c_int { + extern "C" fn smart_factory( + out: *mut *mut raw::git_smart_subtransport, + _owner: *mut raw::git_transport, + ptr: *mut c_void, + ) -> c_int { unsafe { *out = ptr as *mut raw::git_smart_subtransport; 0 @@ -181,18 +190,20 @@ impl Transport { impl Drop for Transport { fn drop(&mut self) { if self.owned { - unsafe { - ((*self.raw).free)(self.raw) - } + unsafe { ((*self.raw).free)(self.raw) } } } } // callback used by register() to create new transports -extern fn transport_factory(out: *mut *mut raw::git_transport, - owner: *mut raw::git_remote, - param: *mut c_void) -> c_int { - struct Bomb<'a> { remote: Option> } +extern "C" fn transport_factory( + out: *mut *mut raw::git_transport, + owner: *mut raw::git_remote, + param: *mut c_void, +) -> c_int { + struct Bomb<'a> { + remote: Option>, + } impl<'a> Drop for Bomb<'a> { fn drop(&mut self) { // TODO: maybe a method instead? @@ -201,7 +212,9 @@ extern fn transport_factory(out: *mut *mut raw::git_transport, } panic::wrap(|| unsafe { - let remote = Bomb { remote: Some(Binding::from_raw(owner)) }; + let remote = Bomb { + remote: Some(Binding::from_raw(owner)), + }; let data = &mut *(param as *mut TransportData); match (data.factory)(remote.remote.as_ref().unwrap()) { Ok(mut transport) => { @@ -211,15 +224,18 @@ extern fn transport_factory(out: *mut *mut raw::git_transport, } Err(e) => e.raw_code() as c_int, } - }).unwrap_or(-1) + }) + .unwrap_or(-1) } // callback used by smart transports to delegate an action to a // `SmartSubtransport` trait object. -extern fn subtransport_action(stream: *mut *mut raw::git_smart_subtransport_stream, - raw_transport: *mut raw::git_smart_subtransport, - url: *const c_char, - action: raw::git_smart_service_t) -> c_int { +extern "C" fn subtransport_action( + stream: *mut *mut raw::git_smart_subtransport_stream, + raw_transport: *mut raw::git_smart_subtransport, + url: *const c_char, + action: raw::git_smart_service_t, +) -> c_int { panic::wrap(|| unsafe { let url = CStr::from_ptr(url).to_bytes(); let url = match str::from_utf8(url).ok() { @@ -248,13 +264,13 @@ extern fn subtransport_action(stream: *mut *mut raw::git_smart_subtransport_stre obj: obj, })); 0 - }).unwrap_or(-1) + }) + .unwrap_or(-1) } // callback used by smart transports to close a `SmartSubtransport` trait // object. -extern fn subtransport_close(transport: *mut raw::git_smart_subtransport) - -> c_int { +extern "C" fn subtransport_close(transport: *mut raw::git_smart_subtransport) -> c_int { let ret = panic::wrap(|| unsafe { let transport = &mut *(transport as *mut RawSmartSubtransport); transport.obj.close() @@ -268,7 +284,7 @@ extern fn subtransport_close(transport: *mut raw::git_smart_subtransport) // callback used by smart transports to free a `SmartSubtransport` trait // object. -extern fn subtransport_free(transport: *mut raw::git_smart_subtransport) { +extern "C" fn subtransport_free(transport: *mut raw::git_smart_subtransport) { let _ = panic::wrap(|| unsafe { mem::transmute::<_, Box>(transport); }); @@ -276,31 +292,40 @@ extern fn subtransport_free(transport: *mut raw::git_smart_subtransport) { // callback used by smart transports to read from a `SmartSubtransportStream` // object. -extern fn stream_read(stream: *mut raw::git_smart_subtransport_stream, - buffer: *mut c_char, - buf_size: size_t, - bytes_read: *mut size_t) -> c_int { +extern "C" fn stream_read( + stream: *mut raw::git_smart_subtransport_stream, + buffer: *mut c_char, + buf_size: size_t, + bytes_read: *mut size_t, +) -> c_int { let ret = panic::wrap(|| unsafe { let transport = &mut *(stream as *mut RawSmartSubtransportStream); - let buf = slice::from_raw_parts_mut(buffer as *mut u8, - buf_size as usize); + let buf = slice::from_raw_parts_mut(buffer as *mut u8, buf_size as usize); match transport.obj.read(buf) { - Ok(n) => { *bytes_read = n as size_t; Ok(n) } + Ok(n) => { + *bytes_read = n as size_t; + Ok(n) + } e => e, } }); match ret { Some(Ok(_)) => 0, - Some(Err(e)) => unsafe { set_err(&e); -2 }, + Some(Err(e)) => unsafe { + set_err(&e); + -2 + }, None => -1, } } // callback used by smart transports to write to a `SmartSubtransportStream` // object. -extern fn stream_write(stream: *mut raw::git_smart_subtransport_stream, - buffer: *const c_char, - len: size_t) -> c_int { +extern "C" fn stream_write( + stream: *mut raw::git_smart_subtransport_stream, + buffer: *const c_char, + len: size_t, +) -> c_int { let ret = panic::wrap(|| unsafe { let transport = &mut *(stream as *mut RawSmartSubtransportStream); let buf = slice::from_raw_parts(buffer as *const u8, len as usize); @@ -308,7 +333,10 @@ extern fn stream_write(stream: *mut raw::git_smart_subtransport_stream, }); match ret { Some(Ok(())) => 0, - Some(Err(e)) => unsafe { set_err(&e); -2 }, + Some(Err(e)) => unsafe { + set_err(&e); + -2 + }, None => -1, } } @@ -320,7 +348,7 @@ unsafe fn set_err(e: &io::Error) { // callback used by smart transports to free a `SmartSubtransportStream` // object. -extern fn stream_free(stream: *mut raw::git_smart_subtransport_stream) { +extern "C" fn stream_free(stream: *mut raw::git_smart_subtransport_stream) { let _ = panic::wrap(|| unsafe { mem::transmute::<_, Box>(stream); }); diff --git a/src/tree.rs b/src/tree.rs index 62be5a8674..02c46829fc 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,15 +1,15 @@ -use std::mem; +use libc::{self, c_char, c_int, c_void}; use std::cmp::Ordering; use std::ffi::{CStr, CString}; -use std::ops::Range; use std::marker; +use std::mem; +use std::ops::Range; use std::path::Path; use std::ptr; use std::str; -use libc::{self, c_int, c_char, c_void}; -use {panic, raw, Oid, Repository, Error, Object, ObjectType}; use util::{c_cmp_to_ordering, Binding, IntoCString}; +use {panic, raw, Error, Object, ObjectType, Oid, Repository}; /// A structure to represent a git [tree][1] /// @@ -88,7 +88,10 @@ impl<'repo> Tree<'repo> { /// Returns an iterator over the entries in this tree. pub fn iter(&self) -> TreeIter { - TreeIter { range: 0..self.len(), tree: self } + TreeIter { + range: 0..self.len(), + tree: self, + } } /// Traverse the entries in a tree and its subtrees in post or pre order. @@ -120,10 +123,12 @@ impl<'repo> Tree<'repo> { { #[allow(unused)] struct TreeWalkCbData<'a, T: 'a> { - pub callback: &'a mut TreeWalkCb<'a, T> + pub callback: &'a mut TreeWalkCb<'a, T>, } unsafe { - let mut data = TreeWalkCbData { callback: &mut callback }; + let mut data = TreeWalkCbData { + callback: &mut callback, + }; raw::git_tree_walk( self.raw(), mode.into(), @@ -149,8 +154,7 @@ impl<'repo> Tree<'repo> { /// Lookup a tree entry by its position in the tree pub fn get(&self, n: usize) -> Option { unsafe { - let ptr = raw::git_tree_entry_byindex(&*self.raw(), - n as libc::size_t); + let ptr = raw::git_tree_entry_byindex(&*self.raw(), n as libc::size_t); if ptr.is_null() { None } else { @@ -185,23 +189,23 @@ impl<'repo> Tree<'repo> { /// Casts this Tree to be usable as an `Object` pub fn as_object(&self) -> &Object<'repo> { - unsafe { - &*(self as *const _ as *const Object<'repo>) - } + unsafe { &*(self as *const _ as *const Object<'repo>) } } /// Consumes Commit to be returned as an `Object` pub fn into_object(self) -> Object<'repo> { assert_eq!(mem::size_of_val(&self), mem::size_of::()); - unsafe { - mem::transmute(self) - } + unsafe { mem::transmute(self) } } } type TreeWalkCb<'a, T> = dyn FnMut(&str, &TreeEntry) -> T + 'a; -extern fn treewalk_cb>(root: *const c_char, entry: *const raw::git_tree_entry, payload: *mut c_void) -> c_int { +extern "C" fn treewalk_cb>( + root: *const c_char, + entry: *const raw::git_tree_entry, + payload: *mut c_void, +) -> c_int { match panic::wrap(|| unsafe { let root = match CStr::from_ptr(root).to_str() { Ok(value) => value, @@ -220,9 +224,14 @@ impl<'repo> Binding for Tree<'repo> { type Raw = *mut raw::git_tree; unsafe fn from_raw(raw: *mut raw::git_tree) -> Tree<'repo> { - Tree { raw: raw, _marker: marker::PhantomData } + Tree { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_tree { + self.raw } - fn raw(&self) -> *mut raw::git_tree { self.raw } } impl<'repo> ::std::fmt::Debug for Tree<'repo> { @@ -255,8 +264,7 @@ impl<'repo, 'iter> IntoIterator for &'iter Tree<'repo> { /// /// The lifetime of the entry is tied to the tree provided and the function /// is unsafe because the validity of the pointer cannot be guaranteed. -pub unsafe fn entry_from_raw_const<'tree>(raw: *const raw::git_tree_entry) - -> TreeEntry<'tree> { +pub unsafe fn entry_from_raw_const<'tree>(raw: *const raw::git_tree_entry) -> TreeEntry<'tree> { TreeEntry { raw: raw as *mut raw::git_tree_entry, owned: false, @@ -279,18 +287,18 @@ impl<'tree> TreeEntry<'tree> { /// Get the filename of a tree entry pub fn name_bytes(&self) -> &[u8] { - unsafe { - ::opt_bytes(self, raw::git_tree_entry_name(&*self.raw())).unwrap() - } + unsafe { ::opt_bytes(self, raw::git_tree_entry_name(&*self.raw())).unwrap() } } /// Convert a tree entry to the object it points to. - pub fn to_object<'a>(&self, repo: &'a Repository) - -> Result, Error> { + pub fn to_object<'a>(&self, repo: &'a Repository) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { - try_call!(raw::git_tree_entry_to_object(&mut ret, repo.raw(), - &*self.raw())); + try_call!(raw::git_tree_entry_to_object( + &mut ret, + repo.raw(), + &*self.raw() + )); Ok(Binding::from_raw(ret)) } } @@ -331,7 +339,9 @@ impl<'a> Binding for TreeEntry<'a> { _marker: marker::PhantomData, } } - fn raw(&self) -> *mut raw::git_tree_entry { self.raw } + fn raw(&self) -> *mut raw::git_tree_entry { + self.raw + } } impl<'a> Clone for TreeEntry<'a> { @@ -375,7 +385,9 @@ impl<'tree> Iterator for TreeIter<'tree> { fn next(&mut self) -> Option> { self.range.next().and_then(|i| self.tree.get(i)) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } } impl<'tree> DoubleEndedIterator for TreeIter<'tree> { fn next_back(&mut self) -> Option> { @@ -386,12 +398,12 @@ impl<'tree> ExactSizeIterator for TreeIter<'tree> {} #[cfg(test)] mod tests { - use {Repository,Tree,TreeEntry,ObjectType,Object}; use super::{TreeWalkMode, TreeWalkResult}; - use tempdir::TempDir; use std::fs::File; use std::io::prelude::*; use std::path::Path; + use tempdir::TempDir; + use {Object, ObjectType, Repository, Tree, TreeEntry}; pub struct TestTreeIter<'a> { entries: Vec>, @@ -401,7 +413,7 @@ mod tests { impl<'a> Iterator for TestTreeIter<'a> { type Item = TreeEntry<'a>; - fn next(&mut self) -> Option > { + fn next(&mut self) -> Option> { if self.entries.is_empty() { None } else { @@ -425,8 +437,7 @@ mod tests { } } - fn tree_iter<'repo>(tree: &Tree<'repo>, repo: &'repo Repository) - -> TestTreeIter<'repo> { + fn tree_iter<'repo>(tree: &Tree<'repo>, repo: &'repo Repository) -> TestTreeIter<'repo> { let mut initial = vec![]; for entry in tree.iter() { @@ -460,15 +471,26 @@ mod tests { fn setup_repo(td: &TempDir, repo: &Repository) { let mut index = repo.index().unwrap(); - File::create(&td.path().join("foo")).unwrap().write_all(b"foo").unwrap(); + File::create(&td.path().join("foo")) + .unwrap() + .write_all(b"foo") + .unwrap(); index.add_path(Path::new("foo")).unwrap(); let id = index.write_tree().unwrap(); let sig = repo.signature().unwrap(); let tree = repo.find_tree(id).unwrap(); - let parent = repo.find_commit(repo.head().unwrap().target() - .unwrap()).unwrap(); - repo.commit(Some("HEAD"), &sig, &sig, "another commit", - &tree, &[&parent]).unwrap(); + let parent = repo + .find_commit(repo.head().unwrap().target().unwrap()) + .unwrap(); + repo.commit( + Some("HEAD"), + &sig, + &sig, + "another commit", + &tree, + &[&parent], + ) + .unwrap(); } #[test] @@ -494,8 +516,15 @@ mod tests { } tree.into_object(); - repo.find_object(commit.tree_id(), None).unwrap().as_tree().unwrap(); - repo.find_object(commit.tree_id(), None).unwrap().into_tree().ok().unwrap(); + repo.find_object(commit.tree_id(), None) + .unwrap() + .as_tree() + .unwrap(); + repo.find_object(commit.tree_id(), None) + .unwrap() + .into_tree() + .ok() + .unwrap(); } #[test] @@ -514,7 +543,8 @@ mod tests { assert_eq!(entry.name(), Some("foo")); ct += 1; 0 - }).unwrap(); + }) + .unwrap(); assert_eq!(ct, 1); let mut ct = 0; @@ -522,7 +552,8 @@ mod tests { assert_eq!(entry.name(), Some("foo")); ct += 1; TreeWalkResult::Ok - }).unwrap(); + }) + .unwrap(); assert_eq!(ct, 1); } } diff --git a/src/treebuilder.rs b/src/treebuilder.rs index 8a5600ac85..6eabf17f25 100644 --- a/src/treebuilder.rs +++ b/src/treebuilder.rs @@ -3,8 +3,8 @@ use std::ptr; use libc::{c_int, c_void}; -use {panic, raw, tree, Error, Oid, Repository, TreeEntry}; use util::{Binding, IntoCString}; +use {panic, raw, tree, Error, Oid, Repository, TreeEntry}; /// Constructor for in-memory trees pub struct TreeBuilder<'repo> { @@ -30,7 +30,8 @@ impl<'repo> TreeBuilder<'repo> { /// Get en entry from the builder from its filename pub fn get

(&self, filename: P) -> Result, Error> - where P: IntoCString + where + P: IntoCString, { let filename = try!(filename.into_c_string()); unsafe { @@ -50,15 +51,24 @@ impl<'repo> TreeBuilder<'repo> { /// /// The mode given must be one of 0o040000, 0o100644, 0o100755, 0o120000 or /// 0o160000 currently. - pub fn insert(&mut self, filename: P, oid: Oid, - filemode: i32) -> Result { + pub fn insert( + &mut self, + filename: P, + oid: Oid, + filemode: i32, + ) -> Result { let filename = try!(filename.into_c_string()); let filemode = filemode as raw::git_filemode_t; let mut ret = ptr::null(); unsafe { - try_call!(raw::git_treebuilder_insert(&mut ret, self.raw, filename, - oid.raw(), filemode)); + try_call!(raw::git_treebuilder_insert( + &mut ret, + self.raw, + filename, + oid.raw(), + filemode + )); Ok(tree::entry_from_raw_const(ret)) } } @@ -77,7 +87,8 @@ impl<'repo> TreeBuilder<'repo> { /// Values for which the filter returns `true` will be kept. Note /// that this behavior is different from the libgit2 C interface. pub fn filter(&mut self, mut filter: F) - where F: FnMut(&TreeEntry) -> bool + where + F: FnMut(&TreeEntry) -> bool, { let mut cb: &mut FilterCb = &mut filter; let ptr = &mut cb as *mut _; @@ -90,7 +101,9 @@ impl<'repo> TreeBuilder<'repo> { /// Write the contents of the TreeBuilder as a Tree object and /// return its Oid pub fn write(&self) -> Result { - let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] }; + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; unsafe { try_call!(raw::git_treebuilder_write(&mut raw, self.raw())); Ok(Binding::from_raw(&raw as *const _)) @@ -100,8 +113,7 @@ impl<'repo> TreeBuilder<'repo> { type FilterCb<'a> = dyn FnMut(&TreeEntry) -> bool + 'a; -extern fn filter_cb(entry: *const raw::git_tree_entry, - payload: *mut c_void) -> c_int { +extern "C" fn filter_cb(entry: *const raw::git_tree_entry, payload: *mut c_void) -> c_int { let ret = panic::wrap(|| unsafe { // There's no way to return early from git_treebuilder_filter. if panic::panicked() { @@ -112,16 +124,25 @@ extern fn filter_cb(entry: *const raw::git_tree_entry, (*payload)(&entry) } }); - if ret == Some(false) {1} else {0} + if ret == Some(false) { + 1 + } else { + 0 + } } impl<'repo> Binding for TreeBuilder<'repo> { type Raw = *mut raw::git_treebuilder; unsafe fn from_raw(raw: *mut raw::git_treebuilder) -> TreeBuilder<'repo> { - TreeBuilder { raw: raw, _marker: marker::PhantomData } + TreeBuilder { + raw: raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> *mut raw::git_treebuilder { + self.raw } - fn raw(&self) -> *mut raw::git_treebuilder { self.raw } } impl<'repo> Drop for TreeBuilder<'repo> { @@ -180,8 +201,7 @@ mod tests { let mut builder = repo.treebuilder(None).unwrap(); let blob = repo.blob(b"data").unwrap(); let tree = { - let head = repo.head().unwrap() - .peel(ObjectType::Commit).unwrap(); + let head = repo.head().unwrap().peel(ObjectType::Commit).unwrap(); let head = head.as_commit().unwrap(); head.tree_id() }; diff --git a/src/util.rs b/src/util.rs index c1b9cde9d9..cf135d9292 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,8 +1,8 @@ +use libc::{c_char, c_int, size_t}; use std::cmp::Ordering; use std::ffi::{CString, OsStr, OsString}; use std::iter::IntoIterator; use std::path::{Path, PathBuf}; -use libc::{c_char, c_int, size_t}; use {raw, Error}; @@ -29,7 +29,9 @@ pub trait Binding: Sized { fn raw(&self) -> Self::Raw; unsafe fn from_raw_opt(raw: T) -> Option - where T: Copy + IsNull, Self: Binding + where + T: Copy + IsNull, + Self: Binding, { if raw.is_ptr_null() { None @@ -39,9 +41,12 @@ pub trait Binding: Sized { } } -pub fn iter2cstrs(iter: I) -> Result<(Vec, Vec<*const c_char>, - raw::git_strarray), Error> - where T: IntoCString, I: IntoIterator +pub fn iter2cstrs( + iter: I, +) -> Result<(Vec, Vec<*const c_char>, raw::git_strarray), Error> +where + T: IntoCString, + I: IntoIterator, { let cstrs: Vec<_> = try!(iter.into_iter().map(|i| i.into_c_string()).collect()); let ptrs = cstrs.iter().map(|i| i.as_ptr()).collect::>(); @@ -91,7 +96,9 @@ impl IntoCString for String { } impl IntoCString for CString { - fn into_c_string(self) -> Result { Ok(self) } + fn into_c_string(self) -> Result { + Ok(self) + } } impl<'a> IntoCString for &'a Path { @@ -125,8 +132,10 @@ impl IntoCString for OsString { fn into_c_string(self) -> Result { match self.to_str() { Some(s) => s.into_c_string(), - None => Err(Error::from_str("only valid unicode paths are accepted \ - on windows")), + None => Err(Error::from_str( + "only valid unicode paths are accepted \ + on windows", + )), } } } @@ -144,7 +153,8 @@ impl IntoCString for Vec { } pub fn into_opt_c_string(opt_s: Option) -> Result, Error> - where S: IntoCString +where + S: IntoCString, { match opt_s { None => Ok(None), diff --git a/systest/build.rs b/systest/build.rs index fbe3c156b1..3881fb66fc 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -6,22 +6,20 @@ use std::path::PathBuf; fn main() { let mut cfg = ctest::TestGenerator::new(); if let Some(root) = env::var_os("DEP_GIT2_ROOT") { - cfg.include(PathBuf::from(root).join("include")); + cfg.include(PathBuf::from(root).join("include")); } cfg.header("git2.h") - .header("git2/sys/transport.h") - .header("git2/sys/refs.h") - .header("git2/sys/refdb_backend.h") - .header("git2/sys/odb_backend.h") - .header("git2/sys/mempack.h") - .header("git2/sys/repository.h") - .header("git2/cred_helpers.h") - .type_name(|s, _, _| s.to_string()); - cfg.field_name(|_, f| { - match f { - "kind" => "type".to_string(), - _ => f.to_string(), - } + .header("git2/sys/transport.h") + .header("git2/sys/refs.h") + .header("git2/sys/refdb_backend.h") + .header("git2/sys/odb_backend.h") + .header("git2/sys/mempack.h") + .header("git2/sys/repository.h") + .header("git2/cred_helpers.h") + .type_name(|s, _, _| s.to_string()); + cfg.field_name(|_, f| match f { + "kind" => "type".to_string(), + _ => f.to_string(), }); cfg.skip_field(|struct_, f| { // this field is marked as const which ctest complains about @@ -31,9 +29,9 @@ fn main() { match s { s if s.ends_with("_cb") => true, s if s.ends_with("_callback") => true, - "git_push_transfer_progress" | - "git_push_negotiation" | - "git_packbuilder_progress" => true, + "git_push_transfer_progress" | "git_push_negotiation" | "git_packbuilder_progress" => { + true + } // TODO: fix this on the next major update of libgit2-sys "git_diff_option_t" => true, _ => false, diff --git a/systest/src/main.rs b/systest/src/main.rs index af7dd925e3..bb7d91be5b 100644 --- a/systest/src/main.rs +++ b/systest/src/main.rs @@ -1,7 +1,7 @@ #![allow(bad_style, improper_ctypes)] -extern crate libgit2_sys; extern crate libc; +extern crate libgit2_sys; use libc::*; use libgit2_sys::*; From e39a0acf5cb205432e33a2cdb6cedd2ad0515855 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 4 Jun 2019 10:26:46 -0700 Subject: [PATCH 354/860] Update to 2018 edition. --- Cargo.toml | 1 + examples/add.rs | 10 +- examples/blame.rs | 10 +- examples/cat-file.rs | 4 +- examples/clone.rs | 4 +- examples/diff.rs | 34 ++--- examples/fetch.rs | 10 +- examples/init.rs | 18 +-- examples/ls-remote.rs | 10 +- examples/rev-list.rs | 14 +-- examples/rev-parse.rs | 6 +- examples/status.rs | 10 +- examples/tag.rs | 20 +-- git2-curl/Cargo.toml | 1 + git2-curl/src/lib.rs | 51 ++++---- libgit2-sys/Cargo.toml | 1 + src/blame.rs | 8 +- src/blob.rs | 10 +- src/branch.rs | 14 +-- src/buf.rs | 6 +- src/build.rs | 18 +-- src/call.rs | 18 +-- src/cert.rs | 4 +- src/commit.rs | 26 ++-- src/config.rs | 82 ++++++------ src/cred.rs | 42 +++---- src/describe.rs | 8 +- src/diff.rs | 20 +-- src/error.rs | 8 +- src/index.rs | 48 +++---- src/lib.rs | 90 ++++++------- src/merge.rs | 6 +- src/message.rs | 8 +- src/note.rs | 12 +- src/object.rs | 10 +- src/odb.rs | 10 +- src/oid.rs | 16 +-- src/oid_array.rs | 10 +- src/packbuilder.rs | 26 ++-- src/panic.rs | 2 +- src/patch.rs | 18 +-- src/pathspec.rs | 16 +-- src/proxy_options.rs | 4 +- src/rebase.rs | 16 +-- src/reference.rs | 38 +++--- src/reflog.rs | 10 +- src/refspec.rs | 10 +- src/remote.rs | 58 ++++----- src/remote_callbacks.rs | 22 ++-- src/repo.rs | 273 ++++++++++++++++++++-------------------- src/revspec.rs | 2 +- src/revwalk.rs | 18 +-- src/signature.rs | 22 ++-- src/stash.rs | 12 +- src/status.rs | 24 ++-- src/string_array.rs | 6 +- src/submodule.rs | 28 +++-- src/tag.rs | 18 +-- src/test.rs | 4 +- src/time.rs | 4 +- src/transport.rs | 8 +- src/tree.rs | 20 +-- src/treebuilder.rs | 18 +-- src/util.rs | 19 +-- systest/Cargo.toml | 1 + 65 files changed, 699 insertions(+), 676 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bf76d2e35b..e075984e99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ both threadsafe and memory safe and allows both reading and writing git repositories. """ categories = ["api-bindings"] +edition = "2018" [badges] travis-ci = { repository = "rust-lang/git2-rs" } diff --git a/examples/add.rs b/examples/add.rs index b4440ca5d8..47dc56b281 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -33,8 +33,8 @@ struct Args { } fn run(args: &Args) -> Result<(), git2::Error> { - let repo = try!(Repository::open(&Path::new("."))); - let mut index = try!(repo.index()); + let repo = Repository::open(&Path::new("."))?; + let mut index = repo.index()?; let cb = &mut |path: &Path, _matched_spec: &[u8]| -> i32 { let status = repo.status_file(path).unwrap(); @@ -61,12 +61,12 @@ fn run(args: &Args) -> Result<(), git2::Error> { }; if args.flag_update { - try!(index.update_all(args.arg_spec.iter(), cb)); + index.update_all(args.arg_spec.iter(), cb)?; } else { - try!(index.add_all(args.arg_spec.iter(), git2::IndexAddOption::DEFAULT, cb)); + index.add_all(args.arg_spec.iter(), git2::IndexAddOption::DEFAULT, cb)?; } - try!(index.write()); + index.write()?; Ok(()) } diff --git a/examples/blame.rs b/examples/blame.rs index 07452dde8d..68f1de20ac 100644 --- a/examples/blame.rs +++ b/examples/blame.rs @@ -33,7 +33,7 @@ struct Args { } fn run(args: &Args) -> Result<(), git2::Error> { - let repo = try!(Repository::open(".")); + let repo = Repository::open(".")?; let path = Path::new(&args.arg_path[..]); // Prepare our blame options @@ -46,7 +46,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { // Parse spec if let Some(spec) = args.arg_spec.as_ref() { - let revspec = try!(repo.revparse(spec)); + let revspec = repo.revparse(spec)?; let (oldest, newest) = if revspec.mode().contains(git2::RevparseMode::SINGLE) { (None, revspec.from()) @@ -69,9 +69,9 @@ fn run(args: &Args) -> Result<(), git2::Error> { } let spec = format!("{}:{}", commit_id, path.display()); - let blame = try!(repo.blame_file(path, Some(&mut opts))); - let object = try!(repo.revparse_single(&spec[..])); - let blob = try!(repo.find_blob(object.id())); + let blame = repo.blame_file(path, Some(&mut opts))?; + let object = repo.revparse_single(&spec[..])?; + let blob = repo.find_blob(object.id())?; let reader = BufReader::new(blob.content()); for (i, line) in reader.lines().enumerate() { diff --git a/examples/cat-file.rs b/examples/cat-file.rs index ae7de5d179..07ead1bfcf 100644 --- a/examples/cat-file.rs +++ b/examples/cat-file.rs @@ -38,9 +38,9 @@ struct Args { fn run(args: &Args) -> Result<(), git2::Error> { let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); - let repo = try!(Repository::open(path)); + let repo = Repository::open(path)?; - let obj = try!(repo.revparse_single(&args.arg_object)); + let obj = repo.revparse_single(&args.arg_object)?; if args.flag_v && !args.flag_q { println!("{} {}\n--", obj.kind().unwrap().str(), obj.id()); } diff --git a/examples/clone.rs b/examples/clone.rs index 86553b2d30..bd3a8122c2 100644 --- a/examples/clone.rs +++ b/examples/clone.rs @@ -111,10 +111,10 @@ fn run(args: &Args) -> Result<(), git2::Error> { let mut fo = FetchOptions::new(); fo.remote_callbacks(cb); - try!(RepoBuilder::new() + RepoBuilder::new() .fetch_options(fo) .with_checkout(co) - .clone(&args.arg_url, Path::new(&args.arg_path))); + .clone(&args.arg_url, Path::new(&args.arg_path))?; println!(""); Ok(()) diff --git a/examples/diff.rs b/examples/diff.rs index e4dee88aa1..d109db114d 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -79,7 +79,7 @@ enum Cache { fn run(args: &Args) -> Result<(), Error> { let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); - let repo = try!(Repository::open(path)); + let repo = Repository::open(path)?; // Prepare our diff options based on the arguments given let mut opts = DiffOptions::new(); @@ -112,25 +112,25 @@ fn run(args: &Args) -> Result<(), Error> { } // Prepare the diff to inspect - let t1 = try!(tree_to_treeish(&repo, args.arg_from_oid.as_ref())); - let t2 = try!(tree_to_treeish(&repo, args.arg_to_oid.as_ref())); - let head = try!(tree_to_treeish(&repo, Some(&"HEAD".to_string()))).unwrap(); + let t1 = tree_to_treeish(&repo, args.arg_from_oid.as_ref())?; + let t2 = tree_to_treeish(&repo, args.arg_to_oid.as_ref())?; + let head = tree_to_treeish(&repo, Some(&"HEAD".to_string()))?.unwrap(); let mut diff = match (t1, t2, args.cache()) { (Some(t1), Some(t2), _) => { - try!(repo.diff_tree_to_tree(t1.as_tree(), t2.as_tree(), Some(&mut opts))) + repo.diff_tree_to_tree(t1.as_tree(), t2.as_tree(), Some(&mut opts))? } (t1, None, Cache::None) => { let t1 = t1.unwrap_or(head); - try!(repo.diff_tree_to_workdir(t1.as_tree(), Some(&mut opts))) + repo.diff_tree_to_workdir(t1.as_tree(), Some(&mut opts))? } (t1, None, Cache::Only) => { let t1 = t1.unwrap_or(head); - try!(repo.diff_tree_to_index(t1.as_tree(), None, Some(&mut opts))) + repo.diff_tree_to_index(t1.as_tree(), None, Some(&mut opts))? } (Some(t1), None, _) => { - try!(repo.diff_tree_to_workdir_with_index(t1.as_tree(), Some(&mut opts))) + repo.diff_tree_to_workdir_with_index(t1.as_tree(), Some(&mut opts))? } - (None, None, _) => try!(repo.diff_index_to_workdir(None, Some(&mut opts))), + (None, None, _) => repo.diff_index_to_workdir(None, Some(&mut opts))?, (None, Some(_), _) => unreachable!(), }; @@ -151,20 +151,20 @@ fn run(args: &Args) -> Result<(), Error> { } opts.copies_from_unmodified(args.flag_find_copies_harder) .rewrites(args.flag_break_rewrites); - try!(diff.find_similar(Some(&mut opts))); + diff.find_similar(Some(&mut opts))?; } // Generate simple output let stats = args.flag_stat | args.flag_numstat | args.flag_shortstat | args.flag_summary; if stats { - try!(print_stats(&diff, args)); + print_stats(&diff, args)?; } if args.flag_patch || !stats { if args.color() { print!("{}", RESET); } let mut last_color = None; - try!(diff.print(args.diff_format(), |_delta, _hunk, line| { + diff.print(args.diff_format(), |_delta, _hunk, line| { if args.color() { let next = match line.origin() { '+' => Some(GREEN), @@ -190,7 +190,7 @@ fn run(args: &Args) -> Result<(), Error> { } print!("{}", str::from_utf8(line.content()).unwrap()); true - })); + })?; if args.color() { print!("{}", RESET); } @@ -200,7 +200,7 @@ fn run(args: &Args) -> Result<(), Error> { } fn print_stats(diff: &Diff, args: &Args) -> Result<(), Error> { - let stats = try!(diff.stats()); + let stats = diff.stats()?; let mut format = git2::DiffStatsFormat::NONE; if args.flag_stat { format |= git2::DiffStatsFormat::FULL; @@ -214,7 +214,7 @@ fn print_stats(diff: &Diff, args: &Args) -> Result<(), Error> { if args.flag_summary { format |= git2::DiffStatsFormat::INCLUDE_SUMMARY; } - let buf = try!(stats.to_buf(format, 80)); + let buf = stats.to_buf(format, 80)?; print!("{}", str::from_utf8(&*buf).unwrap()); Ok(()) } @@ -227,8 +227,8 @@ fn tree_to_treeish<'a>( Some(s) => s, None => return Ok(None), }; - let obj = try!(repo.revparse_single(arg)); - let tree = try!(obj.peel(ObjectType::Tree)); + let obj = repo.revparse_single(arg)?; + let tree = obj.peel(ObjectType::Tree)?; Ok(Some(tree)) } diff --git a/examples/fetch.rs b/examples/fetch.rs index a4d36e8e76..a400eeacaf 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -30,15 +30,15 @@ struct Args { } fn run(args: &Args) -> Result<(), git2::Error> { - let repo = try!(Repository::open(".")); + let repo = Repository::open(".")?; let remote = args.arg_remote.as_ref().map(|s| &s[..]).unwrap_or("origin"); // Figure out whether it's a named remote or a URL println!("Fetching {} for repo", remote); let mut cb = RemoteCallbacks::new(); - let mut remote = try!(repo + let mut remote = repo .find_remote(remote) - .or_else(|_| { repo.remote_anonymous(remote) })); + .or_else(|_| repo.remote_anonymous(remote))?; cb.sideband_progress(|data| { print!("remote: {}", str::from_utf8(data).unwrap()); io::stdout().flush().unwrap(); @@ -85,7 +85,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { // progress. let mut fo = FetchOptions::new(); fo.remote_callbacks(cb); - try!(remote.download(&[], Some(&mut fo))); + remote.download(&[], Some(&mut fo))?; { // If there are local objects (we got a thin pack), then tell the user @@ -117,7 +117,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { // commits. This may be needed even if there was no packfile to download, // which can happen e.g. when the branches have been changed but all the // needed objects are available locally. - try!(remote.update_tips(None, true, AutotagOption::Unspecified, None)); + remote.update_tips(None, true, AutotagOption::Unspecified, None)?; Ok(()) } diff --git a/examples/init.rs b/examples/init.rs index b547efff83..3b9371bd1d 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -41,7 +41,7 @@ fn run(args: &Args) -> Result<(), Error> { && args.flag_shared.is_none() && args.flag_separate_git_dir.is_none() { - try!(Repository::init(&path)) + Repository::init(&path)? } else { let mut opts = RepositoryInitOptions::new(); opts.bare(args.flag_bare); @@ -58,9 +58,9 @@ fn run(args: &Args) -> Result<(), Error> { } if let Some(ref s) = args.flag_shared { - opts.mode(try!(parse_shared(s))); + opts.mode(parse_shared(s)?); } - try!(Repository::init_opts(&path, &opts)) + Repository::init_opts(&path, &opts)? }; // Print a message to stdout like "git init" does @@ -74,7 +74,7 @@ fn run(args: &Args) -> Result<(), Error> { } if args.flag_initial_commit { - try!(create_initial_commit(&repo)); + create_initial_commit(&repo)?; println!("Created empty initial commit"); } @@ -85,27 +85,27 @@ fn run(args: &Args) -> Result<(), Error> { /// commit in the repository. This is the helper function that does that. fn create_initial_commit(repo: &Repository) -> Result<(), Error> { // First use the config to initialize a commit signature for the user. - let sig = try!(repo.signature()); + let sig = repo.signature()?; // Now let's create an empty tree for this commit let tree_id = { - let mut index = try!(repo.index()); + let mut index = repo.index()?; // Outside of this example, you could call index.add_path() // here to put actual files into the index. For our purposes, we'll // leave it empty for now. - try!(index.write_tree()) + index.write_tree()? }; - let tree = try!(repo.find_tree(tree_id)); + let tree = repo.find_tree(tree_id)?; // Ready to create the initial commit. // // Normally creating a commit would involve looking up the current HEAD // commit and making that be the parent of the initial commit, but here this // is the first commit so there will be no parent. - try!(repo.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[])); + repo.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[])?; Ok(()) } diff --git a/examples/ls-remote.rs b/examples/ls-remote.rs index 4d66099ba9..b5935746af 100644 --- a/examples/ls-remote.rs +++ b/examples/ls-remote.rs @@ -28,19 +28,19 @@ struct Args { } fn run(args: &Args) -> Result<(), git2::Error> { - let repo = try!(Repository::open(".")); + let repo = Repository::open(".")?; let remote = &args.arg_remote; - let mut remote = try!(repo + let mut remote = repo .find_remote(remote) - .or_else(|_| { repo.remote_anonymous(remote) })); + .or_else(|_| repo.remote_anonymous(remote))?; // Connect to the remote and call the printing function for each of the // remote references. - let connection = try!(remote.connect_auth(Direction::Fetch, None, None)); + let connection = remote.connect_auth(Direction::Fetch, None, None)?; // Get the list of references on the remote and print out their name next to // what they point to. - for head in try!(connection.list()).iter() { + for head in connection.list()?.iter() { println!("{}\t{}", head.oid(), head.name()); } Ok(()) diff --git a/examples/rev-list.rs b/examples/rev-list.rs index 84a409e200..6aedb9af73 100644 --- a/examples/rev-list.rs +++ b/examples/rev-list.rs @@ -33,8 +33,8 @@ struct Args { } fn run(args: &Args) -> Result<(), git2::Error> { - let repo = try!(Repository::open(".")); - let mut revwalk = try!(repo.revwalk()); + let repo = Repository::open(".")?; + let mut revwalk = repo.revwalk()?; let base = if args.flag_reverse { git2::Sort::REVERSE @@ -65,20 +65,20 @@ fn run(args: &Args) -> Result<(), git2::Error> { }); for (spec, hide) in specs { let id = if spec.contains("..") { - let revspec = try!(repo.revparse(spec)); + let revspec = repo.revparse(spec)?; if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { return Err(Error::from_str("merge bases not implemented")); } - try!(push(&mut revwalk, revspec.from().unwrap().id(), !hide)); + push(&mut revwalk, revspec.from().unwrap().id(), !hide)?; revspec.to().unwrap().id() } else { - try!(repo.revparse_single(spec)).id() + repo.revparse_single(spec)?.id() }; - try!(push(&mut revwalk, id, hide)); + push(&mut revwalk, id, hide)?; } for id in revwalk { - let id = try!(id); + let id = id?; println!("{}", id); } Ok(()) diff --git a/examples/rev-parse.rs b/examples/rev-parse.rs index f0642f0416..86017974cb 100644 --- a/examples/rev-parse.rs +++ b/examples/rev-parse.rs @@ -30,9 +30,9 @@ struct Args { fn run(args: &Args) -> Result<(), git2::Error> { let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); - let repo = try!(Repository::open(path)); + let repo = Repository::open(path)?; - let revspec = try!(repo.revparse(&args.arg_spec)); + let revspec = repo.revparse(&args.arg_spec)?; if revspec.mode().contains(git2::RevparseMode::SINGLE) { println!("{}", revspec.from().unwrap().id()); @@ -42,7 +42,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { println!("{}", to.id()); if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { - let base = try!(repo.merge_base(from.id(), to.id())); + let base = repo.merge_base(from.id(), to.id())?; println!("{}", base); } diff --git a/examples/status.rs b/examples/status.rs index f5104d6584..a15c6c93f1 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -48,7 +48,7 @@ enum Format { fn run(args: &Args) -> Result<(), Error> { let path = args.flag_git_dir.clone().unwrap_or_else(|| ".".to_string()); - let repo = try!(Repository::open(&path)); + let repo = Repository::open(&path)?; if repo.is_bare() { return Err(Error::from_str("cannot report status on bare repository")); } @@ -85,13 +85,13 @@ fn run(args: &Args) -> Result<(), Error> { println!("\u{1b}[H\u{1b}[2J"); } - let statuses = try!(repo.statuses(Some(&mut opts))); + let statuses = repo.statuses(Some(&mut opts))?; if args.flag_branch { - try!(show_branch(&repo, &args.format())); + show_branch(&repo, &args.format())?; } if args.flag_list_submodules { - try!(print_submodules(&repo)); + print_submodules(&repo)?; } if args.format() == Format::Long { @@ -130,7 +130,7 @@ fn show_branch(repo: &Repository, format: &Format) -> Result<(), Error> { } fn print_submodules(repo: &Repository) -> Result<(), Error> { - let modules = try!(repo.submodules()); + let modules = repo.submodules()?; println!("# Submodules"); for sm in &modules { println!( diff --git a/examples/tag.rs b/examples/tag.rs index c95e5a5d27..e69b925f46 100644 --- a/examples/tag.rs +++ b/examples/tag.rs @@ -36,22 +36,22 @@ struct Args { } fn run(args: &Args) -> Result<(), Error> { - let repo = try!(Repository::open(".")); + let repo = Repository::open(".")?; if let Some(ref name) = args.arg_tagname { let target = args.arg_object.as_ref().map(|s| &s[..]).unwrap_or("HEAD"); - let obj = try!(repo.revparse_single(target)); + let obj = repo.revparse_single(target)?; if let Some(ref message) = args.flag_message { - let sig = try!(repo.signature()); - try!(repo.tag(name, &obj, &sig, message, args.flag_force)); + let sig = repo.signature()?; + repo.tag(name, &obj, &sig, message, args.flag_force)?; } else { - try!(repo.tag_lightweight(name, &obj, args.flag_force)); + repo.tag_lightweight(name, &obj, args.flag_force)?; } } else if let Some(ref name) = args.flag_delete { - let obj = try!(repo.revparse_single(name)); - let id = try!(obj.short_id()); - try!(repo.tag_delete(name)); + let obj = repo.revparse_single(name)?; + let id = obj.short_id()?; + repo.tag_delete(name)?; println!( "Deleted tag '{}' (was {})", name, @@ -59,9 +59,9 @@ fn run(args: &Args) -> Result<(), Error> { ); } else if args.flag_list { let pattern = args.arg_pattern.as_ref().map(|s| &s[..]).unwrap_or("*"); - for name in try!(repo.tag_names(Some(pattern))).iter() { + for name in repo.tag_names(Some(pattern))?.iter() { let name = name.unwrap(); - let obj = try!(repo.revparse_single(name)); + let obj = repo.revparse_single(name)?; if let Some(tag) = obj.as_tag() { print_tag(tag, args); diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 0acfb14f0a..a6954ed43e 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -11,6 +11,7 @@ Backend for an HTTP transport in libgit2 powered by libcurl. Intended to be used with the git2 crate. """ +edition = "2018" [dependencies] curl = "0.4" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 81cf6546a7..17ba61c01b 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -140,8 +140,7 @@ impl CurlSubtransport { // Parse our input URL to figure out the host let url = format!("{}{}", self.base_url.lock().unwrap(), self.url_path); - let parsed = - try!(Url::parse(&url).map_err(|_| { self.err("invalid url, failed to parse") })); + let parsed = Url::parse(&url).map_err(|_| self.err("invalid url, failed to parse"))?; let host = match parsed.host_str() { Some(host) => host, None => return Err(self.err("invalid url, did not have a host")), @@ -150,34 +149,34 @@ impl CurlSubtransport { // Prep the request debug!("request to {}", url); let mut h = self.handle.lock().unwrap(); - try!(h.url(https://github.com/&url)); - try!(h.useragent(&agent)); - try!(h.follow_location(true)); + h.url(https://github.com/&url)?; + h.useragent(&agent)?; + h.follow_location(true)?; match self.method { - "GET" => try!(h.get(true)), - "PUT" => try!(h.put(true)), - "POST" => try!(h.post(true)), - other => try!(h.custom_request(other)), + "GET" => h.get(true)?, + "PUT" => h.put(true)?, + "POST" => h.post(true)?, + other => h.custom_request(other)?, } let mut headers = List::new(); - try!(headers.append(&format!("Host: {}", host))); + headers.append(&format!("Host: {}", host))?; if data.len() > 0 { - try!(h.post_fields_copy(data)); - try!(headers.append(&format!( + h.post_fields_copy(data)?; + headers.append(&format!( "Accept: application/x-git-{}-result", self.service - ))); - try!(headers.append(&format!( + ))?; + headers.append(&format!( "Content-Type: \ application/x-git-{}-request", self.service - ))); + ))?; } else { - try!(headers.append("Accept: */*")); + headers.append("Accept: */*")?; } - try!(headers.append("Expect:")); - try!(h.http_headers(headers)); + headers.append("Expect:")?; + h.http_headers(headers)?; let mut content_type = None; let mut data = Vec::new(); @@ -185,7 +184,7 @@ impl CurlSubtransport { let mut h = h.transfer(); // Look for the Content-Type header - try!(h.header_function(|header| { + h.header_function(|header| { let header = match str::from_utf8(header) { Ok(s) => s, Err(..) => return true, @@ -201,19 +200,19 @@ impl CurlSubtransport { } true - })); + })?; // Collect the request's response in-memory - try!(h.write_function(|buf| { + h.write_function(|buf| { data.extend_from_slice(buf); Ok(buf.len()) - })); + })?; // Send the request - try!(h.perform()); + h.perform()?; } - let code = try!(h.response_code()); + let code = h.response_code()?; if code != 200 { return Err(self.err( &format!( @@ -275,7 +274,7 @@ impl CurlSubtransport { impl Read for CurlSubtransport { fn read(&mut self, buf: &mut [u8]) -> io::Result { if self.reader.is_none() { - try!(self.execute(&[])); + self.execute(&[])?; } self.reader.as_mut().unwrap().read(buf) } @@ -284,7 +283,7 @@ impl Read for CurlSubtransport { impl Write for CurlSubtransport { fn write(&mut self, data: &[u8]) -> io::Result { if self.reader.is_none() { - try!(self.execute(data)); + self.execute(data)?; } Ok(data.len()) } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index d883debb31..9cc8813396 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -10,6 +10,7 @@ description = "Native bindings to the libgit2 library" exclude = [ "libgit2/tests/*", ] +edition = "2018" [lib] name = "libgit2_sys" diff --git a/src/blame.rs b/src/blame.rs index 0dcb6a2c0e..f3d055e5d9 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -1,9 +1,9 @@ +use crate::util::{self, Binding}; +use crate::{raw, signature, Oid, Repository, Signature}; use std::marker; use std::mem; use std::ops::Range; use std::path::Path; -use util::{self, Binding}; -use {raw, signature, Oid, Repository, Signature}; /// Opaque structure to hold blame results. pub struct Blame<'repo> { @@ -124,7 +124,7 @@ impl<'blame> BlameHunk<'blame> { /// Note: `None` could be returned for non-unicode paths on Widnows. pub fn path(&self) -> Option<&Path> { unsafe { - if let Some(bytes) = ::opt_bytes(self, (*self.raw).orig_path) { + if let Some(bytes) = crate::opt_bytes(self, (*self.raw).orig_path) { Some(util::bytes2path(bytes)) } else { None @@ -292,7 +292,7 @@ mod tests { #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut index = repo.index().unwrap(); let root = repo.path().parent().unwrap(); diff --git a/src/blob.rs b/src/blob.rs index ced482bb3a..cdbb6941a3 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -3,8 +3,8 @@ use std::marker; use std::mem; use std::slice; -use util::Binding; -use {raw, Error, Object, Oid}; +use crate::util::Binding; +use crate::{raw, Error, Object, Oid}; /// A structure to represent a git [blob][1] /// @@ -60,8 +60,8 @@ impl<'repo> Binding for Blob<'repo> { } } -impl<'repo> ::std::fmt::Debug for Blob<'repo> { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { +impl<'repo> std::fmt::Debug for Blob<'repo> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { f.debug_struct("Blob").field("id", &self.id()).finish() } } @@ -142,11 +142,11 @@ impl<'repo> io::Write for BlobWriter<'repo> { #[cfg(test)] mod tests { + use crate::Repository; use std::fs::File; use std::io::prelude::*; use std::path::Path; use tempdir::TempDir; - use Repository; #[test] fn buffer() { diff --git a/src/branch.rs b/src/branch.rs index b25f0592d5..a82734b336 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -3,8 +3,8 @@ use std::marker; use std::ptr; use std::str; -use util::Binding; -use {raw, BranchType, Error, Reference, References}; +use crate::util::Binding; +use crate::{raw, BranchType, Error, Reference, References}; /// A structure to represent a git [branch][1] /// @@ -54,7 +54,7 @@ impl<'repo> Branch<'repo> { /// Move/rename an existing local branch reference. pub fn rename(&mut self, new_branch_name: &str, force: bool) -> Result, Error> { let mut ret = ptr::null_mut(); - let new_branch_name = try!(CString::new(new_branch_name)); + let new_branch_name = CString::new(new_branch_name)?; unsafe { try_call!(raw::git_branch_move( &mut ret, @@ -78,7 +78,7 @@ impl<'repo> Branch<'repo> { let mut ret = ptr::null(); unsafe { try_call!(raw::git_branch_name(&mut ret, &*self.get().raw())); - Ok(::opt_bytes(self, ret).unwrap()) + Ok(crate::opt_bytes(self, ret).unwrap()) } } @@ -97,7 +97,7 @@ impl<'repo> Branch<'repo> { /// If `None` is specified, then the upstream branch is unset. The name /// provided is the name of the branch to set as upstream. pub fn set_upstream(&mut self, upstream_name: Option<&str>) -> Result<(), Error> { - let upstream_name = try!(::opt_cstr(upstream_name)); + let upstream_name = crate::opt_cstr(upstream_name)?; unsafe { try_call!(raw::git_branch_set_upstream( self.get().raw(), @@ -146,11 +146,11 @@ impl<'repo> Drop for Branches<'repo> { #[cfg(test)] mod tests { - use BranchType; + use crate::BranchType; #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let head = repo.head().unwrap(); let target = head.target().unwrap(); let commit = repo.find_commit(target).unwrap(); diff --git a/src/buf.rs b/src/buf.rs index 0e8f3dbc69..0ab560ce80 100644 --- a/src/buf.rs +++ b/src/buf.rs @@ -3,8 +3,8 @@ use std::ptr; use std::slice; use std::str; -use raw; -use util::Binding; +use crate::raw; +use crate::util::Binding; /// A structure to wrap an intermediate buffer used by libgit2. /// @@ -23,7 +23,7 @@ impl Default for Buf { impl Buf { /// Creates a new empty buffer. pub fn new() -> Buf { - ::init(); + crate::init(); unsafe { Binding::from_raw(&mut raw::git_buf { ptr: ptr::null_mut(), diff --git a/src/build.rs b/src/build.rs index bd2b0c87ed..abec5295a1 100644 --- a/src/build.rs +++ b/src/build.rs @@ -6,9 +6,9 @@ use std::mem; use std::path::Path; use std::ptr; -use util::{self, Binding}; -use {panic, raw, Error, FetchOptions, IntoCString, Repository}; -use {CheckoutNotificationType, DiffFile, Remote}; +use crate::util::{self, Binding}; +use crate::{panic, raw, Error, FetchOptions, IntoCString, Repository}; +use crate::{CheckoutNotificationType, DiffFile, Remote}; /// A builder struct which is used to build configuration for cloning a new git /// repository. @@ -102,7 +102,7 @@ impl<'cb> RepoBuilder<'cb> { /// When ready, the `clone()` method can be used to clone a new repository /// using this configuration. pub fn new() -> RepoBuilder<'cb> { - ::init(); + crate::init(); RepoBuilder { bare: false, branch: None, @@ -231,8 +231,8 @@ impl<'cb> RepoBuilder<'cb> { opts.remote_cb_payload = callback as *mut _ as *mut _; } - let url = try!(CString::new(url)); - let into = try!(into.into_c_string()); + let url = CString::new(url)?; + let into = into.into_c_string()?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_clone(&mut raw, url, into, &opts)); @@ -256,7 +256,7 @@ extern "C" fn remote_create_cb( let f = payload as *mut Box; match (*f)(&repo, name, url) { Ok(remote) => { - *out = ::remote::remote_into_raw(remote); + *out = crate::remote::remote_into_raw(remote); 0 } Err(e) => e.raw_code(), @@ -277,7 +277,7 @@ impl<'cb> CheckoutBuilder<'cb> { /// Creates a new builder for checkouts with all of its default /// configuration. pub fn new() -> CheckoutBuilder<'cb> { - ::init(); + crate::init(); CheckoutBuilder { disable_filters: false, dir_perm: None, @@ -642,10 +642,10 @@ extern "C" fn notify_cb( #[cfg(test)] mod tests { use super::{CheckoutBuilder, RepoBuilder}; + use crate::{CheckoutNotificationType, Repository}; use std::fs; use std::path::Path; use tempdir::TempDir; - use {CheckoutNotificationType, Repository}; #[test] fn smoke() { diff --git a/src/call.rs b/src/call.rs index 565f08d96f..1509517c0c 100644 --- a/src/call.rs +++ b/src/call.rs @@ -1,19 +1,19 @@ #![macro_use] use libc; -use Error; +use crate::Error; macro_rules! call { (raw::$p:ident ($($e:expr),*)) => ( - raw::$p($(::call::convert(&$e)),*) + raw::$p($(crate::call::convert(&$e)),*) ) } macro_rules! try_call { (raw::$p:ident ($($e:expr),*)) => ({ - match ::call::try(raw::$p($(::call::convert(&$e)),*)) { + match crate::call::c_try(raw::$p($(crate::call::convert(&$e)),*)) { Ok(o) => o, - Err(e) => { ::panic::check(); return Err(e) } + Err(e) => { crate::panic::check(); return Err(e) } } }) } @@ -23,7 +23,7 @@ macro_rules! try_call_iter { match call!($($f)*) { 0 => {} raw::GIT_ITEROVER => return None, - e => return Some(Err(::call::last_error(e))) + e => return Some(Err(crate::call::last_error(e))) } } } @@ -37,7 +37,7 @@ pub fn convert>(u: &U) -> T { u.convert() } -pub fn try(ret: libc::c_int) -> Result { +pub fn c_try(ret: libc::c_int) -> Result { match ret { n if n < 0 => Err(last_error(n)), n => Ok(n), @@ -56,9 +56,9 @@ mod impls { use libc; - use call::Convert; - use {raw, BranchType, ConfigLevel, Direction, ObjectType, ResetType}; - use {AutotagOption, DiffFormat, FetchPrune, FileFavor, SubmoduleIgnore}; + use crate::call::Convert; + use crate::{raw, BranchType, ConfigLevel, Direction, ObjectType, ResetType}; + use crate::{AutotagOption, DiffFormat, FetchPrune, FileFavor, SubmoduleIgnore}; impl Convert for T { fn convert(&self) -> T { diff --git a/src/cert.rs b/src/cert.rs index 4ca84e58aa..80c4ed345a 100644 --- a/src/cert.rs +++ b/src/cert.rs @@ -5,8 +5,8 @@ use std::marker; use std::mem; use std::slice; -use raw; -use util::Binding; +use crate::raw; +use crate::util::Binding; /// A certificate for a remote connection, viewable as one of `CertHostkey` or /// `CertX509` currently. diff --git a/src/commit.rs b/src/commit.rs index d478178790..636d1adede 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -5,8 +5,8 @@ use std::ops::Range; use std::ptr; use std::str; -use util::Binding; -use {raw, signature, Error, Object, Oid, Signature, Time, Tree}; +use crate::util::Binding; +use crate::{raw, signature, Error, Object, Oid, Signature, Time, Tree}; /// A structure to represent a git [commit][1] /// @@ -74,7 +74,7 @@ impl<'repo> Commit<'repo> { /// The returned message will be slightly prettified by removing any /// potential leading newlines. pub fn message_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_commit_message(&*self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_commit_message(&*self.raw)).unwrap() } } /// Get the encoding for the message of a commit, as a string representing a @@ -82,7 +82,7 @@ impl<'repo> Commit<'repo> { /// /// `None` will be returned if the encoding is not known pub fn message_encoding(&self) -> Option<&str> { - let bytes = unsafe { ::opt_bytes(self, raw::git_commit_message_encoding(&*self.raw)) }; + let bytes = unsafe { crate::opt_bytes(self, raw::git_commit_message_encoding(&*self.raw)) }; bytes.and_then(|b| str::from_utf8(b).ok()) } @@ -95,7 +95,7 @@ impl<'repo> Commit<'repo> { /// Get the full raw message of a commit. pub fn message_raw_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_commit_message_raw(&*self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_commit_message_raw(&*self.raw)).unwrap() } } /// Get the full raw text of the commit header. @@ -107,7 +107,7 @@ impl<'repo> Commit<'repo> { /// Get the full raw text of the commit header. pub fn raw_header_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_commit_raw_header(&*self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_commit_raw_header(&*self.raw)).unwrap() } } /// Get the short "summary" of the git commit message. @@ -128,7 +128,7 @@ impl<'repo> Commit<'repo> { /// /// `None` may be returned if an error occurs pub fn summary_bytes(&self) -> Option<&[u8]> { - unsafe { ::opt_bytes(self, raw::git_commit_summary(self.raw)) } + unsafe { crate::opt_bytes(self, raw::git_commit_summary(self.raw)) } } /// Get the commit time (i.e. committer time) of a commit. @@ -198,9 +198,9 @@ impl<'repo> Commit<'repo> { let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; - let update_ref = try!(::opt_cstr(update_ref)); - let encoding = try!(::opt_cstr(message_encoding)); - let message = try!(::opt_cstr(message)); + let update_ref = crate::opt_cstr(update_ref)?; + let encoding = crate::opt_cstr(message_encoding)?; + let message = crate::opt_cstr(message)?; unsafe { try_call!(raw::git_commit_amend( &mut raw, @@ -280,8 +280,8 @@ impl<'repo> Binding for Commit<'repo> { } } -impl<'repo> ::std::fmt::Debug for Commit<'repo> { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { +impl<'repo> std::fmt::Debug for Commit<'repo> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { let mut ds = f.debug_struct("Commit"); ds.field("id", &self.id()); if let Some(summary) = self.summary() { @@ -353,7 +353,7 @@ impl<'repo> Drop for Commit<'repo> { mod tests { #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let head = repo.head().unwrap(); let target = head.target().unwrap(); let commit = repo.find_commit(target).unwrap(); diff --git a/src/config.rs b/src/config.rs index b5fc72d2e6..6eb689cbb4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -5,8 +5,8 @@ use std::path::{Path, PathBuf}; use std::ptr; use std::str; -use util::{self, Binding}; -use {raw, Buf, ConfigLevel, Error, IntoCString}; +use crate::util::{self, Binding}; +use crate::{raw, Buf, ConfigLevel, Error, IntoCString}; /// A structure representing a git configuration key/value store pub struct Config { @@ -34,7 +34,7 @@ impl Config { /// This object is empty, so you have to add a file to it before you can do /// anything with it. pub fn new() -> Result { - ::init(); + crate::init(); let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_config_new(&mut raw)); @@ -44,9 +44,9 @@ impl Config { /// Create a new config instance containing a single on-disk file pub fn open(path: &Path) -> Result { - ::init(); + crate::init(); let mut raw = ptr::null_mut(); - let path = try!(path.into_c_string()); + let path = path.into_c_string()?; unsafe { try_call!(raw::git_config_open_ondisk(&mut raw, path)); Ok(Binding::from_raw(raw)) @@ -59,7 +59,7 @@ impl Config { /// files and opens them into a single prioritized config object that can /// be used when accessing default config data outside a repository. pub fn open_default() -> Result { - ::init(); + crate::init(); let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_config_open_default(&mut raw)); @@ -79,7 +79,7 @@ impl Config { /// This method will not guess the path to the xdg compatible config file /// (`.config/git/config`). pub fn find_global() -> Result { - ::init(); + crate::init(); let buf = Buf::new(); unsafe { try_call!(raw::git_config_find_global(buf.raw())); @@ -91,7 +91,7 @@ impl Config { /// /// If /etc/gitconfig doesn't exist, it will look for %PROGRAMFILES% pub fn find_system() -> Result { - ::init(); + crate::init(); let buf = Buf::new(); unsafe { try_call!(raw::git_config_find_system(buf.raw())); @@ -104,7 +104,7 @@ impl Config { /// The xdg compatible configuration file is usually located in /// `$HOME/.config/git/config`. pub fn find_xdg() -> Result { - ::init(); + crate::init(); let buf = Buf::new(); unsafe { try_call!(raw::git_config_find_xdg(buf.raw())); @@ -122,7 +122,7 @@ impl Config { /// file instances in order (instances with a higher priority level will be /// accessed first). pub fn add_file(&mut self, path: &Path, level: ConfigLevel, force: bool) -> Result<(), Error> { - let path = try!(path.into_c_string()); + let path = path.into_c_string()?; unsafe { try_call!(raw::git_config_add_file_ondisk( self.raw, @@ -138,7 +138,7 @@ impl Config { /// Delete a config variable from the config file with the highest level /// (usually the local one). pub fn remove(&mut self, name: &str) -> Result<(), Error> { - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_delete_entry(self.raw, name)); Ok(()) @@ -148,8 +148,8 @@ impl Config { /// Remove multivar config variables in the config file with the highest level (usually the /// local one). pub fn remove_multivar(&mut self, name: &str, regexp: &str) -> Result<(), Error> { - let name = try!(CString::new(name)); - let regexp = try!(CString::new(regexp)); + let name = CString::new(name)?; + let regexp = CString::new(regexp)?; unsafe { try_call!(raw::git_config_delete_multivar(self.raw, name, regexp)); } @@ -163,7 +163,7 @@ impl Config { /// the variable will be returned here. pub fn get_bool(&self, name: &str) -> Result { let mut out = 0 as libc::c_int; - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_get_bool(&mut out, &*self.raw, name)); } @@ -177,7 +177,7 @@ impl Config { /// the variable will be returned here. pub fn get_i32(&self, name: &str) -> Result { let mut out = 0i32; - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_get_int32(&mut out, &*self.raw, name)); } @@ -191,7 +191,7 @@ impl Config { /// the variable will be returned here. pub fn get_i64(&self, name: &str) -> Result { let mut out = 0i64; - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_get_int64(&mut out, &*self.raw, name)); } @@ -203,7 +203,7 @@ impl Config { /// This is the same as `get_bytes` except that it may return `Err` if /// the bytes are not valid utf-8. pub fn get_str(&self, name: &str) -> Result<&str, Error> { - str::from_utf8(try!(self.get_bytes(name))) + str::from_utf8(self.get_bytes(name)?) .map_err(|_| Error::from_str("configuration value is not valid utf8")) } @@ -212,10 +212,10 @@ impl Config { /// This method will return an error if this `Config` is not a snapshot. pub fn get_bytes(&self, name: &str) -> Result<&[u8], Error> { let mut ret = ptr::null(); - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_get_string(&mut ret, &*self.raw, name)); - Ok(::opt_bytes(self, ret).unwrap()) + Ok(crate::opt_bytes(self, ret).unwrap()) } } @@ -224,7 +224,7 @@ impl Config { /// An error will be returned if the config value is not valid utf-8. pub fn get_string(&self, name: &str) -> Result { let ret = Buf::new(); - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_get_string_buf(ret.raw(), self.raw, name)); } @@ -236,17 +236,17 @@ impl Config { /// Get the value of a path config variable as an owned . pub fn get_path(&self, name: &str) -> Result { let ret = Buf::new(); - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_get_path(ret.raw(), self.raw, name)); } - Ok(::util::bytes2path(&ret).to_path_buf()) + Ok(crate::util::bytes2path(&ret).to_path_buf()) } /// Get the ConfigEntry for a config variable. pub fn get_entry(&self, name: &str) -> Result { let mut ret = ptr::null_mut(); - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_get_entry(&mut ret, self.raw, name)); Ok(Binding::from_raw(ret)) @@ -276,7 +276,7 @@ impl Config { unsafe { match glob { Some(s) => { - let s = try!(CString::new(s)); + let s = CString::new(s)?; try_call!(raw::git_config_iterator_glob_new(&mut ret, &*self.raw, s)); } None => { @@ -316,7 +316,7 @@ impl Config { /// Set the value of a boolean config variable in the config file with the /// highest level (usually the local one). pub fn set_bool(&mut self, name: &str, value: bool) -> Result<(), Error> { - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_set_bool(self.raw, name, value)); } @@ -326,7 +326,7 @@ impl Config { /// Set the value of an integer config variable in the config file with the /// highest level (usually the local one). pub fn set_i32(&mut self, name: &str, value: i32) -> Result<(), Error> { - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_set_int32(self.raw, name, value)); } @@ -336,7 +336,7 @@ impl Config { /// Set the value of an integer config variable in the config file with the /// highest level (usually the local one). pub fn set_i64(&mut self, name: &str, value: i64) -> Result<(), Error> { - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_config_set_int64(self.raw, name, value)); } @@ -346,9 +346,9 @@ impl Config { /// Set the value of an multivar config variable in the config file with the /// highest level (usually the local one). pub fn set_multivar(&mut self, name: &str, regexp: &str, value: &str) -> Result<(), Error> { - let name = try!(CString::new(name)); - let regexp = try!(CString::new(regexp)); - let value = try!(CString::new(value)); + let name = CString::new(name)?; + let regexp = CString::new(regexp)?; + let value = CString::new(value)?; unsafe { try_call!(raw::git_config_set_multivar(self.raw, name, regexp, value)); } @@ -358,8 +358,8 @@ impl Config { /// Set the value of a string config variable in the config file with the /// highest level (usually the local one). pub fn set_str(&mut self, name: &str, value: &str) -> Result<(), Error> { - let name = try!(CString::new(name)); - let value = try!(CString::new(value)); + let name = CString::new(name)?; + let value = CString::new(value)?; unsafe { try_call!(raw::git_config_set_string(self.raw, name, value)); } @@ -383,9 +383,9 @@ impl Config { /// Interprets "true", "yes", "on", 1, or any non-zero number as true. /// Interprets "false", "no", "off", 0, or an empty string as false. pub fn parse_bool(s: S) -> Result { - let s = try!(s.into_c_string()); + let s = s.into_c_string()?; let mut out = 0; - ::init(); + crate::init(); unsafe { try_call!(raw::git_config_parse_bool(&mut out, s)); } @@ -395,9 +395,9 @@ impl Config { /// Parse a string as an i32; handles suffixes like k, M, or G, and /// multiplies by the appropriate power of 1024. pub fn parse_i32(s: S) -> Result { - let s = try!(s.into_c_string()); + let s = s.into_c_string()?; let mut out = 0; - ::init(); + crate::init(); unsafe { try_call!(raw::git_config_parse_int32(&mut out, s)); } @@ -407,9 +407,9 @@ impl Config { /// Parse a string as an i64; handles suffixes like k, M, or G, and /// multiplies by the appropriate power of 1024. pub fn parse_i64(s: S) -> Result { - let s = try!(s.into_c_string()); + let s = s.into_c_string()?; let mut out = 0; - ::init(); + crate::init(); unsafe { try_call!(raw::git_config_parse_int64(&mut out, s)); } @@ -443,7 +443,7 @@ impl<'cfg> ConfigEntry<'cfg> { /// Gets the name of this entry as a byte slice. pub fn name_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, (*self.raw).name).unwrap() } + unsafe { crate::opt_bytes(self, (*self.raw).name).unwrap() } } /// Gets the value of this entry. @@ -455,7 +455,7 @@ impl<'cfg> ConfigEntry<'cfg> { /// Gets the value of this entry as a byte slice. pub fn value_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, (*self.raw).value).unwrap() } + unsafe { crate::opt_bytes(self, (*self.raw).value).unwrap() } } /// Gets the configuration level of this entry. @@ -537,7 +537,7 @@ mod tests { use std::fs::File; use tempdir::TempDir; - use Config; + use crate::Config; #[test] fn smoke() { diff --git a/src/cred.rs b/src/cred.rs index 580b4c0dcc..9717f5e686 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -6,8 +6,8 @@ use std::process::{Command, Stdio}; use std::ptr; use url; -use util::Binding; -use {raw, Config, Error, IntoCString}; +use crate::util::Binding; +use crate::{raw, Config, Error, IntoCString}; /// A structure to represent git credentials in libgit2. pub struct Cred { @@ -29,7 +29,7 @@ impl Cred { /// Create a "default" credential usable for Negotiate mechanisms like NTLM /// or Kerberos authentication. pub fn default() -> Result { - ::init(); + crate::init(); let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_cred_default_new(&mut out)); @@ -41,9 +41,9 @@ impl Cred { /// /// The username specified is the username to authenticate. pub fn ssh_key_from_agent(username: &str) -> Result { - ::init(); + crate::init(); let mut out = ptr::null_mut(); - let username = try!(CString::new(username)); + let username = CString::new(username)?; unsafe { try_call!(raw::git_cred_ssh_key_from_agent(&mut out, username)); Ok(Binding::from_raw(out)) @@ -57,11 +57,11 @@ impl Cred { privatekey: &Path, passphrase: Option<&str>, ) -> Result { - ::init(); - let username = try!(CString::new(username)); - let publickey = try!(::opt_cstr(publickey)); - let privatekey = try!(privatekey.into_c_string()); - let passphrase = try!(::opt_cstr(passphrase)); + crate::init(); + let username = CString::new(username)?; + let publickey = crate::opt_cstr(publickey)?; + let privatekey = privatekey.into_c_string()?; + let passphrase = crate::opt_cstr(passphrase)?; let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_cred_ssh_key_new( @@ -78,11 +78,11 @@ impl Cred { privatekey: &str, passphrase: Option<&str>, ) -> Result { - ::init(); - let username = try!(CString::new(username)); - let publickey = try!(::opt_cstr(publickey)); - let privatekey = try!(CString::new(privatekey)); - let passphrase = try!(::opt_cstr(passphrase)); + crate::init(); + let username = CString::new(username)?; + let publickey = crate::opt_cstr(publickey)?; + let privatekey = CString::new(privatekey)?; + let passphrase = crate::opt_cstr(passphrase)?; let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_cred_ssh_key_memory_new( @@ -94,9 +94,9 @@ impl Cred { /// Create a new plain-text username and password credential object. pub fn userpass_plaintext(username: &str, password: &str) -> Result { - ::init(); - let username = try!(CString::new(username)); - let password = try!(CString::new(password)); + crate::init(); + let username = CString::new(username)?; + let password = CString::new(password)?; let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_cred_userpass_plaintext_new( @@ -139,8 +139,8 @@ impl Cred { /// THis is used with ssh authentication to query for the username if non is /// specified in the url. pub fn username(username: &str) -> Result { - ::init(); - let username = try!(CString::new(username)); + crate::init(); + let username = CString::new(username)?; let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_cred_username_new(&mut out, username)); @@ -437,7 +437,7 @@ mod test { use std::path::Path; use tempdir::TempDir; - use {Config, ConfigLevel, Cred, CredentialHelper}; + use crate::{Config, ConfigLevel, Cred, CredentialHelper}; macro_rules! test_cfg( ($($k:expr => $v:expr),*) => ({ let td = TempDir::new("git2-rs").unwrap(); diff --git a/src/describe.rs b/src/describe.rs index 5e8d1e9391..efa66e826d 100644 --- a/src/describe.rs +++ b/src/describe.rs @@ -5,8 +5,8 @@ use std::ptr; use libc::{c_int, c_uint}; -use util::Binding; -use {raw, Buf, Error, Repository}; +use crate::util::Binding; +use crate::{raw, Buf, Error, Repository}; /// The result of a `describe` operation on either an `Describe` or a /// `Repository`. @@ -178,11 +178,11 @@ impl Binding for DescribeOptions { #[cfg(test)] mod tests { - use DescribeOptions; + use crate::DescribeOptions; #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let head = t!(repo.head()).target().unwrap(); let d = t!(repo.describe(DescribeOptions::new().show_commit_oid_as_fallback(true))); diff --git a/src/diff.rs b/src/diff.rs index 74f81b774d..ad8ee0d9f0 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -7,9 +7,9 @@ use std::path::Path; use std::ptr; use std::slice; -use util::{self, Binding}; -use {panic, raw, Buf, Delta, DiffFormat, Error, Oid, Repository}; -use {DiffStatsFormat, IntoCString}; +use crate::util::{self, Binding}; +use crate::{panic, raw, Buf, Delta, DiffFormat, Error, Oid, Repository}; +use crate::{DiffStatsFormat, IntoCString}; /// The diff object that contains all individual file deltas. /// @@ -457,7 +457,7 @@ impl<'a> DiffFile<'a> { /// directory of the repository. pub fn path_bytes(&self) -> Option<&'a [u8]> { static FOO: () = (); - unsafe { ::opt_bytes(&FOO, (*self.raw).path) } + unsafe { crate::opt_bytes(&FOO, (*self.raw).path) } } /// Returns the path of the entry relative to the working directory of the @@ -1213,15 +1213,15 @@ impl DiffFindOptions { #[cfg(test)] mod tests { + use crate::DiffOptions; use std::borrow::Borrow; use std::fs::File; use std::io::Write; use std::path::Path; - use DiffOptions; #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let diff = repo.diff_tree_to_workdir(None, None).unwrap(); assert_eq!(diff.deltas().len(), 0); let stats = diff.stats().unwrap(); @@ -1232,7 +1232,7 @@ mod tests { #[test] fn foreach_smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let diff = t!(repo.diff_tree_to_workdir(None, None)); let mut count = 0; t!(diff.foreach( @@ -1250,7 +1250,7 @@ mod tests { #[test] fn foreach_file_only() { let path = Path::new("foo"); - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); t!(t!(File::create(&td.path().join(path))).write_all(b"bar")); let mut opts = DiffOptions::new(); opts.include_untracked(true); @@ -1274,7 +1274,7 @@ mod tests { #[test] fn foreach_file_and_hunk() { let path = Path::new("foo"); - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); t!(t!(File::create(&td.path().join(path))).write_all(b"bar")); let mut index = t!(repo.index()); t!(index.add_path(path)); @@ -1302,7 +1302,7 @@ mod tests { let deflated_fib = vec![120, 156, 99, 96, 100, 100, 98, 102, 229, 0, 0, 0, 53, 0, 21]; let foo_path = Path::new("foo"); let bin_path = Path::new("bin"); - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); t!(t!(File::create(&td.path().join(foo_path))).write_all(b"bar\n")); t!(t!(File::create(&td.path().join(bin_path))).write_all(&fib)); let mut index = t!(repo.index()); diff --git a/src/error.rs b/src/error.rs index 23b601377e..cb55e8aa7c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,7 +5,7 @@ use std::ffi::{CStr, NulError}; use std::fmt; use std::str; -use {raw, ErrorClass, ErrorCode}; +use crate::{raw, ErrorClass, ErrorCode}; /// A structure to represent errors coming out of libgit2. #[derive(Debug, PartialEq)] @@ -26,7 +26,7 @@ impl Error { /// safe to unwrap the return value. This API will change in the next major /// version. pub fn last_error(code: c_int) -> Option { - ::init(); + crate::init(); unsafe { // Note that whenever libgit2 returns an error any negative value // indicates that an error happened. Auxiliary information is @@ -280,11 +280,11 @@ impl From for Error { #[cfg(test)] mod tests { - use {ErrorClass, ErrorCode}; + use crate::{ErrorClass, ErrorCode}; #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let err = repo.find_submodule("does_not_exist").err().unwrap(); assert_eq!(err.code(), ErrorCode::NotFound); diff --git a/src/index.rs b/src/index.rs index 9d5f14054b..9ff379e0f7 100644 --- a/src/index.rs +++ b/src/index.rs @@ -7,9 +7,9 @@ use std::slice; use libc::{c_char, c_int, c_uint, c_void, size_t}; -use util::{self, Binding}; -use IntoCString; -use {panic, raw, Error, IndexAddOption, IndexTime, Oid, Repository, Tree}; +use crate::util::{self, Binding}; +use crate::IntoCString; +use crate::{panic, raw, Error, IndexAddOption, IndexTime, Oid, Repository, Tree}; /// A structure to represent a git [index][1] /// @@ -75,7 +75,7 @@ impl Index { /// This index object cannot be read/written to the filesystem, but may be /// used to perform in-memory index operations. pub fn new() -> Result { - ::init(); + crate::init(); let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_index_new(&mut raw)); @@ -92,9 +92,9 @@ impl Index { /// If you need an index attached to a repository, use the `index()` method /// on `Repository`. pub fn open(index_path: &Path) -> Result { - ::init(); + crate::init(); let mut raw = ptr::null_mut(); - let index_path = try!(index_path.into_c_string()); + let index_path = index_path.into_c_string()?; unsafe { try_call!(raw::git_index_open(&mut raw, index_path)); Ok(Binding::from_raw(raw)) @@ -107,7 +107,7 @@ impl Index { /// given 'source_entry', it will be replaced. Otherwise, the 'source_entry' /// will be added. pub fn add(&mut self, entry: &IndexEntry) -> Result<(), Error> { - let path = try!(CString::new(&entry.path[..])); + let path = CString::new(&entry.path[..])?; // libgit2 encodes the length of the path in the lower bits of the // `flags` entry, so mask those out and recalculate here to ensure we @@ -164,7 +164,7 @@ impl Index { /// no longer be marked as conflicting. The data about the conflict will be /// moved to the "resolve undo" (REUC) section. pub fn add_frombuffer(&mut self, entry: &IndexEntry, data: &[u8]) -> Result<(), Error> { - let path = try!(CString::new(&entry.path[..])); + let path = CString::new(&entry.path[..])?; // libgit2 encodes the length of the path in the lower bits of the // `flags` entry, so mask those out and recalculate here to ensure we @@ -228,7 +228,7 @@ impl Index { } posix_path.push(comp.as_os_str()); } - let posix_path = try!(posix_path.into_c_string()); + let posix_path = posix_path.into_c_string()?; unsafe { try_call!(raw::git_index_add_bypath(self.raw, posix_path)); Ok(()) @@ -278,7 +278,7 @@ impl Index { T: IntoCString, I: IntoIterator, { - let (_a, _b, raw_strarray) = try!(::util::iter2cstrs(pathspecs)); + let (_a, _b, raw_strarray) = crate::util::iter2cstrs(pathspecs)?; let ptr = cb.as_mut(); let callback = ptr .as_ref() @@ -338,7 +338,7 @@ impl Index { /// Get an iterator over the index entries that have conflicts pub fn conflicts(&self) -> Result { - ::init(); + crate::init(); let mut conflict_iter = ptr::null_mut(); unsafe { try_call!(raw::git_index_conflict_iterator_new( @@ -373,7 +373,7 @@ impl Index { /// /// Returns `None` if this is an in-memory index. pub fn path(&self) -> Option<&Path> { - unsafe { ::opt_bytes(self, raw::git_index_path(&*self.raw)).map(util::bytes2path) } + unsafe { crate::opt_bytes(self, raw::git_index_path(&*self.raw)).map(util::bytes2path) } } /// Update the contents of an existing index object in memory by reading @@ -406,7 +406,7 @@ impl Index { /// Remove an entry from the index pub fn remove(&mut self, path: &Path, stage: i32) -> Result<(), Error> { - let path = try!(path.into_c_string()); + let path = path.into_c_string()?; unsafe { try_call!(raw::git_index_remove(self.raw, path, stage as c_int)); } @@ -422,7 +422,7 @@ impl Index { /// no longer be marked as conflicting. The data about the conflict will be /// moved to the "resolve undo" (REUC) section. pub fn remove_path(&mut self, path: &Path) -> Result<(), Error> { - let path = try!(path.into_c_string()); + let path = path.into_c_string()?; unsafe { try_call!(raw::git_index_remove_bypath(self.raw, path)); } @@ -431,7 +431,7 @@ impl Index { /// Remove all entries from the index under a given directory. pub fn remove_dir(&mut self, path: &Path, stage: i32) -> Result<(), Error> { - let path = try!(path.into_c_string()); + let path = path.into_c_string()?; unsafe { try_call!(raw::git_index_remove_directory( self.raw, @@ -456,7 +456,7 @@ impl Index { T: IntoCString, I: IntoIterator, { - let (_a, _b, raw_strarray) = try!(::util::iter2cstrs(pathspecs)); + let (_a, _b, raw_strarray) = crate::util::iter2cstrs(pathspecs)?; let ptr = cb.as_mut(); let callback = ptr .as_ref() @@ -494,7 +494,7 @@ impl Index { T: IntoCString, I: IntoIterator, { - let (_a, _b, raw_strarray) = try!(::util::iter2cstrs(pathspecs)); + let (_a, _b, raw_strarray) = crate::util::iter2cstrs(pathspecs)?; let ptr = cb.as_mut(); let callback = ptr .as_ref() @@ -703,7 +703,7 @@ mod tests { use std::path::Path; use tempdir::TempDir; - use {Index, IndexEntry, IndexTime, Oid, Repository, ResetType}; + use crate::{Index, IndexEntry, IndexTime, Oid, Repository, ResetType}; #[test] fn smoke() { @@ -718,7 +718,7 @@ mod tests { #[test] fn smoke_from_repo() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut index = repo.index().unwrap(); assert_eq!( index.path().map(|s| s.to_path_buf()), @@ -735,7 +735,7 @@ mod tests { #[test] fn add_all() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut index = repo.index().unwrap(); let root = repo.path().parent().unwrap(); @@ -745,7 +745,7 @@ mod tests { index .add_all( ["foo"].iter(), - ::IndexAddOption::DEFAULT, + crate::IndexAddOption::DEFAULT, Some(&mut |a: &Path, b: &[u8]| { assert!(!called); called = true; @@ -775,7 +775,7 @@ mod tests { #[test] fn smoke_add() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut index = repo.index().unwrap(); let root = repo.path().parent().unwrap(); @@ -798,7 +798,7 @@ mod tests { repo.reset(&obj, ResetType::Hard, None).unwrap(); let td2 = TempDir::new("git").unwrap(); - let url = ::test::path2url(https://github.com/&root); + let url = crate::test::path2url(https://github.com/&root); let repo = Repository::clone(&url, td2.path()).unwrap(); let obj = repo.find_object(commit, None).unwrap(); repo.reset(&obj, ResetType::Hard, None).unwrap(); @@ -819,7 +819,7 @@ mod tests { #[test] fn add_frombuffer_then_read() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut index = repo.index().unwrap(); let mut e = entry(); diff --git a/src/lib.rs b/src/lib.rs index 917c9fe14d..3476921f0b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,49 +83,53 @@ use std::fmt; use std::str; use std::sync::{Once, ONCE_INIT}; -pub use blame::{Blame, BlameHunk, BlameIter, BlameOptions}; -pub use blob::{Blob, BlobWriter}; -pub use branch::{Branch, Branches}; -pub use buf::Buf; -pub use commit::{Commit, Parents}; -pub use config::{Config, ConfigEntries, ConfigEntry}; -pub use cred::{Cred, CredentialHelper}; -pub use describe::{Describe, DescribeFormatOptions, DescribeOptions}; -pub use diff::{Deltas, Diff, DiffDelta, DiffFile, DiffOptions}; -pub use diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind}; -pub use diff::{DiffFindOptions, DiffHunk, DiffLine, DiffStats}; -pub use error::Error; -pub use index::{Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath}; -pub use merge::{AnnotatedCommit, MergeOptions}; -pub use message::{message_prettify, DEFAULT_COMMENT_CHAR}; -pub use note::{Note, Notes}; -pub use object::Object; -pub use odb::{Odb, OdbObject, OdbReader, OdbWriter}; -pub use oid::Oid; -pub use packbuilder::{PackBuilder, PackBuilderStage}; -pub use patch::Patch; -pub use pathspec::{Pathspec, PathspecFailedEntries, PathspecMatchList}; -pub use pathspec::{PathspecDiffEntries, PathspecEntries}; -pub use proxy_options::ProxyOptions; -pub use rebase::{Rebase, RebaseOperation, RebaseOperationType, RebaseOptions}; -pub use reference::{Reference, ReferenceNames, References}; -pub use reflog::{Reflog, ReflogEntry, ReflogIter}; -pub use refspec::Refspec; -pub use remote::{FetchOptions, PushOptions, Refspecs, Remote, RemoteConnection, RemoteHead}; -pub use remote_callbacks::{Credentials, RemoteCallbacks, TransferProgress}; -pub use remote_callbacks::{Progress, TransportMessage, UpdateTips}; -pub use repo::{Repository, RepositoryInitOptions}; -pub use revspec::Revspec; -pub use revwalk::Revwalk; -pub use signature::Signature; -pub use stash::{StashApplyOptions, StashApplyProgressCb, StashCb}; -pub use status::{StatusEntry, StatusIter, StatusOptions, StatusShow, Statuses}; -pub use submodule::{Submodule, SubmoduleUpdateOptions}; -pub use tag::Tag; -pub use time::{IndexTime, Time}; -pub use tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult}; -pub use treebuilder::TreeBuilder; -pub use util::IntoCString; +pub use crate::blame::{Blame, BlameHunk, BlameIter, BlameOptions}; +pub use crate::blob::{Blob, BlobWriter}; +pub use crate::branch::{Branch, Branches}; +pub use crate::buf::Buf; +pub use crate::commit::{Commit, Parents}; +pub use crate::config::{Config, ConfigEntries, ConfigEntry}; +pub use crate::cred::{Cred, CredentialHelper}; +pub use crate::describe::{Describe, DescribeFormatOptions, DescribeOptions}; +pub use crate::diff::{Deltas, Diff, DiffDelta, DiffFile, DiffOptions}; +pub use crate::diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind}; +pub use crate::diff::{DiffFindOptions, DiffHunk, DiffLine, DiffStats}; +pub use crate::error::Error; +pub use crate::index::{ + Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath, +}; +pub use crate::merge::{AnnotatedCommit, MergeOptions}; +pub use crate::message::{message_prettify, DEFAULT_COMMENT_CHAR}; +pub use crate::note::{Note, Notes}; +pub use crate::object::Object; +pub use crate::odb::{Odb, OdbObject, OdbReader, OdbWriter}; +pub use crate::oid::Oid; +pub use crate::packbuilder::{PackBuilder, PackBuilderStage}; +pub use crate::patch::Patch; +pub use crate::pathspec::{Pathspec, PathspecFailedEntries, PathspecMatchList}; +pub use crate::pathspec::{PathspecDiffEntries, PathspecEntries}; +pub use crate::proxy_options::ProxyOptions; +pub use crate::rebase::{Rebase, RebaseOperation, RebaseOperationType, RebaseOptions}; +pub use crate::reference::{Reference, ReferenceNames, References}; +pub use crate::reflog::{Reflog, ReflogEntry, ReflogIter}; +pub use crate::refspec::Refspec; +pub use crate::remote::{ + FetchOptions, PushOptions, Refspecs, Remote, RemoteConnection, RemoteHead, +}; +pub use crate::remote_callbacks::{Credentials, RemoteCallbacks, TransferProgress}; +pub use crate::remote_callbacks::{Progress, TransportMessage, UpdateTips}; +pub use crate::repo::{Repository, RepositoryInitOptions}; +pub use crate::revspec::Revspec; +pub use crate::revwalk::Revwalk; +pub use crate::signature::Signature; +pub use crate::stash::{StashApplyOptions, StashApplyProgressCb, StashCb}; +pub use crate::status::{StatusEntry, StatusIter, StatusOptions, StatusShow, Statuses}; +pub use crate::submodule::{Submodule, SubmoduleUpdateOptions}; +pub use crate::tag::Tag; +pub use crate::time::{IndexTime, Time}; +pub use crate::tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult}; +pub use crate::treebuilder::TreeBuilder; +pub use crate::util::IntoCString; // Create a convinience method on bitflag struct which checks the given flag macro_rules! is_bit_set { diff --git a/src/merge.rs b/src/merge.rs index 27a52c90cc..edf7cee64d 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -2,9 +2,9 @@ use libc::c_uint; use std::marker; use std::mem; -use call::Convert; -use util::Binding; -use {raw, Commit, FileFavor, Oid}; +use crate::call::Convert; +use crate::util::Binding; +use crate::{raw, Commit, FileFavor, Oid}; /// A structure to represent an annotated commit, the input to merge and rebase. /// diff --git a/src/message.rs b/src/message.rs index b36419e270..7c17eeffe0 100644 --- a/src/message.rs +++ b/src/message.rs @@ -2,8 +2,8 @@ use std::ffi::CString; use libc::{c_char, c_int}; -use util::Binding; -use {raw, Buf, Error, IntoCString}; +use crate::util::Binding; +use crate::{raw, Buf, Error, IntoCString}; /// Clean up a message, removing extraneous whitespace, and ensure that the /// message ends with a newline. If `comment_char` is `Some`, also remove comment @@ -12,7 +12,7 @@ pub fn message_prettify( message: T, comment_char: Option, ) -> Result { - _message_prettify(try!(message.into_c_string()), comment_char) + _message_prettify(message.into_c_string()?, comment_char) } fn _message_prettify(message: CString, comment_char: Option) -> Result { @@ -33,7 +33,7 @@ pub const DEFAULT_COMMENT_CHAR: Option = Some(b'#'); #[cfg(test)] mod tests { - use {message_prettify, DEFAULT_COMMENT_CHAR}; + use crate::{message_prettify, DEFAULT_COMMENT_CHAR}; #[test] fn prettify() { diff --git a/src/note.rs b/src/note.rs index 8bf8a7f8b4..25dc3bef0d 100644 --- a/src/note.rs +++ b/src/note.rs @@ -1,8 +1,8 @@ use std::marker; use std::str; -use util::Binding; -use {raw, signature, Error, Oid, Repository, Signature}; +use crate::util::Binding; +use crate::{raw, signature, Error, Oid, Repository, Signature}; /// A structure representing a [note][note] in git. /// @@ -35,7 +35,7 @@ impl<'repo> Note<'repo> { /// Get the note message, in bytes. pub fn message_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_note_message(&*self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_note_message(&*self.raw)).unwrap() } } /// Get the note message as a string, returning `None` if it is not UTF-8. @@ -62,8 +62,8 @@ impl<'repo> Binding for Note<'repo> { } } -impl<'repo> ::std::fmt::Debug for Note<'repo> { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { +impl<'repo> std::fmt::Debug for Note<'repo> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { f.debug_struct("Note").field("id", &self.id()).finish() } } @@ -122,7 +122,7 @@ impl<'repo> Drop for Notes<'repo> { mod tests { #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); assert!(repo.notes(None).is_err()); let sig = repo.signature().unwrap(); diff --git a/src/object.rs b/src/object.rs index 023a4aed96..18c7b03c44 100644 --- a/src/object.rs +++ b/src/object.rs @@ -2,9 +2,9 @@ use std::marker; use std::mem; use std::ptr; -use util::Binding; -use {raw, Blob, Buf, Commit, Error, ObjectType, Oid, Repository, Tag, Tree}; -use {Describe, DescribeOptions}; +use crate::util::Binding; +use crate::{raw, Blob, Buf, Commit, Error, ObjectType, Oid, Repository, Tag, Tree}; +use crate::{Describe, DescribeOptions}; /// A structure to represent a git [object][1] /// @@ -212,8 +212,8 @@ impl<'repo> Clone for Object<'repo> { } } -impl<'repo> ::std::fmt::Debug for Object<'repo> { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { +impl<'repo> std::fmt::Debug for Object<'repo> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { let mut ds = f.debug_struct("Object"); match self.kind() { Some(kind) => ds.field("kind", &kind), diff --git a/src/odb.rs b/src/odb.rs index 353a0778d5..6d3635a887 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -7,9 +7,9 @@ use std::ffi::CString; use libc::{c_char, c_int, c_void, size_t}; -use panic; -use util::Binding; -use {raw, Error, Object, ObjectType, Oid}; +use crate::panic; +use crate::util::Binding; +use crate::{raw, Error, Object, ObjectType, Oid}; /// A structure to represent a git object database pub struct Odb<'repo> { @@ -187,7 +187,7 @@ impl<'repo> Odb<'repo> { /// Adds an alternate disk backend to the object database. pub fn add_disk_alternate(&self, path: &str) -> Result<(), Error> { unsafe { - let path = try!(CString::new(path)); + let path = CString::new(path)?; try_call!(raw::git_odb_add_disk_alternate(self.raw, path)); Ok(()) } @@ -376,9 +376,9 @@ extern "C" fn foreach_cb(id: *const raw::git_oid, payload: *mut c_void) -> c_int #[cfg(test)] mod tests { + use crate::{ObjectType, Oid, Repository}; use std::io::prelude::*; use tempdir::TempDir; - use {ObjectType, Oid, Repository}; #[test] fn read() { diff --git a/src/oid.rs b/src/oid.rs index 6af1296613..7de941bfc7 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -5,9 +5,9 @@ use std::hash::{Hash, Hasher}; use std::path::Path; use std::str; -use {raw, Error, IntoCString, ObjectType}; +use crate::{raw, Error, IntoCString, ObjectType}; -use util::{c_cmp_to_ordering, Binding}; +use crate::util::{c_cmp_to_ordering, Binding}; /// Unique identity of any object (commit, tree, blob, tag). #[derive(Copy, Clone)] @@ -23,7 +23,7 @@ impl Oid { /// Returns an error if the string is empty, is longer than 40 hex /// characters, or contains any non-hex characters. pub fn from_str(s: &str) -> Result { - ::init(); + crate::init(); let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; @@ -41,7 +41,7 @@ impl Oid { /// /// If the array given is not 20 bytes in length, an error is returned. pub fn from_bytes(bytes: &[u8]) -> Result { - ::init(); + crate::init(); let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; @@ -65,7 +65,7 @@ impl Oid { /// an Oid corresponding to the result. This does not store the object /// inside any object database or repository. pub fn hash_object(kind: ObjectType, bytes: &[u8]) -> Result { - ::init(); + crate::init(); let mut out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], @@ -86,9 +86,9 @@ impl Oid { /// and returns an Oid corresponding to the result. This does not store the object /// inside any object database or repository. pub fn hash_file>(kind: ObjectType, path: P) -> Result { - ::init(); + crate::init(); - let rpath = try!(path.as_ref().into_c_string()); + let rpath = path.as_ref().into_c_string()?; let mut out = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], @@ -196,8 +196,8 @@ mod tests { use super::Error; use super::Oid; + use crate::ObjectType; use tempdir::TempDir; - use ObjectType; #[test] fn conversions() { diff --git a/src/oid_array.rs b/src/oid_array.rs index 1a369abd07..b2caf0e061 100644 --- a/src/oid_array.rs +++ b/src/oid_array.rs @@ -2,11 +2,11 @@ use std::ops::Deref; -use oid::Oid; -use raw; +use crate::oid::Oid; +use crate::raw; +use crate::util::Binding; use std::mem; use std::slice; -use util::Binding; /// An oid array structure used by libgit2 /// @@ -39,8 +39,8 @@ impl Binding for OidArray { } } -impl<'repo> ::std::fmt::Debug for OidArray { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { +impl<'repo> std::fmt::Debug for OidArray { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { f.debug_tuple("OidArray").field(&self.deref()).finish() } } diff --git a/src/packbuilder.rs b/src/packbuilder.rs index 1890cf9c54..2d65c6e9d6 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -3,8 +3,8 @@ use std::marker; use std::ptr; use std::slice; -use util::Binding; -use {panic, raw, Buf, Error, Oid, Repository, Revwalk}; +use crate::util::Binding; +use crate::{panic, raw, Buf, Error, Oid, Repository, Revwalk}; /// Stages that are reported by the `PackBuilder` progress callback. pub enum PackBuilderStage { @@ -28,7 +28,7 @@ impl<'repo> PackBuilder<'repo> { /// Insert a single object. For an optimal pack it's mandatory to insert /// objects in recency order, commits followed by trees and blobs. pub fn insert_object(&mut self, id: Oid, name: Option<&str>) -> Result<(), Error> { - let name = try!(::opt_cstr(name)); + let name = crate::opt_cstr(name)?; unsafe { try_call!(raw::git_packbuilder_insert(self.raw, id.raw(), name)); } @@ -65,7 +65,7 @@ impl<'repo> PackBuilder<'repo> { /// Recursively insert an object and its referenced objects. Insert the /// object as well as any object it references. pub fn insert_recursive(&mut self, id: Oid, name: Option<&str>) -> Result<(), Error> { - let name = try!(::opt_cstr(name)); + let name = crate::opt_cstr(name)?; unsafe { try_call!(raw::git_packbuilder_insert_recur(self.raw, id.raw(), name)); } @@ -239,9 +239,9 @@ extern "C" fn progress_c( #[cfg(test)] mod tests { + use crate::{Buf, Oid, Repository}; use std::fs::File; use std::path::Path; - use {Buf, Oid, Repository}; fn commit(repo: &Repository) -> (Oid, Oid) { let mut index = t!(repo.index()); @@ -282,13 +282,13 @@ mod tests { #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let _builder = t!(repo.packbuilder()); } #[test] fn smoke_write_buf() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); let mut buf = Buf::new(); t!(builder.write_buf(&mut buf)); @@ -298,7 +298,7 @@ mod tests { #[test] fn smoke_foreach() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); let mut buf = Vec::::new(); t!(builder.foreach(|bytes| { @@ -310,7 +310,7 @@ mod tests { #[test] fn insert_write_buf() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); let mut buf = Buf::new(); let (commit, _tree) = commit(&repo); @@ -323,7 +323,7 @@ mod tests { #[test] fn insert_tree_write_buf() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); let mut buf = Buf::new(); let (_commit, tree) = commit(&repo); @@ -337,7 +337,7 @@ mod tests { #[test] fn insert_commit_write_buf() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); let mut buf = Buf::new(); let (commit, _tree) = commit(&repo); @@ -353,7 +353,7 @@ mod tests { fn progress_callback() { let mut progress_called = false; { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); let (commit, _tree) = commit(&repo); t!(builder.set_progress_callback(|_, _, _| { @@ -370,7 +370,7 @@ mod tests { fn clear_progress_callback() { let mut progress_called = false; { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); let (commit, _tree) = commit(&repo); t!(builder.set_progress_callback(|_, _, _| { diff --git a/src/panic.rs b/src/panic.rs index 3d7c235029..70038d910c 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -5,7 +5,7 @@ thread_local!(static LAST_ERROR: RefCell>> = { RefCell::new(None) }); -pub fn wrap T + ::std::panic::UnwindSafe>(f: F) -> Option { +pub fn wrap T + std::panic::UnwindSafe>(f: F) -> Option { use std::panic; if LAST_ERROR.with(|slot| slot.borrow().is_some()) { return None; diff --git a/src/patch.rs b/src/patch.rs index c0ac9af528..62c30017b1 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -2,9 +2,9 @@ use libc::{c_int, c_void}; use std::path::Path; use std::ptr; -use diff::{print_cb, LineCb}; -use util::{into_opt_c_string, Binding}; -use {raw, Blob, Buf, Diff, DiffDelta, DiffHunk, DiffLine, DiffOptions, Error}; +use crate::diff::{print_cb, LineCb}; +use crate::util::{into_opt_c_string, Binding}; +use crate::{raw, Blob, Buf, Diff, DiffDelta, DiffHunk, DiffLine, DiffOptions, Error}; /// A structure representing the text changes in a single diff delta. /// @@ -52,8 +52,8 @@ impl Patch { opts: Option<&mut DiffOptions>, ) -> Result { let mut ret = ptr::null_mut(); - let old_path = try!(into_opt_c_string(old_path)); - let new_path = try!(into_opt_c_string(new_path)); + let old_path = into_opt_c_string(old_path)?; + let new_path = into_opt_c_string(new_path)?; unsafe { try_call!(raw::git_patch_from_blobs( &mut ret, @@ -76,8 +76,8 @@ impl Patch { opts: Option<&mut DiffOptions>, ) -> Result { let mut ret = ptr::null_mut(); - let old_path = try!(into_opt_c_string(old_path)); - let new_path = try!(into_opt_c_string(new_path)); + let old_path = into_opt_c_string(old_path)?; + let new_path = into_opt_c_string(new_path)?; unsafe { try_call!(raw::git_patch_from_blob_and_buffer( &mut ret, @@ -101,8 +101,8 @@ impl Patch { opts: Option<&mut DiffOptions>, ) -> Result { let mut ret = ptr::null_mut(); - let old_path = try!(into_opt_c_string(old_path)); - let new_path = try!(into_opt_c_string(new_path)); + let old_path = into_opt_c_string(old_path)?; + let new_path = into_opt_c_string(new_path)?; unsafe { try_call!(raw::git_patch_from_buffers( &mut ret, diff --git a/src/pathspec.rs b/src/pathspec.rs index 26a68afb2e..d609649fd2 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -5,8 +5,8 @@ use std::ops::Range; use std::path::Path; use std::ptr; -use util::Binding; -use {raw, Diff, DiffDelta, Error, Index, IntoCString, PathspecFlags, Repository, Tree}; +use crate::util::Binding; +use crate::{raw, Diff, DiffDelta, Error, Index, IntoCString, PathspecFlags, Repository, Tree}; /// Structure representing a compiled pathspec used for matching against various /// structures. @@ -45,7 +45,7 @@ impl Pathspec { T: IntoCString, I: IntoIterator, { - let (_a, _b, arr) = try!(::util::iter2cstrs(specs)); + let (_a, _b, arr) = crate::util::iter2cstrs(specs)?; unsafe { let mut ret = ptr::null_mut(); try_call!(raw::git_pathspec_new(&mut ret, &arr)); @@ -210,7 +210,7 @@ impl<'ps> PathspecMatchList<'ps> { pub fn entry(&self, i: usize) -> Option<&[u8]> { unsafe { let ptr = raw::git_pathspec_match_list_entry(&*self.raw, i as size_t); - ::opt_bytes(self, ptr) + crate::opt_bytes(self, ptr) } } @@ -257,7 +257,7 @@ impl<'ps> PathspecMatchList<'ps> { pub fn failed_entry(&self, i: usize) -> Option<&[u8]> { unsafe { let ptr = raw::git_pathspec_match_list_failed_entry(&*self.raw, i as size_t); - ::opt_bytes(self, ptr) + crate::opt_bytes(self, ptr) } } } @@ -335,9 +335,9 @@ impl<'list> ExactSizeIterator for PathspecFailedEntries<'list> {} #[cfg(test)] mod tests { use super::Pathspec; + use crate::PathspecFlags; use std::fs::File; use std::path::Path; - use PathspecFlags; #[test] fn smoke() { @@ -347,7 +347,7 @@ mod tests { assert!(!ps.matches_path(Path::new("b"), PathspecFlags::DEFAULT)); assert!(!ps.matches_path(Path::new("ab/c"), PathspecFlags::DEFAULT)); - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); let list = ps.match_workdir(&repo, PathspecFlags::DEFAULT).unwrap(); assert_eq!(list.entries().len(), 0); assert_eq!(list.diff_entries().len(), 0); @@ -356,7 +356,7 @@ mod tests { File::create(&td.path().join("a")).unwrap(); let list = ps - .match_workdir(&repo, ::PathspecFlags::FIND_FAILURES) + .match_workdir(&repo, crate::PathspecFlags::FIND_FAILURES) .unwrap(); assert_eq!(list.entries().len(), 1); assert_eq!(list.entries().next(), Some("a".as_bytes())); diff --git a/src/proxy_options.rs b/src/proxy_options.rs index e1601749be..b19ba3a527 100644 --- a/src/proxy_options.rs +++ b/src/proxy_options.rs @@ -2,8 +2,8 @@ use std::ffi::CString; use std::marker; use std::ptr; -use raw; -use util::Binding; +use crate::raw; +use crate::util::Binding; /// Options which can be specified to various fetch operations. #[derive(Default)] diff --git a/src/rebase.rs b/src/rebase.rs index 3d9b574905..578247a7e5 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -1,9 +1,9 @@ use std::ffi::CString; use std::{marker, mem, ptr, str}; -use build::CheckoutBuilder; -use util::Binding; -use {raw, Error, Index, MergeOptions, Oid, Signature}; +use crate::build::CheckoutBuilder; +use crate::util::Binding; +use crate::{raw, Error, Index, MergeOptions, Oid, Signature}; /// Rebase options /// @@ -157,7 +157,7 @@ impl<'repo> Rebase<'repo> { message: Option<&str>, ) -> Result { let mut id: raw::git_oid = unsafe { mem::zeroed() }; - let message = try!(::opt_cstr(message)); + let message = crate::opt_cstr(message)?; unsafe { try_call!(raw::git_rebase_commit( &mut id, @@ -299,7 +299,7 @@ impl<'rebase> RebaseOperation<'rebase> { ///The executable the user has requested be run. This will only /// be populated for operations of type RebaseOperationType::Exec pub fn exec(&self) -> Option<&str> { - unsafe { str::from_utf8(::opt_bytes(self, (*self.raw).exec).unwrap()).ok() } + unsafe { str::from_utf8(crate::opt_bytes(self, (*self.raw).exec).unwrap()).ok() } } } @@ -318,12 +318,12 @@ impl<'rebase> Binding for RebaseOperation<'rebase> { #[cfg(test)] mod tests { + use crate::{RebaseOperationType, RebaseOptions, Signature}; use std::{fs, path}; - use {RebaseOperationType, RebaseOptions, Signature}; #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let head_target = repo.head().unwrap().target().unwrap(); let tip = repo.find_commit(head_target).unwrap(); let sig = tip.author(); @@ -366,7 +366,7 @@ mod tests { #[test] fn keeping_original_author_msg() { - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); let head_target = repo.head().unwrap().target().unwrap(); let tip = repo.find_commit(head_target).unwrap(); let sig = Signature::now("testname", "testemail").unwrap(); diff --git a/src/reference.rs b/src/reference.rs index 11e5b30aad..eeaa5bd180 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -5,9 +5,11 @@ use std::mem; use std::ptr; use std::str; -use object::CastOrPanic; -use util::{c_cmp_to_ordering, Binding}; -use {raw, Blob, Commit, Error, Object, ObjectType, Oid, ReferenceType, Repository, Tag, Tree}; +use crate::object::CastOrPanic; +use crate::util::{c_cmp_to_ordering, Binding}; +use crate::{ + raw, Blob, Commit, Error, Object, ObjectType, Oid, ReferenceType, Repository, Tag, Tree, +}; struct Refdb<'repo>(&'repo Repository); @@ -33,7 +35,7 @@ pub struct ReferenceNames<'repo: 'references, 'references> { impl<'repo> Reference<'repo> { /// Ensure the reference name is well-formed. pub fn is_valid_name(refname: &str) -> bool { - ::init(); + crate::init(); let refname = CString::new(refname).unwrap(); unsafe { raw::git_reference_is_valid_name(refname.as_ptr()) == 1 } } @@ -93,7 +95,7 @@ impl<'repo> Reference<'repo> { /// Get the full name of a reference. pub fn name_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_reference_name(&*self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_reference_name(&*self.raw)).unwrap() } } /// Get the full shorthand of a reference. @@ -108,7 +110,7 @@ impl<'repo> Reference<'repo> { /// Get the full shorthand of a reference. pub fn shorthand_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_reference_shorthand(&*self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_reference_shorthand(&*self.raw)).unwrap() } } /// Get the OID pointed to by a direct reference. @@ -140,7 +142,7 @@ impl<'repo> Reference<'repo> { /// /// Only available if the reference is symbolic. pub fn symbolic_target_bytes(&self) -> Option<&[u8]> { - unsafe { ::opt_bytes(self, raw::git_reference_symbolic_target(&*self.raw)) } + unsafe { crate::opt_bytes(self, raw::git_reference_symbolic_target(&*self.raw)) } } /// Resolve a symbolic reference to a direct reference. @@ -175,7 +177,7 @@ impl<'repo> Reference<'repo> { /// This method recursively peels the reference until it reaches /// a blob. pub fn peel_to_blob(&self) -> Result, Error> { - Ok(try!(self.peel(ObjectType::Blob)).cast_or_panic(ObjectType::Blob)) + Ok(self.peel(ObjectType::Blob)?.cast_or_panic(ObjectType::Blob)) } /// Peel a reference to a commit @@ -183,7 +185,9 @@ impl<'repo> Reference<'repo> { /// This method recursively peels the reference until it reaches /// a commit. pub fn peel_to_commit(&self) -> Result, Error> { - Ok(try!(self.peel(ObjectType::Commit)).cast_or_panic(ObjectType::Commit)) + Ok(self + .peel(ObjectType::Commit)? + .cast_or_panic(ObjectType::Commit)) } /// Peel a reference to a tree @@ -191,7 +195,7 @@ impl<'repo> Reference<'repo> { /// This method recursively peels the reference until it reaches /// a tree. pub fn peel_to_tree(&self) -> Result, Error> { - Ok(try!(self.peel(ObjectType::Tree)).cast_or_panic(ObjectType::Tree)) + Ok(self.peel(ObjectType::Tree)?.cast_or_panic(ObjectType::Tree)) } /// Peel a reference to a tag @@ -199,7 +203,7 @@ impl<'repo> Reference<'repo> { /// This method recursively peels the reference until it reaches /// a tag. pub fn peel_to_tag(&self) -> Result, Error> { - Ok(try!(self.peel(ObjectType::Tag)).cast_or_panic(ObjectType::Tag)) + Ok(self.peel(ObjectType::Tag)?.cast_or_panic(ObjectType::Tag)) } /// Rename an existing reference. @@ -215,8 +219,8 @@ impl<'repo> Reference<'repo> { msg: &str, ) -> Result, Error> { let mut raw = ptr::null_mut(); - let new_name = try!(CString::new(new_name)); - let msg = try!(CString::new(msg)); + let new_name = CString::new(new_name)?; + let msg = CString::new(msg)?; unsafe { try_call!(raw::git_reference_rename( &mut raw, self.raw, new_name, force, msg @@ -233,7 +237,7 @@ impl<'repo> Reference<'repo> { /// reference. pub fn set_target(&mut self, id: Oid, reflog_msg: &str) -> Result, Error> { let mut raw = ptr::null_mut(); - let msg = try!(CString::new(reflog_msg)); + let msg = CString::new(reflog_msg)?; unsafe { try_call!(raw::git_reference_set_target( &mut raw, @@ -334,7 +338,7 @@ impl<'repo, 'references> Iterator for ReferenceNames<'repo, 'references> { let mut out = ptr::null(); unsafe { try_call_iter!(raw::git_reference_next_name(&mut out, self.inner.raw)); - let bytes = ::opt_bytes(self, out).unwrap(); + let bytes = crate::opt_bytes(self, out).unwrap(); let s = str::from_utf8(bytes).unwrap(); Some(Ok(mem::transmute::<&str, &'references str>(s))) } @@ -343,7 +347,7 @@ impl<'repo, 'references> Iterator for ReferenceNames<'repo, 'references> { #[cfg(test)] mod tests { - use {ObjectType, Reference, ReferenceType}; + use crate::{ObjectType, Reference, ReferenceType}; #[test] fn smoke() { @@ -353,7 +357,7 @@ mod tests { #[test] fn smoke2() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut head = repo.head().unwrap(); assert!(head.is_branch()); assert!(!head.is_remote()); diff --git a/src/reflog.rs b/src/reflog.rs index 4e0acfba5d..0aed4e56bd 100644 --- a/src/reflog.rs +++ b/src/reflog.rs @@ -3,8 +3,8 @@ use std::marker; use std::ops::Range; use std::str; -use util::Binding; -use {raw, signature, Error, Oid, Signature}; +use crate::util::Binding; +use crate::{raw, signature, Error, Oid, Signature}; /// A reference log of a git repository. pub struct Reflog { @@ -31,7 +31,7 @@ impl Reflog { committer: &Signature, msg: Option<&str>, ) -> Result<(), Error> { - let msg = try!(::opt_cstr(msg)); + let msg = crate::opt_cstr(msg)?; unsafe { try_call!(raw::git_reflog_append( self.raw, @@ -142,7 +142,7 @@ impl<'reflog> ReflogEntry<'reflog> { /// Get the log message as a byte array. pub fn message_bytes(&self) -> Option<&[u8]> { - unsafe { ::opt_bytes(self, raw::git_reflog_entry_message(self.raw)) } + unsafe { crate::opt_bytes(self, raw::git_reflog_entry_message(self.raw)) } } } @@ -180,7 +180,7 @@ impl<'reflog> ExactSizeIterator for ReflogIter<'reflog> {} mod tests { #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut reflog = repo.reflog("HEAD").unwrap(); assert_eq!(reflog.iter().len(), 1); reflog.write().unwrap(); diff --git a/src/refspec.rs b/src/refspec.rs index 61654a6762..79e529d6c8 100644 --- a/src/refspec.rs +++ b/src/refspec.rs @@ -2,8 +2,8 @@ use std::ffi::CString; use std::marker; use std::str; -use util::Binding; -use {raw, Direction}; +use crate::util::Binding; +use crate::{raw, Direction}; /// A structure to represent a git [refspec][1]. /// @@ -34,7 +34,7 @@ impl<'remote> Refspec<'remote> { /// Get the destination specifier, in bytes. pub fn dst_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_refspec_dst(self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_refspec_dst(self.raw)).unwrap() } } /// Check if a refspec's destination descriptor matches a reference @@ -52,7 +52,7 @@ impl<'remote> Refspec<'remote> { /// Get the source specifier, in bytes. pub fn src_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_refspec_src(self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_refspec_src(self.raw)).unwrap() } } /// Check if a refspec's source descriptor matches a reference @@ -75,7 +75,7 @@ impl<'remote> Refspec<'remote> { /// Get the refspec's string as a byte array pub fn bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_refspec_string(self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_refspec_string(self.raw)).unwrap() } } } diff --git a/src/remote.rs b/src/remote.rs index e723155c42..9b919c9cbd 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -7,10 +7,10 @@ use std::ptr; use std::slice; use std::str; -use string_array::StringArray; -use util::Binding; -use {raw, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec}; -use {AutotagOption, Progress, RemoteCallbacks, Repository}; +use crate::string_array::StringArray; +use crate::util::Binding; +use crate::{raw, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec}; +use crate::{AutotagOption, Progress, RemoteCallbacks, Repository}; /// A structure representing a [remote][1] of a git repository. /// @@ -71,7 +71,7 @@ pub fn remote_into_raw(remote: Remote) -> *mut raw::git_remote { impl<'repo> Remote<'repo> { /// Ensure the remote name is well-formed. pub fn is_valid_name(remote_name: &str) -> bool { - ::init(); + crate::init(); let remote_name = CString::new(remote_name).unwrap(); unsafe { raw::git_remote_is_valid_name(remote_name.as_ptr()) == 1 } } @@ -88,7 +88,7 @@ impl<'repo> Remote<'repo> { /// /// Returns `None` if this remote has not yet been named pub fn name_bytes(&self) -> Option<&[u8]> { - unsafe { ::opt_bytes(self, raw::git_remote_name(&*self.raw)) } + unsafe { crate::opt_bytes(self, raw::git_remote_name(&*self.raw)) } } /// Get the remote's url. @@ -100,7 +100,7 @@ impl<'repo> Remote<'repo> { /// Get the remote's url as a byte array. pub fn url_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_remote_url(https://github.com/&*self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_remote_url(https://github.com/&*self.raw)).unwrap() } } /// Get the remote's pushurl. @@ -112,7 +112,7 @@ impl<'repo> Remote<'repo> { /// Get the remote's pushurl as a byte array. pub fn pushurl_bytes(&self) -> Option<&[u8]> { - unsafe { ::opt_bytes(self, raw::git_remote_pushurl(https://github.com/&*self.raw)) } + unsafe { crate::opt_bytes(self, raw::git_remote_pushurl(https://github.com/&*self.raw)) } } /// Open a connection to a remote. @@ -183,7 +183,7 @@ impl<'repo> Remote<'repo> { specs: &[&str], opts: Option<&mut FetchOptions>, ) -> Result<(), Error> { - let (_a, _b, arr) = try!(::util::iter2cstrs(specs.iter())); + let (_a, _b, arr) = crate::util::iter2cstrs(specs.iter())?; let raw = opts.map(|o| o.raw()); unsafe { try_call!(raw::git_remote_download(self.raw, &arr, raw.as_ref())); @@ -233,8 +233,8 @@ impl<'repo> Remote<'repo> { opts: Option<&mut FetchOptions>, reflog_msg: Option<&str>, ) -> Result<(), Error> { - let (_a, _b, arr) = try!(::util::iter2cstrs(refspecs.iter())); - let msg = try!(::opt_cstr(reflog_msg)); + let (_a, _b, arr) = crate::util::iter2cstrs(refspecs.iter())?; + let msg = crate::opt_cstr(reflog_msg)?; let raw = opts.map(|o| o.raw()); unsafe { try_call!(raw::git_remote_fetch(self.raw, &arr, raw.as_ref(), msg)); @@ -250,7 +250,7 @@ impl<'repo> Remote<'repo> { download_tags: AutotagOption, msg: Option<&str>, ) -> Result<(), Error> { - let msg = try!(::opt_cstr(msg)); + let msg = crate::opt_cstr(msg)?; let cbs = callbacks.map(|cb| cb.raw()); unsafe { try_call!(raw::git_remote_update_tips( @@ -273,7 +273,7 @@ impl<'repo> Remote<'repo> { /// `push_update_reference` to test whether all the references were pushed /// successfully. pub fn push(&mut self, refspecs: &[&str], opts: Option<&mut PushOptions>) -> Result<(), Error> { - let (_a, _b, arr) = try!(::util::iter2cstrs(refspecs.iter())); + let (_a, _b, arr) = crate::util::iter2cstrs(refspecs.iter())?; let raw = opts.map(|o| o.raw()); unsafe { try_call!(raw::git_remote_push(self.raw, &arr, raw.as_ref())); @@ -395,12 +395,12 @@ impl<'remote> RemoteHead<'remote> { } pub fn name(&self) -> &str { - let b = unsafe { ::opt_bytes(self, (*self.raw).name).unwrap() }; + let b = unsafe { crate::opt_bytes(self, (*self.raw).name).unwrap() }; str::from_utf8(b).unwrap() } pub fn symref_target(&self) -> Option<&str> { - let b = unsafe { ::opt_bytes(self, (*self.raw).symref_target) }; + let b = unsafe { crate::opt_bytes(self, (*self.raw).symref_target) }; b.map(|b| str::from_utf8(b).unwrap()) } } @@ -478,9 +478,9 @@ impl<'cb> Binding for FetchOptions<'cb> { .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), + prune: crate::call::convert(&self.prune), + update_fetchhead: crate::call::convert(&self.update_fetchhead), + download_tags: crate::call::convert(&self.download_tags), // TODO: expose this as a builder option custom_headers: raw::git_strarray { count: 0, @@ -582,14 +582,14 @@ impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb> #[cfg(test)] mod tests { + use crate::{AutotagOption, PushOptions}; + use crate::{Direction, FetchOptions, Remote, RemoteCallbacks, Repository}; use std::cell::Cell; use tempdir::TempDir; - use {AutotagOption, PushOptions}; - use {Direction, FetchOptions, Remote, RemoteCallbacks, Repository}; #[test] fn smoke() { - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); t!(repo.remote("origin", "/path/to/nowhere")); drop(repo); @@ -612,7 +612,7 @@ mod tests { let remote = td.path().join("remote"); Repository::init_bare(&remote).unwrap(); - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let url = if cfg!(unix) { format!("file://{}", remote.display()) } else { @@ -681,7 +681,7 @@ mod tests { #[test] fn rename_remote() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); repo.remote("origin", "foo").unwrap(); drop(repo.remote_rename("origin", "foo")); drop(repo.remote_delete("foo")); @@ -705,9 +705,9 @@ mod tests { #[test] fn transfer_cb() { - let (td, _repo) = ::test::repo_init(); + let (td, _repo) = crate::test::repo_init(); let td2 = TempDir::new("git").unwrap(); - let url = ::test::path2url(https://github.com/&td.path()); + let url = crate::test::path2url(https://github.com/&td.path()); let repo = Repository::init(td2.path()).unwrap(); let progress_hit = Cell::new(false); @@ -741,9 +741,9 @@ mod tests { /// segfaults #[test] fn connect_list() { - let (td, _repo) = ::test::repo_init(); + let (td, _repo) = crate::test::repo_init(); let td2 = TempDir::new("git").unwrap(); - let url = ::test::path2url(https://github.com/&td.path()); + let url = crate::test::path2url(https://github.com/&td.path()); let repo = Repository::init(td2.path()).unwrap(); let mut callbacks = RemoteCallbacks::new(); @@ -772,10 +772,10 @@ mod tests { #[test] fn push() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let td2 = TempDir::new("git1").unwrap(); let td3 = TempDir::new("git2").unwrap(); - let url = ::test::path2url(https://github.com/&td2.path()); + let url = crate::test::path2url(https://github.com/&td2.path()); Repository::init_bare(td2.path()).unwrap(); // git push diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index fdadd77a18..b4521213a9 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -6,9 +6,9 @@ use std::ptr; use std::slice; use std::str; -use cert::Cert; -use util::Binding; -use {panic, raw, Cred, CredentialType, Error, Oid}; +use crate::cert::Cert; +use crate::util::Binding; +use crate::{panic, raw, Cred, CredentialType, Error, Oid}; /// A structure to contain the callbacks which are invoked when a repository is /// being updated or downloaded. @@ -276,17 +276,17 @@ extern "C" fn credentials_cb( unsafe { let ok = panic::wrap(|| { let payload = &mut *(payload as *mut RemoteCallbacks); - let callback = try!(payload + let callback = payload .credentials .as_mut() - .ok_or(raw::GIT_PASSTHROUGH as c_int)); + .ok_or(raw::GIT_PASSTHROUGH as c_int)?; *ret = ptr::null_mut(); - let url = try!(str::from_utf8(CStr::from_ptr(url).to_bytes()) - .map_err(|_| raw::GIT_PASSTHROUGH as c_int)); - let username_from_url = match ::opt_bytes(&url, username_from_url) { - Some(username) => Some(try!( - str::from_utf8(username).map_err(|_| raw::GIT_PASSTHROUGH as c_int) - )), + let url = str::from_utf8(CStr::from_ptr(url).to_bytes()) + .map_err(|_| raw::GIT_PASSTHROUGH as c_int)?; + let username_from_url = match crate::opt_bytes(&url, username_from_url) { + Some(username) => { + Some(str::from_utf8(username).map_err(|_| raw::GIT_PASSTHROUGH as c_int)?) + } None => None, }; diff --git a/src/repo.rs b/src/repo.rs index 2135354f22..59cdf4f8a5 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -7,24 +7,24 @@ use std::path::Path; use std::ptr; use std::str; -use build::{CheckoutBuilder, RepoBuilder}; -use oid_array::OidArray; -use stash::{stash_cb, StashApplyOptions, StashCbData}; -use string_array::StringArray; -use util::{self, Binding}; -use { +use crate::build::{CheckoutBuilder, RepoBuilder}; +use crate::oid_array::OidArray; +use crate::stash::{stash_cb, StashApplyOptions, StashCbData}; +use crate::string_array::StringArray; +use crate::util::{self, Binding}; +use crate::{ init, raw, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, Revspec, StashFlags, }; -use { +use crate::{ AnnotatedCommit, MergeAnalysis, MergeOptions, MergePreference, SubmoduleIgnore, SubmoduleStatus, }; -use {Blame, BlameOptions, Reference, References, ResetType, Signature, Submodule}; -use {Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, Oid, Tree}; -use {Describe, IntoCString, Reflog, RepositoryInitMode, RevparseMode}; -use {DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder}; -use {Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag}; -use {Rebase, RebaseOptions}; +use crate::{Blame, BlameOptions, Reference, References, ResetType, Signature, Submodule}; +use crate::{Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, Oid, Tree}; +use crate::{Describe, IntoCString, Reflog, RepositoryInitMode, RevparseMode}; +use crate::{DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder}; +use crate::{Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag}; +use crate::{Rebase, RebaseOptions}; /// An owned git repository, representing all state associated with the /// underlying filesystem. @@ -60,7 +60,7 @@ impl Repository { /// The path can point to either a normal or bare repository. pub fn open>(path: P) -> Result { init(); - let path = try!(path.as_ref().into_c_string()); + let path = path.as_ref().into_c_string()?; let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_repository_open(&mut ret, path)); @@ -73,7 +73,7 @@ impl Repository { /// The path can point to only a bare repository. pub fn open_bare>(path: P) -> Result { init(); - let path = try!(path.as_ref().into_c_string()); + let path = path.as_ref().into_c_string()?; let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_repository_open_bare(&mut ret, path)); @@ -138,9 +138,9 @@ impl Repository { I: IntoIterator, { 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 path = path.as_ref().into_c_string()?; + let ceiling_dirs_os = env::join_paths(ceiling_dirs)?; + let ceiling_dirs = ceiling_dirs_os.into_c_string()?; let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_repository_open_ext( @@ -161,7 +161,7 @@ impl Repository { // TODO: this diverges significantly from the libgit2 API init(); let buf = Buf::new(); - let path = try!(path.as_ref().into_c_string()); + let path = path.as_ref().into_c_string()?; unsafe { try_call!(raw::git_repository_discover( buf.raw(), @@ -197,7 +197,7 @@ impl Repository { opts: &RepositoryInitOptions, ) -> Result { init(); - let path = try!(path.as_ref().into_c_string()); + let path = path.as_ref().into_c_string()?; let mut ret = ptr::null_mut(); unsafe { let mut opts = opts.raw(); @@ -211,7 +211,7 @@ impl Repository { /// See the `RepoBuilder` struct for more information. This function will /// delegate to a fresh `RepoBuilder` pub fn clone>(url: &str, into: P) -> Result { - ::init(); + crate::init(); RepoBuilder::new().clone(url, into.as_ref()) } @@ -265,7 +265,7 @@ impl Repository { to: ptr::null_mut(), flags: 0, }; - let spec = try!(CString::new(spec)); + let spec = CString::new(spec)?; unsafe { try_call!(raw::git_revparse(&mut raw, self.raw, spec)); let to = Binding::from_raw_opt(raw.to); @@ -277,7 +277,7 @@ impl Repository { /// Find a single object, as specified by a revision string. pub fn revparse_single(&self, spec: &str) -> Result { - let spec = try!(CString::new(spec)); + let spec = CString::new(spec)?; let mut obj = ptr::null_mut(); unsafe { try_call!(raw::git_revparse_single(&mut obj, self.raw, spec)); @@ -296,7 +296,7 @@ impl Repository { /// may point to an intermediate reference. When such expressions are being /// passed in, this intermediate reference is returned. pub fn revparse_ext(&self, spec: &str) -> Result<(Object, Option), Error> { - let spec = try!(CString::new(spec)); + let spec = CString::new(spec)?; let mut git_obj = ptr::null_mut(); let mut git_ref = ptr::null_mut(); unsafe { @@ -337,7 +337,7 @@ impl Repository { pub fn path(&self) -> &Path { unsafe { let ptr = raw::git_repository_path(self.raw); - util::bytes2path(::opt_bytes(self, ptr).unwrap()) + util::bytes2path(crate::opt_bytes(self, ptr).unwrap()) } } @@ -389,7 +389,7 @@ impl Repository { /// and set config "core.worktree" (if workdir is not the parent of the .git /// directory). pub fn set_workdir(&self, path: &Path, update_gitlink: bool) -> Result<(), Error> { - let path = try!(path.into_c_string()); + let path = path.into_c_string()?; unsafe { try_call!(raw::git_repository_set_workdir( self.raw(), @@ -412,7 +412,7 @@ impl Repository { /// /// If there is no namespace, `None` is returned. pub fn namespace_bytes(&self) -> Option<&[u8]> { - unsafe { ::opt_bytes(self, raw::git_repository_get_namespace(self.raw)) } + unsafe { crate::opt_bytes(self, raw::git_repository_get_namespace(self.raw)) } } /// Set the active namespace for this repository. @@ -423,7 +423,7 @@ impl Repository { /// Set the active namespace for this repository as a byte array. pub fn set_namespace_bytes(&self, namespace: &[u8]) -> Result<(), Error> { unsafe { - let namespace = try!(CString::new(namespace)); + let namespace = CString::new(namespace)?; try_call!(raw::git_repository_set_namespace(self.raw, namespace)); Ok(()) } @@ -470,7 +470,7 @@ impl Repository { /// Get the information for a particular remote pub fn find_remote(&self, name: &str) -> Result { let mut ret = ptr::null_mut(); - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_remote_lookup(&mut ret, self.raw, name)); Ok(Binding::from_raw(ret)) @@ -481,8 +481,8 @@ impl Repository { /// configuration. pub fn remote(&self, name: &str, url: &str) -> Result { let mut ret = ptr::null_mut(); - let name = try!(CString::new(name)); - let url = try!(CString::new(url)); + let name = CString::new(name)?; + let url = CString::new(url)?; unsafe { try_call!(raw::git_remote_create(&mut ret, self.raw, name, url)); Ok(Binding::from_raw(ret)) @@ -496,7 +496,7 @@ impl Repository { /// remotes cannot be converted to persisted remotes. pub fn remote_anonymous(&self, url: &str) -> Result { let mut ret = ptr::null_mut(); - let url = try!(CString::new(url)); + let url = CString::new(url)?; unsafe { try_call!(raw::git_remote_create_anonymous(&mut ret, self.raw, url)); Ok(Binding::from_raw(ret)) @@ -517,8 +517,8 @@ impl Repository { /// which cannot be renamed and are returned for further processing by the /// caller. pub fn remote_rename(&self, name: &str, new_name: &str) -> Result { - let name = try!(CString::new(name)); - let new_name = try!(CString::new(new_name)); + let name = CString::new(name)?; + let new_name = CString::new(new_name)?; let mut problems = raw::git_strarray { count: 0, strings: 0 as *mut *mut c_char, @@ -539,7 +539,7 @@ impl Repository { /// All remote-tracking branches and configuration settings for the remote /// will be removed. pub fn remote_delete(&self, name: &str) -> Result<(), Error> { - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_remote_delete(self.raw, name)); } @@ -551,8 +551,8 @@ impl Repository { /// Add the given refspec to the fetch list in the configuration. No loaded /// remote instances will be affected. pub fn remote_add_fetch(&self, name: &str, spec: &str) -> Result<(), Error> { - let name = try!(CString::new(name)); - let spec = try!(CString::new(spec)); + let name = CString::new(name)?; + let spec = CString::new(spec)?; unsafe { try_call!(raw::git_remote_add_fetch(self.raw, name, spec)); } @@ -564,8 +564,8 @@ impl Repository { /// Add the given refspec to the push list in the configuration. No /// loaded remote instances will be affected. pub fn remote_add_push(&self, name: &str, spec: &str) -> Result<(), Error> { - let name = try!(CString::new(name)); - let spec = try!(CString::new(spec)); + let name = CString::new(name)?; + let spec = CString::new(spec)?; unsafe { try_call!(raw::git_remote_add_push(self.raw, name, spec)); } @@ -578,8 +578,8 @@ impl Repository { /// the common case of a single-url remote and will otherwise return an /// error. pub fn remote_set_url(https://github.com/&self,%20name:%20&str,%20url:%20&str) -> Result<(), Error> { - let name = try!(CString::new(name)); - let url = try!(CString::new(url)); + let name = CString::new(name)?; + let url = CString::new(url)?; unsafe { try_call!(raw::git_remote_set_url(https://github.com/self.raw,%20name,%20url)); } @@ -594,8 +594,8 @@ impl Repository { /// /// `None` indicates that it should be cleared. pub fn remote_set_pushurl(https://github.com/&self,%20name:%20&str,%20pushurl:%20Option%3C&str%3E) -> Result<(), Error> { - let name = try!(CString::new(name)); - let pushurl = try!(::opt_cstr(pushurl)); + let name = CString::new(name)?; + let pushurl = crate::opt_cstr(pushurl)?; unsafe { try_call!(raw::git_remote_set_pushurl(https://github.com/self.raw,%20name,%20pushurl)); } @@ -652,7 +652,7 @@ impl Repository { T: IntoCString, I: IntoIterator, { - let (_a, _b, mut arr) = try!(::util::iter2cstrs(paths)); + let (_a, _b, mut arr) = crate::util::iter2cstrs(paths)?; let target = target.map(|t| t.raw()); unsafe { try_call!(raw::git_reset_default(self.raw, target, &mut arr)); @@ -682,7 +682,7 @@ impl Repository { /// Otherwise, the HEAD will be detached and will directly point to the /// commit. pub fn set_head(&self, refname: &str) -> Result<(), Error> { - let refname = try!(CString::new(refname)); + let refname = CString::new(refname)?; unsafe { try_call!(raw::git_repository_set_head(self.raw, refname)); } @@ -734,7 +734,7 @@ impl Repository { /// glob pub fn references_glob(&self, glob: &str) -> Result { let mut ret = ptr::null_mut(); - let glob = try!(CString::new(glob)); + let glob = CString::new(glob)?; unsafe { try_call!(raw::git_reference_iterator_glob_new( &mut ret, self.raw, glob @@ -810,7 +810,7 @@ impl Repository { /// directory containing the file, would it be added or not? pub fn status_should_ignore(&self, path: &Path) -> Result { let mut ret = 0 as c_int; - let path = try!(path.into_c_string()); + let path = path.into_c_string()?; unsafe { try_call!(raw::git_status_should_ignore(&mut ret, self.raw, path)); } @@ -838,11 +838,9 @@ impl Repository { let path = if cfg!(windows) { // `git_status_file` dose not work with windows path separator // so we convert \ to / - try!(::std::ffi::CString::new( - path.to_string_lossy().replace('\\', "/") - )) + std::ffi::CString::new(path.to_string_lossy().replace('\\', "/"))? } else { - try!(path.into_c_string()) + path.into_c_string()? }; unsafe { try_call!(raw::git_status_file(&mut ret, self.raw, path)); @@ -918,7 +916,7 @@ impl Repository { /// The Oid returned can in turn be passed to `find_blob` to get a handle to /// the blob. pub fn blob_path(&self, path: &Path) -> Result { - let path = try!(path.into_c_string()); + let path = path.into_c_string()?; let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; @@ -941,7 +939,7 @@ impl Repository { /// to the object database. pub fn blob_writer(&self, hintpath: Option<&Path>) -> Result { let path_str = match hintpath { - Some(path) => Some(try!(path.into_c_string())), + Some(path) => Some(path.into_c_string()?), None => None, }; let path = match path_str { @@ -979,7 +977,7 @@ impl Repository { /// If `force` is true and a reference already exists with the given name, /// it'll be replaced. pub fn branch(&self, branch_name: &str, target: &Commit, force: bool) -> Result { - let branch_name = try!(CString::new(branch_name)); + let branch_name = CString::new(branch_name)?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_branch_create( @@ -995,7 +993,7 @@ impl Repository { /// Lookup a branch by its name in a repository. pub fn find_branch(&self, name: &str, branch_type: BranchType) -> Result { - let name = try!(CString::new(name)); + let name = CString::new(name)?; let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_branch_lookup( @@ -1025,12 +1023,12 @@ impl Repository { tree: &Tree, parents: &[&Commit], ) -> Result { - let update_ref = try!(::opt_cstr(update_ref)); + let update_ref = crate::opt_cstr(update_ref)?; let mut parent_ptrs = parents .iter() .map(|p| p.raw() as *const raw::git_commit) .collect::>(); - let message = try!(CString::new(message)); + let message = CString::new(message)?; let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; @@ -1067,9 +1065,9 @@ impl Repository { signature: &str, signature_field: Option<&str>, ) -> Result { - let commit_content = try!(CString::new(commit_content)); - let signature = try!(CString::new(signature)); - let signature_field = try!(::opt_cstr(signature_field)); + let commit_content = CString::new(commit_content)?; + let signature = CString::new(signature)?; + let signature_field = crate::opt_cstr(signature_field)?; let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; @@ -1094,7 +1092,7 @@ impl Repository { commit_id: &Oid, signature_field: Option<&str>, ) -> Result<(Buf, Buf), Error> { - let signature_field = try!(::opt_cstr(signature_field)); + let signature_field = crate::opt_cstr(signature_field)?; let signature = Buf::new(); let content = Buf::new(); unsafe { @@ -1157,8 +1155,8 @@ impl Repository { force: bool, log_message: &str, ) -> Result { - let name = try!(CString::new(name)); - let log_message = try!(CString::new(log_message)); + let name = CString::new(name)?; + let log_message = CString::new(log_message)?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_create( @@ -1211,8 +1209,8 @@ impl Repository { current_id: Oid, log_message: &str, ) -> Result { - let name = try!(CString::new(name)); - let log_message = try!(CString::new(log_message)); + let name = CString::new(name)?; + let log_message = CString::new(log_message)?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_create_matching( @@ -1240,9 +1238,9 @@ impl Repository { force: bool, log_message: &str, ) -> Result { - let name = try!(CString::new(name)); - let target = try!(CString::new(target)); - let log_message = try!(CString::new(log_message)); + let name = CString::new(name)?; + let target = CString::new(target)?; + let log_message = CString::new(log_message)?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_symbolic_create( @@ -1274,10 +1272,10 @@ impl Repository { current_value: &str, log_message: &str, ) -> Result { - let name = try!(CString::new(name)); - let target = try!(CString::new(target)); - let current_value = try!(CString::new(current_value)); - let log_message = try!(CString::new(log_message)); + let name = CString::new(name)?; + let target = CString::new(target)?; + let current_value = CString::new(current_value)?; + let log_message = CString::new(log_message)?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_symbolic_create_matching( @@ -1295,7 +1293,7 @@ impl Repository { /// Lookup a reference to one of the objects in a repository. pub fn find_reference(&self, name: &str) -> Result { - let name = try!(CString::new(name)); + let name = CString::new(name)?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_lookup(&mut raw, self.raw(), name)); @@ -1308,7 +1306,7 @@ impl Repository { /// human-readable format e.g. 'master' instead of 'refs/heads/master', and it /// will do-what-you-mean, returning the `Reference`. pub fn resolve_reference_from_short_name(&self, refname: &str) -> Result { - let refname = try!(CString::new(refname)); + let refname = CString::new(refname)?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_reference_dwim(&mut raw, self.raw(), refname)); @@ -1322,7 +1320,7 @@ impl Repository { /// through to the object id that it refers to. This avoids having to /// allocate or free any `Reference` objects for simple situations. pub fn refname_to_id(&self, name: &str) -> Result { - let name = try!(CString::new(name)); + let name = CString::new(name)?; let mut ret = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; @@ -1375,8 +1373,8 @@ impl Repository { /// `add_finalize()` to wrap up adding the new submodule and `.gitmodules` /// to the index to be ready to commit. pub fn submodule(&self, url: &str, path: &Path, use_gitlink: bool) -> Result { - let url = try!(CString::new(url)); - let path = try!(path.into_c_string()); + let url = CString::new(url)?; + let path = path.into_c_string()?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_submodule_add_setup( @@ -1395,7 +1393,7 @@ impl Repository { /// Given either the submodule name or path (they are usually the same), /// this returns a structure describing the submodule. pub fn find_submodule(&self, name: &str) -> Result { - let name = try!(CString::new(name)); + let name = CString::new(name)?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_submodule_lookup(&mut raw, self.raw(), name)); @@ -1413,7 +1411,7 @@ impl Repository { ignore: SubmoduleIgnore, ) -> Result { let mut ret = 0; - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_submodule_status(&mut ret, self.raw, name, ignore)); } @@ -1465,8 +1463,8 @@ impl Repository { message: &str, force: bool, ) -> Result { - let name = try!(CString::new(name)); - let message = try!(CString::new(message)); + let name = CString::new(name)?; + let message = CString::new(message)?; let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; @@ -1490,7 +1488,7 @@ impl Repository { /// If force is true and a reference already exists with the given name, /// it'll be replaced. pub fn tag_lightweight(&self, name: &str, target: &Object, force: bool) -> Result { - let name = try!(CString::new(name)); + let name = CString::new(name)?; let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; @@ -1520,7 +1518,7 @@ impl Repository { /// The tag name will be checked for validity, see `tag` for some rules /// about valid names. pub fn tag_delete(&self, name: &str) -> Result<(), Error> { - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_tag_delete(self.raw, name)); Ok(()) @@ -1538,7 +1536,7 @@ impl Repository { unsafe { match pattern { Some(s) => { - let s = try!(CString::new(s)); + let s = CString::new(s)?; try_call!(raw::git_tag_list_match(&mut arr, s, self.raw)); } None => { @@ -1793,8 +1791,8 @@ impl Repository { note: &str, force: bool, ) -> Result { - let notes_ref = try!(::opt_cstr(notes_ref)); - let note = try!(CString::new(note)); + let notes_ref = crate::opt_cstr(notes_ref)?; + let note = CString::new(note)?; let mut ret = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; @@ -1831,7 +1829,7 @@ impl Repository { /// is the id of the note and the second id is the id the note is /// annotating. pub fn notes(&self, notes_ref: Option<&str>) -> Result { - let notes_ref = try!(::opt_cstr(notes_ref)); + let notes_ref = crate::opt_cstr(notes_ref)?; let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_note_iterator_new(&mut ret, self.raw, notes_ref)); @@ -1846,7 +1844,7 @@ impl Repository { /// /// The id specified is the Oid of the git object to read the note from. pub fn find_note(&self, notes_ref: Option<&str>, id: Oid) -> Result { - let notes_ref = try!(::opt_cstr(notes_ref)); + let notes_ref = crate::opt_cstr(notes_ref)?; let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_note_read(&mut ret, self.raw, notes_ref, id.raw())); @@ -1867,7 +1865,7 @@ impl Repository { author: &Signature, committer: &Signature, ) -> Result<(), Error> { - let notes_ref = try!(::opt_cstr(notes_ref)); + let notes_ref = crate::opt_cstr(notes_ref)?; unsafe { try_call!(raw::git_note_remove( self.raw, @@ -1891,7 +1889,7 @@ impl Repository { /// Get the blame for a single file. pub fn blame_file(&self, path: &Path, opts: Option<&mut BlameOptions>) -> Result { - let path = try!(path.into_c_string()); + let path = path.into_c_string()?; let mut raw = ptr::null_mut(); unsafe { @@ -1976,7 +1974,7 @@ impl Repository { /// If there is no reflog file for the given reference yet, an empty reflog /// object will be returned. pub fn reflog(&self, name: &str) -> Result { - let name = try!(CString::new(name)); + let name = CString::new(name)?; let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_reflog_read(&mut ret, self.raw, name)); @@ -1986,7 +1984,7 @@ impl Repository { /// Delete the reflog for the given reference pub fn reflog_delete(&self, name: &str) -> Result<(), Error> { - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_reflog_delete(self.raw, name)); } @@ -1997,8 +1995,8 @@ impl Repository { /// /// The reflog to be renamed is expected to already exist. pub fn reflog_rename(&self, old_name: &str, new_name: &str) -> Result<(), Error> { - let old_name = try!(CString::new(old_name)); - let new_name = try!(CString::new(new_name)); + let old_name = CString::new(old_name)?; + let new_name = CString::new(new_name)?; unsafe { try_call!(raw::git_reflog_rename(self.raw, old_name, new_name)); } @@ -2007,14 +2005,14 @@ impl Repository { /// Check if the given reference has a reflog. pub fn reference_has_log(&self, name: &str) -> Result { - let name = try!(CString::new(name)); + let name = CString::new(name)?; let ret = unsafe { try_call!(raw::git_reference_has_log(self.raw, name)) }; Ok(ret != 0) } /// Ensure that the given reference has a reflog. pub fn reference_ensure_log(&self, name: &str) -> Result<(), Error> { - let name = try!(CString::new(name)); + let name = CString::new(name)?; unsafe { try_call!(raw::git_reference_ensure_log(self.raw, name)); } @@ -2224,7 +2222,7 @@ impl Repository { let mut raw_oid = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; - let message = try!(CString::new(message)); + let message = CString::new(message)?; let flags = flags.unwrap_or_else(StashFlags::empty); try_call!(raw::git_stash_save( &mut raw_oid, @@ -2315,11 +2313,9 @@ impl Repository { let path = if cfg!(windows) { // `git_ignore_path_is_ignored` dose not work with windows path separator // so we convert \ to / - try!(::std::ffi::CString::new( - path.as_ref().to_string_lossy().replace('\\', "/") - )) + std::ffi::CString::new(path.as_ref().to_string_lossy().replace('\\', "/"))? } else { - try!(path.as_ref().into_c_string()) + path.as_ref().into_c_string()? }; let mut ignored: c_int = 0; unsafe { @@ -2498,23 +2494,23 @@ impl RepositoryInitOptions { ); opts.flags = self.flags; opts.mode = self.mode; - opts.workdir_path = ::call::convert(&self.workdir_path); - opts.description = ::call::convert(&self.description); - opts.template_path = ::call::convert(&self.template_path); - opts.initial_head = ::call::convert(&self.initial_head); - opts.origin_url = ::call::convert(&self.origin_url); + opts.workdir_path = crate::call::convert(&self.workdir_path); + opts.description = crate::call::convert(&self.description); + opts.template_path = crate::call::convert(&self.template_path); + opts.initial_head = crate::call::convert(&self.initial_head); + opts.origin_url = crate::call::convert(&self.origin_url); opts } } #[cfg(test)] mod tests { - use build::CheckoutBuilder; + use crate::build::CheckoutBuilder; + use crate::{ObjectType, Oid, Repository, ResetType}; use std::ffi::OsStr; use std::fs; use std::path::Path; use tempdir::TempDir; - use {ObjectType, Oid, Repository, ResetType}; #[test] fn smoke_init() { @@ -2545,10 +2541,10 @@ mod tests { assert!(!repo.is_shallow()); assert!(repo.is_empty().unwrap()); assert_eq!( - ::test::realpath(&repo.path()).unwrap(), - ::test::realpath(&td.path().join(".git/")).unwrap() + crate::test::realpath(&repo.path()).unwrap(), + crate::test::realpath(&td.path().join(".git/")).unwrap() ); - assert_eq!(repo.state(), ::RepositoryState::Clean); + assert_eq!(repo.state(), crate::RepositoryState::Clean); } #[test] @@ -2560,20 +2556,20 @@ mod tests { let repo = Repository::open(path).unwrap(); assert!(repo.is_bare()); assert_eq!( - ::test::realpath(&repo.path()).unwrap(), - ::test::realpath(&td.path().join("")).unwrap() + crate::test::realpath(&repo.path()).unwrap(), + crate::test::realpath(&td.path().join("")).unwrap() ); } #[test] fn smoke_checkout() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); repo.checkout_head(None).unwrap(); } #[test] fn smoke_revparse() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let rev = repo.revparse("HEAD").unwrap(); assert!(rev.to().is_none()); let from = rev.from().unwrap(); @@ -2602,8 +2598,8 @@ mod tests { Repository::init_bare(td.path()).unwrap(); let repo = Repository::discover(&subdir).unwrap(); assert_eq!( - ::test::realpath(&repo.path()).unwrap(), - ::test::realpath(&td.path().join("")).unwrap() + crate::test::realpath(&repo.path()).unwrap(), + crate::test::realpath(&td.path().join("")).unwrap() ); } @@ -2614,32 +2610,43 @@ mod tests { fs::create_dir(&subdir).unwrap(); Repository::init(td.path()).unwrap(); - let repo = Repository::open_ext(&subdir, ::RepositoryOpenFlags::empty(), &[] as &[&OsStr]) - .unwrap(); + let repo = Repository::open_ext( + &subdir, + crate::RepositoryOpenFlags::empty(), + &[] as &[&OsStr], + ) + .unwrap(); assert!(!repo.is_bare()); assert_eq!( - ::test::realpath(&repo.path()).unwrap(), - ::test::realpath(&td.path().join(".git")).unwrap() + crate::test::realpath(&repo.path()).unwrap(), + crate::test::realpath(&td.path().join(".git")).unwrap() ); let repo = - Repository::open_ext(&subdir, ::RepositoryOpenFlags::BARE, &[] as &[&OsStr]).unwrap(); + Repository::open_ext(&subdir, crate::RepositoryOpenFlags::BARE, &[] as &[&OsStr]) + .unwrap(); assert!(repo.is_bare()); assert_eq!( - ::test::realpath(&repo.path()).unwrap(), - ::test::realpath(&td.path().join(".git")).unwrap() + crate::test::realpath(&repo.path()).unwrap(), + crate::test::realpath(&td.path().join(".git")).unwrap() ); - let err = Repository::open_ext(&subdir, ::RepositoryOpenFlags::NO_SEARCH, &[] as &[&OsStr]) - .err() - .unwrap(); - assert_eq!(err.code(), ::ErrorCode::NotFound); + let err = Repository::open_ext( + &subdir, + crate::RepositoryOpenFlags::NO_SEARCH, + &[] as &[&OsStr], + ) + .err() + .unwrap(); + assert_eq!(err.code(), crate::ErrorCode::NotFound); - assert!(Repository::open_ext(&subdir, ::RepositoryOpenFlags::empty(), &[&subdir]).is_ok()); + assert!( + Repository::open_ext(&subdir, crate::RepositoryOpenFlags::empty(), &[&subdir]).is_ok() + ); } fn graph_repo_init() -> (TempDir, Repository) { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); { let head = repo.head().unwrap().target().unwrap(); let head = repo.find_commit(head).unwrap(); @@ -2683,7 +2690,7 @@ mod tests { #[test] fn smoke_reference_has_log_ensure_log() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); assert_eq!(repo.reference_has_log("HEAD").unwrap(), true); assert_eq!(repo.reference_has_log("refs/heads/master").unwrap(), true); @@ -2699,7 +2706,7 @@ mod tests { #[test] fn smoke_set_head() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); assert!(repo.set_head("refs/heads/does-not-exist").is_ok()); assert!(repo.head().is_err()); @@ -2712,7 +2719,7 @@ mod tests { #[test] fn smoke_set_head_detached() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let void_oid = Oid::from_bytes(b"00000000000000000000").unwrap(); assert!(repo.set_head_detached(void_oid).is_err()); diff --git a/src/revspec.rs b/src/revspec.rs index de6cf01076..120f83a359 100644 --- a/src/revspec.rs +++ b/src/revspec.rs @@ -1,4 +1,4 @@ -use {Object, RevparseMode}; +use crate::{Object, RevparseMode}; /// A revspec represents a range of revisions within a repository. pub struct Revspec<'repo> { diff --git a/src/revwalk.rs b/src/revwalk.rs index fe33fddab8..4afd36ed9f 100644 --- a/src/revwalk.rs +++ b/src/revwalk.rs @@ -2,8 +2,8 @@ use libc::c_uint; use std::ffi::CString; use std::marker; -use util::Binding; -use {raw, Error, Oid, Repository, Sort}; +use crate::util::Binding; +use crate::{raw, Error, Oid, Repository, Sort}; /// A revwalk allows traversal of the commit graph defined by including one or /// more leaves and excluding one or more roots. @@ -68,7 +68,7 @@ impl<'repo> Revwalk<'repo> { /// Any references matching this glob which do not point to a committish /// will be ignored. pub fn push_glob(&mut self, glob: &str) -> Result<(), Error> { - let glob = try!(CString::new(glob)); + let glob = CString::new(glob)?; unsafe { try_call!(raw::git_revwalk_push_glob(self.raw, glob)); } @@ -81,7 +81,7 @@ impl<'repo> Revwalk<'repo> { /// `` is in the form accepted by `revparse_single`. The left-hand /// commit will be hidden and the right-hand commit pushed. pub fn push_range(&mut self, range: &str) -> Result<(), Error> { - let range = try!(CString::new(range)); + let range = CString::new(range)?; unsafe { try_call!(raw::git_revwalk_push_range(self.raw, range)); } @@ -92,7 +92,7 @@ impl<'repo> Revwalk<'repo> { /// /// The reference must point to a committish. pub fn push_ref(&mut self, reference: &str) -> Result<(), Error> { - let reference = try!(CString::new(reference)); + let reference = CString::new(reference)?; unsafe { try_call!(raw::git_revwalk_push_ref(self.raw, reference)); } @@ -128,7 +128,7 @@ impl<'repo> Revwalk<'repo> { /// Any references matching this glob which do not point to a committish /// will be ignored. pub fn hide_glob(&mut self, glob: &str) -> Result<(), Error> { - let glob = try!(CString::new(glob)); + let glob = CString::new(glob)?; unsafe { try_call!(raw::git_revwalk_hide_glob(self.raw, glob)); } @@ -139,7 +139,7 @@ impl<'repo> Revwalk<'repo> { /// /// The reference must point to a committish. pub fn hide_ref(&mut self, reference: &str) -> Result<(), Error> { - let reference = try!(CString::new(reference)); + let reference = CString::new(reference)?; unsafe { try_call!(raw::git_revwalk_hide_ref(self.raw, reference)); } @@ -183,14 +183,14 @@ impl<'repo> Iterator for Revwalk<'repo> { mod tests { #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let head = repo.head().unwrap(); let target = head.target().unwrap(); let mut walk = repo.revwalk().unwrap(); walk.push(target).unwrap(); - let oids: Vec<::Oid> = walk.by_ref().collect::, _>>().unwrap(); + let oids: Vec = walk.by_ref().collect::, _>>().unwrap(); assert_eq!(oids.len(), 1); assert_eq!(oids[0], target); diff --git a/src/signature.rs b/src/signature.rs index a915b2dcb4..e0beaa60af 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -6,8 +6,8 @@ use std::mem; use std::ptr; use std::str; -use util::Binding; -use {raw, Error, Time}; +use crate::util::Binding; +use crate::{raw, Error, Time}; /// A Signature is used to indicate authorship of various actions throughout the /// library. @@ -29,10 +29,10 @@ impl<'a> Signature<'a> { /// /// See `new` for more information pub fn now(name: &str, email: &str) -> Result, Error> { - ::init(); + crate::init(); let mut ret = ptr::null_mut(); - let name = try!(CString::new(name)); - let email = try!(CString::new(email)); + let name = CString::new(name)?; + let email = CString::new(email)?; unsafe { try_call!(raw::git_signature_now(&mut ret, name, email)); Ok(Binding::from_raw(ret)) @@ -46,10 +46,10 @@ impl<'a> Signature<'a> { /// /// Returns error if either `name` or `email` contain angle brackets. pub fn new(name: &str, email: &str, time: &Time) -> Result, Error> { - ::init(); + crate::init(); let mut ret = ptr::null_mut(); - let name = try!(CString::new(name)); - let email = try!(CString::new(email)); + let name = CString::new(name)?; + let email = CString::new(email)?; unsafe { try_call!(raw::git_signature_new( &mut ret, @@ -71,7 +71,7 @@ impl<'a> Signature<'a> { /// Gets the name on the signature as a byte slice. pub fn name_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, (*self.raw).name).unwrap() } + unsafe { crate::opt_bytes(self, (*self.raw).name).unwrap() } } /// Gets the email on the signature. @@ -83,7 +83,7 @@ impl<'a> Signature<'a> { /// Gets the email on the signature as a byte slice. pub fn email_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, (*self.raw).email).unwrap() } + unsafe { crate::opt_bytes(self, (*self.raw).email).unwrap() } } /// Get the `when` of this signature. @@ -160,7 +160,7 @@ impl<'a> fmt::Display for Signature<'a> { #[cfg(test)] mod tests { - use {Signature, Time}; + use crate::{Signature, Time}; #[test] fn smoke() { diff --git a/src/stash.rs b/src/stash.rs index 6881f2d246..280d164132 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -1,9 +1,9 @@ -use build::CheckoutBuilder; +use crate::build::CheckoutBuilder; +use crate::util::Binding; +use crate::{panic, raw, Oid, StashApplyProgress}; use libc::{c_char, c_int, c_void, size_t}; use std::ffi::CStr; use std::mem; -use util::Binding; -use {panic, raw, Oid, StashApplyProgress}; /// Stash application progress notification function. /// @@ -151,12 +151,12 @@ extern "C" fn stash_apply_progress_cb( #[cfg(test)] mod tests { - use stash::StashApplyOptions; + use crate::stash::StashApplyOptions; + use crate::test::repo_init; + use crate::{Repository, StashFlags, Status}; use std::fs; use std::io::Write; use std::path::Path; - use test::repo_init; - use {Repository, StashFlags, Status}; fn make_stash(next: C) where diff --git a/src/status.rs b/src/status.rs index baef097eb5..4ea28be575 100644 --- a/src/status.rs +++ b/src/status.rs @@ -5,8 +5,8 @@ use std::mem; use std::ops::Range; use std::str; -use util::Binding; -use {raw, DiffDelta, IntoCString, Repository, Status}; +use crate::util::Binding; +use crate::{raw, DiffDelta, IntoCString, Repository, Status}; /// Options that can be provided to `repo.statuses()` to control how the status /// information is gathered. @@ -302,9 +302,9 @@ impl<'statuses> StatusEntry<'statuses> { pub fn path_bytes(&self) -> &[u8] { unsafe { if (*self.raw).head_to_index.is_null() { - ::opt_bytes(self, (*(*self.raw).index_to_workdir).old_file.path) + crate::opt_bytes(self, (*(*self.raw).index_to_workdir).old_file.path) } else { - ::opt_bytes(self, (*(*self.raw).head_to_index).old_file.path) + crate::opt_bytes(self, (*(*self.raw).head_to_index).old_file.path) } .unwrap() } @@ -358,15 +358,15 @@ mod tests { #[test] fn smoke() { - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); assert_eq!(repo.statuses(None).unwrap().len(), 0); File::create(&td.path().join("foo")).unwrap(); let statuses = repo.statuses(None).unwrap(); assert_eq!(statuses.iter().count(), 1); let status = statuses.iter().next().unwrap(); assert_eq!(status.path(), Some("foo")); - assert!(status.status().contains(::Status::WT_NEW)); - assert!(!status.status().contains(::Status::INDEX_NEW)); + assert!(status.status().contains(crate::Status::WT_NEW)); + assert!(!status.status().contains(crate::Status::INDEX_NEW)); assert!(status.head_to_index().is_none()); let diff = status.index_to_workdir().unwrap(); assert_eq!(diff.old_file().path_bytes().unwrap(), b"foo"); @@ -375,7 +375,7 @@ mod tests { #[test] fn filter() { - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); t!(File::create(&td.path().join("foo"))); t!(File::create(&td.path().join("bar"))); let mut opts = StatusOptions::new(); @@ -389,7 +389,7 @@ mod tests { #[test] fn gitignore() { - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); t!(t!(File::create(td.path().join(".gitignore"))).write_all(b"foo\n")); assert!(!t!(repo.status_should_ignore(Path::new("bar")))); assert!(t!(repo.status_should_ignore(Path::new("foo")))); @@ -397,7 +397,7 @@ mod tests { #[test] fn status_file() { - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); assert!(repo.status_file(Path::new("foo")).is_err()); if cfg!(windows) { assert!(repo.status_file(Path::new("bar\\foo.txt")).is_err()); @@ -408,10 +408,10 @@ mod tests { t!(File::create(td.path().join("bar").join("foo.txt"))); } let status = t!(repo.status_file(Path::new("foo"))); - assert!(status.contains(::Status::WT_NEW)); + assert!(status.contains(crate::Status::WT_NEW)); if cfg!(windows) { let status = t!(repo.status_file(Path::new("bar\\foo.txt"))); - assert!(status.contains(::Status::WT_NEW)); + assert!(status.contains(crate::Status::WT_NEW)); } } } diff --git a/src/string_array.rs b/src/string_array.rs index 8c23b0cb32..1bb40c24ea 100644 --- a/src/string_array.rs +++ b/src/string_array.rs @@ -3,8 +3,8 @@ use std::ops::Range; use std::str; -use raw; -use util::Binding; +use crate::raw; +use crate::util::Binding; /// A string array structure used by libgit2 /// @@ -38,7 +38,7 @@ impl StringArray { if i < self.raw.count as usize { unsafe { let ptr = *self.raw.strings.offset(i as isize) as *const _; - Some(::opt_bytes(self, ptr).unwrap()) + Some(crate::opt_bytes(self, ptr).unwrap()) } } else { None diff --git a/src/submodule.rs b/src/submodule.rs index 26e6224ea2..4112210405 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -5,9 +5,9 @@ use std::path::Path; use std::ptr; use std::str; -use build::CheckoutBuilder; -use util::{self, Binding}; -use {raw, Error, FetchOptions, Oid, Repository}; +use crate::build::CheckoutBuilder; +use crate::util::{self, Binding}; +use crate::{raw, Error, FetchOptions, Oid, Repository}; /// A structure to represent a git [submodule][1] /// @@ -30,7 +30,7 @@ impl<'repo> Submodule<'repo> { /// /// Returns `None` if the branch is not yet available. pub fn branch_bytes(&self) -> Option<&[u8]> { - unsafe { ::opt_bytes(self, raw::git_submodule_branch(self.raw)) } + unsafe { crate::opt_bytes(self, raw::git_submodule_branch(self.raw)) } } /// Get the submodule's url. @@ -53,7 +53,7 @@ impl<'repo> Submodule<'repo> { // TODO: delete this method and fix the signature of `url_bytes` on next // major version bump pub fn opt_url_bytes(&self) -> Option<&[u8]> { - unsafe { ::opt_bytes(self, raw::git_submodule_url(https://github.com/self.raw)) } + unsafe { crate::opt_bytes(self, raw::git_submodule_url(https://github.com/self.raw)) } } /// Get the submodule's name. @@ -65,12 +65,14 @@ impl<'repo> Submodule<'repo> { /// Get the name for the submodule. pub fn name_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_submodule_name(self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_submodule_name(self.raw)).unwrap() } } /// Get the path for the submodule. pub fn path(&self) -> &Path { - util::bytes2path(unsafe { ::opt_bytes(self, raw::git_submodule_path(self.raw)).unwrap() }) + util::bytes2path(unsafe { + crate::opt_bytes(self, raw::git_submodule_path(self.raw)).unwrap() + }) } /// Get the OID for the submodule in the current HEAD tree. @@ -282,8 +284,8 @@ mod tests { use tempdir::TempDir; use url::Url; - use Repository; - use SubmoduleUpdateOptions; + use crate::Repository; + use crate::SubmoduleUpdateOptions; #[test] fn smoke() { @@ -318,8 +320,8 @@ mod tests { #[test] fn add_a_submodule() { - let (_td, repo1) = ::test::repo_init(); - let (td, repo2) = ::test::repo_init(); + let (_td, repo1) = crate::test::repo_init(); + let (td, repo2) = crate::test::repo_init(); let url = Url::from_file_path(&repo1.workdir().unwrap()).unwrap(); let mut s = repo2 @@ -335,8 +337,8 @@ mod tests { fn update_submodule() { // ----------------------------------- // Same as `add_a_submodule()` - let (_td, repo1) = ::test::repo_init(); - let (td, repo2) = ::test::repo_init(); + let (_td, repo1) = crate::test::repo_init(); + let (td, repo2) = crate::test::repo_init(); let url = Url::from_file_path(&repo1.workdir().unwrap()).unwrap(); let mut s = repo2 diff --git a/src/tag.rs b/src/tag.rs index 2442a8b30a..5a02b43b26 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -3,8 +3,8 @@ use std::mem; use std::ptr; use std::str; -use util::Binding; -use {raw, signature, Error, Object, ObjectType, Oid, Signature}; +use crate::util::Binding; +use crate::{raw, signature, Error, Object, ObjectType, Oid, Signature}; /// A structure to represent a git [tag][1] /// @@ -31,7 +31,7 @@ impl<'repo> Tag<'repo> { /// /// Returns None if there is no message pub fn message_bytes(&self) -> Option<&[u8]> { - unsafe { ::opt_bytes(self, raw::git_tag_message(&*self.raw)) } + unsafe { crate::opt_bytes(self, raw::git_tag_message(&*self.raw)) } } /// Get the name of a tag @@ -43,7 +43,7 @@ impl<'repo> Tag<'repo> { /// Get the name of a tag pub fn name_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_tag_name(&*self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_tag_name(&*self.raw)).unwrap() } } /// Recursively peel a tag until a non tag git_object is found @@ -103,8 +103,8 @@ impl<'repo> Tag<'repo> { } } -impl<'repo> ::std::fmt::Debug for Tag<'repo> { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { +impl<'repo> std::fmt::Debug for Tag<'repo> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { let mut ds = f.debug_struct("Tag"); if let Some(name) = self.name() { ds.field("name", &name); @@ -143,7 +143,7 @@ impl<'repo> Drop for Tag<'repo> { mod tests { #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let head = repo.head().unwrap(); let id = head.target().unwrap(); assert!(repo.find_tag(id).is_err()); @@ -162,7 +162,7 @@ mod tests { assert_eq!(tag.message(), Some("msg")); assert_eq!(tag.peel().unwrap().id(), obj.id()); assert_eq!(tag.target_id(), obj.id()); - assert_eq!(tag.target_type(), Some(::ObjectType::Commit)); + assert_eq!(tag.target_type(), Some(crate::ObjectType::Commit)); assert_eq!(tag.tagger().unwrap().name(), sig.name()); tag.target().unwrap(); @@ -180,7 +180,7 @@ mod tests { #[test] fn lite() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let head = t!(repo.head()); let id = head.target().unwrap(); let obj = t!(repo.find_object(id, None)); diff --git a/src/test.rs b/src/test.rs index 5fed0a7882..6f885bd6f3 100644 --- a/src/test.rs +++ b/src/test.rs @@ -5,7 +5,7 @@ use std::ptr; use tempdir::TempDir; use url::Url; -use Repository; +use crate::Repository; macro_rules! t { ($e:expr) => { @@ -51,7 +51,7 @@ pub fn realpath(original: &Path) -> io::Result { fn realpath(name: *const c_char, resolved: *mut c_char) -> *mut c_char; } unsafe { - let cstr = try!(CString::new(original.as_os_str().as_bytes())); + let cstr = CString::new(original.as_os_str().as_bytes())?; let ptr = realpath(cstr.as_ptr(), ptr::null_mut()); if ptr.is_null() { return Err(io::Error::last_os_error()); diff --git a/src/time.rs b/src/time.rs index 69508e37e0..92dc0b36ff 100644 --- a/src/time.rs +++ b/src/time.rs @@ -2,8 +2,8 @@ use std::cmp::Ordering; use libc::{c_char, c_int}; -use raw; -use util::Binding; +use crate::raw; +use crate::util::Binding; /// Time in a signature #[derive(Copy, Clone, Eq, PartialEq)] diff --git a/src/transport.rs b/src/transport.rs index 53e2e13208..b19d764e9d 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -9,8 +9,8 @@ use std::ptr; use std::slice; use std::str; -use util::Binding; -use {panic, raw, Error, Remote}; +use crate::util::Binding; +use crate::{panic, raw, Error, Remote}; /// A transport is a structure which knows how to transfer data to and from a /// remote. @@ -107,11 +107,11 @@ pub unsafe fn register(prefix: &str, factory: F) -> Result<(), Error> where F: Fn(&Remote) -> Result + Send + Sync + 'static, { - ::init(); + crate::init(); let mut data = Box::new(TransportData { factory: Box::new(factory), }); - let prefix = try!(CString::new(prefix)); + let prefix = CString::new(prefix)?; let datap = (&mut *data) as *mut TransportData as *mut c_void; try_call!(raw::git_transport_register( prefix, diff --git a/src/tree.rs b/src/tree.rs index 02c46829fc..6035f63310 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -8,8 +8,8 @@ use std::path::Path; use std::ptr; use std::str; -use util::{c_cmp_to_ordering, Binding, IntoCString}; -use {panic, raw, Error, Object, ObjectType, Oid, Repository}; +use crate::util::{c_cmp_to_ordering, Binding, IntoCString}; +use crate::{panic, raw, Error, Object, ObjectType, Oid, Repository}; /// A structure to represent a git [tree][1] /// @@ -179,7 +179,7 @@ impl<'repo> Tree<'repo> { /// Retrieve a tree entry contained in a tree or in any of its subtrees, /// given its relative path. pub fn get_path(&self, path: &Path) -> Result, Error> { - let path = try!(path.into_c_string()); + let path = path.into_c_string()?; let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_tree_entry_bypath(&mut ret, &*self.raw(), path)); @@ -234,8 +234,8 @@ impl<'repo> Binding for Tree<'repo> { } } -impl<'repo> ::std::fmt::Debug for Tree<'repo> { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { +impl<'repo> std::fmt::Debug for Tree<'repo> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { f.debug_struct("Tree").field("id", &self.id()).finish() } } @@ -287,7 +287,7 @@ impl<'tree> TreeEntry<'tree> { /// Get the filename of a tree entry pub fn name_bytes(&self) -> &[u8] { - unsafe { ::opt_bytes(self, raw::git_tree_entry_name(&*self.raw())).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_tree_entry_name(&*self.raw())).unwrap() } } /// Convert a tree entry to the object it points to. @@ -399,11 +399,11 @@ impl<'tree> ExactSizeIterator for TreeIter<'tree> {} #[cfg(test)] mod tests { use super::{TreeWalkMode, TreeWalkResult}; + use crate::{Object, ObjectType, Repository, Tree, TreeEntry}; use std::fs::File; use std::io::prelude::*; use std::path::Path; use tempdir::TempDir; - use {Object, ObjectType, Repository, Tree, TreeEntry}; pub struct TestTreeIter<'a> { entries: Vec>, @@ -452,7 +452,7 @@ mod tests { #[test] fn smoke_tree_iter() { - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); setup_repo(&td, &repo); @@ -495,7 +495,7 @@ mod tests { #[test] fn smoke() { - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); setup_repo(&td, &repo); @@ -529,7 +529,7 @@ mod tests { #[test] fn tree_walk() { - let (td, repo) = ::test::repo_init(); + let (td, repo) = crate::test::repo_init(); setup_repo(&td, &repo); diff --git a/src/treebuilder.rs b/src/treebuilder.rs index 6eabf17f25..16f60123ce 100644 --- a/src/treebuilder.rs +++ b/src/treebuilder.rs @@ -3,8 +3,8 @@ use std::ptr; use libc::{c_int, c_void}; -use util::{Binding, IntoCString}; -use {panic, raw, tree, Error, Oid, Repository, TreeEntry}; +use crate::util::{Binding, IntoCString}; +use crate::{panic, raw, tree, Error, Oid, Repository, TreeEntry}; /// Constructor for in-memory trees pub struct TreeBuilder<'repo> { @@ -33,7 +33,7 @@ impl<'repo> TreeBuilder<'repo> { where P: IntoCString, { - let filename = try!(filename.into_c_string()); + let filename = filename.into_c_string()?; unsafe { let ret = raw::git_treebuilder_get(self.raw, filename.as_ptr()); if ret.is_null() { @@ -57,7 +57,7 @@ impl<'repo> TreeBuilder<'repo> { oid: Oid, filemode: i32, ) -> Result { - let filename = try!(filename.into_c_string()); + let filename = filename.into_c_string()?; let filemode = filemode as raw::git_filemode_t; let mut ret = ptr::null(); @@ -75,7 +75,7 @@ impl<'repo> TreeBuilder<'repo> { /// Remove an entry from the builder by its filename pub fn remove(&mut self, filename: P) -> Result<(), Error> { - let filename = try!(filename.into_c_string()); + let filename = filename.into_c_string()?; unsafe { try_call!(raw::git_treebuilder_remove(self.raw, filename)); } @@ -153,11 +153,11 @@ impl<'repo> Drop for TreeBuilder<'repo> { #[cfg(test)] mod tests { - use ObjectType; + use crate::ObjectType; #[test] fn smoke() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut builder = repo.treebuilder(None).unwrap(); assert_eq!(builder.len(), 0); @@ -177,7 +177,7 @@ mod tests { #[test] fn write() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut builder = repo.treebuilder(None).unwrap(); let data = repo.blob(b"data").unwrap(); @@ -196,7 +196,7 @@ mod tests { #[test] fn filter() { - let (_td, repo) = ::test::repo_init(); + let (_td, repo) = crate::test::repo_init(); let mut builder = repo.treebuilder(None).unwrap(); let blob = repo.blob(b"data").unwrap(); diff --git a/src/util.rs b/src/util.rs index cf135d9292..d2402fcc71 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,7 +4,7 @@ use std::ffi::{CString, OsStr, OsString}; use std::iter::IntoIterator; use std::path::{Path, PathBuf}; -use {raw, Error}; +use crate::{raw, Error}; #[doc(hidden)] pub trait IsNull { @@ -48,7 +48,10 @@ where T: IntoCString, I: IntoIterator, { - let cstrs: Vec<_> = try!(iter.into_iter().map(|i| i.into_c_string()).collect()); + let cstrs = iter + .into_iter() + .map(|i| i.into_c_string()) + .collect::, _>>()?; let ptrs = cstrs.iter().map(|i| i.as_ptr()).collect::>(); let raw = raw::git_strarray { strings: ptrs.as_ptr() as *mut _, @@ -85,13 +88,13 @@ impl<'a, T: IntoCString + Clone> IntoCString for &'a T { impl<'a> IntoCString for &'a str { fn into_c_string(self) -> Result { - Ok(try!(CString::new(self))) + Ok(CString::new(self)?) } } impl IntoCString for String { fn into_c_string(self) -> Result { - Ok(try!(CString::new(self.into_bytes()))) + Ok(CString::new(self.into_bytes())?) } } @@ -126,7 +129,7 @@ impl IntoCString for OsString { fn into_c_string(self) -> Result { use std::os::unix::prelude::*; let s: &OsStr = self.as_ref(); - Ok(try!(CString::new(s.as_bytes()))) + Ok(CString::new(s.as_bytes())?) } #[cfg(windows)] fn into_c_string(self) -> Result { @@ -142,13 +145,13 @@ impl IntoCString for OsString { impl<'a> IntoCString for &'a [u8] { fn into_c_string(self) -> Result { - Ok(try!(CString::new(self))) + Ok(CString::new(self)?) } } impl IntoCString for Vec { fn into_c_string(self) -> Result { - Ok(try!(CString::new(self))) + Ok(CString::new(self)?) } } @@ -158,7 +161,7 @@ where { match opt_s { None => Ok(None), - Some(s) => Ok(Some(try!(s.into_c_string()))), + Some(s) => Ok(Some(s.into_c_string()?)), } } diff --git a/systest/Cargo.toml b/systest/Cargo.toml index 3507d85e6d..a95c28fb85 100644 --- a/systest/Cargo.toml +++ b/systest/Cargo.toml @@ -3,6 +3,7 @@ name = "systest" version = "0.1.0" authors = ["Alex Crichton "] build = "build.rs" +edition = "2018" [dependencies] libgit2-sys = { path = "../libgit2-sys", features = ['https', 'ssh'] } From d327bb127605b5b59945e05079bffb9a51517fab Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 4 Jun 2019 16:12:40 -0700 Subject: [PATCH 355/860] Update with edition idioms. --- examples/add.rs | 8 +- examples/blame.rs | 8 +- examples/cat-file.rs | 8 +- examples/clone.rs | 12 +-- examples/diff.rs | 21 ++--- examples/fetch.rs | 8 +- examples/init.rs | 8 +- examples/log.rs | 9 +- examples/ls-remote.rs | 8 +- examples/rev-list.rs | 8 +- examples/rev-parse.rs | 8 +- examples/status.rs | 8 +- examples/tag.rs | 14 +-- git2-curl/src/lib.rs | 12 +-- git2-curl/tests/all.rs | 9 +- libgit2-sys/build.rs | 3 - libgit2-sys/lib.rs | 10 +- src/blame.rs | 10 +- src/blob.rs | 4 +- src/branch.rs | 2 +- src/build.rs | 18 ++-- src/commit.rs | 14 +-- src/config.rs | 6 +- src/cred.rs | 1 + src/diff.rs | 36 +++---- src/error.rs | 2 +- src/index.rs | 14 +-- src/lib.rs | 22 ++--- src/note.rs | 6 +- src/object.rs | 6 +- src/odb.rs | 8 +- src/oid.rs | 4 +- src/oid_array.rs | 2 +- src/packbuilder.rs | 10 +- src/patch.rs | 20 ++-- src/pathspec.rs | 20 ++-- src/rebase.rs | 12 +-- src/reflog.rs | 8 +- src/remote.rs | 26 +++--- src/remote_callbacks.rs | 20 ++-- src/repo.rs | 201 ++++++++++++++++++++++------------------ src/signature.rs | 2 +- src/stash.rs | 4 +- src/status.rs | 4 +- src/string_array.rs | 6 +- src/submodule.rs | 2 +- src/tag.rs | 6 +- src/transport.rs | 6 +- src/tree.rs | 20 ++-- src/treebuilder.rs | 12 +-- systest/build.rs | 2 - systest/src/main.rs | 3 - 52 files changed, 323 insertions(+), 378 deletions(-) diff --git a/examples/add.rs b/examples/add.rs index 47dc56b281..35ca7e4b55 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -15,13 +15,9 @@ #![deny(warnings)] #![allow(trivial_casts)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use docopt::Docopt; use git2::Repository; +use serde_derive::Deserialize; use std::path::Path; #[derive(Deserialize)] @@ -71,7 +67,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: add [options] [--] [..] Options: diff --git a/examples/blame.rs b/examples/blame.rs index 68f1de20ac..2464155e0f 100644 --- a/examples/blame.rs +++ b/examples/blame.rs @@ -12,13 +12,9 @@ * . */ -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use docopt::Docopt; use git2::{BlameOptions, Repository}; +use serde_derive::Deserialize; use std::io::{BufRead, BufReader}; use std::path::Path; @@ -91,7 +87,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: blame [options] [] Options: diff --git a/examples/cat-file.rs b/examples/cat-file.rs index 07ead1bfcf..2faf88b688 100644 --- a/examples/cat-file.rs +++ b/examples/cat-file.rs @@ -14,15 +14,11 @@ #![deny(warnings)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use std::io::{self, Write}; use docopt::Docopt; use git2::{Blob, Commit, ObjectType, Repository, Signature, Tag, Tree}; +use serde_derive::Deserialize; #[derive(Deserialize)] struct Args { @@ -132,7 +128,7 @@ fn show_sig(header: &str, sig: Option) { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: cat-file (-t | -s | -e | -p) [options] Options: diff --git a/examples/clone.rs b/examples/clone.rs index bd3a8122c2..bf00524154 100644 --- a/examples/clone.rs +++ b/examples/clone.rs @@ -14,14 +14,10 @@ #![deny(warnings)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use docopt::Docopt; use git2::build::{CheckoutBuilder, RepoBuilder}; use git2::{FetchOptions, Progress, RemoteCallbacks}; +use serde_derive::Deserialize; use std::cell::RefCell; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -52,7 +48,7 @@ fn print(state: &mut State) { let kbytes = stats.received_bytes() / 1024; if stats.received_objects() == stats.total_objects() { if !state.newline { - println!(""); + println!(); state.newline = true; } print!( @@ -115,13 +111,13 @@ fn run(args: &Args) -> Result<(), git2::Error> { .fetch_options(fo) .with_checkout(co) .clone(&args.arg_url, Path::new(&args.arg_path))?; - println!(""); + println!(); Ok(()) } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: add [options] Options: diff --git a/examples/diff.rs b/examples/diff.rs index d109db114d..1e6c76a802 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -14,16 +14,11 @@ #![deny(warnings)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - -use std::str; - use docopt::Docopt; use git2::{Diff, DiffOptions, Error, Object, ObjectType, Repository}; use git2::{DiffFindOptions, DiffFormat}; +use serde_derive::Deserialize; +use std::str; #[derive(Deserialize)] #[allow(non_snake_case)] @@ -64,11 +59,11 @@ struct Args { flag_git_dir: Option, } -const RESET: &'static str = "\u{1b}[m"; -const BOLD: &'static str = "\u{1b}[1m"; -const RED: &'static str = "\u{1b}[31m"; -const GREEN: &'static str = "\u{1b}[32m"; -const CYAN: &'static str = "\u{1b}[36m"; +const RESET: &str = "\u{1b}[m"; +const BOLD: &str = "\u{1b}[1m"; +const RED: &str = "\u{1b}[31m"; +const GREEN: &str = "\u{1b}[32m"; +const CYAN: &str = "\u{1b}[36m"; #[derive(PartialEq, Eq, Copy, Clone)] enum Cache { @@ -267,7 +262,7 @@ impl Args { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: diff [options] [ []] Options: diff --git a/examples/fetch.rs b/examples/fetch.rs index a400eeacaf..e2e7552bd9 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -14,13 +14,9 @@ #![deny(warnings)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use docopt::Docopt; use git2::{AutotagOption, FetchOptions, RemoteCallbacks, Repository}; +use serde_derive::Deserialize; use std::io::{self, Write}; use std::str; @@ -123,7 +119,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: fetch [options] [] Options: diff --git a/examples/init.rs b/examples/init.rs index 3b9371bd1d..c43f59edd8 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -14,13 +14,9 @@ #![deny(warnings)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use docopt::Docopt; use git2::{Error, Repository, RepositoryInitMode, RepositoryInitOptions}; +use serde_derive::Deserialize; use std::path::{Path, PathBuf}; #[derive(Deserialize)] @@ -129,7 +125,7 @@ fn parse_shared(shared: &str) -> Result { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: init [options] Options: diff --git a/examples/log.rs b/examples/log.rs index 141766c59b..94066f385a 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -14,15 +14,10 @@ #![deny(warnings)] -#[macro_use] -extern crate serde_derive; -extern crate docopt; -extern crate git2; -extern crate time; - use docopt::Docopt; use git2::{Commit, DiffOptions, ObjectType, Repository, Signature, Time}; use git2::{DiffFormat, Error, Pathspec}; +use serde_derive::Deserialize; use std::str; #[derive(Deserialize)] @@ -274,7 +269,7 @@ impl Args { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: log [options] [..] [--] [..] Options: diff --git a/examples/ls-remote.rs b/examples/ls-remote.rs index b5935746af..38ecd71eeb 100644 --- a/examples/ls-remote.rs +++ b/examples/ls-remote.rs @@ -14,13 +14,9 @@ #![deny(warnings)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use docopt::Docopt; use git2::{Direction, Repository}; +use serde_derive::Deserialize; #[derive(Deserialize)] struct Args { @@ -47,7 +43,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: ls-remote [option] Options: diff --git a/examples/rev-list.rs b/examples/rev-list.rs index 6aedb9af73..84c0adcedb 100644 --- a/examples/rev-list.rs +++ b/examples/rev-list.rs @@ -15,13 +15,9 @@ #![deny(warnings)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use docopt::Docopt; use git2::{Error, Oid, Repository, Revwalk}; +use serde_derive::Deserialize; #[derive(Deserialize)] struct Args { @@ -93,7 +89,7 @@ fn push(revwalk: &mut Revwalk, id: Oid, hide: bool) -> Result<(), Error> { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: rev-list [options] [--] ... Options: diff --git a/examples/rev-parse.rs b/examples/rev-parse.rs index 86017974cb..4c8ccc813a 100644 --- a/examples/rev-parse.rs +++ b/examples/rev-parse.rs @@ -14,13 +14,9 @@ #![deny(warnings)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use docopt::Docopt; use git2::Repository; +use serde_derive::Deserialize; #[derive(Deserialize)] struct Args { @@ -54,7 +50,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: rev-parse [options] Options: diff --git a/examples/status.rs b/examples/status.rs index a15c6c93f1..689c42a67c 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -14,13 +14,9 @@ #![deny(warnings)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use docopt::Docopt; use git2::{Error, ErrorCode, Repository, StatusOptions, SubmoduleIgnore}; +use serde_derive::Deserialize; use std::str; use std::time::Duration; @@ -415,7 +411,7 @@ impl Args { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: status [options] [--] [..] Options: diff --git a/examples/tag.rs b/examples/tag.rs index e69b925f46..107b9db0c7 100644 --- a/examples/tag.rs +++ b/examples/tag.rs @@ -14,13 +14,9 @@ #![deny(warnings)] -extern crate docopt; -extern crate git2; -#[macro_use] -extern crate serde_derive; - use docopt::Docopt; use git2::{Commit, Error, Repository, Tag}; +use serde_derive::Deserialize; use std::str; #[derive(Deserialize)] @@ -80,7 +76,7 @@ fn print_tag(tag: &Tag, args: &Args) { if args.flag_n.is_some() { print_list_lines(tag.message(), args); } else { - println!(""); + println!(); } } @@ -89,7 +85,7 @@ fn print_commit(commit: &Commit, name: &str, args: &Args) { if args.flag_n.is_some() { print_list_lines(commit.message(), args); } else { - println!(""); + println!(); } } @@ -106,7 +102,7 @@ fn print_list_lines(message: Option<&str>, args: &Args) { if let Some(first) = lines.next() { print!("{}", first); } - println!(""); + println!(); for line in lines.take(args.flag_n.unwrap_or(0) as usize) { print!(" {}", line); @@ -114,7 +110,7 @@ fn print_list_lines(message: Option<&str>, args: &Args) { } fn main() { - const USAGE: &'static str = " + const USAGE: &str = " usage: tag [-a] [-f] [-m ] [] tag -d diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 17ba61c01b..687ec7e735 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -16,12 +16,9 @@ //! > operation, only clones. #![doc(html_root_url = "http://alexcrichton.com/git2-rs")] - -extern crate curl; -extern crate git2; -extern crate url; -#[macro_use] -extern crate log; +#![deny(missing_docs)] +#![warn(rust_2018_idioms)] +#![cfg_attr(test, deny(warnings))] use std::error; use std::io::prelude::*; @@ -33,6 +30,7 @@ use curl::easy::{Easy, List}; use git2::transport::SmartSubtransportStream; use git2::transport::{Service, SmartSubtransport, Transport}; use git2::Error; +use log::{debug, info}; use url::Url; struct CurlTransport { @@ -81,7 +79,7 @@ pub unsafe fn register(handle: Easy) { }); } -fn factory(remote: &git2::Remote, handle: Arc>) -> Result { +fn factory(remote: &git2::Remote<'_>, handle: Arc>) -> Result { Transport::smart( remote, true, diff --git a/git2-curl/tests/all.rs b/git2-curl/tests/all.rs index 7673143e3b..03c68b7b10 100644 --- a/git2-curl/tests/all.rs +++ b/git2-curl/tests/all.rs @@ -1,12 +1,5 @@ -extern crate civet; -extern crate conduit; -extern crate conduit_git_http_backend as git_backend; -extern crate curl; -extern crate git2; -extern crate git2_curl; -extern crate tempfile; - use civet::{Config, Server}; +use conduit_git_http_backend as git_backend; use std::fs::File; use std::path::Path; use tempfile::TempDir; diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 8a2848e415..e622f2cde8 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -1,6 +1,3 @@ -extern crate cc; -extern crate pkg_config; - use std::env; use std::fs; use std::path::{Path, PathBuf}; diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 563a271d85..0444d83d81 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,16 +1,12 @@ #![doc(html_root_url = "http://alexcrichton.com/git2-rs")] #![allow(non_camel_case_types, unused_extern_crates)] -#[cfg(feature = "curl")] -extern crate curl_sys; -extern crate libc; -#[cfg(feature = "ssh")] -extern crate libssh2_sys as libssh2; +// This is required to link libz when libssh2-sys is not included. extern crate libz_sys as libz; -#[cfg(all(unix, feature = "https"))] -extern crate openssl_sys; use libc::{c_char, c_int, c_uchar, c_uint, c_void, size_t}; +#[cfg(feature = "ssh")] +use libssh2_sys as libssh2; pub const GIT_OID_RAWSZ: usize = 20; pub const GIT_OID_HEXSZ: usize = GIT_OID_RAWSZ * 2; diff --git a/src/blame.rs b/src/blame.rs index f3d055e5d9..1341c147aa 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -40,7 +40,7 @@ impl<'repo> Blame<'repo> { } /// Gets the blame hunk at the given index. - pub fn get_index(&self, index: usize) -> Option { + pub fn get_index(&self, index: usize) -> Option> { unsafe { let ptr = raw::git_blame_get_hunk_byindex(self.raw(), index as u32); if ptr.is_null() { @@ -53,7 +53,7 @@ impl<'repo> Blame<'repo> { /// Gets the hunk that relates to the given line number in the newest /// commit. - pub fn get_line(&self, lineno: usize) -> Option { + pub fn get_line(&self, lineno: usize) -> Option> { unsafe { let ptr = raw::git_blame_get_hunk_byline(self.raw(), lineno); if ptr.is_null() { @@ -65,7 +65,7 @@ impl<'repo> Blame<'repo> { } /// Returns an iterator over the hunks in this blame. - pub fn iter(&self) -> BlameIter { + pub fn iter(&self) -> BlameIter<'_> { BlameIter { range: 0..self.len(), blame: self, @@ -87,7 +87,7 @@ impl<'blame> BlameHunk<'blame> { } /// Returns signature of the commit. - pub fn final_signature(&self) -> Signature { + pub fn final_signature(&self) -> Signature<'_> { unsafe { signature::from_raw_const(self, (*self.raw).final_signature) } } @@ -108,7 +108,7 @@ impl<'blame> BlameHunk<'blame> { } /// Returns signature of the commit. - pub fn orig_signature(&self) -> Signature { + pub fn orig_signature(&self) -> Signature<'_> { unsafe { signature::from_raw_const(self, (*self.raw).orig_signature) } } diff --git a/src/blob.rs b/src/blob.rs index cdbb6941a3..c0a471f358 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -41,7 +41,7 @@ impl<'repo> Blob<'repo> { /// Consumes Blob to be returned as an `Object` pub fn into_object(self) -> Object<'repo> { - assert_eq!(mem::size_of_val(&self), mem::size_of::()); + assert_eq!(mem::size_of_val(&self), mem::size_of::>()); unsafe { mem::transmute(self) } } } @@ -61,7 +61,7 @@ impl<'repo> Binding for Blob<'repo> { } impl<'repo> std::fmt::Debug for Blob<'repo> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { f.debug_struct("Blob").field("id", &self.id()).finish() } } diff --git a/src/branch.rs b/src/branch.rs index a82734b336..75ae018ec7 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -24,7 +24,7 @@ pub struct Branches<'repo> { impl<'repo> Branch<'repo> { /// Creates Branch type from a Reference - pub fn wrap(reference: Reference) -> Branch { + pub fn wrap(reference: Reference<'_>) -> Branch<'_> { Branch { inner: reference } } diff --git a/src/build.rs b/src/build.rs index abec5295a1..71cf583c6c 100644 --- a/src/build.rs +++ b/src/build.rs @@ -62,9 +62,9 @@ pub type Progress<'a> = dyn FnMut(Option<&Path>, usize, usize) + 'a; pub type Notify<'a> = dyn FnMut( CheckoutNotificationType, Option<&Path>, - Option, - Option, - Option, + Option>, + Option>, + Option>, ) -> bool + 'a; @@ -253,7 +253,7 @@ extern "C" fn remote_create_cb( let code = panic::wrap(|| { let name = CStr::from_ptr(name).to_str().unwrap(); let url = CStr::from_ptr(url).to_str().unwrap(); - let f = payload as *mut Box; + let f = payload as *mut Box>; match (*f)(&repo, name, url) { Ok(remote) => { *out = crate::remote::remote_into_raw(remote); @@ -516,9 +516,9 @@ impl<'cb> CheckoutBuilder<'cb> { F: FnMut( CheckoutNotificationType, Option<&Path>, - Option, - Option, - Option, + Option>, + Option>, + Option>, ) -> bool + 'cb, { @@ -575,7 +575,7 @@ extern "C" fn progress_cb( data: *mut c_void, ) { panic::wrap(|| unsafe { - let payload = &mut *(data as *mut CheckoutBuilder); + let payload = &mut *(data as *mut CheckoutBuilder<'_>); let callback = match payload.progress { Some(ref mut c) => c, None => return, @@ -599,7 +599,7 @@ extern "C" fn notify_cb( ) -> c_int { // pack callback etc panic::wrap(|| unsafe { - let payload = &mut *(data as *mut CheckoutBuilder); + let payload = &mut *(data as *mut CheckoutBuilder<'_>); let callback = match payload.notify { Some(ref mut c) => c, None => return 0, diff --git a/src/commit.rs b/src/commit.rs index 636d1adede..1bb468278d 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -154,7 +154,7 @@ impl<'repo> Commit<'repo> { } /// Creates a new iterator over the parents of this commit. - pub fn parent_ids(&self) -> ParentIds { + pub fn parent_ids(&self) -> ParentIds<'_> { ParentIds { range: 0..self.parent_count(), commit: self, @@ -162,7 +162,7 @@ impl<'repo> Commit<'repo> { } /// Get the author of this commit. - pub fn author(&self) -> Signature { + pub fn author(&self) -> Signature<'_> { unsafe { let ptr = raw::git_commit_author(&*self.raw); signature::from_raw_const(self, ptr) @@ -170,7 +170,7 @@ impl<'repo> Commit<'repo> { } /// Get the committer of this commit. - pub fn committer(&self) -> Signature { + pub fn committer(&self) -> Signature<'_> { unsafe { let ptr = raw::git_commit_committer(&*self.raw); signature::from_raw_const(self, ptr) @@ -189,8 +189,8 @@ impl<'repo> Commit<'repo> { pub fn amend( &self, update_ref: Option<&str>, - author: Option<&Signature>, - committer: Option<&Signature>, + author: Option<&Signature<'_>>, + committer: Option<&Signature<'_>>, message_encoding: Option<&str>, message: Option<&str>, tree: Option<&Tree<'repo>>, @@ -262,7 +262,7 @@ impl<'repo> Commit<'repo> { /// Consumes Commit to be returned as an `Object` pub fn into_object(self) -> Object<'repo> { - assert_eq!(mem::size_of_val(&self), mem::size_of::()); + assert_eq!(mem::size_of_val(&self), mem::size_of::>()); unsafe { mem::transmute(self) } } } @@ -281,7 +281,7 @@ impl<'repo> Binding for Commit<'repo> { } impl<'repo> std::fmt::Debug for Commit<'repo> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { let mut ds = f.debug_struct("Commit"); ds.field("id", &self.id()); if let Some(summary) = self.summary() { diff --git a/src/config.rs b/src/config.rs index 6eb689cbb4..9df476cf2b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -167,7 +167,7 @@ impl Config { unsafe { try_call!(raw::git_config_get_bool(&mut out, &*self.raw, name)); } - Ok(!(out == 0)) + Ok(out != 0) } /// Get the value of an integer config variable. @@ -244,7 +244,7 @@ impl Config { } /// Get the ConfigEntry for a config variable. - pub fn get_entry(&self, name: &str) -> Result { + pub fn get_entry(&self, name: &str) -> Result, Error> { let mut ret = ptr::null_mut(); let name = CString::new(name)?; unsafe { @@ -271,7 +271,7 @@ impl Config { /// println!("{} => {}", entry.name().unwrap(), entry.value().unwrap()); /// } /// ``` - pub fn entries(&self, glob: Option<&str>) -> Result { + pub fn entries(&self, glob: Option<&str>) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { match glob { diff --git a/src/cred.rs b/src/cred.rs index 9717f5e686..ad5e86b03e 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -1,3 +1,4 @@ +use log::{debug, trace}; use std::ffi::CString; use std::io::Write; use std::mem; diff --git a/src/diff.rs b/src/diff.rs index ad8ee0d9f0..bf1d2a5173 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -102,12 +102,12 @@ pub enum DiffBinaryKind { Delta, } -type PrintCb<'a> = dyn FnMut(DiffDelta, Option, DiffLine) -> bool + 'a; +type PrintCb<'a> = dyn FnMut(DiffDelta<'_>, Option>, DiffLine<'_>) -> bool + 'a; -pub type FileCb<'a> = dyn FnMut(DiffDelta, f32) -> bool + 'a; -pub type BinaryCb<'a> = dyn FnMut(DiffDelta, DiffBinary) -> bool + 'a; -pub type HunkCb<'a> = dyn FnMut(DiffDelta, DiffHunk) -> bool + 'a; -pub type LineCb<'a> = dyn FnMut(DiffDelta, Option, DiffLine) -> bool + 'a; +pub type FileCb<'a> = dyn FnMut(DiffDelta<'_>, f32) -> bool + 'a; +pub type BinaryCb<'a> = dyn FnMut(DiffDelta<'_>, DiffBinary<'_>) -> bool + 'a; +pub type HunkCb<'a> = dyn FnMut(DiffDelta<'_>, DiffHunk<'_>) -> bool + 'a; +pub type LineCb<'a> = dyn FnMut(DiffDelta<'_>, Option>, DiffLine<'_>) -> bool + 'a; struct ForeachCallbacks<'a, 'b: 'a, 'c, 'd: 'c, 'e, 'f: 'e, 'g, 'h: 'g> { file: &'a mut FileCb<'b>, @@ -133,7 +133,7 @@ impl<'repo> Diff<'repo> { } /// Returns an iterator over the deltas in this diff. - pub fn deltas(&self) -> Deltas { + pub fn deltas(&self) -> Deltas<'_> { let num_deltas = unsafe { raw::git_diff_num_deltas(&*self.raw) }; Deltas { range: 0..(num_deltas as usize), @@ -142,7 +142,7 @@ impl<'repo> Diff<'repo> { } /// Return the diff delta for an entry in the diff list. - pub fn get_delta(&self, i: usize) -> Option { + pub fn get_delta(&self, i: usize) -> Option> { unsafe { let ptr = raw::git_diff_get_delta(&*self.raw, i as size_t); Binding::from_raw_opt(ptr as *mut _) @@ -160,9 +160,9 @@ impl<'repo> Diff<'repo> { /// return an error from this function. pub fn print(&self, format: DiffFormat, mut cb: F) -> Result<(), Error> where - F: FnMut(DiffDelta, Option, DiffLine) -> bool, + F: FnMut(DiffDelta<'_>, Option>, DiffLine<'_>) -> bool, { - let mut cb: &mut PrintCb = &mut cb; + let mut cb: &mut PrintCb<'_> = &mut cb; let ptr = &mut cb as *mut _; unsafe { try_call!(raw::git_diff_print( @@ -181,10 +181,10 @@ impl<'repo> Diff<'repo> { /// return an error from this function. pub fn foreach( &self, - file_cb: &mut FileCb, - binary_cb: Option<&mut BinaryCb>, - hunk_cb: Option<&mut HunkCb>, - line_cb: Option<&mut LineCb>, + file_cb: &mut FileCb<'_>, + binary_cb: Option<&mut BinaryCb<'_>>, + hunk_cb: Option<&mut HunkCb<'_>>, + line_cb: Option<&mut LineCb<'_>>, ) -> Result<(), Error> { let mut cbs = ForeachCallbacks { file: file_cb, @@ -259,7 +259,7 @@ pub extern "C" fn print_cb( let line = Binding::from_raw(line); let r = panic::wrap(|| { - let data = data as *mut &mut PrintCb; + let data = data as *mut &mut PrintCb<'_>; (*data)(delta, hunk, line) }); if r == Some(true) { @@ -279,7 +279,7 @@ extern "C" fn file_cb_c( let delta = Binding::from_raw(delta as *mut _); let r = panic::wrap(|| { - let cbs = data as *mut ForeachCallbacks; + let cbs = data as *mut ForeachCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; ((*cbs).file)(delta, progress) }); if r == Some(true) { @@ -300,7 +300,7 @@ extern "C" fn binary_cb_c( let binary = Binding::from_raw(binary); let r = panic::wrap(|| { - let cbs = data as *mut ForeachCallbacks; + let cbs = data as *mut ForeachCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; match (*cbs).binary { Some(ref mut cb) => cb(delta, binary), None => false, @@ -324,7 +324,7 @@ extern "C" fn hunk_cb_c( let hunk = Binding::from_raw(hunk); let r = panic::wrap(|| { - let cbs = data as *mut ForeachCallbacks; + let cbs = data as *mut ForeachCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; match (*cbs).hunk { Some(ref mut cb) => cb(delta, hunk), None => false, @@ -350,7 +350,7 @@ extern "C" fn line_cb_c( let line = Binding::from_raw(line); let r = panic::wrap(|| { - let cbs = data as *mut ForeachCallbacks; + let cbs = data as *mut ForeachCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; match (*cbs).line { Some(ref mut cb) => cb(delta, hunk, line), None => false, diff --git a/src/error.rs b/src/error.rs index cb55e8aa7c..2a8dcca7e7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -249,7 +249,7 @@ impl error::Error for Error { } impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.message)?; match self.class() { ErrorClass::None => {} diff --git a/src/index.rs b/src/index.rs index 9ff379e0f7..06f8425bfe 100644 --- a/src/index.rs +++ b/src/index.rs @@ -272,7 +272,7 @@ impl Index { &mut self, pathspecs: I, flag: IndexAddOption, - mut cb: Option<&mut IndexMatchedPath>, + mut cb: Option<&mut IndexMatchedPath<'_>>, ) -> Result<(), Error> where T: IntoCString, @@ -329,7 +329,7 @@ impl Index { } /// Get an iterator over the entries in this index. - pub fn iter(&self) -> IndexEntries { + pub fn iter(&self) -> IndexEntries<'_> { IndexEntries { range: 0..self.len(), index: self, @@ -337,7 +337,7 @@ impl Index { } /// Get an iterator over the index entries that have conflicts - pub fn conflicts(&self) -> Result { + pub fn conflicts(&self) -> Result, Error> { crate::init(); let mut conflict_iter = ptr::null_mut(); unsafe { @@ -397,7 +397,7 @@ impl Index { /// Read a tree into the index file with stats /// /// The current index contents will be replaced by the specified tree. - pub fn read_tree(&mut self, tree: &Tree) -> Result<(), Error> { + pub fn read_tree(&mut self, tree: &Tree<'_>) -> Result<(), Error> { unsafe { try_call!(raw::git_index_read_tree(self.raw, &*tree.raw())); } @@ -450,7 +450,7 @@ impl Index { pub fn remove_all( &mut self, pathspecs: I, - mut cb: Option<&mut IndexMatchedPath>, + mut cb: Option<&mut IndexMatchedPath<'_>>, ) -> Result<(), Error> where T: IntoCString, @@ -488,7 +488,7 @@ impl Index { pub fn update_all( &mut self, pathspecs: I, - mut cb: Option<&mut IndexMatchedPath>, + mut cb: Option<&mut IndexMatchedPath<'_>>, ) -> Result<(), Error> where T: IntoCString, @@ -589,7 +589,7 @@ extern "C" fn index_matched_path_cb( let matched_pathspec = CStr::from_ptr(matched_pathspec).to_bytes(); panic::wrap(|| { - let payload = payload as *mut &mut IndexMatchedPath; + let payload = payload as *mut &mut IndexMatchedPath<'_>; (*payload)(util::bytes2path(path), matched_pathspec) as c_int }) .unwrap_or(-1) diff --git a/src/lib.rs b/src/lib.rs index 3476921f0b..8f932a0796 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,17 +66,11 @@ #![doc(html_root_url = "https://docs.rs/git2/0.6")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] +#![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] -extern crate libc; -extern crate libgit2_sys as raw; -extern crate url; -#[macro_use] -extern crate bitflags; -#[macro_use] -extern crate log; -#[cfg(test)] -extern crate tempdir; +use bitflags::bitflags; +use libgit2_sys as raw; use std::ffi::{CStr, CString}; use std::fmt; @@ -674,8 +668,6 @@ fn init() { feature = "https" ))] fn openssl_env_init() { - extern crate openssl_probe; - // Currently, libgit2 leverages OpenSSL for SSL support when cloning // repositories over HTTPS. This means that we're picking up an OpenSSL // dependency on non-Windows platforms (where it has its own HTTPS @@ -853,7 +845,7 @@ impl ObjectType { } impl fmt::Display for ObjectType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.str().fmt(f) } } @@ -862,8 +854,8 @@ impl ReferenceType { /// Convert an object type to its string representation. pub fn str(&self) -> &'static str { match self { - &ReferenceType::Direct => "direct", - &ReferenceType::Symbolic => "symbolic", + ReferenceType::Direct => "direct", + ReferenceType::Symbolic => "symbolic", } } @@ -878,7 +870,7 @@ impl ReferenceType { } impl fmt::Display for ReferenceType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.str().fmt(f) } } diff --git a/src/note.rs b/src/note.rs index 25dc3bef0d..39c2576100 100644 --- a/src/note.rs +++ b/src/note.rs @@ -24,12 +24,12 @@ pub struct Notes<'repo> { impl<'repo> Note<'repo> { /// Get the note author - pub fn author(&self) -> Signature { + pub fn author(&self) -> Signature<'_> { unsafe { signature::from_raw_const(self, raw::git_note_author(&*self.raw)) } } /// Get the note committer - pub fn committer(&self) -> Signature { + pub fn committer(&self) -> Signature<'_> { unsafe { signature::from_raw_const(self, raw::git_note_committer(&*self.raw)) } } @@ -63,7 +63,7 @@ impl<'repo> Binding for Note<'repo> { } impl<'repo> std::fmt::Debug for Note<'repo> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { f.debug_struct("Note").field("id", &self.id()).finish() } } diff --git a/src/object.rs b/src/object.rs index 18c7b03c44..278c55d8c0 100644 --- a/src/object.rs +++ b/src/object.rs @@ -137,7 +137,7 @@ impl<'repo> Object<'repo> { /// Describes a commit /// /// Performs a describe operation on this commitish object. - pub fn describe(&self, opts: &DescribeOptions) -> Result { + pub fn describe(&self, opts: &DescribeOptions) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_describe_commit(&mut ret, self.raw, opts.raw())); @@ -146,7 +146,7 @@ impl<'repo> Object<'repo> { } fn cast(&self, kind: ObjectType) -> Option<&T> { - assert_eq!(mem::size_of::(), mem::size_of::()); + assert_eq!(mem::size_of::>(), mem::size_of::()); if self.kind() == Some(kind) { unsafe { Some(&*(self as *const _ as *const T)) } } else { @@ -213,7 +213,7 @@ impl<'repo> Clone for Object<'repo> { } impl<'repo> std::fmt::Debug for Object<'repo> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { let mut ds = f.debug_struct("Object"); match self.kind() { Some(kind) => ds.field("kind", &kind), diff --git a/src/odb.rs b/src/odb.rs index 6d3635a887..71b34b0aad 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -51,7 +51,7 @@ impl<'repo> Odb<'repo> { /// /// Note that most backends do not support streaming reads because they store their objects as compressed/delta'ed blobs. /// If the backend does not support streaming reads, use the `read` method instead. - pub fn reader(&self, oid: Oid) -> Result<(OdbReader, usize, ObjectType), Error> { + pub fn reader(&self, oid: Oid) -> Result<(OdbReader<'_>, usize, ObjectType), Error> { let mut out = ptr::null_mut(); let mut size = 0usize; let mut otype: raw::git_object_t = ObjectType::Any.raw(); @@ -75,7 +75,7 @@ impl<'repo> Odb<'repo> { /// /// The type and final length of the object must be specified when opening the stream. /// If the backend does not support streaming writes, use the `write` method instead. - pub fn writer(&self, size: usize, obj_type: ObjectType) -> Result { + pub fn writer(&self, size: usize, obj_type: ObjectType) -> Result, Error> { let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_odb_open_wstream( @@ -107,7 +107,7 @@ impl<'repo> Odb<'repo> { } /// Read an object from the database. - pub fn read(&self, oid: Oid) -> Result { + pub fn read(&self, oid: Oid) -> Result, Error> { let mut out = ptr::null_mut(); unsafe { try_call!(raw::git_odb_read(&mut out, self.raw, oid.raw())); @@ -359,7 +359,7 @@ struct ForeachCbData<'a> { extern "C" fn foreach_cb(id: *const raw::git_oid, payload: *mut c_void) -> c_int { panic::wrap(|| unsafe { - let data = &mut *(payload as *mut ForeachCbData); + let data = &mut *(payload as *mut ForeachCbData<'_>); let res = { let callback = &mut data.callback; callback(&Binding::from_raw(id)) diff --git a/src/oid.rs b/src/oid.rs index 7de941bfc7..4a582e8c69 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -123,14 +123,14 @@ impl Binding for Oid { } impl fmt::Debug for Oid { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } } impl fmt::Display for Oid { /// Hex-encode this Oid into a formatter. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut dst = [0u8; raw::GIT_OID_HEXSZ + 1]; unsafe { raw::git_oid_tostr( diff --git a/src/oid_array.rs b/src/oid_array.rs index b2caf0e061..914681ecc6 100644 --- a/src/oid_array.rs +++ b/src/oid_array.rs @@ -40,7 +40,7 @@ impl Binding for OidArray { } impl<'repo> std::fmt::Debug for OidArray { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { f.debug_tuple("OidArray").field(&self.deref()).finish() } } diff --git a/src/packbuilder.rs b/src/packbuilder.rs index 2d65c6e9d6..d043f0497c 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -55,7 +55,7 @@ impl<'repo> PackBuilder<'repo> { /// Insert objects as given by the walk. Those commits and all objects they /// reference will be inserted into the packbuilder. - pub fn insert_walk(&mut self, walk: &mut Revwalk) -> Result<(), Error> { + pub fn insert_walk(&mut self, walk: &mut Revwalk<'_>) -> Result<(), Error> { unsafe { try_call!(raw::git_packbuilder_insert_walk(self.raw, walk.raw())); } @@ -87,7 +87,7 @@ impl<'repo> PackBuilder<'repo> { where F: FnMut(&[u8]) -> bool, { - let mut cb = &mut cb as &mut ForEachCb; + let mut cb = &mut cb as &mut ForEachCb<'_>; let ptr = &mut cb as *mut _; unsafe { try_call!(raw::git_packbuilder_foreach( @@ -110,7 +110,7 @@ impl<'repo> PackBuilder<'repo> { where F: FnMut(PackBuilderStage, u32, u32) -> bool + 'repo, { - let mut progress = Box::new(Box::new(progress) as Box); + let mut progress = Box::new(Box::new(progress) as Box>); let ptr = &mut *progress as *mut _; let progress_c = Some(progress_c as raw::git_packbuilder_progress); unsafe { @@ -205,7 +205,7 @@ extern "C" fn foreach_c(buf: *const c_void, size: size_t, data: *mut c_void) -> let buf = slice::from_raw_parts(buf as *const u8, size as usize); let r = panic::wrap(|| { - let data = data as *mut &mut ForEachCb; + let data = data as *mut &mut ForEachCb<'_>; (*data)(buf) }); if r == Some(true) { @@ -226,7 +226,7 @@ extern "C" fn progress_c( let stage = Binding::from_raw(stage); let r = panic::wrap(|| { - let data = data as *mut Box; + let data = data as *mut Box>; (*data)(stage, current, total) }); if r == Some(true) { diff --git a/src/patch.rs b/src/patch.rs index 62c30017b1..65cff4704b 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -35,7 +35,7 @@ impl Patch { /// Return a Patch for one file in a Diff. /// /// Returns Ok(None) for an unchanged or binary file. - pub fn from_diff(diff: &Diff, idx: usize) -> Result, Error> { + pub fn from_diff(diff: &Diff<'_>, idx: usize) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_patch_from_diff(&mut ret, diff.raw(), idx)); @@ -45,9 +45,9 @@ impl Patch { /// Generate a Patch by diffing two blobs. pub fn from_blobs( - old_blob: &Blob, + old_blob: &Blob<'_>, old_path: Option<&Path>, - new_blob: &Blob, + new_blob: &Blob<'_>, new_path: Option<&Path>, opts: Option<&mut DiffOptions>, ) -> Result { @@ -69,7 +69,7 @@ impl Patch { /// Generate a Patch by diffing a blob and a buffer. pub fn from_blob_and_buffer( - old_blob: &Blob, + old_blob: &Blob<'_>, old_path: Option<&Path>, new_buffer: &[u8], new_path: Option<&Path>, @@ -119,7 +119,7 @@ impl Patch { } /// Get the DiffDelta associated with the Patch. - pub fn delta(&self) -> DiffDelta { + pub fn delta(&self) -> DiffDelta<'_> { unsafe { Binding::from_raw(raw::git_patch_get_delta(self.raw) as *mut _) } } @@ -145,7 +145,7 @@ impl Patch { } /// Get a DiffHunk and its total line count from the Patch. - pub fn hunk(&self, hunk_idx: usize) -> Result<(DiffHunk, usize), Error> { + pub fn hunk(&self, hunk_idx: usize) -> Result<(DiffHunk<'_>, usize), Error> { let mut ret = ptr::null(); let mut lines = 0; unsafe { @@ -162,7 +162,11 @@ impl Patch { } /// Get a DiffLine from a hunk of the Patch. - pub fn line_in_hunk(&self, hunk_idx: usize, line_of_hunk: usize) -> Result { + pub fn line_in_hunk( + &self, + hunk_idx: usize, + line_of_hunk: usize, + ) -> Result, Error> { let mut ret = ptr::null(); unsafe { try_call!(raw::git_patch_get_line_in_hunk( @@ -193,7 +197,7 @@ impl Patch { } /// Print the Patch to text via a callback. - pub fn print(&mut self, mut line_cb: &mut LineCb) -> Result<(), Error> { + pub fn print(&mut self, mut line_cb: &mut LineCb<'_>) -> Result<(), Error> { let ptr = &mut line_cb as *mut _ as *mut c_void; unsafe { try_call!(raw::git_patch_print(self.raw, print_cb, ptr)); diff --git a/src/pathspec.rs b/src/pathspec.rs index d609649fd2..3b23c2fc85 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -61,9 +61,9 @@ impl Pathspec { /// specified. pub fn match_diff( &self, - diff: &Diff, + diff: &Diff<'_>, flags: PathspecFlags, - ) -> Result { + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_pathspec_match_diff( @@ -84,9 +84,9 @@ impl Pathspec { /// specified. pub fn match_tree( &self, - tree: &Tree, + tree: &Tree<'_>, flags: PathspecFlags, - ) -> Result { + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_pathspec_match_tree( @@ -109,7 +109,7 @@ impl Pathspec { &self, index: &Index, flags: PathspecFlags, - ) -> Result { + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_pathspec_match_index( @@ -138,7 +138,7 @@ impl Pathspec { &self, repo: &Repository, flags: PathspecFlags, - ) -> Result { + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_pathspec_match_workdir( @@ -190,7 +190,7 @@ impl<'ps> PathspecMatchList<'ps> { } /// Returns an iterator over the matching filenames in this list. - pub fn entries(&self) -> PathspecEntries { + pub fn entries(&self) -> PathspecEntries<'_> { let n = self.entrycount(); let n = if n > 0 && self.entry(0).is_none() { 0 @@ -215,7 +215,7 @@ impl<'ps> PathspecMatchList<'ps> { } /// Returns an iterator over the matching diff entries in this list. - pub fn diff_entries(&self) -> PathspecDiffEntries { + pub fn diff_entries(&self) -> PathspecDiffEntries<'_> { let n = self.entrycount(); let n = if n > 0 && self.diff_entry(0).is_none() { 0 @@ -232,7 +232,7 @@ impl<'ps> PathspecMatchList<'ps> { /// /// If the list was not generated from a diff, then the return value will /// always be `None`. - pub fn diff_entry(&self, i: usize) -> Option { + pub fn diff_entry(&self, i: usize) -> Option> { unsafe { let ptr = raw::git_pathspec_match_list_diff_entry(&*self.raw, i as size_t); Binding::from_raw_opt(ptr as *mut _) @@ -240,7 +240,7 @@ impl<'ps> PathspecMatchList<'ps> { } /// Returns an iterator over the non-matching entries in this list. - pub fn failed_entries(&self) -> PathspecFailedEntries { + pub fn failed_entries(&self) -> PathspecFailedEntries<'_> { let n = self.failed_entrycount(); let n = if n > 0 && self.failed_entry(0).is_none() { 0 diff --git a/src/rebase.rs b/src/rebase.rs index 578247a7e5..598acecd19 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -108,7 +108,7 @@ impl<'repo> Rebase<'repo> { } /// Gets the rebase operation specified by the given index. - pub fn nth(&mut self, n: usize) -> Option { + pub fn nth(&mut self, n: usize) -> Option> { unsafe { let op = raw::git_rebase_operation_byindex(self.raw, n); if op.is_null() { @@ -152,8 +152,8 @@ impl<'repo> Rebase<'repo> { /// them as None pub fn commit( &mut self, - author: Option<&Signature>, - committer: &Signature, + author: Option<&Signature<'_>>, + committer: &Signature<'_>, message: Option<&str>, ) -> Result { let mut id: raw::git_oid = unsafe { mem::zeroed() }; @@ -183,7 +183,7 @@ impl<'repo> Rebase<'repo> { /// Finishes a rebase that is currently in progress once all patches have /// been applied. - pub fn finish(&mut self, signature: Option<&Signature>) -> Result<(), Error> { + pub fn finish(&mut self, signature: Option<&Signature<'_>>) -> Result<(), Error> { unsafe { try_call!(raw::git_rebase_finish(self.raw, signature.map(|s| s.raw()))); } @@ -341,7 +341,7 @@ mod tests { let branch = repo.find_annotated_commit(c2).unwrap(); let upstream = repo.find_annotated_commit(tip.id()).unwrap(); - let mut opts: RebaseOptions = Default::default(); + let mut opts: RebaseOptions<'_> = Default::default(); opts.inmemory(true); let mut rebase = repo .rebase(Some(&branch), Some(&upstream), None, Some(&mut opts)) @@ -393,7 +393,7 @@ mod tests { let branch = repo.find_annotated_commit(c2).unwrap(); let upstream = repo.find_annotated_commit(tip.id()).unwrap(); - let mut opts: RebaseOptions = Default::default(); + let mut opts: RebaseOptions<'_> = Default::default(); let mut rebase = repo .rebase(Some(&branch), Some(&upstream), None, Some(&mut opts)) .unwrap(); diff --git a/src/reflog.rs b/src/reflog.rs index 0aed4e56bd..4bd6f90f06 100644 --- a/src/reflog.rs +++ b/src/reflog.rs @@ -28,7 +28,7 @@ impl Reflog { pub fn append( &mut self, new_oid: Oid, - committer: &Signature, + committer: &Signature<'_>, msg: Option<&str>, ) -> Result<(), Error> { let msg = crate::opt_cstr(msg)?; @@ -64,7 +64,7 @@ impl Reflog { /// /// Requesting the reflog entry with an index of 0 (zero) will return the /// most recently created entry. - pub fn get(&self, i: usize) -> Option { + pub fn get(&self, i: usize) -> Option> { unsafe { let ptr = raw::git_reflog_entry_byindex(self.raw, i as size_t); Binding::from_raw_opt(ptr) @@ -82,7 +82,7 @@ impl Reflog { } /// Get an iterator to all entries inside of this reflog - pub fn iter(&self) -> ReflogIter { + pub fn iter(&self) -> ReflogIter<'_> { ReflogIter { range: 0..self.len(), reflog: self, @@ -118,7 +118,7 @@ impl Drop for Reflog { impl<'reflog> ReflogEntry<'reflog> { /// Get the committer of this entry - pub fn committer(&self) -> Signature { + pub fn committer(&self) -> Signature<'_> { unsafe { let ptr = raw::git_reflog_entry_committer(self.raw); signature::from_raw_const(self, ptr) diff --git a/src/remote.rs b/src/remote.rs index 9b919c9cbd..fbc8eb90ad 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -62,7 +62,7 @@ where remote: &'connection mut Remote<'repo>, } -pub fn remote_into_raw(remote: Remote) -> *mut raw::git_remote { +pub fn remote_into_raw(remote: Remote<'_>) -> *mut raw::git_remote { let ret = remote.raw; mem::forget(remote); return ret; @@ -181,7 +181,7 @@ impl<'repo> Remote<'repo> { pub fn download( &mut self, specs: &[&str], - opts: Option<&mut FetchOptions>, + opts: Option<&mut FetchOptions<'_>>, ) -> Result<(), Error> { let (_a, _b, arr) = crate::util::iter2cstrs(specs.iter())?; let raw = opts.map(|o| o.raw()); @@ -192,7 +192,7 @@ impl<'repo> Remote<'repo> { } /// Get the number of refspecs for a remote - pub fn refspecs<'a>(&'a self) -> Refspecs<'a> { + pub fn refspecs(&self) -> Refspecs<'_> { let cnt = unsafe { raw::git_remote_refspec_count(&*self.raw) as usize }; Refspecs { range: 0..cnt, @@ -230,7 +230,7 @@ impl<'repo> Remote<'repo> { pub fn fetch( &mut self, refspecs: &[&str], - opts: Option<&mut FetchOptions>, + opts: Option<&mut FetchOptions<'_>>, reflog_msg: Option<&str>, ) -> Result<(), Error> { let (_a, _b, arr) = crate::util::iter2cstrs(refspecs.iter())?; @@ -245,7 +245,7 @@ impl<'repo> Remote<'repo> { /// Update the tips to the new state pub fn update_tips( &mut self, - callbacks: Option<&mut RemoteCallbacks>, + callbacks: Option<&mut RemoteCallbacks<'_>>, update_fetchhead: bool, download_tags: AutotagOption, msg: Option<&str>, @@ -272,7 +272,11 @@ impl<'repo> Remote<'repo> { /// Note that you'll likely want to use `RemoteCallbacks` and set /// `push_update_reference` to test whether all the references were pushed /// successfully. - pub fn push(&mut self, refspecs: &[&str], opts: Option<&mut PushOptions>) -> Result<(), Error> { + pub fn push( + &mut self, + refspecs: &[&str], + opts: Option<&mut PushOptions<'_>>, + ) -> Result<(), Error> { let (_a, _b, arr) = crate::util::iter2cstrs(refspecs.iter())?; let raw = opts.map(|o| o.raw()); unsafe { @@ -282,7 +286,7 @@ impl<'repo> Remote<'repo> { } /// Get the statistics structure that is filled in by the fetch operation. - pub fn stats(&self) -> Progress { + pub fn stats(&self) -> Progress<'_> { unsafe { Binding::from_raw(raw::git_remote_stats(self.raw)) } } @@ -294,19 +298,19 @@ impl<'repo> Remote<'repo> { /// The remote (or more exactly its transport) must have connected to the /// remote repository. This list is available as soon as the connection to /// the remote is initiated and it remains available after disconnecting. - pub fn list(&self) -> Result<&[RemoteHead], Error> { + pub fn list(&self) -> Result<&[RemoteHead<'_>], Error> { let mut size = 0; let mut base = ptr::null_mut(); unsafe { try_call!(raw::git_remote_ls(&mut base, &mut size, self.raw)); assert_eq!( - mem::size_of::(), + mem::size_of::>(), mem::size_of::<*const raw::git_remote_head>() ); let slice = slice::from_raw_parts(base as *const _, size as usize); Ok(mem::transmute::< &[*const raw::git_remote_head], - &[RemoteHead], + &[RemoteHead<'_>], >(slice)) } } @@ -569,7 +573,7 @@ impl<'repo, 'connection, 'cb> RemoteConnection<'repo, 'connection, 'cb> { /// /// This list is available as soon as the connection to /// the remote is initiated and it remains available after disconnecting. - pub fn list(&self) -> Result<&[RemoteHead], Error> { + pub fn list(&self) -> Result<&[RemoteHead<'_>], Error> { self.remote.list() } } diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index b4521213a9..90a6e5c98a 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -51,7 +51,7 @@ pub type Credentials<'a> = /// continue. A return value of `false` will cancel the transfer. /// /// * `progress` - the progress being made so far. -pub type TransferProgress<'a> = dyn FnMut(Progress) -> bool + 'a; +pub type TransferProgress<'a> = dyn FnMut(Progress<'_>) -> bool + 'a; /// Callback for receiving messages delivered by the transport. /// @@ -68,7 +68,7 @@ pub type UpdateTips<'a> = dyn FnMut(&str, Oid, Oid) -> bool + 'a; /// /// The second argument is the hostname for the connection is passed as the last /// argument. -pub type CertificateCheck<'a> = dyn FnMut(&Cert, &str) -> bool + 'a; +pub type CertificateCheck<'a> = dyn FnMut(&Cert<'_>, &str) -> bool + 'a; /// Callback for each updated reference on push. /// @@ -108,7 +108,7 @@ impl<'a> RemoteCallbacks<'a> { /// The callback through which progress is monitored. pub fn transfer_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> where - F: FnMut(Progress) -> bool + 'a, + F: FnMut(Progress<'_>) -> bool + 'a, { self.progress = Some(Box::new(cb) as Box>); self @@ -141,7 +141,7 @@ impl<'a> RemoteCallbacks<'a> { /// connection to proceed. pub fn certificate_check(&mut self, cb: F) -> &mut RemoteCallbacks<'a> where - F: FnMut(&Cert, &str) -> bool + 'a, + F: FnMut(&Cert<'_>, &str) -> bool + 'a, { self.certificate_check = Some(Box::new(cb) as Box>); self @@ -275,7 +275,7 @@ extern "C" fn credentials_cb( ) -> c_int { unsafe { let ok = panic::wrap(|| { - let payload = &mut *(payload as *mut RemoteCallbacks); + let payload = &mut *(payload as *mut RemoteCallbacks<'_>); let callback = payload .credentials .as_mut() @@ -320,7 +320,7 @@ extern "C" fn transfer_progress_cb( payload: *mut c_void, ) -> c_int { let ok = panic::wrap(|| unsafe { - let payload = &mut *(payload as *mut RemoteCallbacks); + let payload = &mut *(payload as *mut RemoteCallbacks<'_>); let callback = match payload.progress { Some(ref mut c) => c, None => return true, @@ -337,7 +337,7 @@ extern "C" fn transfer_progress_cb( extern "C" fn sideband_progress_cb(str: *const c_char, len: c_int, payload: *mut c_void) -> c_int { let ok = panic::wrap(|| unsafe { - let payload = &mut *(payload as *mut RemoteCallbacks); + let payload = &mut *(payload as *mut RemoteCallbacks<'_>); let callback = match payload.sideband_progress { Some(ref mut c) => c, None => return true, @@ -359,7 +359,7 @@ extern "C" fn update_tips_cb( data: *mut c_void, ) -> c_int { let ok = panic::wrap(|| unsafe { - let payload = &mut *(data as *mut RemoteCallbacks); + let payload = &mut *(data as *mut RemoteCallbacks<'_>); let callback = match payload.update_tips { Some(ref mut c) => c, None => return true, @@ -383,7 +383,7 @@ extern "C" fn certificate_check_cb( data: *mut c_void, ) -> c_int { let ok = panic::wrap(|| unsafe { - let payload = &mut *(data as *mut RemoteCallbacks); + let payload = &mut *(data as *mut RemoteCallbacks<'_>); let callback = match payload.certificate_check { Some(ref mut c) => c, None => return true, @@ -405,7 +405,7 @@ extern "C" fn push_update_reference_cb( data: *mut c_void, ) -> c_int { panic::wrap(|| unsafe { - let payload = &mut *(data as *mut RemoteCallbacks); + let payload = &mut *(data as *mut RemoteCallbacks<'_>); let callback = match payload.push_update_reference { Some(ref mut c) => c, None => return 0, diff --git a/src/repo.rs b/src/repo.rs index 59cdf4f8a5..0f60f7acd5 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -226,7 +226,7 @@ impl Repository { } /// Attempt to wrap an object database as a repository. - pub fn from_odb(odb: Odb) -> Result { + pub fn from_odb(odb: Odb<'_>) -> Result { init(); let mut ret = ptr::null_mut(); unsafe { @@ -259,7 +259,7 @@ impl Repository { /// /// The resulting revision specification is returned, or an error is /// returned if one occurs. - pub fn revparse(&self, spec: &str) -> Result { + pub fn revparse(&self, spec: &str) -> Result, Error> { let mut raw = raw::git_revspec { from: ptr::null_mut(), to: ptr::null_mut(), @@ -276,7 +276,7 @@ impl Repository { } /// Find a single object, as specified by a revision string. - pub fn revparse_single(&self, spec: &str) -> Result { + pub fn revparse_single(&self, spec: &str) -> Result, Error> { let spec = CString::new(spec)?; let mut obj = ptr::null_mut(); unsafe { @@ -295,7 +295,7 @@ impl Repository { /// In some cases (`@{<-n>}` or `@{upstream}`), the expression /// may point to an intermediate reference. When such expressions are being /// passed in, this intermediate reference is returned. - pub fn revparse_ext(&self, spec: &str) -> Result<(Object, Option), Error> { + pub fn revparse_ext(&self, spec: &str) -> Result<(Object<'_>, Option>), Error> { let spec = CString::new(spec)?; let mut git_obj = ptr::null_mut(); let mut git_ref = ptr::null_mut(); @@ -458,7 +458,7 @@ impl Repository { /// List all remotes for a given repository pub fn remotes(&self) -> Result { let mut arr = raw::git_strarray { - strings: 0 as *mut *mut c_char, + strings: ptr::null_mut(), count: 0, }; unsafe { @@ -468,7 +468,7 @@ impl Repository { } /// Get the information for a particular remote - pub fn find_remote(&self, name: &str) -> Result { + pub fn find_remote(&self, name: &str) -> Result, Error> { let mut ret = ptr::null_mut(); let name = CString::new(name)?; unsafe { @@ -479,7 +479,7 @@ impl Repository { /// Add a remote with the default fetch refspec to the repository's /// configuration. - pub fn remote(&self, name: &str, url: &str) -> Result { + pub fn remote(&self, name: &str, url: &str) -> Result, Error> { let mut ret = ptr::null_mut(); let name = CString::new(name)?; let url = CString::new(url)?; @@ -494,7 +494,7 @@ impl Repository { /// Create a remote with the given url and refspec in memory. You can use /// this when you have a URL instead of a remote's name. Note that anonymous /// remotes cannot be converted to persisted remotes. - pub fn remote_anonymous(&self, url: &str) -> Result { + pub fn remote_anonymous(&self, url: &str) -> Result, Error> { let mut ret = ptr::null_mut(); let url = CString::new(url)?; unsafe { @@ -521,7 +521,7 @@ impl Repository { let new_name = CString::new(new_name)?; let mut problems = raw::git_strarray { count: 0, - strings: 0 as *mut *mut c_char, + strings: ptr::null_mut(), }; unsafe { try_call!(raw::git_remote_rename( @@ -621,9 +621,9 @@ impl Repository { /// The `checkout` options will only be used for a hard reset. pub fn reset( &self, - target: &Object, + target: &Object<'_>, kind: ResetType, - checkout: Option<&mut CheckoutBuilder>, + checkout: Option<&mut CheckoutBuilder<'_>>, ) -> Result<(), Error> { unsafe { let mut opts: raw::git_checkout_options = mem::zeroed(); @@ -647,7 +647,7 @@ impl Repository { /// /// Passing a `None` target will result in removing entries in the index /// matching the provided pathspecs. - pub fn reset_default(&self, target: Option<&Object>, paths: I) -> Result<(), Error> + pub fn reset_default(&self, target: Option<&Object<'_>>, paths: I) -> Result<(), Error> where T: IntoCString, I: IntoIterator, @@ -661,7 +661,7 @@ impl Repository { } /// Retrieve and resolve the reference pointed at by HEAD. - pub fn head(&self) -> Result { + pub fn head(&self) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_repository_head(&mut ret, self.raw)); @@ -722,7 +722,7 @@ impl Repository { } /// Create an iterator for the repo's references - pub fn references(&self) -> Result { + pub fn references(&self) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_reference_iterator_new(&mut ret, self.raw)); @@ -732,7 +732,7 @@ impl Repository { /// Create an iterator for the repo's references that match the specified /// glob - pub fn references_glob(&self, glob: &str) -> Result { + pub fn references_glob(&self, glob: &str) -> Result, Error> { let mut ret = ptr::null_mut(); let glob = CString::new(glob)?; unsafe { @@ -745,7 +745,7 @@ impl Repository { } /// Load all submodules for this repository and return them. - pub fn submodules(&self) -> Result, Error> { + pub fn submodules(&self) -> Result>, Error> { struct Data<'a, 'b: 'a> { repo: &'b Repository, ret: &'a mut Vec>, @@ -772,7 +772,7 @@ impl Repository { data: *mut c_void, ) -> c_int { unsafe { - let data = &mut *(data as *mut Data); + let data = &mut *(data as *mut Data<'_, '_>); let mut raw = ptr::null_mut(); let rc = raw::git_submodule_lookup(&mut raw, data.repo.raw(), name); assert_eq!(rc, 0); @@ -788,7 +788,7 @@ impl Repository { /// status, then the results from rename detection (if you enable it) may /// not be accurate. To do rename detection properly, this must be called /// with no pathspec so that all files can be considered. - pub fn statuses(&self, options: Option<&mut StatusOptions>) -> Result { + pub fn statuses(&self, options: Option<&mut StatusOptions>) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_status_list_new( @@ -849,7 +849,7 @@ impl Repository { } /// Create an iterator which loops over the requested branches. - pub fn branches(&self, filter: Option) -> Result { + pub fn branches(&self, filter: Option) -> Result, Error> { let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_branch_iterator_new(&mut raw, self.raw(), filter)); @@ -937,7 +937,7 @@ impl Repository { /// If the `hintpath` parameter is filled, it will be used to determine /// what git filters should be applied to the object before it is written /// to the object database. - pub fn blob_writer(&self, hintpath: Option<&Path>) -> Result { + pub fn blob_writer(&self, hintpath: Option<&Path>) -> Result, Error> { let path_str = match hintpath { Some(path) => Some(path.into_c_string()?), None => None, @@ -954,7 +954,7 @@ impl Repository { } /// Lookup a reference to one of the objects in a repository. - pub fn find_blob(&self, oid: Oid) -> Result { + pub fn find_blob(&self, oid: Oid) -> Result, Error> { let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_blob_lookup(&mut raw, self.raw(), oid.raw())); @@ -963,7 +963,7 @@ impl Repository { } /// Get the object database for this repository - pub fn odb(&self) -> Result { + pub fn odb(&self) -> Result, Error> { let mut odb = ptr::null_mut(); unsafe { try_call!(raw::git_repository_odb(&mut odb, self.raw())); @@ -976,7 +976,12 @@ impl Repository { /// A new direct reference will be created pointing to this target commit. /// If `force` is true and a reference already exists with the given name, /// it'll be replaced. - pub fn branch(&self, branch_name: &str, target: &Commit, force: bool) -> Result { + pub fn branch( + &self, + branch_name: &str, + target: &Commit<'_>, + force: bool, + ) -> Result, Error> { let branch_name = CString::new(branch_name)?; let mut raw = ptr::null_mut(); unsafe { @@ -992,7 +997,7 @@ impl Repository { } /// Lookup a branch by its name in a repository. - pub fn find_branch(&self, name: &str, branch_type: BranchType) -> Result { + pub fn find_branch(&self, name: &str, branch_type: BranchType) -> Result, Error> { let name = CString::new(name)?; let mut ret = ptr::null_mut(); unsafe { @@ -1017,11 +1022,11 @@ impl Repository { pub fn commit( &self, update_ref: Option<&str>, - author: &Signature, - committer: &Signature, + author: &Signature<'_>, + committer: &Signature<'_>, message: &str, - tree: &Tree, - parents: &[&Commit], + tree: &Tree<'_>, + parents: &[&Commit<'_>], ) -> Result { let update_ref = crate::opt_cstr(update_ref)?; let mut parent_ptrs = parents @@ -1108,7 +1113,7 @@ impl Repository { } /// Lookup a reference to one of the commits in a repository. - pub fn find_commit(&self, oid: Oid) -> Result { + pub fn find_commit(&self, oid: Oid) -> Result, Error> { let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_commit_lookup(&mut raw, self.raw(), oid.raw())); @@ -1117,9 +1122,9 @@ impl Repository { } /// Creates a `AnnotatedCommit` from the given commit id. - pub fn find_annotated_commit(&self, id: Oid) -> Result { + pub fn find_annotated_commit(&self, id: Oid) -> Result, Error> { unsafe { - let mut raw = 0 as *mut raw::git_annotated_commit; + let mut raw = ptr::null_mut(); try_call!(raw::git_annotated_commit_lookup( &mut raw, self.raw(), @@ -1130,7 +1135,7 @@ impl Repository { } /// Lookup a reference to one of the objects in a repository. - pub fn find_object(&self, oid: Oid, kind: Option) -> Result { + pub fn find_object(&self, oid: Oid, kind: Option) -> Result, Error> { let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_object_lookup( @@ -1154,7 +1159,7 @@ impl Repository { id: Oid, force: bool, log_message: &str, - ) -> Result { + ) -> Result, Error> { let name = CString::new(name)?; let log_message = CString::new(log_message)?; let mut raw = ptr::null_mut(); @@ -1208,7 +1213,7 @@ impl Repository { force: bool, current_id: Oid, log_message: &str, - ) -> Result { + ) -> Result, Error> { let name = CString::new(name)?; let log_message = CString::new(log_message)?; let mut raw = ptr::null_mut(); @@ -1237,7 +1242,7 @@ impl Repository { target: &str, force: bool, log_message: &str, - ) -> Result { + ) -> Result, Error> { let name = CString::new(name)?; let target = CString::new(target)?; let log_message = CString::new(log_message)?; @@ -1271,7 +1276,7 @@ impl Repository { force: bool, current_value: &str, log_message: &str, - ) -> Result { + ) -> Result, Error> { let name = CString::new(name)?; let target = CString::new(target)?; let current_value = CString::new(current_value)?; @@ -1292,7 +1297,7 @@ impl Repository { } /// Lookup a reference to one of the objects in a repository. - pub fn find_reference(&self, name: &str) -> Result { + pub fn find_reference(&self, name: &str) -> Result, Error> { let name = CString::new(name)?; let mut raw = ptr::null_mut(); unsafe { @@ -1305,7 +1310,7 @@ impl Repository { /// `Repository::find_reference` with teeth; give the method your reference in /// human-readable format e.g. 'master' instead of 'refs/heads/master', and it /// will do-what-you-mean, returning the `Reference`. - pub fn resolve_reference_from_short_name(&self, refname: &str) -> Result { + pub fn resolve_reference_from_short_name(&self, refname: &str) -> Result, Error> { let refname = CString::new(refname)?; let mut raw = ptr::null_mut(); unsafe { @@ -1333,8 +1338,8 @@ impl Repository { /// Creates a git_annotated_commit from the given reference. pub fn reference_to_annotated_commit( &self, - reference: &Reference, - ) -> Result { + reference: &Reference<'_>, + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_annotated_commit_from_ref( @@ -1372,7 +1377,12 @@ impl Repository { /// the submodule repo and perform the clone step as needed. Lastly, call /// `add_finalize()` to wrap up adding the new submodule and `.gitmodules` /// to the index to be ready to commit. - pub fn submodule(&self, url: &str, path: &Path, use_gitlink: bool) -> Result { + pub fn submodule( + &self, + url: &str, + path: &Path, + use_gitlink: bool, + ) -> Result, Error> { let url = CString::new(url)?; let path = path.into_c_string()?; let mut raw = ptr::null_mut(); @@ -1392,7 +1402,7 @@ impl Repository { /// /// Given either the submodule name or path (they are usually the same), /// this returns a structure describing the submodule. - pub fn find_submodule(&self, name: &str) -> Result { + pub fn find_submodule(&self, name: &str) -> Result, Error> { let name = CString::new(name)?; let mut raw = ptr::null_mut(); unsafe { @@ -1419,7 +1429,7 @@ impl Repository { } /// Lookup a reference to one of the objects in a repository. - pub fn find_tree(&self, oid: Oid) -> Result { + pub fn find_tree(&self, oid: Oid) -> Result, Error> { let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_tree_lookup(&mut raw, self.raw(), oid.raw())); @@ -1432,7 +1442,7 @@ impl Repository { /// /// The tree builder can be used to create or modify trees in memory and /// write them as tree objects to the database. - pub fn treebuilder(&self, tree: Option<&Tree>) -> Result { + pub fn treebuilder(&self, tree: Option<&Tree<'_>>) -> Result, Error> { unsafe { let mut ret = ptr::null_mut(); let tree = match tree { @@ -1458,8 +1468,8 @@ impl Repository { pub fn tag( &self, name: &str, - target: &Object, - tagger: &Signature, + target: &Object<'_>, + tagger: &Signature<'_>, message: &str, force: bool, ) -> Result { @@ -1487,7 +1497,12 @@ impl Repository { /// A new direct reference will be created pointing to this target object. /// If force is true and a reference already exists with the given name, /// it'll be replaced. - pub fn tag_lightweight(&self, name: &str, target: &Object, force: bool) -> Result { + pub fn tag_lightweight( + &self, + name: &str, + target: &Object<'_>, + force: bool, + ) -> Result { let name = CString::new(name)?; let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], @@ -1505,7 +1520,7 @@ impl Repository { } /// Lookup a tag object from the repository. - pub fn find_tag(&self, id: Oid) -> Result { + pub fn find_tag(&self, id: Oid) -> Result, Error> { let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_tag_lookup(&mut raw, self.raw, id.raw())); @@ -1530,7 +1545,7 @@ impl Repository { /// An optional fnmatch pattern can also be specified. pub fn tag_names(&self, pattern: Option<&str>) -> Result { let mut arr = raw::git_strarray { - strings: 0 as *mut *mut c_char, + strings: ptr::null_mut(), count: 0, }; unsafe { @@ -1549,7 +1564,7 @@ impl Repository { /// Updates files in the index and the working tree to match the content of /// the commit pointed at by HEAD. - pub fn checkout_head(&self, opts: Option<&mut CheckoutBuilder>) -> Result<(), Error> { + pub fn checkout_head(&self, opts: Option<&mut CheckoutBuilder<'_>>) -> Result<(), Error> { unsafe { let mut raw_opts = mem::zeroed(); try_call!(raw::git_checkout_init_options( @@ -1571,7 +1586,7 @@ impl Repository { pub fn checkout_index( &self, index: Option<&mut Index>, - opts: Option<&mut CheckoutBuilder>, + opts: Option<&mut CheckoutBuilder<'_>>, ) -> Result<(), Error> { unsafe { let mut raw_opts = mem::zeroed(); @@ -1596,8 +1611,8 @@ impl Repository { /// tree pointed at by the treeish. pub fn checkout_tree( &self, - treeish: &Object, - opts: Option<&mut CheckoutBuilder>, + treeish: &Object<'_>, + opts: Option<&mut CheckoutBuilder<'_>>, ) -> Result<(), Error> { unsafe { let mut raw_opts = mem::zeroed(); @@ -1624,9 +1639,9 @@ impl Repository { /// clear this state by calling git_repository_state_cleanup(). pub fn merge( &self, - annotated_commits: &[&AnnotatedCommit], + annotated_commits: &[&AnnotatedCommit<'_>], merge_opts: Option<&mut MergeOptions>, - checkout_opts: Option<&mut CheckoutBuilder>, + checkout_opts: Option<&mut CheckoutBuilder<'_>>, ) -> Result<(), Error> { unsafe { let mut raw_checkout_opts = mem::zeroed(); @@ -1660,8 +1675,8 @@ impl Repository { /// should resolve any conflicts that arose as part of the merge. pub fn merge_commits( &self, - our_commit: &Commit, - their_commit: &Commit, + our_commit: &Commit<'_>, + their_commit: &Commit<'_>, opts: Option<&MergeOptions>, ) -> Result { let mut raw = ptr::null_mut(); @@ -1683,9 +1698,9 @@ impl Repository { /// should resolve any conflicts that arose as part of the merge. pub fn merge_trees( &self, - ancestor_tree: &Tree, - our_tree: &Tree, - their_tree: &Tree, + ancestor_tree: &Tree<'_>, + our_tree: &Tree<'_>, + their_tree: &Tree<'_>, opts: Option<&MergeOptions>, ) -> Result { let mut raw = ptr::null_mut(); @@ -1715,7 +1730,7 @@ impl Repository { /// merging them into the HEAD of the repository. pub fn merge_analysis( &self, - their_heads: &[&AnnotatedCommit], + their_heads: &[&AnnotatedCommit<'_>], ) -> Result<(MergeAnalysis, MergePreference), Error> { unsafe { let mut raw_merge_analysis = 0 as raw::git_merge_analysis_t; @@ -1743,11 +1758,11 @@ impl Repository { /// call `next()`. pub fn rebase( &self, - branch: Option<&AnnotatedCommit>, - upstream: Option<&AnnotatedCommit>, - onto: Option<&AnnotatedCommit>, - opts: Option<&mut RebaseOptions>, - ) -> Result { + branch: Option<&AnnotatedCommit<'_>>, + upstream: Option<&AnnotatedCommit<'_>>, + onto: Option<&AnnotatedCommit<'_>>, + opts: Option<&mut RebaseOptions<'_>>, + ) -> Result, Error> { let mut rebase: *mut raw::git_rebase = ptr::null_mut(); unsafe { try_call!(raw::git_rebase_init( @@ -1765,7 +1780,7 @@ impl Repository { /// Opens an existing rebase that was previously started by either an /// invocation of `rebase()` or by another client. - pub fn open_rebase(&self, opts: Option<&mut RebaseOptions>) -> Result { + pub fn open_rebase(&self, opts: Option<&mut RebaseOptions<'_>>) -> Result, Error> { let mut rebase: *mut raw::git_rebase = ptr::null_mut(); unsafe { try_call!(raw::git_rebase_open( @@ -1784,8 +1799,8 @@ impl Repository { /// previous notes are overwritten. pub fn note( &self, - author: &Signature, - committer: &Signature, + author: &Signature<'_>, + committer: &Signature<'_>, notes_ref: Option<&str>, oid: Oid, note: &str, @@ -1828,7 +1843,7 @@ impl Repository { /// The iterator returned yields pairs of (Oid, Oid) where the first element /// is the id of the note and the second id is the id the note is /// annotating. - pub fn notes(&self, notes_ref: Option<&str>) -> Result { + pub fn notes(&self, notes_ref: Option<&str>) -> Result, Error> { let notes_ref = crate::opt_cstr(notes_ref)?; let mut ret = ptr::null_mut(); unsafe { @@ -1843,7 +1858,7 @@ impl Repository { /// defaulting to "refs/notes/commits". /// /// The id specified is the Oid of the git object to read the note from. - pub fn find_note(&self, notes_ref: Option<&str>, id: Oid) -> Result { + pub fn find_note(&self, notes_ref: Option<&str>, id: Oid) -> Result, Error> { let notes_ref = crate::opt_cstr(notes_ref)?; let mut ret = ptr::null_mut(); unsafe { @@ -1862,8 +1877,8 @@ impl Repository { &self, id: Oid, notes_ref: Option<&str>, - author: &Signature, - committer: &Signature, + author: &Signature<'_>, + committer: &Signature<'_>, ) -> Result<(), Error> { let notes_ref = crate::opt_cstr(notes_ref)?; unsafe { @@ -1879,7 +1894,7 @@ impl Repository { } /// Create a revwalk that can be used to traverse the commit graph. - pub fn revwalk(&self) -> Result { + pub fn revwalk(&self) -> Result, Error> { let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_revwalk_new(&mut raw, self.raw())); @@ -1888,7 +1903,11 @@ impl Repository { } /// Get the blame for a single file. - pub fn blame_file(&self, path: &Path, opts: Option<&mut BlameOptions>) -> Result { + pub fn blame_file( + &self, + path: &Path, + opts: Option<&mut BlameOptions>, + ) -> Result, Error> { let path = path.into_c_string()?; let mut raw = ptr::null_mut(); @@ -2024,7 +2043,7 @@ impl Repository { /// Performs a describe operation on the current commit and the worktree. /// After performing a describe on HEAD, a status is run and description is /// considered to be dirty if there are. - pub fn describe(&self, opts: &DescribeOptions) -> Result { + pub fn describe(&self, opts: &DescribeOptions) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_describe_workdir(&mut ret, self.raw, opts.raw())); @@ -2042,10 +2061,10 @@ impl Repository { /// `None` for both the `old_tree` and `new_tree`. pub fn diff_tree_to_tree( &self, - old_tree: Option<&Tree>, - new_tree: Option<&Tree>, + old_tree: Option<&Tree<'_>>, + new_tree: Option<&Tree<'_>>, opts: Option<&mut DiffOptions>, - ) -> Result { + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_tree_to_tree( @@ -2074,10 +2093,10 @@ impl Repository { /// If the tree is `None`, then it is considered an empty tree. pub fn diff_tree_to_index( &self, - old_tree: Option<&Tree>, + old_tree: Option<&Tree<'_>>, index: Option<&Index>, opts: Option<&mut DiffOptions>, - ) -> Result { + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_tree_to_index( @@ -2100,7 +2119,7 @@ impl Repository { old_index: &Index, new_index: &Index, opts: Option<&mut DiffOptions>, - ) -> Result { + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_index_to_index( @@ -2131,7 +2150,7 @@ impl Repository { &self, index: Option<&Index>, opts: Option<&mut DiffOptions>, - ) -> Result { + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_index_to_workdir( @@ -2164,9 +2183,9 @@ impl Repository { /// If `None` is passed for `tree`, then an empty tree is used. pub fn diff_tree_to_workdir( &self, - old_tree: Option<&Tree>, + old_tree: Option<&Tree<'_>>, opts: Option<&mut DiffOptions>, - ) -> Result { + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_tree_to_workdir( @@ -2187,9 +2206,9 @@ impl Repository { /// single diff that includes staged deleted, etc. pub fn diff_tree_to_workdir_with_index( &self, - old_tree: Option<&Tree>, + old_tree: Option<&Tree<'_>>, opts: Option<&mut DiffOptions>, - ) -> Result { + ) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_diff_tree_to_workdir_with_index( @@ -2203,7 +2222,7 @@ impl Repository { } /// Create a PackBuilder - pub fn packbuilder(&self) -> Result { + pub fn packbuilder(&self) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_packbuilder_new(&mut ret, self.raw())); @@ -2214,7 +2233,7 @@ impl Repository { /// Save the local modifications to a new stash. pub fn stash_save( &mut self, - stasher: &Signature, + stasher: &Signature<'_>, message: &str, flags: Option, ) -> Result { @@ -2239,7 +2258,7 @@ impl Repository { pub fn stash_apply( &mut self, index: usize, - opts: Option<&mut StashApplyOptions>, + opts: Option<&mut StashApplyOptions<'_>>, ) -> Result<(), Error> { unsafe { let opts = opts.map(|opts| opts.raw()); @@ -2280,7 +2299,7 @@ impl Repository { pub fn stash_pop( &mut self, index: usize, - opts: Option<&mut StashApplyOptions>, + opts: Option<&mut StashApplyOptions<'_>>, ) -> Result<(), Error> { unsafe { let opts = opts.map(|opts| opts.raw()); diff --git a/src/signature.rs b/src/signature.rs index e0beaa60af..5677b7b577 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -148,7 +148,7 @@ impl<'a> Drop for Signature<'a> { } impl<'a> fmt::Display for Signature<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "{} <{}>", diff --git a/src/stash.rs b/src/stash.rs index 280d164132..465f63eb0d 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -94,7 +94,7 @@ pub extern "C" fn stash_cb( payload: *mut c_void, ) -> c_int { panic::wrap(|| unsafe { - let mut data = &mut *(payload as *mut StashCbData); + let mut data = &mut *(payload as *mut StashCbData<'_>); let res = { let mut callback = &mut data.callback; callback( @@ -134,7 +134,7 @@ extern "C" fn stash_apply_progress_cb( payload: *mut c_void, ) -> c_int { panic::wrap(|| unsafe { - let mut options = &mut *(payload as *mut StashApplyOptions); + let mut options = &mut *(payload as *mut StashApplyOptions<'_>); let res = { let mut callback = options.progress.as_mut().unwrap(); callback(convert_progress(progress)) diff --git a/src/status.rs b/src/status.rs index 4ea28be575..25b57327af 100644 --- a/src/status.rs +++ b/src/status.rs @@ -231,7 +231,7 @@ impl<'repo> Statuses<'repo> { /// Gets a status entry from this list at the specified index. /// /// Returns `None` if the index is out of bounds. - pub fn get(&self, index: usize) -> Option { + pub fn get(&self, index: usize) -> Option> { unsafe { let p = raw::git_status_byindex(self.raw, index as size_t); Binding::from_raw_opt(p) @@ -252,7 +252,7 @@ impl<'repo> Statuses<'repo> { } /// Returns an iterator over the statuses in this list. - pub fn iter(&self) -> StatusIter { + pub fn iter(&self) -> StatusIter<'_> { StatusIter { statuses: self, range: 0..self.len(), diff --git a/src/string_array.rs b/src/string_array.rs index 1bb40c24ea..b924e4033a 100644 --- a/src/string_array.rs +++ b/src/string_array.rs @@ -37,7 +37,7 @@ impl StringArray { pub fn get_bytes(&self, i: usize) -> Option<&[u8]> { if i < self.raw.count as usize { unsafe { - let ptr = *self.raw.strings.offset(i as isize) as *const _; + let ptr = *self.raw.strings.add(i) as *const _; Some(crate::opt_bytes(self, ptr).unwrap()) } } else { @@ -49,7 +49,7 @@ impl StringArray { /// /// The iterator yields `Option<&str>` as it is unknown whether the contents /// are utf-8 or not. - pub fn iter(&self) -> Iter { + pub fn iter(&self) -> Iter<'_> { Iter { range: 0..self.len(), arr: self, @@ -58,7 +58,7 @@ impl StringArray { /// Returns an iterator over the strings contained within this array, /// yielding byte slices. - pub fn iter_bytes(&self) -> IterBytes { + pub fn iter_bytes(&self) -> IterBytes<'_> { IterBytes { range: 0..self.len(), arr: self, diff --git a/src/submodule.rs b/src/submodule.rs index 4112210405..90ea1be10f 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -186,7 +186,7 @@ impl<'repo> Submodule<'repo> { pub fn update( &mut self, init: bool, - opts: Option<&mut SubmoduleUpdateOptions>, + opts: Option<&mut SubmoduleUpdateOptions<'_>>, ) -> Result<(), Error> { unsafe { let mut raw_opts = opts.map(|o| o.raw()); diff --git a/src/tag.rs b/src/tag.rs index 5a02b43b26..697e4f2757 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -58,7 +58,7 @@ impl<'repo> Tag<'repo> { /// Get the tagger (author) of a tag /// /// If the author is unspecified, then `None` is returned. - pub fn tagger(&self) -> Option { + pub fn tagger(&self) -> Option> { unsafe { let ptr = raw::git_tag_tagger(&*self.raw); if ptr.is_null() { @@ -98,13 +98,13 @@ impl<'repo> Tag<'repo> { /// Consumes Tag to be returned as an `Object` pub fn into_object(self) -> Object<'repo> { - assert_eq!(mem::size_of_val(&self), mem::size_of::()); + assert_eq!(mem::size_of_val(&self), mem::size_of::>()); unsafe { mem::transmute(self) } } } impl<'repo> std::fmt::Debug for Tag<'repo> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { let mut ds = f.debug_struct("Tag"); if let Some(name) = self.name() { ds.field("name", &name); diff --git a/src/transport.rs b/src/transport.rs index b19d764e9d..b5938d3aa8 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -73,7 +73,7 @@ pub trait SmartSubtransportStream: Read + Write + Send + 'static {} impl SmartSubtransportStream for T {} -type TransportFactory = dyn Fn(&Remote) -> Result + Send + Sync + 'static; +type TransportFactory = dyn Fn(&Remote<'_>) -> Result + Send + Sync + 'static; /// Boxed data payload used for registering new transports. /// @@ -105,7 +105,7 @@ struct RawSmartSubtransportStream { /// to creation of other transports. pub unsafe fn register(prefix: &str, factory: F) -> Result<(), Error> where - F: Fn(&Remote) -> Result + Send + Sync + 'static, + F: Fn(&Remote<'_>) -> Result + Send + Sync + 'static, { crate::init(); let mut data = Box::new(TransportData { @@ -133,7 +133,7 @@ impl Transport { /// /// The `rpc` argument is `true` if the protocol is stateless, false /// otherwise. For example `http://` is stateless but `git://` is not. - pub fn smart(remote: &Remote, rpc: bool, subtransport: S) -> Result + pub fn smart(remote: &Remote<'_>, rpc: bool, subtransport: S) -> Result where S: SmartSubtransport, { diff --git a/src/tree.rs b/src/tree.rs index 6035f63310..11db0cc9f0 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -87,7 +87,7 @@ impl<'repo> Tree<'repo> { } /// Returns an iterator over the entries in this tree. - pub fn iter(&self) -> TreeIter { + pub fn iter(&self) -> TreeIter<'_> { TreeIter { range: 0..self.len(), tree: self, @@ -118,11 +118,11 @@ impl<'repo> Tree<'repo> { /// [1]: https://libgit2.org/libgit2/#HEAD/group/tree/git_tree_walk pub fn walk(&self, mode: TreeWalkMode, mut callback: C) -> Result<(), Error> where - C: FnMut(&str, &TreeEntry) -> T, + C: FnMut(&str, &TreeEntry<'_>) -> T, T: Into, { #[allow(unused)] - struct TreeWalkCbData<'a, T: 'a> { + struct TreeWalkCbData<'a, T> { pub callback: &'a mut TreeWalkCb<'a, T>, } unsafe { @@ -140,7 +140,7 @@ impl<'repo> Tree<'repo> { } /// Lookup a tree entry by SHA value. - pub fn get_id(&self, id: Oid) -> Option { + pub fn get_id(&self, id: Oid) -> Option> { unsafe { let ptr = raw::git_tree_entry_byid(&*self.raw(), &*id.raw()); if ptr.is_null() { @@ -152,7 +152,7 @@ impl<'repo> Tree<'repo> { } /// Lookup a tree entry by its position in the tree - pub fn get(&self, n: usize) -> Option { + pub fn get(&self, n: usize) -> Option> { unsafe { let ptr = raw::git_tree_entry_byindex(&*self.raw(), n as libc::size_t); if ptr.is_null() { @@ -164,7 +164,7 @@ impl<'repo> Tree<'repo> { } /// Lookup a tree entry by its filename - pub fn get_name(&self, filename: &str) -> Option { + pub fn get_name(&self, filename: &str) -> Option> { let filename = CString::new(filename).unwrap(); unsafe { let ptr = call!(raw::git_tree_entry_byname(&*self.raw(), filename)); @@ -194,12 +194,12 @@ impl<'repo> Tree<'repo> { /// Consumes Commit to be returned as an `Object` pub fn into_object(self) -> Object<'repo> { - assert_eq!(mem::size_of_val(&self), mem::size_of::()); + assert_eq!(mem::size_of_val(&self), mem::size_of::>()); unsafe { mem::transmute(self) } } } -type TreeWalkCb<'a, T> = dyn FnMut(&str, &TreeEntry) -> T + 'a; +type TreeWalkCb<'a, T> = dyn FnMut(&str, &TreeEntry<'_>) -> T + 'a; extern "C" fn treewalk_cb>( root: *const c_char, @@ -212,7 +212,7 @@ extern "C" fn treewalk_cb>( _ => return -1, }; let entry = entry_from_raw_const(entry); - let payload = payload as *mut &mut TreeWalkCb; + let payload = payload as *mut &mut TreeWalkCb<'_, T>; (*payload)(root, &entry).into() }) { Some(value) => value, @@ -235,7 +235,7 @@ impl<'repo> Binding for Tree<'repo> { } impl<'repo> std::fmt::Debug for Tree<'repo> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { f.debug_struct("Tree").field("id", &self.id()).finish() } } diff --git a/src/treebuilder.rs b/src/treebuilder.rs index 16f60123ce..4eec55c10b 100644 --- a/src/treebuilder.rs +++ b/src/treebuilder.rs @@ -29,7 +29,7 @@ impl<'repo> TreeBuilder<'repo> { } /// Get en entry from the builder from its filename - pub fn get

(&self, filename: P) -> Result, Error> + pub fn get

(&self, filename: P) -> Result>, Error> where P: IntoCString, { @@ -56,7 +56,7 @@ impl<'repo> TreeBuilder<'repo> { filename: P, oid: Oid, filemode: i32, - ) -> Result { + ) -> Result, Error> { let filename = filename.into_c_string()?; let filemode = filemode as raw::git_filemode_t; @@ -88,9 +88,9 @@ impl<'repo> TreeBuilder<'repo> { /// that this behavior is different from the libgit2 C interface. pub fn filter(&mut self, mut filter: F) where - F: FnMut(&TreeEntry) -> bool, + F: FnMut(&TreeEntry<'_>) -> bool, { - let mut cb: &mut FilterCb = &mut filter; + let mut cb: &mut FilterCb<'_> = &mut filter; let ptr = &mut cb as *mut _; unsafe { raw::git_treebuilder_filter(self.raw, filter_cb, ptr as *mut _); @@ -111,7 +111,7 @@ impl<'repo> TreeBuilder<'repo> { } } -type FilterCb<'a> = dyn FnMut(&TreeEntry) -> bool + 'a; +type FilterCb<'a> = dyn FnMut(&TreeEntry<'_>) -> bool + 'a; extern "C" fn filter_cb(entry: *const raw::git_tree_entry, payload: *mut c_void) -> c_int { let ret = panic::wrap(|| unsafe { @@ -120,7 +120,7 @@ extern "C" fn filter_cb(entry: *const raw::git_tree_entry, payload: *mut c_void) true } else { let entry = tree::entry_from_raw_const(entry); - let payload = payload as *mut &mut FilterCb; + let payload = payload as *mut &mut FilterCb<'_>; (*payload)(&entry) } }); diff --git a/systest/build.rs b/systest/build.rs index 3881fb66fc..c2b0c6bc0c 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -1,5 +1,3 @@ -extern crate ctest; - use std::env; use std::path::PathBuf; diff --git a/systest/src/main.rs b/systest/src/main.rs index bb7d91be5b..6193730dd8 100644 --- a/systest/src/main.rs +++ b/systest/src/main.rs @@ -1,8 +1,5 @@ #![allow(bad_style, improper_ctypes)] -extern crate libc; -extern crate libgit2_sys; - use libc::*; use libgit2_sys::*; From 2241f53e3024c98db695f1829b948db45ff063dd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 7 Jun 2019 10:20:25 -0700 Subject: [PATCH 356/860] Relax credential helper checks Instead of looking for an absolute path and pattern matching to avoid using `git credential-*` instead just look directly for `/` or `\`. This'll handle a new case of `C:/foo/bar` on Windows where previously only `C:\foo\bar` worked. --- src/cred.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cred.rs b/src/cred.rs index ad5e86b03e..c217872f11 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -269,7 +269,7 @@ impl CredentialHelper { if cmd.starts_with('!') { self.commands.push(cmd[1..].to_string()); - } else if cmd.starts_with('/') || cmd.starts_with('\\') || cmd[1..].starts_with(":\\") { + } else if cmd.contains("/") || cmd.contains("\\") { self.commands.push(cmd.to_string()); } else { self.commands.push(format!("git credential-{}", cmd)); @@ -347,6 +347,7 @@ impl CredentialHelper { .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()); + debug!("executing credential helper {:?}", c); let mut p = match c.spawn() { Ok(p) => p, Err(e) => { @@ -360,6 +361,7 @@ impl CredentialHelper { .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()); + debug!("executing credential helper {:?}", c); match c.spawn() { Ok(p) => p, Err(e) => { From 1c6952bd8a77a222cc14576c317927a851ece542 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 7 Jun 2019 11:02:42 -0700 Subject: [PATCH 357/860] Bump to 0.9.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e075984e99..259920d26e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.9.0" +version = "0.9.1" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From e39e7662549fee064f8291d925daebad4f775adb Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 7 Jun 2019 13:32:46 -0700 Subject: [PATCH 358/860] Update versions in html_root_url. --- git2-curl/src/lib.rs | 2 +- libgit2-sys/lib.rs | 2 +- src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 687ec7e735..3800398fe9 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -15,7 +15,7 @@ //! > **NOTE**: At this time this crate likely does not support a `git push` //! > operation, only clones. -#![doc(html_root_url = "http://alexcrichton.com/git2-rs")] +#![doc(html_root_url = "https://docs.rs/git2-curl/0.10")] #![deny(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 0444d83d81..e473f4f1d4 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url = "http://alexcrichton.com/git2-rs")] +#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.8")] #![allow(non_camel_case_types, unused_extern_crates)] // This is required to link libz when libssh2-sys is not included. diff --git a/src/lib.rs b/src/lib.rs index 8f932a0796..17ffe94eeb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,7 +63,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.6")] +#![doc(html_root_url = "https://docs.rs/git2/0.9")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] From 60c0a672fbda2ed0c6e5ce71a2f100aa46218ef1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 17 Jun 2019 08:20:54 -0700 Subject: [PATCH 359/860] Define more constants when compiling for Windows Targeted at fixing [this] issue it looks like libgit2's own build system passes these defines so let's mirror that. [this]: https://github.com/rust-lang/rust/pull/61771#issuecomment-502321507 --- libgit2-sys/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index e622f2cde8..4586d56318 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -59,6 +59,8 @@ fn main() { if windows { add_c_files(&mut cfg, "libgit2/src/win32".as_ref()); cfg.define("STRSAFE_NO_DEPRECATE", None); + cfg.define("WIN32", None); + cfg.define("_WIN32_WINNT", Some("0x0600")); // libgit2's build system claims that forks like mingw-w64 of MinGW // still want this define to use C99 stdio functions automatically. From c410f8df1e02914fb9a9435dc70ce97d41f186b2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 17 Jun 2019 08:22:03 -0700 Subject: [PATCH 360/860] Bump libgit2-sys to 0.8.1 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 9cc8813396..5e0649a56c 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.8.0" +version = "0.8.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From b8060164267b4a14c86477ed5fe7039a737b25b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Wed, 26 Jun 2019 11:28:09 +0200 Subject: [PATCH 361/860] Update versions in readme The version of the git2 crate mentioned in the readme as well as the currently used version of libgit2 were outdated. This patch brings both up-to-date. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ee9aa8b3ba..f34b740aa4 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ libgit2 bindings for Rust ```toml [dependencies] -git2 = "0.8" +git2 = "0.9" ``` ## Rust version requirements @@ -19,7 +19,7 @@ version of Rust known to pass tests. ## Version of libgit2 -Currently this library requires libgit2 0.28.0. The source for libgit2 is +Currently this library requires libgit2 0.28.2. The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. From 9c8351aeeeac7dfd1e0e381fc0b283783343e79b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Jul 2019 09:19:14 -0700 Subject: [PATCH 362/860] Fix compat with latest `ctest` --- systest/Cargo.toml | 2 +- systest/build.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/systest/Cargo.toml b/systest/Cargo.toml index a95c28fb85..9047e7f307 100644 --- a/systest/Cargo.toml +++ b/systest/Cargo.toml @@ -10,4 +10,4 @@ libgit2-sys = { path = "../libgit2-sys", features = ['https', 'ssh'] } libc = "0.2" [build-dependencies] -ctest = "0.2" +ctest = "0.2.17" diff --git a/systest/build.rs b/systest/build.rs index c2b0c6bc0c..57bb7c3bd8 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -35,6 +35,10 @@ fn main() { _ => false, } }); + + // not entirely sure why this is failing... + cfg.skip_roundtrip(|t| t == "git_clone_options" || t == "git_submodule_update_options"); + cfg.skip_type(|t| t == "__enum_ty"); cfg.generate("../libgit2-sys/lib.rs", "all.rs"); } From e7f67a86b2e7ac844ba1b69e294958fe923496f5 Mon Sep 17 00:00:00 2001 From: Vincent Thiberville Date: Tue, 25 Jun 2019 09:36:14 +0200 Subject: [PATCH 363/860] Add cherrypick method on Repository object Add wrappers to: * build a git_cherrypick_options object and modify it * call git_cherrypick A test is added for the cherrypick method (no test for the cherrypick options however). --- libgit2-sys/lib.rs | 17 +++++++++ src/cherrypick.rs | 63 +++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ src/repo.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+) create mode 100644 src/cherrypick.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index e473f4f1d4..5d51e4b4bc 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1567,6 +1567,14 @@ pub struct git_rebase_operation { pub exec: *const c_char, } +#[repr(C)] +pub struct git_cherrypick_options { + pub version: c_uint, + pub mainline: c_uint, + pub merge_opts: git_merge_options, + pub checkout_opts: git_checkout_options, +} + extern "C" { // threads pub fn git_libgit2_init() -> c_int; @@ -3343,6 +3351,15 @@ extern "C" { pub fn git_rebase_abort(rebase: *mut git_rebase) -> c_int; pub fn git_rebase_finish(rebase: *mut git_rebase, signature: *const git_signature) -> c_int; pub fn git_rebase_free(rebase: *mut git_rebase); + + // cherrypick + pub fn git_cherrypick_init_options(opts: *mut git_cherrypick_options, version: c_uint) + -> c_int; + pub fn git_cherrypick( + repo: *mut git_repository, + commit: *mut git_commit, + options: *const git_cherrypick_options, + ) -> c_int; } pub fn init() { diff --git a/src/cherrypick.rs b/src/cherrypick.rs new file mode 100644 index 0000000000..2aa4a38472 --- /dev/null +++ b/src/cherrypick.rs @@ -0,0 +1,63 @@ +use std::mem; + +use crate::build::CheckoutBuilder; +use crate::merge::MergeOptions; +use crate::raw; +use std::ptr; + +/// Options to specify when cherry picking +pub struct CherrypickOptions<'cb> { + mainline: u32, + checkout_builder: Option>, + merge_opts: Option, +} + +impl<'cb> CherrypickOptions<'cb> { + /// Creates a default set of cherrypick options + pub fn new() -> CherrypickOptions<'cb> { + CherrypickOptions { + mainline: 1, + checkout_builder: None, + merge_opts: None, + } + } + + /// Set the mainline value + pub fn mainline(&mut self, mainline: u32) -> &mut Self { + self.mainline = mainline; + self + } + + /// Set the checkout builder + pub fn checkout_builder(&mut self, cb: CheckoutBuilder<'cb>) -> &mut Self { + self.checkout_builder = Some(cb); + self + } + + /// Set the merge options + pub fn merge_opts(&mut self, merge_opts: MergeOptions) -> &mut Self { + self.merge_opts = Some(merge_opts); + self + } + + /// Obtain the raw struct + pub fn raw(&mut self) -> raw::git_cherrypick_options { + unsafe { + let mut checkout_opts: raw::git_checkout_options = mem::zeroed(); + raw::git_checkout_init_options(&mut checkout_opts, raw::GIT_CHECKOUT_OPTIONS_VERSION); + if let Some(ref mut cb) = self.checkout_builder { + cb.configure(&mut checkout_opts); + } + let mut merge_opts = mem::zeroed(); + if let Some(ref opts) = self.merge_opts { + ptr::copy(opts.raw(), &mut merge_opts, 1); + } + raw::git_cherrypick_options { + version: 1, + mainline: self.mainline, + checkout_opts: checkout_opts, + merge_opts: merge_opts, + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 17ffe94eeb..e719aa106f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,6 +81,7 @@ pub use crate::blame::{Blame, BlameHunk, BlameIter, BlameOptions}; pub use crate::blob::{Blob, BlobWriter}; pub use crate::branch::{Branch, Branches}; pub use crate::buf::Buf; +pub use crate::cherrypick::CherrypickOptions; pub use crate::commit::{Commit, Parents}; pub use crate::config::{Config, ConfigEntries, ConfigEntry}; pub use crate::cred::{Cred, CredentialHelper}; @@ -616,6 +617,7 @@ mod blame; mod blob; mod branch; mod buf; +mod cherrypick; mod commit; mod config; mod cred; diff --git a/src/repo.rs b/src/repo.rs index 0f60f7acd5..9316e9ff26 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -12,6 +12,7 @@ use crate::oid_array::OidArray; use crate::stash::{stash_cb, StashApplyOptions, StashCbData}; use crate::string_array::StringArray; use crate::util::{self, Binding}; +use crate::CherrypickOptions; use crate::{ init, raw, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, Revspec, StashFlags, @@ -2346,6 +2347,23 @@ impl Repository { } Ok(ignored == 1) } + + /// Perform a cherrypick + pub fn cherrypick( + &self, + commit: &Commit<'_>, + options: Option<&mut CherrypickOptions<'_>>, + ) -> Result<(), Error> { + unsafe { + let raw_opts = match options { + Some(opts) => &opts.raw(), + None => 0 as *const _, + }; + try_call!(raw::git_cherrypick(self.raw(), commit.raw(), raw_opts)); + + Ok(()) + } + } } impl Binding for Repository { @@ -2902,4 +2920,72 @@ mod tests { assert!(!repo.is_path_ignored(Path::new("\\foo\\thing")).unwrap()); } } + + #[test] + fn smoke_cherrypick() { + let (_td, repo) = crate::test::repo_init(); + let sig = repo.signature().unwrap(); + + let oid1 = repo.head().unwrap().target().unwrap(); + let commit1 = repo.find_commit(oid1).unwrap(); + + repo.branch("branch_a", &commit1, true).unwrap(); + + // Add 2 commits on top of the initial one in branch_a + let mut index = repo.index().unwrap(); + let p1 = Path::new(repo.workdir().unwrap()).join("file_c"); + fs::File::create(&p1).unwrap(); + index.add_path(Path::new("file_c")).unwrap(); + let id = index.write_tree().unwrap(); + let tree_c = repo.find_tree(id).unwrap(); + let oid2 = repo + .commit( + Some("refs/heads/branch_a"), + &sig, + &sig, + "commit 2", + &tree_c, + &[&commit1], + ) + .unwrap(); + let commit2 = repo.find_commit(oid2).unwrap(); + println!("created oid2 {:?}", oid2); + assert!(p1.exists()); + + let mut index = repo.index().unwrap(); + let p2 = Path::new(repo.workdir().unwrap()).join("file_d"); + fs::File::create(&p2).unwrap(); + index.add_path(Path::new("file_d")).unwrap(); + let id = index.write_tree().unwrap(); + let tree_d = repo.find_tree(id).unwrap(); + let oid3 = repo + .commit( + Some("refs/heads/branch_a"), + &sig, + &sig, + "commit 3", + &tree_d, + &[&commit2], + ) + .unwrap(); + let commit3 = repo.find_commit(oid3).unwrap(); + println!("created oid3 {:?}", oid3); + assert!(p1.exists()); + assert!(p2.exists()); + + // cherry-pick commit3 on top of commit1 in branch b + repo.reset(commit1.as_object(), ResetType::Hard, None) + .unwrap(); + repo.cherrypick(&commit3, None).unwrap(); + let id = repo.index().unwrap().write_tree().unwrap(); + let tree_d = repo.find_tree(id).unwrap(); + let oid4 = repo + .commit(Some("HEAD"), &sig, &sig, "commit 4", &tree_d, &[&commit1]) + .unwrap(); + let commit4 = repo.find_commit(oid4).unwrap(); + // should have file from commit3, but not the file from commit2 + assert_eq!(commit4.parent(0).unwrap().id(), commit1.id()); + assert!(!p1.exists()); + assert!(p2.exists()); + } } From 432d5e9cd8a7b5739edab7f394d0d714429946b7 Mon Sep 17 00:00:00 2001 From: Vincent Thiberville Date: Thu, 4 Jul 2019 10:56:54 +0200 Subject: [PATCH 364/860] cherrypick: fix multiple errors in cherrypick options impl * the mainline was wrong, the default value is 0, to work with regular commits. * the merge options was badly built, missing the version and call to init function. * the cherry pick options was badly built too, missing the version and call to init function. The CHERRYPICK_OPTIONS_VERSION constant from libgit2 is added, to be used when git_cherrypick_init_options is called. --- libgit2-sys/lib.rs | 1 + src/cherrypick.rs | 23 +++++++++++++++-------- src/repo.rs | 5 ++++- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5d51e4b4bc..7fd1e883ed 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -21,6 +21,7 @@ pub const GIT_PROXY_OPTIONS_VERSION: c_uint = 1; pub const GIT_SUBMODULE_UPDATE_OPTIONS_VERSION: c_uint = 1; pub const GIT_ODB_BACKEND_VERSION: c_uint = 1; pub const GIT_REFDB_BACKEND_VERSION: c_uint = 1; +pub const GIT_CHERRYPICK_OPTIONS_VERSION: c_uint = 1; macro_rules! git_enum { (pub enum $name:ident { $($variants:tt)* }) => { diff --git a/src/cherrypick.rs b/src/cherrypick.rs index 2aa4a38472..edbf573a65 100644 --- a/src/cherrypick.rs +++ b/src/cherrypick.rs @@ -16,7 +16,7 @@ impl<'cb> CherrypickOptions<'cb> { /// Creates a default set of cherrypick options pub fn new() -> CherrypickOptions<'cb> { CherrypickOptions { - mainline: 1, + mainline: 0, checkout_builder: None, merge_opts: None, } @@ -48,16 +48,23 @@ impl<'cb> CherrypickOptions<'cb> { if let Some(ref mut cb) = self.checkout_builder { cb.configure(&mut checkout_opts); } - let mut merge_opts = mem::zeroed(); + + let mut merge_opts: raw::git_merge_options = mem::zeroed(); + raw::git_merge_init_options(&mut merge_opts, raw::GIT_MERGE_OPTIONS_VERSION); if let Some(ref opts) = self.merge_opts { ptr::copy(opts.raw(), &mut merge_opts, 1); } - raw::git_cherrypick_options { - version: 1, - mainline: self.mainline, - checkout_opts: checkout_opts, - merge_opts: merge_opts, - } + + let mut cherrypick_opts: raw::git_cherrypick_options = mem::zeroed(); + raw::git_cherrypick_init_options( + &mut cherrypick_opts, + raw::GIT_CHERRYPICK_OPTIONS_VERSION, + ); + cherrypick_opts.mainline = self.mainline; + cherrypick_opts.checkout_opts = checkout_opts; + cherrypick_opts.merge_opts = merge_opts; + + cherrypick_opts } } } diff --git a/src/repo.rs b/src/repo.rs index 9316e9ff26..bd14eaaacd 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2543,6 +2543,7 @@ impl RepositoryInitOptions { #[cfg(test)] mod tests { use crate::build::CheckoutBuilder; + use crate::CherrypickOptions; use crate::{ObjectType, Oid, Repository, ResetType}; use std::ffi::OsStr; use std::fs; @@ -2976,7 +2977,9 @@ mod tests { // cherry-pick commit3 on top of commit1 in branch b repo.reset(commit1.as_object(), ResetType::Hard, None) .unwrap(); - repo.cherrypick(&commit3, None).unwrap(); + let mut cherrypick_opts = CherrypickOptions::new(); + repo.cherrypick(&commit3, Some(&mut cherrypick_opts)) + .unwrap(); let id = repo.index().unwrap().write_tree().unwrap(); let tree_d = repo.find_tree(id).unwrap(); let oid4 = repo From 60e088ae6dc07d830d0c0f70a1096c7506ed3a0e Mon Sep 17 00:00:00 2001 From: Vincent Thiberville Date: Tue, 9 Jul 2019 21:06:20 +0200 Subject: [PATCH 365/860] cherrypick: fix dangling pointer in cherrypick method Do not keep a pointer on a struct temporarily created, the pointer will become invalid immediately. Also, improve the documentation of the "mainline" parameter of cherrypick options. --- src/cherrypick.rs | 2 ++ src/repo.rs | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/cherrypick.rs b/src/cherrypick.rs index edbf573a65..659b73089b 100644 --- a/src/cherrypick.rs +++ b/src/cherrypick.rs @@ -23,6 +23,8 @@ impl<'cb> CherrypickOptions<'cb> { } /// Set the mainline value + /// + /// For merge commits, the "mainline" is treated as the parent. pub fn mainline(&mut self, mainline: u32) -> &mut Self { self.mainline = mainline; self diff --git a/src/repo.rs b/src/repo.rs index bd14eaaacd..383911a6d5 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2354,12 +2354,13 @@ impl Repository { commit: &Commit<'_>, options: Option<&mut CherrypickOptions<'_>>, ) -> Result<(), Error> { + let raw_opts = options.map(|o| o.raw()); + let ptr_raw_opts = match raw_opts.as_ref() { + Some(v) => v, + None => 0 as *const _, + }; unsafe { - let raw_opts = match options { - Some(opts) => &opts.raw(), - None => 0 as *const _, - }; - try_call!(raw::git_cherrypick(self.raw(), commit.raw(), raw_opts)); + try_call!(raw::git_cherrypick(self.raw(), commit.raw(), ptr_raw_opts)); Ok(()) } From d2af1ae1be388bfc030d5088de7a6b479e1fc7f5 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 12 Jul 2019 15:15:54 -0700 Subject: [PATCH 366/860] Fix azure rustc installation. --- azure-pipelines.yml | 10 ++++----- ci/azure-install-rust.yml | 44 ++++++++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 65091dfc00..652ab01045 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -31,10 +31,8 @@ jobs: vmImage: macos-10.13 steps: - template: ci/azure-test-all.yml - strategy: - matrix: - x86_64: - TARGET: x86_64-apple-darwin + variables: + TOOLCHAIN: stable - job: Windows pool: @@ -44,6 +42,6 @@ jobs: strategy: matrix: x86_64-msvc: - TARGET: x86_64-pc-windows-msvc + TOOLCHAIN: stable-x86_64-pc-windows-msvc i686-msvc: - TARGET: i686-pc-windows-msvc + TOOLCHAIN: stable-i686-pc-windows-msvc diff --git a/ci/azure-install-rust.yml b/ci/azure-install-rust.yml index fa7eae459b..b99f1cf18e 100644 --- a/ci/azure-install-rust.yml +++ b/ci/azure-install-rust.yml @@ -1,23 +1,33 @@ steps: + # Rustup is currently installed on Windows and Linux, but not macOS. + # It is installed in /usr/local/cargo/bin/ or C:\Program Files\Rust\.cargo\bin\ + # This steps ensures that rustup is installed, mainly for macOS, or if the + # azure image changes in the future. - bash: | - set -e - toolchain=$TOOLCHAIN - if [ "$toolchain" = "" ]; then - toolchain=stable + set -ex + if [ -x "`command -v rustup`" ]; then + echo `command -v rustup` `rustup -V` already installed + rustup self update + else + if [ "$Agent.OS" = "Windows_NT" ]; then + curl -sSf -o rustup-init.exe https://win.rustup.rs + rustup-init.exe -y --default-toolchain $TOOLCHAIN + echo ##vso[task.prependpath]$USERPROFILE\.cargo\bin + else + curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $TOOLCHAIN + echo "##vso[task.prependpath]$HOME/.cargo/bin" + fi fi - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $toolchain - echo "##vso[task.prependpath]$HOME/.cargo/bin" - displayName: Install rust (unix) - condition: ne( variables['Agent.OS'], 'Windows_NT' ) + displayName: Install rustup - - script: | - curl -sSf -o rustup-init.exe https://win.rustup.rs - rustup-init.exe -y --default-toolchain stable-%TARGET% - echo ##vso[task.prependpath]%USERPROFILE%\.cargo\bin - displayName: Install rust (windows) - condition: eq( variables['Agent.OS'], 'Windows_NT' ) + - bash: | + set -ex + rustup update $TOOLCHAIN + rustup default $TOOLCHAIN + displayName: Install rust - - script: | - rustc -Vv - cargo -V + - bash: | + set -ex + rustc -Vv + cargo -V displayName: Query rust and cargo versions From 5334dcaf253ad48de175fa6a1b0250e940537f12 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 12 Jul 2019 15:37:38 -0700 Subject: [PATCH 367/860] Fix deprecation warnings. - ONCE_INIT deprecated. - fix "outlives requirements can be inferred" --- git2-curl/src/lib.rs | 4 ++-- libgit2-sys/lib.rs | 4 ++-- src/commit.rs | 2 +- src/diff.rs | 2 +- src/lib.rs | 4 ++-- src/reference.rs | 2 +- src/remote.rs | 5 +---- src/repo.rs | 2 +- 8 files changed, 11 insertions(+), 14 deletions(-) diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 3800398fe9..a036a5e42a 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -24,7 +24,7 @@ use std::error; use std::io::prelude::*; use std::io::{self, Cursor}; use std::str; -use std::sync::{Arc, Mutex, Once, ONCE_INIT}; +use std::sync::{Arc, Mutex, Once}; use curl::easy::{Easy, List}; use git2::transport::SmartSubtransportStream; @@ -69,7 +69,7 @@ struct CurlSubtransport { /// This function may be called concurrently, but only the first `handle` will /// be used. All others will be discarded. pub unsafe fn register(handle: Easy) { - static INIT: Once = ONCE_INIT; + static INIT: Once = Once::new(); let handle = Arc::new(Mutex::new(handle)); let handle2 = handle.clone(); diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 7fd1e883ed..cb376d5673 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -3364,9 +3364,9 @@ extern "C" { } pub fn init() { - use std::sync::{Once, ONCE_INIT}; + use std::sync::Once; - static INIT: Once = ONCE_INIT; + static INIT: Once = Once::new(); INIT.call_once(|| unsafe { openssl_init(); ssh_init(); diff --git a/src/commit.rs b/src/commit.rs index 1bb468278d..6ff815d0b4 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -19,7 +19,7 @@ pub struct Commit<'repo> { /// An iterator over the parent commits of a commit. /// /// Aborts iteration when a commit cannot be found -pub struct Parents<'commit, 'repo: 'commit> { +pub struct Parents<'commit, 'repo> { range: Range, commit: &'commit Commit<'repo>, } diff --git a/src/diff.rs b/src/diff.rs index bf1d2a5173..2d47199dd2 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -109,7 +109,7 @@ pub type BinaryCb<'a> = dyn FnMut(DiffDelta<'_>, DiffBinary<'_>) -> bool + 'a; pub type HunkCb<'a> = dyn FnMut(DiffDelta<'_>, DiffHunk<'_>) -> bool + 'a; pub type LineCb<'a> = dyn FnMut(DiffDelta<'_>, Option>, DiffLine<'_>) -> bool + 'a; -struct ForeachCallbacks<'a, 'b: 'a, 'c, 'd: 'c, 'e, 'f: 'e, 'g, 'h: 'g> { +struct ForeachCallbacks<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h> { file: &'a mut FileCb<'b>, binary: Option<&'c mut BinaryCb<'d>>, hunk: Option<&'e mut HunkCb<'f>>, diff --git a/src/lib.rs b/src/lib.rs index e719aa106f..d10fc9938f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,7 +75,7 @@ use libgit2_sys as raw; use std::ffi::{CStr, CString}; use std::fmt; use std::str; -use std::sync::{Once, ONCE_INIT}; +use std::sync::Once; pub use crate::blame::{Blame, BlameHunk, BlameIter, BlameOptions}; pub use crate::blob::{Blob, BlobWriter}; @@ -654,7 +654,7 @@ mod tree; mod treebuilder; fn init() { - static INIT: Once = ONCE_INIT; + static INIT: Once = Once::new(); INIT.call_once(|| { openssl_env_init(); diff --git a/src/reference.rs b/src/reference.rs index eeaa5bd180..7955fcfe78 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -28,7 +28,7 @@ pub struct References<'repo> { } /// An iterator over the names of references in a repository. -pub struct ReferenceNames<'repo: 'references, 'references> { +pub struct ReferenceNames<'repo, 'references> { inner: &'references mut References<'repo>, } diff --git a/src/remote.rs b/src/remote.rs index fbc8eb90ad..e3e41f130a 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -53,10 +53,7 @@ pub struct PushOptions<'cb> { } /// Holds callbacks for a connection to a `Remote`. Disconnects when dropped -pub struct RemoteConnection<'repo, 'connection, 'cb> -where - 'repo: 'connection, -{ +pub struct RemoteConnection<'repo, 'connection, 'cb> { _callbacks: Box>, _proxy: ProxyOptions<'cb>, remote: &'connection mut Remote<'repo>, diff --git a/src/repo.rs b/src/repo.rs index 383911a6d5..bae81d0d88 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -747,7 +747,7 @@ impl Repository { /// Load all submodules for this repository and return them. pub fn submodules(&self) -> Result>, Error> { - struct Data<'a, 'b: 'a> { + struct Data<'a, 'b> { repo: &'b Repository, ret: &'a mut Vec>, } From 8d8cf06187cdee9b338c0529b539af0ff1a72996 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 12 Jul 2019 15:54:58 -0700 Subject: [PATCH 368/860] Add rustfmt check to CI. --- azure-pipelines.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 65091dfc00..6639c5845e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -2,6 +2,19 @@ trigger: - master jobs: + - job: rustfmt + pool: + vmImage: ubuntu-16.04 + steps: + - template: ci/azure-install-rust.yml + - bash: | + set -ex + rustup component add rustfmt + cargo fmt --all -- --check + displayName: "rustfmt check" + variables: + TOOLCHAIN: stable + - job: MSRV pool: vmImage: ubuntu-16.04 From 7700974be1296cf2ed065cd08d5eddac28089fcc Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 12 Jul 2019 20:09:14 -0700 Subject: [PATCH 369/860] Update CI badge in Cargo.toml. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 259920d26e..60d6266831 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ categories = ["api-bindings"] edition = "2018" [badges] -travis-ci = { repository = "rust-lang/git2-rs" } +azure-devops = { project = "rust-lang/git2-rs", pipeline = "rust-lang.git2-rs", build="9" } [dependencies] url = "1.0" From 25a2ba2fb256b95935d1ff642829d7addb91ba17 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 13 Jul 2019 10:58:54 -0700 Subject: [PATCH 370/860] Update libgit2 to latest master. --- libgit2-sys/build.rs | 60 +++++++++++++++++++++++++++++++------------- libgit2-sys/lib.rs | 5 +++- libgit2-sys/libgit2 | 2 +- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 4586d56318..2209c60916 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -31,7 +31,7 @@ fn main() { fs::create_dir_all(&include).unwrap(); // Copy over all header files - cp_r("libgit2/include".as_ref(), &include); + cp_r("libgit2/include", &include); cfg.include(&include) .include("libgit2/src") @@ -39,25 +39,46 @@ fn main() { .warnings(false); // Include all cross-platform C files - add_c_files(&mut cfg, "libgit2/src".as_ref()); - add_c_files(&mut cfg, "libgit2/src/xdiff".as_ref()); + add_c_files(&mut cfg, "libgit2/src"); + add_c_files(&mut cfg, "libgit2/src/xdiff"); // These are activated by features, but they're all unconditionally always // compiled apparently and have internal #define's to make sure they're // compiled correctly. - add_c_files(&mut cfg, "libgit2/src/transports".as_ref()); - add_c_files(&mut cfg, "libgit2/src/streams".as_ref()); + add_c_files(&mut cfg, "libgit2/src/transports"); + add_c_files(&mut cfg, "libgit2/src/streams"); // Always use bundled http-parser for now cfg.include("libgit2/deps/http-parser") .file("libgit2/deps/http-parser/http_parser.c"); - // Always use bundled regex for now - cfg.include("libgit2/deps/regex") - .file("libgit2/deps/regex/regex.c"); + // Use the included PCRE regex backend. + // + // Ideally these defines would be specific to the pcre files (or placed in + // a config.h), but since libgit2 already has a config.h used for other + // reasons, just define on the command-line for everything. Perhaps there + // is some way with cc to have different instructions per-file? + cfg.define("GIT_REGEX_BUILTIN", "1") + .include("libgit2/deps/pcre") + .define("HAVE_STDINT_H", Some("1")) + .define("HAVE_MEMMOVE", Some("1")) + .define("NO_RECURSE", Some("1")) + .define("NEWLINE", Some("10")) + .define("POSIX_MALLOC_THRESHOLD", Some("10")) + .define("LINK_SIZE", Some("2")) + .define("PARENS_NEST_LIMIT", Some("250")) + .define("MATCH_LIMIT", Some("10000000")) + .define("MATCH_LIMIT_RECURSION", Some("MATCH_LIMIT")) + .define("MAX_NAME_SIZE", Some("32")) + .define("MAX_NAME_COUNT", Some("10000")); + // "no symbols" warning on pcre_string_utils.c is because it is only used + // when when COMPILE_PCRE8 is not defined, which is the default. + add_c_files(&mut cfg, "libgit2/deps/pcre"); + + cfg.file("libgit2/src/allocators/stdalloc.c"); if windows { - add_c_files(&mut cfg, "libgit2/src/win32".as_ref()); + add_c_files(&mut cfg, "libgit2/src/win32"); cfg.define("STRSAFE_NO_DEPRECATE", None); cfg.define("WIN32", None); cfg.define("_WIN32_WINNT", Some("0x0600")); @@ -69,7 +90,7 @@ fn main() { cfg.define("__USE_MINGW_ANSI_STDIO", "1"); } } else { - add_c_files(&mut cfg, "libgit2/src/unix".as_ref()); + add_c_files(&mut cfg, "libgit2/src/unix"); cfg.flag("-fvisibility=hidden"); } if target.contains("solaris") { @@ -112,24 +133,27 @@ fn main() { if windows { features.push_str("#define GIT_WINHTTP 1\n"); features.push_str("#define GIT_SHA1_WIN32 1\n"); - cfg.file("libgit2/src/hash/hash_win32.c"); + cfg.file("libgit2/src/hash/sha1/win32.c"); } else if target.contains("apple") { features.push_str("#define GIT_SECURE_TRANSPORT 1\n"); features.push_str("#define GIT_SHA1_COMMON_CRYPTO 1\n"); + cfg.file("libgit2/src/hash/sha1/common_crypto.c"); } else { features.push_str("#define GIT_OPENSSL 1\n"); features.push_str("#define GIT_SHA1_OPENSSL 1\n"); if let Some(path) = env::var_os("DEP_OPENSSL_INCLUDE") { cfg.include(path); } + cfg.file("libgit2/src/hash/sha1/openssl.c"); } } else { features.push_str("#define GIT_SHA1_COLLISIONDETECT 1\n"); cfg.define("SHA1DC_NO_STANDARD_INCLUDES", "1"); cfg.define("SHA1DC_CUSTOM_INCLUDE_SHA1_C", "\"common.h\""); cfg.define("SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C", "\"common.h\""); - cfg.file("libgit2/src/hash/sha1dc/sha1.c"); - cfg.file("libgit2/src/hash/sha1dc/ubc_check.c"); + cfg.file("libgit2/src/hash/sha1/collisiondetect.c"); + cfg.file("libgit2/src/hash/sha1/sha1dc/sha1.c"); + cfg.file("libgit2/src/hash/sha1/sha1dc/ubc_check.c"); } if let Some(path) = env::var_os("DEP_Z_INCLUDE") { @@ -162,11 +186,11 @@ fn main() { } } -fn cp_r(from: &Path, to: &Path) { - for e in from.read_dir().unwrap() { +fn cp_r(from: impl AsRef, to: impl AsRef) { + for e in from.as_ref().read_dir().unwrap() { let e = e.unwrap(); let from = e.path(); - let to = to.join(e.file_name()); + let to = to.as_ref().join(e.file_name()); if e.file_type().unwrap().is_dir() { fs::create_dir_all(&to).unwrap(); cp_r(&from, &to); @@ -177,8 +201,8 @@ fn cp_r(from: &Path, to: &Path) { } } -fn add_c_files(build: &mut cc::Build, path: &Path) { - for e in path.read_dir().unwrap() { +fn add_c_files(build: &mut cc::Build, path: impl AsRef) { + for e in path.as_ref().read_dir().unwrap() { let e = e.unwrap(); let path = e.path(); if e.file_type().unwrap().is_dir() { diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 7fd1e883ed..527032e535 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -331,6 +331,7 @@ pub struct git_remote_callbacks { pub push_negotiation: Option, pub transport: Option, pub payload: *mut c_void, + pub resolve_url: Option, } #[repr(C)] @@ -384,6 +385,8 @@ pub type git_push_negotiation = pub type git_push_update_reference_cb = extern "C" fn(*const c_char, *const c_char, *mut c_void) -> c_int; +pub type git_url_resolve_cb = + extern "C" fn(*mut git_buf, *const c_char, c_int, *mut c_void) -> c_int; #[repr(C)] pub struct git_push_update { @@ -2216,7 +2219,7 @@ extern "C" { source: *const git_tree, ) -> c_int; pub fn git_treebuilder_clear(bld: *mut git_treebuilder); - pub fn git_treebuilder_entrycount(bld: *mut git_treebuilder) -> c_uint; + pub fn git_treebuilder_entrycount(bld: *mut git_treebuilder) -> size_t; pub fn git_treebuilder_free(bld: *mut git_treebuilder); pub fn git_treebuilder_get( bld: *mut git_treebuilder, diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index b3e1a56ebb..f92d495d44 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit b3e1a56ebb2b9291e82dc027ba9cbcfc3ead54d3 +Subproject commit f92d495d44bff2bdb6fd99524a93986ea268c9e8 From 52855c468cfb1a0aea1deb9addd33253d00a09a6 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 13 Jul 2019 11:44:19 -0700 Subject: [PATCH 371/860] Switch SHA1 implementation. This switches to the CollisionDetection SHA1 implementation for all platforms regardless if the `https` feature is enabled. This is the default behavior of libgit2 now. Also, the windows sha1 implementation doesn't seem to compile anymore. --- libgit2-sys/build.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 2209c60916..e89a9a0ad2 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -132,30 +132,25 @@ fn main() { if windows { features.push_str("#define GIT_WINHTTP 1\n"); - features.push_str("#define GIT_SHA1_WIN32 1\n"); - cfg.file("libgit2/src/hash/sha1/win32.c"); } else if target.contains("apple") { features.push_str("#define GIT_SECURE_TRANSPORT 1\n"); - features.push_str("#define GIT_SHA1_COMMON_CRYPTO 1\n"); - cfg.file("libgit2/src/hash/sha1/common_crypto.c"); } else { features.push_str("#define GIT_OPENSSL 1\n"); - features.push_str("#define GIT_SHA1_OPENSSL 1\n"); if let Some(path) = env::var_os("DEP_OPENSSL_INCLUDE") { cfg.include(path); } - cfg.file("libgit2/src/hash/sha1/openssl.c"); } - } else { - features.push_str("#define GIT_SHA1_COLLISIONDETECT 1\n"); - cfg.define("SHA1DC_NO_STANDARD_INCLUDES", "1"); - cfg.define("SHA1DC_CUSTOM_INCLUDE_SHA1_C", "\"common.h\""); - cfg.define("SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C", "\"common.h\""); - cfg.file("libgit2/src/hash/sha1/collisiondetect.c"); - cfg.file("libgit2/src/hash/sha1/sha1dc/sha1.c"); - cfg.file("libgit2/src/hash/sha1/sha1dc/ubc_check.c"); } + // Use the CollisionDetection SHA1 implementation. + features.push_str("#define GIT_SHA1_COLLISIONDETECT 1\n"); + cfg.define("SHA1DC_NO_STANDARD_INCLUDES", "1"); + cfg.define("SHA1DC_CUSTOM_INCLUDE_SHA1_C", "\"common.h\""); + cfg.define("SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C", "\"common.h\""); + cfg.file("libgit2/src/hash/sha1/collisiondetect.c"); + cfg.file("libgit2/src/hash/sha1/sha1dc/sha1.c"); + cfg.file("libgit2/src/hash/sha1/sha1dc/ubc_check.c"); + if let Some(path) = env::var_os("DEP_Z_INCLUDE") { cfg.include(path); } From 6cc35f6b66b4ac8a8a1d403a2cfaf9ec2dc4b4ca Mon Sep 17 00:00:00 2001 From: Samuel Harrington Date: Tue, 16 Jul 2019 02:35:03 -0700 Subject: [PATCH 372/860] Add support for getting file attributes Closes #441 --- libgit2-sys/lib.rs | 18 ++++++++++++++++++ src/lib.rs | 20 ++++++++++++++++++++ src/repo.rs | 18 +++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 649e6a53d0..cadeb75bf9 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -806,6 +806,20 @@ pub struct git_writestream { pub free: extern "C" fn(*mut git_writestream), } +git_enum! { + pub enum git_attr_value_t: c_int { + GIT_ATTR_VALUE_UNSPECIFIED = 0, + GIT_ATTR_VALUE_TRUE, + GIT_ATTR_VALUE_FALSE, + GIT_ATTR_VALUE_STRING, + } +} + +pub const GIT_ATTR_CHECK_FILE_THEN_INDEX: u32 = 0; +pub const GIT_ATTR_CHECK_INDEX_THEN_FILE: u32 = 1; +pub const GIT_ATTR_CHECK_INDEX_ONLY: u32 = 2; +pub const GIT_ATTR_CHECK_NO_SYSTEM: u32 = 1 << 2; + #[repr(C)] pub struct git_cred { pub credtype: git_credtype_t, @@ -2547,6 +2561,10 @@ extern "C" { pub fn git_config_snapshot(out: *mut *mut git_config, config: *mut git_config) -> c_int; pub fn git_config_entry_free(entry: *mut git_config_entry); + // attr + pub fn git_attr_get(value_out: *mut *const c_char, repo: *mut git_repository, flags: u32, path: *const c_char, name: *const c_char) -> c_int; + pub fn git_attr_value(value: *const c_char) -> git_attr_value_t; + // cred pub fn git_cred_default_new(out: *mut *mut git_cred) -> c_int; pub fn git_cred_has_username(cred: *mut git_cred) -> c_int; diff --git a/src/lib.rs b/src/lib.rs index d10fc9938f..08440357e4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1309,6 +1309,26 @@ impl Default for StashFlags { } } +bitflags! { + #[allow(missing_docs)] + pub struct AttrCheckFlags: u32 { + /// Check the working directory, then the index. + const FILE_THEN_INDEX = raw::GIT_ATTR_CHECK_FILE_THEN_INDEX as u32; + /// Check the index, then the working directory. + const INDEX_THEN_FILE = raw::GIT_ATTR_CHECK_INDEX_THEN_FILE as u32; + /// Check the index only. + const INDEX_ONLY = raw::GIT_ATTR_CHECK_INDEX_ONLY as u32; + /// Do not use the system gitattributes file. + const NO_SYSTEM = raw::GIT_ATTR_CHECK_NO_SYSTEM as u32; + } +} + +impl Default for AttrCheckFlags { + fn default() -> Self { + AttrCheckFlags::FILE_THEN_INDEX + } +} + #[cfg(test)] mod tests { use super::ObjectType; diff --git a/src/repo.rs b/src/repo.rs index bae81d0d88..e4c0facfef 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -15,7 +15,7 @@ use crate::util::{self, Binding}; use crate::CherrypickOptions; use crate::{ init, raw, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, Revspec, - StashFlags, + StashFlags, AttrCheckFlags, }; use crate::{ AnnotatedCommit, MergeAnalysis, MergeOptions, MergePreference, SubmoduleIgnore, SubmoduleStatus, @@ -890,6 +890,22 @@ impl Repository { } } + /// Get the value of a git attribute for a path as a string. + pub fn get_attr(&self, path: &Path, name: &str, flags: AttrCheckFlags) -> Result, Error> { + Ok(self.get_attr_bytes(path, name, flags)?.and_then(|a| str::from_utf8(a).ok())) + } + + /// Get the value of a git attribute for a path as a byte slice. + pub fn get_attr_bytes(&self, path: &Path, name: &str, flags: AttrCheckFlags) -> Result, Error> { + let mut ret = ptr::null(); + let path = path.into_c_string()?; + let name = CString::new(name)?; + unsafe { + try_call!(raw::git_attr_get(&mut ret, self.raw(), flags.bits(), path, name)); + Ok(crate::opt_bytes(self, ret)) + } + } + /// Write an in-memory buffer to the ODB as a blob. /// /// The Oid returned can in turn be passed to `find_blob` to get a handle to From ec224a780e594052a63edcce0af0b702f73f2d13 Mon Sep 17 00:00:00 2001 From: Samuel Harrington Date: Wed, 17 Jul 2019 22:45:25 -0700 Subject: [PATCH 373/860] Address CI test failures --- libgit2-sys/lib.rs | 10 ++++++++-- src/repo.rs | 30 ++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index cadeb75bf9..7a2396cf0d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -807,7 +807,7 @@ pub struct git_writestream { } git_enum! { - pub enum git_attr_value_t: c_int { + pub enum git_attr_value_t { GIT_ATTR_VALUE_UNSPECIFIED = 0, GIT_ATTR_VALUE_TRUE, GIT_ATTR_VALUE_FALSE, @@ -2562,7 +2562,13 @@ extern "C" { pub fn git_config_entry_free(entry: *mut git_config_entry); // attr - pub fn git_attr_get(value_out: *mut *const c_char, repo: *mut git_repository, flags: u32, path: *const c_char, name: *const c_char) -> c_int; + pub fn git_attr_get( + value_out: *mut *const c_char, + repo: *mut git_repository, + flags: u32, + path: *const c_char, + name: *const c_char, + ) -> c_int; pub fn git_attr_value(value: *const c_char) -> git_attr_value_t; // cred diff --git a/src/repo.rs b/src/repo.rs index e4c0facfef..e69ac8b051 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -14,8 +14,8 @@ use crate::string_array::StringArray; use crate::util::{self, Binding}; use crate::CherrypickOptions; use crate::{ - init, raw, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, Revspec, - StashFlags, AttrCheckFlags, + init, raw, AttrCheckFlags, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, + Revspec, StashFlags, }; use crate::{ AnnotatedCommit, MergeAnalysis, MergeOptions, MergePreference, SubmoduleIgnore, SubmoduleStatus, @@ -891,17 +891,35 @@ impl Repository { } /// Get the value of a git attribute for a path as a string. - pub fn get_attr(&self, path: &Path, name: &str, flags: AttrCheckFlags) -> Result, Error> { - Ok(self.get_attr_bytes(path, name, flags)?.and_then(|a| str::from_utf8(a).ok())) + pub fn get_attr( + &self, + path: &Path, + name: &str, + flags: AttrCheckFlags, + ) -> Result, Error> { + Ok(self + .get_attr_bytes(path, name, flags)? + .and_then(|a| str::from_utf8(a).ok())) } /// Get the value of a git attribute for a path as a byte slice. - pub fn get_attr_bytes(&self, path: &Path, name: &str, flags: AttrCheckFlags) -> Result, Error> { + pub fn get_attr_bytes( + &self, + path: &Path, + name: &str, + flags: AttrCheckFlags, + ) -> Result, Error> { let mut ret = ptr::null(); let path = path.into_c_string()?; let name = CString::new(name)?; unsafe { - try_call!(raw::git_attr_get(&mut ret, self.raw(), flags.bits(), path, name)); + try_call!(raw::git_attr_get( + &mut ret, + self.raw(), + flags.bits(), + path, + name + )); Ok(crate::opt_bytes(self, ret)) } } From 4364d9c995ff1eb255327e4533299f768febd8e4 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Tue, 23 Jul 2019 01:49:11 +0000 Subject: [PATCH 374/860] packbuilder: allow users to set number of threads libgit2 provides the option for the pack builder to be multi-threaded during deltification. On repositories of any significant size, such as the Linux kernel, threading provides a significant performance benefit. Allow users to specify the thread count used by a pack builder. --- src/packbuilder.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/packbuilder.rs b/src/packbuilder.rs index d043f0497c..10d1682368 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -138,6 +138,13 @@ impl<'repo> PackBuilder<'repo> { Ok(()) } + /// Set the number of threads to be used. + /// + /// Returns the number of threads to be used. + pub fn set_threads(&mut self, threads: u32) -> u32 { + unsafe { raw::git_packbuilder_set_threads(self.raw, threads) } + } + /// 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) } @@ -383,4 +390,13 @@ mod tests { } assert_eq!(progress_called, false); } + + #[test] + fn set_threads() { + let (_td, repo) = crate::test::repo_init(); + let mut builder = t!(repo.packbuilder()); + let used = builder.set_threads(4); + // Will be 1 if not compiled with threading. + assert!(used == 1 || used == 4); + } } From 42ffe506f70428fc8f362e64e171f8d8dc5c7343 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 24 Jul 2019 07:50:31 -0700 Subject: [PATCH 375/860] Update libgit2 submodule Primarily pull in libgit2/libgit2#5151 to help address rust-lang/cargo#7173 --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index f92d495d44..e3adc99e1f 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit f92d495d44bff2bdb6fd99524a93986ea268c9e8 +Subproject commit e3adc99e1f9b71ceaddd650eba9c7c644290e4a6 From 50aa448857fec1edcb207b5fc5ca5bca0b5a677c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 24 Jul 2019 07:44:14 -0700 Subject: [PATCH 376/860] Update depenency on `url` to 2.0 Looks like no changes needed! --- Cargo.toml | 2 +- azure-pipelines.yml | 2 +- git2-curl/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 60d6266831..371f86f3b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" azure-devops = { project = "rust-lang/git2-rs", pipeline = "rust-lang.git2-rs", build="9" } [dependencies] -url = "1.0" +url = "2.0" bitflags = "1.0" libc = "0.2" log = "0.4" diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b0a78f13ae..2a514738cb 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -23,7 +23,7 @@ jobs: - script: cargo build displayName: "Build crate" variables: - TOOLCHAIN: 1.32.0 + TOOLCHAIN: 1.33.0 - job: Linux pool: diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index a6954ed43e..ba95166fad 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -15,7 +15,7 @@ edition = "2018" [dependencies] curl = "0.4" -url = "1.0" +url = "2.0" log = "0.4" git2 = { path = "..", version = "0.9", default-features = false } From 9d7d7394eab8b8ace646363a60f2928fccc34805 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 24 Jul 2019 09:47:24 -0700 Subject: [PATCH 377/860] Bump libgit2-sys to 0.8.2 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 5e0649a56c..ae2a0184b8 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.8.1" +version = "0.8.2" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 198b9ca48bd24d287140fa72149a4281ba858cdc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 24 Jul 2019 09:47:55 -0700 Subject: [PATCH 378/860] Bump to 0.9.2 --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 371f86f3b1..18e635ef56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.9.1" +version = "0.9.2" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -24,7 +24,7 @@ url = "2.0" bitflags = "1.0" libc = "0.2" log = "0.4" -libgit2-sys = { path = "libgit2-sys", version = "0.8.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.8.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 1d33b290e034d0d85ac0e4bc0ac64cebfa8cfbc7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 24 Jul 2019 09:48:18 -0700 Subject: [PATCH 379/860] Bump git2-curl to 0.10.1 --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index ba95166fad..99d73b9dde 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.10.0" +version = "0.10.1" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" From a160f0672b1604ff0b3bcb340b2d1746912142ed Mon Sep 17 00:00:00 2001 From: Kornel Date: Thu, 8 Aug 2019 21:57:56 +0100 Subject: [PATCH 380/860] Replace deprecated tempdir crate --- Cargo.toml | 2 +- src/blob.rs | 8 ++++---- src/build.rs | 8 ++++---- src/config.rs | 6 +++--- src/cred.rs | 10 +++++----- src/index.rs | 4 ++-- src/odb.rs | 14 +++++++------- src/oid.rs | 4 ++-- src/remote.rs | 14 +++++++------- src/repo.rs | 16 ++++++++-------- src/submodule.rs | 4 ++-- src/test.rs | 4 ++-- src/tree.rs | 2 +- 13 files changed, 48 insertions(+), 48 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 18e635ef56..6e857f4fce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ docopt = "1.0" serde = "1.0" serde_derive = "1.0" time = "0.1.39" -tempdir = "0.3.7" +tempfile = "3.1.0" thread-id = "3.3.0" # remove when we work with minimal-versions without it [features] diff --git a/src/blob.rs b/src/blob.rs index c0a471f358..d4d3a00ee4 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -146,11 +146,11 @@ mod tests { use std::fs::File; use std::io::prelude::*; use std::path::Path; - use tempdir::TempDir; + use tempfile::TempDir; #[test] fn buffer() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); let id = repo.blob(&[5, 4, 6]).unwrap(); let blob = repo.find_blob(id).unwrap(); @@ -169,7 +169,7 @@ mod tests { #[test] fn path() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path().join("foo"); File::create(&path).unwrap().write_all(&[7, 8, 9]).unwrap(); let repo = Repository::init(td.path()).unwrap(); @@ -181,7 +181,7 @@ mod tests { #[test] fn stream() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); let mut ws = repo.blob_writer(Some(Path::new("foo"))).unwrap(); let wl = ws.write(&[10, 11, 12]).unwrap(); diff --git a/src/build.rs b/src/build.rs index 71cf583c6c..c1ca06ed61 100644 --- a/src/build.rs +++ b/src/build.rs @@ -645,7 +645,7 @@ mod tests { use crate::{CheckoutNotificationType, Repository}; use std::fs; use std::path::Path; - use tempdir::TempDir; + use tempfile::TempDir; #[test] fn smoke() { @@ -655,7 +655,7 @@ mod tests { #[test] fn smoke2() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); Repository::init_bare(&td.path().join("bare")).unwrap(); let url = if cfg!(unix) { format!("file://{}/bare", td.path().display()) @@ -675,8 +675,8 @@ mod tests { /// Issue regression test #365 #[test] fn notify_callback() { - let td = TempDir::new("test").unwrap(); - let cd = TempDir::new("external-checkout").unwrap(); + let td = TempDir::new().unwrap(); + let cd = TempDir::new().unwrap(); { let repo = Repository::init(&td.path()).unwrap(); diff --git a/src/config.rs b/src/config.rs index 9df476cf2b..cc190899eb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -535,7 +535,7 @@ impl<'cfg> Drop for ConfigEntry<'cfg> { #[cfg(test)] mod tests { use std::fs::File; - use tempdir::TempDir; + use tempfile::TempDir; use crate::Config; @@ -549,7 +549,7 @@ mod tests { #[test] fn persisted() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path().join("foo"); File::create(&path).unwrap(); @@ -578,7 +578,7 @@ mod tests { #[test] fn multivar() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path().join("foo"); File::create(&path).unwrap(); diff --git a/src/cred.rs b/src/cred.rs index c217872f11..6d7c59ebe2 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -438,12 +438,12 @@ mod test { use std::fs::File; use std::io::prelude::*; use std::path::Path; - use tempdir::TempDir; + use tempfile::TempDir; use crate::{Config, ConfigLevel, Cred, CredentialHelper}; macro_rules! test_cfg( ($($k:expr => $v:expr),*) => ({ - let td = TempDir::new("git2-rs").unwrap(); + let td = TempDir::new().unwrap(); let mut cfg = Config::new().unwrap(); cfg.add_file(&td.path().join("cfg"), ConfigLevel::Highest, false).unwrap(); $(cfg.set_str($k, $v).unwrap();)* @@ -498,7 +498,7 @@ mod test { return; } // shell scripts don't work on Windows - let td = TempDir::new("git2-rs").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path().join("script"); File::create(&path) .unwrap() @@ -528,7 +528,7 @@ echo username=c if cfg!(windows) { return; } // shell scripts don't work on Windows - let td = TempDir::new("git2-rs").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path().join("git-credential-script"); File::create(&path) .unwrap() @@ -574,7 +574,7 @@ echo username=c if cfg!(windows) { return; } // shell scripts don't work on Windows - let td = TempDir::new("git2-rs").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path().join("script"); File::create(&path) .unwrap() diff --git a/src/index.rs b/src/index.rs index 06f8425bfe..f2188fceff 100644 --- a/src/index.rs +++ b/src/index.rs @@ -701,7 +701,7 @@ impl Binding for IndexEntry { mod tests { use std::fs::{self, File}; use std::path::Path; - use tempdir::TempDir; + use tempfile::TempDir; use crate::{Index, IndexEntry, IndexTime, Oid, Repository, ResetType}; @@ -797,7 +797,7 @@ mod tests { let obj = repo.find_object(commit, None).unwrap(); repo.reset(&obj, ResetType::Hard, None).unwrap(); - let td2 = TempDir::new("git").unwrap(); + let td2 = TempDir::new().unwrap(); let url = crate::test::path2url(https://github.com/&root); let repo = Repository::clone(&url, td2.path()).unwrap(); let obj = repo.find_object(commit, None).unwrap(); diff --git a/src/odb.rs b/src/odb.rs index 71b34b0aad..a99e29f40b 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -378,11 +378,11 @@ extern "C" fn foreach_cb(id: *const raw::git_oid, payload: *mut c_void) -> c_int mod tests { use crate::{ObjectType, Oid, Repository}; use std::io::prelude::*; - use tempdir::TempDir; + use tempfile::TempDir; #[test] fn read() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); let dat = [4, 3, 5, 6, 9]; let id = repo.blob(&dat).unwrap(); @@ -397,7 +397,7 @@ mod tests { #[test] fn read_header() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); let dat = [4, 3, 5, 6, 9]; let id = repo.blob(&dat).unwrap(); @@ -410,7 +410,7 @@ mod tests { #[test] fn write() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); let dat = [4, 3, 5, 6, 9]; let db = repo.odb().unwrap(); @@ -421,7 +421,7 @@ mod tests { #[test] fn writer() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); let dat = [4, 3, 5, 6, 9]; let db = repo.odb().unwrap(); @@ -437,7 +437,7 @@ mod tests { #[test] fn exists() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); let dat = [4, 3, 5, 6, 9]; let db = repo.odb().unwrap(); @@ -447,7 +447,7 @@ mod tests { #[test] fn exists_prefix() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); let dat = [4, 3, 5, 6, 9]; let db = repo.odb().unwrap(); diff --git a/src/oid.rs b/src/oid.rs index 4a582e8c69..4bbb16663a 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -197,7 +197,7 @@ mod tests { use super::Error; use super::Oid; use crate::ObjectType; - use tempdir::TempDir; + use tempfile::TempDir; #[test] fn conversions() { @@ -246,7 +246,7 @@ mod tests { #[test] fn hash_file() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path().join("hello.txt"); let mut file = File::create(&path).unwrap(); file.write_all("Hello".as_bytes()).unwrap(); diff --git a/src/remote.rs b/src/remote.rs index e3e41f130a..33dd912eb6 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -586,7 +586,7 @@ mod tests { use crate::{AutotagOption, PushOptions}; use crate::{Direction, FetchOptions, Remote, RemoteCallbacks, Repository}; use std::cell::Cell; - use tempdir::TempDir; + use tempfile::TempDir; #[test] fn smoke() { @@ -609,7 +609,7 @@ mod tests { #[test] fn create_remote() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let remote = td.path().join("remote"); Repository::init_bare(&remote).unwrap(); @@ -690,7 +690,7 @@ mod tests { #[test] fn create_remote_anonymous() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); let origin = repo.remote_anonymous("/path/to/nowhere").unwrap(); @@ -707,7 +707,7 @@ mod tests { #[test] fn transfer_cb() { let (td, _repo) = crate::test::repo_init(); - let td2 = TempDir::new("git").unwrap(); + let td2 = TempDir::new().unwrap(); let url = crate::test::path2url(https://github.com/&td.path()); let repo = Repository::init(td2.path()).unwrap(); @@ -743,7 +743,7 @@ mod tests { #[test] fn connect_list() { let (td, _repo) = crate::test::repo_init(); - let td2 = TempDir::new("git").unwrap(); + let td2 = TempDir::new().unwrap(); let url = crate::test::path2url(https://github.com/&td.path()); let repo = Repository::init(td2.path()).unwrap(); @@ -774,8 +774,8 @@ mod tests { #[test] fn push() { let (_td, repo) = crate::test::repo_init(); - let td2 = TempDir::new("git1").unwrap(); - let td3 = TempDir::new("git2").unwrap(); + let td2 = TempDir::new().unwrap(); + let td3 = TempDir::new().unwrap(); let url = crate::test::path2url(https://github.com/&td2.path()); Repository::init_bare(td2.path()).unwrap(); diff --git a/src/repo.rs b/src/repo.rs index e69ac8b051..b0331c0d40 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2583,11 +2583,11 @@ mod tests { use std::ffi::OsStr; use std::fs; use std::path::Path; - use tempdir::TempDir; + use tempfile::TempDir; #[test] fn smoke_init() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path(); let repo = Repository::init(path).unwrap(); @@ -2596,7 +2596,7 @@ mod tests { #[test] fn smoke_init_bare() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path(); let repo = Repository::init_bare(path).unwrap(); @@ -2606,7 +2606,7 @@ mod tests { #[test] fn smoke_open() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path(); Repository::init(td.path()).unwrap(); let repo = Repository::open(path).unwrap(); @@ -2622,7 +2622,7 @@ mod tests { #[test] fn smoke_open_bare() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let path = td.path(); Repository::init_bare(td.path()).unwrap(); @@ -2659,13 +2659,13 @@ mod tests { #[test] fn makes_dirs() { - let td = TempDir::new("foo").unwrap(); + let td = TempDir::new().unwrap(); Repository::init(&td.path().join("a/b/c/d")).unwrap(); } #[test] fn smoke_discover() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let subdir = td.path().join("subdi"); fs::create_dir(&subdir).unwrap(); Repository::init_bare(td.path()).unwrap(); @@ -2678,7 +2678,7 @@ mod tests { #[test] fn smoke_open_ext() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let subdir = td.path().join("subdir"); fs::create_dir(&subdir).unwrap(); Repository::init(td.path()).unwrap(); diff --git a/src/submodule.rs b/src/submodule.rs index 90ea1be10f..f5515f83fd 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -281,7 +281,7 @@ impl<'cb> Default for SubmoduleUpdateOptions<'cb> { mod tests { use std::fs; use std::path::Path; - use tempdir::TempDir; + use tempfile::TempDir; use url::Url; use crate::Repository; @@ -289,7 +289,7 @@ mod tests { #[test] fn smoke() { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); let mut s1 = repo .submodule("/path/to/nowhere", Path::new("foo"), true) diff --git a/src/test.rs b/src/test.rs index 6f885bd6f3..a3fe9448d8 100644 --- a/src/test.rs +++ b/src/test.rs @@ -2,7 +2,7 @@ use std::io; use std::path::{Path, PathBuf}; #[cfg(unix)] use std::ptr; -use tempdir::TempDir; +use tempfile::TempDir; use url::Url; use crate::Repository; @@ -17,7 +17,7 @@ macro_rules! t { } pub fn repo_init() -> (TempDir, Repository) { - let td = TempDir::new("test").unwrap(); + let td = TempDir::new().unwrap(); let repo = Repository::init(td.path()).unwrap(); { let mut config = repo.config().unwrap(); diff --git a/src/tree.rs b/src/tree.rs index 11db0cc9f0..9fd4e0cee1 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -403,7 +403,7 @@ mod tests { use std::fs::File; use std::io::prelude::*; use std::path::Path; - use tempdir::TempDir; + use tempfile::TempDir; pub struct TestTreeIter<'a> { entries: Vec>, From df7cd05426a8a9b94c33a3779c3f7d5e419424f5 Mon Sep 17 00:00:00 2001 From: Kornel Date: Thu, 8 Aug 2019 22:02:46 +0100 Subject: [PATCH 381/860] Correct dependency versions --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 18e635ef56..63fb297ad4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,9 +21,9 @@ azure-devops = { project = "rust-lang/git2-rs", pipeline = "rust-lang.git2-rs", [dependencies] url = "2.0" -bitflags = "1.0" +bitflags = "1.1.0" libc = "0.2" -log = "0.4" +log = "0.4.8" libgit2-sys = { path = "libgit2-sys", version = "0.8.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] From 792e0b35238cf4e32a6d7d5a6119c879f2ec4d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 13 Aug 2019 19:38:38 +0200 Subject: [PATCH 382/860] Update libgit2 submodule Includes a fix for a potential DoS/memory corruption and adds checks for configuration file in ProgramData. --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index e3adc99e1f..08cfa43d0e 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit e3adc99e1f9b71ceaddd650eba9c7c644290e4a6 +Subproject commit 08cfa43d0e1a9214a2f1239593686078e75e5636 From 3920a9465a3820f0c2c6e1840f2b7f3b958ce55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 13 Aug 2019 20:45:22 +0200 Subject: [PATCH 383/860] libgit2-sys: include new git_rebase_options fields --- libgit2-sys/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 7a2396cf0d..78722fc0bc 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1555,6 +1555,13 @@ pub type git_packbuilder_foreach_cb = extern "C" fn(*const c_void, size_t, *mut pub type git_odb_foreach_cb = extern "C" fn(id: *const git_oid, payload: *mut c_void) -> c_int; +pub type git_commit_signing_cb = extern "C" fn( + signature: *mut git_buf, + signature_field: *mut git_buf, + commit_content: *const c_char, + payload: *mut c_void, +) -> c_int; + pub const GIT_REBASE_NO_OPERATION: usize = usize::max_value(); #[repr(C)] @@ -1565,6 +1572,8 @@ pub struct git_rebase_options { pub rewrite_notes_ref: *const c_char, pub merge_options: git_merge_options, pub checkout_options: git_checkout_options, + pub signing_cb: git_commit_signing_cb, + pub payload: *mut c_void, } git_enum! { From dfae2e6882f819735cf683a702d9e5a3b04d963e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 13 Aug 2019 12:31:47 -0700 Subject: [PATCH 384/860] Wrap callbacks in struct fields in `Option` Pointed out by nightly rustc we're accidentally relying on undefined behavior right now by calling `mem::zeroed` on structs which internally contain non-nullable function references. Let's instead wrap everything in `Option` so the zero bit pattern is valid for these structs. --- libgit2-sys/lib.rs | 340 +++++++++++++++++++++++++-------------------- src/stash.rs | 2 +- src/transport.rs | 4 +- 3 files changed, 192 insertions(+), 154 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 78722fc0bc..3da70f6591 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1028,8 +1028,8 @@ pub struct git_diff_options { pub flags: u32, pub ignore_submodules: git_submodule_ignore_t, pub pathspec: git_strarray, - pub notify_cb: git_diff_notify_cb, - pub progress_cb: git_diff_progress_cb, + pub notify_cb: Option, + pub progress_cb: Option, pub payload: *mut c_void, pub context_lines: u32, pub interhunk_lines: u32, @@ -1238,174 +1238,212 @@ pub type git_transport_cb = extern "C" fn( #[repr(C)] pub struct git_transport { pub version: c_uint, - pub set_callbacks: extern "C" fn( - *mut git_transport, - git_transport_message_cb, - git_transport_message_cb, - git_transport_certificate_check_cb, - *mut c_void, - ) -> c_int, - pub set_custom_headers: extern "C" fn(*mut git_transport, *const git_strarray) -> c_int, - pub connect: extern "C" fn( - *mut git_transport, - *const c_char, - git_cred_acquire_cb, - *mut c_void, - *const git_proxy_options, - c_int, - c_int, - ) -> c_int, - pub ls: + pub set_callbacks: Option< + extern "C" fn( + *mut git_transport, + git_transport_message_cb, + git_transport_message_cb, + git_transport_certificate_check_cb, + *mut c_void, + ) -> c_int, + >, + pub set_custom_headers: Option c_int>, + pub connect: Option< + extern "C" fn( + *mut git_transport, + *const c_char, + git_cred_acquire_cb, + *mut c_void, + *const git_proxy_options, + c_int, + c_int, + ) -> c_int, + >, + pub ls: Option< extern "C" fn(*mut *mut *const git_remote_head, *mut size_t, *mut git_transport) -> c_int, - pub push: + >, + pub push: Option< extern "C" fn(*mut git_transport, *mut git_push, *const git_remote_callbacks) -> c_int, - pub negotiate_fetch: extern "C" fn( - *mut git_transport, - *mut git_repository, - *const *const git_remote_head, - size_t, - ) -> c_int, - pub download_pack: extern "C" fn( - *mut git_transport, - *mut git_repository, - *mut git_transfer_progress, - git_transfer_progress_cb, - *mut c_void, - ) -> c_int, - pub is_connected: extern "C" fn(*mut git_transport) -> c_int, - pub read_flags: extern "C" fn(*mut git_transport, *mut c_int) -> c_int, - pub cancel: extern "C" fn(*mut git_transport), - pub close: extern "C" fn(*mut git_transport) -> c_int, - pub free: extern "C" fn(*mut git_transport), + >, + pub negotiate_fetch: Option< + extern "C" fn( + *mut git_transport, + *mut git_repository, + *const *const git_remote_head, + size_t, + ) -> c_int, + >, + pub download_pack: Option< + extern "C" fn( + *mut git_transport, + *mut git_repository, + *mut git_transfer_progress, + git_transfer_progress_cb, + *mut c_void, + ) -> c_int, + >, + pub is_connected: Option c_int>, + pub read_flags: Option c_int>, + pub cancel: Option, + pub close: Option c_int>, + pub free: Option, } #[repr(C)] pub struct git_odb_backend { pub version: c_uint, pub odb: *mut git_odb, - pub read: extern "C" fn( - *mut *mut c_void, - *mut size_t, - *mut git_object_t, - *mut git_odb_backend, - *const git_oid, - ) -> c_int, - - pub read_prefix: extern "C" fn( - *mut git_oid, - *mut *mut c_void, - *mut size_t, - *mut git_object_t, - *mut git_odb_backend, - *const git_oid, - size_t, - ) -> c_int, - pub read_header: extern "C" fn( - *mut size_t, - *mut git_object_t, - *mut git_odb_backend, - *const git_oid, - ) -> c_int, - - pub write: extern "C" fn( - *mut git_odb_backend, - *const git_oid, - *const c_void, - size_t, - git_object_t, - ) -> c_int, - - pub writestream: extern "C" fn( - *mut *mut git_odb_stream, - *mut git_odb_backend, - git_off_t, - git_object_t, - ) -> c_int, - - pub readstream: extern "C" fn( - *mut *mut git_odb_stream, - *mut size_t, - *mut git_object_t, - *mut git_odb_backend, - *const git_oid, - ) -> c_int, - - pub exists: extern "C" fn(*mut git_odb_backend, *const git_oid) -> c_int, + pub read: Option< + extern "C" fn( + *mut *mut c_void, + *mut size_t, + *mut git_object_t, + *mut git_odb_backend, + *const git_oid, + ) -> c_int, + >, + + pub read_prefix: Option< + extern "C" fn( + *mut git_oid, + *mut *mut c_void, + *mut size_t, + *mut git_object_t, + *mut git_odb_backend, + *const git_oid, + size_t, + ) -> c_int, + >, + pub read_header: Option< + extern "C" fn( + *mut size_t, + *mut git_object_t, + *mut git_odb_backend, + *const git_oid, + ) -> c_int, + >, + + pub write: Option< + extern "C" fn( + *mut git_odb_backend, + *const git_oid, + *const c_void, + size_t, + git_object_t, + ) -> c_int, + >, + + pub writestream: Option< + extern "C" fn( + *mut *mut git_odb_stream, + *mut git_odb_backend, + git_off_t, + git_object_t, + ) -> c_int, + >, + + pub readstream: Option< + extern "C" fn( + *mut *mut git_odb_stream, + *mut size_t, + *mut git_object_t, + *mut git_odb_backend, + *const git_oid, + ) -> c_int, + >, + + pub exists: Option c_int>, pub exists_prefix: - extern "C" fn(*mut git_oid, *mut git_odb_backend, *const git_oid, size_t) -> c_int, + Option c_int>, - pub refresh: extern "C" fn(*mut git_odb_backend) -> c_int, + pub refresh: Option c_int>, - pub foreach: extern "C" fn(*mut git_odb_backend, git_odb_foreach_cb, *mut c_void) -> c_int, + pub foreach: + Option c_int>, - pub writepack: extern "C" fn( - *mut *mut git_odb_writepack, - *mut git_odb_backend, - *mut git_odb, - git_transfer_progress_cb, - *mut c_void, - ) -> c_int, + pub writepack: Option< + extern "C" fn( + *mut *mut git_odb_writepack, + *mut git_odb_backend, + *mut git_odb, + git_transfer_progress_cb, + *mut c_void, + ) -> c_int, + >, - pub freshen: extern "C" fn(*mut git_odb_backend, *const git_oid) -> c_int, + pub freshen: Option c_int>, - pub free: extern "C" fn(*mut git_odb_backend), + pub free: Option, } #[repr(C)] pub struct git_refdb_backend { pub version: c_uint, - pub exists: extern "C" fn(*mut c_int, *mut git_refdb_backend, *const c_char) -> c_int, - pub lookup: + pub exists: Option c_int>, + pub lookup: Option< extern "C" fn(*mut *mut git_reference, *mut git_refdb_backend, *const c_char) -> c_int, - pub iterator: extern "C" fn( - *mut *mut git_reference_iterator, - *mut git_refdb_backend, - *const c_char, - ) -> c_int, - pub write: extern "C" fn( - *mut git_refdb_backend, - *const git_reference, - c_int, - *const git_signature, - *const c_char, - *const git_oid, - *const c_char, - ) -> c_int, - pub rename: extern "C" fn( - *mut *mut git_reference, - *mut git_refdb_backend, - *const c_char, - *const c_char, - c_int, - *const git_signature, - *const c_char, - ) -> c_int, - pub del: extern "C" fn( - *mut git_refdb_backend, - *const c_char, - *const git_oid, - *const c_char, - ) -> c_int, - pub compress: extern "C" fn(*mut git_refdb_backend) -> c_int, - pub has_log: extern "C" fn(*mut git_refdb_backend, *const c_char) -> c_int, - pub ensure_log: extern "C" fn(*mut git_refdb_backend, *const c_char) -> c_int, - pub free: extern "C" fn(*mut git_refdb_backend), + >, + pub iterator: Option< + extern "C" fn( + *mut *mut git_reference_iterator, + *mut git_refdb_backend, + *const c_char, + ) -> c_int, + >, + pub write: Option< + extern "C" fn( + *mut git_refdb_backend, + *const git_reference, + c_int, + *const git_signature, + *const c_char, + *const git_oid, + *const c_char, + ) -> c_int, + >, + pub rename: Option< + extern "C" fn( + *mut *mut git_reference, + *mut git_refdb_backend, + *const c_char, + *const c_char, + c_int, + *const git_signature, + *const c_char, + ) -> c_int, + >, + pub del: Option< + extern "C" fn( + *mut git_refdb_backend, + *const c_char, + *const git_oid, + *const c_char, + ) -> c_int, + >, + pub compress: Option c_int>, + pub has_log: Option c_int>, + pub ensure_log: Option c_int>, + pub free: Option, pub reflog_read: - extern "C" fn(*mut *mut git_reflog, *mut git_refdb_backend, *const c_char) -> c_int, - pub reflog_write: extern "C" fn(*mut git_refdb_backend, *mut git_reflog) -> c_int, - pub reflog_rename: extern "C" fn(*mut git_refdb_backend, *const c_char, *const c_char) -> c_int, - pub reflog_delete: extern "C" fn(*mut git_refdb_backend, *const c_char) -> c_int, - pub lock: extern "C" fn(*mut *mut c_void, *mut git_refdb_backend, *const c_char) -> c_int, - pub unlock: extern "C" fn( - *mut git_refdb_backend, - *mut c_void, - c_int, - c_int, - *const git_reference, - *const git_signature, - *const c_char, - ) -> c_int, + Option c_int>, + pub reflog_write: Option c_int>, + pub reflog_rename: + Option c_int>, + pub reflog_delete: Option c_int>, + pub lock: + Option c_int>, + pub unlock: Option< + extern "C" fn( + *mut git_refdb_backend, + *mut c_void, + c_int, + c_int, + *const git_reference, + *const git_signature, + *const c_char, + ) -> c_int, + >, } #[repr(C)] @@ -1465,7 +1503,7 @@ pub type git_smart_subtransport_cb = #[repr(C)] pub struct git_smart_subtransport_definition { - pub callback: git_smart_subtransport_cb, + pub callback: Option, pub rpc: c_uint, pub param: *mut c_void, } @@ -1537,7 +1575,7 @@ pub struct git_stash_apply_options { pub version: c_uint, pub flags: git_stash_apply_flags, pub checkout_options: git_checkout_options, - pub progress_cb: git_stash_apply_progress_cb, + pub progress_cb: Option, pub progress_payload: *mut c_void, } @@ -1572,7 +1610,7 @@ pub struct git_rebase_options { pub rewrite_notes_ref: *const c_char, pub merge_options: git_merge_options, pub checkout_options: git_checkout_options, - pub signing_cb: git_commit_signing_cb, + pub signing_cb: Option, pub payload: *mut c_void, } diff --git a/src/stash.rs b/src/stash.rs index 465f63eb0d..f2654fa950 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -65,7 +65,7 @@ impl<'cb> StashApplyOptions<'cb> { C: FnMut(StashApplyProgress) -> bool + 'cb, { self.progress = Some(Box::new(callback) as Box>); - self.raw_opts.progress_cb = stash_apply_progress_cb; + self.raw_opts.progress_cb = Some(stash_apply_progress_cb); self.raw_opts.progress_payload = self as *mut _ as *mut _; self } diff --git a/src/transport.rs b/src/transport.rs index b5938d3aa8..0543c39779 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -148,7 +148,7 @@ impl Transport { obj: Box::new(subtransport), }); let mut defn = raw::git_smart_subtransport_definition { - callback: smart_factory, + callback: Some(smart_factory), rpc: rpc as c_uint, param: &mut *raw as *mut _ as *mut _, }; @@ -190,7 +190,7 @@ impl Transport { impl Drop for Transport { fn drop(&mut self) { if self.owned { - unsafe { ((*self.raw).free)(self.raw) } + unsafe { (*self.raw).free.unwrap()(self.raw) } } } } From acec73d4a54a057da4480ec2bc8c7d9e81cdbc07 Mon Sep 17 00:00:00 2001 From: Tom Forbes Date: Thu, 15 Aug 2019 18:15:31 +0100 Subject: [PATCH 385/860] Fix typo in status_file --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index b0331c0d40..975511163a 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -837,7 +837,7 @@ impl Repository { pub fn status_file(&self, path: &Path) -> Result { let mut ret = 0 as c_uint; let path = if cfg!(windows) { - // `git_status_file` dose not work with windows path separator + // `git_status_file` does not work with windows path separator // so we convert \ to / std::ffi::CString::new(path.to_string_lossy().replace('\\', "/"))? } else { From cc56be015fbc6daf9ffaf03eac75293e5348bb92 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 13 Aug 2019 12:34:23 -0700 Subject: [PATCH 386/860] Bump version numbers of crates * Bump main crate to 0.10.0 * Bump libgit2-sys to 0.9.0 * Bump git2-curl to 0.11.0 --- Cargo.toml | 4 ++-- README.md | 2 +- git2-curl/Cargo.toml | 4 ++-- git2-curl/src/lib.rs | 2 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/lib.rs | 2 +- src/lib.rs | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c2627ef1c7..003cdec6f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.9.2" +version = "0.10.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -24,7 +24,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.8.2" } +libgit2-sys = { path = "libgit2-sys", version = "0.9.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/README.md b/README.md index f34b740aa4..885570f3d7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ libgit2 bindings for Rust ```toml [dependencies] -git2 = "0.9" +git2 = "0.10" ``` ## Rust version requirements diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 99d73b9dde..599a0dddef 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.10.1" +version = "0.11.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" @@ -17,7 +17,7 @@ edition = "2018" curl = "0.4" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.9", default-features = false } +git2 = { path = "..", version = "0.10", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index a036a5e42a..59b10c2839 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -15,7 +15,7 @@ //! > **NOTE**: At this time this crate likely does not support a `git push` //! > operation, only clones. -#![doc(html_root_url = "https://docs.rs/git2-curl/0.10")] +#![doc(html_root_url = "https://docs.rs/git2-curl/0.11")] #![deny(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index ae2a0184b8..e85f09b301 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.8.2" +version = "0.9.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 3da70f6591..dd808d6a23 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.8")] +#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.9")] #![allow(non_camel_case_types, unused_extern_crates)] // This is required to link libz when libssh2-sys is not included. diff --git a/src/lib.rs b/src/lib.rs index 08440357e4..b48b492d43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,7 +63,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.9")] +#![doc(html_root_url = "https://docs.rs/git2/0.10")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] From ce6a1ef463bd4455dbef06c961a2f89452086863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 20 Aug 2019 09:09:49 +0200 Subject: [PATCH 387/860] rebase: keep track of the rewrite_notes_ref string We can't just take the pointer, as Rust won't know to free it when the options struct will go out of scope. --- src/rebase.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/rebase.rs b/src/rebase.rs index 598acecd19..b486b8a698 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -10,6 +10,7 @@ use crate::{raw, Error, Index, MergeOptions, Oid, Signature}; /// Use to tell the rebase machinery how to operate. pub struct RebaseOptions<'cb> { raw: raw::git_rebase_options, + rewrite_notes_ref: Option, merge_options: Option, checkout_options: Option>, } @@ -25,6 +26,7 @@ impl<'cb> RebaseOptions<'cb> { pub fn new() -> RebaseOptions<'cb> { let mut opts = RebaseOptions { raw: unsafe { mem::zeroed() }, + rewrite_notes_ref: None, merge_options: None, checkout_options: None, }; @@ -59,8 +61,7 @@ impl<'cb> RebaseOptions<'cb> { /// is set to false. If `notes.rewriteRef` is also NULL, notes will /// not be rewritten. pub fn rewrite_notes_ref(&mut self, rewrite_notes_ref: &str) -> &mut RebaseOptions<'cb> { - let s = CString::new(rewrite_notes_ref).unwrap().as_ptr(); - self.raw.rewrite_notes_ref = s; + self.rewrite_notes_ref = Some(CString::new(rewrite_notes_ref).unwrap()); self } @@ -90,6 +91,11 @@ impl<'cb> RebaseOptions<'cb> { if let Some(opts) = self.checkout_options.as_mut() { opts.configure(&mut self.raw.checkout_options); } + self.raw.rewrite_notes_ref = self + .rewrite_notes_ref + .as_ref() + .map(|s| s.as_ptr()) + .unwrap_or(ptr::null()); } &self.raw } From 7ded1178ad4f8372bed4ed0f4067ef8afa0295e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 20 Aug 2019 09:40:25 +0200 Subject: [PATCH 388/860] rebase: no need to forget the options We don't have anything to drop. --- src/rebase.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/rebase.rs b/src/rebase.rs index b486b8a698..bb9e72d4f7 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -86,7 +86,6 @@ impl<'cb> RebaseOptions<'cb> { unsafe { if let Some(opts) = self.merge_options.as_mut().take() { ptr::copy_nonoverlapping(opts.raw(), &mut self.raw.merge_options, 1); - mem::forget(opts); } if let Some(opts) = self.checkout_options.as_mut() { opts.configure(&mut self.raw.checkout_options); From c209c4030285c0e30baa1e35ad36fb783039098b Mon Sep 17 00:00:00 2001 From: ksqsf Date: Fri, 30 Aug 2019 01:59:23 +0800 Subject: [PATCH 389/860] Add `Blob::size()` --- src/blob.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/blob.rs b/src/blob.rs index d4d3a00ee4..d8cb48fe41 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -34,6 +34,11 @@ impl<'repo> Blob<'repo> { } } + /// Get the size of this blob. + pub fn size(&self) -> usize { + unsafe { raw::git_blob_rawsize(&*self.raw) as usize } + } + /// Casts this Blob to be usable as an `Object` pub fn as_object(&self) -> &Object<'repo> { unsafe { &*(self as *const _ as *const Object<'repo>) } @@ -156,6 +161,7 @@ mod tests { let blob = repo.find_blob(id).unwrap(); assert_eq!(blob.id(), id); + assert_eq!(blob.size(), 3); assert_eq!(blob.content(), [5, 4, 6]); assert!(blob.is_binary()); From fc65a01c65ac9047eb82e423af9c876d60bc34bc Mon Sep 17 00:00:00 2001 From: ksqsf Date: Sun, 1 Sep 2019 01:31:13 +0800 Subject: [PATCH 390/860] Improve doc comment of `Blob::size()` Co-Authored-By: Eric Huss --- src/blob.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blob.rs b/src/blob.rs index d8cb48fe41..93159f68e3 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -34,7 +34,7 @@ impl<'repo> Blob<'repo> { } } - /// Get the size of this blob. + /// Get the size in bytes of the contents of this blob. pub fn size(&self) -> usize { unsafe { raw::git_blob_rawsize(&*self.raw) as usize } } From 05170635cd953f6006a4c1a9fd811b151cd8b654 Mon Sep 17 00:00:00 2001 From: ksqsf Date: Sun, 1 Sep 2019 01:42:54 +0800 Subject: [PATCH 391/860] Change the return type of `Blob::size()` to u64 --- src/blob.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/blob.rs b/src/blob.rs index 93159f68e3..e62141e437 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -35,8 +35,8 @@ impl<'repo> Blob<'repo> { } /// Get the size in bytes of the contents of this blob. - pub fn size(&self) -> usize { - unsafe { raw::git_blob_rawsize(&*self.raw) as usize } + pub fn size(&self) -> u64 { + unsafe { raw::git_blob_rawsize(&*self.raw) as u64 } } /// Casts this Blob to be usable as an `Object` From e282581bf352b8e587e134d78138dc052554322d Mon Sep 17 00:00:00 2001 From: Fredrik Larsson Date: Tue, 3 Sep 2019 23:33:17 +0200 Subject: [PATCH 392/860] Add merge_base_many and merge_bases_many for Repository --- libgit2-sys/lib.rs | 14 +++++ src/repo.rs | 148 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index dd808d6a23..234ec3003a 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2879,6 +2879,13 @@ extern "C" { two: *const git_oid, ) -> c_int; + pub fn git_merge_base_many( + out: *mut git_oid, + repo: *mut git_repository, + length: size_t, + input_array: *const git_oid, + ) -> c_int; + pub fn git_merge_bases( out: *mut git_oidarray, repo: *mut git_repository, @@ -2886,6 +2893,13 @@ extern "C" { two: *const git_oid, ) -> c_int; + pub fn git_merge_bases_many( + out: *mut git_oidarray, + repo: *mut git_repository, + length: size_t, + input_array: *const git_oid, + ) -> c_int; + // pathspec pub fn git_pathspec_free(ps: *mut git_pathspec); pub fn git_pathspec_match_diff( diff --git a/src/repo.rs b/src/repo.rs index 975511163a..29db5ed3bd 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1973,6 +1973,25 @@ impl Repository { } } + /// Find a merge base given a list of commits + pub fn merge_base_many(&self, oids: &[Oid]) -> Result { + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; + + unsafe { + let raw_oids = oids.iter().map(|oid| *oid.raw()).collect::>(); + + try_call!(raw::git_merge_base_many( + &mut raw, + self.raw, + oids.len() as size_t, + raw_oids.as_ptr() + )); + Ok(Binding::from_raw(&raw as *const _)) + } + } + /// Find all merge bases between two commits pub fn merge_bases(&self, one: Oid, two: Oid) -> Result { let mut arr = raw::git_oidarray { @@ -1990,6 +2009,25 @@ impl Repository { } } + /// Find all merge bases given a list of commits + pub fn merge_bases_many(&self, oids: &[Oid]) -> Result { + let mut arr = raw::git_oidarray { + ids: ptr::null_mut(), + count: 0, + }; + unsafe { + let raw_oids = oids.iter().map(|oid| *oid.raw()).collect::>(); + + try_call!(raw::git_merge_bases_many( + &mut arr, + self.raw, + oids.len() as size_t, + raw_oids.as_ptr() + )); + Ok(Binding::from_raw(arr)) + } + } + /// Count the number of unique commits between two commit objects /// /// There is no need for branches containing the commits to have any @@ -2802,6 +2840,98 @@ mod tests { assert_eq!(repo.head().unwrap().target().unwrap(), master_oid); } + /// create the following: + /// /---o4 + /// /---o3 + /// o1---o2 + #[test] + fn smoke_merge_base() { + let (_td, repo) = graph_repo_init(); + let sig = repo.signature().unwrap(); + + // let oid1 = head + let oid1 = repo.head().unwrap().target().unwrap(); + let commit1 = repo.find_commit(oid1).unwrap(); + println!("created oid1 {:?}", oid1); + + repo.branch("branch_a", &commit1, true).unwrap(); + repo.branch("branch_b", &commit1, true).unwrap(); + repo.branch("branch_c", &commit1, true).unwrap(); + + // create commit oid2 on branch_a + let mut index = repo.index().unwrap(); + let p = Path::new(repo.workdir().unwrap()).join("file_a"); + println!("using path {:?}", p); + fs::File::create(&p).unwrap(); + index.add_path(Path::new("file_a")).unwrap(); + let id_a = index.write_tree().unwrap(); + let tree_a = repo.find_tree(id_a).unwrap(); + let oid2 = repo + .commit( + Some("refs/heads/branch_a"), + &sig, + &sig, + "commit 2", + &tree_a, + &[&commit1], + ) + .unwrap(); + repo.find_commit(oid2).unwrap(); + println!("created oid2 {:?}", oid2); + + t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); + + // create commit oid3 on branch_b + let mut index = repo.index().unwrap(); + let p = Path::new(repo.workdir().unwrap()).join("file_b"); + fs::File::create(&p).unwrap(); + index.add_path(Path::new("file_b")).unwrap(); + let id_b = index.write_tree().unwrap(); + let tree_b = repo.find_tree(id_b).unwrap(); + let oid3 = repo + .commit( + Some("refs/heads/branch_b"), + &sig, + &sig, + "commit 3", + &tree_b, + &[&commit1], + ) + .unwrap(); + repo.find_commit(oid3).unwrap(); + println!("created oid3 {:?}", oid3); + + t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); + + // create commit oid4 on branch_c + let mut index = repo.index().unwrap(); + let p = Path::new(repo.workdir().unwrap()).join("file_c"); + fs::File::create(&p).unwrap(); + index.add_path(Path::new("file_c")).unwrap(); + let id_c = index.write_tree().unwrap(); + let tree_c = repo.find_tree(id_c).unwrap(); + let oid4 = repo + .commit( + Some("refs/heads/branch_c"), + &sig, + &sig, + "commit 3", + &tree_c, + &[&commit1], + ) + .unwrap(); + repo.find_commit(oid4).unwrap(); + println!("created oid4 {:?}", oid4); + + // the merge base of (oid2,oid3) should be oid1 + let merge_base = repo.merge_base(oid2, oid3).unwrap(); + assert_eq!(merge_base, oid1); + + // the merge base of (oid2,oid3,oid4) should be oid1 + let merge_base = repo.merge_base_many(&[oid2, oid3, oid4]).unwrap(); + assert_eq!(merge_base, oid1); + } + /// create an octopus: /// /---o2-o4 /// o1 X @@ -2914,6 +3044,24 @@ mod tests { assert!(found_oid2); assert!(found_oid3); assert_eq!(merge_bases.len(), 2); + + // merge bases of (oid4,oid5) should be (oid2,oid3) + let merge_bases = repo.merge_bases_many(&[oid4, oid5]).unwrap(); + let mut found_oid2 = false; + let mut found_oid3 = false; + for mg in merge_bases.iter() { + println!("found merge base {:?}", mg); + if mg == &oid2 { + found_oid2 = true; + } else if mg == &oid3 { + found_oid3 = true; + } else { + assert!(false); + } + } + assert!(found_oid2); + assert!(found_oid3); + assert_eq!(merge_bases.len(), 2); } #[test] From b9dc8124ff14d37dd3ab8a9d512e28d431525704 Mon Sep 17 00:00:00 2001 From: ksqsf Date: Thu, 5 Sep 2019 01:22:24 +0800 Subject: [PATCH 393/860] Revert "Change the return type of `Blob::size()` to u64" This reverts commit 05170635cd953f6006a4c1a9fd811b151cd8b654. --- src/blob.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/blob.rs b/src/blob.rs index e62141e437..93159f68e3 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -35,8 +35,8 @@ impl<'repo> Blob<'repo> { } /// Get the size in bytes of the contents of this blob. - pub fn size(&self) -> u64 { - unsafe { raw::git_blob_rawsize(&*self.raw) as u64 } + pub fn size(&self) -> usize { + unsafe { raw::git_blob_rawsize(&*self.raw) as usize } } /// Casts this Blob to be usable as an `Object` From 92491dbcc12cdcc73194859e6ea68f293a256bb2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Sep 2019 08:59:25 -0700 Subject: [PATCH 394/860] Enable the `parallel` feature of `cc` There's a lot of C objects to compile so serial compilation can actually take quite some time! This enables the `parallel` feature of the `cc` crate to compile objects in parallel and regain some build time back. --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index e85f09b301..31762ca3a5 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -23,7 +23,7 @@ libz-sys = "1.0.22" [build-dependencies] pkg-config = "0.3.7" -cc = "1.0.25" +cc = { version = "1.0.25", features = ['parallel'] } [target.'cfg(unix)'.dependencies] openssl-sys = { version = "0.9", optional = true } From 054f06c2e028ee37bbcda375cc2de3382f0dc626 Mon Sep 17 00:00:00 2001 From: Fredrik Larsson Date: Thu, 5 Sep 2019 18:12:18 +0200 Subject: [PATCH 395/860] Use #[repr(C)] for Oid to enable pointer cast of slice ref in raw call --- src/oid.rs | 1 + src/repo.rs | 8 ++------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/oid.rs b/src/oid.rs index 4bbb16663a..4f69bec8ef 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -11,6 +11,7 @@ use crate::util::{c_cmp_to_ordering, Binding}; /// Unique identity of any object (commit, tree, blob, tag). #[derive(Copy, Clone)] +#[repr(C)] pub struct Oid { raw: raw::git_oid, } diff --git a/src/repo.rs b/src/repo.rs index 29db5ed3bd..a60253231a 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1980,13 +1980,11 @@ impl Repository { }; unsafe { - let raw_oids = oids.iter().map(|oid| *oid.raw()).collect::>(); - try_call!(raw::git_merge_base_many( &mut raw, self.raw, oids.len() as size_t, - raw_oids.as_ptr() + oids.as_ptr() as *const raw::git_oid )); Ok(Binding::from_raw(&raw as *const _)) } @@ -2016,13 +2014,11 @@ impl Repository { count: 0, }; unsafe { - let raw_oids = oids.iter().map(|oid| *oid.raw()).collect::>(); - try_call!(raw::git_merge_bases_many( &mut arr, self.raw, oids.len() as size_t, - raw_oids.as_ptr() + oids.as_ptr() as *const raw::git_oid )); Ok(Binding::from_raw(arr)) } From 43e4afb54f27921c4486c916510cea3c38e17973 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Sep 2019 11:24:12 -0700 Subject: [PATCH 396/860] Bump to 0.10.1 and 0.9.1 Publish a version of `libgit2-sys` which activates the `parallel` feature and otherwise pull in recent changes to `git2` as well. --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 003cdec6f7..cc53f90e18 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2" -version = "0.10.0" +version = "0.10.1" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -24,7 +24,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.9.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.9.1" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 31762ca3a5..097da61ac8 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.9.0" +version = "0.9.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" @@ -23,7 +23,7 @@ libz-sys = "1.0.22" [build-dependencies] pkg-config = "0.3.7" -cc = { version = "1.0.25", features = ['parallel'] } +cc = { version = "1.0.42", features = ['parallel'] } [target.'cfg(unix)'.dependencies] openssl-sys = { version = "0.9", optional = true } From c9aaff5a2b60c562fcf178bbdb4f9bb1c4e008db Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 Sep 2019 21:22:57 -0500 Subject: [PATCH 397/860] Migrate to Github Actions from Azure Pipelines (#468) Gives us more parallelism while also making user management easier! --- .github/workflows/main.yml | 58 ++++++++++++++++++++++++++++++++++++ Cargo.toml | 3 -- README.md | 2 -- azure-pipelines.yml | 60 -------------------------------------- ci/azure-install-rust.yml | 33 --------------------- ci/azure-test-all.yml | 11 ------- 6 files changed, 58 insertions(+), 109 deletions(-) create mode 100644 .github/workflows/main.yml delete mode 100644 azure-pipelines.yml delete mode 100644 ci/azure-install-rust.yml delete mode 100644 ci/azure-test-all.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000..d82cf73184 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,58 @@ +name: CI +on: [push, pull_request] + +jobs: + test: + name: Test + runs-on: ${{ matrix.os }} + strategy: + matrix: + build: [stable, beta, nightly, macos, windows] + include: + - build: stable + os: ubuntu-latest + rust: stable + - build: beta + os: ubuntu-latest + rust: beta + - build: nightly + os: ubuntu-latest + rust: nightly + - build: macos + os: macos-latest + rust: stable + - build: windows + os: windows-latest + rust: stable + steps: + - uses: actions/checkout@master + - name: Install Rust (rustup) + run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} + if: matrix.os != 'macos-latest' + - name: Install Rust (macos) + run: | + curl https://sh.rustup.rs | sh -s -- -y + echo "##[add-path]$HOME/.cargo/bin" + if: matrix.os == 'macos-latest' + - run: cargo test --no-default-features + - run: cargo test + - run: cargo run --manifest-path systest/Cargo.toml + - run: cargo test --manifest-path git2-curl/Cargo.toml + + rustfmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: rustup update stable && rustup default stable && rustup component add rustfmt + - run: cargo fmt -- --check + + msrv: + name: MSRV + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: rustup update 1.33.0 && rustup default 1.33.0 + - run: cargo build diff --git a/Cargo.toml b/Cargo.toml index cc53f90e18..ea49d74c9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,9 +16,6 @@ repositories. categories = ["api-bindings"] edition = "2018" -[badges] -azure-devops = { project = "rust-lang/git2-rs", pipeline = "rust-lang.git2-rs", build="9" } - [dependencies] url = "2.0" bitflags = "1.1.0" diff --git a/README.md b/README.md index 885570f3d7..459db8861a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # git2-rs -[![Build Status](https://dev.azure.com/rust-lang/git2-rs/_apis/build/status/rust-lang.git2-rs?branchName=master)](https://dev.azure.com/rust-lang/git2-rs/_build/latest?definitionId=9&branchName=master) - [Documentation](https://docs.rs/git2) libgit2 bindings for Rust diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 2a514738cb..0000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,60 +0,0 @@ -trigger: - - master - -jobs: - - job: rustfmt - pool: - vmImage: ubuntu-16.04 - steps: - - template: ci/azure-install-rust.yml - - bash: | - set -ex - rustup component add rustfmt - cargo fmt --all -- --check - displayName: "rustfmt check" - variables: - TOOLCHAIN: stable - - - job: MSRV - pool: - vmImage: ubuntu-16.04 - steps: - - template: ci/azure-install-rust.yml - - script: cargo build - displayName: "Build crate" - variables: - TOOLCHAIN: 1.33.0 - - - job: Linux - pool: - vmImage: ubuntu-16.04 - steps: - - template: ci/azure-test-all.yml - strategy: - matrix: - stable: - TOOLCHAIN: stable - beta: - TOOLCHAIN: beta - nightly: - TOOLCHAIN: nightly - - - job: macOS - pool: - vmImage: macos-10.13 - steps: - - template: ci/azure-test-all.yml - variables: - TOOLCHAIN: stable - - - job: Windows - pool: - vmImage: vs2017-win2016 - steps: - - template: ci/azure-test-all.yml - strategy: - matrix: - x86_64-msvc: - TOOLCHAIN: stable-x86_64-pc-windows-msvc - i686-msvc: - TOOLCHAIN: stable-i686-pc-windows-msvc diff --git a/ci/azure-install-rust.yml b/ci/azure-install-rust.yml deleted file mode 100644 index b99f1cf18e..0000000000 --- a/ci/azure-install-rust.yml +++ /dev/null @@ -1,33 +0,0 @@ -steps: - # Rustup is currently installed on Windows and Linux, but not macOS. - # It is installed in /usr/local/cargo/bin/ or C:\Program Files\Rust\.cargo\bin\ - # This steps ensures that rustup is installed, mainly for macOS, or if the - # azure image changes in the future. - - bash: | - set -ex - if [ -x "`command -v rustup`" ]; then - echo `command -v rustup` `rustup -V` already installed - rustup self update - else - if [ "$Agent.OS" = "Windows_NT" ]; then - curl -sSf -o rustup-init.exe https://win.rustup.rs - rustup-init.exe -y --default-toolchain $TOOLCHAIN - echo ##vso[task.prependpath]$USERPROFILE\.cargo\bin - else - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $TOOLCHAIN - echo "##vso[task.prependpath]$HOME/.cargo/bin" - fi - fi - displayName: Install rustup - - - bash: | - set -ex - rustup update $TOOLCHAIN - rustup default $TOOLCHAIN - displayName: Install rust - - - bash: | - set -ex - rustc -Vv - cargo -V - displayName: Query rust and cargo versions diff --git a/ci/azure-test-all.yml b/ci/azure-test-all.yml deleted file mode 100644 index 5f9124c302..0000000000 --- a/ci/azure-test-all.yml +++ /dev/null @@ -1,11 +0,0 @@ -steps: - - template: azure-install-rust.yml - - - bash: cargo test --no-default-features - displayName: "cargo test --no-default-features" - - bash: cargo test - displayName: "cargo test" - - bash: cargo run --manifest-path systest/Cargo.toml - displayName: "run systest" - - bash: cargo test --manifest-path git2-curl/Cargo.toml - displayName: "test git2-curl" From 6909754adb08402343f89c7ebb23c9b31d8104e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Kj=C3=A4ll?= Date: Tue, 17 Sep 2019 22:04:18 +0200 Subject: [PATCH 398/860] Fix documentation bug The c function name was referenced instead of the rust function name. --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index a60253231a..02e660d9d2 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1671,7 +1671,7 @@ impl Repository { /// /// For compatibility with git, the repository is put into a merging state. /// Once the commit is done (or if the user wishes to abort), you should - /// clear this state by calling git_repository_state_cleanup(). + /// clear this state by calling cleanup_state(). pub fn merge( &self, annotated_commits: &[&AnnotatedCommit<'_>], From 36e7bf96c50401d1be5cafd9e86504aefc5e12e1 Mon Sep 17 00:00:00 2001 From: Atul Bhosale Date: Wed, 25 Sep 2019 19:21:23 +0700 Subject: [PATCH 399/860] Format code using 'cargo fmt' --- git2-curl/tests/all.rs | 2 +- src/blame.rs | 1 - src/build.rs | 1 - src/lib.rs | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/git2-curl/tests/all.rs b/git2-curl/tests/all.rs index 03c68b7b10..c7f09dd40a 100644 --- a/git2-curl/tests/all.rs +++ b/git2-curl/tests/all.rs @@ -68,7 +68,7 @@ fn main() { let b = r.find_branch("master", git2::BranchType::Local).unwrap(); let id = b.get().target().unwrap(); let obj = r.find_object(id, None).unwrap(); - r.reset(&obj, git2::ResetType::Hard, None).unwrap();; + r.reset(&obj, git2::ResetType::Hard, None).unwrap(); assert!(File::open(&td2.path().join("bar")).is_ok()); } diff --git a/src/blame.rs b/src/blame.rs index 1341c147aa..5c582458df 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -323,5 +323,4 @@ mod tests { assert_eq!(hunk.lines_in_hunk(), 0); assert!(!hunk.is_boundary()) } - } diff --git a/src/build.rs b/src/build.rs index c1ca06ed61..397ad75d55 100644 --- a/src/build.rs +++ b/src/build.rs @@ -719,5 +719,4 @@ mod tests { repo.checkout_index(Some(&mut index), Some(&mut checkout_opts)) .unwrap(); } - } diff --git a/src/lib.rs b/src/lib.rs index b48b492d43..e24196c1b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1339,5 +1339,4 @@ mod tests { assert_eq!(ObjectType::from_str("blob"), Some(ObjectType::Blob)); assert!(ObjectType::Blob.is_loose()); } - } From f28a70902db0af88eb2d3bba099c723a8feaafa6 Mon Sep 17 00:00:00 2001 From: Roman Date: Mon, 7 Oct 2019 07:18:34 +0200 Subject: [PATCH 400/860] replace the azure link in the readme the readme contained a url to the azure pipelines which were replaced with GitHub actions in #468 (c9aaff5a2b60c562fcf178bbdb4f9bb1c4e008db). --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 459db8861a..2d565a7d7f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ git2 = "0.10" ## Rust version requirements git2-rs works with stable Rust, and typically works with the most recent prior -stable release as well. Check [azure-pipelines.yml](azure-pipelines.yml) to see the oldest +stable release as well. Check [GitHub Actions](https://github.com/rust-lang/git2-rs/actions) to see the oldest version of Rust known to pass tests. ## Version of libgit2 From 45ecf12d4ca02873c84f9473d94f23a280fe3dd9 Mon Sep 17 00:00:00 2001 From: Roman Date: Mon, 7 Oct 2019 20:40:16 +0200 Subject: [PATCH 401/860] change from the GitHub actions tab to the workflow definition Co-Authored-By: Eric Huss --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d565a7d7f..a79d7fd9ea 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ git2 = "0.10" ## Rust version requirements git2-rs works with stable Rust, and typically works with the most recent prior -stable release as well. Check [GitHub Actions](https://github.com/rust-lang/git2-rs/actions) to see the oldest +stable release as well. Check the MSRV job of [the CI script](.github/workflows/main.yml) to see the oldest version of Rust known to pass tests. ## Version of libgit2 From 12202bfc0cb4a456bfb5747244393e6bdb491b41 Mon Sep 17 00:00:00 2001 From: Kristoffer Haugsbakk Date: Fri, 18 Oct 2019 17:01:05 +0200 Subject: [PATCH 402/860] Link to a blog post about git-notes(1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation for the `Note` struct contains an expired link—the blog doesn’t exist any more. So replace that with a link to a good (and live) blog post about git-notes(1) from 2011. Fixes #480 --- src/note.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/note.rs b/src/note.rs index 39c2576100..99f7a686e8 100644 --- a/src/note.rs +++ b/src/note.rs @@ -6,7 +6,7 @@ use crate::{raw, signature, Error, Oid, Repository, Signature}; /// A structure representing a [note][note] in git. /// -/// [note]: http://git-scm.com/blog/2010/08/25/notes.html +/// [note]: http://alblue.bandlem.com/2011/11/git-tip-of-week-git-notes.html pub struct Note<'repo> { raw: *mut raw::git_note, From cb97807ea198e06a9ee5192c14747caec9006a60 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 28 Oct 2019 07:41:11 -0700 Subject: [PATCH 403/860] Fix Github Actions for recent system changes --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d82cf73184..bfe2a70cd2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,6 +29,7 @@ jobs: - name: Install Rust (rustup) run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} if: matrix.os != 'macos-latest' + shell: bash - name: Install Rust (macos) run: | curl https://sh.rustup.rs | sh -s -- -y From e7973c4f9b877bb2005eae704a89e141d0e9f074 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" <193874+carols10cents@users.noreply.github.com> Date: Mon, 28 Oct 2019 15:25:39 -0400 Subject: [PATCH 404/860] Fix 2 typos --- src/cred.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cred.rs b/src/cred.rs index 6d7c59ebe2..3bc443746b 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -137,7 +137,7 @@ impl Cred { /// Create a credential to specify a username. /// - /// THis is used with ssh authentication to query for the username if non is + /// This is used with ssh authentication to query for the username if none is /// specified in the url. pub fn username(username: &str) -> Result { crate::init(); From 6b8063ef84ef04d0325d886dfd4d8832980f68f9 Mon Sep 17 00:00:00 2001 From: Sebastian Wiesner Date: Sun, 3 Nov 2019 11:40:23 +0100 Subject: [PATCH 405/860] Add support for remotes of branches Wrap git_branch_upstream_name and git_branch_upstream_remote which retrieve the configured upstream remote and branch, but do not attempt to resolve them, i.e. these functions don't fail if the configured upstream doesn't exist. Closes GH-469 --- libgit2-sys/lib.rs | 10 ++++++++++ src/repo.rs | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 234ec3003a..0f1b942497 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2424,6 +2424,16 @@ extern "C" { ) -> c_int; pub fn git_branch_upstream(out: *mut *mut git_reference, branch: *const git_reference) -> c_int; + pub fn git_branch_upstream_name( + out: *mut git_buf, + repo: *mut git_repository, + refname: *const c_char, + ) -> c_int; + pub fn git_branch_upstream_remote( + out: *mut git_buf, + repo: *mut git_repository, + refname: *const c_char, + ) -> c_int; // index pub fn git_index_add(index: *mut git_index, entry: *const git_index_entry) -> c_int; diff --git a/src/repo.rs b/src/repo.rs index 02e660d9d2..451f912ad1 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2433,6 +2433,31 @@ impl Repository { Ok(()) } } + + /// Retrieves the name of the reference supporting the remote tracking branch, + /// given the name of a local branch reference. + pub fn branch_upstream_name(&self, refname: &str) -> Result { + let refname = CString::new(refname)?; + unsafe { + let buf = Buf::new(); + try_call!(raw::git_branch_upstream_name(buf.raw(), self.raw, refname)); + Ok(buf) + } + } + + /// Retrieve the name of the upstream remote of a local branch. + pub fn branch_upstream_remote(&self, refname: &str) -> Result { + let refname = CString::new(refname)?; + unsafe { + let buf = Buf::new(); + try_call!(raw::git_branch_upstream_remote( + buf.raw(), + self.raw, + refname + )); + Ok(buf) + } + } } impl Binding for Repository { From 6db585162cb6f1dbf4b3ea30b64920438ed12732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Kj=C3=A4ll?= Date: Sun, 10 Nov 2019 08:44:16 +0100 Subject: [PATCH 406/860] fixed a documentation typo --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 451f912ad1..e667206cf9 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1156,7 +1156,7 @@ impl Repository { } } - /// Creates a `AnnotatedCommit` from the given commit id. + /// Creates an `AnnotatedCommit` from the given commit id. pub fn find_annotated_commit(&self, id: Oid) -> Result, Error> { unsafe { let mut raw = ptr::null_mut(); From 3eb498a380d0331312802c239778f2320c3a6096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Kj=C3=A4ll?= Date: Fri, 8 Nov 2019 20:40:30 +0100 Subject: [PATCH 407/860] added bindings for git_commit_create_buffer --- libgit2-sys/lib.rs | 11 +++++++++++ src/repo.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 0f1b942497..dc552c0a64 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2359,6 +2359,17 @@ extern "C" { parent_count: size_t, parents: *mut *const git_commit, ) -> c_int; + pub fn git_commit_create_buffer( + out: *mut git_buf, + repo: *mut git_repository, + author: *const git_signature, + committer: *const git_signature, + message_encoding: *const c_char, + message: *const c_char, + tree: *const git_tree, + parent_count: size_t, + parents: *mut *const git_commit, + ) -> c_int; pub fn git_commit_header_field( out: *mut git_buf, commit: *const git_commit, diff --git a/src/repo.rs b/src/repo.rs index e667206cf9..1bdd90fa5a 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1089,6 +1089,40 @@ impl Repository { } } + /// Create a commit object and return that as a string. + /// + /// This string is suitable to be passed to the `commit_signed` function, + /// the arguments behave the same as in the `commit` function. + pub fn commit_create_buffer( + &self, + author: &Signature<'_>, + committer: &Signature<'_>, + message: &str, + tree: &Tree<'_>, + parents: &[&Commit<'_>], + ) -> Result { + let mut parent_ptrs = parents + .iter() + .map(|p| p.raw() as *const raw::git_commit) + .collect::>(); + let message = CString::new(message)?; + let buf = Buf::new(); + unsafe { + try_call!(raw::git_commit_create_buffer( + buf.raw(), + self.raw(), + author.raw(), + committer.raw(), + ptr::null(), + message, + tree.raw(), + parents.len() as size_t, + parent_ptrs.as_mut_ptr() + )); + Ok(str::from_utf8(&buf).unwrap().to_string()) + } + } + /// Create a commit object from the given buffer and signature /// /// Given the unsigned commit object's contents, its signature and the From fdddce561dd9b8df6d315b4528d3ee499b4665f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Kj=C3=A4ll?= Date: Tue, 12 Nov 2019 18:41:44 +0100 Subject: [PATCH 408/860] changed return type of commit_create_buffer function to be Result --- src/repo.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index 1bdd90fa5a..02d952840c 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1089,9 +1089,10 @@ impl Repository { } } - /// Create a commit object and return that as a string. + /// Create a commit object and return that as a Buf. /// - /// This string is suitable to be passed to the `commit_signed` function, + /// That can be converted to a string like this `str::from_utf8(&buf).unwrap().to_string()`. + /// And that string can be passed to the `commit_signed` function, /// the arguments behave the same as in the `commit` function. pub fn commit_create_buffer( &self, @@ -1100,7 +1101,7 @@ impl Repository { message: &str, tree: &Tree<'_>, parents: &[&Commit<'_>], - ) -> Result { + ) -> Result { let mut parent_ptrs = parents .iter() .map(|p| p.raw() as *const raw::git_commit) @@ -1119,7 +1120,7 @@ impl Repository { parents.len() as size_t, parent_ptrs.as_mut_ptr() )); - Ok(str::from_utf8(&buf).unwrap().to_string()) + Ok(buf) } } From 694947064b36047a1190156c7a5963a40a06fb35 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 16 Nov 2019 17:00:45 -0800 Subject: [PATCH 409/860] Fix array_into_iter warning. --- src/packbuilder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packbuilder.rs b/src/packbuilder.rs index 10d1682368..123e65119d 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -266,7 +266,7 @@ mod tests { } fn pack_header(len: u8) -> Vec { - [].into_iter() + [].iter() .chain(b"PACK") // signature .chain(&[0, 0, 0, 2]) // version number .chain(&[0, 0, 0, len]) // number of objects From 177254171f396fda2391862074a8f369e8397e1d Mon Sep 17 00:00:00 2001 From: Patrick Wang Date: Fri, 15 Nov 2019 06:28:31 +0800 Subject: [PATCH 410/860] Fix Odb.exists() --- src/odb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odb.rs b/src/odb.rs index a99e29f40b..aff1b19b26 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -152,7 +152,7 @@ impl<'repo> Odb<'repo> { /// Checks if the object database has an object. pub fn exists(&self, oid: Oid) -> bool { - unsafe { raw::git_odb_exists(self.raw, oid.raw()) != -1 } + unsafe { raw::git_odb_exists(self.raw, oid.raw()) != 0 } } /// Potentially finds an object that starts with the given prefix. From a3888c8a4ef38fd04d9df5f727c442af8bd9f0a6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 18 Nov 2019 08:14:54 -0800 Subject: [PATCH 411/860] Add a missing initialization in `Patch::from_buffers`. Closes #491 --- src/patch.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/patch.rs b/src/patch.rs index 65cff4704b..cda09efe72 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -100,6 +100,7 @@ impl Patch { new_path: Option<&Path>, opts: Option<&mut DiffOptions>, ) -> Result { + crate::init(); let mut ret = ptr::null_mut(); let old_path = into_opt_c_string(old_path)?; let new_path = into_opt_c_string(new_path)?; From 7f076f65a8ceb8dd1f8baa627982760132fdd2e9 Mon Sep 17 00:00:00 2001 From: Andres Suarez Date: Mon, 18 Nov 2019 13:22:15 -0500 Subject: [PATCH 412/860] Implement Debug for Patch and related diff structs --- src/diff.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/patch.rs | 12 ++++++++++ 2 files changed, 76 insertions(+) diff --git a/src/diff.rs b/src/diff.rs index 2d47199dd2..b8bfddfee0 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -444,6 +444,17 @@ impl<'a> Binding for DiffDelta<'a> { } } +impl<'a> std::fmt::Debug for DiffDelta<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + f.debug_struct("DiffDelta") + .field("nfiles", &self.nfiles()) + .field("status", &self.status()) + .field("old_file", &self.old_file()) + .field("new_file", &self.new_file()) + .finish() + } +} + impl<'a> DiffFile<'a> { /// Returns the Oid of this item. /// @@ -487,6 +498,20 @@ impl<'a> Binding for DiffFile<'a> { } } +impl<'a> std::fmt::Debug for DiffFile<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + let mut ds = f.debug_struct("DiffFile"); + ds.field("id", &self.id()); + if let Some(path_bytes) = &self.path_bytes() { + ds.field("path_bytes", path_bytes); + } + if let Some(path) = &self.path() { + ds.field("path", path); + } + ds.field("size", &self.size()).finish() + } +} + impl Default for DiffOptions { fn default() -> Self { Self::new() @@ -863,6 +888,23 @@ impl<'a> Binding for DiffLine<'a> { } } +impl<'a> std::fmt::Debug for DiffLine<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + let mut ds = f.debug_struct("DiffLine"); + if let Some(old_lineno) = &self.old_lineno() { + ds.field("old_lineno", old_lineno); + } + if let Some(new_lineno) = &self.new_lineno() { + ds.field("new_lineno", new_lineno); + } + ds.field("num_lines", &self.num_lines()) + .field("content_offset", &self.content_offset()) + .field("content", &self.content()) + .field("origin", &self.origin()) + .finish() + } +} + impl<'a> DiffHunk<'a> { /// Starting line number in old_file pub fn old_start(&self) -> u32 { @@ -908,6 +950,18 @@ impl<'a> Binding for DiffHunk<'a> { } } +impl<'a> std::fmt::Debug for DiffHunk<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + f.debug_struct("DiffHunk") + .field("old_start", &self.old_start()) + .field("old_lines", &self.old_lines()) + .field("new_start", &self.new_start()) + .field("new_lines", &self.new_lines()) + .field("header", &self.header()) + .finish() + } +} + impl DiffStats { /// Get the total number of files chaned in a diff. pub fn files_changed(&self) -> usize { @@ -956,6 +1010,16 @@ impl Drop for DiffStats { } } +impl std::fmt::Debug for DiffStats { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + f.debug_struct("DiffStats") + .field("files_changed", &self.files_changed()) + .field("insertions", &self.insertions()) + .field("deletions", &self.deletions()) + .finish() + } +} + impl<'a> DiffBinary<'a> { /// Returns whether there is data in this binary structure or not. /// diff --git a/src/patch.rs b/src/patch.rs index 65cff4704b..d7f946b10a 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -214,3 +214,15 @@ impl Patch { Ok(buf) } } + +impl std::fmt::Debug for Patch { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + let mut ds = f.debug_struct("Patch"); + ds.field("delta", &self.delta()) + .field("num_hunks", &self.num_hunks()); + if let Ok(line_stats) = &self.line_stats() { + ds.field("line_stats", line_stats); + } + ds.finish() + } +} From 6db911b8b50b0ff57d06a0d6f02578258f2fe6ae Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 20 Nov 2019 09:28:41 -0600 Subject: [PATCH 413/860] Bump versions of git2 and libgit2-sys (#496) --- Cargo.toml | 5 ++--- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ea49d74c9a..160b14a7f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [package] - name = "git2" -version = "0.10.1" +version = "0.10.2" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -21,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.9.1" } +libgit2-sys = { path = "libgit2-sys", version = "0.9.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 097da61ac8..7c00f843dd 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.9.1" +version = "0.9.2" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 18d0fd34a38505bff1903d9631920f4927280d9f Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Mon, 2 Dec 2019 07:47:16 -0800 Subject: [PATCH 414/860] Add Repository::cherrypick_commit() (#499) --- libgit2-sys/lib.rs | 8 ++++++++ src/repo.rs | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index dc552c0a64..e79864c8e8 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -3470,6 +3470,14 @@ extern "C" { commit: *mut git_commit, options: *const git_cherrypick_options, ) -> c_int; + pub fn git_cherrypick_commit( + out: *mut *mut git_index, + repo: *mut git_repository, + cherrypick_commit: *mut git_commit, + our_commit: *mut git_commit, + mainline: c_uint, + merge_options: *const git_merge_options, + ) -> c_int; } pub fn init() { diff --git a/src/repo.rs b/src/repo.rs index 02d952840c..580b3280e2 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2469,6 +2469,29 @@ impl Repository { } } + /// Create an index of uncommitted changes, representing the result of + /// cherry-picking. + pub fn cherrypick_commit( + &self, + cherrypick_commit: &Commit<'_>, + our_commit: &Commit<'_>, + mainline: u32, + options: Option<&MergeOptions>, + ) -> Result { + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_cherrypick_commit( + &mut ret, + self.raw(), + cherrypick_commit.raw(), + our_commit.raw(), + mainline, + options.map(|o| o.raw()) + )); + Ok(Binding::from_raw(ret)) + } + } + /// Retrieves the name of the reference supporting the remote tracking branch, /// given the name of a local branch reference. pub fn branch_upstream_name(&self, refname: &str) -> Result { From abd3785084e3cc7accdd12afbc4eaae53d0135e7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 2 Dec 2019 07:48:42 -0800 Subject: [PATCH 415/860] Remove MSRV builder as it's broken --- .github/workflows/main.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bfe2a70cd2..e3bf819908 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,12 +48,3 @@ jobs: - name: Install Rust run: rustup update stable && rustup default stable && rustup component add rustfmt - run: cargo fmt -- --check - - msrv: - name: MSRV - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - name: Install Rust - run: rustup update 1.33.0 && rustup default 1.33.0 - - run: cargo build From a80e6ea5de397cd8405998b4b5fdab50a800ae25 Mon Sep 17 00:00:00 2001 From: Fredrik Larsson Date: Thu, 12 Dec 2019 01:27:05 +0100 Subject: [PATCH 416/860] Update libgit2 submodule. (#503) --- .gitmodules | 1 - Cargo.toml | 4 ++-- git2-curl/Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/lib.rs | 21 ++++++++++++++------- libgit2-sys/libgit2 | 2 +- src/call.rs | 1 + src/cert.rs | 11 +++++++++++ src/lib.rs | 2 ++ src/merge.rs | 28 ++++++++++++++-------------- src/odb.rs | 2 +- src/stash.rs | 2 +- systest/build.rs | 1 + 13 files changed, 50 insertions(+), 29 deletions(-) diff --git a/.gitmodules b/.gitmodules index f27afa9218..95c45cce48 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,3 @@ [submodule "libgit2-sys/libgit2"] path = libgit2-sys/libgit2 url = https://github.com/libgit2/libgit2 - branch = maint/v0.28 diff --git a/Cargo.toml b/Cargo.toml index 160b14a7f2..2ceb4344ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.10.2" +version = "0.11.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.9.2" } +libgit2-sys = { path = "libgit2-sys", version = "0.10.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 599a0dddef..61d5fb8fd0 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -17,7 +17,7 @@ edition = "2018" curl = "0.4" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.10", default-features = false } +git2 = { path = "..", version = "0.11", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 7c00f843dd..525f1192c1 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.9.2" +version = "0.10.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index e79864c8e8..77b4d616a4 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -148,6 +148,7 @@ pub struct git_time { pub type git_off_t = i64; pub type git_time_t = i64; +pub type git_object_size_t = u64; git_enum! { pub enum git_revparse_mode_t { @@ -401,6 +402,7 @@ git_enum! { GIT_CERT_NONE, GIT_CERT_X509, GIT_CERT_HOSTKEY_LIBSSH2, + GIT_CERT_STRARRAY, } } @@ -415,6 +417,7 @@ pub struct git_cert_hostkey { pub kind: git_cert_ssh_t, pub hash_md5: [u8; 16], pub hash_sha1: [u8; 20], + pub hash_sha256: [u8; 32], } #[repr(C)] @@ -428,6 +431,7 @@ git_enum! { pub enum git_cert_ssh_t { GIT_CERT_SSH_MD5 = 1 << 0, GIT_CERT_SSH_SHA1 = 1 << 1, + GIT_CERT_SSH_SHA256 = 1 << 2, } } @@ -447,9 +451,10 @@ pub struct git_transfer_progress { pub struct git_diff_file { pub id: git_oid, pub path: *const c_char, - pub size: git_off_t, + pub size: git_object_size_t, pub flags: u32, pub mode: u16, + pub id_abbrev: u16, } pub type git_repository_create_cb = @@ -819,6 +824,7 @@ pub const GIT_ATTR_CHECK_FILE_THEN_INDEX: u32 = 0; pub const GIT_ATTR_CHECK_INDEX_THEN_FILE: u32 = 1; pub const GIT_ATTR_CHECK_INDEX_ONLY: u32 = 2; pub const GIT_ATTR_CHECK_NO_SYSTEM: u32 = 1 << 2; +pub const GIT_ATTR_CHECK_INCLUDE_HEAD: u32 = 1 << 3; #[repr(C)] pub struct git_cred { @@ -1046,6 +1052,7 @@ git_enum! { GIT_DIFF_FORMAT_RAW = 3, GIT_DIFF_FORMAT_NAME_ONLY = 4, GIT_DIFF_FORMAT_NAME_STATUS = 5, + GIT_DIFF_FORMAT_PATCH_ID = 6, } } @@ -1169,14 +1176,14 @@ git_enum! { #[repr(C)] pub struct git_merge_options { pub version: c_uint, - pub flags: git_merge_flag_t, + pub flags: u32, pub rename_threshold: c_uint, 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, + pub file_flags: u32, } git_enum! { @@ -1337,7 +1344,7 @@ pub struct git_odb_backend { extern "C" fn( *mut *mut git_odb_stream, *mut git_odb_backend, - git_off_t, + git_object_size_t, git_object_t, ) -> c_int, >, @@ -1573,7 +1580,7 @@ git_enum! { #[repr(C)] pub struct git_stash_apply_options { pub version: c_uint, - pub flags: git_stash_apply_flags, + pub flags: u32, pub checkout_options: git_checkout_options, pub progress_cb: Option, pub progress_payload: *mut c_void, @@ -2206,7 +2213,7 @@ extern "C" { len: size_t, ) -> c_int; pub fn git_blob_rawcontent(blob: *const git_blob) -> *const c_void; - pub fn git_blob_rawsize(blob: *const git_blob) -> git_off_t; + pub fn git_blob_rawsize(blob: *const git_blob) -> git_object_size_t; pub fn git_blob_create_frombuffer( id: *mut git_oid, repo: *mut git_repository, @@ -3298,7 +3305,7 @@ extern "C" { pub fn git_odb_open_wstream( out: *mut *mut git_odb_stream, db: *mut git_odb, - size: git_off_t, + size: git_object_size_t, obj_type: git_object_t, ) -> c_int; pub fn git_odb_stream_write( diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 08cfa43d0e..6bd37c3409 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 08cfa43d0e1a9214a2f1239593686078e75e5636 +Subproject commit 6bd37c3409d759cb4a2a87ffee7494a798999f20 diff --git a/src/call.rs b/src/call.rs index 1509517c0c..f1ade4a8f3 100644 --- a/src/call.rs +++ b/src/call.rs @@ -181,6 +181,7 @@ mod impls { DiffFormat::Raw => raw::GIT_DIFF_FORMAT_RAW, DiffFormat::NameOnly => raw::GIT_DIFF_FORMAT_NAME_ONLY, DiffFormat::NameStatus => raw::GIT_DIFF_FORMAT_NAME_STATUS, + DiffFormat::PatchId => raw::GIT_DIFF_FORMAT_PATCH_ID, } } } diff --git a/src/cert.rs b/src/cert.rs index 80c4ed345a..9153880b69 100644 --- a/src/cert.rs +++ b/src/cert.rs @@ -76,6 +76,17 @@ impl<'a> CertHostkey<'a> { } } } + + /// Returns the SHA-256 hash of the hostkey, if available. + pub fn hash_sha256(&self) -> Option<&[u8; 32]> { + unsafe { + if (*self.raw).kind as u32 & raw::GIT_CERT_SSH_SHA256 as u32 == 0 { + None + } else { + Some(&(*self.raw).hash_sha256) + } + } + } } impl<'a> CertX509<'a> { diff --git a/src/lib.rs b/src/lib.rs index e24196c1b2..9533b0e47f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1187,6 +1187,8 @@ pub enum DiffFormat { NameOnly, /// like git diff --name-status NameStatus, + /// git diff as used by git patch-id + PatchId, } bitflags! { diff --git a/src/merge.rs b/src/merge.rs index edf7cee64d..417f12bbd3 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -44,7 +44,7 @@ impl MergeOptions { opts } - fn flag(&mut self, opt: raw::git_merge_flag_t, val: bool) -> &mut MergeOptions { + fn flag(&mut self, opt: u32, val: bool) -> &mut MergeOptions { if val { self.raw.flags |= opt; } else { @@ -55,25 +55,25 @@ impl MergeOptions { /// Detect file renames pub fn find_renames(&mut self, find: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FIND_RENAMES, find) + self.flag(raw::GIT_MERGE_FIND_RENAMES as u32, find) } /// If a conflict occurs, exit immediately instead of attempting to continue /// resolving conflicts pub fn fail_on_conflict(&mut self, fail: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FAIL_ON_CONFLICT, fail) + self.flag(raw::GIT_MERGE_FAIL_ON_CONFLICT as u32, fail) } /// Do not write the REUC extension on the generated index pub fn skip_reuc(&mut self, skip: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_FAIL_ON_CONFLICT, skip) + self.flag(raw::GIT_MERGE_FAIL_ON_CONFLICT as u32, skip) } /// If the commits being merged have multiple merge bases, do not build a /// recursive merge base (by merging the multiple merge bases), instead /// simply use the first base. pub fn no_recursive(&mut self, disable: bool) -> &mut MergeOptions { - self.flag(raw::GIT_MERGE_NO_RECURSIVE, disable) + self.flag(raw::GIT_MERGE_NO_RECURSIVE as u32, disable) } /// Similarity to consider a file renamed (default 50) @@ -106,7 +106,7 @@ impl MergeOptions { self } - fn file_flag(&mut self, opt: raw::git_merge_file_flag_t, val: bool) -> &mut MergeOptions { + fn file_flag(&mut self, opt: u32, val: bool) -> &mut MergeOptions { if val { self.raw.file_flags |= opt; } else { @@ -117,42 +117,42 @@ impl MergeOptions { /// Create standard conflicted merge files pub fn standard_style(&mut self, standard: bool) -> &mut MergeOptions { - self.file_flag(raw::GIT_MERGE_FILE_STYLE_MERGE, standard) + self.file_flag(raw::GIT_MERGE_FILE_STYLE_MERGE as u32, standard) } /// Create diff3-style file pub fn diff3_style(&mut self, diff3: bool) -> &mut MergeOptions { - self.file_flag(raw::GIT_MERGE_FILE_STYLE_DIFF3, diff3) + self.file_flag(raw::GIT_MERGE_FILE_STYLE_DIFF3 as u32, diff3) } /// Condense non-alphanumeric regions for simplified diff file pub fn simplify_alnum(&mut self, simplify: bool) -> &mut MergeOptions { - self.file_flag(raw::GIT_MERGE_FILE_SIMPLIFY_ALNUM, simplify) + self.file_flag(raw::GIT_MERGE_FILE_SIMPLIFY_ALNUM as u32, simplify) } /// Ignore all whitespace pub fn ignore_whitespace(&mut self, ignore: bool) -> &mut MergeOptions { - self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE, ignore) + self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE as u32, ignore) } /// Ignore changes in amount of whitespace pub fn ignore_whitespace_change(&mut self, ignore: bool) -> &mut MergeOptions { - self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE, ignore) + self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE as u32, ignore) } /// Ignore whitespace at end of line pub fn ignore_whitespace_eol(&mut self, ignore: bool) -> &mut MergeOptions { - self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL, ignore) + self.file_flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL as u32, ignore) } /// Use the "patience diff" algorithm pub fn patience(&mut self, patience: bool) -> &mut MergeOptions { - self.file_flag(raw::GIT_MERGE_FILE_DIFF_PATIENCE, patience) + self.file_flag(raw::GIT_MERGE_FILE_DIFF_PATIENCE as u32, patience) } /// Take extra time to find minimal diff pub fn minimal(&mut self, minimal: bool) -> &mut MergeOptions { - self.file_flag(raw::GIT_MERGE_FILE_DIFF_MINIMAL, minimal) + self.file_flag(raw::GIT_MERGE_FILE_DIFF_MINIMAL as u32, minimal) } /// Acquire a pointer to the underlying raw options. diff --git a/src/odb.rs b/src/odb.rs index aff1b19b26..75857b2e37 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -81,7 +81,7 @@ impl<'repo> Odb<'repo> { try_call!(raw::git_odb_open_wstream( &mut out, self.raw, - size as raw::git_off_t, + size as raw::git_object_size_t, obj_type.raw() )); Ok(OdbWriter::from_raw(out)) diff --git a/src/stash.rs b/src/stash.rs index f2654fa950..ad4155e64e 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -46,7 +46,7 @@ impl<'cb> StashApplyOptions<'cb> { /// Set stash application flag to GIT_STASH_APPLY_REINSTATE_INDEX pub fn reinstantiate_index(&mut self) -> &mut StashApplyOptions<'cb> { - self.raw_opts.flags = raw::GIT_STASH_APPLY_REINSTATE_INDEX; + self.raw_opts.flags = raw::GIT_STASH_APPLY_REINSTATE_INDEX as u32; self } diff --git a/systest/build.rs b/systest/build.rs index 57bb7c3bd8..23a57bdc1e 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -13,6 +13,7 @@ fn main() { .header("git2/sys/odb_backend.h") .header("git2/sys/mempack.h") .header("git2/sys/repository.h") + .header("git2/sys/cred.h") .header("git2/cred_helpers.h") .type_name(|s, _, _| s.to_string()); cfg.field_name(|_, f| match f { From 775d92814a201bdb3b0106e8a2ea3b2236d241d4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 12 Dec 2019 14:34:21 -0800 Subject: [PATCH 417/860] Update libgit2 submodule again --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 6bd37c3409..6777db8e83 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 6bd37c3409d759cb4a2a87ffee7494a798999f20 +Subproject commit 6777db8e8343014d57c41b335e0c60af44d4e9f2 From a6938c0408bfb65df8e8612a72f0bf05976823ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Thu, 12 Dec 2019 23:35:58 +0100 Subject: [PATCH 418/860] Accept all refspecs that implement AsRef (#482) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Accept all refspecs that implement AsRef This changes the signature of the Remote::fetch and Remote::push methods to accept refspecs as slices of not only &str but anything that implements AsRef (and IntoCString and Clone). In this way, refspecs can be provided, for example, by a &Vec, which wasn’t possible before. * Accept AsRef refspecs in Remote::download This extends the signature of Remote::download to accept refspecs of type &[Str], where Str: AsRef, to bring it in line with the previous change for Remote::fetch and Remote::push. --- examples/fetch.rs | 2 +- src/remote.rs | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/fetch.rs b/examples/fetch.rs index e2e7552bd9..6ede3c9ab5 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -81,7 +81,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { // progress. let mut fo = FetchOptions::new(); fo.remote_callbacks(cb); - remote.download(&[], Some(&mut fo))?; + remote.download(&[] as &[&str], Some(&mut fo))?; { // If there are local objects (we got a thin pack), then tell the user diff --git a/src/remote.rs b/src/remote.rs index 33dd912eb6..ded0387fb2 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -175,9 +175,9 @@ impl<'repo> Remote<'repo> { /// /// The `specs` argument is a list of refspecs to use for this negotiation /// and download. Use an empty array to use the base refspecs. - pub fn download( + pub fn download + crate::IntoCString + Clone>( &mut self, - specs: &[&str], + specs: &[Str], opts: Option<&mut FetchOptions<'_>>, ) -> Result<(), Error> { let (_a, _b, arr) = crate::util::iter2cstrs(specs.iter())?; @@ -224,9 +224,9 @@ impl<'repo> Remote<'repo> { /// let repo = git2::Repository::discover("rust").unwrap(); /// fetch_origin_master(repo).unwrap(); /// ``` - pub fn fetch( + pub fn fetch + crate::IntoCString + Clone>( &mut self, - refspecs: &[&str], + refspecs: &[Str], opts: Option<&mut FetchOptions<'_>>, reflog_msg: Option<&str>, ) -> Result<(), Error> { @@ -269,9 +269,9 @@ impl<'repo> Remote<'repo> { /// Note that you'll likely want to use `RemoteCallbacks` and set /// `push_update_reference` to test whether all the references were pushed /// successfully. - pub fn push( + pub fn push + crate::IntoCString + Clone>( &mut self, - refspecs: &[&str], + refspecs: &[Str], opts: Option<&mut PushOptions<'_>>, ) -> Result<(), Error> { let (_a, _b, arr) = crate::util::iter2cstrs(refspecs.iter())?; @@ -652,7 +652,7 @@ mod tests { origin.connect(Direction::Fetch).unwrap(); assert!(origin.connected()); - origin.download(&[], None).unwrap(); + origin.download(&[] as &[&str], None).unwrap(); origin.disconnect(); { @@ -667,8 +667,8 @@ mod tests { } assert!(!origin.connected()); - origin.fetch(&[], None, None).unwrap(); - origin.fetch(&[], None, Some("foo")).unwrap(); + origin.fetch(&[] as &[&str], None, None).unwrap(); + origin.fetch(&[] as &[&str], None, Some("foo")).unwrap(); origin .update_tips(None, true, AutotagOption::Unspecified, None) .unwrap(); @@ -722,7 +722,7 @@ mod tests { }); origin .fetch( - &[], + &[] as &[&str], Some(FetchOptions::new().remote_callbacks(callbacks)), None, ) From 14233a28a8408f41498151648b9e014c36e8e611 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 12 Dec 2019 14:45:00 -0800 Subject: [PATCH 419/860] Bump git2-curl to 0.12.0 --- git2-curl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 61d5fb8fd0..1d75a1d281 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.11.0" +version = "0.12.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" From f0bfe7ac0cbee58b11f1708eca4f76b4828146c0 Mon Sep 17 00:00:00 2001 From: Fredrik Larsson Date: Mon, 16 Dec 2019 16:33:15 +0100 Subject: [PATCH 420/860] Add missing error classes and error codes (#506) --- libgit2-sys/lib.rs | 7 +++++++ src/error.rs | 10 ++++++++++ src/lib.rs | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 77b4d616a4..623ec8f78a 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -187,6 +187,10 @@ git_enum! { GIT_EMERGECONFLICT = -24, GIT_PASSTHROUGH = -30, GIT_ITEROVER = -31, + GIT_RETRY = -32, + GIT_EMISMATCH = -33, + GIT_EINDEXDIRTY = -34, + GIT_EAPPLYFAIL = -35, } } @@ -223,6 +227,9 @@ git_enum! { GIT_ERROR_DESCRIBE, GIT_ERROR_REBASE, GIT_ERROR_FILESYSTEM, + GIT_ERROR_PATCH, + GIT_ERROR_WORKTREE, + GIT_ERROR_SHA1, } } diff --git a/src/error.rs b/src/error.rs index 2a8dcca7e7..cbced83941 100644 --- a/src/error.rs +++ b/src/error.rs @@ -153,6 +153,9 @@ impl Error { raw::GIT_ERROR_DESCRIBE => super::ErrorClass::Describe, raw::GIT_ERROR_REBASE => super::ErrorClass::Rebase, raw::GIT_ERROR_FILESYSTEM => super::ErrorClass::Filesystem, + raw::GIT_ERROR_PATCH => super::ErrorClass::Patch, + raw::GIT_ERROR_WORKTREE => super::ErrorClass::Worktree, + raw::GIT_ERROR_SHA1 => super::ErrorClass::Sha1, _ => super::ErrorClass::None, } } @@ -190,6 +193,10 @@ impl Error { GIT_EUNCOMMITTED, GIT_PASSTHROUGH, GIT_ITEROVER, + GIT_RETRY, + GIT_EMISMATCH, + GIT_EINDEXDIRTY, + GIT_EAPPLYFAIL, ) } @@ -233,6 +240,9 @@ impl Error { GIT_ERROR_DESCRIBE, GIT_ERROR_REBASE, GIT_ERROR_FILESYSTEM, + GIT_ERROR_PATCH, + GIT_ERROR_WORKTREE, + GIT_ERROR_SHA1, ) } diff --git a/src/lib.rs b/src/lib.rs index 9533b0e47f..dce9e19d4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -252,6 +252,12 @@ pub enum ErrorClass { Rebase, /// Filesystem-related error Filesystem, + /// Invalid patch data + Patch, + /// Error involving worktrees + Worktree, + /// Hash library error or SHA-1 collision + Sha1, } /// A listing of the possible states that a repository can be in. From b64307141252a08f10abaada8b7090a5958ee99a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 7 Jan 2020 07:24:33 -0800 Subject: [PATCH 421/860] Remove usage of `Error::description` --- src/error.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/error.rs b/src/error.rs index cbced83941..93f8f69cce 100644 --- a/src/error.rs +++ b/src/error.rs @@ -252,11 +252,7 @@ impl Error { } } -impl error::Error for Error { - fn description(&self) -> &str { - &self.message - } -} +impl error::Error for Error {} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -284,7 +280,7 @@ impl From for Error { impl From for Error { fn from(e: JoinPathsError) -> Error { - Error::from_str(error::Error::description(&e)) + Error::from_str(&e.to_string()) } } From 33b606c5292d658d78491911115831c517e461d5 Mon Sep 17 00:00:00 2001 From: phR0ze Date: Wed, 8 Jan 2020 08:49:53 -0700 Subject: [PATCH 422/860] Adding missing binding for git_remote_create_with_fetchspec (#510) * Adding missing binding for git_remote_create_with_fetchspec * Formatting with rustfmt for cicd check --- libgit2-sys/lib.rs | 7 +++++++ src/repo.rs | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 623ec8f78a..c6a4c2da71 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1810,6 +1810,13 @@ extern "C" { name: *const c_char, url: *const c_char, ) -> c_int; + pub fn git_remote_create_with_fetchspec( + out: *mut *mut git_remote, + repo: *mut git_repository, + name: *const c_char, + url: *const c_char, + fetch: *const c_char, + ) -> c_int; pub fn git_remote_lookup( out: *mut *mut git_remote, repo: *mut git_repository, diff --git a/src/repo.rs b/src/repo.rs index 580b3280e2..77694df008 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -490,6 +490,26 @@ impl Repository { } } + /// Add a remote with the provided fetch refspec to the repository's + /// configuration. + pub fn remote_with_fetch( + &self, + name: &str, + url: &str, + fetch: &str, + ) -> Result, Error> { + let mut ret = ptr::null_mut(); + let name = CString::new(name)?; + let url = CString::new(url)?; + let fetch = CString::new(fetch)?; + unsafe { + try_call!(raw::git_remote_create_with_fetchspec( + &mut ret, self.raw, name, url, fetch + )); + Ok(Binding::from_raw(ret)) + } + } + /// Create an anonymous remote /// /// Create a remote with the given url and refspec in memory. You can use From 171967b2358239a87c7435e237a4ec9b626bc57b Mon Sep 17 00:00:00 2001 From: Nathan Wilson Date: Mon, 13 Jan 2020 11:14:18 -0400 Subject: [PATCH 423/860] Updated libgit2. (#512) --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 6777db8e83..cc4f4cbea4 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 6777db8e8343014d57c41b335e0c60af44d4e9f2 +Subproject commit cc4f4cbea48ac00a5edec1b3570ac3d2ef10fe77 From 4c680c3b7c6cdb29832cb93b235163a1b1204e20 Mon Sep 17 00:00:00 2001 From: stoically Date: Tue, 14 Jan 2020 16:04:25 +0100 Subject: [PATCH 424/860] Odb writepack support (#509) * Rename git_transfer_progress Matching the upstream refactoring, details are here: https://github.com/libgit2/libgit2/commit/975d6722a5c203427ab63789d329c00b76461225 Keeping an alias with deprecation warning for TransportProgress around * Add OdbPackwriter --- libgit2-sys/lib.rs | 73 ++++++++++++----- src/indexer.rs | 96 ++++++++++++++++++++++ src/lib.rs | 6 +- src/odb.rs | 172 +++++++++++++++++++++++++++++++++++++++- src/packbuilder.rs | 29 ++----- src/remote_callbacks.rs | 88 ++------------------ src/test.rs | 18 ++++- 7 files changed, 351 insertions(+), 131 deletions(-) create mode 100644 src/indexer.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index c6a4c2da71..576cf2d995 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -85,7 +85,6 @@ pub enum git_packbuilder {} pub enum git_odb {} pub enum git_odb_stream {} pub enum git_odb_object {} -pub enum git_odb_writepack {} pub enum git_worktree {} #[repr(C)] @@ -323,6 +322,26 @@ pub struct git_checkout_perfdata { pub chmod_calls: size_t, } +#[repr(C)] +#[derive(Copy, Clone)] +pub struct git_indexer_progress { + pub total_objects: c_uint, + pub indexed_objects: c_uint, + pub received_objects: c_uint, + pub local_objects: c_uint, + pub total_deltas: c_uint, + pub indexed_deltas: c_uint, + pub received_bytes: size_t, +} + +pub type git_indexer_progress_cb = extern "C" fn(*const git_indexer_progress, *mut c_void) -> c_int; + +#[deprecated( + since = "0.10.0", + note = "renamed to `git_indexer_progress` to match upstream" +)] +pub type git_transfer_progress = git_indexer_progress; + #[repr(C)] pub struct git_remote_callbacks { pub version: c_uint, @@ -330,7 +349,7 @@ pub struct git_remote_callbacks { pub completion: Option c_int>, pub credentials: Option, pub certificate_check: Option, - pub transfer_progress: Option, + pub transfer_progress: Option, pub update_tips: Option c_int>, pub pack_progress: Option, @@ -382,7 +401,7 @@ pub type git_transport_message_cb = extern "C" fn(*const c_char, c_int, *mut c_v pub type git_cred_acquire_cb = extern "C" fn(*mut *mut git_cred, *const c_char, *const c_char, c_uint, *mut c_void) -> c_int; pub type git_transfer_progress_cb = - extern "C" fn(*const git_transfer_progress, *mut c_void) -> c_int; + extern "C" fn(*const git_indexer_progress, *mut c_void) -> c_int; pub type git_packbuilder_progress = extern "C" fn(git_packbuilder_stage_t, c_uint, c_uint, *mut c_void) -> c_int; pub type git_push_transfer_progress = extern "C" fn(c_uint, c_uint, size_t, *mut c_void) -> c_int; @@ -442,18 +461,6 @@ git_enum! { } } -#[repr(C)] -#[derive(Copy, Clone)] -pub struct git_transfer_progress { - pub total_objects: c_uint, - pub indexed_objects: c_uint, - pub received_objects: c_uint, - pub local_objects: c_uint, - pub total_deltas: c_uint, - pub indexed_deltas: c_uint, - pub received_bytes: size_t, -} - #[repr(C)] pub struct git_diff_file { pub id: git_oid, @@ -1291,8 +1298,8 @@ pub struct git_transport { extern "C" fn( *mut git_transport, *mut git_repository, - *mut git_transfer_progress, - git_transfer_progress_cb, + *mut git_indexer_progress, + git_indexer_progress_cb, *mut c_void, ) -> c_int, >, @@ -1381,7 +1388,7 @@ pub struct git_odb_backend { *mut *mut git_odb_writepack, *mut git_odb_backend, *mut git_odb, - git_transfer_progress_cb, + git_indexer_progress_cb, *mut c_void, ) -> c_int, >, @@ -1391,6 +1398,25 @@ pub struct git_odb_backend { pub free: Option, } +#[repr(C)] +pub struct git_odb_writepack { + pub backend: *mut git_odb_backend, + + pub append: Option< + extern "C" fn( + *mut git_odb_writepack, + *const c_void, + size_t, + *mut git_indexer_progress, + ) -> c_int, + >, + + pub commit: + Option c_int>, + + pub free: Option, +} + #[repr(C)] pub struct git_refdb_backend { pub version: c_uint, @@ -1906,7 +1932,7 @@ extern "C" { ) -> c_int; pub fn git_remote_init_callbacks(opts: *mut git_remote_callbacks, version: c_uint) -> c_int; pub fn git_fetch_init_options(opts: *mut git_fetch_options, version: c_uint) -> c_int; - pub fn git_remote_stats(remote: *mut git_remote) -> *const git_transfer_progress; + pub fn git_remote_stats(remote: *mut git_remote) -> *const git_indexer_progress; pub fn git_remote_ls( out: *mut *mut *const git_remote_head, size: *mut size_t, @@ -3282,7 +3308,7 @@ extern "C" { pb: *mut git_packbuilder, path: *const c_char, mode: c_uint, - progress_cb: Option, + progress_cb: Option, progress_cb_payload: *mut c_void, ) -> c_int; pub fn git_packbuilder_hash(pb: *mut git_packbuilder) -> *const git_oid; @@ -3353,6 +3379,13 @@ extern "C" { otype: git_object_t, ) -> c_int; + pub fn git_odb_write_pack( + out: *mut *mut git_odb_writepack, + odb: *mut git_odb, + progress_cb: git_indexer_progress_cb, + progress_payload: *mut c_void, + ) -> c_int; + pub fn git_odb_hash( out: *mut git_oid, data: *const c_void, diff --git a/src/indexer.rs b/src/indexer.rs new file mode 100644 index 0000000000..1003abeb76 --- /dev/null +++ b/src/indexer.rs @@ -0,0 +1,96 @@ +use std::marker; + +use crate::raw; +use crate::util::Binding; + +/// Struct representing the progress by an in-flight transfer. +pub struct Progress<'a> { + pub(crate) raw: ProgressState, + pub(crate) _marker: marker::PhantomData<&'a raw::git_indexer_progress>, +} + +pub(crate) enum ProgressState { + Borrowed(*const raw::git_indexer_progress), + Owned(raw::git_indexer_progress), +} + +/// Callback to be invoked while indexing is in progress. +/// +/// This callback will be periodically called with updates to the progress of +/// the indexing so far. The return value indicates whether the indexing or +/// transfer should continue. A return value of `false` will cancel the +/// indexing or transfer. +/// +/// * `progress` - the progress being made so far. +pub type IndexerProgress<'a> = dyn FnMut(Progress<'_>) -> bool + 'a; + +impl<'a> Progress<'a> { + /// Number of objects in the packfile being downloaded + pub fn total_objects(&self) -> usize { + unsafe { (*self.raw()).total_objects as usize } + } + /// Received objects that have been hashed + pub fn indexed_objects(&self) -> usize { + unsafe { (*self.raw()).indexed_objects as usize } + } + /// Objects which have been downloaded + pub fn received_objects(&self) -> usize { + unsafe { (*self.raw()).received_objects as usize } + } + /// Locally-available objects that have been injected in order to fix a thin + /// pack. + pub fn local_objects(&self) -> usize { + unsafe { (*self.raw()).local_objects as usize } + } + /// Number of deltas in the packfile being downloaded + pub fn total_deltas(&self) -> usize { + unsafe { (*self.raw()).total_deltas as usize } + } + /// Received deltas that have been hashed. + pub fn indexed_deltas(&self) -> usize { + unsafe { (*self.raw()).indexed_deltas as usize } + } + /// Size of the packfile received up to now + pub fn received_bytes(&self) -> usize { + unsafe { (*self.raw()).received_bytes as usize } + } + + /// Convert this to an owned version of `Progress`. + pub fn to_owned(&self) -> Progress<'static> { + Progress { + raw: ProgressState::Owned(unsafe { *self.raw() }), + _marker: marker::PhantomData, + } + } +} + +impl<'a> Binding for Progress<'a> { + type Raw = *const raw::git_indexer_progress; + unsafe fn from_raw(raw: *const raw::git_indexer_progress) -> Progress<'a> { + Progress { + raw: ProgressState::Borrowed(raw), + _marker: marker::PhantomData, + } + } + + fn raw(&self) -> *const raw::git_indexer_progress { + match self.raw { + ProgressState::Borrowed(raw) => raw, + ProgressState::Owned(ref raw) => raw as *const _, + } + } +} + +/// Callback to be invoked while a transfer is in progress. +/// +/// This callback will be periodically called with updates to the progress of +/// the transfer so far. The return value indicates whether the transfer should +/// continue. A return value of `false` will cancel the transfer. +/// +/// * `progress` - the progress being made so far. +#[deprecated( + since = "0.11.0", + note = "renamed to `IndexerProgress` to match upstream" +)] +#[allow(dead_code)] +pub type TransportProgress<'a> = IndexerProgress<'a>; diff --git a/src/lib.rs b/src/lib.rs index dce9e19d4f..0ee8f9d7b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,6 +93,7 @@ pub use crate::error::Error; pub use crate::index::{ Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath, }; +pub use crate::indexer::{IndexerProgress, Progress}; pub use crate::merge::{AnnotatedCommit, MergeOptions}; pub use crate::message::{message_prettify, DEFAULT_COMMENT_CHAR}; pub use crate::note::{Note, Notes}; @@ -111,8 +112,8 @@ pub use crate::refspec::Refspec; pub use crate::remote::{ FetchOptions, PushOptions, Refspecs, Remote, RemoteConnection, RemoteHead, }; -pub use crate::remote_callbacks::{Credentials, RemoteCallbacks, TransferProgress}; -pub use crate::remote_callbacks::{Progress, TransportMessage, UpdateTips}; +pub use crate::remote_callbacks::{Credentials, RemoteCallbacks}; +pub use crate::remote_callbacks::{TransportMessage, UpdateTips}; pub use crate::repo::{Repository, RepositoryInitOptions}; pub use crate::revspec::Revspec; pub use crate::revwalk::Revwalk; @@ -631,6 +632,7 @@ mod describe; mod diff; mod error; mod index; +mod indexer; mod merge; mod message; mod note; diff --git a/src/odb.rs b/src/odb.rs index 75857b2e37..a6b1bc5397 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -1,5 +1,6 @@ use std::io; use std::marker; +use std::mem::MaybeUninit; use std::ptr; use std::slice; @@ -9,7 +10,7 @@ use libc::{c_char, c_int, c_void, size_t}; use crate::panic; use crate::util::Binding; -use crate::{raw, Error, Object, ObjectType, Oid}; +use crate::{raw, Error, IndexerProgress, Object, ObjectType, Oid, Progress}; /// A structure to represent a git object database pub struct Odb<'repo> { @@ -150,6 +151,30 @@ impl<'repo> Odb<'repo> { } } + /// Create stream for writing a pack file to the ODB + pub fn packwriter(&self) -> Result, Error> { + let mut out = ptr::null_mut(); + let progress = MaybeUninit::uninit(); + let progress_cb = write_pack_progress_cb; + let progress_payload = Box::new(OdbPackwriterCb { cb: None }); + let progress_payload_ptr = Box::into_raw(progress_payload); + + unsafe { + try_call!(raw::git_odb_write_pack( + &mut out, + self.raw, + progress_cb, + progress_payload_ptr as *mut c_void + )); + } + + Ok(OdbPackwriter { + raw: out, + progress, + progress_payload_ptr, + }) + } + /// Checks if the object database has an object. pub fn exists(&self, oid: Oid) -> bool { unsafe { raw::git_odb_exists(self.raw, oid.raw()) != 0 } @@ -351,6 +376,87 @@ impl<'repo> io::Write for OdbWriter<'repo> { } } +struct OdbPackwriterCb<'repo> { + cb: Option>>, +} + +/// A stream to write a packfile to the ODB +pub struct OdbPackwriter<'repo> { + raw: *mut raw::git_odb_writepack, + progress: MaybeUninit, + progress_payload_ptr: *mut OdbPackwriterCb<'repo>, +} + +impl<'repo> OdbPackwriter<'repo> { + /// Finish writing the packfile + pub fn commit(&mut self) -> Result { + unsafe { + let writepack = &*self.raw; + let res = match writepack.commit { + Some(commit) => commit(self.raw, self.progress.as_mut_ptr()), + None => -1, + }; + + if res < 0 { + Err(Error::last_error(res).unwrap()) + } else { + Ok(res) + } + } + } + + /// The callback through which progress is monitored. Be aware that this is + /// called inline, so performance may be affected. + pub fn progress(&mut self, cb: F) -> &mut OdbPackwriter<'repo> + where + F: FnMut(Progress<'_>) -> bool + 'repo, + { + let progress_payload = + unsafe { &mut *(self.progress_payload_ptr as *mut OdbPackwriterCb<'_>) }; + + progress_payload.cb = Some(Box::new(cb) as Box>); + self + } +} + +impl<'repo> io::Write for OdbPackwriter<'repo> { + fn write(&mut self, buf: &[u8]) -> io::Result { + unsafe { + let ptr = buf.as_ptr() as *mut c_void; + let len = buf.len(); + + let writepack = &*self.raw; + let res = match writepack.append { + Some(append) => append(self.raw, ptr, len, self.progress.as_mut_ptr()), + None => -1, + }; + + if res < 0 { + Err(io::Error::new(io::ErrorKind::Other, "Write error")) + } else { + Ok(buf.len()) + } + } + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl<'repo> Drop for OdbPackwriter<'repo> { + fn drop(&mut self) { + unsafe { + let writepack = &*self.raw; + match writepack.free { + Some(free) => free(self.raw), + None => (), + }; + + Box::from_raw(self.progress_payload_ptr); + } + } +} + pub type ForeachCb<'a> = dyn FnMut(&Oid) -> bool + 'a; struct ForeachCbData<'a> { @@ -374,9 +480,31 @@ extern "C" fn foreach_cb(id: *const raw::git_oid, payload: *mut c_void) -> c_int .unwrap_or(1) } +extern "C" fn write_pack_progress_cb( + stats: *const raw::git_indexer_progress, + payload: *mut c_void, +) -> c_int { + let ok = panic::wrap(|| unsafe { + let payload = &mut *(payload as *mut OdbPackwriterCb<'_>); + + let callback = match payload.cb { + Some(ref mut cb) => cb, + None => return true, + }; + + let progress: Progress<'_> = Binding::from_raw(stats); + callback(progress) + }); + if ok == Some(true) { + 0 + } else { + -1 + } +} + #[cfg(test)] mod tests { - use crate::{ObjectType, Oid, Repository}; + use crate::{Buf, ObjectType, Oid, Repository}; use std::io::prelude::*; use tempfile::TempDir; @@ -457,4 +585,44 @@ mod tests { let found_oid = db.exists_prefix(id_prefix, 10).unwrap(); assert_eq!(found_oid, id); } + + #[test] + fn packwriter() { + let (_td, repo_source) = crate::test::repo_init(); + let (_td, repo_target) = crate::test::repo_init(); + let mut builder = t!(repo_source.packbuilder()); + let mut buf = Buf::new(); + let (commit_source_id, _tree) = crate::test::commit(&repo_source); + t!(builder.insert_object(commit_source_id, None)); + t!(builder.write_buf(&mut buf)); + let db = repo_target.odb().unwrap(); + let mut packwriter = db.packwriter().unwrap(); + packwriter.write(&buf).unwrap(); + packwriter.commit().unwrap(); + let commit_target = repo_target.find_commit(commit_source_id).unwrap(); + assert_eq!(commit_target.id(), commit_source_id); + } + + #[test] + fn packwriter_progress() { + let mut progress_called = false; + { + let (_td, repo_source) = crate::test::repo_init(); + let (_td, repo_target) = crate::test::repo_init(); + let mut builder = t!(repo_source.packbuilder()); + let mut buf = Buf::new(); + let (commit_source_id, _tree) = crate::test::commit(&repo_source); + t!(builder.insert_object(commit_source_id, None)); + t!(builder.write_buf(&mut buf)); + let db = repo_target.odb().unwrap(); + let mut packwriter = db.packwriter().unwrap(); + packwriter.progress(|_| { + progress_called = true; + true + }); + packwriter.write(&buf).unwrap(); + packwriter.commit().unwrap(); + } + assert_eq!(progress_called, true); + } } diff --git a/src/packbuilder.rs b/src/packbuilder.rs index 123e65119d..6769d35114 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -246,24 +246,7 @@ extern "C" fn progress_c( #[cfg(test)] mod tests { - use crate::{Buf, Oid, Repository}; - use std::fs::File; - use std::path::Path; - - fn commit(repo: &Repository) -> (Oid, Oid) { - let mut index = t!(repo.index()); - let root = repo.path().parent().unwrap(); - t!(File::create(&root.join("foo"))); - t!(index.add_path(Path::new("foo"))); - - let tree_id = t!(index.write_tree()); - let tree = t!(repo.find_tree(tree_id)); - let sig = t!(repo.signature()); - let head_id = t!(repo.refname_to_id("HEAD")); - let parent = t!(repo.find_commit(head_id)); - let commit = t!(repo.commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent])); - (commit, tree_id) - } + use crate::Buf; fn pack_header(len: u8) -> Vec { [].iter() @@ -320,7 +303,7 @@ mod tests { let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); let mut buf = Buf::new(); - let (commit, _tree) = commit(&repo); + let (commit, _tree) = crate::test::commit(&repo); t!(builder.insert_object(commit, None)); assert_eq!(builder.object_count(), 1); t!(builder.write_buf(&mut buf)); @@ -333,7 +316,7 @@ mod tests { let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); let mut buf = Buf::new(); - let (_commit, tree) = commit(&repo); + let (_commit, tree) = crate::test::commit(&repo); // will insert the tree itself and the blob, 2 objects t!(builder.insert_tree(tree)); assert_eq!(builder.object_count(), 2); @@ -347,7 +330,7 @@ mod tests { let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); let mut buf = Buf::new(); - let (commit, _tree) = commit(&repo); + let (commit, _tree) = crate::test::commit(&repo); // will insert the commit, its tree and the blob, 3 objects t!(builder.insert_commit(commit)); assert_eq!(builder.object_count(), 3); @@ -362,7 +345,7 @@ mod tests { { let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); - let (commit, _tree) = commit(&repo); + let (commit, _tree) = crate::test::commit(&repo); t!(builder.set_progress_callback(|_, _, _| { progress_called = true; true @@ -379,7 +362,7 @@ mod tests { { let (_td, repo) = crate::test::repo_init(); let mut builder = t!(repo.packbuilder()); - let (commit, _tree) = commit(&repo); + let (commit, _tree) = crate::test::commit(&repo); t!(builder.set_progress_callback(|_, _, _| { progress_called = true; true diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 90a6e5c98a..1c4c8d736b 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -1,6 +1,5 @@ use libc::{c_char, c_int, c_uint, c_void}; use std::ffi::{CStr, CString}; -use std::marker; use std::mem; use std::ptr; use std::slice; @@ -8,7 +7,7 @@ use std::str; use crate::cert::Cert; use crate::util::Binding; -use crate::{panic, raw, Cred, CredentialType, Error, Oid}; +use crate::{panic, raw, Cred, CredentialType, Error, IndexerProgress, Oid, Progress}; /// A structure to contain the callbacks which are invoked when a repository is /// being updated or downloaded. @@ -16,7 +15,7 @@ use crate::{panic, raw, Cred, CredentialType, Error, Oid}; /// These callbacks are used to manage facilities such as authentication, /// transfer progress, etc. pub struct RemoteCallbacks<'a> { - progress: Option>>, + progress: Option>>, credentials: Option>>, sideband_progress: Option>>, update_tips: Option>>, @@ -24,17 +23,6 @@ pub struct RemoteCallbacks<'a> { push_update_reference: Option>>, } -/// Struct representing the progress by an in-flight transfer. -pub struct Progress<'a> { - raw: ProgressState, - _marker: marker::PhantomData<&'a raw::git_transfer_progress>, -} - -enum ProgressState { - Borrowed(*const raw::git_transfer_progress), - Owned(raw::git_transfer_progress), -} - /// Callback used to acquire credentials for when a remote is fetched. /// /// * `url` - the resource for which the credentials are required. @@ -44,15 +32,6 @@ enum ProgressState { pub type Credentials<'a> = dyn FnMut(&str, Option<&str>, CredentialType) -> Result + 'a; -/// Callback to be invoked while a transfer is in progress. -/// -/// This callback will be periodically called with updates to the progress of -/// the transfer so far. The return value indicates whether the transfer should -/// continue. A return value of `false` will cancel the transfer. -/// -/// * `progress` - the progress being made so far. -pub type TransferProgress<'a> = dyn FnMut(Progress<'_>) -> bool + 'a; - /// Callback for receiving messages delivered by the transport. /// /// The return value indicates whether the network operation should continue. @@ -110,7 +89,7 @@ impl<'a> RemoteCallbacks<'a> { where F: FnMut(Progress<'_>) -> bool + 'a, { - self.progress = Some(Box::new(cb) as Box>); + self.progress = Some(Box::new(cb) as Box>); self } @@ -175,7 +154,7 @@ impl<'a> Binding for RemoteCallbacks<'a> { 0 ); if self.progress.is_some() { - let f: raw::git_transfer_progress_cb = transfer_progress_cb; + let f: raw::git_indexer_progress_cb = transfer_progress_cb; callbacks.transfer_progress = Some(f); } if self.credentials.is_some() { @@ -209,63 +188,6 @@ impl<'a> Binding for RemoteCallbacks<'a> { } } -impl<'a> Progress<'a> { - /// Number of objects in the packfile being downloaded - pub fn total_objects(&self) -> usize { - unsafe { (*self.raw()).total_objects as usize } - } - /// Received objects that have been hashed - pub fn indexed_objects(&self) -> usize { - unsafe { (*self.raw()).indexed_objects as usize } - } - /// Objects which have been downloaded - pub fn received_objects(&self) -> usize { - unsafe { (*self.raw()).received_objects as usize } - } - /// Locally-available objects that have been injected in order to fix a thin - /// pack. - pub fn local_objects(&self) -> usize { - unsafe { (*self.raw()).local_objects as usize } - } - /// Number of deltas in the packfile being downloaded - pub fn total_deltas(&self) -> usize { - unsafe { (*self.raw()).total_deltas as usize } - } - /// Received deltas that have been hashed. - pub fn indexed_deltas(&self) -> usize { - unsafe { (*self.raw()).indexed_deltas as usize } - } - /// Size of the packfile received up to now - pub fn received_bytes(&self) -> usize { - unsafe { (*self.raw()).received_bytes as usize } - } - - /// Convert this to an owned version of `Progress`. - pub fn to_owned(&self) -> Progress<'static> { - Progress { - raw: ProgressState::Owned(unsafe { *self.raw() }), - _marker: marker::PhantomData, - } - } -} - -impl<'a> Binding for Progress<'a> { - type Raw = *const raw::git_transfer_progress; - unsafe fn from_raw(raw: *const raw::git_transfer_progress) -> Progress<'a> { - Progress { - raw: ProgressState::Borrowed(raw), - _marker: marker::PhantomData, - } - } - - fn raw(&self) -> *const raw::git_transfer_progress { - match self.raw { - ProgressState::Borrowed(raw) => raw, - ProgressState::Owned(ref raw) => raw as *const _, - } - } -} - extern "C" fn credentials_cb( ret: *mut *mut raw::git_cred, url: *const c_char, @@ -316,7 +238,7 @@ extern "C" fn credentials_cb( } extern "C" fn transfer_progress_cb( - stats: *const raw::git_transfer_progress, + stats: *const raw::git_indexer_progress, payload: *mut c_void, ) -> c_int { let ok = panic::wrap(|| unsafe { diff --git a/src/test.rs b/src/test.rs index a3fe9448d8..149f4946c5 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,3 +1,4 @@ +use std::fs::File; use std::io; use std::path::{Path, PathBuf}; #[cfg(unix)] @@ -5,7 +6,7 @@ use std::ptr; use tempfile::TempDir; use url::Url; -use crate::Repository; +use crate::{Oid, Repository}; macro_rules! t { ($e:expr) => { @@ -34,6 +35,21 @@ pub fn repo_init() -> (TempDir, Repository) { (td, repo) } +pub fn commit(repo: &Repository) -> (Oid, Oid) { + let mut index = t!(repo.index()); + let root = repo.path().parent().unwrap(); + t!(File::create(&root.join("foo"))); + t!(index.add_path(Path::new("foo"))); + + let tree_id = t!(index.write_tree()); + let tree = t!(repo.find_tree(tree_id)); + let sig = t!(repo.signature()); + let head_id = t!(repo.refname_to_id("HEAD")); + let parent = t!(repo.find_commit(head_id)); + let commit = t!(repo.commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent])); + (commit, tree_id) +} + pub fn path2url(/service/path: &Path) -> String { Url::from_file_path(path).unwrap().to_string() } From 6a4b47d430a39ce39bfe15cc46ea6ec5a7bbf23b Mon Sep 17 00:00:00 2001 From: Stephan Seitz Date: Sat, 18 Jan 2020 14:41:47 +0100 Subject: [PATCH 425/860] Fix typo in examples/tag.rs --- examples/tag.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/tag.rs b/examples/tag.rs index 107b9db0c7..1e73889607 100644 --- a/examples/tag.rs +++ b/examples/tag.rs @@ -117,7 +117,7 @@ usage: tag [-n ] -l [] Options: - -n specify number of lines from teh annotation to print + -n specify number of lines from the annotation to print -f, --force replace an existing tag with the given name -l, --list list tags with names matching the pattern given -d, --delete delete the tag specified From ee122d2228234d4c42d74b001baf9cf888bde615 Mon Sep 17 00:00:00 2001 From: Tuomas Siipola Date: Thu, 23 Jan 2020 17:26:27 +0200 Subject: [PATCH 426/860] Expose DiffFile flags and mode (#514) --- libgit2-sys/lib.rs | 9 +++++++++ src/diff.rs | 35 +++++++++++++++++++++++++++++++++-- src/lib.rs | 17 +++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 576cf2d995..eba2077126 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -461,6 +461,15 @@ git_enum! { } } +git_enum! { + pub enum git_diff_flag_t { + GIT_DIFF_FLAG_BINARY = 1 << 0, + GIT_DIFF_FLAG_NOT_BINARY = 1 << 1, + GIT_DIFF_FLAG_VALID_ID = 1 << 2, + GIT_DIFF_FLAG_EXISTS = 1 << 3, + } +} + #[repr(C)] pub struct git_diff_file { pub id: git_oid, diff --git a/src/diff.rs b/src/diff.rs index b8bfddfee0..4e959ac27c 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -8,7 +8,7 @@ use std::ptr; use std::slice; use crate::util::{self, Binding}; -use crate::{panic, raw, Buf, Delta, DiffFormat, Error, Oid, Repository}; +use crate::{panic, raw, Buf, Delta, DiffFormat, Error, FileMode, Oid, Repository}; use crate::{DiffStatsFormat, IntoCString}; /// The diff object that contains all individual file deltas. @@ -482,7 +482,38 @@ impl<'a> DiffFile<'a> { unsafe { (*self.raw).size as u64 } } - // TODO: expose flags/mode + /// Returns `true` if file(s) are treated as binary data. + pub fn is_binary(&self) -> bool { + unsafe { (*self.raw).flags & raw::GIT_DIFF_FLAG_BINARY as u32 != 0 } + } + + /// Returns `true` if file(s) are treated as text data. + pub fn is_not_binary(&self) -> bool { + unsafe { (*self.raw).flags & raw::GIT_DIFF_FLAG_NOT_BINARY as u32 != 0 } + } + + /// Returns `true` if `id` value is known correct. + pub fn is_valid_id(&self) -> bool { + unsafe { (*self.raw).flags & raw::GIT_DIFF_FLAG_VALID_ID as u32 != 0 } + } + + /// Returns `true` if file exists at this side of the delta. + pub fn exists(&self) -> bool { + unsafe { (*self.raw).flags & raw::GIT_DIFF_FLAG_EXISTS as u32 != 0 } + } + + /// Returns file mode. + pub fn mode(&self) -> FileMode { + match unsafe { (*self.raw).mode.into() } { + raw::GIT_FILEMODE_UNREADABLE => FileMode::Unreadable, + raw::GIT_FILEMODE_TREE => FileMode::Tree, + raw::GIT_FILEMODE_BLOB => FileMode::Blob, + raw::GIT_FILEMODE_BLOB_EXECUTABLE => FileMode::BlobExecutable, + raw::GIT_FILEMODE_LINK => FileMode::Link, + raw::GIT_FILEMODE_COMMIT => FileMode::Commit, + mode => panic!("unknown mode: {}", mode), + } + } } impl<'a> Binding for DiffFile<'a> { diff --git a/src/lib.rs b/src/lib.rs index 0ee8f9d7b8..b7fe37d189 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1004,6 +1004,23 @@ pub enum Delta { Conflicted, } +/// Valid modes for index and tree entries. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum FileMode { + /// Unreadable + Unreadable, + /// Tree + Tree, + /// Blob + Blob, + /// Blob executable + BlobExecutable, + /// Link + Link, + /// Commit + Commit, +} + bitflags! { /// Return codes for submodule status. /// From 87b2cd3b66d4cc195babe2864e29b192572d8abc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 28 Jan 2020 00:40:38 -0800 Subject: [PATCH 427/860] Update CI installation of Rust on macos --- .github/workflows/main.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e3bf819908..567a830852 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,13 +28,7 @@ jobs: - uses: actions/checkout@master - name: Install Rust (rustup) run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} - if: matrix.os != 'macos-latest' shell: bash - - name: Install Rust (macos) - run: | - curl https://sh.rustup.rs | sh -s -- -y - echo "##[add-path]$HOME/.cargo/bin" - if: matrix.os == 'macos-latest' - run: cargo test --no-default-features - run: cargo test - run: cargo run --manifest-path systest/Cargo.toml From 0174895e7aed02409078b8b6db205dae99f7612a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 28 Jan 2020 00:45:36 -0800 Subject: [PATCH 428/860] Remove unnecessary parens --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index b7fe37d189..9cf3a56228 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -827,7 +827,7 @@ impl ObjectType { /// Determine if the given git_object_t is a valid loose object type. pub fn is_loose(&self) -> bool { - unsafe { (call!(raw::git_object_typeisloose(*self)) == 1) } + unsafe { call!(raw::git_object_typeisloose(*self)) == 1 } } /// Convert a raw git_object_t to an ObjectType From 9f16b6ed915207a79c6c767ac6a538c83fe5436c Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Fri, 7 Feb 2020 00:13:03 +0900 Subject: [PATCH 429/860] Support libgit2 error message report when assertion failed (#517) * Support libgit2 error message report when assertion failed * Check fetched return code and print error messages when its nagative --- libgit2-sys/lib.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index eba2077126..9d1afba840 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -7,6 +7,8 @@ extern crate libz_sys as libz; use libc::{c_char, c_int, c_uchar, c_uint, c_void, size_t}; #[cfg(feature = "ssh")] use libssh2_sys as libssh2; +use std::ffi::CStr; +use std::ptr; pub const GIT_OID_RAWSZ: usize = 20; pub const GIT_OID_HEXSZ: usize = GIT_OID_RAWSZ * 2; @@ -3551,7 +3553,25 @@ pub fn init() { openssl_init(); ssh_init(); let r = git_libgit2_init(); - assert!(r >= 0, "couldn't initialize the libgit2 library: {}", r); + if r < 0 { + let git_error = git_error_last(); + let mut error_msg: *mut c_char = ptr::null_mut(); + if !git_error.is_null() { + error_msg = (*git_error).message; + } + if !error_msg.is_null() { + assert!( + r >= 0, + "couldn't initialize the libgit2 library: {}, error: {}", + r, + CStr::from_ptr(error_msg).to_string_lossy() + ); + } else { + assert!(r >= 0, "couldn't initialize the libgit2 library: {}", r); + } + } else { + assert!(r >= 0, "couldn't initialize the libgit2 library: {}", r); + } // Note that we intentionally never schedule `git_libgit2_shutdown` to // get called. There's not really a great time to call that and #276 has From 2c7b2c281fa07f8805326eadaa08d621636a80bc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 6 Feb 2020 07:15:49 -0800 Subject: [PATCH 430/860] Tidy up one-time initialization --- libgit2-sys/lib.rs | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 9d1afba840..a5998af84c 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -8,7 +8,6 @@ use libc::{c_char, c_int, c_uchar, c_uint, c_void, size_t}; #[cfg(feature = "ssh")] use libssh2_sys as libssh2; use std::ffi::CStr; -use std::ptr; pub const GIT_OID_RAWSZ: usize = 20; pub const GIT_OID_HEXSZ: usize = GIT_OID_RAWSZ * 2; @@ -3552,30 +3551,25 @@ pub fn init() { INIT.call_once(|| unsafe { openssl_init(); ssh_init(); - let r = git_libgit2_init(); - if r < 0 { - let git_error = git_error_last(); - let mut error_msg: *mut c_char = ptr::null_mut(); - if !git_error.is_null() { - error_msg = (*git_error).message; - } - if !error_msg.is_null() { - assert!( - r >= 0, - "couldn't initialize the libgit2 library: {}, error: {}", - r, - CStr::from_ptr(error_msg).to_string_lossy() - ); - } else { - assert!(r >= 0, "couldn't initialize the libgit2 library: {}", r); - } - } else { - assert!(r >= 0, "couldn't initialize the libgit2 library: {}", r); + let rc = git_libgit2_init(); + if rc >= 0 { + // Note that we intentionally never schedule `git_libgit2_shutdown` + // to get called. There's not really a great time to call that and + // #276 has some more info about how automatically doing it can + // cause problems. + return; } - // Note that we intentionally never schedule `git_libgit2_shutdown` to - // get called. There's not really a great time to call that and #276 has - // some more info about how automatically doing it can cause problems. + let git_error = git_error_last(); + let error = if !git_error.is_null() { + CStr::from_ptr((*git_error).message).to_string_lossy() + } else { + "unknown error".into() + }; + panic!( + "couldn't initialize the libgit2 library: {}, error: {}", + rc, error + ); }); } From 43b8e28ada54120ff55dc550ab177109f162eb10 Mon Sep 17 00:00:00 2001 From: Matthias Schwarz Date: Fri, 7 Feb 2020 15:38:46 +0100 Subject: [PATCH 431/860] Add support for non defined value in ConfigEntry (#518) --- src/config.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/config.rs b/src/config.rs index cc190899eb..ddda1d4fe2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -449,15 +449,30 @@ impl<'cfg> ConfigEntry<'cfg> { /// Gets the value of this entry. /// /// May return `None` if the value is not valid utf-8 + /// + /// # Panics + /// + /// Panics when no value is defined. pub fn value(&self) -> Option<&str> { str::from_utf8(self.value_bytes()).ok() } /// Gets the value of this entry as a byte slice. + /// + /// # Panics + /// + /// Panics when no value is defined. pub fn value_bytes(&self) -> &[u8] { unsafe { crate::opt_bytes(self, (*self.raw).value).unwrap() } } + /// Returns `true` when a value is defined otherwise `false`. + /// + /// No value defined is a short-hand to represent a Boolean `true`. + pub fn has_value(&self) -> bool { + unsafe { !(*self.raw).value.is_null() } + } + /// Gets the configuration level of this entry. pub fn level(&self) -> ConfigLevel { unsafe { ConfigLevel::from_raw((*self.raw).level) } From 147c5b4f026f8fa53a8a5d79dcbd59012a585a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Greinhofer?= Date: Tue, 18 Feb 2020 08:33:05 -0600 Subject: [PATCH 432/860] Add examples (#519) While starting to use this library, I spent way too much time trying to perform the 3 following tasks, therefore I thought I would contribute some examples to the documentation. The examples should help to: * Clone/push using SSH * Stage all files --- src/build.rs | 35 +++++++++++++++++++++++++++++++++++ src/index.rs | 13 +++++++++++++ src/lib.rs | 2 ++ src/remote_callbacks.rs | 20 ++++++++++++++++++++ 4 files changed, 70 insertions(+) diff --git a/src/build.rs b/src/build.rs index 397ad75d55..62f42f752e 100644 --- a/src/build.rs +++ b/src/build.rs @@ -12,6 +12,41 @@ use crate::{CheckoutNotificationType, DiffFile, Remote}; /// A builder struct which is used to build configuration for cloning a new git /// repository. +/// +/// # Example +/// +/// Cloning using SSH: +/// +/// ```no_run +/// use git2::{Cred, Error, RemoteCallbacks}; +/// use std::env; +/// use std::path::Path; +/// +/// // Prepare callbacks. +/// let mut callbacks = RemoteCallbacks::new(); +/// callbacks.credentials(|_url, username_from_url, _allowed_types| { +/// Cred::ssh_key( +/// username_from_url.unwrap(), +/// None, +/// std::path::Path::new(&format!("{}/.ssh/id_rsa", env::var("HOME").unwrap())), +/// None, +/// ) +/// }); +/// +/// // Prepare fetch options. +/// let mut fo = git2::FetchOptions::new(); +/// fo.remote_callbacks(callbacks); +/// +/// // Prepare builder. +/// let mut builder = git2::build::RepoBuilder::new(); +/// builder.fetch_options(fo); +/// +/// // Clone the project. +/// builder.clone( +/// "git@github.com:rust-lang/git2-rs.git", +/// Path::new("/tmp/git2-rs"), +/// ); +/// ``` pub struct RepoBuilder<'cb> { bare: bool, branch: Option, diff --git a/src/index.rs b/src/index.rs index f2188fceff..4d537b64a6 100644 --- a/src/index.rs +++ b/src/index.rs @@ -268,6 +268,19 @@ impl Index { /// updated in the index. Returning zero will add the item to the index, /// greater than zero will skip the item, and less than zero will abort the /// scan an return an error to the caller. + /// + /// # Example + /// + /// Emulate `git add *`: + /// + /// ```no_run + /// use git2::{Index, IndexAddOption, Repository}; + /// + /// let repo = Repository::open("/path/to/a/repo").expect("failed to open"); + /// let mut index = repo.index().expect("cannot get the Index file"); + /// index.add_all(["*"].iter(), IndexAddOption::DEFAULT, None); + /// index.write(); + /// ``` pub fn add_all( &mut self, pathspecs: I, diff --git a/src/lib.rs b/src/lib.rs index 9cf3a56228..9c82610dbe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,6 +57,8 @@ //! }; //! ``` //! +//! To clone using SSH, refer to [RepoBuilder](./build/struct.RepoBuilder.html). +//! //! ## Working with a `Repository` //! //! All deriviative objects, references, etc are attached to the lifetime of the diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 1c4c8d736b..619cef610c 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -76,6 +76,26 @@ impl<'a> RemoteCallbacks<'a> { } /// The callback through which to fetch credentials if required. + /// + /// # Example + /// + /// Prepare a callback to authenticate using the `$HOME/.ssh/id_rsa` SSH key, and + /// extracting the username from the URL (i.e. git@github.com:rust-lang/git2-rs.git): + /// + /// ```no_run + /// use git2::{Cred, RemoteCallbacks}; + /// use std::env; + /// + /// let mut callbacks = RemoteCallbacks::new(); + /// callbacks.credentials(|_url, username_from_url, _allowed_types| { + /// Cred::ssh_key( + /// username_from_url.unwrap(), + /// None, + /// std::path::Path::new(&format!("{}/.ssh/id_rsa", env::var("HOME").unwrap())), + /// None, + /// ) + /// }); + /// ``` pub fn credentials(&mut self, cb: F) -> &mut RemoteCallbacks<'a> where F: FnMut(&str, Option<&str>, CredentialType) -> Result + 'a, From 850c9b96d5659f40ee31d1b3d130a4806c91ff61 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 19 Feb 2020 12:06:37 -0600 Subject: [PATCH 433/860] Update the libgit2 submodule to v0.99.0 (#520) * Update the libgit2 submodule to v0.99.0 Brings in a number of API improvements, security fixes, etc. * rustfmt --- examples/fetch.rs | 2 +- examples/log.rs | 2 +- examples/rev-list.rs | 2 +- libgit2-sys/lib.rs | 28 ++++++++++++++-------------- libgit2-sys/libgit2 | 2 +- src/oid.rs | 4 +++- src/remote.rs | 13 ++++++++----- src/repo.rs | 5 +++-- src/revwalk.rs | 28 ++++++++++++++++++++-------- src/transport.rs | 2 +- src/treebuilder.rs | 26 ++++++++++++++++++-------- 11 files changed, 71 insertions(+), 43 deletions(-) diff --git a/examples/fetch.rs b/examples/fetch.rs index 6ede3c9ab5..212f934da4 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -107,7 +107,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } // Disconnect the underlying connection to prevent from idling. - remote.disconnect(); + remote.disconnect()?; // Update the references in the remote's namespace to point to the right // commits. This may be needed even if there was no packfile to download, diff --git a/examples/log.rs b/examples/log.rs index 94066f385a..d7f7711186 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -61,7 +61,7 @@ fn run(args: &Args) -> Result<(), Error> { } else { git2::Sort::NONE }, - ); + )?; for commit in &args.arg_commit { if commit.starts_with('^') { let obj = repo.revparse_single(&commit[1..])?; diff --git a/examples/rev-list.rs b/examples/rev-list.rs index 84c0adcedb..de72102671 100644 --- a/examples/rev-list.rs +++ b/examples/rev-list.rs @@ -45,7 +45,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } else { git2::Sort::NONE }, - ); + )?; let specs = args .flag_not diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a5998af84c..b6ad79ab4c 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1752,13 +1752,13 @@ extern "C" { update_gitlink: c_int, ) -> c_int; pub fn git_repository_index(out: *mut *mut git_index, repo: *mut git_repository) -> c_int; - pub fn git_repository_set_index(repo: *mut git_repository, index: *mut git_index); + pub fn git_repository_set_index(repo: *mut git_repository, index: *mut git_index) -> c_int; pub fn git_repository_message(buf: *mut git_buf, repo: *mut git_repository) -> c_int; pub fn git_repository_message_remove(repo: *mut git_repository) -> c_int; pub fn git_repository_config(out: *mut *mut git_config, repo: *mut git_repository) -> c_int; - pub fn git_repository_set_config(repo: *mut git_repository, config: *mut git_config); + pub fn git_repository_set_config(repo: *mut git_repository, config: *mut git_config) -> c_int; pub fn git_repository_config_snapshot( out: *mut *mut git_config, repo: *mut git_repository, @@ -1769,10 +1769,10 @@ extern "C" { across_fs: c_int, ceiling_dirs: *const c_char, ) -> c_int; - pub fn git_repository_set_odb(repo: *mut git_repository, odb: *mut git_odb); + pub fn git_repository_set_odb(repo: *mut git_repository, odb: *mut git_odb) -> c_int; pub fn git_repository_refdb(out: *mut *mut git_refdb, repo: *mut git_repository) -> c_int; - pub fn git_repository_set_refdb(repo: *mut git_repository, refdb: *mut git_refdb); + pub fn git_repository_set_refdb(repo: *mut git_repository, refdb: *mut git_refdb) -> c_int; pub fn git_repository_reinit_filesystem( repo: *mut git_repository, @@ -1826,7 +1826,7 @@ extern "C" { pub fn git_object_typeisloose(kind: git_object_t) -> c_int; // oid - pub fn git_oid_fromraw(out: *mut git_oid, raw: *const c_uchar); + pub fn git_oid_fromraw(out: *mut git_oid, raw: *const c_uchar) -> c_int; pub fn git_oid_fromstrn(out: *mut git_oid, str: *const c_char, len: size_t) -> c_int; pub fn git_oid_tostr(out: *mut c_char, n: size_t, id: *const git_oid) -> *mut c_char; pub fn git_oid_cmp(a: *const git_oid, b: *const git_oid) -> c_int; @@ -1837,7 +1837,7 @@ extern "C" { // error pub fn git_error_last() -> *const git_error; pub fn git_error_clear(); - pub fn git_error_set_str(error_class: c_int, string: *const c_char); + pub fn git_error_set_str(error_class: c_int, string: *const c_char) -> c_int; // remote pub fn git_remote_create( @@ -1877,7 +1877,7 @@ extern "C" { 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); + pub fn git_remote_disconnect(remote: *mut git_remote) -> c_int; pub fn git_remote_add_fetch( repo: *mut git_repository, remote: *const c_char, @@ -1893,7 +1893,7 @@ extern "C" { refspecs: *const git_strarray, opts: *const git_fetch_options, ) -> c_int; - pub fn git_remote_stop(remote: *mut git_remote); + pub fn git_remote_stop(remote: *mut git_remote) -> c_int; pub fn git_remote_dup(dest: *mut *mut git_remote, source: *mut git_remote) -> c_int; pub fn git_remote_get_fetch_refspecs( array: *mut git_strarray, @@ -2336,7 +2336,7 @@ extern "C" { repo: *mut git_repository, source: *const git_tree, ) -> c_int; - pub fn git_treebuilder_clear(bld: *mut git_treebuilder); + pub fn git_treebuilder_clear(bld: *mut git_treebuilder) -> c_int; pub fn git_treebuilder_entrycount(bld: *mut git_treebuilder) -> size_t; pub fn git_treebuilder_free(bld: *mut git_treebuilder); pub fn git_treebuilder_get( @@ -2355,7 +2355,7 @@ extern "C" { bld: *mut git_treebuilder, filter: git_treebuilder_filter_cb, payload: *mut c_void, - ); + ) -> c_int; pub fn git_treebuilder_write(id: *mut git_oid, bld: *mut git_treebuilder) -> c_int; // buf @@ -2926,16 +2926,16 @@ extern "C" { pub fn git_revwalk_new(out: *mut *mut git_revwalk, repo: *mut git_repository) -> c_int; pub fn git_revwalk_free(walk: *mut git_revwalk); - pub fn git_revwalk_reset(walk: *mut git_revwalk); + pub fn git_revwalk_reset(walk: *mut git_revwalk) -> c_int; - pub fn git_revwalk_sorting(walk: *mut git_revwalk, sort_mode: c_uint); + pub fn git_revwalk_sorting(walk: *mut git_revwalk, sort_mode: c_uint) -> c_int; pub fn git_revwalk_push_head(walk: *mut git_revwalk) -> c_int; pub fn git_revwalk_push(walk: *mut git_revwalk, oid: *const git_oid) -> c_int; pub fn git_revwalk_push_ref(walk: *mut git_revwalk, refname: *const c_char) -> c_int; pub fn git_revwalk_push_glob(walk: *mut git_revwalk, glob: *const c_char) -> c_int; pub fn git_revwalk_push_range(walk: *mut git_revwalk, range: *const c_char) -> c_int; - pub fn git_revwalk_simplify_first_parent(walk: *mut git_revwalk); + pub fn git_revwalk_simplify_first_parent(walk: *mut git_revwalk) -> c_int; pub fn git_revwalk_hide_head(walk: *mut git_revwalk) -> c_int; pub fn git_revwalk_hide(walk: *mut git_revwalk, oid: *const git_oid) -> c_int; @@ -3469,7 +3469,7 @@ extern "C" { // mempack pub fn git_mempack_new(out: *mut *mut git_odb_backend) -> c_int; - pub fn git_mempack_reset(backend: *mut git_odb_backend); + pub fn git_mempack_reset(backend: *mut git_odb_backend) -> c_int; pub fn git_mempack_dump( pack: *mut git_buf, repo: *mut git_repository, diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index cc4f4cbea4..172239021f 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit cc4f4cbea48ac00a5edec1b3570ac3d2ef10fe77 +Subproject commit 172239021f7ba04fe7327647b213799853a9eb89 diff --git a/src/oid.rs b/src/oid.rs index 4f69bec8ef..59f2a7ffa2 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -49,7 +49,9 @@ impl Oid { if bytes.len() != raw::GIT_OID_RAWSZ { Err(Error::from_str("raw byte array must be 20 bytes")) } else { - unsafe { raw::git_oid_fromraw(&mut raw, bytes.as_ptr()) } + unsafe { + try_call!(raw::git_oid_fromraw(&mut raw, bytes.as_ptr())); + } Ok(Oid { raw: raw }) } } diff --git a/src/remote.rs b/src/remote.rs index ded0387fb2..b00f7e1c84 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -161,8 +161,11 @@ impl<'repo> Remote<'repo> { } /// Disconnect from the remote - pub fn disconnect(&mut self) { - unsafe { raw::git_remote_disconnect(self.raw) } + pub fn disconnect(&mut self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_remote_disconnect(self.raw)); + } + Ok(()) } /// Download and index the packfile @@ -577,7 +580,7 @@ impl<'repo, 'connection, 'cb> RemoteConnection<'repo, 'connection, 'cb> { impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb> { fn drop(&mut self) { - self.remote.disconnect() + drop(self.remote.disconnect()); } } @@ -648,12 +651,12 @@ mod tests { origin.connect(Direction::Push).unwrap(); assert!(origin.connected()); - origin.disconnect(); + origin.disconnect().unwrap(); origin.connect(Direction::Fetch).unwrap(); assert!(origin.connected()); origin.download(&[] as &[&str], None).unwrap(); - origin.disconnect(); + origin.disconnect().unwrap(); { let mut connection = origin.connect_auth(Direction::Push, None, None).unwrap(); diff --git a/src/repo.rs b/src/repo.rs index 77694df008..29ca2b37f9 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -891,10 +891,11 @@ impl Repository { } /// Set the Index file for this repository. - pub fn set_index(&self, index: &mut Index) { + pub fn set_index(&self, index: &mut Index) -> Result<(), Error> { unsafe { - raw::git_repository_set_index(self.raw(), index.raw()); + try_call!(raw::git_repository_set_index(self.raw(), index.raw())); } + Ok(()) } /// Get the configuration file for this repository. diff --git a/src/revwalk.rs b/src/revwalk.rs index 4afd36ed9f..00152a2e32 100644 --- a/src/revwalk.rs +++ b/src/revwalk.rs @@ -17,20 +17,32 @@ impl<'repo> Revwalk<'repo> { /// /// The revwalk is automatically reset when iteration of its commits /// completes. - pub fn reset(&mut self) { - unsafe { raw::git_revwalk_reset(self.raw()) } + pub fn reset(&mut self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_revwalk_reset(self.raw())); + } + Ok(()) } /// Set the order in which commits are visited. - pub fn set_sorting(&mut self, sort_mode: Sort) { - unsafe { raw::git_revwalk_sorting(self.raw(), sort_mode.bits() as c_uint) } + pub fn set_sorting(&mut self, sort_mode: Sort) -> Result<(), Error> { + unsafe { + try_call!(raw::git_revwalk_sorting( + self.raw(), + sort_mode.bits() as c_uint + )); + } + Ok(()) } /// Simplify the history by first-parent /// /// No parents other than the first for each commit will be enqueued. - pub fn simplify_first_parent(&mut self) { - unsafe { raw::git_revwalk_simplify_first_parent(self.raw) } + pub fn simplify_first_parent(&mut self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_revwalk_simplify_first_parent(self.raw)); + } + Ok(()) } /// Mark a commit to start traversal from. @@ -195,11 +207,11 @@ mod tests { assert_eq!(oids.len(), 1); assert_eq!(oids[0], target); - walk.reset(); + walk.reset().unwrap(); walk.push_head().unwrap(); assert_eq!(walk.by_ref().count(), 1); - walk.reset(); + walk.reset().unwrap(); walk.push_head().unwrap(); walk.hide_head().unwrap(); assert_eq!(walk.by_ref().count(), 0); diff --git a/src/transport.rs b/src/transport.rs index 0543c39779..e7b398ce6b 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -343,7 +343,7 @@ extern "C" fn stream_write( unsafe fn set_err(e: &io::Error) { let s = CString::new(e.to_string()).unwrap(); - raw::git_error_set_str(raw::GIT_ERROR_NET as c_int, s.as_ptr()) + raw::git_error_set_str(raw::GIT_ERROR_NET as c_int, s.as_ptr()); } // callback used by smart transports to free a `SmartSubtransportStream` diff --git a/src/treebuilder.rs b/src/treebuilder.rs index 4eec55c10b..e14d96319b 100644 --- a/src/treebuilder.rs +++ b/src/treebuilder.rs @@ -14,8 +14,11 @@ pub struct TreeBuilder<'repo> { impl<'repo> TreeBuilder<'repo> { /// Clear all the entries in the builder - pub fn clear(&mut self) { - unsafe { raw::git_treebuilder_clear(self.raw) } + pub fn clear(&mut self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_treebuilder_clear(self.raw)); + } + Ok(()) } /// Get the number of entries @@ -86,16 +89,21 @@ impl<'repo> TreeBuilder<'repo> { /// /// Values for which the filter returns `true` will be kept. Note /// that this behavior is different from the libgit2 C interface. - pub fn filter(&mut self, mut filter: F) + pub fn filter(&mut self, mut filter: F) -> Result<(), Error> where F: FnMut(&TreeEntry<'_>) -> bool, { let mut cb: &mut FilterCb<'_> = &mut filter; let ptr = &mut cb as *mut _; unsafe { - raw::git_treebuilder_filter(self.raw, filter_cb, ptr as *mut _); + try_call!(raw::git_treebuilder_filter( + self.raw, + filter_cb, + ptr as *mut _ + )); panic::check(); } + Ok(()) } /// Write the contents of the TreeBuilder as a Tree object and @@ -171,7 +179,7 @@ mod tests { builder.remove("a").unwrap(); assert_eq!(builder.len(), 1); assert_eq!(builder.get("b").unwrap().unwrap().id(), blob); - builder.clear(); + builder.clear().unwrap(); assert_eq!(builder.len(), 0); } @@ -209,11 +217,13 @@ mod tests { builder.insert("dir", tree, 0o040000).unwrap(); builder.insert("dir2", tree, 0o040000).unwrap(); - builder.filter(|_| true); + builder.filter(|_| true).unwrap(); assert_eq!(builder.len(), 3); - builder.filter(|e| e.kind().unwrap() != ObjectType::Blob); + builder + .filter(|e| e.kind().unwrap() != ObjectType::Blob) + .unwrap(); assert_eq!(builder.len(), 2); - builder.filter(|_| false); + builder.filter(|_| false).unwrap(); assert_eq!(builder.len(), 0); } } From 9071a87bad3f4ff96ce491f871b0cb1e0ab2549f Mon Sep 17 00:00:00 2001 From: Andrew Hickman Date: Mon, 24 Feb 2020 15:51:17 +0000 Subject: [PATCH 434/860] Add `Branch::get_mut()` (#522) --- src/branch.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/branch.rs b/src/branch.rs index 75ae018ec7..c33a18370e 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -33,6 +33,11 @@ impl<'repo> Branch<'repo> { &self.inner } + /// Gain mutable access to the reference that is this branch + pub fn get_mut(&mut self) -> &mut Reference<'repo> { + &mut self.inner + } + /// Take ownership of the underlying reference. pub fn into_reference(self) -> Reference<'repo> { self.inner From ecd56b00fb83114cff54fcdaf103aad22e31c59f Mon Sep 17 00:00:00 2001 From: Andrey Nekrasov Date: Wed, 26 Feb 2020 20:36:16 +0300 Subject: [PATCH 435/860] Tie Patch lifetime to its input buffers (#523) --- src/patch.rs | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/patch.rs b/src/patch.rs index dcbaa6e1bd..370782b281 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -1,4 +1,5 @@ use libc::{c_int, c_void}; +use std::marker::PhantomData; use std::path::Path; use std::ptr; @@ -9,33 +10,37 @@ use crate::{raw, Blob, Buf, Diff, DiffDelta, DiffHunk, DiffLine, DiffOptions, Er /// A structure representing the text changes in a single diff delta. /// /// This is an opaque structure. -pub struct Patch { +pub struct Patch<'buffers> { raw: *mut raw::git_patch, + buffers: PhantomData<&'buffers ()>, } -unsafe impl Send for Patch {} +unsafe impl<'buffers> Send for Patch<'buffers> {} -impl Binding for Patch { +impl<'buffers> Binding for Patch<'buffers> { type Raw = *mut raw::git_patch; - unsafe fn from_raw(raw: Self::Raw) -> Patch { - Patch { raw: raw } + unsafe fn from_raw(raw: Self::Raw) -> Self { + Patch { + raw: raw, + buffers: PhantomData, + } } fn raw(&self) -> Self::Raw { self.raw } } -impl Drop for Patch { +impl<'buffers> Drop for Patch<'buffers> { fn drop(&mut self) { unsafe { raw::git_patch_free(self.raw) } } } -impl Patch { +impl<'buffers> Patch<'buffers> { /// Return a Patch for one file in a Diff. /// /// Returns Ok(None) for an unchanged or binary file. - pub fn from_diff(diff: &Diff<'_>, idx: usize) -> Result, Error> { + pub fn from_diff(diff: &Diff<'buffers>, idx: usize) -> Result, Error> { let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_patch_from_diff(&mut ret, diff.raw(), idx)); @@ -45,12 +50,12 @@ impl Patch { /// Generate a Patch by diffing two blobs. pub fn from_blobs( - old_blob: &Blob<'_>, + old_blob: &Blob<'buffers>, old_path: Option<&Path>, - new_blob: &Blob<'_>, + new_blob: &Blob<'buffers>, new_path: Option<&Path>, opts: Option<&mut DiffOptions>, - ) -> Result { + ) -> Result { let mut ret = ptr::null_mut(); let old_path = into_opt_c_string(old_path)?; let new_path = into_opt_c_string(new_path)?; @@ -69,12 +74,12 @@ impl Patch { /// Generate a Patch by diffing a blob and a buffer. pub fn from_blob_and_buffer( - old_blob: &Blob<'_>, + old_blob: &Blob<'buffers>, old_path: Option<&Path>, - new_buffer: &[u8], + new_buffer: &'buffers [u8], new_path: Option<&Path>, opts: Option<&mut DiffOptions>, - ) -> Result { + ) -> Result { let mut ret = ptr::null_mut(); let old_path = into_opt_c_string(old_path)?; let new_path = into_opt_c_string(new_path)?; @@ -94,12 +99,12 @@ impl Patch { /// Generate a Patch by diffing two buffers. pub fn from_buffers( - old_buffer: &[u8], + old_buffer: &'buffers [u8], old_path: Option<&Path>, - new_buffer: &[u8], + new_buffer: &'buffers [u8], new_path: Option<&Path>, opts: Option<&mut DiffOptions>, - ) -> Result { + ) -> Result { crate::init(); let mut ret = ptr::null_mut(); let old_path = into_opt_c_string(old_path)?; @@ -120,7 +125,7 @@ impl Patch { } /// Get the DiffDelta associated with the Patch. - pub fn delta(&self) -> DiffDelta<'_> { + pub fn delta(&self) -> DiffDelta<'buffers> { unsafe { Binding::from_raw(raw::git_patch_get_delta(self.raw) as *mut _) } } @@ -146,7 +151,7 @@ impl Patch { } /// Get a DiffHunk and its total line count from the Patch. - pub fn hunk(&self, hunk_idx: usize) -> Result<(DiffHunk<'_>, usize), Error> { + pub fn hunk(&self, hunk_idx: usize) -> Result<(DiffHunk<'buffers>, usize), Error> { let mut ret = ptr::null(); let mut lines = 0; unsafe { @@ -167,7 +172,7 @@ impl Patch { &self, hunk_idx: usize, line_of_hunk: usize, - ) -> Result, Error> { + ) -> Result, Error> { let mut ret = ptr::null(); unsafe { try_call!(raw::git_patch_get_line_in_hunk( @@ -216,7 +221,7 @@ impl Patch { } } -impl std::fmt::Debug for Patch { +impl<'buffers> std::fmt::Debug for Patch<'buffers> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { let mut ds = f.debug_struct("Patch"); ds.field("delta", &self.delta()) From 666aeab3491526004b1f458914001ca9801bcb70 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 26 Feb 2020 09:37:15 -0800 Subject: [PATCH 436/860] Bump version numbers of crates --- Cargo.toml | 4 ++-- git2-curl/Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2ceb4344ca..ed7696b04c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.11.0" +version = "0.12.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.10.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.11.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 1d75a1d281..49cb0910d9 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "git2-curl" -version = "0.12.0" +version = "0.13.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" @@ -17,7 +17,7 @@ edition = "2018" curl = "0.4" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.11", default-features = false } +git2 = { path = "..", version = "0.12", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 525f1192c1..2ab481a781 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.10.0" +version = "0.11.0+0.99.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 08114526f83fb64c1620161891a0339da3929b15 Mon Sep 17 00:00:00 2001 From: Andrew Hickman Date: Mon, 2 Mar 2020 14:42:47 +0000 Subject: [PATCH 437/860] Add Repository::fetchhead_to_annotated_commit (#524) --- libgit2-sys/lib.rs | 7 +++++++ src/repo.rs | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index b6ad79ab4c..b3f281c648 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2828,6 +2828,13 @@ extern "C" { repo: *mut git_repository, reference: *const git_reference, ) -> c_int; + pub fn git_annotated_commit_from_fetchhead( + out: *mut *mut git_annotated_commit, + repo: *mut git_repository, + branch_name: *const c_char, + remote_url: *const c_char, + oid: *const git_oid, + ) -> c_int; pub fn git_annotated_commit_free(commit: *mut git_annotated_commit); pub fn git_merge_init_options(opts: *mut git_merge_options, version: c_uint) -> c_int; pub fn git_merge( diff --git a/src/repo.rs b/src/repo.rs index 29ca2b37f9..89a40b53a1 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1442,6 +1442,29 @@ impl Repository { } } + /// Creates a git_annotated_commit from FETCH_HEAD. + pub fn annotated_commit_from_fetchhead( + &self, + branch_name: &str, + remote_url: &str, + id: &Oid, + ) -> Result, Error> { + let branch_name = CString::new(branch_name)?; + let remote_url = CString::new(remote_url)?; + + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_annotated_commit_from_fetchhead( + &mut ret, + self.raw(), + branch_name, + remote_url, + id.raw() + )); + Ok(AnnotatedCommit::from_raw(ret)) + } + } + /// Create a new action signature with default user and now timestamp. /// /// This looks up the user.name and user.email from the configuration and From d34e49cc120a08557d85134064352925845105fa Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 13 Mar 2020 08:49:35 -0700 Subject: [PATCH 438/860] Remove unnecessary parentheses. (#526) --- libgit2-sys/lib.rs | 170 ++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index b3f281c648..f6e9c3201c 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -494,11 +494,11 @@ pub type git_remote_create_cb = extern "C" fn( git_enum! { pub enum git_checkout_notify_t { GIT_CHECKOUT_NOTIFY_NONE = 0, - GIT_CHECKOUT_NOTIFY_CONFLICT = (1 << 0), - GIT_CHECKOUT_NOTIFY_DIRTY = (1 << 1), - GIT_CHECKOUT_NOTIFY_UPDATED = (1 << 2), - GIT_CHECKOUT_NOTIFY_UNTRACKED = (1 << 3), - GIT_CHECKOUT_NOTIFY_IGNORED = (1 << 4), + GIT_CHECKOUT_NOTIFY_CONFLICT = 1 << 0, + GIT_CHECKOUT_NOTIFY_DIRTY = 1 << 1, + GIT_CHECKOUT_NOTIFY_UPDATED = 1 << 2, + GIT_CHECKOUT_NOTIFY_UNTRACKED = 1 << 3, + GIT_CHECKOUT_NOTIFY_IGNORED = 1 << 4, GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFF, } @@ -508,43 +508,43 @@ git_enum! { pub enum git_status_t { GIT_STATUS_CURRENT = 0, - GIT_STATUS_INDEX_NEW = (1 << 0), - GIT_STATUS_INDEX_MODIFIED = (1 << 1), - GIT_STATUS_INDEX_DELETED = (1 << 2), - GIT_STATUS_INDEX_RENAMED = (1 << 3), - GIT_STATUS_INDEX_TYPECHANGE = (1 << 4), - - GIT_STATUS_WT_NEW = (1 << 7), - GIT_STATUS_WT_MODIFIED = (1 << 8), - GIT_STATUS_WT_DELETED = (1 << 9), - GIT_STATUS_WT_TYPECHANGE = (1 << 10), - GIT_STATUS_WT_RENAMED = (1 << 11), - GIT_STATUS_WT_UNREADABLE = (1 << 12), - - GIT_STATUS_IGNORED = (1 << 14), - GIT_STATUS_CONFLICTED = (1 << 15), + GIT_STATUS_INDEX_NEW = 1 << 0, + GIT_STATUS_INDEX_MODIFIED = 1 << 1, + GIT_STATUS_INDEX_DELETED = 1 << 2, + GIT_STATUS_INDEX_RENAMED = 1 << 3, + GIT_STATUS_INDEX_TYPECHANGE = 1 << 4, + + GIT_STATUS_WT_NEW = 1 << 7, + GIT_STATUS_WT_MODIFIED = 1 << 8, + GIT_STATUS_WT_DELETED = 1 << 9, + GIT_STATUS_WT_TYPECHANGE = 1 << 10, + GIT_STATUS_WT_RENAMED = 1 << 11, + GIT_STATUS_WT_UNREADABLE = 1 << 12, + + GIT_STATUS_IGNORED = 1 << 14, + GIT_STATUS_CONFLICTED = 1 << 15, } } git_enum! { pub enum git_status_opt_t { - GIT_STATUS_OPT_INCLUDE_UNTRACKED = (1 << 0), - GIT_STATUS_OPT_INCLUDE_IGNORED = (1 << 1), - GIT_STATUS_OPT_INCLUDE_UNMODIFIED = (1 << 2), - GIT_STATUS_OPT_EXCLUDE_SUBMODULES = (1 << 3), - GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS = (1 << 4), - GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH = (1 << 5), - GIT_STATUS_OPT_RECURSE_IGNORED_DIRS = (1 << 6), - GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX = (1 << 7), - GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR = (1 << 8), - GIT_STATUS_OPT_SORT_CASE_SENSITIVELY = (1 << 9), - GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = (1 << 10), - - GIT_STATUS_OPT_RENAMES_FROM_REWRITES = (1 << 11), - GIT_STATUS_OPT_NO_REFRESH = (1 << 12), - GIT_STATUS_OPT_UPDATE_INDEX = (1 << 13), - GIT_STATUS_OPT_INCLUDE_UNREADABLE = (1 << 14), - GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED = (1 << 15), + GIT_STATUS_OPT_INCLUDE_UNTRACKED = 1 << 0, + GIT_STATUS_OPT_INCLUDE_IGNORED = 1 << 1, + GIT_STATUS_OPT_INCLUDE_UNMODIFIED = 1 << 2, + GIT_STATUS_OPT_EXCLUDE_SUBMODULES = 1 << 3, + GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS = 1 << 4, + GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH = 1 << 5, + GIT_STATUS_OPT_RECURSE_IGNORED_DIRS = 1 << 6, + GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX = 1 << 7, + GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR = 1 << 8, + GIT_STATUS_OPT_SORT_CASE_SENSITIVELY = 1 << 9, + GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = 1 << 10, + + GIT_STATUS_OPT_RENAMES_FROM_REWRITES = 1 << 11, + GIT_STATUS_OPT_NO_REFRESH = 1 << 12, + GIT_STATUS_OPT_UPDATE_INDEX = 1 << 13, + GIT_STATUS_OPT_INCLUDE_UNREADABLE = 1 << 14, + GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED = 1 << 15, } } @@ -601,26 +601,26 @@ pub struct git_status_entry { git_enum! { pub enum git_checkout_strategy_t { GIT_CHECKOUT_NONE = 0, - GIT_CHECKOUT_SAFE = (1 << 0), - GIT_CHECKOUT_FORCE = (1 << 1), - GIT_CHECKOUT_RECREATE_MISSING = (1 << 2), - GIT_CHECKOUT_ALLOW_CONFLICTS = (1 << 4), - GIT_CHECKOUT_REMOVE_UNTRACKED = (1 << 5), - GIT_CHECKOUT_REMOVE_IGNORED = (1 << 6), - GIT_CHECKOUT_UPDATE_ONLY = (1 << 7), - GIT_CHECKOUT_DONT_UPDATE_INDEX = (1 << 8), - GIT_CHECKOUT_NO_REFRESH = (1 << 9), - GIT_CHECKOUT_SKIP_UNMERGED = (1 << 10), - GIT_CHECKOUT_USE_OURS = (1 << 11), - GIT_CHECKOUT_USE_THEIRS = (1 << 12), - GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH = (1 << 13), - GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES = (1 << 18), - GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = (1 << 19), - GIT_CHECKOUT_CONFLICT_STYLE_MERGE = (1 << 20), - GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = (1 << 21), - - GIT_CHECKOUT_UPDATE_SUBMODULES = (1 << 16), - GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = (1 << 17), + GIT_CHECKOUT_SAFE = 1 << 0, + GIT_CHECKOUT_FORCE = 1 << 1, + GIT_CHECKOUT_RECREATE_MISSING = 1 << 2, + GIT_CHECKOUT_ALLOW_CONFLICTS = 1 << 4, + GIT_CHECKOUT_REMOVE_UNTRACKED = 1 << 5, + GIT_CHECKOUT_REMOVE_IGNORED = 1 << 6, + GIT_CHECKOUT_UPDATE_ONLY = 1 << 7, + GIT_CHECKOUT_DONT_UPDATE_INDEX = 1 << 8, + GIT_CHECKOUT_NO_REFRESH = 1 << 9, + GIT_CHECKOUT_SKIP_UNMERGED = 1 << 10, + GIT_CHECKOUT_USE_OURS = 1 << 11, + GIT_CHECKOUT_USE_THEIRS = 1 << 12, + GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH = 1 << 13, + GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES = 1 << 18, + GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = 1 << 19, + GIT_CHECKOUT_CONFLICT_STYLE_MERGE = 1 << 20, + GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = 1 << 21, + + GIT_CHECKOUT_UPDATE_SUBMODULES = 1 << 16, + GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = 1 << 17, } } @@ -915,11 +915,11 @@ 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), - GIT_REPOSITORY_OPEN_NO_DOTGIT = (1 << 3), - GIT_REPOSITORY_OPEN_FROM_ENV = (1 << 4), + GIT_REPOSITORY_OPEN_NO_SEARCH = 1 << 0, + GIT_REPOSITORY_OPEN_CROSS_FS = 1 << 1, + GIT_REPOSITORY_OPEN_BARE = 1 << 2, + GIT_REPOSITORY_OPEN_NO_DOTGIT = 1 << 3, + GIT_REPOSITORY_OPEN_FROM_ENV = 1 << 4, } } @@ -939,12 +939,12 @@ pub const GIT_REPOSITORY_INIT_OPTIONS_VERSION: c_uint = 1; git_enum! { pub enum git_repository_init_flag_t { - GIT_REPOSITORY_INIT_BARE = (1 << 0), - GIT_REPOSITORY_INIT_NO_REINIT = (1 << 1), - GIT_REPOSITORY_INIT_NO_DOTGIT_DIR = (1 << 2), - GIT_REPOSITORY_INIT_MKDIR = (1 << 3), - GIT_REPOSITORY_INIT_MKPATH = (1 << 4), - GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE = (1 << 5), + GIT_REPOSITORY_INIT_BARE = 1 << 0, + GIT_REPOSITORY_INIT_NO_REINIT = 1 << 1, + GIT_REPOSITORY_INIT_NO_DOTGIT_DIR = 1 << 2, + GIT_REPOSITORY_INIT_MKDIR = 1 << 3, + GIT_REPOSITORY_INIT_MKPATH = 1 << 4, + GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE = 1 << 5, } } @@ -959,9 +959,9 @@ git_enum! { git_enum! { pub enum git_sort_t { GIT_SORT_NONE = 0, - GIT_SORT_TOPOLOGICAL = (1 << 0), - GIT_SORT_TIME = (1 << 1), - GIT_SORT_REVERSE = (1 << 2), + GIT_SORT_TOPOLOGICAL = 1 << 0, + GIT_SORT_TIME = 1 << 1, + GIT_SORT_REVERSE = 1 << 2, } } @@ -1231,32 +1231,32 @@ git_enum! { git_enum! { pub enum git_merge_file_flag_t { GIT_MERGE_FILE_DEFAULT = 0, - GIT_MERGE_FILE_STYLE_MERGE = (1 << 0), - GIT_MERGE_FILE_STYLE_DIFF3 = (1 << 1), - GIT_MERGE_FILE_SIMPLIFY_ALNUM = (1 << 2), - GIT_MERGE_FILE_IGNORE_WHITESPACE = (1 << 3), - GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE = (1 << 4), - GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL = (1 << 5), - GIT_MERGE_FILE_DIFF_PATIENCE = (1 << 6), - GIT_MERGE_FILE_DIFF_MINIMAL = (1 << 7), + GIT_MERGE_FILE_STYLE_MERGE = 1 << 0, + GIT_MERGE_FILE_STYLE_DIFF3 = 1 << 1, + GIT_MERGE_FILE_SIMPLIFY_ALNUM = 1 << 2, + GIT_MERGE_FILE_IGNORE_WHITESPACE = 1 << 3, + GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE = 1 << 4, + GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL = 1 << 5, + GIT_MERGE_FILE_DIFF_PATIENCE = 1 << 6, + GIT_MERGE_FILE_DIFF_MINIMAL = 1 << 7, } } git_enum! { pub enum git_merge_analysis_t { GIT_MERGE_ANALYSIS_NONE = 0, - GIT_MERGE_ANALYSIS_NORMAL = (1 << 0), - GIT_MERGE_ANALYSIS_UP_TO_DATE = (1 << 1), - GIT_MERGE_ANALYSIS_FASTFORWARD = (1 << 2), - GIT_MERGE_ANALYSIS_UNBORN = (1 << 3), + GIT_MERGE_ANALYSIS_NORMAL = 1 << 0, + GIT_MERGE_ANALYSIS_UP_TO_DATE = 1 << 1, + GIT_MERGE_ANALYSIS_FASTFORWARD = 1 << 2, + GIT_MERGE_ANALYSIS_UNBORN = 1 << 3, } } git_enum! { pub enum git_merge_preference_t { GIT_MERGE_PREFERENCE_NONE = 0, - GIT_MERGE_PREFERENCE_NO_FASTFORWARD = (1 << 0), - GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY = (1 << 1), + GIT_MERGE_PREFERENCE_NO_FASTFORWARD = 1 << 0, + GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY = 1 << 1, } } From d70b64599a080ea91f6052cb234a4a485f5dcdff Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 13 Mar 2020 09:13:44 -0700 Subject: [PATCH 439/860] Make all callbacks optional in libgit2-sys Appease the nightly compiler's checks for undefinededness and reflect how this is actually what the typedef is in C, a nullable function pointer. --- libgit2-sys/lib.rs | 335 ++++++++++++++++++++++------------------ src/blob.rs | 18 ++- src/build.rs | 6 +- src/cred.rs | 6 +- src/diff.rs | 23 ++- src/index.rs | 6 +- src/odb.rs | 5 +- src/packbuilder.rs | 5 +- src/patch.rs | 3 +- src/remote_callbacks.rs | 15 +- src/repo.rs | 6 +- src/transport.rs | 19 +-- src/tree.rs | 2 +- src/treebuilder.rs | 7 +- 14 files changed, 247 insertions(+), 209 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index f6e9c3201c..c6ac07fc8d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -265,9 +265,9 @@ pub struct git_clone_options { pub bare: c_int, pub local: git_clone_local_t, pub checkout_branch: *const c_char, - pub repository_cb: Option, + pub repository_cb: git_repository_create_cb, pub repository_cb_payload: *mut c_void, - pub remote_cb: Option, + pub remote_cb: git_remote_create_cb, pub remote_cb_payload: *mut c_void, } @@ -289,9 +289,9 @@ pub struct git_checkout_options { pub file_mode: c_uint, pub file_open_flags: c_int, pub notify_flags: c_uint, - pub notify_cb: Option, + pub notify_cb: git_checkout_notify_cb, pub notify_payload: *mut c_void, - pub progress_cb: Option, + pub progress_cb: git_checkout_progress_cb, pub progress_payload: *mut c_void, pub paths: git_strarray, pub baseline: *mut git_tree, @@ -300,21 +300,25 @@ pub struct git_checkout_options { pub ancestor_label: *const c_char, pub our_label: *const c_char, pub their_label: *const c_char, - pub perfdata_cb: Option, + pub perfdata_cb: git_checkout_perfdata_cb, pub perfdata_payload: *mut c_void, } -pub type git_checkout_notify_cb = extern "C" fn( - git_checkout_notify_t, - *const c_char, - *const git_diff_file, - *const git_diff_file, - *const git_diff_file, - *mut c_void, -) -> c_int; -pub type git_checkout_progress_cb = extern "C" fn(*const c_char, size_t, size_t, *mut c_void); +pub type git_checkout_notify_cb = Option< + extern "C" fn( + git_checkout_notify_t, + *const c_char, + *const git_diff_file, + *const git_diff_file, + *const git_diff_file, + *mut c_void, + ) -> c_int, +>; +pub type git_checkout_progress_cb = + Option; -pub type git_checkout_perfdata_cb = extern "C" fn(*const git_checkout_perfdata, *mut c_void); +pub type git_checkout_perfdata_cb = + Option; #[repr(C)] pub struct git_checkout_perfdata { @@ -335,7 +339,8 @@ pub struct git_indexer_progress { pub received_bytes: size_t, } -pub type git_indexer_progress_cb = extern "C" fn(*const git_indexer_progress, *mut c_void) -> c_int; +pub type git_indexer_progress_cb = + Option c_int>; #[deprecated( since = "0.10.0", @@ -346,20 +351,20 @@ pub type git_transfer_progress = git_indexer_progress; #[repr(C)] pub struct git_remote_callbacks { pub version: c_uint, - pub sideband_progress: Option, + pub sideband_progress: git_transport_message_cb, pub completion: Option c_int>, - pub credentials: Option, - pub certificate_check: Option, - pub transfer_progress: Option, + pub credentials: git_cred_acquire_cb, + pub certificate_check: git_transport_certificate_check_cb, + pub transfer_progress: git_indexer_progress_cb, pub update_tips: Option c_int>, - pub pack_progress: Option, - pub push_transfer_progress: Option, - pub push_update_reference: Option, - pub push_negotiation: Option, - pub transport: Option, + pub pack_progress: git_packbuilder_progress, + pub push_transfer_progress: git_push_transfer_progress, + pub push_update_reference: git_push_update_reference_cb, + pub push_negotiation: git_push_negotiation, + pub transport: git_transport_cb, pub payload: *mut c_void, - pub resolve_url: Option, + pub resolve_url: git_url_resolve_cb, } #[repr(C)] @@ -398,23 +403,26 @@ git_enum! { } } -pub type git_transport_message_cb = extern "C" fn(*const c_char, c_int, *mut c_void) -> c_int; -pub type git_cred_acquire_cb = - extern "C" fn(*mut *mut git_cred, *const c_char, *const c_char, c_uint, *mut c_void) -> c_int; +pub type git_transport_message_cb = + Option c_int>; +pub type git_cred_acquire_cb = Option< + extern "C" fn(*mut *mut git_cred, *const c_char, *const c_char, c_uint, *mut c_void) -> c_int, +>; pub type git_transfer_progress_cb = - extern "C" fn(*const git_indexer_progress, *mut c_void) -> c_int; + Option c_int>; pub type git_packbuilder_progress = - extern "C" fn(git_packbuilder_stage_t, c_uint, c_uint, *mut c_void) -> c_int; -pub type git_push_transfer_progress = extern "C" fn(c_uint, c_uint, size_t, *mut c_void) -> c_int; + Option c_int>; +pub type git_push_transfer_progress = + Option c_int>; pub type git_transport_certificate_check_cb = - extern "C" fn(*mut git_cert, c_int, *const c_char, *mut c_void) -> c_int; + Option c_int>; pub type git_push_negotiation = - extern "C" fn(*mut *const git_push_update, size_t, *mut c_void) -> c_int; + Option c_int>; pub type git_push_update_reference_cb = - extern "C" fn(*const c_char, *const c_char, *mut c_void) -> c_int; + Option c_int>; pub type git_url_resolve_cb = - extern "C" fn(*mut git_buf, *const c_char, c_int, *mut c_void) -> c_int; + Option c_int>; #[repr(C)] pub struct git_push_update { @@ -482,14 +490,16 @@ pub struct git_diff_file { } pub type git_repository_create_cb = - extern "C" fn(*mut *mut git_repository, *const c_char, c_int, *mut c_void) -> c_int; -pub type git_remote_create_cb = extern "C" fn( - *mut *mut git_remote, - *mut git_repository, - *const c_char, - *const c_char, - *mut c_void, -) -> c_int; + Option c_int>; +pub type git_remote_create_cb = Option< + extern "C" fn( + *mut *mut git_remote, + *mut git_repository, + *const c_char, + *const c_char, + *mut c_void, + ) -> c_int, +>; git_enum! { pub enum git_checkout_notify_t { @@ -673,10 +683,11 @@ git_enum! { } pub type git_treewalk_cb = - extern "C" fn(*const c_char, *const git_tree_entry, *mut c_void) -> c_int; -pub type git_treebuilder_filter_cb = extern "C" fn(*const git_tree_entry, *mut c_void) -> c_int; + Option c_int>; +pub type git_treebuilder_filter_cb = + Option c_int>; -pub type git_revwalk_hide_cb = extern "C" fn(*const git_oid, *mut c_void) -> c_int; +pub type git_revwalk_hide_cb = Option c_int>; #[repr(C)] #[derive(Copy, Clone)] @@ -729,7 +740,7 @@ pub struct git_blame_hunk { } pub type git_index_matched_path_cb = - extern "C" fn(*const c_char, *const c_char, *mut c_void) -> c_int; + Option c_int>; git_enum! { pub enum git_index_entry_extended_flag_t { @@ -781,7 +792,7 @@ pub struct git_config_entry { pub value: *const c_char, pub include_depth: c_uint, pub level: git_config_level_t, - pub free: extern "C" fn(*mut git_config_entry), + pub free: Option, pub payload: *mut c_void, } @@ -818,7 +829,8 @@ git_enum! { } } -pub type git_submodule_cb = extern "C" fn(*mut git_submodule, *const c_char, *mut c_void) -> c_int; +pub type git_submodule_cb = + Option c_int>; #[repr(C)] pub struct git_submodule_update_options { @@ -830,9 +842,9 @@ pub struct git_submodule_update_options { #[repr(C)] pub struct git_writestream { - pub write: extern "C" fn(*mut git_writestream, *const c_char, size_t) -> c_int, - pub close: extern "C" fn(*mut git_writestream) -> c_int, - pub free: extern "C" fn(*mut git_writestream), + pub write: Option c_int>, + pub close: Option c_int>, + pub free: Option, } git_enum! { @@ -853,7 +865,7 @@ pub const GIT_ATTR_CHECK_INCLUDE_HEAD: u32 = 1 << 3; #[repr(C)] pub struct git_cred { pub credtype: git_credtype_t, - pub free: extern "C" fn(*mut git_cred), + pub free: Option, } git_enum! { @@ -868,25 +880,29 @@ git_enum! { } } -pub type git_cred_ssh_interactive_callback = extern "C" fn( - name: *const c_char, - name_len: c_int, - instruction: *const c_char, - instruction_len: c_int, - num_prompts: c_int, - prompts: *const LIBSSH2_USERAUTH_KBDINT_PROMPT, - responses: *mut LIBSSH2_USERAUTH_KBDINT_RESPONSE, - abstrakt: *mut *mut c_void, -); - -pub type git_cred_sign_callback = extern "C" fn( - session: *mut LIBSSH2_SESSION, - sig: *mut *mut c_uchar, - sig_len: *mut size_t, - data: *const c_uchar, - data_len: size_t, - abstrakt: *mut *mut c_void, -); +pub type git_cred_ssh_interactive_callback = Option< + extern "C" fn( + name: *const c_char, + name_len: c_int, + instruction: *const c_char, + instruction_len: c_int, + num_prompts: c_int, + prompts: *const LIBSSH2_USERAUTH_KBDINT_PROMPT, + responses: *mut LIBSSH2_USERAUTH_KBDINT_RESPONSE, + abstrakt: *mut *mut c_void, + ), +>; + +pub type git_cred_sign_callback = Option< + extern "C" fn( + session: *mut LIBSSH2_SESSION, + sig: *mut *mut c_uchar, + sig_len: *mut size_t, + data: *const c_uchar, + data_len: size_t, + abstrakt: *mut *mut c_void, + ), +>; pub enum LIBSSH2_SESSION {} pub enum LIBSSH2_USERAUTH_KBDINT_PROMPT {} @@ -902,7 +918,7 @@ pub struct git_push_options { } pub type git_tag_foreach_cb = - extern "C" fn(name: *const c_char, oid: *mut git_oid, payload: *mut c_void) -> c_int; + Option c_int>; git_enum! { pub enum git_index_add_option_t { @@ -1005,17 +1021,19 @@ git_enum! { } } -pub type git_diff_file_cb = extern "C" fn(*const git_diff_delta, f32, *mut c_void) -> c_int; +pub type git_diff_file_cb = Option c_int>; pub type git_diff_hunk_cb = - extern "C" fn(*const git_diff_delta, *const git_diff_hunk, *mut c_void) -> c_int; -pub type git_diff_line_cb = extern "C" fn( - *const git_diff_delta, - *const git_diff_hunk, - *const git_diff_line, - *mut c_void, -) -> c_int; + Option c_int>; +pub type git_diff_line_cb = Option< + extern "C" fn( + *const git_diff_delta, + *const git_diff_hunk, + *const git_diff_line, + *mut c_void, + ) -> c_int, +>; pub type git_diff_binary_cb = - extern "C" fn(*const git_diff_delta, *const git_diff_binary, *mut c_void) -> c_int; + Option c_int>; #[repr(C)] pub struct git_diff_hunk { @@ -1058,8 +1076,8 @@ pub struct git_diff_options { pub flags: u32, pub ignore_submodules: git_submodule_ignore_t, pub pathspec: git_strarray, - pub notify_cb: Option, - pub progress_cb: Option, + pub notify_cb: git_diff_notify_cb, + pub progress_cb: git_diff_progress_cb, pub payload: *mut c_void, pub context_lines: u32, pub interhunk_lines: u32, @@ -1090,11 +1108,12 @@ git_enum! { } } -pub type git_diff_notify_cb = - extern "C" fn(*const git_diff, *const git_diff_delta, *const c_char, *mut c_void) -> c_int; +pub type git_diff_notify_cb = Option< + extern "C" fn(*const git_diff, *const git_diff_delta, *const c_char, *mut c_void) -> c_int, +>; pub type git_diff_progress_cb = - extern "C" fn(*const git_diff, *const c_char, *const c_char, *mut c_void) -> c_int; + Option c_int>; pub type git_diff_option_t = i32; pub const GIT_DIFF_NORMAL: git_diff_option_t = 0; @@ -1141,17 +1160,21 @@ pub struct git_diff_find_options { #[repr(C)] pub struct git_diff_similarity_metric { - pub file_signature: + pub file_signature: Option< extern "C" fn(*mut *mut c_void, *const git_diff_file, *const c_char, *mut c_void) -> c_int, - pub buffer_signature: extern "C" fn( - *mut *mut c_void, - *const git_diff_file, - *const c_char, - size_t, - *mut c_void, - ) -> c_int, - pub free_signature: extern "C" fn(*mut c_void, *mut c_void), - pub similarity: extern "C" fn(*mut c_int, *mut c_void, *mut c_void, *mut c_void) -> c_int, + >, + pub buffer_signature: Option< + extern "C" fn( + *mut *mut c_void, + *const git_diff_file, + *const c_char, + size_t, + *mut c_void, + ) -> c_int, + >, + pub free_signature: Option, + pub similarity: + Option c_int>, pub payload: *mut c_void, } @@ -1260,11 +1283,13 @@ git_enum! { } } -pub type git_transport_cb = extern "C" fn( - out: *mut *mut git_transport, - owner: *mut git_remote, - param: *mut c_void, -) -> c_int; +pub type git_transport_cb = Option< + extern "C" fn( + out: *mut *mut git_transport, + owner: *mut git_remote, + param: *mut c_void, + ) -> c_int, +>; #[repr(C)] pub struct git_transport { @@ -1501,8 +1526,8 @@ 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 credentials: git_cred_acquire_cb, + pub certificate_check: git_transport_certificate_check_cb, pub payload: *mut c_void, } @@ -1526,34 +1551,40 @@ git_enum! { #[repr(C)] pub struct git_smart_subtransport_stream { pub subtransport: *mut git_smart_subtransport, - pub read: extern "C" fn( - *mut git_smart_subtransport_stream, - *mut c_char, - size_t, - *mut size_t, - ) -> c_int, - pub write: extern "C" fn(*mut git_smart_subtransport_stream, *const c_char, size_t) -> c_int, - pub free: extern "C" fn(*mut git_smart_subtransport_stream), + pub read: Option< + extern "C" fn( + *mut git_smart_subtransport_stream, + *mut c_char, + size_t, + *mut size_t, + ) -> c_int, + >, + pub write: + Option c_int>, + pub free: Option, } #[repr(C)] pub struct git_smart_subtransport { - pub action: extern "C" fn( - *mut *mut git_smart_subtransport_stream, - *mut git_smart_subtransport, - *const c_char, - git_smart_service_t, - ) -> c_int, - pub close: extern "C" fn(*mut git_smart_subtransport) -> c_int, - pub free: extern "C" fn(*mut git_smart_subtransport), + pub action: Option< + extern "C" fn( + *mut *mut git_smart_subtransport_stream, + *mut git_smart_subtransport, + *const c_char, + git_smart_service_t, + ) -> c_int, + >, + pub close: Option c_int>, + pub free: Option, } -pub type git_smart_subtransport_cb = - extern "C" fn(*mut *mut git_smart_subtransport, *mut git_transport, *mut c_void) -> c_int; +pub type git_smart_subtransport_cb = Option< + extern "C" fn(*mut *mut git_smart_subtransport, *mut git_transport, *mut c_void) -> c_int, +>; #[repr(C)] pub struct git_smart_subtransport_definition { - pub callback: Option, + pub callback: git_smart_subtransport_cb, pub rpc: c_uint, pub param: *mut c_void, } @@ -1625,30 +1656,36 @@ pub struct git_stash_apply_options { pub version: c_uint, pub flags: u32, pub checkout_options: git_checkout_options, - pub progress_cb: Option, + pub progress_cb: git_stash_apply_progress_cb, pub progress_payload: *mut c_void, } pub type git_stash_apply_progress_cb = - extern "C" fn(progress: git_stash_apply_progress_t, payload: *mut c_void) -> c_int; + Option c_int>; -pub type git_stash_cb = extern "C" fn( - index: size_t, - message: *const c_char, - stash_id: *const git_oid, - payload: *mut c_void, -) -> c_int; +pub type git_stash_cb = Option< + extern "C" fn( + index: size_t, + message: *const c_char, + stash_id: *const git_oid, + payload: *mut c_void, + ) -> c_int, +>; -pub type git_packbuilder_foreach_cb = extern "C" fn(*const c_void, size_t, *mut c_void) -> c_int; +pub type git_packbuilder_foreach_cb = + Option c_int>; -pub type git_odb_foreach_cb = extern "C" fn(id: *const git_oid, payload: *mut c_void) -> c_int; +pub type git_odb_foreach_cb = + Option c_int>; -pub type git_commit_signing_cb = extern "C" fn( - signature: *mut git_buf, - signature_field: *mut git_buf, - commit_content: *const c_char, - payload: *mut c_void, -) -> c_int; +pub type git_commit_signing_cb = Option< + extern "C" fn( + signature: *mut git_buf, + signature_field: *mut git_buf, + commit_content: *const c_char, + payload: *mut c_void, + ) -> c_int, +>; pub const GIT_REBASE_NO_OPERATION: usize = usize::max_value(); @@ -1660,7 +1697,7 @@ pub struct git_rebase_options { pub rewrite_notes_ref: *const c_char, pub merge_options: git_merge_options, pub checkout_options: git_checkout_options, - pub signing_cb: Option, + pub signing_cb: git_commit_signing_cb, pub payload: *mut c_void, } @@ -2509,7 +2546,7 @@ extern "C" { index: *mut git_index, pathspec: *const git_strarray, flags: c_uint, - callback: Option, + callback: git_index_matched_path_cb, payload: *mut c_void, ) -> c_int; pub fn git_index_add_bypath(index: *mut git_index, path: *const c_char) -> c_int; @@ -2566,7 +2603,7 @@ extern "C" { pub fn git_index_remove_all( index: *mut git_index, pathspec: *const git_strarray, - callback: Option, + callback: git_index_matched_path_cb, payload: *mut c_void, ) -> c_int; pub fn git_index_remove_bypath(index: *mut git_index, path: *const c_char) -> c_int; @@ -2578,7 +2615,7 @@ extern "C" { pub fn git_index_update_all( index: *mut git_index, pathspec: *const git_strarray, - callback: Option, + callback: git_index_matched_path_cb, payload: *mut c_void, ) -> c_int; pub fn git_index_write(index: *mut git_index) -> c_int; @@ -3081,9 +3118,9 @@ extern "C" { pub fn git_diff_foreach( diff: *mut git_diff, file_cb: git_diff_file_cb, - binary_cb: Option, - hunk_cb: Option, - line_cb: Option, + binary_cb: git_diff_binary_cb, + hunk_cb: git_diff_hunk_cb, + line_cb: git_diff_line_cb, payload: *mut c_void, ) -> c_int; pub fn git_diff_free(diff: *mut git_diff); @@ -3325,7 +3362,7 @@ extern "C" { pb: *mut git_packbuilder, path: *const c_char, mode: c_uint, - progress_cb: Option, + progress_cb: git_indexer_progress_cb, progress_cb_payload: *mut c_void, ) -> c_int; pub fn git_packbuilder_hash(pb: *mut git_packbuilder) -> *const git_oid; @@ -3338,7 +3375,7 @@ extern "C" { 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: git_packbuilder_progress, progress_cb_payload: *mut c_void, ) -> c_int; pub fn git_packbuilder_free(pb: *mut git_packbuilder); diff --git a/src/blob.rs b/src/blob.rs index 93159f68e3..ae7505a69e 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -124,7 +124,11 @@ impl<'repo> Drop for BlobWriter<'repo> { fn drop(&mut self) { // We need cleanup in case the stream has not been committed if self.need_cleanup { - unsafe { ((*self.raw).free)(self.raw) } + unsafe { + if let Some(f) = (*self.raw).free { + f(self.raw) + } + } } } } @@ -132,11 +136,15 @@ impl<'repo> Drop for BlobWriter<'repo> { impl<'repo> io::Write for BlobWriter<'repo> { fn write(&mut self, buf: &[u8]) -> io::Result { unsafe { - let res = ((*self.raw).write)(self.raw, buf.as_ptr() as *const _, buf.len()); - if res < 0 { - Err(io::Error::new(io::ErrorKind::Other, "Write error")) + if let Some(f) = (*self.raw).write { + let res = f(self.raw, buf.as_ptr() as *const _, buf.len()); + if res < 0 { + Err(io::Error::new(io::ErrorKind::Other, "Write error")) + } else { + Ok(buf.len()) + } } else { - Ok(buf.len()) + Err(io::Error::new(io::ErrorKind::Other, "no write callback")) } } } diff --git a/src/build.rs b/src/build.rs index 62f42f752e..e1b75bd43b 100644 --- a/src/build.rs +++ b/src/build.rs @@ -589,13 +589,11 @@ impl<'cb> CheckoutBuilder<'cb> { opts.their_label = c.as_ptr(); } if self.progress.is_some() { - let f: raw::git_checkout_progress_cb = progress_cb; - opts.progress_cb = Some(f); + opts.progress_cb = Some(progress_cb); opts.progress_payload = self as *mut _ as *mut _; } if self.notify.is_some() { - let f: raw::git_checkout_notify_cb = notify_cb; - opts.notify_cb = Some(f); + opts.notify_cb = Some(notify_cb); opts.notify_payload = self as *mut _ as *mut _; opts.notify_flags = self.notify_flags.bits() as c_uint; } diff --git a/src/cred.rs b/src/cred.rs index 3bc443746b..c3a49939a6 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -179,7 +179,11 @@ impl Binding for Cred { impl Drop for Cred { fn drop(&mut self) { if !self.raw.is_null() { - unsafe { ((*self.raw).free)(self.raw) } + unsafe { + if let Some(f) = (*self.raw).free { + f(self.raw) + } + } } } } diff --git a/src/diff.rs b/src/diff.rs index 4e959ac27c..4cedb77d2d 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -164,13 +164,9 @@ impl<'repo> Diff<'repo> { { let mut cb: &mut PrintCb<'_> = &mut cb; let ptr = &mut cb as *mut _; + let print: raw::git_diff_line_cb = Some(print_cb); unsafe { - try_call!(raw::git_diff_print( - self.raw, - format, - print_cb, - ptr as *mut _ - )); + try_call!(raw::git_diff_print(self.raw, format, print, ptr as *mut _)); Ok(()) } } @@ -194,24 +190,25 @@ impl<'repo> Diff<'repo> { }; let ptr = &mut cbs as *mut _; unsafe { - let binary_cb_c = if cbs.binary.is_some() { - Some(binary_cb_c as raw::git_diff_binary_cb) + let binary_cb_c: raw::git_diff_binary_cb = if cbs.binary.is_some() { + Some(binary_cb_c) } else { None }; - let hunk_cb_c = if cbs.hunk.is_some() { - Some(hunk_cb_c as raw::git_diff_hunk_cb) + let hunk_cb_c: raw::git_diff_hunk_cb = if cbs.hunk.is_some() { + Some(hunk_cb_c) } else { None }; - let line_cb_c = if cbs.line.is_some() { - Some(line_cb_c as raw::git_diff_line_cb) + let line_cb_c: raw::git_diff_line_cb = if cbs.line.is_some() { + Some(line_cb_c) } else { None }; + let file_cb: raw::git_diff_file_cb = Some(file_cb_c); try_call!(raw::git_diff_foreach( self.raw, - file_cb_c, + file_cb, binary_cb_c, hunk_cb_c, line_cb_c, diff --git a/src/index.rs b/src/index.rs index 4d537b64a6..797e6d8815 100644 --- a/src/index.rs +++ b/src/index.rs @@ -295,7 +295,7 @@ impl Index { let ptr = cb.as_mut(); let callback = ptr .as_ref() - .map(|_| index_matched_path_cb as raw::git_index_matched_path_cb); + .map(|_| index_matched_path_cb as extern "C" fn(_, _, _) -> _); unsafe { try_call!(raw::git_index_add_all( self.raw, @@ -473,7 +473,7 @@ impl Index { let ptr = cb.as_mut(); let callback = ptr .as_ref() - .map(|_| index_matched_path_cb as raw::git_index_matched_path_cb); + .map(|_| index_matched_path_cb as extern "C" fn(_, _, _) -> _); unsafe { try_call!(raw::git_index_remove_all( self.raw, @@ -511,7 +511,7 @@ impl Index { let ptr = cb.as_mut(); let callback = ptr .as_ref() - .map(|_| index_matched_path_cb as raw::git_index_matched_path_cb); + .map(|_| index_matched_path_cb as extern "C" fn(_, _, _) -> _); unsafe { try_call!(raw::git_index_update_all( self.raw, diff --git a/src/odb.rs b/src/odb.rs index a6b1bc5397..9ee034ac21 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -98,9 +98,10 @@ impl<'repo> Odb<'repo> { let mut data = ForeachCbData { callback: &mut callback, }; + let cb: raw::git_odb_foreach_cb = Some(foreach_cb); try_call!(raw::git_odb_foreach( self.raw(), - foreach_cb, + cb, &mut data as *mut _ as *mut _ )); Ok(()) @@ -155,7 +156,7 @@ impl<'repo> Odb<'repo> { pub fn packwriter(&self) -> Result, Error> { let mut out = ptr::null_mut(); let progress = MaybeUninit::uninit(); - let progress_cb = write_pack_progress_cb; + let progress_cb: raw::git_indexer_progress_cb = Some(write_pack_progress_cb); let progress_payload = Box::new(OdbPackwriterCb { cb: None }); let progress_payload_ptr = Box::into_raw(progress_payload); diff --git a/src/packbuilder.rs b/src/packbuilder.rs index 6769d35114..06bf41dc7a 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -89,10 +89,11 @@ impl<'repo> PackBuilder<'repo> { { let mut cb = &mut cb as &mut ForEachCb<'_>; let ptr = &mut cb as *mut _; + let foreach: raw::git_packbuilder_foreach_cb = Some(foreach_c); unsafe { try_call!(raw::git_packbuilder_foreach( self.raw, - foreach_c, + foreach, ptr as *mut _ )); } @@ -112,7 +113,7 @@ impl<'repo> PackBuilder<'repo> { { let mut progress = Box::new(Box::new(progress) as Box>); let ptr = &mut *progress as *mut _; - let progress_c = Some(progress_c as raw::git_packbuilder_progress); + let progress_c: raw::git_packbuilder_progress = Some(progress_c); unsafe { try_call!(raw::git_packbuilder_set_callbacks( self.raw, diff --git a/src/patch.rs b/src/patch.rs index 370782b281..2ff112b2c3 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -206,7 +206,8 @@ impl<'buffers> Patch<'buffers> { pub fn print(&mut self, mut line_cb: &mut LineCb<'_>) -> Result<(), Error> { let ptr = &mut line_cb as *mut _ as *mut c_void; unsafe { - try_call!(raw::git_patch_print(self.raw, print_cb, ptr)); + let cb: raw::git_diff_line_cb = Some(print_cb); + try_call!(raw::git_patch_print(self.raw, cb, ptr)); Ok(()) } } diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 619cef610c..ae741be399 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -174,24 +174,19 @@ impl<'a> Binding for RemoteCallbacks<'a> { 0 ); if self.progress.is_some() { - let f: raw::git_indexer_progress_cb = transfer_progress_cb; - callbacks.transfer_progress = Some(f); + callbacks.transfer_progress = Some(transfer_progress_cb); } if self.credentials.is_some() { - let f: raw::git_cred_acquire_cb = credentials_cb; - callbacks.credentials = Some(f); + callbacks.credentials = Some(credentials_cb); } if self.sideband_progress.is_some() { - let f: raw::git_transport_message_cb = sideband_progress_cb; - callbacks.sideband_progress = Some(f); + callbacks.sideband_progress = Some(sideband_progress_cb); } if self.certificate_check.is_some() { - let f: raw::git_transport_certificate_check_cb = certificate_check_cb; - callbacks.certificate_check = Some(f); + callbacks.certificate_check = Some(certificate_check_cb); } if self.push_update_reference.is_some() { - let f: extern "C" fn(_, _, _) -> c_int = push_update_reference_cb; - callbacks.push_update_reference = Some(f); + callbacks.push_update_reference = Some(push_update_reference_cb); } if self.update_tips.is_some() { let f: extern "C" fn( diff --git a/src/repo.rs b/src/repo.rs index 89a40b53a1..7f3bb4c98e 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -778,9 +778,10 @@ impl Repository { repo: self, ret: &mut ret, }; + let cb: raw::git_submodule_cb = Some(append); try_call!(raw::git_submodule_foreach( self.raw, - append, + cb, &mut data as *mut _ as *mut c_void )); } @@ -2426,9 +2427,10 @@ impl Repository { let mut data = StashCbData { callback: &mut callback, }; + let cb: raw::git_stash_cb = Some(stash_cb); try_call!(raw::git_stash_foreach( self.raw(), - stash_cb, + cb, &mut data as *mut _ as *mut _ )); Ok(()) diff --git a/src/transport.rs b/src/transport.rs index e7b398ce6b..c82eb1b27c 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -113,11 +113,8 @@ where }); let prefix = CString::new(prefix)?; let datap = (&mut *data) as *mut TransportData as *mut c_void; - try_call!(raw::git_transport_register( - prefix, - transport_factory, - datap - )); + let factory: raw::git_transport_cb = Some(transport_factory); + try_call!(raw::git_transport_register(prefix, factory, datap)); mem::forget(data); Ok(()) } @@ -141,9 +138,9 @@ impl Transport { let mut raw = Box::new(RawSmartSubtransport { raw: raw::git_smart_subtransport { - action: subtransport_action, - close: subtransport_close, - free: subtransport_free, + action: Some(subtransport_action), + close: Some(subtransport_close), + free: Some(subtransport_free), }, obj: Box::new(subtransport), }); @@ -257,9 +254,9 @@ extern "C" fn subtransport_action( *stream = mem::transmute(Box::new(RawSmartSubtransportStream { raw: raw::git_smart_subtransport_stream { subtransport: raw_transport, - read: stream_read, - write: stream_write, - free: stream_free, + read: Some(stream_read), + write: Some(stream_write), + free: Some(stream_free), }, obj: obj, })); diff --git a/src/tree.rs b/src/tree.rs index 9fd4e0cee1..436a8f50a2 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -132,7 +132,7 @@ impl<'repo> Tree<'repo> { raw::git_tree_walk( self.raw(), mode.into(), - treewalk_cb::, + Some(treewalk_cb::), &mut data as *mut _ as *mut c_void, ); Ok(()) diff --git a/src/treebuilder.rs b/src/treebuilder.rs index e14d96319b..5d40ea9b39 100644 --- a/src/treebuilder.rs +++ b/src/treebuilder.rs @@ -95,12 +95,9 @@ impl<'repo> TreeBuilder<'repo> { { let mut cb: &mut FilterCb<'_> = &mut filter; let ptr = &mut cb as *mut _; + let cb: raw::git_treebuilder_filter_cb = Some(filter_cb); unsafe { - try_call!(raw::git_treebuilder_filter( - self.raw, - filter_cb, - ptr as *mut _ - )); + try_call!(raw::git_treebuilder_filter(self.raw, cb, ptr as *mut _)); panic::check(); } Ok(()) From 760330973895a2072afa6b0ffaadd137c9150c6b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 13 Mar 2020 12:05:04 -0700 Subject: [PATCH 440/860] Update libgit2 (#527) --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 172239021f..be36db28f6 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 172239021f7ba04fe7327647b213799853a9eb89 +Subproject commit be36db28f64de8ed5ca9870708a56b6668c6c482 From 30f013875ec69e6c794392a41e3d8f364ea8ec5b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 13 Mar 2020 12:24:54 -0700 Subject: [PATCH 441/860] Bump versions --- Cargo.toml | 4 ++-- git2-curl/Cargo.toml | 5 ++--- libgit2-sys/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ed7696b04c..a90ef255c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.12.0" +version = "0.13.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.11.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 49cb0910d9..d34e76aa40 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,7 +1,6 @@ [package] - name = "git2-curl" -version = "0.13.0" +version = "0.14.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" @@ -17,7 +16,7 @@ edition = "2018" curl = "0.4" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.12", default-features = false } +git2 = { path = "..", version = "0.13", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 2ab481a781..0d262d3c7f 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.11.0+0.99.0" +version = "0.12.0+0.99.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 345b708eb0f942bf4bf54373f40a89a62358da73 Mon Sep 17 00:00:00 2001 From: Thanh Le Date: Tue, 17 Mar 2020 15:02:25 +0100 Subject: [PATCH 442/860] Correct library version on Readme (#530) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a79d7fd9ea..4d427cdbf8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust ```toml [dependencies] -git2 = "0.10" +git2 = "0.13" ``` ## Rust version requirements From e4ebe77881e4e4deb247fdfb78ecd3ac2f5af56b Mon Sep 17 00:00:00 2001 From: ratmice Date: Tue, 17 Mar 2020 14:07:44 +0000 Subject: [PATCH 443/860] Migrate examples from docopt to structopt. (#528) --- Cargo.toml | 4 +- examples/add.rs | 26 ++++------ examples/blame.rs | 28 +++++------ examples/cat-file.rs | 37 +++++++------- examples/clone.rs | 18 ++----- examples/diff.rs | 114 +++++++++++++++++++++++++----------------- examples/fetch.rs | 17 ++----- examples/init.rs | 34 ++++++------- examples/log.rs | 70 ++++++++++++++------------ examples/ls-remote.rs | 17 ++----- examples/rev-list.rs | 31 +++++------- examples/rev-parse.rs | 19 +++---- examples/status.rs | 50 +++++++++--------- examples/tag.rs | 34 +++++-------- 14 files changed, 236 insertions(+), 263 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a90ef255c5..b980d5ccba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,9 +27,7 @@ openssl-sys = { version = "0.9.0", optional = true } openssl-probe = { version = "0.1", optional = true } [dev-dependencies] -docopt = "1.0" -serde = "1.0" -serde_derive = "1.0" +structopt = "0.3" time = "0.1.39" tempfile = "3.1.0" thread-id = "3.3.0" # remove when we work with minimal-versions without it diff --git a/examples/add.rs b/examples/add.rs index 35ca7e4b55..25e972c7aa 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -15,16 +15,22 @@ #![deny(warnings)] #![allow(trivial_casts)] -use docopt::Docopt; use git2::Repository; -use serde_derive::Deserialize; use std::path::Path; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { + #[structopt(name = "spec")] arg_spec: Vec, + #[structopt(name = "dry_run", short = "n", long)] + /// dry run flag_dry_run: bool, + #[structopt(name = "verbose", short, long)] + /// be verbose flag_verbose: bool, + #[structopt(name = "update", short, long)] + /// update tracked files flag_update: bool, } @@ -67,19 +73,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &str = " -usage: add [options] [--] [..] - -Options: - -n, --dry-run dry run - -v, --verbose be verbose - -u, --update update tracked files - -h, --help show this message -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/blame.rs b/examples/blame.rs index 2464155e0f..7cb1b69470 100644 --- a/examples/blame.rs +++ b/examples/blame.rs @@ -12,19 +12,28 @@ * . */ -use docopt::Docopt; +#![deny(warnings)] + use git2::{BlameOptions, Repository}; -use serde_derive::Deserialize; use std::io::{BufRead, BufReader}; use std::path::Path; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] #[allow(non_snake_case)] struct Args { + #[structopt(name = "path")] arg_path: String, + #[structopt(name = "spec")] arg_spec: Option, + #[structopt(short = "M")] + /// find line moves within and across files flag_M: bool, + #[structopt(short = "C")] + /// find line copies within and across files flag_C: bool, + #[structopt(short = "F")] + /// follow only the first parent commits flag_F: bool, } @@ -87,18 +96,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &str = " -usage: blame [options] [] - -Options: - -M find line moves within and across files - -C find line copies within and across files - -F follow only the first parent commits -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/cat-file.rs b/examples/cat-file.rs index 2faf88b688..0ce21b34aa 100644 --- a/examples/cat-file.rs +++ b/examples/cat-file.rs @@ -16,19 +16,32 @@ use std::io::{self, Write}; -use docopt::Docopt; use git2::{Blob, Commit, ObjectType, Repository, Signature, Tag, Tree}; -use serde_derive::Deserialize; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { + #[structopt(name = "object")] arg_object: String, + #[structopt(short = "t")] + /// show the object type flag_t: bool, + #[structopt(short = "s")] + /// show the object size flag_s: bool, + #[structopt(short = "e")] + /// suppress all output flag_e: bool, + #[structopt(short = "p")] + /// pretty print the contents of the object flag_p: bool, + #[structopt(name = "quiet", short, long)] + /// suppress output flag_q: bool, + #[structopt(name = "verbose", short, long)] flag_v: bool, + #[structopt(name = "dir", long = "git-dir")] + /// use the specified directory as the base directory flag_git_dir: Option, } @@ -128,23 +141,7 @@ fn show_sig(header: &str, sig: Option) { } fn main() { - const USAGE: &str = " -usage: cat-file (-t | -s | -e | -p) [options] - -Options: - -t show the object type - -s show the object size - -e suppress all output - -p pretty print the contents of the object - -q suppress output - -v use verbose output - --git-dir use the specified directory as the base directory - -h, --help show this message -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/clone.rs b/examples/clone.rs index bf00524154..5af73222f0 100644 --- a/examples/clone.rs +++ b/examples/clone.rs @@ -14,17 +14,18 @@ #![deny(warnings)] -use docopt::Docopt; use git2::build::{CheckoutBuilder, RepoBuilder}; use git2::{FetchOptions, Progress, RemoteCallbacks}; -use serde_derive::Deserialize; use std::cell::RefCell; use std::io::{self, Write}; use std::path::{Path, PathBuf}; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { + #[structopt(name = "url")] arg_url: String, + #[structopt(name = "path")] arg_path: String, } @@ -117,16 +118,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &str = " -usage: add [options] - -Options: - -h, --help show this message -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/diff.rs b/examples/diff.rs index 1e6c76a802..8a02c261a3 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -14,48 +14,113 @@ #![deny(warnings)] -use docopt::Docopt; use git2::{Diff, DiffOptions, Error, Object, ObjectType, Repository}; use git2::{DiffFindOptions, DiffFormat}; -use serde_derive::Deserialize; use std::str; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] #[allow(non_snake_case)] struct Args { + #[structopt(name = "from_oid")] arg_from_oid: Option, + #[structopt(name = "to_oid")] arg_to_oid: Option, + #[structopt(name = "patch", short, long)] + /// show output in patch format flag_patch: bool, + #[structopt(name = "cached", long)] + /// use staged changes as diff flag_cached: bool, + #[structopt(name = "nocached", long)] + /// do not use staged changes flag_nocached: bool, + #[structopt(name = "name-only", long)] + /// show only names of changed files flag_name_only: bool, + #[structopt(name = "name-status", long)] + /// show only names and status changes flag_name_status: bool, + #[structopt(name = "raw", long)] + /// generate the raw format flag_raw: bool, + #[structopt(name = "format", long)] + /// specify format for stat summary flag_format: Option, + #[structopt(name = "color", long)] + /// use color output flag_color: bool, + #[structopt(name = "no-color", long)] + /// never use color output flag_no_color: bool, + #[structopt(short = "R")] + /// swap two inputs flag_R: bool, + #[structopt(name = "text", short = "a", long)] + /// treat all files as text flag_text: bool, + #[structopt(name = "ignore-space-at-eol", long)] + /// ignore changes in whitespace at EOL flag_ignore_space_at_eol: bool, + #[structopt(name = "ignore-space-change", short = "b", long)] + /// ignore changes in amount of whitespace flag_ignore_space_change: bool, + #[structopt(name = "ignore-all-space", short = "w", long)] + /// ignore whitespace when comparing lines flag_ignore_all_space: bool, + #[structopt(name = "ignored", long)] + /// show untracked files flag_ignored: bool, + #[structopt(name = "untracked", long)] + /// generate diff using the patience algorithm flag_untracked: bool, + #[structopt(name = "patience", long)] + /// show ignored files as well flag_patience: bool, + #[structopt(name = "minimal", long)] + /// spend extra time to find smallest diff flag_minimal: bool, + #[structopt(name = "stat", long)] + /// generate a diffstat flag_stat: bool, + #[structopt(name = "numstat", long)] + /// similar to --stat, but more machine friendly flag_numstat: bool, + #[structopt(name = "shortstat", long)] + /// only output last line of --stat flag_shortstat: bool, + #[structopt(name = "summary", long)] + /// output condensed summary of header info flag_summary: bool, + #[structopt(name = "find-renames", short = "M", long)] + /// set threshold for findind renames (default 50) flag_find_renames: Option, + #[structopt(name = "find-copies", short = "C", long)] + /// set threshold for finding copies (default 50) flag_find_copies: Option, + #[structopt(name = "find-copies-harder", long)] + /// inspect unmodified files for sources of copies flag_find_copies_harder: bool, + #[structopt(name = "break_rewrites", short = "B", long)] + /// break complete rewrite changes into pairs flag_break_rewrites: bool, + #[structopt(name = "unified", short = "U", long)] + /// lints of context to show flag_unified: Option, + #[structopt(name = "inter-hunk-context", long)] + /// maximum lines of change between hunks flag_inter_hunk_context: Option, + #[structopt(name = "abbrev", long)] + /// length to abbreviate commits to flag_abbrev: Option, + #[structopt(name = "src-prefix", long)] + /// show given source prefix instead of 'a/' flag_src_prefix: Option, + #[structopt(name = "dst-prefix", long)] + /// show given destinction prefix instead of 'b/' flag_dst_prefix: Option, + #[structopt(name = "path", long = "git-dir")] + /// path to git repository to use flag_git_dir: Option, } @@ -262,48 +327,7 @@ impl Args { } fn main() { - const USAGE: &str = " -usage: diff [options] [ []] - -Options: - -p, --patch show output in patch format - --cached use staged changes as diff - --nocached do not use staged changes - --name-only show only names of changed files - --name-status show only names and status changes - --raw generate the raw format - --format= specify format for stat summary - --color use color output - --no-color never use color output - -R swap two inputs - -a, --text treat all files as text - --ignore-space-at-eol ignore changes in whitespace at EOL - -b, --ignore-space-change ignore changes in amount of whitespace - -w, --ignore-all-space ignore whitespace when comparing lines - --ignored show ignored files as well - --untracked show untracked files - --patience generate diff using the patience algorithm - --minimal spend extra time to find smallest diff - --stat generate a diffstat - --numstat similar to --stat, but more machine friendly - --shortstat only output last line of --stat - --summary output condensed summary of header info - -M, --find-renames set threshold for findind renames (default 50) - -C, --find-copies set threshold for finding copies (default 50) - --find-copies-harder inspect unmodified files for sources of copies - -B, --break-rewrites break complete rewrite changes into pairs - -U, --unified lints of context to show - --inter-hunk-context maximum lines of change between hunks - --abbrev length to abbreviate commits to - --src-prefix show given source prefix instead of 'a/' - --dst-prefix show given destinction prefix instead of 'b/' - --git-dir path to git repository to use - -h, --help show this message -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/fetch.rs b/examples/fetch.rs index 212f934da4..64374a6d48 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -14,14 +14,14 @@ #![deny(warnings)] -use docopt::Docopt; use git2::{AutotagOption, FetchOptions, RemoteCallbacks, Repository}; -use serde_derive::Deserialize; use std::io::{self, Write}; use std::str; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { + #[structopt(name = "remote")] arg_remote: Option, } @@ -119,16 +119,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &str = " -usage: fetch [options] [] - -Options: - -h, --help show this message -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/init.rs b/examples/init.rs index c43f59edd8..3e447cbdee 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -14,19 +14,31 @@ #![deny(warnings)] -use docopt::Docopt; use git2::{Error, Repository, RepositoryInitMode, RepositoryInitOptions}; -use serde_derive::Deserialize; use std::path::{Path, PathBuf}; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { + #[structopt(name = "directory")] arg_directory: String, + #[structopt(name = "quiet", short, long)] + /// don't print information to stdout flag_quiet: bool, + #[structopt(name = "bare", long)] + /// initialize a new bare repository flag_bare: bool, + #[structopt(name = "dir", long = "template")] + /// use as an initialization template flag_template: Option, + #[structopt(name = "separate-git-dir", long)] + /// use as the .git directory flag_separate_git_dir: Option, + #[structopt(name = "initial-commit", long)] + /// create an initial empty commit flag_initial_commit: bool, + #[structopt(name = "perms", long = "shared")] + /// permissions to create the repository with flag_shared: Option, } @@ -125,21 +137,7 @@ fn parse_shared(shared: &str) -> Result { } fn main() { - const USAGE: &str = " -usage: init [options] - -Options: - -q, --quiet don't print information to stdout - --bare initialize a new bare repository - --template use as an initialization template - --separate-git-dir use as the .git directory - --initial-commit create an initial empty commit - --shared permissions to create the repository with -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/log.rs b/examples/log.rs index d7f7711186..ad3bb354d0 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -14,32 +14,65 @@ #![deny(warnings)] -use docopt::Docopt; use git2::{Commit, DiffOptions, ObjectType, Repository, Signature, Time}; use git2::{DiffFormat, Error, Pathspec}; -use serde_derive::Deserialize; use std::str; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { - arg_commit: Vec, - arg_spec: Vec, + #[structopt(name = "topo-order", long)] + /// sort commits in topological order flag_topo_order: bool, + #[structopt(name = "date-order", long)] + /// sort commits in date order flag_date_order: bool, + #[structopt(name = "reverse", long)] + /// sort commits in reverse flag_reverse: bool, + #[structopt(name = "author", long)] + /// author to sort by flag_author: Option, + #[structopt(name = "committer", long)] + /// committer to sort by flag_committer: Option, + #[structopt(name = "pat", long = "grep")] + /// pattern to filter commit messages by flag_grep: Option, + #[structopt(name = "dir", long = "git-dir")] + /// alternative git directory to use flag_git_dir: Option, + #[structopt(name = "skip", long)] + /// number of commits to skip flag_skip: Option, + #[structopt(name = "max-count", short = "n", long)] + /// maximum number of commits to show flag_max_count: Option, + #[structopt(name = "merges", long)] + /// only show merge commits flag_merges: bool, + #[structopt(name = "no-merges", long)] + /// don't show merge commits flag_no_merges: bool, + #[structopt(name = "no-min-parents", long)] + /// don't require a minimum number of parents flag_no_min_parents: bool, + #[structopt(name = "no-max-parents", long)] + /// don't require a maximum number of parents flag_no_max_parents: bool, + #[structopt(name = "max-parents")] + /// specify a maximum number of parents for a commit flag_max_parents: Option, + #[structopt(name = "min-parents")] + /// specify a minimum number of parents for a commit flag_min_parents: Option, + #[structopt(name = "patch", long, short)] + /// show commit diff flag_patch: bool, + #[structopt(name = "commit")] + arg_commit: Vec, + #[structopt(name = "spec", last = true)] + arg_spec: Vec, } fn run(args: &Args) -> Result<(), Error> { @@ -269,32 +302,7 @@ impl Args { } fn main() { - const USAGE: &str = " -usage: log [options] [..] [--] [..] - -Options: - --topo-order sort commits in topological order - --date-order sort commits in date order - --reverse sort commits in reverse - --author author to sort by - --committer committer to sort by - --grep pattern to filter commit messages by - --git-dir alternative git directory to use - --skip number of commits to skip - -n, --max-count maximum number of commits to show - --merges only show merge commits - --no-merges don't show merge commits - --no-min-parents don't require a minimum number of parents - --no-max-parents don't require a maximum number of parents - --max-parents specify a maximum number of parents for a commit - --min-parents specify a minimum number of parents for a commit - -p, --patch show commit diff - -h, --help show this message -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/ls-remote.rs b/examples/ls-remote.rs index 38ecd71eeb..1808459416 100644 --- a/examples/ls-remote.rs +++ b/examples/ls-remote.rs @@ -14,12 +14,12 @@ #![deny(warnings)] -use docopt::Docopt; use git2::{Direction, Repository}; -use serde_derive::Deserialize; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { + #[structopt(name = "remote")] arg_remote: String, } @@ -43,16 +43,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &str = " -usage: ls-remote [option] - -Options: - -h, --help show this message -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/rev-list.rs b/examples/rev-list.rs index de72102671..9b49877283 100644 --- a/examples/rev-list.rs +++ b/examples/rev-list.rs @@ -15,17 +15,25 @@ #![deny(warnings)] -use docopt::Docopt; use git2::{Error, Oid, Repository, Revwalk}; -use serde_derive::Deserialize; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { - arg_spec: Vec, + #[structopt(name = "topo-order", long)] + /// sort commits in topological order flag_topo_order: bool, + #[structopt(name = "date-order", long)] + /// sort commits in date order flag_date_order: bool, + #[structopt(name = "reverse", long)] + /// sort commits in reverse flag_reverse: bool, + #[structopt(name = "not")] + /// don't show flag_not: Vec, + #[structopt(name = "spec", last = true)] + arg_spec: Vec, } fn run(args: &Args) -> Result<(), git2::Error> { @@ -89,20 +97,7 @@ fn push(revwalk: &mut Revwalk, id: Oid, hide: bool) -> Result<(), Error> { } fn main() { - const USAGE: &str = " -usage: rev-list [options] [--] ... - -Options: - --topo-order sort commits in topological order - --date-order sort commits in date order - --reverse sort commits in reverse - --not don't show - -h, --help show this message -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/rev-parse.rs b/examples/rev-parse.rs index 4c8ccc813a..a465f15a4d 100644 --- a/examples/rev-parse.rs +++ b/examples/rev-parse.rs @@ -14,13 +14,15 @@ #![deny(warnings)] -use docopt::Docopt; use git2::Repository; -use serde_derive::Deserialize; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { + #[structopt(name = "spec")] arg_spec: String, + #[structopt(name = "dir", long = "git-dir")] + /// directory of the git repository to check flag_git_dir: Option, } @@ -50,16 +52,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - const USAGE: &str = " -usage: rev-parse [options] - -Options: - --git-dir directory of the git repository to check -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/status.rs b/examples/status.rs index 689c42a67c..4f7bc791c0 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -14,24 +14,46 @@ #![deny(warnings)] -use docopt::Docopt; use git2::{Error, ErrorCode, Repository, StatusOptions, SubmoduleIgnore}; -use serde_derive::Deserialize; use std::str; use std::time::Duration; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { arg_spec: Vec, + #[structopt(name = "long", long)] + /// show longer statuses (default) + _flag_long: bool, + /// show short statuses + #[structopt(name = "short", long)] flag_short: bool, + #[structopt(name = "porcelain", long)] + /// ?? flag_porcelain: bool, + #[structopt(name = "branch", short, long)] + /// show branch information flag_branch: bool, + #[structopt(name = "z", short)] + /// ?? flag_z: bool, + #[structopt(name = "ignored", long)] + /// show ignored files as well flag_ignored: bool, + #[structopt(name = "opt-modules", long = "untracked-files")] + /// setting for showing untracked files [no|normal|all] flag_untracked_files: Option, + #[structopt(name = "opt-files", long = "ignore-submodules")] + /// setting for ignoring submodules [all] flag_ignore_submodules: Option, + #[structopt(name = "dir", long = "git-dir")] + /// git directory to analyze flag_git_dir: Option, + #[structopt(name = "repeat", long)] + /// repeatedly show status, sleeping inbetween flag_repeat: bool, + #[structopt(name = "list-submodules", long)] + /// show submodules flag_list_submodules: bool, } @@ -411,27 +433,7 @@ impl Args { } fn main() { - const USAGE: &str = " -usage: status [options] [--] [..] - -Options: - -s, --short show short statuses - --long show longer statuses (default) - --porcelain ?? - -b, --branch show branch information - -z ?? - --ignored show ignored files as well - --untracked-files setting for showing untracked files [no|normal|all] - --ignore-submodules setting for ignoring submodules [all] - --git-dir git directory to analyze - --repeat repeatedly show status, sleeping inbetween - --list-submodules show submodules - -h, --help show this message -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/tag.rs b/examples/tag.rs index 1e73889607..c44c2887d2 100644 --- a/examples/tag.rs +++ b/examples/tag.rs @@ -14,20 +14,29 @@ #![deny(warnings)] -use docopt::Docopt; use git2::{Commit, Error, Repository, Tag}; -use serde_derive::Deserialize; use std::str; +use structopt::StructOpt; -#[derive(Deserialize)] +#[derive(StructOpt)] struct Args { arg_tagname: Option, arg_object: Option, arg_pattern: Option, + #[structopt(name = "n", short)] + /// specify number of lines from the annotation to print flag_n: Option, + #[structopt(name = "force", short, long)] + /// replace an existing tag with the given name flag_force: bool, + #[structopt(name = "list", short, long)] + /// list tags with names matching the pattern given flag_list: bool, + #[structopt(name = "tag", short, long = "delete")] + /// delete the tag specified flag_delete: Option, + #[structopt(name = "msg", short, long = "message")] + /// message for a new tag flag_message: Option, } @@ -110,24 +119,7 @@ fn print_list_lines(message: Option<&str>, args: &Args) { } fn main() { - const USAGE: &str = " -usage: - tag [-a] [-f] [-m ] [] - tag -d - tag [-n ] -l [] - -Options: - -n specify number of lines from the annotation to print - -f, --force replace an existing tag with the given name - -l, --list list tags with names matching the pattern given - -d, --delete delete the tag specified - -m, --message message for a new tag - -h, --help show this message -"; - - let args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), From 0b8047f80d1eeb81c38d3f2e637e5dfc4321f897 Mon Sep 17 00:00:00 2001 From: Nathan Wilson Date: Tue, 17 Mar 2020 10:16:28 -0400 Subject: [PATCH 444/860] =?UTF-8?q?Libgit2=20has=20a=20new=20error=20class?= =?UTF-8?q?=20to=20represent=20HTTP=20errors.=20Add=20it=20to=20the?= =?UTF-8?q?=E2=80=A6=20(#529)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Libgit2 has a new error class to represent HTTP errors. Add it to the appropriate enums. * Updated Error::class and Error::raw_class to return the Http enum variant. --- libgit2-sys/lib.rs | 1 + src/error.rs | 2 ++ src/lib.rs | 2 ++ 3 files changed, 5 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index c6ac07fc8d..32dc026287 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -230,6 +230,7 @@ git_enum! { GIT_ERROR_PATCH, GIT_ERROR_WORKTREE, GIT_ERROR_SHA1, + GIT_ERROR_HTTP, } } diff --git a/src/error.rs b/src/error.rs index 93f8f69cce..d093e5cf2b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -156,6 +156,7 @@ impl Error { raw::GIT_ERROR_PATCH => super::ErrorClass::Patch, raw::GIT_ERROR_WORKTREE => super::ErrorClass::Worktree, raw::GIT_ERROR_SHA1 => super::ErrorClass::Sha1, + raw::GIT_ERROR_HTTP => super::ErrorClass::Http, _ => super::ErrorClass::None, } } @@ -243,6 +244,7 @@ impl Error { GIT_ERROR_PATCH, GIT_ERROR_WORKTREE, GIT_ERROR_SHA1, + GIT_ERROR_HTTP, ) } diff --git a/src/lib.rs b/src/lib.rs index 9c82610dbe..6d69437197 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -261,6 +261,8 @@ pub enum ErrorClass { Worktree, /// Hash library error or SHA-1 collision Sha1, + /// HTTP error + Http, } /// A listing of the possible states that a repository can be in. From e8347d3daf37b1e770e60ffdf3226aad7be148bd Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Fri, 20 Mar 2020 15:37:26 +0100 Subject: [PATCH 445/860] add apply sys api (#531) seems like enum flags need to be untyped (fix ci) trying to fix windows ci issue fix typo next try fixing windows warning next windows ci fix --- libgit2-sys/lib.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 32dc026287..a8c6922c87 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -23,6 +23,7 @@ pub const GIT_SUBMODULE_UPDATE_OPTIONS_VERSION: c_uint = 1; pub const GIT_ODB_BACKEND_VERSION: c_uint = 1; pub const GIT_REFDB_BACKEND_VERSION: c_uint = 1; pub const GIT_CHERRYPICK_OPTIONS_VERSION: c_uint = 1; +pub const GIT_APPLY_OPTIONS_VERSION: c_uint = 1; macro_rules! git_enum { (pub enum $name:ident { $($variants:tt)* }) => { @@ -1728,6 +1729,35 @@ pub struct git_cherrypick_options { pub checkout_opts: git_checkout_options, } +pub type git_apply_delta_cb = + Option c_int>; + +pub type git_apply_hunk_cb = + Option c_int>; + +git_enum! { + pub enum git_apply_flags_t { + GIT_APPLY_CHECK = 1<<0, + } +} + +#[repr(C)] +pub struct git_apply_options { + pub version: c_uint, + pub delta_cb: git_apply_delta_cb, + pub hunk_cb: git_apply_hunk_cb, + pub payload: *mut c_void, + pub flags: u32, +} + +git_enum! { + pub enum git_apply_location_t { + GIT_APPLY_LOCATION_WORKDIR = 0, + GIT_APPLY_LOCATION_INDEX = 1, + GIT_APPLY_LOCATION_BOTH = 2, + } +} + extern "C" { // threads pub fn git_libgit2_init() -> c_int; @@ -3587,6 +3617,22 @@ extern "C" { mainline: c_uint, merge_options: *const git_merge_options, ) -> c_int; + + // apply + pub fn git_apply_options_init(opts: *mut git_apply_options, version: c_uint) -> c_int; + pub fn git_apply_to_tree( + out: *mut *mut git_index, + repo: *mut git_repository, + preimage: *mut git_tree, + diff: *mut git_diff, + options: *const git_apply_options, + ) -> c_int; + pub fn git_apply( + repo: *mut git_repository, + diff: *mut git_diff, + location: git_apply_location_t, + options: *const git_apply_options, + ) -> c_int; } pub fn init() { From f3b87baed1e33d6c2d94fe1fa6aa6503a071d837 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Sun, 22 Mar 2020 08:38:24 -0400 Subject: [PATCH 446/860] A first stab at a pull example. (#427) A first stab at a pull example. --- examples/pull.rs | 208 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 examples/pull.rs diff --git a/examples/pull.rs b/examples/pull.rs new file mode 100644 index 0000000000..33f5cb1ef1 --- /dev/null +++ b/examples/pull.rs @@ -0,0 +1,208 @@ +/* + * libgit2 "pull" example - shows how to pull remote data into a local branch. + * + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . + */ + +use git2::Repository; +use std::io::{self, Write}; +use std::str; +use structopt::StructOpt; + +#[derive(StructOpt)] +struct Args { + arg_remote: Option, + arg_branch: Option, +} + +fn do_fetch<'a>( + repo: &'a git2::Repository, + refs: &[&str], + remote: &'a mut git2::Remote, +) -> Result, git2::Error> { + let mut cb = git2::RemoteCallbacks::new(); + + // Print out our transfer progress. + cb.transfer_progress(|stats| { + if stats.received_objects() == stats.total_objects() { + print!( + "Resolving deltas {}/{}\r", + stats.indexed_deltas(), + stats.total_deltas() + ); + } else if stats.total_objects() > 0 { + print!( + "Received {}/{} objects ({}) in {} bytes\r", + stats.received_objects(), + stats.total_objects(), + stats.indexed_objects(), + stats.received_bytes() + ); + } + io::stdout().flush().unwrap(); + true + }); + + let mut fo = git2::FetchOptions::new(); + fo.remote_callbacks(cb); + // Always fetch all tags. + // Perform a download and also update tips + fo.download_tags(git2::AutotagOption::All); + println!("Fetching {} for repo", remote.name().unwrap()); + remote.fetch(refs, Some(&mut fo), None)?; + + // If there are local objects (we got a thin pack), then tell the user + // how many objects we saved from having to cross the network. + let stats = remote.stats(); + if stats.local_objects() > 0 { + println!( + "\rReceived {}/{} objects in {} bytes (used {} local \ + objects)", + stats.indexed_objects(), + stats.total_objects(), + stats.received_bytes(), + stats.local_objects() + ); + } else { + println!( + "\rReceived {}/{} objects in {} bytes", + stats.indexed_objects(), + stats.total_objects(), + stats.received_bytes() + ); + } + + let fetch_head = repo.find_reference("FETCH_HEAD")?; + Ok(repo.reference_to_annotated_commit(&fetch_head)?) +} + +fn fast_forward( + repo: &Repository, + lb: &mut git2::Reference, + rc: &git2::AnnotatedCommit, +) -> Result<(), git2::Error> { + let name = match lb.name() { + Some(s) => s.to_string(), + None => String::from_utf8_lossy(lb.name_bytes()).to_string(), + }; + let msg = format!("Fast-Forward: Setting {} to id: {}", name, rc.id()); + println!("{}", msg); + lb.set_target(rc.id(), &msg)?; + repo.set_head(&name)?; + repo.checkout_head(Some( + git2::build::CheckoutBuilder::default() + // For some reason the force is required to make the working directory actually get updated + // I suspect we should be adding some logic to handle dirty working directory states + // but this is just an example so maybe not. + .force(), + ))?; + Ok(()) +} + +fn normal_merge( + repo: &Repository, + local: &git2::AnnotatedCommit, + remote: &git2::AnnotatedCommit, +) -> Result<(), git2::Error> { + let local_tree = repo.find_commit(local.id())?.tree()?; + let remote_tree = repo.find_commit(remote.id())?.tree()?; + let ancestor = repo + .find_commit(repo.merge_base(local.id(), remote.id())?)? + .tree()?; + let mut idx = repo.merge_trees(&ancestor, &local_tree, &remote_tree, None)?; + + if idx.has_conflicts() { + println!("Merge conficts detected..."); + repo.checkout_index(Some(&mut idx), None)?; + return Ok(()); + } + let result_tree = repo.find_tree(idx.write_tree_to(repo)?)?; + // now create the merge commit + let msg = format!("Merge: {} into {}", remote.id(), local.id()); + let sig = repo.signature()?; + let local_commit = repo.find_commit(local.id())?; + let remote_commit = repo.find_commit(remote.id())?; + // Do our merge commit and set current branch head to that commit. + let _merge_commit = repo.commit( + Some("HEAD"), + &sig, + &sig, + &msg, + &result_tree, + &[&local_commit, &remote_commit], + )?; + // Set working tree to match head. + repo.checkout_head(None)?; + Ok(()) +} + +fn do_merge<'a>( + repo: &'a Repository, + remote_branch: &str, + fetch_commit: git2::AnnotatedCommit<'a>, +) -> Result<(), git2::Error> { + // 1. do a merge analysis + let analysis = repo.merge_analysis(&[&fetch_commit])?; + + // 2. Do the appopriate merge + if analysis.0.is_fast_forward() { + println!("Doing a fast forward"); + // do a fast forward + let refname = format!("refs/heads/{}", remote_branch); + match repo.find_reference(&refname) { + Ok(mut r) => { + fast_forward(repo, &mut r, &fetch_commit)?; + } + Err(_) => { + // The branch doesn't exist so just set the reference to the + // commit directly. Usually this is because you are pulling + // into an empty repository. + repo.reference( + &refname, + fetch_commit.id(), + true, + &format!("Setting {} to {}", remote_branch, fetch_commit.id()), + )?; + repo.set_head(&refname)?; + repo.checkout_head(Some( + git2::build::CheckoutBuilder::default() + .allow_conflicts(true) + .conflict_style_merge(true) + .force(), + ))?; + } + }; + } else if analysis.0.is_normal() { + // do a normal merge + let head_commit = repo.reference_to_annotated_commit(&repo.head()?)?; + normal_merge(&repo, &head_commit, &fetch_commit)?; + } else { + println!("Nothing to do..."); + } + Ok(()) +} + +fn run(args: &Args) -> Result<(), git2::Error> { + let remote_name = args.arg_remote.as_ref().map(|s| &s[..]).unwrap_or("origin"); + let remote_branch = args.arg_branch.as_ref().map(|s| &s[..]).unwrap_or("master"); + let repo = Repository::open(".")?; + let mut remote = repo.find_remote(remote_name)?; + let fetch_commit = do_fetch(&repo, &[remote_branch], &mut remote)?; + do_merge(&repo, &remote_branch, fetch_commit) +} + +fn main() { + let args = Args::from_args(); + match run(&args) { + Ok(()) => {} + Err(e) => println!("error: {}", e), + } +} From 6f14f0f4ec83027dd6df2da0f1e56c82af531bdb Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Mon, 23 Mar 2020 14:54:05 +0100 Subject: [PATCH 447/860] fix typo (#533) --- src/diff.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diff.rs b/src/diff.rs index 4cedb77d2d..a5e753c4f3 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -696,7 +696,7 @@ impl DiffOptions { self.flag(raw::GIT_DIFF_IGNORE_WHITESPACE_CHANGE, ignore) } - /// Ignore whitespace at tend of line + /// Ignore whitespace at the end of line pub fn ignore_whitespace_eol(&mut self, ignore: bool) -> &mut DiffOptions { self.flag(raw::GIT_DIFF_IGNORE_WHITESPACE_EOL, ignore) } From 613d6536cce7535a447e405bedf9084445575aac Mon Sep 17 00:00:00 2001 From: Patrick Mooney Date: Thu, 26 Mar 2020 10:28:14 -0500 Subject: [PATCH 448/860] Use Solaris build flags for illumos targets (#535) --- libgit2-sys/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index e89a9a0ad2..25a16a3885 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -93,7 +93,7 @@ fn main() { add_c_files(&mut cfg, "libgit2/src/unix"); cfg.flag("-fvisibility=hidden"); } - if target.contains("solaris") { + if target.contains("solaris") || target.contains("illumos") { cfg.define("_POSIX_C_SOURCE", "200112L"); cfg.define("__EXTENSIONS__", None); } From 2e9fb0c67ebd7c4b6cd54e1eedcd2ce91660bd98 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 1 Apr 2020 06:52:33 -0700 Subject: [PATCH 449/860] Bump versions --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b980d5ccba..c19830c50a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.0" +version = "0.13.1" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 0d262d3c7f..f0b2604a09 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.0+0.99.0" +version = "0.12.1+0.99.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 0a529b5347f08f6ef7950269bca5220226ec8d2e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 1 Apr 2020 09:55:51 -0700 Subject: [PATCH 450/860] Update to libgit2's 1.0.0 release * Enable pkg-config by default now that it has a stable ABI * Bump libgit2-sys version number --- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 12 +++++------- libgit2-sys/libgit2 | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index f0b2604a09..03d9db59f9 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.1+0.99.0" +version = "0.12.2+1.0.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 25a16a3885..54601bfbb9 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -7,14 +7,12 @@ fn main() { let https = env::var("CARGO_FEATURE_HTTPS").is_ok(); let ssh = env::var("CARGO_FEATURE_SSH").is_ok(); - if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() { - let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.atleast_version("0.28.0").probe("libgit2") { - for include in &lib.include_paths { - println!("cargo:root={}", include.display()); - } - return; + let mut cfg = pkg_config::Config::new(); + if let Ok(lib) = cfg.atleast_version("1.0.0").probe("libgit2") { + for include in &lib.include_paths { + println!("cargo:root={}", include.display()); } + return; } if !Path::new("libgit2/.git").exists() { diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index be36db28f6..7d3c7057f0 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit be36db28f64de8ed5ca9870708a56b6668c6c482 +Subproject commit 7d3c7057f0e774aecd6fc4ef8333e69e5c4873e0 From d2c6f8b0f83a91df9ef8a78e190242160086efc9 Mon Sep 17 00:00:00 2001 From: stoically Date: Wed, 1 Apr 2020 20:24:04 +0200 Subject: [PATCH 451/860] Expose OdbPackwriter (#539) --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6d69437197..335724850b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,7 +100,7 @@ pub use crate::merge::{AnnotatedCommit, MergeOptions}; pub use crate::message::{message_prettify, DEFAULT_COMMENT_CHAR}; pub use crate::note::{Note, Notes}; pub use crate::object::Object; -pub use crate::odb::{Odb, OdbObject, OdbReader, OdbWriter}; +pub use crate::odb::{Odb, OdbObject, OdbPackwriter, OdbReader, OdbWriter}; pub use crate::oid::Oid; pub use crate::packbuilder::{PackBuilder, PackBuilderStage}; pub use crate::patch::Patch; From 45ba1b800c3c4794a807dedab4aba16ccf8e4dbe Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Mon, 6 Apr 2020 20:33:27 +0200 Subject: [PATCH 452/860] add apply support to repository (#542) --- src/apply.rs | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + src/repo.rs | 21 +++++- 3 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 src/apply.rs diff --git a/src/apply.rs b/src/apply.rs new file mode 100644 index 0000000000..d0796cdd4f --- /dev/null +++ b/src/apply.rs @@ -0,0 +1,208 @@ +//! git_apply support +//! see original: https://github.com/libgit2/libgit2/blob/master/include/git2/apply.h + +use crate::{panic, raw, util::Binding, DiffDelta, DiffHunk}; +use libc::c_int; +use std::{ffi::c_void, mem}; + +/// Possible application locations for git_apply +/// see https://libgit2.org/libgit2/#HEAD/type/git_apply_options +#[derive(Copy, Clone, Debug)] +pub enum ApplyLocation { + /// Apply the patch to the workdir + WorkDir, + /// Apply the patch to the index + Index, + /// Apply the patch to both the working directory and the index + Both, +} + +impl Binding for ApplyLocation { + type Raw = raw::git_apply_location_t; + unsafe fn from_raw(raw: raw::git_apply_location_t) -> Self { + match raw { + raw::GIT_APPLY_LOCATION_WORKDIR => Self::WorkDir, + raw::GIT_APPLY_LOCATION_INDEX => Self::Index, + raw::GIT_APPLY_LOCATION_BOTH => Self::Both, + _ => panic!("Unknown git diff binary kind"), + } + } + fn raw(&self) -> raw::git_apply_location_t { + match *self { + Self::WorkDir => raw::GIT_APPLY_LOCATION_WORKDIR, + Self::Index => raw::GIT_APPLY_LOCATION_INDEX, + Self::Both => raw::GIT_APPLY_LOCATION_BOTH, + } + } +} + +/// Options to specify when applying a diff +pub struct ApplyOptions<'cb> { + raw: raw::git_apply_options, + hunk_cb: Option>>, + delta_cb: Option>>, +} + +type HunkCB<'a> = dyn FnMut(Option>) -> bool + 'a; +type DeltaCB<'a> = dyn FnMut(Option>) -> bool + 'a; + +extern "C" fn delta_cb_c(delta: *const raw::git_diff_delta, data: *mut c_void) -> c_int { + panic::wrap(|| unsafe { + let delta = Binding::from_raw_opt(delta as *mut _); + + let payload = &mut *(data as *mut ApplyOptions<'_>); + let callback = match payload.delta_cb { + Some(ref mut c) => c, + None => return -1, + }; + + let apply = callback(delta); + if apply { + 0 + } else { + 1 + } + }) + .unwrap_or(-1) +} + +extern "C" fn hunk_cb_c(hunk: *const raw::git_diff_hunk, data: *mut c_void) -> c_int { + panic::wrap(|| unsafe { + let hunk = Binding::from_raw_opt(hunk); + + let payload = &mut *(data as *mut ApplyOptions<'_>); + let callback = match payload.hunk_cb { + Some(ref mut c) => c, + None => return -1, + }; + + let apply = callback(hunk); + if apply { + 0 + } else { + 1 + } + }) + .unwrap_or(-1) +} + +impl<'cb> ApplyOptions<'cb> { + /// Creates a new set of empty options (zeroed). + pub fn new() -> Self { + let mut opts = Self { + raw: unsafe { mem::zeroed() }, + hunk_cb: None, + delta_cb: None, + }; + assert_eq!( + unsafe { raw::git_apply_options_init(&mut opts.raw, raw::GIT_APPLY_OPTIONS_VERSION) }, + 0 + ); + opts + } + + fn flag(&mut self, opt: raw::git_apply_flags_t, val: bool) -> &mut Self { + let opt = opt as u32; + if val { + self.raw.flags |= opt; + } else { + self.raw.flags &= !opt; + } + self + } + + /// Don't actually make changes, just test that the patch applies. + pub fn check(&mut self, check: bool) -> &mut Self { + self.flag(raw::GIT_APPLY_CHECK, check) + } + + /// When applying a patch, callback that will be made per hunk. + pub fn hunk_callback(&mut self, cb: F) -> &mut Self + where + F: FnMut(Option>) -> bool + 'cb, + { + self.hunk_cb = Some(Box::new(cb) as Box>); + + self.raw.hunk_cb = Some(hunk_cb_c); + self.raw.payload = self as *mut _ as *mut _; + + self + } + + /// When applying a patch, callback that will be made per delta (file). + pub fn delta_callback(&mut self, cb: F) -> &mut Self + where + F: FnMut(Option>) -> bool + 'cb, + { + self.delta_cb = Some(Box::new(cb) as Box>); + + self.raw.delta_cb = Some(delta_cb_c); + self.raw.payload = self as *mut _ as *mut _; + + self + } + + /// Pointer to a raw git_stash_apply_options + pub unsafe fn raw(&mut self) -> *const raw::git_apply_options { + &self.raw as *const _ + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::{fs::File, io::Write, path::Path}; + + #[test] + fn smoke_test() { + let (_td, repo) = crate::test::repo_init(); + let diff = t!(repo.diff_tree_to_workdir(None, None)); + let mut count_hunks = 0; + let mut count_delta = 0; + { + let mut opts = ApplyOptions::new(); + opts.hunk_callback(|_hunk| { + count_hunks += 1; + true + }); + opts.delta_callback(|_delta| { + count_delta += 1; + true + }); + t!(repo.apply(&diff, ApplyLocation::Both, Some(&mut opts))); + } + assert_eq!(count_hunks, 0); + assert_eq!(count_delta, 0); + } + + #[test] + fn apply_hunks_and_delta() { + let file_path = Path::new("foo.txt"); + let (td, repo) = crate::test::repo_init(); + // create new file + t!(t!(File::create(&td.path().join(file_path))).write_all(b"bar")); + // stage the new file + t!(t!(repo.index()).add_path(file_path)); + // now change workdir version + t!(t!(File::create(&td.path().join(file_path))).write_all(b"foo\nbar")); + + let diff = t!(repo.diff_index_to_workdir(None, None)); + assert_eq!(diff.deltas().len(), 1); + let mut count_hunks = 0; + let mut count_delta = 0; + { + let mut opts = ApplyOptions::new(); + opts.hunk_callback(|_hunk| { + count_hunks += 1; + true + }); + opts.delta_callback(|_delta| { + count_delta += 1; + true + }); + t!(repo.apply(&diff, ApplyLocation::Index, Some(&mut opts))); + } + assert_eq!(count_delta, 1); + assert_eq!(count_hunks, 1); + } +} diff --git a/src/lib.rs b/src/lib.rs index 335724850b..bc7bf1b6a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,6 +79,7 @@ use std::fmt; use std::str; use std::sync::Once; +pub use crate::apply::{ApplyLocation, ApplyOptions}; pub use crate::blame::{Blame, BlameHunk, BlameIter, BlameOptions}; pub use crate::blob::{Blob, BlobWriter}; pub use crate::branch::{Branch, Branches}; @@ -624,6 +625,7 @@ pub mod oid_array; pub mod string_array; pub mod transport; +mod apply; mod blame; mod blob; mod branch; diff --git a/src/repo.rs b/src/repo.rs index 7f3bb4c98e..9d36622d01 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -20,12 +20,12 @@ use crate::{ use crate::{ AnnotatedCommit, MergeAnalysis, MergeOptions, MergePreference, SubmoduleIgnore, SubmoduleStatus, }; +use crate::{ApplyLocation, ApplyOptions, Rebase, RebaseOptions}; use crate::{Blame, BlameOptions, Reference, References, ResetType, Signature, Submodule}; use crate::{Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, Oid, Tree}; use crate::{Describe, IntoCString, Reflog, RepositoryInitMode, RevparseMode}; use crate::{DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder}; use crate::{Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag}; -use crate::{Rebase, RebaseOptions}; /// An owned git repository, representing all state associated with the /// underlying filesystem. @@ -2562,6 +2562,25 @@ impl Repository { Ok(buf) } } + + /// Apply a Diff to the given repo, making changes directly in the working directory, the index, or both. + pub fn apply( + &self, + diff: &Diff<'_>, + location: ApplyLocation, + options: Option<&mut ApplyOptions<'_>>, + ) -> Result<(), Error> { + unsafe { + try_call!(raw::git_apply( + self.raw, + diff.raw(), + location.raw(), + options.map(|s| s.raw()).unwrap_or(ptr::null()) + )); + + Ok(()) + } + } } impl Binding for Repository { From 617499d7fcf315cf92faa1ffde425666d3edd500 Mon Sep 17 00:00:00 2001 From: Nathan Wilson Date: Mon, 6 Apr 2020 14:33:49 -0400 Subject: [PATCH 453/860] =?UTF-8?q?Added=20some=20low-=20and=20high-level?= =?UTF-8?q?=20bindings=20for=20creating=20branches,=20settin=E2=80=A6=20(#?= =?UTF-8?q?543)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added some low- and high-level bindings for creating branches, setting the repository HEAD, and getting reference names pointed to by annotated commits. * Fixed rustfmt issue. * Truly fix rustfmt issue. --- libgit2-sys/lib.rs | 12 ++++++++++++ src/merge.rs | 13 ++++++++++++ src/repo.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a8c6922c87..07123e51b9 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1806,6 +1806,10 @@ extern "C" { repo: *mut git_repository, commitish: *const git_oid, ) -> c_int; + pub fn git_repository_set_head_detached_from_annotated( + repo: *mut git_repository, + commitish: *const git_annotated_commit, + ) -> c_int; pub fn git_repository_set_bare(repo: *mut git_repository) -> c_int; pub fn git_repository_is_worktree(repo: *const git_repository) -> c_int; pub fn git_repository_is_bare(repo: *const git_repository) -> c_int; @@ -2528,6 +2532,13 @@ extern "C" { target: *const git_commit, force: c_int, ) -> c_int; + pub fn git_branch_create_from_annotated( + ref_out: *mut *mut git_reference, + repository: *mut git_repository, + branch_name: *const c_char, + commit: *const git_annotated_commit, + force: c_int, + ) -> c_int; pub fn git_branch_delete(branch: *mut git_reference) -> c_int; pub fn git_branch_is_head(branch: *const git_reference) -> c_int; pub fn git_branch_iterator_free(iter: *mut git_branch_iterator); @@ -2891,6 +2902,7 @@ extern "C" { // merge pub fn git_annotated_commit_id(commit: *const git_annotated_commit) -> *const git_oid; + pub fn git_annotated_commit_ref(commit: *const git_annotated_commit) -> *const c_char; pub fn git_annotated_commit_from_ref( out: *mut *mut git_annotated_commit, repo: *mut git_repository, diff --git a/src/merge.rs b/src/merge.rs index 417f12bbd3..4c2749bf9c 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -1,6 +1,7 @@ use libc::c_uint; use std::marker; use std::mem; +use std::str; use crate::call::Convert; use crate::util::Binding; @@ -26,6 +27,18 @@ impl<'repo> AnnotatedCommit<'repo> { pub fn id(&self) -> Oid { unsafe { Binding::from_raw(raw::git_annotated_commit_id(self.raw)) } } + + /// Get the refname that the given git_annotated_commit refers to + /// + /// Returns None if it is not valid utf8 + pub fn refname(&self) -> Option<&str> { + str::from_utf8(self.refname_bytes()).ok() + } + + /// Get the refname that the given git_annotated_commit refers to. + pub fn refname_bytes(&self) -> &[u8] { + unsafe { crate::opt_bytes(self, raw::git_annotated_commit_ref(&*self.raw)).unwrap() } + } } impl Default for MergeOptions { diff --git a/src/repo.rs b/src/repo.rs index 9d36622d01..b4daefa567 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -742,6 +742,27 @@ impl Repository { Ok(()) } + /// Make the repository HEAD directly point to the commit. + /// + /// If the provided committish cannot be found in the repository, the HEAD + /// is unaltered and an error is returned. + /// If the provided commitish cannot be peeled into a commit, the HEAD is + /// unaltered and an error is returned. + /// Otherwise, the HEAD will eventually be detached and will directly point + /// to the peeled commit. + pub fn set_head_detached_from_annotated( + &self, + commitish: AnnotatedCommit<'_>, + ) -> Result<(), Error> { + unsafe { + try_call!(raw::git_repository_set_head_detached_from_annotated( + self.raw, + commitish.raw() + )); + } + Ok(()) + } + /// Create an iterator for the repo's references pub fn references(&self) -> Result, Error> { let mut ret = ptr::null_mut(); @@ -1053,6 +1074,34 @@ impl Repository { } } + /// Create a new branch pointing at a target commit + /// + /// This behaves like `Repository::branch()` but takes + /// an annotated commit, which lets you specify which + /// extended sha syntax string was specified by a user, + /// allowing for more exact reflog messages. + /// + /// See the documentation for `Repository::branch()` + pub fn branch_from_annotated_commit( + &self, + branch_name: &str, + target: &AnnotatedCommit<'_>, + force: bool, + ) -> Result, Error> { + let branch_name = CString::new(branch_name)?; + let mut raw = ptr::null_mut(); + unsafe { + try_call!(raw::git_branch_create_from_annotated( + &mut raw, + self.raw(), + branch_name, + target.raw(), + force + )); + Ok(Branch::wrap(Binding::from_raw(raw))) + } + } + /// Lookup a branch by its name in a repository. pub fn find_branch(&self, name: &str, branch_type: BranchType) -> Result, Error> { let name = CString::new(name)?; From 066d2ec84dbe8012316c43c3c33e3afe59bdd34c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 10 Apr 2020 09:55:11 -0700 Subject: [PATCH 454/860] Bump version numbers --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c19830c50a..efbf6e4313 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.1" +version = "0.13.2" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 03d9db59f9..a474348f35 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.2+1.0.0" +version = "0.12.3+1.0.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From c42e8e964b99e193ec3e64619c2be34f262ea0c2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 10 Apr 2020 09:56:07 -0700 Subject: [PATCH 455/860] Bump version requirement of libgit2-sys --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index efbf6e4313..09b3a131e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.2" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.3" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 47d4e6a8b7491a4b160098bf422204626dbd09bd Mon Sep 17 00:00:00 2001 From: "Kartikaya Gupta (kats)" Date: Mon, 13 Apr 2020 14:20:01 -0400 Subject: [PATCH 456/860] Expose git_diff_blobs API (#548) * Generify ForeachCallbacks a bit. In particular, this makes the file callback optional as well. It also renames the struct to be a bit less specific to the foreach method; the next patch will reuse this in a different API. * Expose the git_diff_blobs API. Fixes #547 * Update diff example to allow basic diffing of blobs. This could be improved by adding color support, etc. --- examples/diff.rs | 99 ++++++++++++++++++++++++++++++++---------------- src/diff.rs | 35 +++++++++-------- src/repo.rs | 75 ++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 49 deletions(-) diff --git a/examples/diff.rs b/examples/diff.rs index 8a02c261a3..c3026edb0e 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -14,8 +14,8 @@ #![deny(warnings)] -use git2::{Diff, DiffOptions, Error, Object, ObjectType, Repository}; -use git2::{DiffFindOptions, DiffFormat}; +use git2::{Blob, Diff, DiffOptions, Error, Object, ObjectType, Oid, Repository}; +use git2::{DiffDelta, DiffFindOptions, DiffFormat, DiffHunk, DiffLine}; use std::str; use structopt::StructOpt; @@ -26,6 +26,9 @@ struct Args { arg_from_oid: Option, #[structopt(name = "to_oid")] arg_to_oid: Option, + #[structopt(name = "blobs", long)] + /// treat from_oid and to_oid as blob ids + flag_blobs: bool, #[structopt(name = "patch", short, long)] /// show output in patch format flag_patch: bool, @@ -137,6 +140,38 @@ enum Cache { None, } +fn line_color(line: &DiffLine) -> Option<&'static str> { + match line.origin() { + '+' => Some(GREEN), + '-' => Some(RED), + '>' => Some(GREEN), + '<' => Some(RED), + 'F' => Some(BOLD), + 'H' => Some(CYAN), + _ => None, + } +} + +fn print_diff_line( + _delta: DiffDelta, + _hunk: Option, + line: DiffLine, + args: &Args, +) -> bool { + if args.color() { + print!("{}", RESET); + if let Some(color) = line_color(&line) { + print!("{}", color); + } + } + match line.origin() { + '+' | '-' | ' ' => print!("{}", line.origin()), + _ => {} + } + print!("{}", str::from_utf8(line.content()).unwrap()); + true +} + fn run(args: &Args) -> Result<(), Error> { let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); let repo = Repository::open(path)?; @@ -171,6 +206,26 @@ fn run(args: &Args) -> Result<(), Error> { opts.id_abbrev(40); } + if args.flag_blobs { + let b1 = resolve_blob(&repo, args.arg_from_oid.as_ref())?; + let b2 = resolve_blob(&repo, args.arg_to_oid.as_ref())?; + repo.diff_blobs( + b1.as_ref(), + None, + b2.as_ref(), + None, + Some(&mut opts), + None, + None, + None, + Some(&mut |d, h, l| print_diff_line(d, h, l, args)), + )?; + if args.color() { + print!("{}", RESET); + } + return Ok(()); + } + // Prepare the diff to inspect let t1 = tree_to_treeish(&repo, args.arg_from_oid.as_ref())?; let t2 = tree_to_treeish(&repo, args.arg_to_oid.as_ref())?; @@ -220,37 +275,7 @@ fn run(args: &Args) -> Result<(), Error> { print_stats(&diff, args)?; } if args.flag_patch || !stats { - if args.color() { - print!("{}", RESET); - } - let mut last_color = None; - diff.print(args.diff_format(), |_delta, _hunk, line| { - if args.color() { - let next = match line.origin() { - '+' => Some(GREEN), - '-' => Some(RED), - '>' => Some(GREEN), - '<' => Some(RED), - 'F' => Some(BOLD), - 'H' => Some(CYAN), - _ => None, - }; - if args.color() && next != last_color { - if last_color == Some(BOLD) || next == Some(BOLD) { - print!("{}", RESET); - } - print!("{}", next.unwrap_or(RESET)); - last_color = next; - } - } - - match line.origin() { - '+' | '-' | ' ' => print!("{}", line.origin()), - _ => {} - } - print!("{}", str::from_utf8(line.content()).unwrap()); - true - })?; + diff.print(args.diff_format(), |d, h, l| print_diff_line(d, h, l, args))?; if args.color() { print!("{}", RESET); } @@ -292,6 +317,14 @@ fn tree_to_treeish<'a>( Ok(Some(tree)) } +fn resolve_blob<'a>(repo: &'a Repository, arg: Option<&String>) -> Result>, Error> { + let arg = match arg { + Some(s) => Oid::from_str(s)?, + None => return Ok(None), + }; + repo.find_blob(arg).map(|b| Some(b)) +} + impl Args { fn cache(&self) -> Cache { if self.flag_cached { diff --git a/src/diff.rs b/src/diff.rs index a5e753c4f3..4da44f1f5b 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -109,11 +109,11 @@ pub type BinaryCb<'a> = dyn FnMut(DiffDelta<'_>, DiffBinary<'_>) -> bool + 'a; pub type HunkCb<'a> = dyn FnMut(DiffDelta<'_>, DiffHunk<'_>) -> bool + 'a; pub type LineCb<'a> = dyn FnMut(DiffDelta<'_>, Option>, DiffLine<'_>) -> bool + 'a; -struct ForeachCallbacks<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h> { - file: &'a mut FileCb<'b>, - binary: Option<&'c mut BinaryCb<'d>>, - hunk: Option<&'e mut HunkCb<'f>>, - line: Option<&'g mut LineCb<'h>>, +pub struct DiffCallbacks<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h> { + pub file: Option<&'a mut FileCb<'b>>, + pub binary: Option<&'c mut BinaryCb<'d>>, + pub hunk: Option<&'e mut HunkCb<'f>>, + pub line: Option<&'g mut LineCb<'h>>, } impl<'repo> Diff<'repo> { @@ -182,8 +182,8 @@ impl<'repo> Diff<'repo> { hunk_cb: Option<&mut HunkCb<'_>>, line_cb: Option<&mut LineCb<'_>>, ) -> Result<(), Error> { - let mut cbs = ForeachCallbacks { - file: file_cb, + let mut cbs = DiffCallbacks { + file: Some(file_cb), binary: binary_cb, hunk: hunk_cb, line: line_cb, @@ -267,7 +267,7 @@ pub extern "C" fn print_cb( } } -extern "C" fn file_cb_c( +pub extern "C" fn file_cb_c( delta: *const raw::git_diff_delta, progress: f32, data: *mut c_void, @@ -276,8 +276,11 @@ extern "C" fn file_cb_c( let delta = Binding::from_raw(delta as *mut _); let r = panic::wrap(|| { - let cbs = data as *mut ForeachCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; - ((*cbs).file)(delta, progress) + let cbs = data as *mut DiffCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; + match (*cbs).file { + Some(ref mut cb) => cb(delta, progress), + None => false, + } }); if r == Some(true) { 0 @@ -287,7 +290,7 @@ extern "C" fn file_cb_c( } } -extern "C" fn binary_cb_c( +pub extern "C" fn binary_cb_c( delta: *const raw::git_diff_delta, binary: *const raw::git_diff_binary, data: *mut c_void, @@ -297,7 +300,7 @@ extern "C" fn binary_cb_c( let binary = Binding::from_raw(binary); let r = panic::wrap(|| { - let cbs = data as *mut ForeachCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; + let cbs = data as *mut DiffCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; match (*cbs).binary { Some(ref mut cb) => cb(delta, binary), None => false, @@ -311,7 +314,7 @@ extern "C" fn binary_cb_c( } } -extern "C" fn hunk_cb_c( +pub extern "C" fn hunk_cb_c( delta: *const raw::git_diff_delta, hunk: *const raw::git_diff_hunk, data: *mut c_void, @@ -321,7 +324,7 @@ extern "C" fn hunk_cb_c( let hunk = Binding::from_raw(hunk); let r = panic::wrap(|| { - let cbs = data as *mut ForeachCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; + let cbs = data as *mut DiffCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; match (*cbs).hunk { Some(ref mut cb) => cb(delta, hunk), None => false, @@ -335,7 +338,7 @@ extern "C" fn hunk_cb_c( } } -extern "C" fn line_cb_c( +pub extern "C" fn line_cb_c( delta: *const raw::git_diff_delta, hunk: *const raw::git_diff_hunk, line: *const raw::git_diff_line, @@ -347,7 +350,7 @@ extern "C" fn line_cb_c( let line = Binding::from_raw(line); let r = panic::wrap(|| { - let cbs = data as *mut ForeachCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; + let cbs = data as *mut DiffCallbacks<'_, '_, '_, '_, '_, '_, '_, '_>; match (*cbs).line { Some(ref mut cb) => cb(delta, hunk, line), None => false, diff --git a/src/repo.rs b/src/repo.rs index b4daefa567..ce922826cc 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -8,6 +8,9 @@ use std::ptr; use std::str; use crate::build::{CheckoutBuilder, RepoBuilder}; +use crate::diff::{ + binary_cb_c, file_cb_c, hunk_cb_c, line_cb_c, BinaryCb, DiffCallbacks, FileCb, HunkCb, LineCb, +}; use crate::oid_array::OidArray; use crate::stash::{stash_cb, StashApplyOptions, StashCbData}; use crate::string_array::StringArray; @@ -2249,6 +2252,78 @@ impl Repository { } } + /// Directly run a diff on two blobs. + /// + /// Compared to a file, a blob lacks some contextual information. As such, the + /// `DiffFile` given to the callback will have some fake data; i.e. mode will be + /// 0 and path will be `None`. + /// + /// `None` is allowed for either `old_blob` or `new_blob` and will be treated + /// as an empty blob, with the oid set to zero in the `DiffFile`. Passing `None` + /// for both blobs is a noop; no callbacks will be made at all. + /// + /// We do run a binary content check on the blob content and if either blob looks + /// like binary data, the `DiffFile` binary attribute will be set to 1 and no call to + /// the `hunk_cb` nor `line_cb` will be made (unless you set the `force_text` + /// option). + pub fn diff_blobs( + &self, + old_blob: Option<&Blob<'_>>, + old_as_path: Option<&str>, + new_blob: Option<&Blob<'_>>, + new_as_path: Option<&str>, + opts: Option<&mut DiffOptions>, + file_cb: Option<&mut FileCb<'_>>, + binary_cb: Option<&mut BinaryCb<'_>>, + hunk_cb: Option<&mut HunkCb<'_>>, + line_cb: Option<&mut LineCb<'_>>, + ) -> Result<(), Error> { + let old_as_path = crate::opt_cstr(old_as_path)?; + let new_as_path = crate::opt_cstr(new_as_path)?; + let mut cbs = DiffCallbacks { + file: file_cb, + binary: binary_cb, + hunk: hunk_cb, + line: line_cb, + }; + let ptr = &mut cbs as *mut _; + unsafe { + let file_cb_c: raw::git_diff_file_cb = if cbs.file.is_some() { + Some(file_cb_c) + } else { + None + }; + let binary_cb_c: raw::git_diff_binary_cb = if cbs.binary.is_some() { + Some(binary_cb_c) + } else { + None + }; + let hunk_cb_c: raw::git_diff_hunk_cb = if cbs.hunk.is_some() { + Some(hunk_cb_c) + } else { + None + }; + let line_cb_c: raw::git_diff_line_cb = if cbs.line.is_some() { + Some(line_cb_c) + } else { + None + }; + try_call!(raw::git_diff_blobs( + old_blob.map(|s| s.raw()), + old_as_path, + new_blob.map(|s| s.raw()), + new_as_path, + opts.map(|s| s.raw()), + file_cb_c, + binary_cb_c, + hunk_cb_c, + line_cb_c, + ptr as *mut _ + )); + Ok(()) + } + } + /// Create a diff with the difference between two tree objects. /// /// This is equivalent to `git diff ` From cf91e4c7eb2d38bdc0d228b8d92548dc4aa76e1d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 13 Apr 2020 11:55:53 -0700 Subject: [PATCH 457/860] Attempt to uniformly handle Windows-style paths. (#549) --- src/build.rs | 2 +- src/index.rs | 6 +- src/lib.rs | 4 +- src/oid.rs | 1 + src/pathspec.rs | 2 +- src/repo.rs | 30 +++------ src/status.rs | 4 +- src/tree.rs | 4 +- src/util.rs | 174 +++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 192 insertions(+), 35 deletions(-) diff --git a/src/build.rs b/src/build.rs index e1b75bd43b..6aaa6991dd 100644 --- a/src/build.rs +++ b/src/build.rs @@ -503,7 +503,7 @@ impl<'cb> CheckoutBuilder<'cb> { /// If no paths are specified, then all files are checked out. Otherwise /// only these specified paths are checked out. pub fn path(&mut self, path: T) -> &mut CheckoutBuilder<'cb> { - let path = path.into_c_string().unwrap(); + let path = util::cstring_to_repo_path(path).unwrap(); self.path_ptrs.push(path.as_ptr()); self.paths.push(path); self diff --git a/src/index.rs b/src/index.rs index 797e6d8815..6c27db143b 100644 --- a/src/index.rs +++ b/src/index.rs @@ -291,7 +291,7 @@ impl Index { T: IntoCString, I: IntoIterator, { - let (_a, _b, raw_strarray) = crate::util::iter2cstrs(pathspecs)?; + let (_a, _b, raw_strarray) = crate::util::iter2cstrs_paths(pathspecs)?; let ptr = cb.as_mut(); let callback = ptr .as_ref() @@ -469,7 +469,7 @@ impl Index { T: IntoCString, I: IntoIterator, { - let (_a, _b, raw_strarray) = crate::util::iter2cstrs(pathspecs)?; + let (_a, _b, raw_strarray) = crate::util::iter2cstrs_paths(pathspecs)?; let ptr = cb.as_mut(); let callback = ptr .as_ref() @@ -507,7 +507,7 @@ impl Index { T: IntoCString, I: IntoIterator, { - let (_a, _b, raw_strarray) = crate::util::iter2cstrs(pathspecs)?; + let (_a, _b, raw_strarray) = crate::util::iter2cstrs_paths(pathspecs)?; let ptr = cb.as_mut(); let callback = ptr .as_ref() diff --git a/src/lib.rs b/src/lib.rs index bc7bf1b6a5..bd176a2ee6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -132,12 +132,12 @@ pub use crate::util::IntoCString; // Create a convinience method on bitflag struct which checks the given flag macro_rules! is_bit_set { - ($name:ident, $flag:expr) => ( + ($name:ident, $flag:expr) => { #[allow(missing_docs)] pub fn $name(&self) -> bool { self.intersects($flag) } - ) + }; } /// An enumeration of possible errors that can happen when working with a git diff --git a/src/oid.rs b/src/oid.rs index 59f2a7ffa2..207ecd6840 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -91,6 +91,7 @@ impl Oid { pub fn hash_file>(kind: ObjectType, path: P) -> Result { crate::init(); + // Normal file path OK (does not need Windows conversion). let rpath = path.as_ref().into_c_string()?; let mut out = raw::git_oid { diff --git a/src/pathspec.rs b/src/pathspec.rs index 3b23c2fc85..6d842a55eb 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -45,7 +45,7 @@ impl Pathspec { T: IntoCString, I: IntoIterator, { - let (_a, _b, arr) = crate::util::iter2cstrs(specs)?; + let (_a, _b, arr) = crate::util::iter2cstrs_paths(specs)?; unsafe { let mut ret = ptr::null_mut(); try_call!(raw::git_pathspec_new(&mut ret, &arr)); diff --git a/src/repo.rs b/src/repo.rs index ce922826cc..17e3be33b2 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -14,7 +14,7 @@ use crate::diff::{ use crate::oid_array::OidArray; use crate::stash::{stash_cb, StashApplyOptions, StashCbData}; use crate::string_array::StringArray; -use crate::util::{self, Binding}; +use crate::util::{self, path_to_repo_path, Binding}; use crate::CherrypickOptions; use crate::{ init, raw, AttrCheckFlags, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, @@ -676,7 +676,7 @@ impl Repository { T: IntoCString, I: IntoIterator, { - let (_a, _b, mut arr) = crate::util::iter2cstrs(paths)?; + let (_a, _b, mut arr) = crate::util::iter2cstrs_paths(paths)?; let target = target.map(|t| t.raw()); unsafe { try_call!(raw::git_reset_default(self.raw, target, &mut arr)); @@ -881,13 +881,7 @@ impl Repository { /// through looking for the path that you are interested in. pub fn status_file(&self, path: &Path) -> Result { let mut ret = 0 as c_uint; - let path = if cfg!(windows) { - // `git_status_file` does not work with windows path separator - // so we convert \ to / - std::ffi::CString::new(path.to_string_lossy().replace('\\', "/"))? - } else { - path.into_c_string()? - }; + let path = path_to_repo_path(path)?; unsafe { try_call!(raw::git_status_file(&mut ret, self.raw, path)); } @@ -2603,13 +2597,7 @@ impl Repository { /// Test if the ignore rules apply to a given path. pub fn is_path_ignored>(&self, path: P) -> Result { - let path = if cfg!(windows) { - // `git_ignore_path_is_ignored` dose not work with windows path separator - // so we convert \ to / - std::ffi::CString::new(path.as_ref().to_string_lossy().replace('\\', "/"))? - } else { - path.as_ref().into_c_string()? - }; + let path = path_to_repo_path(path.as_ref())?; let mut ignored: c_int = 0; unsafe { try_call!(raw::git_ignore_path_is_ignored( @@ -3358,18 +3346,18 @@ mod tests { fn smoke_is_path_ignored() { let (_td, repo) = graph_repo_init(); - assert!(!repo.is_path_ignored(Path::new("/foo")).unwrap()); + assert!(!repo.is_path_ignored(Path::new("foo")).unwrap()); let _ = repo.add_ignore_rule("/foo"); - assert!(repo.is_path_ignored(Path::new("/foo")).unwrap()); + assert!(repo.is_path_ignored(Path::new("foo")).unwrap()); if cfg!(windows) { - assert!(repo.is_path_ignored(Path::new("\\foo\\thing")).unwrap()); + assert!(repo.is_path_ignored(Path::new("foo\\thing")).unwrap()); } let _ = repo.clear_ignore_rules(); - assert!(!repo.is_path_ignored(Path::new("/foo")).unwrap()); + assert!(!repo.is_path_ignored(Path::new("foo")).unwrap()); if cfg!(windows) { - assert!(!repo.is_path_ignored(Path::new("\\foo\\thing")).unwrap()); + assert!(!repo.is_path_ignored(Path::new("foo\\thing")).unwrap()); } } diff --git a/src/status.rs b/src/status.rs index 25b57327af..92858e48a5 100644 --- a/src/status.rs +++ b/src/status.rs @@ -5,7 +5,7 @@ use std::mem; use std::ops::Range; use std::str; -use crate::util::Binding; +use crate::util::{self, Binding}; use crate::{raw, DiffDelta, IntoCString, Repository, Status}; /// Options that can be provided to `repo.statuses()` to control how the status @@ -98,7 +98,7 @@ impl StatusOptions { /// path to match. If this is not called, then there will be no patterns to /// match and the entire directory will be used. pub fn pathspec(&mut self, pathspec: T) -> &mut StatusOptions { - let s = pathspec.into_c_string().unwrap(); + let s = util::cstring_to_repo_path(pathspec).unwrap(); self.ptrs.push(s.as_ptr()); self.pathspec.push(s); self diff --git a/src/tree.rs b/src/tree.rs index 436a8f50a2..2f644833dc 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -8,7 +8,7 @@ use std::path::Path; use std::ptr; use std::str; -use crate::util::{c_cmp_to_ordering, Binding, IntoCString}; +use crate::util::{c_cmp_to_ordering, path_to_repo_path, Binding}; use crate::{panic, raw, Error, Object, ObjectType, Oid, Repository}; /// A structure to represent a git [tree][1] @@ -179,7 +179,7 @@ impl<'repo> Tree<'repo> { /// Retrieve a tree entry contained in a tree or in any of its subtrees, /// given its relative path. pub fn get_path(&self, path: &Path) -> Result, Error> { - let path = path.into_c_string()?; + let path = path_to_repo_path(path)?; let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_tree_entry_bypath(&mut ret, &*self.raw(), path)); diff --git a/src/util.rs b/src/util.rs index d2402fcc71..a31e63bce2 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,7 +2,7 @@ use libc::{c_char, c_int, size_t}; use std::cmp::Ordering; use std::ffi::{CString, OsStr, OsString}; use std::iter::IntoIterator; -use std::path::{Path, PathBuf}; +use std::path::{Component, Path, PathBuf}; use crate::{raw, Error}; @@ -41,6 +41,29 @@ pub trait Binding: Sized { } } +/// Converts an iterator of repo paths into a git2-compatible array of cstrings. +/// +/// Only use this for repo-relative paths or pathspecs. +/// +/// See `iter2cstrs` for more details. +pub fn iter2cstrs_paths( + iter: I, +) -> Result<(Vec, Vec<*const c_char>, raw::git_strarray), Error> +where + T: IntoCString, + I: IntoIterator, +{ + let cstrs = iter + .into_iter() + .map(|i| fixup_windows_path(i.into_c_string()?)) + .collect::, _>>()?; + iter2cstrs(cstrs) +} + +/// Converts an iterator of things into a git array of c-strings. +/// +/// Returns a tuple `(cstrings, pointers, git_strarray)`. The first two values +/// should not be dropped before `git_strarray`. pub fn iter2cstrs( iter: I, ) -> Result<(Vec, Vec<*const c_char>, raw::git_strarray), Error> @@ -136,8 +159,7 @@ impl IntoCString for OsString { match self.to_str() { Some(s) => s.into_c_string(), None => Err(Error::from_str( - "only valid unicode paths are accepted \ - on windows", + "only valid unicode paths are accepted on windows", )), } } @@ -172,3 +194,149 @@ pub fn c_cmp_to_ordering(cmp: c_int) -> Ordering { _ => Ordering::Greater, } } + +/// Converts a path to a CString that is usable by the libgit2 API. +/// +/// Checks if it is a relative path. +/// +/// On Windows, this also requires the path to be valid unicode, and translates +/// back slashes to forward slashes. +pub fn path_to_repo_path(path: &Path) -> Result { + macro_rules! err { + ($msg:literal, $path:expr) => { + return Err(Error::from_str(&format!($msg, $path.display()))); + }; + } + match path.components().next() { + None => return Err(Error::from_str("repo path should not be empty")), + Some(Component::Prefix(_)) => err!( + "repo path `{}` should be relative, not a windows prefix", + path + ), + Some(Component::RootDir) => err!("repo path `{}` should be relative", path), + Some(Component::CurDir) => err!("repo path `{}` should not start with `.`", path), + Some(Component::ParentDir) => err!("repo path `{}` should not start with `..`", path), + Some(Component::Normal(_)) => {} + } + #[cfg(windows)] + { + match path.to_str() { + None => { + return Err(Error::from_str( + "only valid unicode paths are accepted on windows", + )) + } + Some(s) => return fixup_windows_path(s), + } + } + #[cfg(not(windows))] + { + path.into_c_string() + } +} + +pub fn cstring_to_repo_path(path: T) -> Result { + fixup_windows_path(path.into_c_string()?) +} + +#[cfg(windows)] +fn fixup_windows_path>>(path: P) -> Result { + let mut bytes: Vec = path.into(); + for i in 0..bytes.len() { + if bytes[i] == b'\\' { + bytes[i] = b'/'; + } + } + Ok(CString::new(bytes)?) +} + +#[cfg(not(windows))] +fn fixup_windows_path(path: CString) -> Result { + Ok(path) +} + +#[cfg(test)] +mod tests { + use super::*; + + macro_rules! assert_err { + ($path:expr, $msg:expr) => { + match path_to_repo_path(Path::new($path)) { + Ok(_) => panic!("expected `{}` to err", $path), + Err(e) => assert_eq!(e.message(), $msg), + } + }; + } + + macro_rules! assert_repo_path_ok { + ($path:expr) => { + assert_repo_path_ok!($path, $path) + }; + ($path:expr, $expect:expr) => { + assert_eq!( + path_to_repo_path(Path::new($path)), + Ok(CString::new($expect).unwrap()) + ); + }; + } + + #[test] + #[cfg(windows)] + fn path_to_repo_path_translate() { + assert_repo_path_ok!("foo"); + assert_repo_path_ok!("foo/bar"); + assert_repo_path_ok!(r"foo\bar", "foo/bar"); + assert_repo_path_ok!(r"foo\bar\", "foo/bar/"); + } + + #[test] + fn path_to_repo_path_no_weird() { + assert_err!("", "repo path should not be empty"); + assert_err!("./foo", "repo path `./foo` should not start with `.`"); + assert_err!("../foo", "repo path `../foo` should not start with `..`"); + } + + #[test] + #[cfg(not(windows))] + fn path_to_repo_path_no_absolute() { + assert_err!("/", "repo path `/` should be relative"); + assert_repo_path_ok!("foo/bar"); + } + + #[test] + #[cfg(windows)] + fn path_to_repo_path_no_absolute() { + assert_err!( + r"c:", + r"repo path `c:` should be relative, not a windows prefix" + ); + assert_err!( + r"c:\", + r"repo path `c:\` should be relative, not a windows prefix" + ); + assert_err!( + r"c:temp", + r"repo path `c:temp` should be relative, not a windows prefix" + ); + assert_err!( + r"\\?\UNC\a\b\c", + r"repo path `\\?\UNC\a\b\c` should be relative, not a windows prefix" + ); + assert_err!( + r"\\?\c:\foo", + r"repo path `\\?\c:\foo` should be relative, not a windows prefix" + ); + assert_err!( + r"\\.\COM42", + r"repo path `\\.\COM42` should be relative, not a windows prefix" + ); + assert_err!( + r"\\a\b", + r"repo path `\\a\b` should be relative, not a windows prefix" + ); + assert_err!(r"\", r"repo path `\` should be relative"); + assert_err!(r"/", r"repo path `/` should be relative"); + assert_err!(r"\foo", r"repo path `\foo` should be relative"); + assert_err!(r"/foo", r"repo path `/foo` should be relative"); + } +} From df643b0365c104b19cc594427cde9cdb4712b793 Mon Sep 17 00:00:00 2001 From: "Kartikaya Gupta (kats)" Date: Mon, 20 Apr 2020 10:21:13 -0400 Subject: [PATCH 458/860] Expose the git_diff_flags_t flags value from the DiffDelta object (#551) --- src/diff.rs | 33 ++++++++++++++++++++++++++++++++- src/lib.rs | 21 +++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/diff.rs b/src/diff.rs index 4da44f1f5b..940259b009 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -9,7 +9,7 @@ use std::slice; use crate::util::{self, Binding}; use crate::{panic, raw, Buf, Delta, DiffFormat, Error, FileMode, Oid, Repository}; -use crate::{DiffStatsFormat, IntoCString}; +use crate::{DiffFlags, DiffStatsFormat, IntoCString}; /// The diff object that contains all individual file deltas. /// @@ -384,6 +384,37 @@ impl<'repo> Drop for Diff<'repo> { } impl<'a> DiffDelta<'a> { + /// Returns the flags on the delta. + /// + /// For more information, see `DiffFlags`'s documentation. + pub fn flags(&self) -> DiffFlags { + let flags = unsafe { (*self.raw).flags }; + let mut result = DiffFlags::empty(); + + #[cfg(windows)] + fn as_u32(flag: i32) -> u32 { + flag as u32 + } + #[cfg(not(windows))] + fn as_u32(flag: u32) -> u32 { + flag + } + + if (flags & as_u32(raw::GIT_DIFF_FLAG_BINARY)) != 0 { + result |= DiffFlags::BINARY; + } + if (flags & as_u32(raw::GIT_DIFF_FLAG_NOT_BINARY)) != 0 { + result |= DiffFlags::NOT_BINARY; + } + if (flags & as_u32(raw::GIT_DIFF_FLAG_VALID_ID)) != 0 { + result |= DiffFlags::VALID_ID; + } + if (flags & as_u32(raw::GIT_DIFF_FLAG_EXISTS)) != 0 { + result |= DiffFlags::EXISTS; + } + result + } + // TODO: expose when diffs are more exposed // pub fn similarity(&self) -> u16 { // unsafe { (*self.raw).similarity } diff --git a/src/lib.rs b/src/lib.rs index bd176a2ee6..8b043216d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1362,6 +1362,27 @@ impl Default for AttrCheckFlags { } } +bitflags! { + #[allow(missing_docs)] + pub struct DiffFlags: u32 { + /// File(s) treated as binary data. + const BINARY = raw::GIT_DIFF_FLAG_BINARY as u32; + /// File(s) treated as text data. + const NOT_BINARY = raw::GIT_DIFF_FLAG_NOT_BINARY as u32; + /// `id` value is known correct. + const VALID_ID = raw::GIT_DIFF_FLAG_VALID_ID as u32; + /// File exists at this side of the delta. + const EXISTS = raw::GIT_DIFF_FLAG_EXISTS as u32; + } +} + +impl DiffFlags { + is_bit_set!(is_binary, DiffFlags::BINARY); + is_bit_set!(is_not_binary, DiffFlags::NOT_BINARY); + is_bit_set!(has_valid_id, DiffFlags::VALID_ID); + is_bit_set!(exists, DiffFlags::EXISTS); +} + #[cfg(test)] mod tests { use super::ObjectType; From d7289685b826fe8dc64d2258bf1543cd72593793 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 22 Apr 2020 12:52:24 -0700 Subject: [PATCH 459/860] Bump versions --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 09b3a131e6..736d1d9ab7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.2" +version = "0.13.3" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.3" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.4" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index a474348f35..51b36766dd 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.3+1.0.0" +version = "0.12.4+1.0.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From a3de6a2fbf0b426f3ed803c8adc51564e0095714 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 23 Apr 2020 08:26:32 -0700 Subject: [PATCH 460/860] Allow absolute paths for Repository::is_path_ignored. (#554) --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 17e3be33b2..14f88760dc 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2597,7 +2597,7 @@ impl Repository { /// Test if the ignore rules apply to a given path. pub fn is_path_ignored>(&self, path: P) -> Result { - let path = path_to_repo_path(path.as_ref())?; + let path = util::cstring_to_repo_path(path.as_ref())?; let mut ignored: c_int = 0; unsafe { try_call!(raw::git_ignore_path_is_ignored( From 7cf9d36d03a7a09d9f20fd0ac659dd3f0b72a9f5 Mon Sep 17 00:00:00 2001 From: Patrick Junger Date: Thu, 23 Apr 2020 17:26:50 +0200 Subject: [PATCH 461/860] Fixed compile issue on windows-gnu. (#556) --- src/diff.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/diff.rs b/src/diff.rs index 940259b009..02764e4ff1 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -391,11 +391,11 @@ impl<'a> DiffDelta<'a> { let flags = unsafe { (*self.raw).flags }; let mut result = DiffFlags::empty(); - #[cfg(windows)] + #[cfg(target_env = "msvc")] fn as_u32(flag: i32) -> u32 { flag as u32 } - #[cfg(not(windows))] + #[cfg(not(target_env = "msvc"))] fn as_u32(flag: u32) -> u32 { flag } From 4ab58cc18fa4834c9686e4a1a5d33c8848fc2e4d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 23 Apr 2020 08:28:13 -0700 Subject: [PATCH 462/860] Bump to 0.13.4 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 736d1d9ab7..769b3c1c44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.3" +version = "0.13.4" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 6dde3ebfbc77d657c47cfc04838414524e21c506 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 24 Apr 2020 08:10:19 -0700 Subject: [PATCH 463/860] Fix more Windows paths. (#557) --- src/build.rs | 2 ++ src/config.rs | 2 ++ src/diff.rs | 2 +- src/index.rs | 23 ++++++++--------------- src/pathspec.rs | 5 +++-- src/repo.rs | 19 ++++++++++++++----- 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/build.rs b/src/build.rs index 6aaa6991dd..f86b89ca93 100644 --- a/src/build.rs +++ b/src/build.rs @@ -267,6 +267,7 @@ impl<'cb> RepoBuilder<'cb> { } let url = CString::new(url)?; + // Normal file path OK (does not need Windows conversion). let into = into.into_c_string()?; let mut raw = ptr::null_mut(); unsafe { @@ -511,6 +512,7 @@ impl<'cb> CheckoutBuilder<'cb> { /// Set the directory to check out to pub fn target_dir(&mut self, dst: &Path) -> &mut CheckoutBuilder<'cb> { + // Normal file path OK (does not need Windows conversion). self.target_dir = Some(dst.into_c_string().unwrap()); self } diff --git a/src/config.rs b/src/config.rs index ddda1d4fe2..8c2768ae58 100644 --- a/src/config.rs +++ b/src/config.rs @@ -46,6 +46,7 @@ impl Config { pub fn open(path: &Path) -> Result { crate::init(); let mut raw = ptr::null_mut(); + // Normal file path OK (does not need Windows conversion). let path = path.into_c_string()?; unsafe { try_call!(raw::git_config_open_ondisk(&mut raw, path)); @@ -122,6 +123,7 @@ impl Config { /// file instances in order (instances with a higher priority level will be /// accessed first). pub fn add_file(&mut self, path: &Path, level: ConfigLevel, force: bool) -> Result<(), Error> { + // Normal file path OK (does not need Windows conversion). let path = path.into_c_string()?; unsafe { try_call!(raw::git_config_add_file_ondisk( diff --git a/src/diff.rs b/src/diff.rs index 02764e4ff1..08a9f4e751 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -828,7 +828,7 @@ impl DiffOptions { /// Add to the array of paths/fnmatch patterns to constrain the diff. pub fn pathspec(&mut self, pathspec: T) -> &mut DiffOptions { - let s = pathspec.into_c_string().unwrap(); + let s = util::cstring_to_repo_path(pathspec).unwrap(); self.pathspec_ptrs.push(s.as_ptr()); self.pathspec.push(s); self diff --git a/src/index.rs b/src/index.rs index 6c27db143b..2ab48b8200 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1,4 +1,4 @@ -use std::ffi::{CStr, CString, OsString}; +use std::ffi::{CStr, CString}; use std::marker; use std::ops::Range; use std::path::Path; @@ -7,7 +7,7 @@ use std::slice; use libc::{c_char, c_int, c_uint, c_void, size_t}; -use crate::util::{self, Binding}; +use crate::util::{self, path_to_repo_path, Binding}; use crate::IntoCString; use crate::{panic, raw, Error, IndexAddOption, IndexTime, Oid, Repository, Tree}; @@ -94,6 +94,7 @@ impl Index { pub fn open(index_path: &Path) -> Result { crate::init(); let mut raw = ptr::null_mut(); + // Normal file path OK (does not need Windows conversion). let index_path = index_path.into_c_string()?; unsafe { try_call!(raw::git_index_open(&mut raw, index_path)); @@ -220,15 +221,7 @@ impl Index { /// no longer be marked as conflicting. The data about the conflict will be /// moved to the "resolve undo" (REUC) section. pub fn add_path(&mut self, path: &Path) -> Result<(), Error> { - // Git apparently expects '/' to be separators for paths - let mut posix_path = OsString::new(); - for (i, comp) in path.components().enumerate() { - if i != 0 { - posix_path.push("/"); - } - posix_path.push(comp.as_os_str()); - } - let posix_path = posix_path.into_c_string()?; + let posix_path = path_to_repo_path(path)?; unsafe { try_call!(raw::git_index_add_bypath(self.raw, posix_path)); Ok(()) @@ -364,7 +357,7 @@ impl Index { /// Get one of the entries in the index by its path. pub fn get_path(&self, path: &Path, stage: i32) -> Option { - let path = path.into_c_string().unwrap(); + let path = path_to_repo_path(path).unwrap(); unsafe { let ptr = call!(raw::git_index_get_bypath(self.raw, path, stage as c_int)); if ptr.is_null() { @@ -419,7 +412,7 @@ impl Index { /// Remove an entry from the index pub fn remove(&mut self, path: &Path, stage: i32) -> Result<(), Error> { - let path = path.into_c_string()?; + let path = path_to_repo_path(path)?; unsafe { try_call!(raw::git_index_remove(self.raw, path, stage as c_int)); } @@ -435,7 +428,7 @@ impl Index { /// no longer be marked as conflicting. The data about the conflict will be /// moved to the "resolve undo" (REUC) section. pub fn remove_path(&mut self, path: &Path) -> Result<(), Error> { - let path = path.into_c_string()?; + let path = path_to_repo_path(path)?; unsafe { try_call!(raw::git_index_remove_bypath(self.raw, path)); } @@ -444,7 +437,7 @@ impl Index { /// Remove all entries from the index under a given directory. pub fn remove_dir(&mut self, path: &Path, stage: i32) -> Result<(), Error> { - let path = path.into_c_string()?; + let path = path_to_repo_path(path)?; unsafe { try_call!(raw::git_index_remove_directory( self.raw, diff --git a/src/pathspec.rs b/src/pathspec.rs index 6d842a55eb..e5fa0493d6 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -5,7 +5,7 @@ use std::ops::Range; use std::path::Path; use std::ptr; -use crate::util::Binding; +use crate::util::{path_to_repo_path, Binding}; use crate::{raw, Diff, DiffDelta, Error, Index, IntoCString, PathspecFlags, Repository, Tree}; /// Structure representing a compiled pathspec used for matching against various @@ -45,6 +45,7 @@ impl Pathspec { T: IntoCString, I: IntoIterator, { + crate::init(); let (_a, _b, arr) = crate::util::iter2cstrs_paths(specs)?; unsafe { let mut ret = ptr::null_mut(); @@ -158,7 +159,7 @@ impl Pathspec { /// explicitly pass flags to control case sensitivity or else this will fall /// back on being case sensitive. pub fn matches_path(&self, path: &Path, flags: PathspecFlags) -> bool { - let path = path.into_c_string().unwrap(); + let path = path_to_repo_path(path).unwrap(); unsafe { raw::git_pathspec_matches_path(&*self.raw, flags.bits(), path.as_ptr()) == 1 } } } diff --git a/src/repo.rs b/src/repo.rs index 14f88760dc..88d5f8c044 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -64,6 +64,7 @@ impl Repository { /// The path can point to either a normal or bare repository. pub fn open>(path: P) -> Result { init(); + // Normal file path OK (does not need Windows conversion). let path = path.as_ref().into_c_string()?; let mut ret = ptr::null_mut(); unsafe { @@ -77,6 +78,7 @@ impl Repository { /// The path can point to only a bare repository. pub fn open_bare>(path: P) -> Result { init(); + // Normal file path OK (does not need Windows conversion). let path = path.as_ref().into_c_string()?; let mut ret = ptr::null_mut(); unsafe { @@ -142,6 +144,7 @@ impl Repository { I: IntoIterator, { init(); + // Normal file path OK (does not need Windows conversion). let path = path.as_ref().into_c_string()?; let ceiling_dirs_os = env::join_paths(ceiling_dirs)?; let ceiling_dirs = ceiling_dirs_os.into_c_string()?; @@ -165,6 +168,7 @@ impl Repository { // TODO: this diverges significantly from the libgit2 API init(); let buf = Buf::new(); + // Normal file path OK (does not need Windows conversion). let path = path.as_ref().into_c_string()?; unsafe { try_call!(raw::git_repository_discover( @@ -201,6 +205,7 @@ impl Repository { opts: &RepositoryInitOptions, ) -> Result { init(); + // Normal file path OK (does not need Windows conversion). let path = path.as_ref().into_c_string()?; let mut ret = ptr::null_mut(); unsafe { @@ -393,6 +398,7 @@ impl Repository { /// and set config "core.worktree" (if workdir is not the parent of the .git /// directory). pub fn set_workdir(&self, path: &Path, update_gitlink: bool) -> Result<(), Error> { + // Normal file path OK (does not need Windows conversion). let path = path.into_c_string()?; unsafe { try_call!(raw::git_repository_set_workdir( @@ -856,7 +862,7 @@ impl Repository { /// directory containing the file, would it be added or not? pub fn status_should_ignore(&self, path: &Path) -> Result { let mut ret = 0 as c_int; - let path = path.into_c_string()?; + let path = util::cstring_to_repo_path(path)?; unsafe { try_call!(raw::git_status_should_ignore(&mut ret, self.raw, path)); } @@ -950,7 +956,7 @@ impl Repository { flags: AttrCheckFlags, ) -> Result, Error> { let mut ret = ptr::null(); - let path = path.into_c_string()?; + let path = util::cstring_to_repo_path(path)?; let name = CString::new(name)?; unsafe { try_call!(raw::git_attr_get( @@ -991,6 +997,7 @@ impl Repository { /// The Oid returned can in turn be passed to `find_blob` to get a handle to /// the blob. pub fn blob_path(&self, path: &Path) -> Result { + // Normal file path OK (does not need Windows conversion). let path = path.into_c_string()?; let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], @@ -1545,7 +1552,7 @@ impl Repository { use_gitlink: bool, ) -> Result, Error> { let url = CString::new(url)?; - let path = path.into_c_string()?; + let path = path_to_repo_path(path)?; let mut raw = ptr::null_mut(); unsafe { try_call!(raw::git_submodule_add_setup( @@ -2069,7 +2076,7 @@ impl Repository { path: &Path, opts: Option<&mut BlameOptions>, ) -> Result, Error> { - let path = path.into_c_string()?; + let path = path_to_repo_path(path)?; let mut raw = ptr::null_mut(); unsafe { @@ -2800,12 +2807,13 @@ impl RepositoryInitOptions { self } - /// The path do the working directory. + /// The path to the working directory. /// /// If this is a relative path it will be evaulated relative to the repo /// path. If this is not the "natural" working directory, a .git gitlink /// file will be created here linking to the repo path. pub fn workdir_path(&mut self, path: &Path) -> &mut RepositoryInitOptions { + // Normal file path OK (does not need Windows conversion). self.workdir_path = Some(path.into_c_string().unwrap()); self } @@ -2823,6 +2831,7 @@ impl RepositoryInitOptions { /// If this is not configured, then the default locations will be searched /// instead. pub fn template_path(&mut self, path: &Path) -> &mut RepositoryInitOptions { + // Normal file path OK (does not need Windows conversion). self.template_path = Some(path.into_c_string().unwrap()); self } From 23954937d69ed5c3a798ba85f653099fbecf3cf2 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 24 Apr 2020 08:10:31 -0700 Subject: [PATCH 464/860] Fix some version numbers. (#558) --- README.md | 2 +- git2-curl/src/lib.rs | 2 +- libgit2-sys/lib.rs | 2 +- src/lib.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4d427cdbf8..cad02eacc1 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ version of Rust known to pass tests. ## Version of libgit2 -Currently this library requires libgit2 0.28.2. The source for libgit2 is +Currently this library requires libgit2 1.0.0. The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 59b10c2839..8f59bceb59 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -15,7 +15,7 @@ //! > **NOTE**: At this time this crate likely does not support a `git push` //! > operation, only clones. -#![doc(html_root_url = "https://docs.rs/git2-curl/0.11")] +#![doc(html_root_url = "https://docs.rs/git2-curl/0.14")] #![deny(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 07123e51b9..ae2d534a37 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.9")] +#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.12")] #![allow(non_camel_case_types, unused_extern_crates)] // This is required to link libz when libssh2-sys is not included. diff --git a/src/lib.rs b/src/lib.rs index 8b043216d6..0513fcc03b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.10")] +#![doc(html_root_url = "https://docs.rs/git2/0.13")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] From 2a6d566f122469aac3f618d2f7b6e27610f70d0d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 24 Apr 2020 08:11:10 -0700 Subject: [PATCH 465/860] Bump versions --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 769b3c1c44..61880f9363 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.4" +version = "0.13.5" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.4" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.5" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 51b36766dd..5e0c88dcbc 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.4+1.0.0" +version = "0.12.5+1.0.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From c552a3bd4f8d0daf45c23c5d6a0b7e9900098fb5 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Tue, 28 Apr 2020 07:53:19 -0700 Subject: [PATCH 466/860] rebase: Add orig_head_name and orig_head_id (#559) Add methods `orig_head_name` and `orig_head_id` to `git2::Rebase`. These are Rust-level surface for libgit2's [`git_rebase_orig_head_name`][1] and [`git_rebase_orig_head_id`][2]. [1]: https://libgit2.org/libgit2/#HEAD/group/rebase/git_rebase_orig_head_name [2]: https://libgit2.org/libgit2/#HEAD/group/rebase/git_rebase_orig_head_id `rebase_head_name` needs the rebase head to have a name; just a commit won't do. To test it, use `refs/heads/master` as the head instead of the head commit. Additionally, since these operations are valid only on merge rebases, switch the test to on-disk from in-memory. --- libgit2-sys/lib.rs | 2 ++ src/rebase.rs | 22 ++++++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index ae2d534a37..fc66a5779e 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -3596,6 +3596,8 @@ extern "C" { rebase: *mut git_rebase, idx: size_t, ) -> *mut git_rebase_operation; + pub fn git_rebase_orig_head_id(rebase: *mut git_rebase) -> *const git_oid; + pub fn git_rebase_orig_head_name(rebase: *mut git_rebase) -> *const c_char; pub fn git_rebase_next( operation: *mut *mut git_rebase_operation, rebase: *mut git_rebase, diff --git a/src/rebase.rs b/src/rebase.rs index bb9e72d4f7..d4e54133bc 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -112,6 +112,18 @@ impl<'repo> Rebase<'repo> { unsafe { raw::git_rebase_operation_entrycount(self.raw) } } + /// Gets the original `HEAD` ref name for merge rebases. + pub fn orig_head_name(&self) -> Option<&str> { + let name_bytes = + unsafe { crate::opt_bytes(self, raw::git_rebase_orig_head_name(self.raw)) }; + name_bytes.and_then(|s| str::from_utf8(s).ok()) + } + + /// Gets the original HEAD id for merge rebases. + pub fn orig_head_id(&self) -> Option { + unsafe { Oid::from_raw_opt(raw::git_rebase_orig_head_id(self.raw)) } + } + /// Gets the rebase operation specified by the given index. pub fn nth(&mut self, n: usize) -> Option> { unsafe { @@ -344,14 +356,16 @@ mod tests { .commit(Some("refs/heads/master"), &sig, &sig, "foo", &tree, &[&c1]) .unwrap(); - let branch = repo.find_annotated_commit(c2).unwrap(); + let head = repo.find_reference("refs/heads/master").unwrap(); + let branch = repo.reference_to_annotated_commit(&head).unwrap(); let upstream = repo.find_annotated_commit(tip.id()).unwrap(); - let mut opts: RebaseOptions<'_> = Default::default(); - opts.inmemory(true); let mut rebase = repo - .rebase(Some(&branch), Some(&upstream), None, Some(&mut opts)) + .rebase(Some(&branch), Some(&upstream), None, None) .unwrap(); + assert_eq!(Some("refs/heads/master"), rebase.orig_head_name()); + assert_eq!(Some(c2), rebase.orig_head_id()); + assert_eq!(rebase.len(), 2); { let op = rebase.next().unwrap().unwrap(); From a3bfaa7b6247ea33f65667e70d9f7099d7448cfc Mon Sep 17 00:00:00 2001 From: Techcable Date: Thu, 30 Apr 2020 14:10:01 -0700 Subject: [PATCH 467/860] Implement Diff::from_buffer for parsing patch files (#560) * Implement Diff::from_buffer for parsing patch files I question the decision to make diff live for 'static. Libgit2 doesn't require that it's dependent on a repository but it seems inconsitent with all the other methods of creating diffs. * Fix formatting issues My local copy of `rustfmt` isn't working..... --- libgit2-sys/lib.rs | 5 +++++ src/diff.rs | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index fc66a5779e..904ec99c9d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -3153,6 +3153,11 @@ extern "C" { line_cb: git_diff_line_cb, payload: *mut c_void, ) -> c_int; + pub fn git_diff_from_buffer( + diff: *mut *mut git_diff, + content: *const c_char, + content_len: size_t, + ) -> c_int; pub fn git_diff_find_similar( diff: *mut git_diff, options: *const git_diff_find_options, diff --git a/src/diff.rs b/src/diff.rs index 08a9f4e751..ad2263ad36 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -243,6 +243,27 @@ impl<'repo> Diff<'repo> { // TODO: num_deltas_of_type, format_email, find_similar } +impl Diff<'static> { + /// Read the contents of a git patch file into a `git_diff` object. + /// + /// The diff object produced is similar to the one that would be + /// produced if you actually produced it computationally by comparing + /// two trees, however there may be subtle differences. For example, + /// a patch file likely contains abbreviated object IDs, so the + /// object IDs parsed by this function will also be abreviated. + pub fn from_buffer(buffer: &[u8]) -> Result, Error> { + let mut diff: *mut raw::git_diff = std::ptr::null_mut(); + unsafe { + // NOTE: Doesn't depend on repo, so lifetime can be 'static + try_call!(raw::git_diff_from_buffer( + &mut diff, + buffer.as_ptr() as *const c_char, + buffer.len() + )); + Ok(Diff::from_raw(diff)) + } + } +} pub extern "C" fn print_cb( delta: *const raw::git_diff_delta, From d05202f3e842bb9cc08ed734d65374dd7799f030 Mon Sep 17 00:00:00 2001 From: Techcable Date: Fri, 1 May 2020 13:47:47 -0700 Subject: [PATCH 468/860] Implement Diff::format_email (#553) * Implement Diff::format_email * Don't hardocde the libgit2 version diff's format_email_simple test was using this, so I just switched to accept anything that looks like a match. * Attempt to fix Github's formatting complaints Rustfmt doesn't seem to be working right on my local copy. For some reason my version of rustc doesn't seem to support `rustfmt --check`. * Document Diff::format_email * Fix compilation error I should've run 'cargo check' after I formatted by hand..... My old code worked just fine. * Fix formatting issues --- libgit2-sys/lib.rs | 27 ++++++ src/diff.rs | 207 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 232 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 904ec99c9d..f3c189cab5 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1199,6 +1199,23 @@ pub const GIT_DIFF_FIND_EXACT_MATCH_ONLY: u32 = 1 << 14; pub const GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY: u32 = 1 << 15; pub const GIT_DIFF_FIND_REMOVE_UNMODIFIED: u32 = 1 << 16; +#[repr(C)] +pub struct git_diff_format_email_options { + pub version: c_uint, + pub flags: u32, + pub patch_no: usize, + pub total_patches: usize, + pub id: *const git_oid, + pub summary: *const c_char, + pub body: *const c_char, + pub author: *const git_signature, +} + +pub const GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION: c_uint = 1; + +pub const GIT_DIFF_FORMAT_EMAIL_NONE: u32 = 0; +pub const GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER: u32 = 1 << 0; + #[repr(C)] pub struct git_diff_binary { pub contains_data: c_uint, @@ -3250,6 +3267,16 @@ extern "C" { ancestor: *const git_oid, ) -> c_int; + pub fn git_diff_format_email( + out: *mut git_buf, + diff: *mut git_diff, + opts: *const git_diff_format_email_options, + ) -> c_int; + pub fn git_diff_format_email_options_init( + opts: *mut git_diff_format_email_options, + version: c_uint, + ) -> c_int; + // patch pub fn git_patch_from_diff(out: *mut *mut git_patch, diff: *mut git_diff, idx: size_t) -> c_int; diff --git a/src/diff.rs b/src/diff.rs index ad2263ad36..8908933d12 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -53,6 +53,11 @@ pub struct DiffFindOptions { raw: raw::git_diff_find_options, } +/// Control behavior of formatting emails +pub struct DiffFormatEmailOptions { + raw: raw::git_diff_format_email_options, +} + /// An iterator over the diffs in a delta pub struct Deltas<'diff> { range: Range, @@ -241,7 +246,38 @@ impl<'repo> Diff<'repo> { Ok(()) } - // TODO: num_deltas_of_type, format_email, find_similar + /// Create an e-mail ready patch from a diff. + /// + /// Matches the format created by `git format-patch` + pub fn format_email( + &mut self, + patch_no: usize, + total_patches: usize, + commit: &crate::Commit<'repo>, + opts: Option<&mut DiffFormatEmailOptions>, + ) -> Result { + assert!(patch_no > 0); + assert!(patch_no <= total_patches); + let mut default = DiffFormatEmailOptions::default(); + let mut raw_opts = opts.map_or(&mut default.raw, |opts| &mut opts.raw); + let summary = commit.summary_bytes().unwrap(); + let mut message = commit.message_bytes(); + assert!(message.starts_with(summary)); + message = &message[summary.len()..]; + raw_opts.patch_no = patch_no; + raw_opts.total_patches = total_patches; + raw_opts.id = commit.id().raw(); + raw_opts.summary = summary.as_ptr() as *const _; + raw_opts.body = message.as_ptr() as *const _; + raw_opts.author = commit.author().raw(); + let buf = Buf::new(); + unsafe { + try_call!(raw::git_diff_format_email(buf.raw(), self.raw, &*raw_opts)); + } + Ok(buf) + } + + // TODO: num_deltas_of_type, find_similar } impl Diff<'static> { /// Read the contents of a git patch file into a `git_diff` object. @@ -1358,9 +1394,47 @@ impl DiffFindOptions { // TODO: expose git_diff_similarity_metric } +impl Default for DiffFormatEmailOptions { + fn default() -> Self { + Self::new() + } +} + +impl DiffFormatEmailOptions { + /// Creates a new set of email options, + /// initialized to the default values + pub fn new() -> Self { + let mut opts = DiffFormatEmailOptions { + raw: unsafe { mem::zeroed() }, + }; + assert_eq!( + unsafe { raw::git_diff_format_email_options_init(&mut opts.raw, 1) }, + 0 + ); + opts + } + + fn flag(&mut self, opt: u32, val: bool) -> &mut Self { + if val { + self.raw.flags |= opt; + } else { + self.raw.flags &= !opt; + } + self + } + + /// Exclude `[PATCH]` from the subject header + pub fn exclude_subject_patch_header(&mut self, should_exclude: bool) -> &mut Self { + self.flag( + raw::GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER, + should_exclude, + ) + } +} + #[cfg(test)] mod tests { - use crate::DiffOptions; + use crate::{DiffOptions, Signature, Time}; use std::borrow::Borrow; use std::fs::File; use std::io::Write; @@ -1480,4 +1554,133 @@ mod tests { assert_eq!(new_lines, 1); assert_eq!(line_content, Some("bar\n".to_string())); } + + #[test] + fn format_email_simple() { + let (_td, repo) = crate::test::repo_init(); + const COMMIT_MESSAGE: &str = "Modify some content"; + const EXPECTED_EMAIL_START: &str = concat!( + "From f1234fb0588b6ed670779a34ba5c51ef962f285f Mon Sep 17 00:00:00 2001\n", + "From: Techcable \n", + "Date: Tue, 11 Jan 1972 17:46:40 +0000\n", + "Subject: [PATCH] Modify some content\n", + "\n", + "---\n", + " file1.txt | 8 +++++---\n", + " 1 file changed, 5 insertions(+), 3 deletions(-)\n", + "\n", + "diff --git a/file1.txt b/file1.txt\n", + "index 94aaae8..af8f41d 100644\n", + "--- a/file1.txt\n", + "+++ b/file1.txt\n", + "@@ -1,15 +1,17 @@\n", + " file1.txt\n", + " file1.txt\n", + "+_file1.txt_\n", + " file1.txt\n", + " file1.txt\n", + " file1.txt\n", + " file1.txt\n", + "+\n", + "+\n", + " file1.txt\n", + " file1.txt\n", + " file1.txt\n", + " file1.txt\n", + " file1.txt\n", + "-file1.txt\n", + "-file1.txt\n", + "-file1.txt\n", + "+_file1.txt_\n", + "+_file1.txt_\n", + " file1.txt\n", + "--\n" + ); + const ORIGINAL_FILE: &str = concat!( + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n" + ); + const UPDATED_FILE: &str = concat!( + "file1.txt\n", + "file1.txt\n", + "_file1.txt_\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "\n", + "\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "file1.txt\n", + "_file1.txt_\n", + "_file1.txt_\n", + "file1.txt\n" + ); + const FILE_MODE: i32 = 0o100644; + let original_file = repo.blob(ORIGINAL_FILE.as_bytes()).unwrap(); + let updated_file = repo.blob(UPDATED_FILE.as_bytes()).unwrap(); + let mut original_tree = repo.treebuilder(None).unwrap(); + original_tree + .insert("file1.txt", original_file, FILE_MODE) + .unwrap(); + let original_tree = original_tree.write().unwrap(); + let mut updated_tree = repo.treebuilder(None).unwrap(); + updated_tree + .insert("file1.txt", updated_file, FILE_MODE) + .unwrap(); + let updated_tree = updated_tree.write().unwrap(); + let time = Time::new(64_000_000, 0); + let author = Signature::new("Techcable", "dummy@dummy.org", &time).unwrap(); + let updated_commit = repo + .commit( + None, + &author, + &author, + COMMIT_MESSAGE, + &repo.find_tree(updated_tree).unwrap(), + &[], // NOTE: Have no parents to ensure stable hash + ) + .unwrap(); + let updated_commit = repo.find_commit(updated_commit).unwrap(); + let mut diff = repo + .diff_tree_to_tree( + Some(&repo.find_tree(original_tree).unwrap()), + Some(&repo.find_tree(updated_tree).unwrap()), + None, + ) + .unwrap(); + let actual_email = diff.format_email(1, 1, &updated_commit, None).unwrap(); + let actual_email = actual_email.as_str().unwrap(); + assert!( + actual_email.starts_with(EXPECTED_EMAIL_START), + "Unexpected email:\n{}", + actual_email + ); + let mut remaining_lines = actual_email[EXPECTED_EMAIL_START.len()..].lines(); + let version_line = remaining_lines.next(); + assert!( + version_line.unwrap().starts_with("libgit2"), + "Invalid version line: {:?}", + version_line + ); + while let Some(line) = remaining_lines.next() { + assert_eq!(line.trim(), "") + } + } } From beea7113a9b2878cb57b6c3a057dfc25af23f3f7 Mon Sep 17 00:00:00 2001 From: Andres Suarez Date: Wed, 6 May 2020 10:30:59 -0400 Subject: [PATCH 469/860] Fix DiffLine::content and DiffHunk::header lifetimes (#562) Tie the return value lifetimes to their underlying raw objects. These are slices from some `Patch` that live as long as the `Patch`. --- src/diff.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/diff.rs b/src/diff.rs index 8908933d12..412667ea2e 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -958,7 +958,7 @@ impl<'a> DiffLine<'a> { } /// Content of this line as bytes. - pub fn content(&self) -> &[u8] { + pub fn content(&self) -> &'a [u8] { unsafe { slice::from_raw_parts( (*self.raw).content as *const u8, @@ -1046,7 +1046,7 @@ impl<'a> DiffHunk<'a> { } /// Header text - pub fn header(&self) -> &[u8] { + pub fn header(&self) -> &'a [u8] { unsafe { slice::from_raw_parts( (*self.raw).header.as_ptr() as *const u8, From e7ebc3fd9d583c6d8c45c67e768eb95f132f559e Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Tue, 19 May 2020 16:42:13 +0200 Subject: [PATCH 470/860] stash_save2 adds support for optional message (#566) --- src/repo.rs | 13 ++++++++++++- src/stash.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 88d5f8c044..437022ed2c 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2510,12 +2510,23 @@ impl Repository { stasher: &Signature<'_>, message: &str, flags: Option, + ) -> Result { + self.stash_save2(stasher, Some(message), flags) + } + + /// Save the local modifications to a new stash. + /// unlike `stash_save` it allows to pass a null `message` + pub fn stash_save2( + &mut self, + stasher: &Signature<'_>, + message: Option<&str>, + flags: Option, ) -> Result { unsafe { let mut raw_oid = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], }; - let message = CString::new(message)?; + let message = crate::opt_cstr(message)?; let flags = flags.unwrap_or_else(StashFlags::empty); try_call!(raw::git_stash_save( &mut raw_oid, diff --git a/src/stash.rs b/src/stash.rs index ad4155e64e..f9f3927473 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -232,4 +232,30 @@ mod tests { assert!(count_stash(repo) == 1) }) } + + #[test] + fn test_stash_save2_msg_none() { + let (_td, mut repo) = repo_init(); + let signature = repo.signature().unwrap(); + + let p = Path::new(repo.workdir().unwrap()).join("file_b.txt"); + + fs::File::create(&p) + .unwrap() + .write("data".as_bytes()) + .unwrap(); + + repo.stash_save2(&signature, None, Some(StashFlags::INCLUDE_UNTRACKED)) + .unwrap(); + + let mut stash_name = String::new(); + repo.stash_foreach(|index, name, _oid| { + assert_eq!(index, 0); + stash_name = name.to_string(); + true + }) + .unwrap(); + + assert!(stash_name.starts_with("WIP on master:")); + } } From 83103a279dbed9a4724907a49c85a86ebab1782b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 19 May 2020 10:08:22 -0700 Subject: [PATCH 471/860] Bump to 0.13.6 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 61880f9363..4ea1347802 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.5" +version = "0.13.6" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 93e4da4f219ca1528d150c1b87c5c18524eac0a8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 19 May 2020 10:09:00 -0700 Subject: [PATCH 472/860] Bump libgit2-sys to 0.12.6 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 5e0c88dcbc..32f7eb7778 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.5+1.0.0" +version = "0.12.6+1.0.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 3fa6feb1a800078ce4686e5963fe24023a98a963 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 19 May 2020 10:09:41 -0700 Subject: [PATCH 473/860] Bump version req for libgit2-sys --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4ea1347802..960b2009ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.5" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.6" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From 622b6eedb52af76dd7b9e1375014c4aef94f7a77 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 3 Jun 2020 10:10:28 -0500 Subject: [PATCH 474/860] Update libgit2 submodule to master branch (#567) Pulls in a libgit2/libgit2#5536 to fix rust-lang/cargo#8258 --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 7d3c7057f0..86b85492b1 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 7d3c7057f0e774aecd6fc4ef8333e69e5c4873e0 +Subproject commit 86b85492b1bc8eeb9ff1af25b92877969f17833a From 07d2861cd0094f0e217c036952be612f365535c5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 3 Jun 2020 08:10:40 -0700 Subject: [PATCH 475/860] Bump to 0.12.7 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 32f7eb7778..ec755ab55c 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.6+1.0.0" +version = "0.12.7+1.0.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 6d771973296334a663e7f5a081386f77bfae2e15 Mon Sep 17 00:00:00 2001 From: Kinchkun Date: Thu, 11 Jun 2020 16:09:46 +0200 Subject: [PATCH 476/860] Add bindings for `git_branch_remote_name` (#568) --- libgit2-sys/lib.rs | 5 +++++ src/repo.rs | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index f3c189cab5..eca52a0423 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2577,6 +2577,11 @@ extern "C" { force: c_int, ) -> c_int; pub fn git_branch_name(out: *mut *const c_char, branch: *const git_reference) -> c_int; + pub fn git_branch_remote_name( + out: *mut git_buf, + repo: *mut git_repository, + refname: *const c_char, + ) -> c_int; pub fn git_branch_next( out: *mut *mut git_reference, out_type: *mut git_branch_t, diff --git a/src/repo.rs b/src/repo.rs index 437022ed2c..04faa92b1e 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2668,6 +2668,16 @@ impl Repository { } } + /// Find the remote name of a remote-tracking branch + pub fn branch_remote_name(&self, refname: &str) -> Result { + let refname = CString::new(refname)?; + unsafe { + let buf = Buf::new(); + try_call!(raw::git_branch_remote_name(buf.raw(), self.raw, refname)); + Ok(buf) + } + } + /// Retrieves the name of the reference supporting the remote tracking branch, /// given the name of a local branch reference. pub fn branch_upstream_name(&self, refname: &str) -> Result { From fc80b4e45ca34111ef269470a769f518dc9d13e8 Mon Sep 17 00:00:00 2001 From: Filip Gospodinov Date: Tue, 23 Jun 2020 15:39:45 +0200 Subject: [PATCH 477/860] Add bindings for git_revert{,_commit} (#573) --- libgit2-sys/lib.rs | 19 ++++++++++++ src/lib.rs | 2 ++ src/repo.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++ src/revert.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 src/revert.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index eca52a0423..0781d5315a 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -24,6 +24,7 @@ pub const GIT_ODB_BACKEND_VERSION: c_uint = 1; pub const GIT_REFDB_BACKEND_VERSION: c_uint = 1; pub const GIT_CHERRYPICK_OPTIONS_VERSION: c_uint = 1; pub const GIT_APPLY_OPTIONS_VERSION: c_uint = 1; +pub const GIT_REVERT_OPTIONS_VERSION: c_uint = 1; macro_rules! git_enum { (pub enum $name:ident { $($variants:tt)* }) => { @@ -1746,6 +1747,8 @@ pub struct git_cherrypick_options { pub checkout_opts: git_checkout_options, } +pub type git_revert_options = git_cherrypick_options; + pub type git_apply_delta_cb = Option c_int>; @@ -3684,6 +3687,22 @@ extern "C" { location: git_apply_location_t, options: *const git_apply_options, ) -> c_int; + + // revert + pub fn git_revert_options_init(opts: *mut git_revert_options, version: c_uint) -> c_int; + pub fn git_revert_commit( + out: *mut *mut git_index, + repo: *mut git_repository, + revert_commit: *mut git_commit, + our_commit: *mut git_commit, + mainline: c_uint, + merge_options: *const git_merge_options, + ) -> c_int; + pub fn git_revert( + repo: *mut git_repository, + commit: *mut git_commit, + given_opts: *const git_revert_options, + ) -> c_int; } pub fn init() { diff --git a/src/lib.rs b/src/lib.rs index 0513fcc03b..0a73722093 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,6 +118,7 @@ pub use crate::remote::{ pub use crate::remote_callbacks::{Credentials, RemoteCallbacks}; pub use crate::remote_callbacks::{TransportMessage, UpdateTips}; pub use crate::repo::{Repository, RepositoryInitOptions}; +pub use crate::revert::RevertOptions; pub use crate::revspec::Revspec; pub use crate::revwalk::Revwalk; pub use crate::signature::Signature; @@ -656,6 +657,7 @@ mod refspec; mod remote; mod remote_callbacks; mod repo; +mod revert; mod revspec; mod revwalk; mod signature; diff --git a/src/repo.rs b/src/repo.rs index 04faa92b1e..c635d6fdb5 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -16,6 +16,7 @@ use crate::stash::{stash_cb, StashApplyOptions, StashCbData}; use crate::string_array::StringArray; use crate::util::{self, path_to_repo_path, Binding}; use crate::CherrypickOptions; +use crate::RevertOptions; use crate::{ init, raw, AttrCheckFlags, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, Revspec, StashFlags, @@ -2721,6 +2722,46 @@ impl Repository { Ok(()) } } + + /// Reverts the given commit, producing changes in the index and working directory. + pub fn revert( + &self, + commit: &Commit<'_>, + options: Option<&mut RevertOptions<'_>>, + ) -> Result<(), Error> { + let raw_opts = options.map(|o| o.raw()); + let ptr_raw_opts = match raw_opts.as_ref() { + Some(v) => v, + None => 0 as *const _, + }; + unsafe { + try_call!(raw::git_revert(self.raw(), commit.raw(), ptr_raw_opts)); + Ok(()) + } + } + + /// Reverts the given commit against the given "our" commit, + /// producing an index that reflects the result of the revert. + pub fn revert_commit( + &self, + revert_commit: &Commit<'_>, + our_commit: &Commit<'_>, + mainline: u32, + options: Option<&MergeOptions>, + ) -> Result { + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_revert_commit( + &mut ret, + self.raw(), + revert_commit.raw(), + our_commit.raw(), + mainline, + options.map(|o| o.raw()) + )); + Ok(Binding::from_raw(ret)) + } + } } impl Binding for Repository { @@ -3460,4 +3501,35 @@ mod tests { assert!(!p1.exists()); assert!(p2.exists()); } + + #[test] + fn smoke_revert() { + let (_td, repo) = crate::test::repo_init(); + let foo_file = Path::new(repo.workdir().unwrap()).join("foo"); + assert!(!foo_file.exists()); + + let (oid1, _id) = crate::test::commit(&repo); + let commit1 = repo.find_commit(oid1).unwrap(); + t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); + assert!(foo_file.exists()); + + repo.revert(&commit1, None).unwrap(); + let id = repo.index().unwrap().write_tree().unwrap(); + let tree2 = repo.find_tree(id).unwrap(); + let sig = repo.signature().unwrap(); + repo.commit(Some("HEAD"), &sig, &sig, "commit 1", &tree2, &[&commit1]) + .unwrap(); + // reverting once removes `foo` file + assert!(!foo_file.exists()); + + let oid2 = repo.head().unwrap().target().unwrap(); + let commit2 = repo.find_commit(oid2).unwrap(); + repo.revert(&commit2, None).unwrap(); + let id = repo.index().unwrap().write_tree().unwrap(); + let tree3 = repo.find_tree(id).unwrap(); + repo.commit(Some("HEAD"), &sig, &sig, "commit 2", &tree3, &[&commit2]) + .unwrap(); + // reverting twice restores `foo` file + assert!(foo_file.exists()); + } } diff --git a/src/revert.rs b/src/revert.rs new file mode 100644 index 0000000000..55d702600e --- /dev/null +++ b/src/revert.rs @@ -0,0 +1,69 @@ +use std::mem; + +use crate::build::CheckoutBuilder; +use crate::merge::MergeOptions; +use crate::raw; +use std::ptr; + +/// Options to specify when reverting +pub struct RevertOptions<'cb> { + mainline: u32, + checkout_builder: Option>, + merge_opts: Option, +} + +impl<'cb> RevertOptions<'cb> { + /// Creates a default set of revert options + pub fn new() -> RevertOptions<'cb> { + RevertOptions { + mainline: 0, + checkout_builder: None, + merge_opts: None, + } + } + + /// Set the mainline value + /// + /// For merge commits, the "mainline" is treated as the parent. + pub fn mainline(&mut self, mainline: u32) -> &mut Self { + self.mainline = mainline; + self + } + + /// Set the checkout builder + pub fn checkout_builder(&mut self, cb: CheckoutBuilder<'cb>) -> &mut Self { + self.checkout_builder = Some(cb); + self + } + + /// Set the merge options + pub fn merge_opts(&mut self, merge_opts: MergeOptions) -> &mut Self { + self.merge_opts = Some(merge_opts); + self + } + + /// Obtain the raw struct + pub fn raw(&mut self) -> raw::git_revert_options { + unsafe { + let mut checkout_opts: raw::git_checkout_options = mem::zeroed(); + raw::git_checkout_init_options(&mut checkout_opts, raw::GIT_CHECKOUT_OPTIONS_VERSION); + if let Some(ref mut cb) = self.checkout_builder { + cb.configure(&mut checkout_opts); + } + + let mut merge_opts: raw::git_merge_options = mem::zeroed(); + raw::git_merge_init_options(&mut merge_opts, raw::GIT_MERGE_OPTIONS_VERSION); + if let Some(ref opts) = self.merge_opts { + ptr::copy(opts.raw(), &mut merge_opts, 1); + } + + let mut revert_opts: raw::git_revert_options = mem::zeroed(); + raw::git_revert_options_init(&mut revert_opts, raw::GIT_REVERT_OPTIONS_VERSION); + revert_opts.mainline = self.mainline; + revert_opts.checkout_opts = checkout_opts; + revert_opts.merge_opts = merge_opts; + + revert_opts + } + } +} From 627fd88f9b9f82716523d6f6ddf07b8f058eae0d Mon Sep 17 00:00:00 2001 From: Muld0r <3489913+muld0r@users.noreply.github.com> Date: Tue, 23 Jun 2020 08:31:14 -0700 Subject: [PATCH 478/860] Fix build.rs: only update libgit2 submodule (#574) (#575) If the user (for whatever reason) has their $CARGO_HOME in a git repository, and libgit2-sys is built in there (e.g. as a dependency of cargo), the build script will erroneously update all submodules in our parent directories. This wasn't intended - we only wish to update libgit2. This commit corrects this by specifying the current directory when calling git submodule update. Co-authored-by: Antonius Mulder --- libgit2-sys/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 54601bfbb9..09fb6e198f 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -17,7 +17,7 @@ fn main() { if !Path::new("libgit2/.git").exists() { let _ = Command::new("git") - .args(&["submodule", "update", "--init"]) + .args(&["submodule", "update", "--init", "libgit2"]) .status(); } From 49da72b2389928f544914387b130e61d5b50ef8f Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Thu, 25 Jun 2020 16:04:42 +0200 Subject: [PATCH 479/860] Transport: set libgit2's last_error (#576) (#577) Previously, the propagated error from a custom transport would always be the default "unknown error" as returned by `Error::last_error` if `git_error_last` returns a null pointer. The attached test case is rather trivial, but can be used to reproduce the old and new behaviour. --- src/transport.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/src/transport.rs b/src/transport.rs index c82eb1b27c..5b2d9748e4 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -249,7 +249,10 @@ extern "C" fn subtransport_action( let transport = &mut *(raw_transport as *mut RawSmartSubtransport); let obj = match transport.obj.action(url, action) { Ok(s) => s, - Err(e) => return e.raw_code() as c_int, + Err(e) => { + set_err(&e); + return e.raw_code() as c_int; + } }; *stream = mem::transmute(Box::new(RawSmartSubtransportStream { raw: raw::git_smart_subtransport_stream { @@ -309,7 +312,7 @@ extern "C" fn stream_read( match ret { Some(Ok(_)) => 0, Some(Err(e)) => unsafe { - set_err(&e); + set_err_io(&e); -2 }, None => -1, @@ -331,18 +334,23 @@ extern "C" fn stream_write( match ret { Some(Ok(())) => 0, Some(Err(e)) => unsafe { - set_err(&e); + set_err_io(&e); -2 }, None => -1, } } -unsafe fn set_err(e: &io::Error) { +unsafe fn set_err_io(e: &io::Error) { let s = CString::new(e.to_string()).unwrap(); raw::git_error_set_str(raw::GIT_ERROR_NET as c_int, s.as_ptr()); } +unsafe fn set_err(e: &Error) { + let s = CString::new(e.message()).unwrap(); + raw::git_error_set_str(e.raw_class() as c_int, s.as_ptr()); +} + // callback used by smart transports to free a `SmartSubtransportStream` // object. extern "C" fn stream_free(stream: *mut raw::git_smart_subtransport_stream) { @@ -350,3 +358,54 @@ extern "C" fn stream_free(stream: *mut raw::git_smart_subtransport_stream) { mem::transmute::<_, Box>(stream); }); } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ErrorClass, ErrorCode}; + use std::sync::Once; + + struct DummyTransport; + + impl SmartSubtransport for DummyTransport { + fn action( + &self, + _url: &str, + _service: Service, + ) -> Result, Error> { + Err(Error::from_str("bleh")) + } + + fn close(&self) -> Result<(), Error> { + Ok(()) + } + } + + #[test] + fn transport_error_propagates() { + static INIT: Once = Once::new(); + + unsafe { + INIT.call_once(|| { + register("dummy", move |remote| { + Transport::smart(&remote, true, DummyTransport) + }) + .unwrap(); + }) + } + + let (_td, repo) = crate::test::repo_init(); + t!(repo.remote("origin", "dummy://ball")); + + let mut origin = t!(repo.find_remote("origin")); + + match origin.fetch(&["master"], None, None) { + Ok(()) => unreachable!(), + Err(e) => { + assert_eq!(e.message(), "bleh"); + assert_eq!(e.code(), ErrorCode::GenericError); + assert_eq!(e.class(), ErrorClass::None); + } + } + } +} From 37ca8dd79648238aaf918be967bb4eab1db4ab73 Mon Sep 17 00:00:00 2001 From: Chris Pick Date: Thu, 25 Jun 2020 10:13:31 -0400 Subject: [PATCH 480/860] Add bindings for `git_remote_default_branch` (#572) (#578) Co-authored-by: Chris Pick --- libgit2-sys/lib.rs | 1 + src/remote.rs | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 0781d5315a..e27cbf578f 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2049,6 +2049,7 @@ extern "C" { remote: *mut git_remote, callbacks: *const git_remote_callbacks, ) -> c_int; + pub fn git_remote_default_branch(out: *mut git_buf, remote: *mut git_remote) -> c_int; // refspec pub fn git_refspec_direction(spec: *const git_refspec) -> git_direction; diff --git a/src/remote.rs b/src/remote.rs index b00f7e1c84..d2ea83fa01 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -9,7 +9,7 @@ use std::str; use crate::string_array::StringArray; use crate::util::Binding; -use crate::{raw, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec}; +use crate::{raw, Buf, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec}; use crate::{AutotagOption, Progress, RemoteCallbacks, Repository}; /// A structure representing a [remote][1] of a git repository. @@ -112,6 +112,20 @@ impl<'repo> Remote<'repo> { unsafe { crate::opt_bytes(self, raw::git_remote_pushurl(https://github.com/&*self.raw)) } } + /// Get the remote's default branch. + /// + /// The remote (or more exactly its transport) must have connected to the + /// remote repository. This default branch is available as soon as the + /// connection to the remote is initiated and it remains available after + /// disconnecting. + pub fn default_branch(&self) -> Result { + unsafe { + let buf = Buf::new(); + try_call!(raw::git_remote_default_branch(buf.raw(), self.raw)); + Ok(buf) + } + } + /// Open a connection to a remote. pub fn connect(&mut self, dir: Direction) -> Result<(), Error> { // TODO: can callbacks be exposed safely? @@ -576,6 +590,14 @@ impl<'repo, 'connection, 'cb> RemoteConnection<'repo, 'connection, 'cb> { pub fn list(&self) -> Result<&[RemoteHead<'_>], Error> { self.remote.list() } + + /// Get the remote's default branch. + /// + /// This default branch is available as soon as the connection to the remote + /// is initiated and it remains available after disconnecting. + pub fn default_branch(&self) -> Result { + self.remote.default_branch() + } } impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb> { From 31c151556d50783c9af48b2cff4e3289cd880b56 Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Thu, 25 Jun 2020 16:27:35 +0200 Subject: [PATCH 481/860] Add more ErrorCode variants (#580) --- src/error.rs | 4 ++++ src/lib.rs | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/error.rs b/src/error.rs index d093e5cf2b..3cf34c1560 100644 --- a/src/error.rs +++ b/src/error.rs @@ -111,6 +111,10 @@ impl Error { raw::GIT_EINVALID => super::ErrorCode::Invalid, raw::GIT_EUNCOMMITTED => super::ErrorCode::Uncommitted, raw::GIT_EDIRECTORY => super::ErrorCode::Directory, + raw::GIT_EMERGECONFLICT => super::ErrorCode::MergeConflict, + raw::GIT_EMISMATCH => super::ErrorCode::HashsumMismatch, + raw::GIT_EINDEXDIRTY => super::ErrorCode::IndexDirty, + raw::GIT_EAPPLYFAIL => super::ErrorCode::ApplyFail, _ => super::ErrorCode::GenericError, } } diff --git a/src/lib.rs b/src/lib.rs index 0a73722093..180dd47b18 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -143,6 +143,12 @@ macro_rules! is_bit_set { /// An enumeration of possible errors that can happen when working with a git /// repository. +// Note: We omit a few native error codes, as they are unlikely to be propagated +// to the library user. Currently: +// +// * GIT_EPASSTHROUGH +// * GIT_ITEROVER +// * GIT_RETRY #[derive(PartialEq, Eq, Clone, Debug, Copy)] pub enum ErrorCode { /// Generic error @@ -187,8 +193,16 @@ pub enum ErrorCode { Invalid, /// Uncommitted changes in index prevented operation Uncommitted, - /// Operation was not valid for a directory, + /// Operation was not valid for a directory Directory, + /// A merge conflict exists and cannot continue + MergeConflict, + /// Hashsum mismatch in object + HashsumMismatch, + /// Unsaved changes in the index would be overwritten + IndexDirty, + /// Patch application failed + ApplyFail, } /// An enumeration of possible categories of things that can have From 6aebca02f5afc7e71df16e12e5671d23b30a3795 Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Fri, 26 Jun 2020 16:04:42 +0200 Subject: [PATCH 482/860] Add modifiers for error code and class (#576) (#579) * Add modifiers for error code and class (#576) * Add `Error::new` constructor and make setters return unit * Cover new variants * Adjust transport test case --- src/error.rs | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ src/transport.rs | 13 +++---- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/src/error.rs b/src/error.rs index 3cf34c1560..4147d77391 100644 --- a/src/error.rs +++ b/src/error.rs @@ -16,6 +16,18 @@ pub struct Error { } impl Error { + /// Creates a new error. + /// + /// This is mainly intended for implementors of custom transports or + /// database backends, where it is desirable to propagate an [`Error`] + /// through `libgit2`. + pub fn new>(code: ErrorCode, class: ErrorClass, message: S) -> Self { + let mut err = Error::from_str(message.as_ref()); + err.set_code(code); + err.set_class(class); + err + } + /// Returns the last error that happened with the code specified by `code`. /// /// The `code` argument typically comes from the return value of a function @@ -119,6 +131,41 @@ impl Error { } } + /// Modify the error code associated with this error. + /// + /// This is mainly intended to be used by implementors of custom transports + /// or database backends, and should be used with care. + pub fn set_code(&mut self, code: ErrorCode) { + self.code = match code { + ErrorCode::GenericError => raw::GIT_ERROR, + ErrorCode::NotFound => raw::GIT_ENOTFOUND, + ErrorCode::Exists => raw::GIT_EEXISTS, + ErrorCode::Ambiguous => raw::GIT_EAMBIGUOUS, + ErrorCode::BufSize => raw::GIT_EBUFS, + ErrorCode::User => raw::GIT_EUSER, + ErrorCode::BareRepo => raw::GIT_EBAREREPO, + ErrorCode::UnbornBranch => raw::GIT_EUNBORNBRANCH, + ErrorCode::Unmerged => raw::GIT_EUNMERGED, + ErrorCode::NotFastForward => raw::GIT_ENONFASTFORWARD, + ErrorCode::InvalidSpec => raw::GIT_EINVALIDSPEC, + ErrorCode::Conflict => raw::GIT_ECONFLICT, + ErrorCode::Locked => raw::GIT_ELOCKED, + ErrorCode::Modified => raw::GIT_EMODIFIED, + ErrorCode::Auth => raw::GIT_EAUTH, + ErrorCode::Certificate => raw::GIT_ECERTIFICATE, + ErrorCode::Applied => raw::GIT_EAPPLIED, + ErrorCode::Peel => raw::GIT_EPEEL, + ErrorCode::Eof => raw::GIT_EEOF, + ErrorCode::Invalid => raw::GIT_EINVALID, + ErrorCode::Uncommitted => raw::GIT_EUNCOMMITTED, + ErrorCode::Directory => raw::GIT_EDIRECTORY, + ErrorCode::MergeConflict => raw::GIT_EMERGECONFLICT, + ErrorCode::HashsumMismatch => raw::GIT_EMISMATCH, + ErrorCode::IndexDirty => raw::GIT_EINDEXDIRTY, + ErrorCode::ApplyFail => raw::GIT_EAPPLYFAIL, + }; + } + /// Return the error class associated with this error. /// /// Error classes are in general mostly just informative. For example the @@ -165,6 +212,50 @@ impl Error { } } + /// Modify the error class associated with this error. + /// + /// This is mainly intended to be used by implementors of custom transports + /// or database backends, and should be used with care. + pub fn set_class(&mut self, class: ErrorClass) { + self.klass = match class { + ErrorClass::None => raw::GIT_ERROR_NONE, + ErrorClass::NoMemory => raw::GIT_ERROR_NOMEMORY, + ErrorClass::Os => raw::GIT_ERROR_OS, + ErrorClass::Invalid => raw::GIT_ERROR_INVALID, + ErrorClass::Reference => raw::GIT_ERROR_REFERENCE, + ErrorClass::Zlib => raw::GIT_ERROR_ZLIB, + ErrorClass::Repository => raw::GIT_ERROR_REPOSITORY, + ErrorClass::Config => raw::GIT_ERROR_CONFIG, + ErrorClass::Regex => raw::GIT_ERROR_REGEX, + ErrorClass::Odb => raw::GIT_ERROR_ODB, + ErrorClass::Index => raw::GIT_ERROR_INDEX, + ErrorClass::Object => raw::GIT_ERROR_OBJECT, + ErrorClass::Net => raw::GIT_ERROR_NET, + ErrorClass::Tag => raw::GIT_ERROR_TAG, + ErrorClass::Tree => raw::GIT_ERROR_TREE, + ErrorClass::Indexer => raw::GIT_ERROR_INDEXER, + ErrorClass::Ssl => raw::GIT_ERROR_SSL, + ErrorClass::Submodule => raw::GIT_ERROR_SUBMODULE, + ErrorClass::Thread => raw::GIT_ERROR_THREAD, + ErrorClass::Stash => raw::GIT_ERROR_STASH, + ErrorClass::Checkout => raw::GIT_ERROR_CHECKOUT, + ErrorClass::FetchHead => raw::GIT_ERROR_FETCHHEAD, + ErrorClass::Merge => raw::GIT_ERROR_MERGE, + ErrorClass::Ssh => raw::GIT_ERROR_SSH, + ErrorClass::Filter => raw::GIT_ERROR_FILTER, + ErrorClass::Revert => raw::GIT_ERROR_REVERT, + ErrorClass::Callback => raw::GIT_ERROR_CALLBACK, + ErrorClass::CherryPick => raw::GIT_ERROR_CHERRYPICK, + ErrorClass::Describe => raw::GIT_ERROR_DESCRIBE, + ErrorClass::Rebase => raw::GIT_ERROR_REBASE, + ErrorClass::Filesystem => raw::GIT_ERROR_FILESYSTEM, + ErrorClass::Patch => raw::GIT_ERROR_PATCH, + ErrorClass::Worktree => raw::GIT_ERROR_WORKTREE, + ErrorClass::Sha1 => raw::GIT_ERROR_SHA1, + ErrorClass::Http => raw::GIT_ERROR_HTTP, + } as c_int; + } + /// Return the raw error code associated with this error. pub fn raw_code(&self) -> raw::git_error_code { macro_rules! check( ($($e:ident,)*) => ( diff --git a/src/transport.rs b/src/transport.rs index 5b2d9748e4..5c5a1e6e8b 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -367,13 +367,18 @@ mod tests { struct DummyTransport; + // in lieu of lazy_static + fn dummy_error() -> Error { + Error::new(ErrorCode::Ambiguous, ErrorClass::Net, "bleh") + } + impl SmartSubtransport for DummyTransport { fn action( &self, _url: &str, _service: Service, ) -> Result, Error> { - Err(Error::from_str("bleh")) + Err(dummy_error()) } fn close(&self) -> Result<(), Error> { @@ -401,11 +406,7 @@ mod tests { match origin.fetch(&["master"], None, None) { Ok(()) => unreachable!(), - Err(e) => { - assert_eq!(e.message(), "bleh"); - assert_eq!(e.code(), ErrorCode::GenericError); - assert_eq!(e.class(), ErrorClass::None); - } + Err(e) => assert_eq!(e, dummy_error()), } } } From 4015887b56ae579a840d528955542370844772ef Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Mon, 29 Jun 2020 22:23:59 +0200 Subject: [PATCH 483/860] Add bindings for `git_config_multivar_iterator_new` (#583) * Add bindings for `git_config_multivar_iterator_new` * rustfmt --- libgit2-sys/lib.rs | 6 ++++++ src/config.rs | 50 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index e27cbf578f..06c82257b3 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2790,6 +2790,12 @@ extern "C" { ) -> c_int; pub fn git_config_snapshot(out: *mut *mut git_config, config: *mut git_config) -> c_int; pub fn git_config_entry_free(entry: *mut git_config_entry); + pub fn git_config_multivar_iterator_new( + out: *mut *mut git_config_iterator, + cfg: *const git_config, + name: *const c_char, + regexp: *const c_char, + ) -> c_int; // attr pub fn git_attr_get( diff --git a/src/config.rs b/src/config.rs index 8c2768ae58..edab9b3e02 100644 --- a/src/config.rs +++ b/src/config.rs @@ -289,6 +289,22 @@ impl Config { } } + /// Iterate over the values of a multivar + /// + /// If `regexp` is `Some`, then the iterator will only iterate over all + /// values which match the pattern. + pub fn multivar(&self, name: &str, regexp: Option<&str>) -> Result, Error> { + let mut ret = ptr::null_mut(); + let name = CString::new(name)?; + let regexp = regexp.map(CString::new).transpose()?; + unsafe { + try_call!(raw::git_config_multivar_iterator_new( + &mut ret, &*self.raw, name, regexp + )); + Ok(Binding::from_raw(ret)) + } + } + /// Open the global/XDG configuration file according to git's rules /// /// Git allows you to store your global configuration at `$HOME/.config` or @@ -602,19 +618,43 @@ mod tests { let mut cfg = Config::open(&path).unwrap(); cfg.set_multivar("foo.bar", "^$", "baz").unwrap(); cfg.set_multivar("foo.bar", "^$", "qux").unwrap(); + cfg.set_multivar("foo.bar", "^$", "quux").unwrap(); + cfg.set_multivar("foo.baz", "^$", "oki").unwrap(); + + // `entries` filters by name + let mut entries: Vec = cfg + .entries(Some("foo.bar")) + .unwrap() + .into_iter() + .map(|entry| entry.unwrap().value().unwrap().into()) + .collect(); + entries.sort(); + assert_eq!(entries, ["baz", "quux", "qux"]); + + // which is the same as `multivar` without a regex + let mut multivals: Vec = cfg + .multivar("foo.bar", None) + .unwrap() + .into_iter() + .map(|entry| entry.unwrap().value().unwrap().into()) + .collect(); + multivals.sort(); + assert_eq!(multivals, entries); - let mut values: Vec = cfg - .entries(None) + // yet _with_ a regex, `multivar` filters by value + let mut quxish: Vec = cfg + .multivar("foo.bar", Some("qu.*x")) .unwrap() .into_iter() .map(|entry| entry.unwrap().value().unwrap().into()) .collect(); - values.sort(); - assert_eq!(values, ["baz", "qux"]); + quxish.sort(); + assert_eq!(quxish, ["quux", "qux"]); cfg.remove_multivar("foo.bar", ".*").unwrap(); - assert_eq!(cfg.entries(None).unwrap().count(), 0); + assert_eq!(cfg.entries(Some("foo.bar")).unwrap().count(), 0); + assert_eq!(cfg.multivar("foo.bar", None).unwrap().count(), 0); } #[test] From 5f1d3b14e459c6db88adaa8720200d0466fa3b93 Mon Sep 17 00:00:00 2001 From: Chris Pick Date: Mon, 6 Jul 2020 11:00:09 -0400 Subject: [PATCH 484/860] Add bindings for `git_refspec_transform()` and `git_refspec_rtransform()` (#584) Co-authored-by: Chris Pick --- libgit2-sys/lib.rs | 10 ++++++++++ src/refspec.rs | 30 +++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 06c82257b3..813e905d05 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2059,6 +2059,16 @@ extern "C" { pub fn git_refspec_src_matches(spec: *const git_refspec, refname: *const c_char) -> c_int; pub fn git_refspec_force(spec: *const git_refspec) -> c_int; pub fn git_refspec_string(spec: *const git_refspec) -> *const c_char; + pub fn git_refspec_transform( + out: *mut git_buf, + spec: *const git_refspec, + name: *const c_char, + ) -> c_int; + pub fn git_refspec_rtransform( + out: *mut git_buf, + spec: *const git_refspec, + name: *const c_char, + ) -> c_int; // strarray pub fn git_strarray_free(array: *mut git_strarray); diff --git a/src/refspec.rs b/src/refspec.rs index 79e529d6c8..dec71c3230 100644 --- a/src/refspec.rs +++ b/src/refspec.rs @@ -3,7 +3,7 @@ use std::marker; use std::str; use crate::util::Binding; -use crate::{raw, Direction}; +use crate::{raw, Buf, Direction, Error}; /// A structure to represent a git [refspec][1]. /// @@ -77,6 +77,34 @@ impl<'remote> Refspec<'remote> { pub fn bytes(&self) -> &[u8] { unsafe { crate::opt_bytes(self, raw::git_refspec_string(self.raw)).unwrap() } } + + /// Transform a reference to its target following the refspec's rules + pub fn transform(&self, name: &str) -> Result { + let name = CString::new(name).unwrap(); + unsafe { + let buf = Buf::new(); + try_call!(raw::git_refspec_transform( + buf.raw(), + self.raw, + name.as_ptr() + )); + Ok(buf) + } + } + + /// Transform a target reference to its source reference following the refspec's rules + pub fn rtransform(&self, name: &str) -> Result { + let name = CString::new(name).unwrap(); + unsafe { + let buf = Buf::new(); + try_call!(raw::git_refspec_rtransform( + buf.raw(), + self.raw, + name.as_ptr() + )); + Ok(buf) + } + } } impl<'remote> Binding for Refspec<'remote> { From 9f5cef63a3b6de6f8f51e5fbdb130b8d21afd6e0 Mon Sep 17 00:00:00 2001 From: Peter Williams Date: Tue, 7 Jul 2020 13:42:50 -0400 Subject: [PATCH 485/860] Document IndexEntry.path a bit. (#586) --- src/index.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/index.rs b/src/index.rs index 2ab48b8200..1bee22ec17 100644 --- a/src/index.rs +++ b/src/index.rs @@ -66,6 +66,21 @@ pub struct IndexEntry { pub id: Oid, pub flags: u16, pub flags_extended: u16, + + /// The path of this index entry as a byte vector. Regardless of the + /// current platform, the directory separator is an ASCII forward slash + /// (`0x2F`). There are no terminating or internal NUL characters, and no + /// trailing slashes. Most of the time, paths will be valid utf-8 — but + /// not always. For more information on the path storage format, see + /// [these git docs][git-index-docs]. Note that libgit2 will take care of + /// handling the prefix compression mentioned there. + /// + /// [git-index-docs]: https://github.com/git/git/blob/a08a83db2bf27f015bec9a435f6d73e223c21c5e/Documentation/technical/index-format.txt#L107-L124 + /// + /// You can turn this value into a `std::ffi::CString` with + /// `CString::new(&entry.path[..]).unwrap()`. To turn a reference into a + /// `&std::path::Path`, see the `bytes2path()` function in the private, + /// internal `util` module in this crate’s source code. pub path: Vec, } From a3e129e2e01e879ca1be975cd512b0ba03ddac09 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Mon, 20 Jul 2020 22:49:19 +0200 Subject: [PATCH 486/860] add tag_foreach to repo (#594) (#595) * add tag_foreach to repo (#594) * switch to raw bytes for tag name --- src/lib.rs | 1 + src/repo.rs | 21 +++++++++++++++ src/tagforeach.rs | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 src/tagforeach.rs diff --git a/src/lib.rs b/src/lib.rs index 180dd47b18..262486c61e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -679,6 +679,7 @@ mod stash; mod status; mod submodule; mod tag; +mod tagforeach; mod time; mod tree; mod treebuilder; diff --git a/src/repo.rs b/src/repo.rs index c635d6fdb5..0a8fc088c8 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -14,6 +14,7 @@ use crate::diff::{ use crate::oid_array::OidArray; use crate::stash::{stash_cb, StashApplyOptions, StashCbData}; use crate::string_array::StringArray; +use crate::tagforeach::{tag_foreach_cb, TagForeachCB, TagForeachData}; use crate::util::{self, path_to_repo_path, Binding}; use crate::CherrypickOptions; use crate::RevertOptions; @@ -1731,6 +1732,26 @@ impl Repository { } } + /// iterate over all tags calling `cb` on each. + /// the callback is provided the tag id and name + pub fn tag_foreach(&self, cb: T) -> Result<(), Error> + where + T: FnMut(Oid, &[u8]) -> bool, + { + let mut data = TagForeachData { + cb: Box::new(cb) as TagForeachCB<'_>, + }; + + unsafe { + raw::git_tag_foreach( + self.raw, + Some(tag_foreach_cb), + (&mut data) as *mut _ as *mut _, + ); + } + Ok(()) + } + /// Updates files in the index and the working tree to match the content of /// the commit pointed at by HEAD. pub fn checkout_head(&self, opts: Option<&mut CheckoutBuilder<'_>>) -> Result<(), Error> { diff --git a/src/tagforeach.rs b/src/tagforeach.rs new file mode 100644 index 0000000000..c8018a44cf --- /dev/null +++ b/src/tagforeach.rs @@ -0,0 +1,69 @@ +//! git_tag_foreach support +//! see original: https://libgit2.org/libgit2/#HEAD/group/tag/git_tag_foreach + +use crate::{panic, raw, util::Binding, Oid}; +use libc::{c_char, c_int}; +use raw::git_oid; +use std::ffi::{c_void, CStr}; + +/// boxed callback type +pub(crate) type TagForeachCB<'a> = Box bool + 'a>; + +/// helper type to be able to pass callback to payload +pub(crate) struct TagForeachData<'a> { + /// callback + pub(crate) cb: TagForeachCB<'a>, +} + +/// c callback forwarding to rust callback inside `TagForeachData` +/// see original: https://libgit2.org/libgit2/#HEAD/group/callback/git_tag_foreach_cb +pub(crate) extern "C" fn tag_foreach_cb( + name: *const c_char, + oid: *mut git_oid, + payload: *mut c_void, +) -> c_int { + panic::wrap(|| unsafe { + let id: Oid = Binding::from_raw(oid as *const _); + + let name = CStr::from_ptr(name); + let name = name.to_bytes(); + + let payload = &mut *(payload as *mut TagForeachData<'_>); + let cb = &mut payload.cb; + + let res = cb(id, name); + + if res { + 0 + } else { + -1 + } + }) + .unwrap_or(-1) +} + +#[cfg(test)] +mod tests { + + #[test] + fn smoke() { + let (_td, repo) = crate::test::repo_init(); + let head = repo.head().unwrap(); + let id = head.target().unwrap(); + assert!(repo.find_tag(id).is_err()); + + let obj = repo.find_object(id, None).unwrap(); + let sig = repo.signature().unwrap(); + let tag_id = repo.tag("foo", &obj, &sig, "msg", false).unwrap(); + + let mut tags = Vec::new(); + repo.tag_foreach(|id, name| { + tags.push((id, String::from_utf8(name.into()).unwrap())); + true + }) + .unwrap(); + + assert_eq!(tags[0].0, tag_id); + assert_eq!(tags[0].1, "refs/tags/foo"); + } +} From e36281d3815fc3cb082fb5ea5096a391fd4ce977 Mon Sep 17 00:00:00 2001 From: "Kartikaya Gupta (kats)" Date: Mon, 20 Jul 2020 16:50:41 -0400 Subject: [PATCH 487/860] Expose the mempack backend in git2 (#593) This also adds a method to override the ODB on the repository, which is also exposed by libgit2. This allows the user to create a new ODB, configure it, and install it on the repository. --- src/lib.rs | 2 ++ src/mempack.rs | 49 +++++++++++++++++++++++++++++ src/odb.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++++++- src/repo.rs | 8 +++++ 4 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 src/mempack.rs diff --git a/src/lib.rs b/src/lib.rs index 262486c61e..0939ccd2b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,6 +97,7 @@ pub use crate::index::{ Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath, }; pub use crate::indexer::{IndexerProgress, Progress}; +pub use crate::mempack::Mempack; pub use crate::merge::{AnnotatedCommit, MergeOptions}; pub use crate::message::{message_prettify, DEFAULT_COMMENT_CHAR}; pub use crate::note::{Note, Notes}; @@ -654,6 +655,7 @@ mod diff; mod error; mod index; mod indexer; +mod mempack; mod merge; mod message; mod note; diff --git a/src/mempack.rs b/src/mempack.rs new file mode 100644 index 0000000000..2de9a27813 --- /dev/null +++ b/src/mempack.rs @@ -0,0 +1,49 @@ +use std::marker; + +use crate::util::Binding; +use crate::{raw, Buf, Error, Odb, Repository}; + +/// A structure to represent a mempack backend for the object database. The +/// Mempack is bound to the Odb that it was created from, and cannot outlive +/// that Odb. +pub struct Mempack<'odb> { + raw: *mut raw::git_odb_backend, + _marker: marker::PhantomData<&'odb Odb<'odb>>, +} + +impl<'odb> Binding for Mempack<'odb> { + type Raw = *mut raw::git_odb_backend; + + unsafe fn from_raw(raw: *mut raw::git_odb_backend) -> Mempack<'odb> { + Mempack { + raw: raw, + _marker: marker::PhantomData, + } + } + + fn raw(&self) -> *mut raw::git_odb_backend { + self.raw + } +} + +// We don't need to implement `Drop` for Mempack because it is owned by the +// odb to which it is attached, and that will take care of freeing the mempack +// and associated memory. + +impl<'odb> Mempack<'odb> { + /// Dumps the contents of the mempack into the provided buffer. + pub fn dump(&self, repo: &Repository, buf: &mut Buf) -> Result<(), Error> { + unsafe { + try_call!(raw::git_mempack_dump(buf.raw(), repo.raw(), self.raw)); + } + Ok(()) + } + + /// Clears all data in the mempack. + pub fn reset(&self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_mempack_reset(self.raw)); + } + Ok(()) + } +} diff --git a/src/odb.rs b/src/odb.rs index 9ee034ac21..de3b42659a 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -10,7 +10,7 @@ use libc::{c_char, c_int, c_void, size_t}; use crate::panic; use crate::util::Binding; -use crate::{raw, Error, IndexerProgress, Object, ObjectType, Oid, Progress}; +use crate::{raw, Error, IndexerProgress, Mempack, Object, ObjectType, Oid, Progress}; /// A structure to represent a git object database pub struct Odb<'repo> { @@ -218,6 +218,47 @@ impl<'repo> Odb<'repo> { Ok(()) } } + + /// Create a new mempack backend, and add it to this odb with the given + /// priority. Higher values give the backend higher precedence. The default + /// loose and pack backends have priorities 1 and 2 respectively (hard-coded + /// in libgit2). A reference to the new mempack backend is returned on + /// success. The lifetime of the backend must be contained within the + /// lifetime of this odb, since deletion of the odb will also result in + /// deletion of the mempack backend. + /// + /// Here is an example that fails to compile because it tries to hold the + /// mempack reference beyond the odb's lifetime: + /// + /// ```compile_fail + /// use git2::Odb; + /// let mempack = { + /// let odb = Odb::new().unwrap(); + /// odb.add_new_mempack_backend(1000).unwrap() + /// }; + /// ``` + pub fn add_new_mempack_backend<'odb>( + &'odb self, + priority: i32, + ) -> Result, Error> { + unsafe { + let mut mempack = ptr::null_mut(); + // The mempack backend object in libgit2 is only ever freed by an + // odb that has the backend in its list. So to avoid potentially + // leaking the mempack backend, this API ensures that the backend + // is added to the odb before returning it. The lifetime of the + // mempack is also bound to the lifetime of the odb, so that users + // can't end up with a dangling reference to a mempack object that + // was actually freed when the odb was destroyed. + try_call!(raw::git_mempack_new(&mut mempack)); + try_call!(raw::git_odb_add_backend( + self.raw, + mempack, + priority as c_int + )); + Ok(Mempack::from_raw(mempack)) + } + } } /// An object from the Object Database. @@ -626,4 +667,45 @@ mod tests { } assert_eq!(progress_called, true); } + + #[test] + fn write_with_mempack() { + use crate::{Buf, ResetType}; + use std::io::Write; + use std::path::Path; + + // Create a repo, add a mempack backend + let (_td, repo) = crate::test::repo_init(); + let odb = repo.odb().unwrap(); + let mempack = odb.add_new_mempack_backend(1000).unwrap(); + + // Sanity check that foo doesn't exist initially + let foo_file = Path::new(repo.workdir().unwrap()).join("foo"); + assert!(!foo_file.exists()); + + // Make a commit that adds foo. This writes new stuff into the mempack + // backend. + let (oid1, _id) = crate::test::commit(&repo); + let commit1 = repo.find_commit(oid1).unwrap(); + t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); + assert!(foo_file.exists()); + + // Dump the mempack modifications into a buf, and reset it. This "erases" + // commit-related objects from the repository. Ensure the commit appears + // to have become invalid, by checking for failure in `reset --hard`. + let mut buf = Buf::new(); + mempack.dump(&repo, &mut buf).unwrap(); + mempack.reset().unwrap(); + assert!(repo + .reset(commit1.as_object(), ResetType::Hard, None) + .is_err()); + + // Write the buf into a packfile in the repo. This brings back the + // missing objects, and we verify everything is good again. + let mut packwriter = odb.packwriter().unwrap(); + packwriter.write(&buf).unwrap(); + packwriter.commit().unwrap(); + t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); + assert!(foo_file.exists()); + } } diff --git a/src/repo.rs b/src/repo.rs index 0a8fc088c8..5559d60935 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1055,6 +1055,14 @@ impl Repository { } } + /// Override the object database for this repository + pub fn set_odb(&self, odb: &Odb<'_>) -> Result<(), Error> { + unsafe { + try_call!(raw::git_repository_set_odb(self.raw(), odb.raw())); + } + Ok(()) + } + /// Create a new branch pointing at a target commit /// /// A new direct reference will be created pointing to this target commit. From f89075b297679ec1c450993675c15b47a4478480 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 Jul 2020 07:00:24 -0700 Subject: [PATCH 488/860] Bump versions Also bump submodule to the official 1.0.1 --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/libgit2 | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 960b2009ad..eb0dc23b1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.6" +version = "0.13.7" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.6" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.7" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index ec755ab55c..e3b01d05d4 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.7+1.0.0" +version = "0.12.8+1.0.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 86b85492b1..0ced29612d 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 86b85492b1bc8eeb9ff1af25b92877969f17833a +Subproject commit 0ced29612dacb67eefe0c562a5c1d3aab21cce96 From c19cc75de917447825d18bba8d8d9f81bda07162 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 Jul 2020 07:01:26 -0700 Subject: [PATCH 489/860] Depend on latest libgit2-sys --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index eb0dc23b1f..09dfc36ba3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.7" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.8" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } From e245130e5ae243059d0582b023a0649ece9cb647 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 Jul 2020 15:48:24 -0700 Subject: [PATCH 490/860] Re-update libgit2 to master branch Forgot that we were ahead of 1.0.1! --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 0ced29612d..a83fd51078 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 0ced29612dacb67eefe0c562a5c1d3aab21cce96 +Subproject commit a83fd5107879d18b31ff8173ea062136256321be From 892dc1a9a1c9b724533fa4802f7581b4b6b630da Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 Jul 2020 15:48:47 -0700 Subject: [PATCH 491/860] Bump versions --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 09dfc36ba3..6620bfd2c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.7" +version = "0.13.8" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.8" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.9" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index e3b01d05d4..ef51d0ee34 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.8+1.0.1" +version = "0.12.9+1.0.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From a9d86f47021886147d46e2a8d9248f94edc45321 Mon Sep 17 00:00:00 2001 From: Patrick Wang Date: Wed, 22 Jul 2020 21:47:31 +0800 Subject: [PATCH 492/860] Add bindings for `git_index_version()` and `git_index_set_version()` (#597) --- libgit2-sys/lib.rs | 2 ++ src/index.rs | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 813e905d05..19759e396b 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2619,6 +2619,8 @@ extern "C" { ) -> c_int; // index + pub fn git_index_version(index: *mut git_index) -> c_uint; + pub fn git_index_set_version(index: *mut git_index, version: c_uint) -> c_int; pub fn git_index_add(index: *mut git_index, entry: *const git_index_entry) -> c_int; pub fn git_index_add_all( index: *mut git_index, diff --git a/src/index.rs b/src/index.rs index 1bee22ec17..5612f43a30 100644 --- a/src/index.rs +++ b/src/index.rs @@ -117,6 +117,27 @@ impl Index { } } + /// Get index on-disk version. + /// + /// Valid return values are 2, 3, or 4. If 3 is returned, an index + /// with version 2 may be written instead, if the extension data in + /// version 3 is not necessary. + pub fn version(&self) -> u32 { + unsafe { raw::git_index_version(self.raw) } + } + + /// Set index on-disk version. + /// + /// Valid values are 2, 3, or 4. If 2 is given, git_index_write may + /// write an index with version 3 instead, if necessary to accurately + /// represent the index. + pub fn set_version(&mut self, version: u32) -> Result<(), Error> { + unsafe { + try_call!(raw::git_index_set_version(self.raw, version)); + } + Ok(()) + } + /// Add or update an index entry from an in-memory struct /// /// If a previous index entry exists that has the same path and stage as the From 97a855443f5678b6f71db59cfaf03b857ec38fac Mon Sep 17 00:00:00 2001 From: lhchavez Date: Thu, 6 Aug 2020 07:34:12 -0700 Subject: [PATCH 493/860] Make the calls to `crate::init()` consistent (#604) This change makes the calls to `crate::init()` in `src/repo.rs` all use the full namespace for consistency. This makes no difference, but makes it easier to find (e.g. through a simple `grep`) which functions eventually invoke `git_libgit2_init()`. --- src/repo.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index 5559d60935..2854d81281 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -19,8 +19,8 @@ use crate::util::{self, path_to_repo_path, Binding}; use crate::CherrypickOptions; use crate::RevertOptions; use crate::{ - init, raw, AttrCheckFlags, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, - Revspec, StashFlags, + raw, AttrCheckFlags, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, Revspec, + StashFlags, }; use crate::{ AnnotatedCommit, MergeAnalysis, MergeOptions, MergePreference, SubmoduleIgnore, SubmoduleStatus, @@ -65,7 +65,7 @@ impl Repository { /// /// The path can point to either a normal or bare repository. pub fn open>(path: P) -> Result { - init(); + crate::init(); // Normal file path OK (does not need Windows conversion). let path = path.as_ref().into_c_string()?; let mut ret = ptr::null_mut(); @@ -79,7 +79,7 @@ impl Repository { /// /// The path can point to only a bare repository. pub fn open_bare>(path: P) -> Result { - init(); + crate::init(); // Normal file path OK (does not need Windows conversion). let path = path.as_ref().into_c_string()?; let mut ret = ptr::null_mut(); @@ -95,7 +95,7 @@ impl Repository { /// With `$GIT_DIR` unset, this will search for a repository starting in /// the current directory. pub fn open_from_env() -> Result { - init(); + crate::init(); let mut ret = ptr::null_mut(); let flags = raw::GIT_REPOSITORY_OPEN_FROM_ENV; unsafe { @@ -145,7 +145,7 @@ impl Repository { O: AsRef, I: IntoIterator, { - init(); + crate::init(); // Normal file path OK (does not need Windows conversion). let path = path.as_ref().into_c_string()?; let ceiling_dirs_os = env::join_paths(ceiling_dirs)?; @@ -168,7 +168,7 @@ impl Repository { /// until it finds a repository. pub fn discover>(path: P) -> Result { // TODO: this diverges significantly from the libgit2 API - init(); + crate::init(); let buf = Buf::new(); // Normal file path OK (does not need Windows conversion). let path = path.as_ref().into_c_string()?; @@ -206,7 +206,7 @@ impl Repository { path: P, opts: &RepositoryInitOptions, ) -> Result { - init(); + crate::init(); // Normal file path OK (does not need Windows conversion). let path = path.as_ref().into_c_string()?; let mut ret = ptr::null_mut(); @@ -238,7 +238,7 @@ impl Repository { /// Attempt to wrap an object database as a repository. pub fn from_odb(odb: Odb<'_>) -> Result { - init(); + crate::init(); let mut ret = ptr::null_mut(); unsafe { try_call!(raw::git_repository_wrap_odb(&mut ret, odb.raw())); From c2a26133731d152f67a4fb11b35c4e139441e60c Mon Sep 17 00:00:00 2001 From: YOSHIOKA Takuma Date: Mon, 17 Aug 2020 23:55:36 +0900 Subject: [PATCH 494/860] Use cc 1.0.43 or later (#608) cc-1.0.42 should not be used as minimal dependency verison, because it could hang on some environment during the build. --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index ef51d0ee34..3a067993a4 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -23,7 +23,7 @@ libz-sys = "1.0.22" [build-dependencies] pkg-config = "0.3.7" -cc = { version = "1.0.42", features = ['parallel'] } +cc = { version = "1.0.43", features = ['parallel'] } [target.'cfg(unix)'.dependencies] openssl-sys = { version = "0.9", optional = true } From f6e90a79f6521427a5067c1ca7a1c519bcbaebb6 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 18 Aug 2020 04:30:13 -0700 Subject: [PATCH 495/860] Add support for zlib-ng Depend on libz-sys 1.1.0, and provide "zlib-ng-compat" features to opt into zlib-ng. Use feature dependencies to ensure that either all C libraries opt in or none do. This provides a substantial performance boost when compressing or decompressing objects in a git2 repository. --- Cargo.toml | 3 ++- git2-curl/Cargo.toml | 5 ++++- libgit2-sys/Cargo.toml | 12 +++++++++--- libgit2-sys/build.rs | 16 ++++++++++------ 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6620bfd2c8..35925e35bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.9" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.10" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } @@ -39,6 +39,7 @@ ssh = ["libgit2-sys/ssh"] https = ["libgit2-sys/https", "openssl-sys", "openssl-probe"] vendored-openssl = ["openssl-sys/vendored"] ssh_key_from_memory = ["libgit2-sys/ssh_key_from_memory"] +zlib-ng-compat = ["libgit2-sys/zlib-ng-compat"] [workspace] members = ["systest", "git2-curl"] diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index d34e76aa40..8e53e6ae81 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -13,7 +13,7 @@ Intended to be used with the git2 crate. edition = "2018" [dependencies] -curl = "0.4" +curl = "0.4.33" url = "2.0" log = "0.4" git2 = { path = "..", version = "0.13", default-features = false } @@ -24,6 +24,9 @@ conduit = "0.8" conduit-git-http-backend = "0.8" tempfile = "3.0" +[features] +zlib-ng-compat = ["git2/zlib-ng-compat", "curl/zlib-ng-compat"] + [[test]] name = "all" harness = false diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 3a067993a4..9cc5fb56f9 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.9+1.0.1" +version = "0.12.10+1.0.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" @@ -18,8 +18,8 @@ path = "lib.rs" [dependencies] libc = "0.2" -libssh2-sys = { version = "0.2.11", optional = true } -libz-sys = "1.0.22" +libssh2-sys = { version = "0.2.19", optional = true } +libz-sys = { version = "1.1.0", default-features = false, features = ["libc"] } [build-dependencies] pkg-config = "0.3.7" @@ -32,3 +32,9 @@ openssl-sys = { version = "0.9", optional = true } ssh = ["libssh2-sys"] https = ["openssl-sys"] ssh_key_from_memory = [] +# Cargo does not support requiring features on an optional dependency without +# requiring the dependency. Rather than introduce additional complexity, we +# just require libssh2 when using zlib-ng-compat. This will require building +# libssh2, but it will not add code to the final binary without the "ssh" +# feature enabled. +zlib-ng-compat = ["libz-sys/zlib-ng", "libssh2-sys/zlib-ng-compat"] diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 09fb6e198f..178d931cf9 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -6,13 +6,17 @@ use std::process::Command; fn main() { let https = env::var("CARGO_FEATURE_HTTPS").is_ok(); let ssh = env::var("CARGO_FEATURE_SSH").is_ok(); - - let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.atleast_version("1.0.0").probe("libgit2") { - for include in &lib.include_paths { - println!("cargo:root={}", include.display()); + let zlib_ng_compat = env::var("CARGO_FEATURE_ZLIB_NG_COMPAT").is_ok(); + + // To use zlib-ng in zlib-compat mode, we have to build libgit2 ourselves. + if !zlib_ng_compat { + let mut cfg = pkg_config::Config::new(); + if let Ok(lib) = cfg.atleast_version("1.0.0").probe("libgit2") { + for include in &lib.include_paths { + println!("cargo:root={}", include.display()); + } + return; } - return; } if !Path::new("libgit2/.git").exists() { From a56acdc68af15153f04aad40b1eacdf74f744ef5 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 18 Aug 2020 20:26:57 -0700 Subject: [PATCH 496/860] Fix dangling pointer in format_email. --- src/diff.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/diff.rs b/src/diff.rs index 412667ea2e..2718cf8d0f 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -266,7 +266,8 @@ impl<'repo> Diff<'repo> { message = &message[summary.len()..]; raw_opts.patch_no = patch_no; raw_opts.total_patches = total_patches; - raw_opts.id = commit.id().raw(); + let id = commit.id(); + raw_opts.id = id.raw(); raw_opts.summary = summary.as_ptr() as *const _; raw_opts.body = message.as_ptr() as *const _; raw_opts.author = commit.author().raw(); From d7757f170d098517a24a76a7982da3f897c0255b Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 19 Aug 2020 12:42:55 -0700 Subject: [PATCH 497/860] Bump versions --- Cargo.toml | 2 +- git2-curl/Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 35925e35bb..ad6d54fd84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.8" +version = "0.13.9" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 8e53e6ae81..6b68488e3d 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2-curl" -version = "0.14.0" +version = "0.14.1" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 9cc5fb56f9..745fc9d957 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.10+1.0.1" +version = "0.12.11+1.0.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 20b17131062dcd311f4b1c01458d59c95fc35d46 Mon Sep 17 00:00:00 2001 From: JP Sugarbroad Date: Sun, 16 Aug 2020 01:44:32 -0700 Subject: [PATCH 498/860] Add git2::opts::strict_hash_verification --- libgit2-sys/lib.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/opts.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/opts.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 19759e396b..a1f07d7b05 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1778,6 +1778,42 @@ git_enum! { } } +git_enum! { + pub enum git_libgit2_opt_t { + GIT_OPT_GET_MWINDOW_SIZE = 0, + GIT_OPT_SET_MWINDOW_SIZE, + GIT_OPT_GET_MWINDOW_MAPPED_LIMIT, + GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, + GIT_OPT_GET_SEARCH_PATH, + GIT_OPT_SET_SEARCH_PATH, + GIT_OPT_SET_CACHE_OBJECT_LIMIT, + GIT_OPT_SET_CACHE_MAX_SIZE, + GIT_OPT_ENABLE_CACHING, + GIT_OPT_GET_CACHED_MEMORY, + GIT_OPT_GET_TEMPLATE_PATH, + GIT_OPT_SET_TEMPLATE_PATH, + GIT_OPT_SET_SSL_CERT_LOCATIONS, + GIT_OPT_SET_USER_AGENT, + GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, + GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, + GIT_OPT_SET_SSL_CIPHERS, + GIT_OPT_GET_USER_AGENT, + GIT_OPT_ENABLE_OFS_DELTA, + GIT_OPT_ENABLE_FSYNC_GITDIR, + GIT_OPT_GET_WINDOWS_SHAREMODE, + GIT_OPT_SET_WINDOWS_SHAREMODE, + GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, + GIT_OPT_SET_ALLOCATOR, + GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY, + GIT_OPT_GET_PACK_MAX_OBJECTS, + GIT_OPT_SET_PACK_MAX_OBJECTS, + GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS, + GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, + GIT_OPT_GET_MWINDOW_FILE_LIMIT, + GIT_OPT_SET_MWINDOW_FILE_LIMIT, + } +} + extern "C" { // threads pub fn git_libgit2_init() -> c_int; @@ -3722,6 +3758,8 @@ extern "C" { commit: *mut git_commit, given_opts: *const git_revert_options, ) -> c_int; + + pub fn git_libgit2_opts(option: c_int, ...) -> c_int; } pub fn init() { diff --git a/src/lib.rs b/src/lib.rs index 0939ccd2b6..1ce760ca7a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -638,6 +638,7 @@ mod util; pub mod build; pub mod cert; pub mod oid_array; +pub mod opts; pub mod string_array; pub mod transport; diff --git a/src/opts.rs b/src/opts.rs new file mode 100644 index 0000000000..3ca558baec --- /dev/null +++ b/src/opts.rs @@ -0,0 +1,26 @@ +//! Bindings to libgit2's git_libgit2_opts function. + +use crate::raw; + +/// Controls whether or not libgit2 will verify that objects loaded have the +/// expected hash. Enabled by default, but disabling this can significantly +/// improve performance at the cost of correctness. +pub fn strict_hash_verification(enabled: bool) { + let error = unsafe { + raw::git_libgit2_opts( + raw::GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION as libc::c_int, + if enabled { 1 } else { 0 } as libc::c_int, + ) + }; + // This function cannot actually fail, but the function has an error return + // for other options that can. + debug_assert!(error >= 0); +} + +#[cfg(test)] +mod test { + #[test] + fn smoke() { + super::strict_hash_verification(false); + } +} From c498af6b1d0a356a0d13c985628d9b069421a26b Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 20 Aug 2020 16:52:02 -0700 Subject: [PATCH 499/860] Clarify implications of disabling strict hash verification --- src/opts.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opts.rs b/src/opts.rs index 3ca558baec..14e7d9a4bd 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -4,7 +4,8 @@ use crate::raw; /// Controls whether or not libgit2 will verify that objects loaded have the /// expected hash. Enabled by default, but disabling this can significantly -/// improve performance at the cost of correctness. +/// improve performance, at the cost of relying on repository integrity +/// without checking it. pub fn strict_hash_verification(enabled: bool) { let error = unsafe { raw::git_libgit2_opts( From a9c8abb188d45be05b4985a90c95ae22a60a6d27 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 20 Aug 2020 19:00:15 -0700 Subject: [PATCH 500/860] Bump versions --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ad6d54fd84..9b8708a79b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.9" +version = "0.13.10" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.10" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.12" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 745fc9d957..3729dad04e 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.11+1.0.1" +version = "0.12.12+1.0.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 7aa5d85d27287f74a5ed44c733aa134c2b1885cb Mon Sep 17 00:00:00 2001 From: Sven Date: Fri, 21 Aug 2020 17:22:24 +0200 Subject: [PATCH 501/860] feat: add git_submodule_clone (#611) Closes #609 --- libgit2-sys/lib.rs | 5 +++++ src/submodule.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a1f07d7b05..83b14fe146 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2324,6 +2324,11 @@ extern "C" { ) -> c_int; pub fn git_submodule_add_to_index(submodule: *mut git_submodule, write_index: c_int) -> c_int; pub fn git_submodule_branch(submodule: *mut git_submodule) -> *const c_char; + pub fn git_submodule_clone( + repo: *mut *mut git_repository, + submodule: *mut git_submodule, + opts: *const git_submodule_update_options, + ) -> c_int; pub fn git_submodule_foreach( repo: *mut git_repository, callback: git_submodule_cb, diff --git a/src/submodule.rs b/src/submodule.rs index f5515f83fd..135f52fd57 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -33,6 +33,25 @@ impl<'repo> Submodule<'repo> { unsafe { crate::opt_bytes(self, raw::git_submodule_branch(self.raw)) } } + /// Perform the clone step for a newly created submodule. + /// + /// This performs the necessary `git_clone` to setup a newly-created submodule. + pub fn clone( + &mut self, + opts: Option<&mut SubmoduleUpdateOptions<'_>>, + ) -> Result { + unsafe { + let raw_opts = opts.map(|o| o.raw()); + let mut raw_repo = ptr::null_mut(); + try_call!(raw::git_submodule_clone( + &mut raw_repo, + self.raw, + raw_opts.as_ref() + )); + Ok(Binding::from_raw(raw_repo)) + } + } + /// Get the submodule's url. /// /// Returns `None` if the url is not valid utf-8 or if the URL isn't present @@ -360,4 +379,26 @@ mod tests { t!(submodule.update(init, opts)); } } + + #[test] + fn clone_submodule() { + // ----------------------------------- + // Same as `add_a_submodule()` + let (_td, repo1) = crate::test::repo_init(); + let (_td, repo2) = crate::test::repo_init(); + let (_td, parent) = crate::test::repo_init(); + + let url1 = Url::from_file_path(&repo1.workdir().unwrap()).unwrap(); + let url3 = Url::from_file_path(&repo2.workdir().unwrap()).unwrap(); + let mut s1 = parent + .submodule(&url1.to_string(), Path::new("bar"), true) + .unwrap(); + let mut s2 = parent + .submodule(&url3.to_string(), Path::new("bar2"), true) + .unwrap(); + // ----------------------------------- + + t!(s1.clone(Some(&mut SubmoduleUpdateOptions::default()))); + t!(s2.clone(None)); + } } From 5fddf7e04dc76e70873569ca9f1de3287ec3edda Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Thu, 3 Sep 2020 16:03:33 +0200 Subject: [PATCH 502/860] allow hooking into push_transfer_progress & pack_progress callbacks (#617) * allow hooking into push_transfer_progress callback * support pack_progress --- src/packbuilder.rs | 1 + src/remote_callbacks.rs | 94 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/packbuilder.rs b/src/packbuilder.rs index 06bf41dc7a..1cdb0fe7cb 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -6,6 +6,7 @@ use std::slice; use crate::util::Binding; use crate::{panic, raw, Buf, Error, Oid, Repository, Revwalk}; +#[derive(PartialEq, Eq, Clone, Debug, Copy)] /// Stages that are reported by the `PackBuilder` progress callback. pub enum PackBuilderStage { /// Adding objects to the pack diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index ae741be399..bcc73e85e9 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -1,4 +1,4 @@ -use libc::{c_char, c_int, c_uint, c_void}; +use libc::{c_char, c_int, c_uint, c_void, size_t}; use std::ffi::{CStr, CString}; use std::mem; use std::ptr; @@ -7,7 +7,9 @@ use std::str; use crate::cert::Cert; use crate::util::Binding; -use crate::{panic, raw, Cred, CredentialType, Error, IndexerProgress, Oid, Progress}; +use crate::{ + panic, raw, Cred, CredentialType, Error, IndexerProgress, Oid, PackBuilderStage, Progress, +}; /// A structure to contain the callbacks which are invoked when a repository is /// being updated or downloaded. @@ -15,7 +17,9 @@ use crate::{panic, raw, Cred, CredentialType, Error, IndexerProgress, Oid, Progr /// These callbacks are used to manage facilities such as authentication, /// transfer progress, etc. pub struct RemoteCallbacks<'a> { + push_progress: Option>>, progress: Option>>, + pack_progress: Option>>, credentials: Option>>, sideband_progress: Option>>, update_tips: Option>>, @@ -56,6 +60,22 @@ pub type CertificateCheck<'a> = dyn FnMut(&Cert<'_>, &str) -> bool + 'a; /// was rejected by the remote server with a reason why. pub type PushUpdateReference<'a> = dyn FnMut(&str, Option<&str>) -> Result<(), Error> + 'a; +/// Callback for push transfer progress +/// +/// Parameters: +/// * current +/// * total +/// * bytes +pub type PushTransferProgress<'a> = dyn FnMut(usize, usize, usize) + 'a; + +/// Callback for pack progress +/// +/// Parameters: +/// * stage +/// * current +/// * total +pub type PackProgress<'a> = dyn FnMut(PackBuilderStage, usize, usize) + 'a; + impl<'a> Default for RemoteCallbacks<'a> { fn default() -> Self { Self::new() @@ -68,10 +88,12 @@ impl<'a> RemoteCallbacks<'a> { RemoteCallbacks { credentials: None, progress: None, + pack_progress: None, sideband_progress: None, update_tips: None, certificate_check: None, push_update_reference: None, + push_progress: None, } } @@ -158,6 +180,26 @@ impl<'a> RemoteCallbacks<'a> { self.push_update_reference = Some(Box::new(cb) as Box>); self } + + /// The callback through which progress of push transfer is monitored + pub fn push_transfer_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> + where + F: FnMut(usize, usize, usize) + 'a, + { + self.push_progress = Some(Box::new(cb) as Box>); + self + } + + /// Function to call with progress information during pack building. + /// Be aware that this is called inline with pack building operations, + /// so performance may be affected. + pub fn pack_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> + where + F: FnMut(PackBuilderStage, usize, usize) + 'a, + { + self.pack_progress = Some(Box::new(cb) as Box>); + self + } } impl<'a> Binding for RemoteCallbacks<'a> { @@ -188,6 +230,12 @@ impl<'a> Binding for RemoteCallbacks<'a> { if self.push_update_reference.is_some() { callbacks.push_update_reference = Some(push_update_reference_cb); } + if self.push_progress.is_some() { + callbacks.push_transfer_progress = Some(push_transfer_progress_cb); + } + if self.pack_progress.is_some() { + callbacks.pack_progress = Some(pack_progress_cb); + } if self.update_tips.is_some() { let f: extern "C" fn( *const c_char, @@ -360,3 +408,45 @@ extern "C" fn push_update_reference_cb( }) .unwrap_or(-1) } + +extern "C" fn push_transfer_progress_cb( + progress: c_uint, + total: c_uint, + bytes: size_t, + data: *mut c_void, +) -> c_int { + panic::wrap(|| unsafe { + let payload = &mut *(data as *mut RemoteCallbacks<'_>); + let callback = match payload.push_progress { + Some(ref mut c) => c, + None => return 0, + }; + + callback(progress as usize, total as usize, bytes as usize); + + 0 + }) + .unwrap_or(-1) +} + +extern "C" fn pack_progress_cb( + stage: raw::git_packbuilder_stage_t, + current: c_uint, + total: c_uint, + data: *mut c_void, +) -> c_int { + panic::wrap(|| unsafe { + let payload = &mut *(data as *mut RemoteCallbacks<'_>); + let callback = match payload.pack_progress { + Some(ref mut c) => c, + None => return 0, + }; + + let stage = Binding::from_raw(stage); + + callback(stage, current as usize, total as usize); + + 0 + }) + .unwrap_or(-1) +} From 218a2b380a6eae17ec8a7499683a5be2232cb659 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 Sep 2020 10:23:24 -0700 Subject: [PATCH 503/860] Bump libgit2-sys and git2 crates --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9b8708a79b..562137a1b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.10" +version = "0.13.11" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.12" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.13" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 3729dad04e..213f84dc4c 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.12+1.0.1" +version = "0.12.13+1.0.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 831faaff95a5a1b63b6f5d0217e3507f5190c041 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Fri, 11 Sep 2020 20:03:07 +0200 Subject: [PATCH 504/860] Compile libgit2 deterministically by sorting read_dir (#619) --- libgit2-sys/build.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 178d931cf9..dadc6c82d1 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -1,5 +1,6 @@ use std::env; use std::fs; +use std::io; use std::path::{Path, PathBuf}; use std::process::Command; @@ -199,8 +200,12 @@ fn cp_r(from: impl AsRef, to: impl AsRef) { } fn add_c_files(build: &mut cc::Build, path: impl AsRef) { - for e in path.as_ref().read_dir().unwrap() { - let e = e.unwrap(); + // sort the C files to ensure a deterministic build for reproducible builds + let dir = path.as_ref().read_dir().unwrap(); + let mut paths = dir.collect::>>().unwrap(); + paths.sort_by_key(|e| e.path()); + + for e in paths { let path = e.path(); if e.file_type().unwrap().is_dir() { // skip dirs for now From 95c243fd5c29c8dba0b55668f2a9e8e0ee5ce510 Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Wed, 16 Sep 2020 18:45:41 +0200 Subject: [PATCH 505/860] Add bindings for `git_reference_normalize_name` (#620) * Add bindings for `git_reference_normalize_name` * fixup! Add bindings for `git_reference_normalize_name` * Fix type * GIT_REFNAME_MAX is not in the includes --- libgit2-sys/lib.rs | 15 ++++++ src/lib.rs | 34 ++++++++++++++ src/reference.rs | 115 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 163 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 83b14fe146..5bf894d07e 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1814,6 +1814,15 @@ git_enum! { } } +git_enum! { + pub enum git_reference_format_t { + GIT_REFERENCE_FORMAT_NORMAL = 0, + GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL = 1 << 0, + GIT_REFERENCE_FORMAT_REFSPEC_PATTERN = 1 << 1, + GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND = 1 << 2, + } +} + extern "C" { // threads pub fn git_libgit2_init() -> c_int; @@ -2278,6 +2287,12 @@ extern "C" { ) -> c_int; pub fn git_reference_has_log(repo: *mut git_repository, name: *const c_char) -> c_int; pub fn git_reference_ensure_log(repo: *mut git_repository, name: *const c_char) -> c_int; + pub fn git_reference_normalize_name( + buffer_out: *mut c_char, + buffer_size: size_t, + name: *const c_char, + flags: u32, + ) -> c_int; // stash pub fn git_stash_save( diff --git a/src/lib.rs b/src/lib.rs index 1ce760ca7a..14cc9b7d3e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1403,6 +1403,40 @@ impl DiffFlags { is_bit_set!(exists, DiffFlags::EXISTS); } +bitflags! { + /// Options for [`Reference::normalize_name`]. + pub struct ReferenceFormat: u32 { + /// No particular normalization. + const NORMAL = raw::GIT_REFERENCE_FORMAT_NORMAL as u32; + /// Constrol whether one-level refname are accepted (i.e., refnames that + /// do not contain multiple `/`-separated components). Those are + /// expected to be written only using uppercase letters and underscore + /// (e.g. `HEAD`, `FETCH_HEAD`). + const ALLOW_ONELEVEL = raw::GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL as u32; + /// Interpret the provided name as a reference pattern for a refspec (as + /// used with remote repositories). If this option is enabled, the name + /// is allowed to contain a single `*` in place of a full pathname + /// components (e.g., `foo/*/bar` but not `foo/bar*`). + const REFSPEC_PATTERN = raw::GIT_REFERENCE_FORMAT_REFSPEC_PATTERN as u32; + /// Interpret the name as part of a refspec in shorthand form so the + /// `ALLOW_ONELEVEL` naming rules aren't enforced and `master` becomes a + /// valid name. + const REFSPEC_SHORTHAND = raw::GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND as u32; + } +} + +impl ReferenceFormat { + is_bit_set!(is_allow_onelevel, ReferenceFormat::ALLOW_ONELEVEL); + is_bit_set!(is_refspec_pattern, ReferenceFormat::REFSPEC_PATTERN); + is_bit_set!(is_refspec_shorthand, ReferenceFormat::REFSPEC_SHORTHAND); +} + +impl Default for ReferenceFormat { + fn default() -> Self { + ReferenceFormat::NORMAL + } +} + #[cfg(test)] mod tests { use super::ObjectType; diff --git a/src/reference.rs b/src/reference.rs index 7955fcfe78..09f4f88671 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -8,9 +8,14 @@ use std::str; use crate::object::CastOrPanic; use crate::util::{c_cmp_to_ordering, Binding}; use crate::{ - raw, Blob, Commit, Error, Object, ObjectType, Oid, ReferenceType, Repository, Tag, Tree, + raw, Blob, Commit, Error, Object, ObjectType, Oid, ReferenceFormat, ReferenceType, Repository, + Tag, Tree, }; +// Not in the public header files (yet?), but a hard limit used by libgit2 +// internally +const GIT_REFNAME_MAX: usize = 1024; + struct Refdb<'repo>(&'repo Repository); /// A structure to represent a git [reference][1]. @@ -34,12 +39,120 @@ pub struct ReferenceNames<'repo, 'references> { impl<'repo> Reference<'repo> { /// Ensure the reference name is well-formed. + /// + /// Validation is performed as if [`ReferenceFormat::ALLOW_ONELEVEL`] + /// was given to [`Reference::normalize_name`]. No normalization is + /// performed, however. + /// + /// ```rust + /// use git2::Reference; + /// + /// assert!(Reference::is_valid_name("HEAD")); + /// assert!(Reference::is_valid_name("refs/heads/master")); + /// + /// // But: + /// assert!(!Reference::is_valid_name("master")); + /// assert!(!Reference::is_valid_name("refs/heads/*")); + /// assert!(!Reference::is_valid_name("foo//bar")); + /// ``` + /// + /// [`ReferenceFormat::ALLOW_ONELEVEL`]: + /// struct.ReferenceFormat#associatedconstant.ALLOW_ONELEVEL + /// [`Reference::normalize_name`]: struct.Reference#method.normalize_name pub fn is_valid_name(refname: &str) -> bool { crate::init(); let refname = CString::new(refname).unwrap(); unsafe { raw::git_reference_is_valid_name(refname.as_ptr()) == 1 } } + /// Normalize reference name and check validity. + /// + /// This will normalize the reference name by collapsing runs of adjacent + /// slashes between name components into a single slash. It also validates + /// the name according to the following rules: + /// + /// 1. If [`ReferenceFormat::ALLOW_ONELEVEL`] is given, the name may + /// contain only capital letters and underscores, and must begin and end + /// with a letter. (e.g. "HEAD", "ORIG_HEAD"). + /// 2. The flag [`ReferenceFormat::REFSPEC_SHORTHAND`] has an effect + /// only when combined with [`ReferenceFormat::ALLOW_ONELEVEL`]. If + /// it is given, "shorthand" branch names (i.e. those not prefixed by + /// `refs/`, but consisting of a single word without `/` separators) + /// become valid. For example, "master" would be accepted. + /// 3. If [`ReferenceFormat::REFSPEC_PATTERN`] is given, the name may + /// contain a single `*` in place of a full pathname component (e.g. + /// `foo/*/bar`, `foo/bar*`). + /// 4. Names prefixed with "refs/" can be almost anything. You must avoid + /// the characters '~', '^', ':', '\\', '?', '[', and '*', and the + /// sequences ".." and "@{" which have special meaning to revparse. + /// + /// If the reference passes validation, it is returned in normalized form, + /// otherwise an [`Error`] with [`ErrorCode::InvalidSpec`] is returned. + /// + /// ```rust + /// use git2::{Reference, ReferenceFormat}; + /// + /// assert_eq!( + /// Reference::normalize_name( + /// "foo//bar", + /// ReferenceFormat::NORMAL + /// ) + /// .unwrap(), + /// "foo/bar".to_owned() + /// ); + /// + /// assert_eq!( + /// Reference::normalize_name( + /// "HEAD", + /// ReferenceFormat::ALLOW_ONELEVEL + /// ) + /// .unwrap(), + /// "HEAD".to_owned() + /// ); + /// + /// assert_eq!( + /// Reference::normalize_name( + /// "refs/heads/*", + /// ReferenceFormat::REFSPEC_PATTERN + /// ) + /// .unwrap(), + /// "refs/heads/*".to_owned() + /// ); + /// + /// assert_eq!( + /// Reference::normalize_name( + /// "master", + /// ReferenceFormat::ALLOW_ONELEVEL | ReferenceFormat::REFSPEC_SHORTHAND + /// ) + /// .unwrap(), + /// "master".to_owned() + /// ); + /// ``` + /// + /// [`ReferenceFormat::ALLOW_ONELEVEL`]: + /// struct.ReferenceFormat#associatedconstant.ALLOW_ONELEVEL + /// [`ReferenceFormat::REFSPEC_SHORTHAND`]: + /// struct.ReferenceFormat#associatedconstant.REFSPEC_SHORTHAND + /// [`ReferenceFormat::REFSPEC_PATTERN`]: + /// struct.ReferenceFormat#associatedconstant.REFSPEC_PATTERN + /// [`Error`]: struct.Error + /// [`ErrorCode::InvalidSpec`]: enum.ErrorCode#variant.InvalidSpec + pub fn normalize_name(refname: &str, flags: ReferenceFormat) -> Result { + crate::init(); + let mut dst = [0u8; GIT_REFNAME_MAX]; + let refname = CString::new(refname)?; + unsafe { + try_call!(raw::git_reference_normalize_name( + dst.as_mut_ptr() as *mut libc::c_char, + dst.len() as libc::size_t, + refname, + flags.bits() + )); + let s = &dst[..dst.iter().position(|&a| a == 0).unwrap()]; + Ok(str::from_utf8(s).unwrap().to_owned()) + } + } + /// Get access to the underlying raw pointer. pub fn raw(&self) -> *mut raw::git_reference { self.raw From 43d583fd8b50fad0cfe0bbc334059ce965b6f3fc Mon Sep 17 00:00:00 2001 From: stoically Date: Thu, 17 Sep 2020 19:54:11 +0200 Subject: [PATCH 506/860] Init before creating Odb with new (#621) --- src/odb.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/odb.rs b/src/odb.rs index de3b42659a..7c53e41d26 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -41,6 +41,7 @@ impl<'repo> Drop for Odb<'repo> { impl<'repo> Odb<'repo> { /// Creates an object database without any backends. pub fn new<'a>() -> Result, Error> { + crate::init(); unsafe { let mut out = ptr::null_mut(); try_call!(raw::git_odb_new(&mut out)); From 68805637017da2fb59bc7dc600e89614db016c32 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Wed, 14 Oct 2020 02:06:54 +0200 Subject: [PATCH 507/860] Update to libgit2 v1.1 and use `main` branch for tests. (#627) * Update to libgit2 v1.1 and use `main` branch for tests. * Update version of libgit2 in README.md --- README.md | 2 +- libgit2-sys/libgit2 | 2 +- src/branch.rs | 2 +- src/build.rs | 6 ++++-- src/lib.rs | 2 +- src/rebase.rs | 12 ++++++------ src/reference.rs | 22 +++++++++++----------- src/remote.rs | 21 ++++++++++++--------- src/repo.rs | 26 +++++++++++++------------- src/stash.rs | 4 ++-- src/test.rs | 6 ++++-- src/transport.rs | 2 +- 12 files changed, 57 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index cad02eacc1..15e5b6d3f6 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ version of Rust known to pass tests. ## Version of libgit2 -Currently this library requires libgit2 1.0.0. The source for libgit2 is +Currently this library requires libgit2 1.1.0. The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index a83fd51078..7f4fa17862 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit a83fd5107879d18b31ff8173ea062136256321be +Subproject commit 7f4fa178629d559c037a1f72f79f79af9c1ef8ce diff --git a/src/branch.rs b/src/branch.rs index c33a18370e..276bc534ac 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -169,7 +169,7 @@ mod tests { let mut b1 = b1.rename("bar", false).unwrap(); assert_eq!(b1.name().unwrap(), Some("bar")); assert!(b1.upstream().is_err()); - b1.set_upstream(Some("master")).unwrap(); + b1.set_upstream(Some("main")).unwrap(); b1.upstream().unwrap(); b1.set_upstream(None).unwrap(); diff --git a/src/build.rs b/src/build.rs index f86b89ca93..286b009f22 100644 --- a/src/build.rs +++ b/src/build.rs @@ -714,7 +714,9 @@ mod tests { let cd = TempDir::new().unwrap(); { - let repo = Repository::init(&td.path()).unwrap(); + let mut opts = crate::RepositoryInitOptions::new(); + opts.initial_head("main"); + let repo = Repository::init_opts(&td.path(), &opts).unwrap(); let mut config = repo.config().unwrap(); config.set_str("user.name", "name").unwrap(); @@ -735,7 +737,7 @@ mod tests { let repo = Repository::open_bare(&td.path().join(".git")).unwrap(); let tree = repo - .revparse_single(&"master") + .revparse_single(&"main") .unwrap() .peel_to_tree() .unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 14cc9b7d3e..ace4009230 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1419,7 +1419,7 @@ bitflags! { /// components (e.g., `foo/*/bar` but not `foo/bar*`). const REFSPEC_PATTERN = raw::GIT_REFERENCE_FORMAT_REFSPEC_PATTERN as u32; /// Interpret the name as part of a refspec in shorthand form so the - /// `ALLOW_ONELEVEL` naming rules aren't enforced and `master` becomes a + /// `ALLOW_ONELEVEL` naming rules aren't enforced and `main` becomes a /// valid name. const REFSPEC_SHORTHAND = raw::GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND as u32; } diff --git a/src/rebase.rs b/src/rebase.rs index d4e54133bc..e44470b820 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -349,21 +349,21 @@ mod tests { // We just want to see the iteration work so we can create commits with // no changes let c1 = repo - .commit(Some("refs/heads/master"), &sig, &sig, "foo", &tree, &[&tip]) + .commit(Some("refs/heads/main"), &sig, &sig, "foo", &tree, &[&tip]) .unwrap(); let c1 = repo.find_commit(c1).unwrap(); let c2 = repo - .commit(Some("refs/heads/master"), &sig, &sig, "foo", &tree, &[&c1]) + .commit(Some("refs/heads/main"), &sig, &sig, "foo", &tree, &[&c1]) .unwrap(); - let head = repo.find_reference("refs/heads/master").unwrap(); + let head = repo.find_reference("refs/heads/main").unwrap(); let branch = repo.reference_to_annotated_commit(&head).unwrap(); let upstream = repo.find_annotated_commit(tip.id()).unwrap(); let mut rebase = repo .rebase(Some(&branch), Some(&upstream), None, None) .unwrap(); - assert_eq!(Some("refs/heads/master"), rebase.orig_head_name()); + assert_eq!(Some("refs/heads/main"), rebase.orig_head_name()); assert_eq!(Some(c2), rebase.orig_head_id()); assert_eq!(rebase.len(), 2); @@ -397,7 +397,7 @@ mod tests { let tree_id_a = index.write_tree().unwrap(); let tree_a = repo.find_tree(tree_id_a).unwrap(); let c1 = repo - .commit(Some("refs/heads/master"), &sig, &sig, "A", &tree_a, &[&tip]) + .commit(Some("refs/heads/main"), &sig, &sig, "A", &tree_a, &[&tip]) .unwrap(); let c1 = repo.find_commit(c1).unwrap(); @@ -407,7 +407,7 @@ mod tests { let tree_id_b = index.write_tree().unwrap(); let tree_b = repo.find_tree(tree_id_b).unwrap(); let c2 = repo - .commit(Some("refs/heads/master"), &sig, &sig, "B", &tree_b, &[&c1]) + .commit(Some("refs/heads/main"), &sig, &sig, "B", &tree_b, &[&c1]) .unwrap(); let branch = repo.find_annotated_commit(c2).unwrap(); diff --git a/src/reference.rs b/src/reference.rs index 09f4f88671..cc08b0dfa6 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -48,10 +48,10 @@ impl<'repo> Reference<'repo> { /// use git2::Reference; /// /// assert!(Reference::is_valid_name("HEAD")); - /// assert!(Reference::is_valid_name("refs/heads/master")); + /// assert!(Reference::is_valid_name("refs/heads/main")); /// /// // But: - /// assert!(!Reference::is_valid_name("master")); + /// assert!(!Reference::is_valid_name("main")); /// assert!(!Reference::is_valid_name("refs/heads/*")); /// assert!(!Reference::is_valid_name("foo//bar")); /// ``` @@ -78,7 +78,7 @@ impl<'repo> Reference<'repo> { /// only when combined with [`ReferenceFormat::ALLOW_ONELEVEL`]. If /// it is given, "shorthand" branch names (i.e. those not prefixed by /// `refs/`, but consisting of a single word without `/` separators) - /// become valid. For example, "master" would be accepted. + /// become valid. For example, "main" would be accepted. /// 3. If [`ReferenceFormat::REFSPEC_PATTERN`] is given, the name may /// contain a single `*` in place of a full pathname component (e.g. /// `foo/*/bar`, `foo/bar*`). @@ -121,11 +121,11 @@ impl<'repo> Reference<'repo> { /// /// assert_eq!( /// Reference::normalize_name( - /// "master", + /// "main", /// ReferenceFormat::ALLOW_ONELEVEL | ReferenceFormat::REFSPEC_SHORTHAND /// ) /// .unwrap(), - /// "master".to_owned() + /// "main".to_owned() /// ); /// ``` /// @@ -482,18 +482,18 @@ mod tests { assert_eq!(head.kind().unwrap(), ReferenceType::Direct); assert!(head == repo.head().unwrap()); - assert_eq!(head.name(), Some("refs/heads/master")); + assert_eq!(head.name(), Some("refs/heads/main")); - assert!(head == repo.find_reference("refs/heads/master").unwrap()); + assert!(head == repo.find_reference("refs/heads/main").unwrap()); assert_eq!( - repo.refname_to_id("refs/heads/master").unwrap(), + repo.refname_to_id("refs/heads/main").unwrap(), head.target().unwrap() ); assert!(head.symbolic_target().is_none()); assert!(head.target_peel().is_none()); - assert_eq!(head.shorthand(), Some("master")); + assert_eq!(head.shorthand(), Some("main")); assert!(head.resolve().unwrap() == head); let mut tag1 = repo @@ -509,7 +509,7 @@ mod tests { tag1.delete().unwrap(); let mut sym1 = repo - .reference_symbolic("refs/tags/tag1", "refs/heads/master", false, "test") + .reference_symbolic("refs/tags/tag1", "refs/heads/main", false, "test") .unwrap(); assert_eq!(sym1.kind().unwrap(), ReferenceType::Symbolic); sym1.delete().unwrap(); @@ -519,7 +519,7 @@ mod tests { assert!(repo.references().unwrap().next().unwrap().unwrap() == head); let mut names = repo.references().unwrap(); let mut names = names.names(); - assert_eq!(names.next().unwrap().unwrap(), "refs/heads/master"); + assert_eq!(names.next().unwrap().unwrap(), "refs/heads/main"); assert!(names.next().is_none()); assert!(repo.references_glob("foo").unwrap().count() == 0); assert!(repo.references_glob("refs/heads/*").unwrap().count() == 1); diff --git a/src/remote.rs b/src/remote.rs index d2ea83fa01..7fb2561038 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -231,15 +231,15 @@ impl<'repo> Remote<'repo> { /// /// # Examples /// - /// Example of functionality similar to `git fetch origin/master`: + /// Example of functionality similar to `git fetch origin/main`: /// /// ```no_run - /// fn fetch_origin_master(repo: git2::Repository) -> Result<(), git2::Error> { - /// repo.find_remote("origin")?.fetch(&["master"], None, None) + /// fn fetch_origin_main(repo: git2::Repository) -> Result<(), git2::Error> { + /// repo.find_remote("origin")?.fetch(&["main"], None, None) /// } /// /// let repo = git2::Repository::discover("rust").unwrap(); - /// fetch_origin_master(repo).unwrap(); + /// fetch_origin_main(repo).unwrap(); /// ``` pub fn fetch + crate::IntoCString + Clone>( &mut self, @@ -757,7 +757,7 @@ mod tests { assert_eq!(list.len(), 2); assert_eq!(list[0].name(), "HEAD"); assert!(!list[0].is_local()); - assert_eq!(list[1].name(), "refs/heads/master"); + assert_eq!(list[1].name(), "refs/heads/main"); assert!(!list[1].is_local()); } assert!(progress_hit.get()); @@ -790,7 +790,7 @@ mod tests { assert_eq!(list.len(), 2); assert_eq!(list[0].name(), "HEAD"); assert!(!list[0].is_local()); - assert_eq!(list[1].name(), "refs/heads/master"); + assert_eq!(list[1].name(), "refs/heads/main"); assert!(!list[1].is_local()); } assert!(!origin.connected()); @@ -803,7 +803,10 @@ mod tests { let td3 = TempDir::new().unwrap(); let url = crate::test::path2url(https://github.com/&td2.path()); - Repository::init_bare(td2.path()).unwrap(); + let mut opts = crate::RepositoryInitOptions::new(); + opts.bare(true); + opts.initial_head("main"); + Repository::init_opts(td2.path(), &opts).unwrap(); // git push let mut remote = repo.remote("origin", &url).unwrap(); let mut updated = false; @@ -811,14 +814,14 @@ mod tests { let mut callbacks = RemoteCallbacks::new(); callbacks.push_update_reference(|refname, status| { updated = true; - assert_eq!(refname, "refs/heads/master"); + assert_eq!(refname, "refs/heads/main"); assert_eq!(status, None); Ok(()) }); let mut options = PushOptions::new(); options.remote_callbacks(callbacks); remote - .push(&["refs/heads/master"], Some(&mut options)) + .push(&["refs/heads/main"], Some(&mut options)) .unwrap(); } assert!(updated); diff --git a/src/repo.rs b/src/repo.rs index 2854d81281..4f53ccb3fc 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1463,7 +1463,7 @@ impl Repository { /// Lookup a reference to one of the objects in a repository. /// `Repository::find_reference` with teeth; give the method your reference in - /// human-readable format e.g. 'master' instead of 'refs/heads/master', and it + /// human-readable format e.g. 'main' instead of 'refs/heads/main', and it /// will do-what-you-mean, returning the `Reference`. pub fn resolve_reference_from_short_name(&self, refname: &str) -> Result, Error> { let refname = CString::new(refname)?; @@ -2929,9 +2929,9 @@ impl RepositoryInitOptions { /// The name of the head to point HEAD at. /// - /// If not configured, this will be treated as `master` and the HEAD ref - /// will be set to `refs/heads/master`. If this begins with `refs/` it will - /// be used verbatim; otherwise `refs/heads/` will be prefixed + /// If not configured, this will be taken from your git configuration. + /// If this begins with `refs/` it will be used verbatim; + /// otherwise `refs/heads/` will be prefixed pub fn initial_head(&mut self, head: &str) -> &mut RepositoryInitOptions { self.initial_head = Some(CString::new(head).unwrap()); self @@ -3160,11 +3160,11 @@ mod tests { let (_td, repo) = crate::test::repo_init(); assert_eq!(repo.reference_has_log("HEAD").unwrap(), true); - assert_eq!(repo.reference_has_log("refs/heads/master").unwrap(), true); + assert_eq!(repo.reference_has_log("refs/heads/main").unwrap(), true); assert_eq!(repo.reference_has_log("NOT_HEAD").unwrap(), false); - let master_oid = repo.revparse_single("master").unwrap().id(); + let main_oid = repo.revparse_single("main").unwrap().id(); assert!(repo - .reference("NOT_HEAD", master_oid, false, "creating a new branch") + .reference("NOT_HEAD", main_oid, false, "creating a new branch") .is_ok()); assert_eq!(repo.reference_has_log("NOT_HEAD").unwrap(), false); assert!(repo.reference_ensure_log("NOT_HEAD").is_ok()); @@ -3178,7 +3178,7 @@ mod tests { assert!(repo.set_head("refs/heads/does-not-exist").is_ok()); assert!(repo.head().is_err()); - assert!(repo.set_head("refs/heads/master").is_ok()); + assert!(repo.set_head("refs/heads/main").is_ok()); assert!(repo.head().is_ok()); assert!(repo.set_head("*").is_err()); @@ -3191,9 +3191,9 @@ mod tests { let void_oid = Oid::from_bytes(b"00000000000000000000").unwrap(); assert!(repo.set_head_detached(void_oid).is_err()); - let master_oid = repo.revparse_single("master").unwrap().id(); - assert!(repo.set_head_detached(master_oid).is_ok()); - assert_eq!(repo.head().unwrap().target().unwrap(), master_oid); + let main_oid = repo.revparse_single("main").unwrap().id(); + assert!(repo.set_head_detached(main_oid).is_ok()); + assert_eq!(repo.head().unwrap().target().unwrap(), main_oid); } /// create the following: @@ -3425,8 +3425,8 @@ mod tests { let (_td, repo) = graph_repo_init(); { - let short_refname = "master"; - let expected_refname = "refs/heads/master"; + let short_refname = "main"; + let expected_refname = "refs/heads/main"; let (obj, reference) = repo.revparse_ext(short_refname).unwrap(); let expected_obj = repo.revparse_single(expected_refname).unwrap(); assert_eq!(obj.id(), expected_obj.id()); diff --git a/src/stash.rs b/src/stash.rs index f9f3927473..97e02b5de6 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -184,7 +184,7 @@ mod tests { repo.stash_foreach(|index, name, _oid| { count += 1; assert!(index == 0); - assert!(name == "On master: msg1"); + assert!(name == "On main: msg1"); true }) .unwrap(); @@ -256,6 +256,6 @@ mod tests { }) .unwrap(); - assert!(stash_name.starts_with("WIP on master:")); + assert!(stash_name.starts_with("WIP on main:")); } } diff --git a/src/test.rs b/src/test.rs index 149f4946c5..f21690e355 100644 --- a/src/test.rs +++ b/src/test.rs @@ -6,7 +6,7 @@ use std::ptr; use tempfile::TempDir; use url::Url; -use crate::{Oid, Repository}; +use crate::{Oid, Repository, RepositoryInitOptions}; macro_rules! t { ($e:expr) => { @@ -19,7 +19,9 @@ macro_rules! t { pub fn repo_init() -> (TempDir, Repository) { let td = TempDir::new().unwrap(); - let repo = Repository::init(td.path()).unwrap(); + let mut opts = RepositoryInitOptions::new(); + opts.initial_head("main"); + let repo = Repository::init_opts(td.path(), &opts).unwrap(); { let mut config = repo.config().unwrap(); config.set_str("user.name", "name").unwrap(); diff --git a/src/transport.rs b/src/transport.rs index 5c5a1e6e8b..83d755716f 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -404,7 +404,7 @@ mod tests { let mut origin = t!(repo.find_remote("origin")); - match origin.fetch(&["master"], None, None) { + match origin.fetch(&["main"], None, None) { Ok(()) => unreachable!(), Err(e) => assert_eq!(e, dummy_error()), } From deed14dcbf17ba87f6659ea05755cf94cb1464ab Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 13 Oct 2020 17:07:30 -0700 Subject: [PATCH 508/860] Bump crate versions --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 562137a1b9..a5c2a82ccc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.11" +version = "0.13.12" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.13" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.14" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 213f84dc4c..aa6838310a 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.13+1.0.1" +version = "0.12.14+1.1.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 7d261e8a4674f13d8c8c06da1583a941d0553efe Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 2 Nov 2020 19:19:51 -0500 Subject: [PATCH 509/860] Remove trailing semicolon from internal `err!` macro This will allow this crate to continue to compile if https://github.com/rust-lang/rust/issues/33953 is fixed --- src/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.rs b/src/util.rs index a31e63bce2..1c6001ddbf 100644 --- a/src/util.rs +++ b/src/util.rs @@ -204,7 +204,7 @@ pub fn c_cmp_to_ordering(cmp: c_int) -> Ordering { pub fn path_to_repo_path(path: &Path) -> Result { macro_rules! err { ($msg:literal, $path:expr) => { - return Err(Error::from_str(&format!($msg, $path.display()))); + return Err(Error::from_str(&format!($msg, $path.display()))) }; } match path.components().next() { From b830b24c8f7032baab6346380580c0e70582dec1 Mon Sep 17 00:00:00 2001 From: Hiroki Noda Date: Wed, 11 Nov 2020 00:16:23 +0900 Subject: [PATCH 510/860] Fix: requires libgit2 v1.1.0 in build.rs (#632) --- libgit2-sys/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index dadc6c82d1..81fb8638e1 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -12,7 +12,7 @@ fn main() { // To use zlib-ng in zlib-compat mode, we have to build libgit2 ourselves. if !zlib_ng_compat { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.atleast_version("1.0.0").probe("libgit2") { + if let Ok(lib) = cfg.atleast_version("1.1.0").probe("libgit2") { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } From 73eee9df01ee73f6d982ea7246da9537da4a2872 Mon Sep 17 00:00:00 2001 From: Hiroki Noda Date: Wed, 11 Nov 2020 00:18:32 +0900 Subject: [PATCH 511/860] Add new blame options (#633) --- libgit2-sys/lib.rs | 2 ++ src/blame.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5bf894d07e..807287558d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -714,6 +714,8 @@ pub const GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES: u32 = 1 << 1; pub const GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES: u32 = 1 << 2; pub const GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES: u32 = 1 << 3; pub const GIT_BLAME_FIRST_PARENT: u32 = 1 << 4; +pub const GIT_BLAME_USE_MAILMAP: u32 = 1 << 5; +pub const GIT_BLAME_IGNORE_WHITESPACE: u32 = 1 << 6; #[repr(C)] #[derive(Copy, Clone)] diff --git a/src/blame.rs b/src/blame.rs index 5c582458df..1d7364b6b3 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -201,6 +201,18 @@ impl BlameOptions { self.flag(raw::GIT_BLAME_FIRST_PARENT, opt) } + /// Use mailmap file to map author and committer names and email addresses + /// to canonical real names and email addresses. The mailmap will be read + /// from the working directory, or HEAD in a bare repository. + pub fn use_mailmap(&mut self, opt: bool) -> &mut BlameOptions { + self.flag(raw::GIT_BLAME_USE_MAILMAP, opt) + } + + /// Ignore whitespace differences. + pub fn ignore_whitespace(&mut self, opt: bool) -> &mut BlameOptions { + self.flag(raw::GIT_BLAME_IGNORE_WHITESPACE, opt) + } + /// Setter for the id of the newest commit to consider. pub fn newest_commit(&mut self, id: Oid) -> &mut BlameOptions { unsafe { From 7d755ae95f96157488e0f7c4aa33fba3fbe07579 Mon Sep 17 00:00:00 2001 From: Matteo Bertini Date: Tue, 17 Nov 2020 00:47:18 +0100 Subject: [PATCH 512/860] Fix "bya" -> "by a" typo (#634) --- src/remote.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remote.rs b/src/remote.rs index 7fb2561038..1b26db7f60 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -29,7 +29,7 @@ pub struct Refspecs<'remote> { remote: &'remote Remote<'remote>, } -/// Description of a reference advertised bya remote server, given out on calls +/// Description of a reference advertised by a remote server, given out on calls /// to `list`. pub struct RemoteHead<'remote> { raw: *const raw::git_remote_head, From 2ba185289ca3ccb254396cf7b8f786d2be9a5172 Mon Sep 17 00:00:00 2001 From: SeongChan Lee Date: Thu, 19 Nov 2020 00:23:26 +0900 Subject: [PATCH 513/860] More Better Worktree Support (#603) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Intial support for working with worktrees The systest changes were necessary due to the actual field name used in the C library being “ref” and not being able to name the field the same in the Rust struct because “ref” is a reserved keyword. Co-authored-by: Matt Keeler --- Cargo.toml | 1 + libgit2-sys/lib.rs | 70 ++++++++++ src/blame.rs | 2 +- src/lib.rs | 2 + src/repo.rs | 60 ++++++++ src/test.rs | 10 +- src/worktree.rs | 331 +++++++++++++++++++++++++++++++++++++++++++++ systest/build.rs | 4 +- 8 files changed, 477 insertions(+), 3 deletions(-) create mode 100644 src/worktree.rs diff --git a/Cargo.toml b/Cargo.toml index a5c2a82ccc..2e2375a5b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ structopt = "0.3" time = "0.1.39" tempfile = "3.1.0" thread-id = "3.3.0" # remove when we work with minimal-versions without it +paste = "0.1.12" [features] unstable = [] diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 807287558d..26f1cd0873 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1825,6 +1825,34 @@ git_enum! { } } +#[repr(C)] +pub struct git_worktree_add_options { + pub version: c_uint, + pub lock: c_int, + pub reference: *mut git_reference, +} + +pub const GIT_WORKTREE_ADD_OPTIONS_VERSION: c_uint = 1; + +git_enum! { + pub enum git_worktree_prune_t { + /* Prune working tree even if working tree is valid */ + GIT_WORKTREE_PRUNE_VALID = 1 << 0, + /* Prune working tree even if it is locked */ + GIT_WORKTREE_PRUNE_LOCKED = 1 << 1, + /* Prune checked out working tree */ + GIT_WORKTREE_PRUNE_WORKING_TREE = 1 << 2, + } +} + +#[repr(C)] +pub struct git_worktree_prune_options { + pub version: c_uint, + pub flags: u32, +} + +pub const GIT_WORKTREE_PRUNE_OPTIONS_VERSION: c_uint = 1; + extern "C" { // threads pub fn git_libgit2_init() -> c_int; @@ -3782,6 +3810,48 @@ extern "C" { ) -> c_int; pub fn git_libgit2_opts(option: c_int, ...) -> c_int; + + // Worktrees + pub fn git_worktree_list(out: *mut git_strarray, repo: *mut git_repository) -> c_int; + pub fn git_worktree_lookup( + out: *mut *mut git_worktree, + repo: *mut git_repository, + name: *const c_char, + ) -> c_int; + pub fn git_worktree_open_from_repository( + out: *mut *mut git_worktree, + repo: *mut git_repository, + ) -> c_int; + pub fn git_worktree_free(wt: *mut git_worktree); + pub fn git_worktree_validate(wt: *const git_worktree) -> c_int; + pub fn git_worktree_add_options_init( + opts: *mut git_worktree_add_options, + version: c_uint, + ) -> c_int; + pub fn git_worktree_add( + out: *mut *mut git_worktree, + repo: *mut git_repository, + name: *const c_char, + path: *const c_char, + opts: *const git_worktree_add_options, + ) -> c_int; + pub fn git_worktree_lock(wt: *mut git_worktree, reason: *const c_char) -> c_int; + pub fn git_worktree_unlock(wt: *mut git_worktree) -> c_int; + pub fn git_worktree_is_locked(reason: *mut git_buf, wt: *const git_worktree) -> c_int; + pub fn git_worktree_name(wt: *const git_worktree) -> *const c_char; + pub fn git_worktree_path(wt: *const git_worktree) -> *const c_char; + pub fn git_worktree_prune_options_init( + opts: *mut git_worktree_prune_options, + version: c_uint, + ) -> c_int; + pub fn git_worktree_is_prunable( + wt: *mut git_worktree, + opts: *mut git_worktree_prune_options, + ) -> c_int; + pub fn git_worktree_prune( + wt: *mut git_worktree, + opts: *mut git_worktree_prune_options, + ) -> c_int; } pub fn init() { diff --git a/src/blame.rs b/src/blame.rs index 1d7364b6b3..3132992ea7 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -307,7 +307,7 @@ mod tests { let (_td, repo) = crate::test::repo_init(); let mut index = repo.index().unwrap(); - let root = repo.path().parent().unwrap(); + let root = repo.workdir().unwrap(); fs::create_dir(&root.join("foo")).unwrap(); File::create(&root.join("foo/bar")).unwrap(); index.add_path(Path::new("foo/bar")).unwrap(); diff --git a/src/lib.rs b/src/lib.rs index ace4009230..cb2e871cca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -131,6 +131,7 @@ pub use crate::time::{IndexTime, Time}; pub use crate::tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult}; pub use crate::treebuilder::TreeBuilder; pub use crate::util::IntoCString; +pub use crate::worktree::{Worktree, WorktreeAddOptions, WorktreeLockStatus, WorktreePruneOptions}; // Create a convinience method on bitflag struct which checks the given flag macro_rules! is_bit_set { @@ -686,6 +687,7 @@ mod tagforeach; mod time; mod tree; mod treebuilder; +mod worktree; fn init() { static INIT: Once = Once::new(); diff --git a/src/repo.rs b/src/repo.rs index 4f53ccb3fc..113112e8a2 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -16,6 +16,7 @@ use crate::stash::{stash_cb, StashApplyOptions, StashCbData}; use crate::string_array::StringArray; use crate::tagforeach::{tag_foreach_cb, TagForeachCB, TagForeachData}; use crate::util::{self, path_to_repo_path, Binding}; +use crate::worktree::{Worktree, WorktreeAddOptions}; use crate::CherrypickOptions; use crate::RevertOptions; use crate::{ @@ -162,6 +163,18 @@ impl Repository { } } + /// Attempt to open an already-existing repository from a worktree. + pub fn open_from_worktree(worktree: &Worktree) -> Result { + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_repository_open_from_worktree( + &mut ret, + worktree.raw() + )); + 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 @@ -2791,6 +2804,53 @@ impl Repository { Ok(Binding::from_raw(ret)) } } + + /// Lists all the worktrees for the repository + pub fn worktrees(&self) -> Result { + let mut arr = raw::git_strarray { + strings: ptr::null_mut(), + count: 0, + }; + unsafe { + try_call!(raw::git_worktree_list(&mut arr, self.raw)); + Ok(Binding::from_raw(arr)) + } + } + + /// Opens a worktree by name for the given repository + /// + /// This can open any worktree that the worktrees method returns. + pub fn find_worktree(&self, name: &str) -> Result { + let mut raw = ptr::null_mut(); + let raw_name = CString::new(name)?; + unsafe { + try_call!(raw::git_worktree_lookup(&mut raw, self.raw, raw_name)); + Ok(Binding::from_raw(raw)) + } + } + + /// Creates a new worktree for the repository + pub fn worktree<'a>( + &'a self, + name: &str, + path: &Path, + opts: Option<&WorktreeAddOptions<'a>>, + ) -> Result { + let mut raw = ptr::null_mut(); + let raw_name = CString::new(name)?; + let raw_path = path.into_c_string()?; + + unsafe { + try_call!(raw::git_worktree_add( + &mut raw, + self.raw, + raw_name, + raw_path, + opts.map(|o| o.raw()) + )); + Ok(Binding::from_raw(raw)) + } + } } impl Binding for Repository { diff --git a/src/test.rs b/src/test.rs index f21690e355..89a13beafe 100644 --- a/src/test.rs +++ b/src/test.rs @@ -6,7 +6,7 @@ use std::ptr; use tempfile::TempDir; use url::Url; -use crate::{Oid, Repository, RepositoryInitOptions}; +use crate::{Branch, Oid, Repository, RepositoryInitOptions}; macro_rules! t { ($e:expr) => { @@ -56,6 +56,14 @@ pub fn path2url(/service/path: &Path) -> String { Url::from_file_path(path).unwrap().to_string() } +pub fn worktrees_env_init(repo: &Repository) -> (TempDir, Branch<'_>) { + let oid = repo.head().unwrap().target().unwrap(); + let commit = repo.find_commit(oid).unwrap(); + let branch = repo.branch("wt-branch", &commit, true).unwrap(); + let wtdir = TempDir::new().unwrap(); + (wtdir, branch) +} + #[cfg(windows)] pub fn realpath(original: &Path) -> io::Result { Ok(original.to_path_buf()) diff --git a/src/worktree.rs b/src/worktree.rs new file mode 100644 index 0000000000..3cb75c6edf --- /dev/null +++ b/src/worktree.rs @@ -0,0 +1,331 @@ +use crate::buf::Buf; +use crate::reference::Reference; +use crate::repo::Repository; +use crate::util::{self, Binding}; +use crate::{raw, Error}; +use std::os::raw::c_int; +use std::path::Path; +use std::ptr; +use std::str; +use std::{marker, mem}; + +/// An owned git worktree +/// +/// This structure corresponds to a `git_worktree` in libgit2. +// +pub struct Worktree { + raw: *mut raw::git_worktree, +} + +/// Options which can be used to configure how a worktree is initialized +pub struct WorktreeAddOptions<'a> { + raw: raw::git_worktree_add_options, + _marker: marker::PhantomData>, +} + +/// Options to configure how worktree pruning is performed +pub struct WorktreePruneOptions { + raw: raw::git_worktree_prune_options, +} + +/// Lock Status of a worktree +#[derive(PartialEq, Debug)] +pub enum WorktreeLockStatus { + /// Worktree is Unlocked + Unlocked, + /// Worktree is locked with the optional message + Locked(Option), +} + +impl Worktree { + /// Open a worktree of a the repository + /// + /// If a repository is not the main tree but a worktree, this + /// function will look up the worktree inside the parent + /// repository and create a new `git_worktree` structure. + pub fn open_from_repository(repo: &Repository) -> Result { + let mut raw = ptr::null_mut(); + unsafe { + try_call!(raw::git_worktree_open_from_repository(&mut raw, repo.raw())); + Ok(Binding::from_raw(raw)) + } + } + + /// Retrieves the name of the worktree + /// + /// This is the name that can be passed to repo::Repository::find_worktree + /// to reopen the worktree. This is also the name that would appear in the + /// list returned by repo::Repository::worktrees + pub fn name(&self) -> Option<&str> { + unsafe { + crate::opt_bytes(self, raw::git_worktree_name(self.raw)) + .and_then(|s| str::from_utf8(s).ok()) + } + } + + /// Retrieves the path to the worktree + /// + /// This is the path to the top-level of the source and not the path to the + /// .git file within the worktree. This path can be passed to + /// repo::Repository::open. + pub fn path(&self) -> &Path { + unsafe { + util::bytes2path(crate::opt_bytes(self, raw::git_worktree_path(self.raw)).unwrap()) + } + } + + /// Validates the worktree + /// + /// This checks that it still exists on the + /// filesystem and that the metadata is correct + pub fn validate(&self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_worktree_validate(self.raw)); + } + Ok(()) + } + + /// Locks the worktree + pub fn lock(&self, reason: Option<&str>) -> Result<(), Error> { + let reason = crate::opt_cstr(reason)?; + unsafe { + try_call!(raw::git_worktree_lock(self.raw, reason)); + } + Ok(()) + } + + /// Unlocks the worktree + pub fn unlock(&self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_worktree_unlock(self.raw)); + } + Ok(()) + } + + /// Checks if worktree is locked + pub fn is_locked(&self) -> Result { + let buf = Buf::new(); + unsafe { + match try_call!(raw::git_worktree_is_locked(buf.raw(), self.raw)) { + 0 => Ok(WorktreeLockStatus::Unlocked), + _ => { + let v = buf.to_vec(); + Ok(WorktreeLockStatus::Locked(match v.len() { + 0 => None, + _ => Some(String::from_utf8(v).unwrap()), + })) + } + } + } + } + + /// Prunes the worktree + pub fn prune(&self, opts: Option<&mut WorktreePruneOptions>) -> Result<(), Error> { + // When successful the worktree should be removed however the backing structure + // of the git_worktree should still be valid. + unsafe { + try_call!(raw::git_worktree_prune(self.raw, opts.map(|o| o.raw()))); + } + Ok(()) + } + + /// Checks if the worktree is prunable + pub fn is_prunable(&self, opts: Option<&mut WorktreePruneOptions>) -> Result { + unsafe { + let rv = try_call!(raw::git_worktree_is_prunable( + self.raw, + opts.map(|o| o.raw()) + )); + Ok(rv != 0) + } + } +} + +impl<'a> WorktreeAddOptions<'a> { + /// Creates a default set of add options. + /// + /// By default this will not lock the worktree + pub fn new() -> WorktreeAddOptions<'a> { + unsafe { + let mut raw = mem::zeroed(); + assert_eq!( + raw::git_worktree_add_options_init(&mut raw, raw::GIT_WORKTREE_ADD_OPTIONS_VERSION), + 0 + ); + WorktreeAddOptions { + raw, + _marker: marker::PhantomData, + } + } + } + + /// If enabled, this will cause the newly added worktree to be locked + pub fn lock(&mut self, enabled: bool) -> &mut WorktreeAddOptions<'a> { + self.raw.lock = enabled as c_int; + self + } + + /// reference to use for the new worktree HEAD + pub fn reference( + &mut self, + reference: Option<&'a Reference<'_>>, + ) -> &mut WorktreeAddOptions<'a> { + self.raw.reference = if let Some(reference) = reference { + reference.raw() + } else { + ptr::null_mut() + }; + self + } + + /// Get a set of raw add options to be used with `git_worktree_add` + pub fn raw(&self) -> *const raw::git_worktree_add_options { + &self.raw + } +} + +impl WorktreePruneOptions { + /// Creates a default set of pruning options + /// + /// By defaults this will prune only worktrees that are no longer valid + /// unlocked and not checked out + pub fn new() -> WorktreePruneOptions { + unsafe { + let mut raw = mem::zeroed(); + assert_eq!( + raw::git_worktree_prune_options_init( + &mut raw, + raw::GIT_WORKTREE_PRUNE_OPTIONS_VERSION + ), + 0 + ); + WorktreePruneOptions { raw } + } + } + + /// Controls whether valid (still existing on the filesystem) worktrees + /// will be pruned + /// + /// Defaults to false + pub fn valid(&mut self, valid: bool) -> &mut WorktreePruneOptions { + self.flag(raw::GIT_WORKTREE_PRUNE_VALID, valid) + } + + /// Controls whether locked worktrees will be pruned + /// + /// Defaults to false + pub fn locked(&mut self, locked: bool) -> &mut WorktreePruneOptions { + self.flag(raw::GIT_WORKTREE_PRUNE_LOCKED, locked) + } + + /// Controls whether the actual working tree on the fs is recursively removed + /// + /// Defaults to false + pub fn working_tree(&mut self, working_tree: bool) -> &mut WorktreePruneOptions { + self.flag(raw::GIT_WORKTREE_PRUNE_WORKING_TREE, working_tree) + } + + fn flag(&mut self, flag: raw::git_worktree_prune_t, on: bool) -> &mut WorktreePruneOptions { + if on { + self.raw.flags |= flag as u32; + } else { + self.raw.flags &= !(flag as u32); + } + self + } + + /// Get a set of raw prune options to be used with `git_worktree_prune` + pub fn raw(&mut self) -> *mut raw::git_worktree_prune_options { + &mut self.raw + } +} + +impl Binding for Worktree { + type Raw = *mut raw::git_worktree; + unsafe fn from_raw(ptr: *mut raw::git_worktree) -> Worktree { + Worktree { raw: ptr } + } + fn raw(&self) -> *mut raw::git_worktree { + self.raw + } +} + +impl Drop for Worktree { + fn drop(&mut self) { + unsafe { raw::git_worktree_free(self.raw) } + } +} + +#[cfg(test)] +mod tests { + use crate::WorktreeAddOptions; + use crate::WorktreeLockStatus; + + use tempfile::TempDir; + + #[test] + fn smoke_add_no_ref() { + let (_td, repo) = crate::test::repo_init(); + + let wtdir = TempDir::new().unwrap(); + let wt_path = wtdir.path().join("tree-no-ref-dir"); + let opts = WorktreeAddOptions::new(); + + let wt = repo.worktree("tree-no-ref", &wt_path, Some(&opts)).unwrap(); + assert_eq!(wt.name(), Some("tree-no-ref")); + assert_eq!( + wt.path().canonicalize().unwrap(), + wt_path.canonicalize().unwrap() + ); + let status = wt.is_locked().unwrap(); + assert_eq!(status, WorktreeLockStatus::Unlocked); + } + + #[test] + fn smoke_add_locked() { + let (_td, repo) = crate::test::repo_init(); + + let wtdir = TempDir::new().unwrap(); + let wt_path = wtdir.path().join("locked-tree"); + let mut opts = WorktreeAddOptions::new(); + opts.lock(true); + + let wt = repo.worktree("locked-tree", &wt_path, Some(&opts)).unwrap(); + // shouldn't be able to lock a worktree that was created locked + assert!(wt.lock(Some("my reason")).is_err()); + assert_eq!(wt.name(), Some("locked-tree")); + assert_eq!( + wt.path().canonicalize().unwrap(), + wt_path.canonicalize().unwrap() + ); + assert_eq!(wt.is_locked().unwrap(), WorktreeLockStatus::Locked(None)); + assert!(wt.unlock().is_ok()); + assert!(wt.lock(Some("my reason")).is_ok()); + assert_eq!( + wt.is_locked().unwrap(), + WorktreeLockStatus::Locked(Some("my reason".to_string())) + ); + } + + #[test] + fn smoke_add_from_branch() { + let (_td, repo) = crate::test::repo_init(); + + let (wt_top, branch) = crate::test::worktrees_env_init(&repo); + let wt_path = wt_top.path().join("test"); + let mut opts = WorktreeAddOptions::new(); + let reference = branch.into_reference(); + opts.reference(Some(&reference)); + + let wt = repo + .worktree("test-worktree", &wt_path, Some(&opts)) + .unwrap(); + assert_eq!(wt.name(), Some("test-worktree")); + assert_eq!( + wt.path().canonicalize().unwrap(), + wt_path.canonicalize().unwrap() + ); + let status = wt.is_locked().unwrap(); + assert_eq!(status, WorktreeLockStatus::Unlocked); + } +} diff --git a/systest/build.rs b/systest/build.rs index 23a57bdc1e..eba93f3090 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -22,7 +22,9 @@ fn main() { }); cfg.skip_field(|struct_, f| { // this field is marked as const which ctest complains about - struct_ == "git_rebase_operation" && f == "id" + (struct_ == "git_rebase_operation" && f == "id") || + // the real name of this field is ref but that is a reserved keyword + (struct_ == "git_worktree_add_options" && f == "reference") }); cfg.skip_signededness(|s| { match s { From 0313adc9624b19cbfe7a7c432831cdd467a925c4 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 9 Dec 2020 07:43:36 -0800 Subject: [PATCH 514/860] Provide a binding for GIT_OPT_ENABLE_STRICT_OBJECT_CREATION (#638) * Simplify handling of bool option Rust supports converting a bool to a 0/1 integer via `as`, so we don't need to use an if. * Provide a binding for GIT_OPT_ENABLE_STRICT_OBJECT_CREATION --- src/opts.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/opts.rs b/src/opts.rs index 14e7d9a4bd..71fa4eadf4 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -2,6 +2,23 @@ use crate::raw; +/// Controls whether or not libgit2 will verify when writing an object that all +/// objects it references are valid. Enabled by default, but disabling this can +/// significantly improve performance, at the cost of potentially allowing the +/// creation of objects that reference invalid objects (due to programming +/// error or repository corruption). +pub fn strict_object_creation(enabled: bool) { + let error = unsafe { + raw::git_libgit2_opts( + raw::GIT_OPT_ENABLE_STRICT_OBJECT_CREATION as libc::c_int, + enabled as libc::c_int, + ) + }; + // This function cannot actually fail, but the function has an error return + // for other options that can. + debug_assert!(error >= 0); +} + /// Controls whether or not libgit2 will verify that objects loaded have the /// expected hash. Enabled by default, but disabling this can significantly /// improve performance, at the cost of relying on repository integrity @@ -10,7 +27,7 @@ pub fn strict_hash_verification(enabled: bool) { let error = unsafe { raw::git_libgit2_opts( raw::GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION as libc::c_int, - if enabled { 1 } else { 0 } as libc::c_int, + enabled as libc::c_int, ) }; // This function cannot actually fail, but the function has an error return From 9a1e9062809764887f3de2393c3717bb46150eda Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 11 Dec 2020 14:10:26 -0800 Subject: [PATCH 515/860] Add rerun-if-changed to libgit2-sys build script. (#640) --- libgit2-sys/build.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 81fb8638e1..6f97db215d 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -182,6 +182,10 @@ fn main() { println!("cargo:rustc-link-lib=framework=Security"); println!("cargo:rustc-link-lib=framework=CoreFoundation"); } + + rerun_if(Path::new("libgit2/include")); + rerun_if(Path::new("libgit2/src")); + rerun_if(Path::new("libgit2/deps")); } fn cp_r(from: impl AsRef, to: impl AsRef) { @@ -214,3 +218,13 @@ fn add_c_files(build: &mut cc::Build, path: impl AsRef) { } } } + +fn rerun_if(path: &Path) { + if path.is_dir() { + for entry in fs::read_dir(path).expect("read_dir") { + rerun_if(&entry.expect("entry").path()); + } + } else { + println!("cargo:rerun-if-changed={}", path.display()); + } +} From e42d59569156f964980cdf7fa481b64e08e31732 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 16 Dec 2020 12:30:29 -0800 Subject: [PATCH 516/860] Update libgit2 (#642) --- libgit2-sys/build.rs | 1 + libgit2-sys/lib.rs | 11 +++++++++++ libgit2-sys/libgit2 | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 6f97db215d..76aa687cf6 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -78,6 +78,7 @@ fn main() { // when when COMPILE_PCRE8 is not defined, which is the default. add_c_files(&mut cfg, "libgit2/deps/pcre"); + cfg.file("libgit2/src/allocators/failalloc.c"); cfg.file("libgit2/src/allocators/stdalloc.c"); if windows { diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 26f1cd0873..665a9c3332 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -456,6 +456,9 @@ pub struct git_cert_hostkey { pub hash_md5: [u8; 16], pub hash_sha1: [u8; 20], pub hash_sha256: [u8; 32], + pub raw_type: git_cert_ssh_raw_type_t, + pub hostkey: *const c_char, + pub hostkey_len: size_t, } #[repr(C)] @@ -473,6 +476,14 @@ git_enum! { } } +git_enum! { + pub enum git_cert_ssh_raw_type_t { + GIT_CERT_SSH_RAW_TYPE_UNKNOWN = 0, + GIT_CERT_SSH_RAW_TYPE_RSA = 1, + GIT_CERT_SSH_RAW_TYPE_DSS = 2, + } +} + git_enum! { pub enum git_diff_flag_t { GIT_DIFF_FLAG_BINARY = 1 << 0, diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 7f4fa17862..530d37beb2 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 7f4fa178629d559c037a1f72f79f79af9c1ef8ce +Subproject commit 530d37beb2731a2073f5298242825a803815c37c From 3a85308cc7114515574a612de4dbe0ced9904ef8 Mon Sep 17 00:00:00 2001 From: Alexander Ovchinnikov <8490695+Alovchin91@users.noreply.github.com> Date: Thu, 17 Dec 2020 01:37:01 +0100 Subject: [PATCH 517/860] Allow creating detached remotes (#641) * Add git_remote_create_detached fn definition * Add Remote::create_detached associated fn * Run cargo fmt * Init crate on detached remote create --- libgit2-sys/lib.rs | 1 + src/remote.rs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 665a9c3332..120df3a3b5 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2041,6 +2041,7 @@ extern "C" { repo: *mut git_repository, url: *const c_char, ) -> c_int; + pub fn git_remote_create_detached(out: *mut *mut git_remote, url: *const c_char) -> c_int; pub fn git_remote_delete(repo: *mut git_repository, name: *const c_char) -> c_int; pub fn git_remote_free(remote: *mut git_remote); pub fn git_remote_name(remote: *const git_remote) -> *const c_char; diff --git a/src/remote.rs b/src/remote.rs index 1b26db7f60..6fab0c73af 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -73,6 +73,22 @@ impl<'repo> Remote<'repo> { unsafe { raw::git_remote_is_valid_name(remote_name.as_ptr()) == 1 } } + /// Create a detached remote + /// + /// Create a remote with the given url in-memory. You can use this + /// when you have a URL instead of a remote's name. + /// Contrasted with an anonymous remote, a detached remote will not + /// consider any repo configuration values. + pub fn create_detached(url: &str) -> Result, Error> { + crate::init(); + let mut ret = ptr::null_mut(); + let url = CString::new(url)?; + unsafe { + try_call!(raw::git_remote_create_detached(&mut ret, url)); + Ok(Binding::from_raw(ret)) + } + } + /// Get the remote's name. /// /// Returns `None` if this remote has not yet been named or if the name is From dd6d3643cca21c55d23cc5a0bd6e72244a0448f8 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 17 Dec 2020 07:06:35 -0800 Subject: [PATCH 518/860] Sync config docs (#643) * Sync Config docs with libgit's docs. * Fix links. Rustdoc now warns about these not being properly linked. --- src/apply.rs | 4 ++-- src/config.rs | 29 ++++++++++++++++++++++++++++- src/repo.rs | 2 +- src/tagforeach.rs | 4 ++-- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/apply.rs b/src/apply.rs index d0796cdd4f..34dc811a01 100644 --- a/src/apply.rs +++ b/src/apply.rs @@ -1,12 +1,12 @@ //! git_apply support -//! see original: https://github.com/libgit2/libgit2/blob/master/include/git2/apply.h +//! see original: use crate::{panic, raw, util::Binding, DiffDelta, DiffHunk}; use libc::c_int; use std::{ffi::c_void, mem}; /// Possible application locations for git_apply -/// see https://libgit2.org/libgit2/#HEAD/type/git_apply_options +/// see #[derive(Copy, Clone, Debug)] pub enum ApplyLocation { /// Apply the patch to the workdir diff --git a/src/config.rs b/src/config.rs index edab9b3e02..66cd5bb4de 100644 --- a/src/config.rs +++ b/src/config.rs @@ -149,6 +149,8 @@ impl Config { /// Remove multivar config variables in the config file with the highest level (usually the /// local one). + /// + /// The regular expression is applied case-sensitively on the value. pub fn remove_multivar(&mut self, name: &str, regexp: &str) -> Result<(), Error> { let name = CString::new(name)?; let regexp = CString::new(regexp)?; @@ -204,6 +206,8 @@ impl Config { /// /// This is the same as `get_bytes` except that it may return `Err` if /// the bytes are not valid utf-8. + /// + /// This method will return an error if this `Config` is not a snapshot. pub fn get_str(&self, name: &str) -> Result<&str, Error> { str::from_utf8(self.get_bytes(name)?) .map_err(|_| Error::from_str("configuration value is not valid utf8")) @@ -223,6 +227,10 @@ impl Config { /// Get the value of a string config variable as an owned string. /// + /// All config files will be looked into, in the order of their + /// defined level. A higher level means a higher priority. The + /// first occurrence of the variable will be returned here. + /// /// An error will be returned if the config value is not valid utf-8. pub fn get_string(&self, name: &str) -> Result { let ret = Buf::new(); @@ -235,7 +243,15 @@ impl Config { .map_err(|_| Error::from_str("configuration value is not valid utf8")) } - /// Get the value of a path config variable as an owned . + /// Get the value of a path config variable as an owned `PathBuf`. + /// + /// A leading '~' will be expanded to the global search path (which + /// defaults to the user's home directory but can be overridden via + /// [`raw::git_libgit2_opts`]. + /// + /// All config files will be looked into, in the order of their + /// defined level. A higher level means a higher priority. The + /// first occurrence of the variable will be returned here. pub fn get_path(&self, name: &str) -> Result { let ret = Buf::new(); let name = CString::new(name)?; @@ -260,6 +276,10 @@ impl Config { /// If `glob` is `Some`, then the iterator will only iterate over all /// variables whose name matches the pattern. /// + /// The regular expression is applied case-sensitively on the normalized form of + /// the variable name: the section and variable parts are lower-cased. The + /// subsection is left unchanged. + /// /// # Example /// /// ``` @@ -293,6 +313,10 @@ impl Config { /// /// If `regexp` is `Some`, then the iterator will only iterate over all /// values which match the pattern. + /// + /// The regular expression is applied case-sensitively on the normalized form of + /// the variable name: the section and variable parts are lower-cased. The + /// subsection is left unchanged. pub fn multivar(&self, name: &str, regexp: Option<&str>) -> Result, Error> { let mut ret = ptr::null_mut(); let name = CString::new(name)?; @@ -363,6 +387,8 @@ impl Config { /// Set the value of an multivar config variable in the config file with the /// highest level (usually the local one). + /// + /// The regular expression is applied case-sensitively on the value. pub fn set_multivar(&mut self, name: &str, regexp: &str, value: &str) -> Result<(), Error> { let name = CString::new(name)?; let regexp = CString::new(regexp)?; @@ -398,6 +424,7 @@ impl Config { } /// Parse a string as a bool. + /// /// Interprets "true", "yes", "on", 1, or any non-zero number as true. /// Interprets "false", "no", "off", 0, or an empty string as false. pub fn parse_bool(s: S) -> Result { diff --git a/src/repo.rs b/src/repo.rs index 113112e8a2..17a54f34c5 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -313,7 +313,7 @@ impl Repository { /// Find a single object and intermediate reference by a revision string. /// /// See `man gitrevisions`, or - /// http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for + /// for /// information on the syntax accepted. /// /// In some cases (`@{<-n>}` or `@{upstream}`), the expression diff --git a/src/tagforeach.rs b/src/tagforeach.rs index c8018a44cf..425eea5a48 100644 --- a/src/tagforeach.rs +++ b/src/tagforeach.rs @@ -1,5 +1,5 @@ //! git_tag_foreach support -//! see original: https://libgit2.org/libgit2/#HEAD/group/tag/git_tag_foreach +//! see original: use crate::{panic, raw, util::Binding, Oid}; use libc::{c_char, c_int}; @@ -16,7 +16,7 @@ pub(crate) struct TagForeachData<'a> { } /// c callback forwarding to rust callback inside `TagForeachData` -/// see original: https://libgit2.org/libgit2/#HEAD/group/callback/git_tag_foreach_cb +/// see original: pub(crate) extern "C" fn tag_foreach_cb( name: *const c_char, oid: *mut git_oid, From ebd15ad3610b40d08f342bc047cb4381938545b3 Mon Sep 17 00:00:00 2001 From: Alex Kesling Date: Thu, 17 Dec 2020 14:23:52 -0500 Subject: [PATCH 519/860] Fix minor typo s/deriviative/derivative/ in docs (#644) --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index cb2e871cca..6a2b00f06a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,7 +61,7 @@ //! //! ## Working with a `Repository` //! -//! All deriviative objects, references, etc are attached to the lifetime of the +//! All derivative objects, references, etc are attached to the lifetime of the //! source `Repository`, to ensure that they do not outlive the repository //! itself. From 56bc2dc7e5751724fd98b008c1af44cc6dd430af Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 18 Dec 2020 07:48:03 -0800 Subject: [PATCH 520/860] Bump libgit2-sys to 0.12.15+1.1.0 --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2e2375a5b6..1a33e2fd6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.14" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.15" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index aa6838310a..1e2c285625 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.14+1.1.0" +version = "0.12.15+1.1.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 1ff740daecd2698004e0ce6185d58e040d3c4343 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 18 Dec 2020 07:49:30 -0800 Subject: [PATCH 521/860] Bump git2 to 0.13.13 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1a33e2fd6b..5e7119959e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.12" +version = "0.13.13" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 1cc1ef6b53dddb1d50f98931ab3a29d6fc87c439 Mon Sep 17 00:00:00 2001 From: Alexander Ovchinnikov <8490695+Alovchin91@users.noreply.github.com> Date: Mon, 21 Dec 2020 22:52:55 +0100 Subject: [PATCH 522/860] Update libgit2 to fix misalignment issue on arm64 (#646) Also update git_cert_ssh_t to include lost value --- libgit2-sys/lib.rs | 1 + libgit2-sys/libgit2 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 120df3a3b5..d34bd28d41 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -473,6 +473,7 @@ git_enum! { GIT_CERT_SSH_MD5 = 1 << 0, GIT_CERT_SSH_SHA1 = 1 << 1, GIT_CERT_SSH_SHA256 = 1 << 2, + GIT_CERT_SSH_RAW = 1 << 3, } } diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 530d37beb2..f4b473fa84 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 530d37beb2731a2073f5298242825a803815c37c +Subproject commit f4b473fa842a84147d8036a27bac5c026c44dad4 From 0e3781fa4571b44d56f8a101f48d989eb2bbac0e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 21 Dec 2020 13:53:33 -0800 Subject: [PATCH 523/860] Support turning a FileMode into a u32 (#647) Sometimes it's helpful to have the underlying numeric mode values, rather than the FileMode enum. Provide a From instance to turn FileMode into a u32. --- src/lib.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6a2b00f06a..2777749af4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1049,6 +1049,19 @@ pub enum FileMode { Commit, } +impl From for u32 { + fn from(mode: FileMode) -> u32 { + match mode { + FileMode::Unreadable => raw::GIT_FILEMODE_UNREADABLE as u32, + FileMode::Tree => raw::GIT_FILEMODE_TREE as u32, + FileMode::Blob => raw::GIT_FILEMODE_BLOB as u32, + FileMode::BlobExecutable => raw::GIT_FILEMODE_BLOB_EXECUTABLE as u32, + FileMode::Link => raw::GIT_FILEMODE_LINK as u32, + FileMode::Commit => raw::GIT_FILEMODE_COMMIT as u32, + } + } +} + bitflags! { /// Return codes for submodule status. /// @@ -1441,7 +1454,7 @@ impl Default for ReferenceFormat { #[cfg(test)] mod tests { - use super::ObjectType; + use super::{FileMode, ObjectType}; #[test] fn convert() { @@ -1449,4 +1462,10 @@ mod tests { assert_eq!(ObjectType::from_str("blob"), Some(ObjectType::Blob)); assert!(ObjectType::Blob.is_loose()); } + + #[test] + fn convert_filemode() { + assert_eq!(u32::from(FileMode::Blob), 0o100644); + assert_eq!(u32::from(FileMode::BlobExecutable), 0o100755); + } } From 0fdbcc02c394e9b1e1892b678c51bffeb93887df Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 21 Dec 2020 17:56:00 -0800 Subject: [PATCH 524/860] Support turning a FileMode into an i32 as well (#649) On some platforms, file modes use i32 rather than u32. Support both, for portability. --- src/lib.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 2777749af4..2a3444855b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1049,6 +1049,19 @@ pub enum FileMode { Commit, } +impl From for i32 { + fn from(mode: FileMode) -> i32 { + match mode { + FileMode::Unreadable => raw::GIT_FILEMODE_UNREADABLE as i32, + FileMode::Tree => raw::GIT_FILEMODE_TREE as i32, + FileMode::Blob => raw::GIT_FILEMODE_BLOB as i32, + FileMode::BlobExecutable => raw::GIT_FILEMODE_BLOB_EXECUTABLE as i32, + FileMode::Link => raw::GIT_FILEMODE_LINK as i32, + FileMode::Commit => raw::GIT_FILEMODE_COMMIT as i32, + } + } +} + impl From for u32 { fn from(mode: FileMode) -> u32 { match mode { @@ -1465,6 +1478,8 @@ mod tests { #[test] fn convert_filemode() { + assert_eq!(i32::from(FileMode::Blob), 0o100644); + assert_eq!(i32::from(FileMode::BlobExecutable), 0o100755); assert_eq!(u32::from(FileMode::Blob), 0o100644); assert_eq!(u32::from(FileMode::BlobExecutable), 0o100755); } From eca10db0640182657768e30dc6a92732854f5e21 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 21 Dec 2020 20:11:55 -0800 Subject: [PATCH 525/860] Bump git2 and libgit2-sys --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5e7119959e..2669484a7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.13" +version = "0.13.14" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.15" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.16" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 1e2c285625..bf4452987d 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.15+1.1.0" +version = "0.12.16+1.1.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 047f653390cd4653f38dff9bd81922a74f3f2561 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 21 Dec 2020 13:43:44 -0800 Subject: [PATCH 526/860] libgit2-sys: Add bindings for git_tree_create_updated and related types --- libgit2-sys/lib.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index d34bd28d41..f0b5c147eb 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -704,6 +704,21 @@ pub type git_treebuilder_filter_cb = pub type git_revwalk_hide_cb = Option c_int>; +git_enum! { + pub enum git_tree_update_t { + GIT_TREE_UPDATE_UPSERT = 0, + GIT_TREE_UPDATE_REMOVE = 1, + } +} + +#[repr(C)] +pub struct git_tree_update { + pub action: git_tree_update_t, + pub id: git_oid, + pub filemode: git_filemode_t, + pub path: *const c_char, +} + #[repr(C)] #[derive(Copy, Clone)] pub struct git_buf { @@ -2531,6 +2546,13 @@ extern "C" { callback: git_treewalk_cb, payload: *mut c_void, ) -> c_int; + pub fn git_tree_create_updated( + out: *mut git_oid, + repo: *mut git_repository, + baseline: *mut git_tree, + nupdates: usize, + updates: *const git_tree_update, + ) -> c_int; // treebuilder pub fn git_treebuilder_new( From d23a94fc2a6099fecc9437fce35d381b9ecb3c16 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 21 Dec 2020 15:37:49 -0800 Subject: [PATCH 527/860] Add TreeUpdateBuilder to support git_tree_create_updated git_tree_create_updated requires a length and a contiguous array of git_tree_update structures, each of which has a pointer to a C string. Create a builder, `TreeUpdateBuilder`, to wrap that safely without excessive copies. --- src/build.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 4 deletions(-) diff --git a/src/build.rs b/src/build.rs index 286b009f22..fd17848346 100644 --- a/src/build.rs +++ b/src/build.rs @@ -7,8 +7,8 @@ use std::path::Path; use std::ptr; use crate::util::{self, Binding}; -use crate::{panic, raw, Error, FetchOptions, IntoCString, Repository}; -use crate::{CheckoutNotificationType, DiffFile, Remote}; +use crate::{panic, raw, Error, FetchOptions, IntoCString, Oid, Repository, Tree}; +use crate::{CheckoutNotificationType, DiffFile, FileMode, Remote}; /// A builder struct which is used to build configuration for cloning a new git /// repository. @@ -64,6 +64,12 @@ pub struct RepoBuilder<'cb> { pub type RemoteCreate<'cb> = dyn for<'a> FnMut(&'a Repository, &str, &str) -> Result, Error> + 'cb; +/// A builder struct for git tree updates, for use with `git_tree_create_updated`. +pub struct TreeUpdateBuilder { + updates: Vec, + paths: Vec, +} + /// A builder struct for configuring checkouts of a repository. pub struct CheckoutBuilder<'cb> { their_label: Option, @@ -674,10 +680,79 @@ extern "C" fn notify_cb( .unwrap_or(2) } +impl Default for TreeUpdateBuilder { + fn default() -> Self { + Self::new() + } +} + +impl TreeUpdateBuilder { + /// Create a new empty series of updates. + pub fn new() -> Self { + Self { + updates: Vec::new(), + paths: Vec::new(), + } + } + + /// Add an update removing the specified `path` from a tree. + pub fn remove(&mut self, path: T) -> &mut Self { + let path = util::cstring_to_repo_path(path).unwrap(); + let path_ptr = path.as_ptr(); + self.paths.push(path); + self.updates.push(raw::git_tree_update { + action: raw::GIT_TREE_UPDATE_REMOVE, + id: raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }, + filemode: raw::GIT_FILEMODE_UNREADABLE, + path: path_ptr, + }); + self + } + + /// Add an update setting the specified `path` to a specific Oid, whether it currently exists + /// or not. + /// + /// Note that libgit2 does not support an upsert of a previously removed path, or an upsert + /// that changes the type of an object (such as from tree to blob or vice versa). + pub fn upsert(&mut self, path: T, id: Oid, filemode: FileMode) -> &mut Self { + let path = util::cstring_to_repo_path(path).unwrap(); + let path_ptr = path.as_ptr(); + self.paths.push(path); + self.updates.push(raw::git_tree_update { + action: raw::GIT_TREE_UPDATE_UPSERT, + id: unsafe { *id.raw() }, + filemode: u32::from(filemode) as raw::git_filemode_t, + path: path_ptr, + }); + self + } + + /// Create a new tree from the specified baseline and this series of updates. + /// + /// The baseline tree must exist in the specified repository. + pub fn create_updated(&mut self, repo: &Repository, baseline: &Tree<'_>) -> Result { + let mut ret = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; + unsafe { + try_call!(raw::git_tree_create_updated( + &mut ret, + repo.raw(), + baseline.raw(), + self.updates.len(), + self.updates.as_ptr() + )); + Ok(Binding::from_raw(&ret as *const _)) + } + } +} + #[cfg(test)] mod tests { - use super::{CheckoutBuilder, RepoBuilder}; - use crate::{CheckoutNotificationType, Repository}; + use super::{CheckoutBuilder, RepoBuilder, TreeUpdateBuilder}; + use crate::{CheckoutNotificationType, FileMode, Repository}; use std::fs; use std::path::Path; use tempfile::TempDir; @@ -707,6 +782,23 @@ mod tests { assert!(RepoBuilder::new().branch("foo").clone(&url, &dst).is_err()); } + #[test] + fn smoke_tree_create_updated() { + let (_tempdir, repo) = crate::test::repo_init(); + let (_, tree_id) = crate::test::commit(&repo); + let tree = t!(repo.find_tree(tree_id)); + assert!(tree.get_name("bar").is_none()); + let foo_id = tree.get_name("foo").unwrap().id(); + let tree2_id = t!(TreeUpdateBuilder::new() + .remove("foo") + .upsert("bar/baz", foo_id, FileMode::Blob) + .create_updated(&repo, &tree)); + let tree2 = t!(repo.find_tree(tree2_id)); + assert!(tree2.get_name("foo").is_none()); + let baz_id = tree2.get_path(Path::new("bar/baz")).unwrap().id(); + assert_eq!(foo_id, baz_id); + } + /// Issue regression test #365 #[test] fn notify_callback() { From ee8551e30c62200b9ae800f2e922a2e2bf51382c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 21 Dec 2020 21:46:23 -0800 Subject: [PATCH 528/860] Exclude more files from the published package. --- libgit2-sys/Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index bf4452987d..60bfd2c46a 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -8,6 +8,10 @@ repository = "https://github.com/rust-lang/git2-rs" license = "MIT/Apache-2.0" description = "Native bindings to the libgit2 library" exclude = [ + "libgit2/ci/*", + "libgit2/docs/*", + "libgit2/examples/*", + "libgit2/fuzzers/*", "libgit2/tests/*", ] edition = "2018" From 01a67148f6e31a15db9b8b9c280e00b8ff4abc9c Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Thu, 24 Dec 2020 15:29:28 -0500 Subject: [PATCH 529/860] Make Time::sign return a sane value The existing implementation returns quasi-garbage, because it's reading from the wrong field. The patch includes tests to exercise the broken scenario. --- src/time.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/time.rs b/src/time.rs index 92dc0b36ff..a01de7abb0 100644 --- a/src/time.rs +++ b/src/time.rs @@ -42,7 +42,7 @@ impl Time { /// Return whether the offset was positive or negative. Primarily useful /// in case the offset is specified as a negative zero. pub fn sign(&self) -> char { - self.raw.offset as u8 as char + self.raw.sign as u8 as char } } @@ -112,3 +112,16 @@ impl Ord for IndexTime { me.cmp(&other) } } + +#[cfg(test)] +mod tests { + use crate::Time; + + #[test] + fn smoke() { + assert_eq!(Time::new(1608839587, -300).seconds(), 1608839587); + assert_eq!(Time::new(1608839587, -300).offset_minutes(), -300); + assert_eq!(Time::new(1608839587, -300).sign(), '-'); + assert_eq!(Time::new(1608839587, 300).sign(), '+'); + } +} From 52a1ea771745cf149a557b4a47f147b90f7e50ba Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 28 Dec 2020 12:00:01 -0800 Subject: [PATCH 530/860] Bump crate versions --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2669484a7d..79fa1b098b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.14" +version = "0.13.15" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.16" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.17" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 60bfd2c46a..be3fc30254 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.16+1.1.0" +version = "0.12.17+1.1.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 3a20aeab82c1933bf4725faea9029e34f20cfa8e Mon Sep 17 00:00:00 2001 From: Igor Raits Date: Tue, 29 Dec 2020 14:01:43 +0100 Subject: [PATCH 531/860] chore: Update paste to 1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 79fa1b098b..32021c032a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ structopt = "0.3" time = "0.1.39" tempfile = "3.1.0" thread-id = "3.3.0" # remove when we work with minimal-versions without it -paste = "0.1.12" +paste = "1" [features] unstable = [] From c7492dfbba9d38a2b8897ee8ca81ba73b05685b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Kj=C3=A4ll?= Date: Mon, 4 Jan 2021 16:13:31 +0100 Subject: [PATCH 532/860] test for the Repository::config() function (#651) * test for verifying that the Repository::config() function returns a config object that have the local repo as highest prio * used the test::repo_init() helper method instead --- src/repo.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index 17a54f34c5..7eb02ca62a 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -3621,4 +3621,22 @@ mod tests { // reverting twice restores `foo` file assert!(foo_file.exists()); } + + #[test] + fn smoke_config_write_and_read() { + let (td, repo) = crate::test::repo_init(); + + let mut config = repo.config().unwrap(); + + config.set_bool("commit.gpgsign", false).unwrap(); + + let c = fs::read_to_string(td.path().join(".git").join("config")).unwrap(); + + assert!(c.contains("[commit]")); + assert!(c.contains("gpgsign = false")); + + let config = repo.config().unwrap(); + + assert!(!config.get_bool("commit.gpgsign").unwrap()); + } } From 5e379e6ae27c30913a9d01d7f526f7f7993fc2cf Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 4 Jan 2021 17:53:11 -0500 Subject: [PATCH 533/860] Add bindings for git_merge_analysis_for_ref (#655) This is a slightly generalised version of git_merge_analysis that allows specifying the ref to analyse against instead of using the repository's current HEAD. --- libgit2-sys/lib.rs | 9 +++++++ src/repo.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index f0b5c147eb..4daf997ce5 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -3116,6 +3116,15 @@ extern "C" { their_heads_len: usize, ) -> c_int; + pub fn git_merge_analysis_for_ref( + analysis_out: *mut git_merge_analysis_t, + pref_out: *mut git_merge_preference_t, + repo: *mut git_repository, + git_reference: *mut git_reference, + their_heads: *mut *const git_annotated_commit, + their_heads_len: usize, + ) -> c_int; + // notes pub fn git_note_author(note: *const git_note) -> *const git_signature; pub fn git_note_committer(note: *const git_note) -> *const git_signature; diff --git a/src/repo.rs b/src/repo.rs index 7eb02ca62a..5ecb64a67a 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1964,6 +1964,35 @@ impl Repository { } } + /// Analyzes the given branch(es) and determines the opportunities for + /// merging them into a reference. + pub fn merge_analysis_for_ref( + &self, + our_ref: &Reference<'_>, + their_heads: &[&AnnotatedCommit<'_>], + ) -> Result<(MergeAnalysis, MergePreference), Error> { + unsafe { + let mut raw_merge_analysis = 0 as raw::git_merge_analysis_t; + let mut raw_merge_preference = 0 as raw::git_merge_preference_t; + let mut their_heads = their_heads + .iter() + .map(|v| v.raw() as *const _) + .collect::>(); + try_call!(raw::git_merge_analysis_for_ref( + &mut raw_merge_analysis, + &mut raw_merge_preference, + self.raw, + our_ref.raw(), + their_heads.as_mut_ptr() as *mut _, + their_heads.len() + )); + Ok(( + MergeAnalysis::from_bits_truncate(raw_merge_analysis as u32), + MergePreference::from_bits_truncate(raw_merge_preference as u32), + )) + } + } + /// Initializes a rebase operation to rebase the changes in `branch` /// relative to `upstream` onto another branch. To begin the rebase process, /// call `next()`. @@ -3639,4 +3668,41 @@ mod tests { assert!(!config.get_bool("commit.gpgsign").unwrap()); } + + #[test] + fn smoke_merge_analysis_for_ref() -> Result<(), crate::Error> { + let (_td, repo) = graph_repo_init(); + + // Set up this repo state: + // * second (their-branch) + // * initial (HEAD -> main) + // + // We expect that their-branch can be fast-forward merged into main. + + // git checkout --detach HEAD + let head_commit = repo.head()?.peel_to_commit()?; + repo.set_head_detached(head_commit.id())?; + + // git branch their-branch HEAD + let their_branch = repo.branch("their-branch", &head_commit, false)?; + + // git branch -f main HEAD~ + let mut parents_iter = head_commit.parents(); + let parent = parents_iter.next().unwrap(); + assert!(parents_iter.next().is_none()); + + let main = repo.branch("main", &parent, true)?; + + // git checkout main + repo.set_head(main.get().name().expect("should be utf-8"))?; + + let (merge_analysis, _merge_preference) = repo.merge_analysis_for_ref( + main.get(), + &[&repo.reference_to_annotated_commit(their_branch.get())?], + )?; + + assert!(merge_analysis.contains(crate::MergeAnalysis::ANALYSIS_FASTFORWARD)); + + Ok(()) + } } From 252f41baf8003299cc8903a4981aeb107cf6c146 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 6 Jan 2021 23:18:47 +0800 Subject: [PATCH 534/860] Add git_libgit2_opts binding for get/set search path (#656) * fix: set ConfigLevel to corret integer * feat(opts): get/set/reset search path * test(opts): get/set/reset search path * fix: thread-safe get/set search path * fix: get_search_path will returns CString * refactor: remove Mutex and change to unsafe fn * refactor: search path test as a integration test --- src/lib.rs | 4 +-- src/opts.rs | 70 +++++++++++++++++++++++++++++++++++++++++-- tests/global_state.rs | 47 +++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 tests/global_state.rs diff --git a/src/lib.rs b/src/lib.rs index 2a3444855b..76e5e748ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -363,7 +363,7 @@ pub enum BranchType { #[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum ConfigLevel { /// System-wide on Windows, for compatibility with portable git - ProgramData, + ProgramData = 1, /// System-wide configuration file, e.g. /etc/gitconfig System, /// XDG-compatible configuration file, e.g. ~/.config/git/config @@ -375,7 +375,7 @@ pub enum ConfigLevel { /// Application specific configuration file App, /// Highest level available - Highest, + Highest = -1, } /// Merge file favor options for `MergeOptions` instruct the file-level diff --git a/src/opts.rs b/src/opts.rs index 71fa4eadf4..ca36804e92 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -1,6 +1,70 @@ //! Bindings to libgit2's git_libgit2_opts function. -use crate::raw; +use std::ffi::CString; + +use crate::util::Binding; +use crate::{call, raw, Buf, ConfigLevel, Error, IntoCString}; + +/// Set the search path for a level of config data. The search path applied to +/// shared attributes and ignore files, too. +/// +/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`], +/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`]. +/// +/// `path` lists directories delimited by `GIT_PATH_LIST_SEPARATOR`. +/// Use magic path `$PATH` to include the old value of the path +/// (if you want to prepend or append, for instance). +/// +/// This function is unsafe as it mutates the global state but cannot guarantee +/// thread-safety. It needs to be externally synchronized with calls to access +/// the global state. +pub unsafe fn set_search_path

(level: ConfigLevel, path: P) -> Result<(), Error> +where + P: IntoCString, +{ + call::c_try(raw::git_libgit2_opts( + raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int, + level as libc::c_int, + path.into_c_string()?.as_ptr(), + ))?; + Ok(()) +} + +/// Reset the search path for a given level of config data to the default +/// (generally based on environment variables). +/// +/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`], +/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`]. +/// +/// This function is unsafe as it mutates the global state but cannot guarantee +/// thread-safety. It needs to be externally synchronized with calls to access +/// the global state. +pub unsafe fn reset_search_path(level: ConfigLevel) -> Result<(), Error> { + call::c_try(raw::git_libgit2_opts( + raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int, + level as libc::c_int, + core::ptr::null::(), + ))?; + Ok(()) +} + +/// Get the search path for a given level of config data. +/// +/// `level` must be one of [`ConfigLevel::System`], [`ConfigLevel::Global`], +/// [`ConfigLevel::XDG`], [`ConfigLevel::ProgramData`]. +/// +/// This function is unsafe as it mutates the global state but cannot guarantee +/// thread-safety. It needs to be externally synchronized with calls to access +/// the global state. +pub unsafe fn get_search_path(level: ConfigLevel) -> Result { + let buf = Buf::new(); + call::c_try(raw::git_libgit2_opts( + raw::GIT_OPT_GET_SEARCH_PATH as libc::c_int, + level as libc::c_int, + buf.raw(), + ))?; + buf.into_c_string() +} /// Controls whether or not libgit2 will verify when writing an object that all /// objects it references are valid. Enabled by default, but disabling this can @@ -37,8 +101,10 @@ pub fn strict_hash_verification(enabled: bool) { #[cfg(test)] mod test { + use super::*; + #[test] fn smoke() { - super::strict_hash_verification(false); + strict_hash_verification(false); } } diff --git a/tests/global_state.rs b/tests/global_state.rs new file mode 100644 index 0000000000..192acdbd3a --- /dev/null +++ b/tests/global_state.rs @@ -0,0 +1,47 @@ +//! Test for some global state set up by libgit2's `git_libgit2_init` function +//! that need to be synchronized within a single process. + +use git2::opts; +use git2::{ConfigLevel, IntoCString}; + +// Test for mutating configuration file search path which is set during +// initialization in libgit2's `git_sysdir_global_init` function. +#[test] +fn search_path() -> Result<(), Box> { + use std::env::join_paths; + + let path = "fake_path"; + let original = unsafe { opts::get_search_path(ConfigLevel::Global) }; + assert_ne!(original, Ok(path.into_c_string()?)); + + // Set + unsafe { + opts::set_search_path(ConfigLevel::Global, &path)?; + } + assert_eq!( + unsafe { opts::get_search_path(ConfigLevel::Global) }, + Ok(path.into_c_string()?) + ); + + // Append + let paths = join_paths(["$PATH", path].iter())?; + let expected_paths = join_paths([path, path].iter())?.into_c_string()?; + unsafe { + opts::set_search_path(ConfigLevel::Global, paths)?; + } + assert_eq!( + unsafe { opts::get_search_path(ConfigLevel::Global) }, + Ok(expected_paths) + ); + + // Reset + unsafe { + opts::reset_search_path(ConfigLevel::Global)?; + } + assert_eq!( + unsafe { opts::get_search_path(ConfigLevel::Global) }, + original + ); + + Ok(()) +} From 53fd0fb8373b783ab8c5c95717132b769d8a077d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 19 Jan 2021 23:26:07 +0800 Subject: [PATCH 535/860] fix: call init() before setting global state (#661) --- src/opts.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/opts.rs b/src/opts.rs index ca36804e92..728d15e1cd 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -22,6 +22,7 @@ pub unsafe fn set_search_path

(level: ConfigLevel, path: P) -> Result<(), Erro where P: IntoCString, { + crate::init(); call::c_try(raw::git_libgit2_opts( raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int, level as libc::c_int, @@ -40,6 +41,7 @@ where /// thread-safety. It needs to be externally synchronized with calls to access /// the global state. pub unsafe fn reset_search_path(level: ConfigLevel) -> Result<(), Error> { + crate::init(); call::c_try(raw::git_libgit2_opts( raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int, level as libc::c_int, @@ -57,6 +59,7 @@ pub unsafe fn reset_search_path(level: ConfigLevel) -> Result<(), Error> { /// thread-safety. It needs to be externally synchronized with calls to access /// the global state. pub unsafe fn get_search_path(level: ConfigLevel) -> Result { + crate::init(); let buf = Buf::new(); call::c_try(raw::git_libgit2_opts( raw::GIT_OPT_GET_SEARCH_PATH as libc::c_int, From 171071d9f158a8c8fa0f8f60db136e1f8e671c44 Mon Sep 17 00:00:00 2001 From: Arlo Siemsen Date: Wed, 20 Jan 2021 14:34:19 -0800 Subject: [PATCH 536/860] Add useHttpPath support in CredentialHelper (#663) --- src/cred.rs | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/cred.rs b/src/cred.rs index c3a49939a6..a47cddba60 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -22,6 +22,7 @@ pub struct CredentialHelper { pub username: Option, protocol: Option, host: Option, + path: Option, url: String, commands: Vec, } @@ -198,6 +199,7 @@ impl CredentialHelper { let mut ret = CredentialHelper { protocol: None, host: None, + path: None, username: None, url: url.to_string(), commands: Vec::new(), @@ -208,7 +210,7 @@ impl CredentialHelper { if let Some(url::Host::Domain(s)) = url.host() { ret.host = Some(s.to_string()); } - ret.protocol = Some(url.scheme().to_string()) + ret.protocol = Some(url.scheme().to_string()); } ret } @@ -227,12 +229,11 @@ impl CredentialHelper { // Figure out the configured username/helper program. // // see http://git-scm.com/docs/gitcredentials.html#_configuration_options - // - // TODO: implement useHttpPath if self.username.is_none() { self.config_username(config); } self.config_helper(config); + self.config_use_http_path(config); self } @@ -261,6 +262,29 @@ impl CredentialHelper { self.add_command(global.as_ref().ok().map(|s| &s[..])); } + // Discover `useHttpPath` from `config` + fn config_use_http_path(&mut self, config: &Config) { + let mut use_http_path = false; + if let Some(value) = config.get_bool(&self.exact_key("useHttpPath")).ok() { + use_http_path = value; + } else if let Some(value) = self + .url_key("useHttpPath") + .and_then(|key| config.get_bool(&key).ok()) + { + use_http_path = value; + } else if let Some(value) = config.get_bool("credential.useHttpPath").ok() { + use_http_path = value; + } + + if use_http_path { + if let Ok(url) = url::Url::parse(&self.url) { + let path = url.path(); + // Url::parse always includes a leading slash for rooted URLs, while git does not. + self.path = Some(path.strip_prefix('/').unwrap_or(path).to_string()); + } + } + } + // Add a `helper` configured command to the list of commands to execute. // // see https://www.kernel.org/pub/software/scm/git/docs/technical @@ -386,6 +410,9 @@ impl CredentialHelper { if let Some(ref p) = self.host { let _ = writeln!(stdin, "host={}", p); } + if let Some(ref p) = self.path { + let _ = writeln!(stdin, "path={}", p); + } if let Some(ref p) = *username { let _ = writeln!(stdin, "username={}", p); } @@ -602,6 +629,16 @@ echo password=$2 assert_eq!(p, "b"); } + #[test] + fn credential_helper8() { + let cfg = test_cfg! { + "credential.useHttpPath" => "true" + }; + let mut helper = CredentialHelper::new("https://example.com/foo/bar"); + helper.config(&cfg); + assert_eq!(helper.path.as_deref(), Some("foo/bar")); + } + #[test] #[cfg(feature = "ssh")] fn ssh_key_from_memory() { From 6eb24a521c02716ae1f11f577176aa63af9ae3d6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Jan 2021 07:19:23 -0800 Subject: [PATCH 537/860] Bump git2-sys and git2 --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 32021c032a..0e022a8ecc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.15" +version = "0.13.16" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.17" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.18" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index be3fc30254..638c68b8aa 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.17+1.1.0" +version = "0.12.18+1.1.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 196c566c52f2c955c14c10c5ebb03ed55a8f2467 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 24 Jan 2021 15:19:12 -0800 Subject: [PATCH 538/860] Fix typos in DiffOptions documentation --- src/diff.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/diff.rs b/src/diff.rs index 2718cf8d0f..34d42b28f9 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -685,7 +685,7 @@ impl DiffOptions { self.flag(raw::GIT_DIFF_INCLUDE_UNTRACKED, include) } - /// Flag indicating whether untracked directories are deeply traversed or + /// Flag indicating whether untracked directories are traversed deeply or /// not. pub fn recurse_untracked_dirs(&mut self, recurse: bool) -> &mut DiffOptions { self.flag(raw::GIT_DIFF_RECURSE_UNTRACKED_DIRS, recurse) @@ -696,13 +696,13 @@ impl DiffOptions { self.flag(raw::GIT_DIFF_INCLUDE_UNMODIFIED, include) } - /// If entrabled, then Typechange delta records are generated. + /// If enabled, then Typechange delta records are generated. pub fn include_typechange(&mut self, include: bool) -> &mut DiffOptions { self.flag(raw::GIT_DIFF_INCLUDE_TYPECHANGE, include) } - /// Event with `include_typechange`, the tree treturned generally shows a - /// deleted blow. This flag correctly labels the tree transitions as a + /// Event with `include_typechange`, the tree returned generally shows a + /// deleted blob. This flag correctly labels the tree transitions as a /// typechange record with the `new_file`'s mode set to tree. /// /// Note that the tree SHA will not be available. @@ -763,7 +763,7 @@ impl DiffOptions { self.flag(raw::GIT_DIFF_INCLUDE_UNREADABLE, include) } - /// Include unreadable files in the diff + /// Include unreadable files in the diff as untracked files pub fn include_unreadable_as_untracked(&mut self, include: bool) -> &mut DiffOptions { self.flag(raw::GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED, include) } From 2e80d7492825eb93a886bf4f531b69e230c6d67a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 24 Jan 2021 15:19:39 -0800 Subject: [PATCH 539/860] Fix DiffOptions::force_binary to pass the correct flag force_binary was passing GIT_DIFF_FORCE_TEXT (like force_text); change it to pass GIT_DIFF_FORCE_BINARY. --- src/diff.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diff.rs b/src/diff.rs index 34d42b28f9..29957fb144 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -775,7 +775,7 @@ impl DiffOptions { /// Treat all files as binary, disabling text diffs pub fn force_binary(&mut self, force: bool) -> &mut DiffOptions { - self.flag(raw::GIT_DIFF_FORCE_TEXT, force) + self.flag(raw::GIT_DIFF_FORCE_BINARY, force) } /// Ignore all whitespace From 3d905e66a77af6f1c9e3d771aee84218398894b6 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 24 Jan 2021 15:33:05 -0800 Subject: [PATCH 540/860] git2 0.13.17 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 0e022a8ecc..4135894104 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.16" +version = "0.13.17" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 1b9ebc6457d75ea9101ae3b568319bab50173631 Mon Sep 17 00:00:00 2001 From: Joel Nises Date: Sun, 24 Jan 2021 18:28:04 +0100 Subject: [PATCH 541/860] add methods for setting min and max line in blame options --- src/blame.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/blame.rs b/src/blame.rs index 3132992ea7..7db275229c 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -228,6 +228,18 @@ impl BlameOptions { } self } + + /// The first line in the file to blame. + pub fn min_line(&mut self, lineno: usize) -> &mut BlameOptions { + self.raw.min_line = lineno; + self + } + + /// The last line in the file to blame. + pub fn max_line(&mut self, lineno: usize) -> &mut BlameOptions { + self.raw.max_line = lineno; + self + } } impl<'repo> Binding for Blame<'repo> { From 05c57f3b471289c663f567f85321c95132e37c89 Mon Sep 17 00:00:00 2001 From: Christian Schilling Date: Tue, 2 Feb 2021 17:16:22 +0100 Subject: [PATCH 542/860] Expose git_revwalk_hide_cb (#667) * Expose git_revwalk_hide_cb * Handle panic in revwalk hide callback * Propagate panic instead of converting to Err * Use wrapper struct for hide callback This has a few advantages over the previous attempt: - No changes to the existing Revwalk and it's Iterator implementation. Meaning also no additional panic::check() in next() if there is no hide callback. - No Boxing - No dyn - No Option - Correct lifetimes, no 'static So overall quite a bit less indirection which is good considering that this callback will be called on potentially every commit in the walk. * Remove mut from hide callback --- src/revwalk.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/src/revwalk.rs b/src/revwalk.rs index 00152a2e32..7730551092 100644 --- a/src/revwalk.rs +++ b/src/revwalk.rs @@ -1,9 +1,9 @@ -use libc::c_uint; +use libc::{c_int, c_uint, c_void}; use std::ffi::CString; use std::marker; use crate::util::Binding; -use crate::{raw, Error, Oid, Repository, Sort}; +use crate::{panic, raw, Error, Oid, Repository, Sort}; /// A revwalk allows traversal of the commit graph defined by including one or /// more leaves and excluding one or more roots. @@ -12,6 +12,39 @@ pub struct Revwalk<'repo> { _marker: marker::PhantomData<&'repo Repository>, } +/// A `Revwalk` with an assiciated "hide callback", see `with_hide_callback` +pub struct RevwalkWithHideCb<'repo, 'cb, C> +where + C: FnMut(Oid) -> bool, +{ + revwalk: Revwalk<'repo>, + _marker: marker::PhantomData<&'cb C>, +} + +extern "C" fn revwalk_hide_cb(commit_id: *const raw::git_oid, payload: *mut c_void) -> c_int +where + C: FnMut(Oid) -> bool, +{ + panic::wrap(|| unsafe { + let hide_cb = payload as *mut C; + if (*hide_cb)(Oid::from_raw(commit_id)) { + return 1; + } + return 0; + }) + .unwrap_or(-1) +} + +impl<'repo, 'cb, C: FnMut(Oid) -> bool> RevwalkWithHideCb<'repo, 'cb, C> { + /// Consumes the `RevwalkWithHideCb` and returns the contained `Revwalk`. + /// + /// Note that this will reset the `Revwalk`. + pub fn into_inner(mut self) -> Result, Error> { + self.revwalk.reset()?; + Ok(self.revwalk) + } +} + impl<'repo> Revwalk<'repo> { /// Reset a revwalk to allow re-configuring it. /// @@ -119,6 +152,29 @@ impl<'repo> Revwalk<'repo> { Ok(()) } + /// Hide all commits for which the callback returns true from + /// the walk. + pub fn with_hide_callback<'cb, C>( + self, + callback: &'cb C, + ) -> Result, Error> + where + C: FnMut(Oid) -> bool, + { + let r = RevwalkWithHideCb { + revwalk: self, + _marker: marker::PhantomData, + }; + unsafe { + raw::git_revwalk_add_hide_cb( + r.revwalk.raw(), + Some(revwalk_hide_cb::), + callback as *const _ as *mut c_void, + ); + }; + Ok(r) + } + /// Hide the repository's HEAD /// /// For more information, see `hide`. @@ -191,6 +247,15 @@ impl<'repo> Iterator for Revwalk<'repo> { } } +impl<'repo, 'cb, C: FnMut(Oid) -> bool> Iterator for RevwalkWithHideCb<'repo, 'cb, C> { + type Item = Result; + fn next(&mut self) -> Option> { + let out = self.revwalk.next(); + crate::panic::check(); + out + } +} + #[cfg(test)] mod tests { #[test] @@ -216,4 +281,35 @@ mod tests { walk.hide_head().unwrap(); assert_eq!(walk.by_ref().count(), 0); } + + #[test] + fn smoke_hide_cb() { + let (_td, repo) = crate::test::repo_init(); + let head = repo.head().unwrap(); + let target = head.target().unwrap(); + + let mut walk = repo.revwalk().unwrap(); + walk.push(target).unwrap(); + + let oids: Vec = walk.by_ref().collect::, _>>().unwrap(); + + assert_eq!(oids.len(), 1); + assert_eq!(oids[0], target); + + walk.reset().unwrap(); + walk.push_head().unwrap(); + assert_eq!(walk.by_ref().count(), 1); + + walk.reset().unwrap(); + walk.push_head().unwrap(); + + let hide_cb = |oid| oid == target; + let mut walk = walk.with_hide_callback(&hide_cb).unwrap(); + + assert_eq!(walk.by_ref().count(), 0); + + let mut walk = walk.into_inner().unwrap(); + walk.push_head().unwrap(); + assert_eq!(walk.by_ref().count(), 1); + } } From 772ca9a12f23b335b85f8531fb19dfc48d065b70 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 2 Feb 2021 08:25:51 -0800 Subject: [PATCH 543/860] Fix a warning --- src/packbuilder.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/packbuilder.rs b/src/packbuilder.rs index 1cdb0fe7cb..e20bf2a97c 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -21,7 +21,7 @@ pub type ForEachCb<'a> = dyn FnMut(&[u8]) -> bool + 'a; /// A builder for creating a packfile pub struct PackBuilder<'repo> { raw: *mut raw::git_packbuilder, - progress: Option>>>, + _progress: Option>>>, _marker: marker::PhantomData<&'repo Repository>, } @@ -122,7 +122,7 @@ impl<'repo> PackBuilder<'repo> { ptr as *mut _ )); } - self.progress = Some(progress); + self._progress = Some(progress); Ok(()) } @@ -135,7 +135,7 @@ impl<'repo> PackBuilder<'repo> { None, ptr::null_mut() )); - self.progress = None; + self._progress = None; } Ok(()) } @@ -174,7 +174,7 @@ impl<'repo> Binding for PackBuilder<'repo> { unsafe fn from_raw(ptr: *mut raw::git_packbuilder) -> PackBuilder<'repo> { PackBuilder { raw: ptr, - progress: None, + _progress: None, _marker: marker::PhantomData, } } From 3db0adaf6a6b3e90afee2087d9f0816a3021d6bb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Feb 2021 07:20:26 -0800 Subject: [PATCH 544/860] Use `std::panic::resume_unwind` Lots of time has passed since this was first written! --- src/panic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panic.rs b/src/panic.rs index 70038d910c..3e1b208bc7 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -24,7 +24,7 @@ pub fn wrap T + std::panic::UnwindSafe>(f: F) -> Option { pub fn check() { let err = LAST_ERROR.with(|slot| slot.borrow_mut().take()); if let Some(err) = err { - panic!(err) + std::panic::resume_unwind(err); } } From 455098a8a1ce24305faf690264fc5b636d210739 Mon Sep 17 00:00:00 2001 From: "A. Cody Schuffelen" Date: Tue, 9 Feb 2021 07:21:12 -0800 Subject: [PATCH 545/860] Expose the git_commit_header_field function. (#669) This accesses individual header fields in the object database representation of commit objects. These header fields can be seen by running the following command in a git repository: git cat-file -p $(git rev-parse HEAD) --- src/commit.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/commit.rs b/src/commit.rs index 6ff815d0b4..ec5cff22ad 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -6,7 +6,7 @@ use std::ptr; use std::str; use crate::util::Binding; -use crate::{raw, signature, Error, Object, Oid, Signature, Time, Tree}; +use crate::{raw, signature, Buf, Error, IntoCString, Object, Oid, Signature, Time, Tree}; /// A structure to represent a git [commit][1] /// @@ -105,6 +105,20 @@ impl<'repo> Commit<'repo> { str::from_utf8(self.raw_header_bytes()).ok() } + /// Get an arbitrary header field. + pub fn header_field_bytes(&self, field: T) -> Result { + let buf = Buf::new(); + let raw_field = field.into_c_string()?; + unsafe { + try_call!(raw::git_commit_header_field( + buf.raw(), + &*self.raw, + raw_field + )); + } + Ok(buf) + } + /// Get the full raw text of the commit header. pub fn raw_header_bytes(&self) -> &[u8] { unsafe { crate::opt_bytes(self, raw::git_commit_raw_header(&*self.raw)).unwrap() } @@ -367,6 +381,11 @@ mod tests { commit.tree().unwrap(); assert_eq!(commit.parents().count(), 0); + let tree_header_bytes = commit.header_field_bytes("tree").unwrap(); + assert_eq!( + crate::Oid::from_str(tree_header_bytes.as_str().unwrap()).unwrap(), + commit.tree_id() + ); assert_eq!(commit.author().name(), Some("name")); assert_eq!(commit.author().email(), Some("email")); assert_eq!(commit.committer().name(), Some("name")); From 65c0dccdf6640d2a832395f0c5d2db763f36628d Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Wed, 24 Feb 2021 23:44:03 +0800 Subject: [PATCH 546/860] Add bindings for `git_attr_value()` (#671) * Add bindings for `git_attr_value()` * Move `git_attr_value()` bindings to a submodule * Change `attr_value(_bytes)` to associate functions `AttrValue(Bytes)::new` * Unify `AttrValue` and `AttrValueBytes` --- src/attr.rs | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + src/repo.rs | 16 +++++ 3 files changed, 183 insertions(+) create mode 100644 src/attr.rs diff --git a/src/attr.rs b/src/attr.rs new file mode 100644 index 0000000000..6161c1fb31 --- /dev/null +++ b/src/attr.rs @@ -0,0 +1,165 @@ +use crate::raw; +use std::ptr; +use std::str; + +/// All possible states of an attribute. +/// +/// This enum is used to interpret the value returned by +/// [`Repository::get_attr`](crate::Repository::get_attr) and +/// [`Repository::get_attr_bytes`](crate::Repository::get_attr_bytes). +#[derive(Debug, Clone, Copy, Eq)] +pub enum AttrValue<'string> { + /// The attribute is set to true. + True, + /// The attribute is unset (set to false). + False, + /// The attribute is set to a [valid UTF-8 string](prim@str). + String(&'string str), + /// The attribute is set to a non-UTF-8 string. + Bytes(&'string [u8]), + /// The attribute is not specified. + Unspecified, +} + +impl<'string> AttrValue<'string> { + /// Returns the state of an attribute by inspecting its [value](crate::Repository::get_attr) + /// by a [string](prim@str). + /// + /// As [`str`](prim@str) is guaranteed to contain only valid UTF-8, this function never returns + /// [`AttrValue::Bytes`]. + pub fn from_string(value: Option<&'string str>) -> Self { + match unsafe { raw::git_attr_value(value.map_or(ptr::null(), |v| v.as_ptr().cast())) } { + raw::GIT_ATTR_VALUE_TRUE => Self::True, + raw::GIT_ATTR_VALUE_FALSE => Self::False, + raw::GIT_ATTR_VALUE_STRING => Self::String(value.unwrap()), + raw::GIT_ATTR_VALUE_UNSPECIFIED => Self::Unspecified, + _ => unreachable!(), + } + } + + /// Returns the state of an attribute by inspecting its [value](crate::Repository::get_attr_bytes) + /// by a [byte](u8) [slice]. + pub fn from_bytes(value: Option<&'string [u8]>) -> Self { + match unsafe { raw::git_attr_value(value.map_or(ptr::null(), |v| v.as_ptr().cast())) } { + raw::GIT_ATTR_VALUE_TRUE => Self::True, + raw::GIT_ATTR_VALUE_FALSE => Self::False, + raw::GIT_ATTR_VALUE_STRING => { + let value = value.unwrap(); + if let Ok(string) = str::from_utf8(value) { + Self::String(string) + } else { + Self::Bytes(value) + } + } + raw::GIT_ATTR_VALUE_UNSPECIFIED => Self::Unspecified, + _ => unreachable!(), + } + } +} + +/// Compare two [`AttrValue`]s. +/// +/// Note that this implementation does not differentiate [`AttrValue::String`] and +/// [`AttrValue::Bytes`]. +impl PartialEq for AttrValue<'_> { + fn eq(&self, other: &AttrValue<'_>) -> bool { + match (self, other) { + (Self::True, AttrValue::True) + | (Self::False, AttrValue::False) + | (Self::Unspecified, AttrValue::Unspecified) => true, + (AttrValue::String(string), AttrValue::Bytes(bytes)) + | (Self::Bytes(bytes), AttrValue::String(string)) => string.as_bytes() == *bytes, + (Self::String(left), AttrValue::String(right)) => left == right, + (Self::Bytes(left), AttrValue::Bytes(right)) => left == right, + _ => false, + } + } +} + +#[cfg(test)] +mod tests { + use super::AttrValue; + use std::ffi::CStr; + use std::os::raw::c_char; + + extern "C" { + // libgit2 defines them as mutable, so they are also declared mutable here. + // However, libgit2 never mutates them, thus it's always safe to access them in Rust. + static mut git_attr__true: *const c_char; + static mut git_attr__false: *const c_char; + static mut git_attr__unset: *const c_char; + } + + macro_rules! test_attr_value_from { + ($function:ident, $variant:ident) => { + let attr_true = unsafe { CStr::from_ptr(git_attr__true) }.to_str().unwrap(); + let attr_false = unsafe { CStr::from_ptr(git_attr__false) }.to_str().unwrap(); + let attr_unset = unsafe { CStr::from_ptr(git_attr__unset) }.to_str().unwrap(); + assert_eq!( + AttrValue::$function(Some(attr_true.to_owned().as_ref())), + AttrValue::$variant(attr_true.as_ref()) + ); + assert_eq!( + AttrValue::$function(Some(attr_false.to_owned().as_ref())), + AttrValue::$variant(attr_false.as_ref()) + ); + assert_eq!( + AttrValue::$function(Some(attr_unset.to_owned().as_ref())), + AttrValue::$variant(attr_unset.as_ref()) + ); + assert_eq!( + AttrValue::$function(Some("foo".as_ref())), + AttrValue::$variant("foo".as_ref()) + ); + assert_eq!( + AttrValue::$function(Some("bar".as_ref())), + AttrValue::$variant("bar".as_ref()) + ); + assert_eq!( + AttrValue::$function(Some(attr_true.as_ref())), + AttrValue::True + ); + assert_eq!( + AttrValue::$function(Some(attr_false.as_ref())), + AttrValue::False + ); + assert_eq!( + AttrValue::$function(Some(attr_unset.as_ref())), + AttrValue::Unspecified + ); + assert_eq!(AttrValue::$function(None), AttrValue::Unspecified); + }; + } + + #[test] + fn attr_value_from_string() { + test_attr_value_from!(from_string, String); + } + + #[test] + fn attr_value_from_bytes() { + test_attr_value_from!(from_bytes, Bytes); + } + + #[test] + fn attr_value_partial_eq() { + assert_eq!(AttrValue::True, AttrValue::True); + assert_eq!(AttrValue::False, AttrValue::False); + assert_eq!(AttrValue::String("foo"), AttrValue::String("foo")); + assert_eq!(AttrValue::Bytes(b"foo"), AttrValue::Bytes(b"foo")); + assert_eq!(AttrValue::String("bar"), AttrValue::Bytes(b"bar")); + assert_eq!(AttrValue::Bytes(b"bar"), AttrValue::String("bar")); + assert_eq!(AttrValue::Unspecified, AttrValue::Unspecified); + assert_ne!(AttrValue::True, AttrValue::False); + assert_ne!(AttrValue::False, AttrValue::Unspecified); + assert_ne!(AttrValue::Unspecified, AttrValue::True); + assert_ne!(AttrValue::True, AttrValue::String("true")); + assert_ne!(AttrValue::Unspecified, AttrValue::Bytes(b"unspecified")); + assert_ne!(AttrValue::Bytes(b"false"), AttrValue::False); + assert_ne!(AttrValue::String("unspecified"), AttrValue::Unspecified); + assert_ne!(AttrValue::String("foo"), AttrValue::String("bar")); + assert_ne!(AttrValue::Bytes(b"foo"), AttrValue::Bytes(b"bar")); + assert_ne!(AttrValue::String("foo"), AttrValue::Bytes(b"bar")); + assert_ne!(AttrValue::Bytes(b"foo"), AttrValue::String("bar")); + } +} diff --git a/src/lib.rs b/src/lib.rs index 76e5e748ab..fa2ace46e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,6 +80,7 @@ use std::str; use std::sync::Once; pub use crate::apply::{ApplyLocation, ApplyOptions}; +pub use crate::attr::AttrValue; pub use crate::blame::{Blame, BlameHunk, BlameIter, BlameOptions}; pub use crate::blob::{Blob, BlobWriter}; pub use crate::branch::{Branch, Branches}; @@ -633,6 +634,7 @@ impl MergePreference { mod test; #[macro_use] mod panic; +mod attr; mod call; mod util; diff --git a/src/repo.rs b/src/repo.rs index 5ecb64a67a..abda5d62ab 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -952,6 +952,14 @@ impl Repository { } /// Get the value of a git attribute for a path as a string. + /// + /// This function will return a special string if the attribute is set to a special value. + /// Interpreting the special string is discouraged. You should always use + /// [`AttrValue::from_string`](crate::AttrValue::from_string) to interpret the return value + /// and avoid the special string. + /// + /// As such, the return type of this function will probably be changed in the next major version + /// to prevent interpreting the returned string without checking whether it's special. pub fn get_attr( &self, path: &Path, @@ -964,6 +972,14 @@ impl Repository { } /// Get the value of a git attribute for a path as a byte slice. + /// + /// This function will return a special byte slice if the attribute is set to a special value. + /// Interpreting the special byte slice is discouraged. You should always use + /// [`AttrValue::from_bytes`](crate::AttrValue::from_bytes) to interpret the return value and + /// avoid the special string. + /// + /// As such, the return type of this function will probably be changed in the next major version + /// to prevent interpreting the returned byte slice without checking whether it's special. pub fn get_attr_bytes( &self, path: &Path, From 0909647aaff6caed37d9d9d079f2628757b3e365 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Tue, 2 Mar 2021 23:21:59 +0800 Subject: [PATCH 547/860] Add an additional binding for `git_attr_value()` that skips UTF-8 validation (#673) * Add an additional binding for `git_attr_value()` that skips UTF-8 validation * Make `AttrValue::from_bytes` call `AttrValue::always_bytes` --- src/attr.rs | 114 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 41 deletions(-) diff --git a/src/attr.rs b/src/attr.rs index 6161c1fb31..77c66b1609 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -15,51 +15,59 @@ pub enum AttrValue<'string> { False, /// The attribute is set to a [valid UTF-8 string](prim@str). String(&'string str), - /// The attribute is set to a non-UTF-8 string. + /// The attribute is set to a string that might not be [valid UTF-8](prim@str). Bytes(&'string [u8]), /// The attribute is not specified. Unspecified, } -impl<'string> AttrValue<'string> { - /// Returns the state of an attribute by inspecting its [value](crate::Repository::get_attr) - /// by a [string](prim@str). - /// - /// As [`str`](prim@str) is guaranteed to contain only valid UTF-8, this function never returns - /// [`AttrValue::Bytes`]. - pub fn from_string(value: Option<&'string str>) -> Self { - match unsafe { raw::git_attr_value(value.map_or(ptr::null(), |v| v.as_ptr().cast())) } { +macro_rules! from_value { + ($value:expr => $string:expr) => { + match unsafe { raw::git_attr_value($value.map_or(ptr::null(), |v| v.as_ptr().cast())) } { raw::GIT_ATTR_VALUE_TRUE => Self::True, raw::GIT_ATTR_VALUE_FALSE => Self::False, - raw::GIT_ATTR_VALUE_STRING => Self::String(value.unwrap()), + raw::GIT_ATTR_VALUE_STRING => $string, raw::GIT_ATTR_VALUE_UNSPECIFIED => Self::Unspecified, _ => unreachable!(), } + }; +} + +impl<'string> AttrValue<'string> { + /// Returns the state of an attribute by inspecting its [value](crate::Repository::get_attr) + /// by a [string](prim@str). + /// + /// This function always returns [`AttrValue::String`] and never returns [`AttrValue::Bytes`] + /// when the attribute is set to a string. + pub fn from_string(value: Option<&'string str>) -> Self { + from_value!(value => Self::String(value.unwrap())) } /// Returns the state of an attribute by inspecting its [value](crate::Repository::get_attr_bytes) /// by a [byte](u8) [slice]. + /// + /// This function will perform UTF-8 validation when the attribute is set to a string, returns + /// [`AttrValue::String`] if it's valid UTF-8 and [`AttrValue::Bytes`] otherwise. pub fn from_bytes(value: Option<&'string [u8]>) -> Self { - match unsafe { raw::git_attr_value(value.map_or(ptr::null(), |v| v.as_ptr().cast())) } { - raw::GIT_ATTR_VALUE_TRUE => Self::True, - raw::GIT_ATTR_VALUE_FALSE => Self::False, - raw::GIT_ATTR_VALUE_STRING => { - let value = value.unwrap(); - if let Ok(string) = str::from_utf8(value) { - Self::String(string) - } else { - Self::Bytes(value) - } + let mut value = Self::always_bytes(value); + if let Self::Bytes(bytes) = value { + if let Ok(string) = str::from_utf8(bytes) { + value = Self::String(string); } - raw::GIT_ATTR_VALUE_UNSPECIFIED => Self::Unspecified, - _ => unreachable!(), } + value + } + + /// Returns the state of an attribute just like [`AttrValue::from_bytes`], but skips UTF-8 + /// validation and always returns [`AttrValue::Bytes`] when it's set to a string. + pub fn always_bytes(value: Option<&'string [u8]>) -> Self { + from_value!(value => Self::Bytes(value.unwrap())) } } /// Compare two [`AttrValue`]s. /// -/// Note that this implementation does not differentiate [`AttrValue::String`] and +/// Note that this implementation does not differentiate between [`AttrValue::String`] and /// [`AttrValue::Bytes`]. impl PartialEq for AttrValue<'_> { fn eq(&self, other: &AttrValue<'_>) -> bool { @@ -90,31 +98,34 @@ mod tests { static mut git_attr__unset: *const c_char; } - macro_rules! test_attr_value_from { + macro_rules! test_attr_value { ($function:ident, $variant:ident) => { let attr_true = unsafe { CStr::from_ptr(git_attr__true) }.to_str().unwrap(); let attr_false = unsafe { CStr::from_ptr(git_attr__false) }.to_str().unwrap(); let attr_unset = unsafe { CStr::from_ptr(git_attr__unset) }.to_str().unwrap(); - assert_eq!( + let as_bytes = AsRef::<[u8]>::as_ref; + // Use `matches!` here since the `PartialEq` implementation does not differentiate + // between `String` and `Bytes`. + assert!(matches!( AttrValue::$function(Some(attr_true.to_owned().as_ref())), - AttrValue::$variant(attr_true.as_ref()) - ); - assert_eq!( + AttrValue::$variant(s) if as_bytes(s) == attr_true.as_bytes() + )); + assert!(matches!( AttrValue::$function(Some(attr_false.to_owned().as_ref())), - AttrValue::$variant(attr_false.as_ref()) - ); - assert_eq!( + AttrValue::$variant(s) if as_bytes(s) == attr_false.as_bytes() + )); + assert!(matches!( AttrValue::$function(Some(attr_unset.to_owned().as_ref())), - AttrValue::$variant(attr_unset.as_ref()) - ); - assert_eq!( + AttrValue::$variant(s) if as_bytes(s) == attr_unset.as_bytes() + )); + assert!(matches!( AttrValue::$function(Some("foo".as_ref())), - AttrValue::$variant("foo".as_ref()) - ); - assert_eq!( + AttrValue::$variant(s) if as_bytes(s) == b"foo" + )); + assert!(matches!( AttrValue::$function(Some("bar".as_ref())), - AttrValue::$variant("bar".as_ref()) - ); + AttrValue::$variant(s) if as_bytes(s) == b"bar" + )); assert_eq!( AttrValue::$function(Some(attr_true.as_ref())), AttrValue::True @@ -133,12 +144,33 @@ mod tests { #[test] fn attr_value_from_string() { - test_attr_value_from!(from_string, String); + test_attr_value!(from_string, String); } #[test] fn attr_value_from_bytes() { - test_attr_value_from!(from_bytes, Bytes); + test_attr_value!(from_bytes, String); + assert!(matches!( + AttrValue::from_bytes(Some(&[0xff])), + AttrValue::Bytes(&[0xff]) + )); + assert!(matches!( + AttrValue::from_bytes(Some(b"\xffoobar")), + AttrValue::Bytes(b"\xffoobar") + )); + } + + #[test] + fn attr_value_always_bytes() { + test_attr_value!(always_bytes, Bytes); + assert!(matches!( + AttrValue::always_bytes(Some(&[0xff; 2])), + AttrValue::Bytes(&[0xff, 0xff]) + )); + assert!(matches!( + AttrValue::always_bytes(Some(b"\xffoo")), + AttrValue::Bytes(b"\xffoo") + )); } #[test] From 79863cba582fcb57bacac39b4514b61175c790b6 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 5 Mar 2021 01:58:24 +0800 Subject: [PATCH 548/860] Expose git_remote_stop and git_remote_prune (#674) * feat(remote): add git_remote_stop * feat(remote): add git_remote_prune --- src/remote.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/remote.rs b/src/remote.rs index 6fab0c73af..aa4a552a0d 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -221,6 +221,17 @@ impl<'repo> Remote<'repo> { Ok(()) } + /// Cancel the operation + /// + /// At certain points in its operation, the network code checks whether the + /// operation has been cancelled and if so stops the operation. + pub fn stop(&mut self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_remote_stop(self.raw)); + } + Ok(()) + } + /// Get the number of refspecs for a remote pub fn refspecs(&self) -> Refspecs<'_> { let cnt = unsafe { raw::git_remote_refspec_count(&*self.raw) as usize }; @@ -345,6 +356,15 @@ impl<'repo> Remote<'repo> { } } + /// Prune tracking refs that are no longer present on remote + pub fn prune(&mut self, callbacks: Option>) -> Result<(), Error> { + let cbs = Box::new(callbacks.unwrap_or_else(RemoteCallbacks::new)); + unsafe { + try_call!(raw::git_remote_prune(self.raw, &cbs.raw())); + } + Ok(()) + } + /// Get the remote's list of fetch refspecs pub fn fetch_refspecs(&self) -> Result { unsafe { @@ -636,7 +656,7 @@ mod tests { drop(repo); let repo = t!(Repository::init(td.path())); - let origin = t!(repo.find_remote("origin")); + let mut origin = t!(repo.find_remote("origin")); assert_eq!(origin.name(), Some("origin")); assert_eq!(origin.url(), Some("/path/to/nowhere")); assert_eq!(origin.pushurl(), None); @@ -646,6 +666,8 @@ mod tests { let stats = origin.stats(); assert_eq!(stats.total_objects(), 0); + + t!(origin.stop()); } #[test] @@ -847,4 +869,46 @@ mod tests { let commit = repo.find_commit(commit).unwrap(); assert_eq!(commit.message(), Some("initial")); } + + #[test] + fn prune() { + let (td, remote_repo) = crate::test::repo_init(); + let oid = remote_repo.head().unwrap().target().unwrap(); + let commit = remote_repo.find_commit(oid).unwrap(); + remote_repo.branch("stale", &commit, true).unwrap(); + + let td2 = TempDir::new().unwrap(); + let url = crate::test::path2url(https://github.com/&td.path()); + let repo = Repository::clone(&url, &td2).unwrap(); + + fn assert_branch_count(repo: &Repository, count: usize) { + assert_eq!( + repo.branches(Some(crate::BranchType::Remote)) + .unwrap() + .filter(|b| b.as_ref().unwrap().0.name().unwrap() == Some("origin/stale")) + .count(), + count, + ); + } + + assert_branch_count(&repo, 1); + + // delete `stale` branch on remote repo + let mut stale_branch = remote_repo + .find_branch("stale", crate::BranchType::Local) + .unwrap(); + stale_branch.delete().unwrap(); + + // prune + let mut remote = repo.find_remote("origin").unwrap(); + remote.connect(Direction::Push).unwrap(); + let mut callbacks = RemoteCallbacks::new(); + callbacks.update_tips(|refname, _a, b| { + assert_eq!(refname, "refs/remotes/origin/stale"); + assert!(b.is_zero()); + true + }); + remote.prune(Some(callbacks)).unwrap(); + assert_branch_count(&repo, 0); + } } From 7b636354f8f699812a645209ddba12f9ef6fcf25 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 5 Mar 2021 01:58:46 +0800 Subject: [PATCH 549/860] refactor: use try_call instead of call::c_try (#675) --- src/opts.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/opts.rs b/src/opts.rs index 728d15e1cd..789034d41d 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -3,7 +3,7 @@ use std::ffi::CString; use crate::util::Binding; -use crate::{call, raw, Buf, ConfigLevel, Error, IntoCString}; +use crate::{raw, Buf, ConfigLevel, Error, IntoCString}; /// Set the search path for a level of config data. The search path applied to /// shared attributes and ignore files, too. @@ -23,11 +23,11 @@ where P: IntoCString, { crate::init(); - call::c_try(raw::git_libgit2_opts( + try_call!(raw::git_libgit2_opts( raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int, level as libc::c_int, - path.into_c_string()?.as_ptr(), - ))?; + path.into_c_string()?.as_ptr() + )); Ok(()) } @@ -42,11 +42,11 @@ where /// the global state. pub unsafe fn reset_search_path(level: ConfigLevel) -> Result<(), Error> { crate::init(); - call::c_try(raw::git_libgit2_opts( + try_call!(raw::git_libgit2_opts( raw::GIT_OPT_SET_SEARCH_PATH as libc::c_int, level as libc::c_int, - core::ptr::null::(), - ))?; + core::ptr::null::() + )); Ok(()) } @@ -61,11 +61,11 @@ pub unsafe fn reset_search_path(level: ConfigLevel) -> Result<(), Error> { pub unsafe fn get_search_path(level: ConfigLevel) -> Result { crate::init(); let buf = Buf::new(); - call::c_try(raw::git_libgit2_opts( + try_call!(raw::git_libgit2_opts( raw::GIT_OPT_GET_SEARCH_PATH as libc::c_int, level as libc::c_int, - buf.raw(), - ))?; + buf.raw() as *const _ + )); buf.into_c_string() } From ab986a32a40a0ed036e9db233464b312934bafdd Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 5 Mar 2021 01:59:27 +0800 Subject: [PATCH 550/860] Add git_submodule_set_* bindings (#676) * feat: SubmoduleUpdate <-> git_submodule_update_t * feat: convert from raw for SubmoduleUpdate & SubmoduleIgnore * feat: add git_submodule_update_strategy & git_submodule_ignore * feat: add git_submodule_set_* bindings --- libgit2-sys/lib.rs | 1 + src/call.rs | 16 ++++++- src/lib.rs | 54 ++++++++++++++++++++++ src/repo.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++- src/submodule.rs | 12 ++++- 5 files changed, 189 insertions(+), 4 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 4daf997ce5..c4ae5219ae 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2409,6 +2409,7 @@ extern "C" { ) -> c_int; pub fn git_submodule_free(submodule: *mut git_submodule); pub fn git_submodule_head_id(submodule: *mut git_submodule) -> *const git_oid; + pub fn git_submodule_ignore(submodule: *mut git_submodule) -> git_submodule_ignore_t; pub fn git_submodule_index_id(submodule: *mut git_submodule) -> *const git_oid; pub fn git_submodule_init(submodule: *mut git_submodule, overwrite: c_int) -> c_int; pub fn git_submodule_location(status: *mut c_uint, submodule: *mut git_submodule) -> c_int; diff --git a/src/call.rs b/src/call.rs index f1ade4a8f3..d9fd234681 100644 --- a/src/call.rs +++ b/src/call.rs @@ -58,7 +58,9 @@ mod impls { use crate::call::Convert; use crate::{raw, BranchType, ConfigLevel, Direction, ObjectType, ResetType}; - use crate::{AutotagOption, DiffFormat, FetchPrune, FileFavor, SubmoduleIgnore}; + use crate::{ + AutotagOption, DiffFormat, FetchPrune, FileFavor, SubmoduleIgnore, SubmoduleUpdate, + }; impl Convert for T { fn convert(&self) -> T { @@ -209,6 +211,18 @@ mod impls { } } + impl Convert for SubmoduleUpdate { + fn convert(&self) -> raw::git_submodule_update_t { + match *self { + SubmoduleUpdate::Checkout => raw::GIT_SUBMODULE_UPDATE_CHECKOUT, + SubmoduleUpdate::Rebase => raw::GIT_SUBMODULE_UPDATE_REBASE, + SubmoduleUpdate::Merge => raw::GIT_SUBMODULE_UPDATE_MERGE, + SubmoduleUpdate::None => raw::GIT_SUBMODULE_UPDATE_NONE, + SubmoduleUpdate::Default => raw::GIT_SUBMODULE_UPDATE_DEFAULT, + } + } + } + impl Convert for AutotagOption { fn convert(&self) -> raw::git_remote_autotag_option_t { match *self { diff --git a/src/lib.rs b/src/lib.rs index fa2ace46e2..8689ff88ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -931,6 +931,34 @@ impl ConfigLevel { } } +impl SubmoduleIgnore { + /// Converts a [`raw::git_submodule_ignore_t`] to a [`SubmoduleIgnore`] + pub fn from_raw(raw: raw::git_submodule_ignore_t) -> Self { + match raw { + raw::GIT_SUBMODULE_IGNORE_UNSPECIFIED => SubmoduleIgnore::Unspecified, + raw::GIT_SUBMODULE_IGNORE_NONE => SubmoduleIgnore::None, + raw::GIT_SUBMODULE_IGNORE_UNTRACKED => SubmoduleIgnore::Untracked, + raw::GIT_SUBMODULE_IGNORE_DIRTY => SubmoduleIgnore::Dirty, + raw::GIT_SUBMODULE_IGNORE_ALL => SubmoduleIgnore::All, + n => panic!("unknown submodule ignore rule: {}", n), + } + } +} + +impl SubmoduleUpdate { + /// Converts a [`raw::git_submodule_update_t`] to a [`SubmoduleUpdate`] + pub fn from_raw(raw: raw::git_submodule_update_t) -> Self { + match raw { + raw::GIT_SUBMODULE_UPDATE_CHECKOUT => SubmoduleUpdate::Checkout, + raw::GIT_SUBMODULE_UPDATE_REBASE => SubmoduleUpdate::Rebase, + raw::GIT_SUBMODULE_UPDATE_MERGE => SubmoduleUpdate::Merge, + raw::GIT_SUBMODULE_UPDATE_NONE => SubmoduleUpdate::None, + raw::GIT_SUBMODULE_UPDATE_DEFAULT => SubmoduleUpdate::Default, + n => panic!("unknown submodule update strategy: {}", n), + } + } +} + bitflags! { /// Status flags for a single file /// @@ -1173,6 +1201,7 @@ impl SubmoduleStatus { /// These values represent settings for the `submodule.$name.ignore` /// configuration value which says how deeply to look at the working /// directory when getting the submodule status. +#[derive(Debug)] pub enum SubmoduleIgnore { /// Use the submodule's configuration Unspecified, @@ -1186,6 +1215,31 @@ pub enum SubmoduleIgnore { All, } +/// Submodule update values +/// +/// These values represent settings for the `submodule.$name.update` +/// configuration value which says how to handle `git submodule update` +/// for this submodule. The value is usually set in the ".gitmodules" +/// file and copied to ".git/config" when the submodule is initialized. +#[derive(Debug)] +pub enum SubmoduleUpdate { + /// The default; when a submodule is updated, checkout the new detached + /// HEAD to the submodule directory. + Checkout, + /// Update by rebasing the current checked out branch onto the commit from + /// the superproject. + Rebase, + /// Update by merging the commit in the superproject into the current + /// checkout out branch of the submodule. + Merge, + /// Do not update this submodule even when the commit in the superproject + /// is updated. + None, + /// Not used except as static initializer when we don't want any particular + /// update rule to be specified. + Default, +} + bitflags! { /// ... pub struct PathspecFlags: u32 { diff --git a/src/repo.rs b/src/repo.rs index abda5d62ab..464c9289b4 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -24,7 +24,8 @@ use crate::{ StashFlags, }; use crate::{ - AnnotatedCommit, MergeAnalysis, MergeOptions, MergePreference, SubmoduleIgnore, SubmoduleStatus, + AnnotatedCommit, MergeAnalysis, MergeOptions, MergePreference, SubmoduleIgnore, + SubmoduleStatus, SubmoduleUpdate, }; use crate::{ApplyLocation, ApplyOptions, Rebase, RebaseOptions}; use crate::{Blame, BlameOptions, Reference, References, ResetType, Signature, Submodule}; @@ -1635,6 +1636,62 @@ impl Repository { Ok(SubmoduleStatus::from_bits_truncate(ret as u32)) } + /// Set the ignore rule for the submodule in the configuration + /// + /// This does not affect any currently-loaded instances. + pub fn submodule_set_ignore( + &mut self, + name: &str, + ignore: SubmoduleIgnore, + ) -> Result<(), Error> { + let name = CString::new(name)?; + unsafe { + try_call!(raw::git_submodule_set_ignore(self.raw(), name, ignore)); + } + Ok(()) + } + + /// Set the update rule for the submodule in the configuration + /// + /// This setting won't affect any existing instances. + pub fn submodule_set_update( + &mut self, + name: &str, + update: SubmoduleUpdate, + ) -> Result<(), Error> { + let name = CString::new(name)?; + unsafe { + try_call!(raw::git_submodule_set_update(self.raw(), name, update)); + } + Ok(()) + } + + /// Set the URL for the submodule in the configuration + /// + /// After calling this, you may wish to call [`Submodule::sync`] to write + /// the changes to the checked out submodule repository. + pub fn submodule_set_url(https://github.com/&mut%20self,%20name:%20&str,%20url:%20&str) -> Result<(), Error> { + let name = CString::new(name)?; + let url = CString::new(url)?; + unsafe { + try_call!(raw::git_submodule_set_url(https://github.com/self.raw(), name, url)); + } + Ok(()) + } + + /// Set the branch for the submodule in the configuration + /// + /// After calling this, you may wish to call [`Submodule::sync`] to write + /// the changes to the checked out submodule repository. + pub fn submodule_set_branch(&mut self, name: &str, branch_name: &str) -> Result<(), Error> { + let name = CString::new(name)?; + let branch_name = CString::new(branch_name)?; + unsafe { + try_call!(raw::git_submodule_set_branch(self.raw(), name, branch_name)); + } + Ok(()) + } + /// Lookup a reference to one of the objects in a repository. pub fn find_tree(&self, oid: Oid) -> Result, Error> { let mut raw = ptr::null_mut(); @@ -3078,7 +3135,7 @@ impl RepositoryInitOptions { mod tests { use crate::build::CheckoutBuilder; use crate::CherrypickOptions; - use crate::{ObjectType, Oid, Repository, ResetType}; + use crate::{ObjectType, Oid, Repository, ResetType, SubmoduleIgnore, SubmoduleUpdate}; use std::ffi::OsStr; use std::fs; use std::path::Path; @@ -3721,4 +3778,53 @@ mod tests { Ok(()) } + + #[test] + fn smoke_submodule_set() -> Result<(), crate::Error> { + let (td1, _repo) = crate::test::repo_init(); + let (td2, mut repo2) = crate::test::repo_init(); + let url = crate::test::path2url(https://github.com/td1.path()); + let name = "bar"; + { + let mut s = repo2.submodule(&url, Path::new(name), true)?; + fs::remove_dir_all(td2.path().join("bar")).unwrap(); + Repository::clone(&url, td2.path().join("bar"))?; + s.add_to_index(false)?; + s.add_finalize()?; + } + + // update strategy + repo2.submodule_set_update(name, SubmoduleUpdate::None)?; + assert!(matches!( + repo2.find_submodule(name)?.update_strategy(), + SubmoduleUpdate::None + )); + repo2.submodule_set_update(name, SubmoduleUpdate::Rebase)?; + assert!(matches!( + repo2.find_submodule(name)?.update_strategy(), + SubmoduleUpdate::Rebase + )); + + // ignore rule + repo2.submodule_set_ignore(name, SubmoduleIgnore::Untracked)?; + assert!(matches!( + repo2.find_submodule(name)?.ignore_rule(), + SubmoduleIgnore::Untracked + )); + repo2.submodule_set_ignore(name, SubmoduleIgnore::Dirty)?; + assert!(matches!( + repo2.find_submodule(name)?.ignore_rule(), + SubmoduleIgnore::Dirty + )); + + // url + repo2.submodule_set_url(https://github.com/name,%20%22fake-url")?; + assert_eq!(repo2.find_submodule(name)?.url(), Some("fake-url")); + + // branch + repo2.submodule_set_branch(name, "fake-branch")?; + assert_eq!(repo2.find_submodule(name)?.branch(), Some("fake-branch")); + + Ok(()) + } } diff --git a/src/submodule.rs b/src/submodule.rs index 135f52fd57..c8f72efbde 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -5,8 +5,8 @@ use std::path::Path; use std::ptr; use std::str; -use crate::build::CheckoutBuilder; use crate::util::{self, Binding}; +use crate::{build::CheckoutBuilder, SubmoduleIgnore, SubmoduleUpdate}; use crate::{raw, Error, FetchOptions, Oid, Repository}; /// A structure to represent a git [submodule][1] @@ -113,6 +113,16 @@ impl<'repo> Submodule<'repo> { unsafe { Binding::from_raw_opt(raw::git_submodule_wd_id(self.raw)) } } + /// Get the ignore rule that will be used for the submodule. + pub fn ignore_rule(&self) -> SubmoduleIgnore { + SubmoduleIgnore::from_raw(unsafe { raw::git_submodule_ignore(self.raw) }) + } + + /// Get the update rule that will be used for the submodule. + pub fn update_strategy(&self) -> SubmoduleUpdate { + SubmoduleUpdate::from_raw(unsafe { raw::git_submodule_update_strategy(self.raw) }) + } + /// Copy submodule info into ".git/config" file. /// /// Just like "git submodule init", this copies information about the From cd88194ed3932b863fcd9e0bbecc9f9248294d9c Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Fri, 5 Mar 2021 16:24:13 +0100 Subject: [PATCH 551/860] add accessor for internal remote wrapped in RemoteConnection (#677) --- src/remote.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/remote.rs b/src/remote.rs index aa4a552a0d..042a3caa45 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -634,6 +634,11 @@ impl<'repo, 'connection, 'cb> RemoteConnection<'repo, 'connection, 'cb> { pub fn default_branch(&self) -> Result { self.remote.default_branch() } + + /// access remote bound to this connection + pub fn remote(&mut self) -> &mut Remote<'repo> { + self.remote + } } impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb> { From 57b2a87d640a2e9ee4497ee2dad0d0decfdbb5ff Mon Sep 17 00:00:00 2001 From: SeongChan Lee Date: Fri, 12 Mar 2021 06:36:21 +0900 Subject: [PATCH 552/860] Implement git_diff_patchid (#678) --- libgit2-sys/lib.rs | 17 +++++++++++++++++ src/diff.rs | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index c4ae5219ae..a1b0e48946 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1246,6 +1246,13 @@ pub const GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION: c_uint = 1; pub const GIT_DIFF_FORMAT_EMAIL_NONE: u32 = 0; pub const GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER: u32 = 1 << 0; +#[repr(C)] +pub struct git_diff_patchid_options { + pub version: c_uint, +} + +pub const GIT_DIFF_PATCHID_OPTIONS_VERSION: c_uint = 1; + #[repr(C)] pub struct git_diff_binary { pub contains_data: c_uint, @@ -3435,6 +3442,16 @@ extern "C" { version: c_uint, ) -> c_int; + pub fn git_diff_patchid( + out: *mut git_oid, + diff: *mut git_diff, + opts: *mut git_diff_patchid_options, + ) -> c_int; + pub fn git_diff_patchid_options_init( + opts: *mut git_diff_patchid_options, + version: c_uint, + ) -> c_int; + // patch pub fn git_patch_from_diff(out: *mut *mut git_patch, diff: *mut git_diff, idx: size_t) -> c_int; diff --git a/src/diff.rs b/src/diff.rs index 29957fb144..2ac23e2c77 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -58,6 +58,11 @@ pub struct DiffFormatEmailOptions { raw: raw::git_diff_format_email_options, } +/// Control behavior of formatting emails +pub struct DiffPatchidOptions { + raw: raw::git_diff_patchid_options, +} + /// An iterator over the diffs in a delta pub struct Deltas<'diff> { range: Range, @@ -278,6 +283,21 @@ impl<'repo> Diff<'repo> { Ok(buf) } + /// Create an patchid from a diff. + pub fn patchid(&self, opts: Option<&mut DiffPatchidOptions>) -> Result { + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; + unsafe { + try_call!(raw::git_diff_patchid( + &mut raw, + self.raw, + opts.map(|o| &mut o.raw) + )); + Ok(Binding::from_raw(&raw as *const _)) + } + } + // TODO: num_deltas_of_type, find_similar } impl Diff<'static> { @@ -1433,9 +1453,29 @@ impl DiffFormatEmailOptions { } } +impl DiffPatchidOptions { + /// Creates a new set of patchid options, + /// initialized to the default values + pub fn new() -> Self { + let mut opts = DiffPatchidOptions { + raw: unsafe { mem::zeroed() }, + }; + assert_eq!( + unsafe { + raw::git_diff_patchid_options_init( + &mut opts.raw, + raw::GIT_DIFF_PATCHID_OPTIONS_VERSION, + ) + }, + 0 + ); + opts + } +} + #[cfg(test)] mod tests { - use crate::{DiffOptions, Signature, Time}; + use crate::{DiffOptions, Oid, Signature, Time}; use std::borrow::Borrow; use std::fs::File; use std::io::Write; @@ -1450,6 +1490,8 @@ mod tests { assert_eq!(stats.insertions(), 0); assert_eq!(stats.deletions(), 0); assert_eq!(stats.files_changed(), 0); + let patchid = diff.patchid(None).unwrap(); + assert_ne!(patchid, Oid::zero()); } #[test] From 64920c827feb670f58e56b55463d3ec2b689b02d Mon Sep 17 00:00:00 2001 From: Knut Franke <43853514+sckfranke@users.noreply.github.com> Date: Tue, 16 Mar 2021 15:11:34 +0100 Subject: [PATCH 553/860] Fix handling of URLs with port in credential.helper (#682) Credentials stored by Git for the URL `https://example.com:3000/foo/bar` use `host=example.com:3000`. A CredentialHelper object for the same URL currently queries the credential helper with `host=example.com` and thus can't access the stored credentials. --- src/cred.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/cred.rs b/src/cred.rs index a47cddba60..41ff1c193b 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -22,6 +22,7 @@ pub struct CredentialHelper { pub username: Option, protocol: Option, host: Option, + port: Option, path: Option, url: String, commands: Vec, @@ -199,6 +200,7 @@ impl CredentialHelper { let mut ret = CredentialHelper { protocol: None, host: None, + port: None, path: None, username: None, url: url.to_string(), @@ -210,6 +212,7 @@ impl CredentialHelper { if let Some(url::Host::Domain(s)) = url.host() { ret.host = Some(s.to_string()); } + ret.port = url.port(); ret.protocol = Some(url.scheme().to_string()); } ret @@ -408,7 +411,11 @@ impl CredentialHelper { let _ = writeln!(stdin, "protocol={}", p); } if let Some(ref p) = self.host { - let _ = writeln!(stdin, "host={}", p); + if let Some(ref p2) = self.port { + let _ = writeln!(stdin, "host={}:{}", p, p2); + } else { + let _ = writeln!(stdin, "host={}", p); + } } if let Some(ref p) = self.path { let _ = writeln!(stdin, "path={}", p); @@ -639,6 +646,19 @@ echo password=$2 assert_eq!(helper.path.as_deref(), Some("foo/bar")); } + #[test] + fn credential_helper9() { + let cfg = test_cfg! { + "credential.helper" => "!f() { while read line; do eval $line; done; if [ \"$host\" = example.com:3000 ]; then echo username=a; echo password=b; fi; }; f" + }; + let (u, p) = CredentialHelper::new("https://example.com:3000/foo/bar") + .config(&cfg) + .execute() + .unwrap(); + assert_eq!(u, "a"); + assert_eq!(p, "b"); + } + #[test] #[cfg(feature = "ssh")] fn ssh_key_from_memory() { From 8d22454ac498919c30b7cdded4d0b4ab5eaed0fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= Date: Thu, 18 Mar 2021 14:26:42 -0400 Subject: [PATCH 554/860] transport: correctly handle rpc parameter (#684) When rpc is off, libgit2 reuses the stream allocated during upload-pack-ls or receive-pack-ls. The previous API forced the user of the API to create a new stream even if rpc was false. Issue: #681 --- src/transport.rs | 51 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/transport.rs b/src/transport.rs index 83d755716f..db3fc3ef04 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -54,7 +54,7 @@ pub trait SmartSubtransport: Send + 'static { } /// Actions that a smart transport can ask a subtransport to perform -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq)] #[allow(missing_docs)] pub enum Service { UploadPackLs, @@ -87,6 +87,8 @@ struct TransportData { #[repr(C)] struct RawSmartSubtransport { raw: raw::git_smart_subtransport, + stream: Option<*mut raw::git_smart_subtransport_stream>, + rpc: bool, obj: Box, } @@ -142,6 +144,8 @@ impl Transport { close: Some(subtransport_close), free: Some(subtransport_free), }, + stream: None, + rpc, obj: Box::new(subtransport), }); let mut defn = raw::git_smart_subtransport_definition { @@ -246,23 +250,36 @@ extern "C" fn subtransport_action( raw::GIT_SERVICE_RECEIVEPACK => Service::ReceivePack, n => panic!("unknown action: {}", n), }; - let transport = &mut *(raw_transport as *mut RawSmartSubtransport); - let obj = match transport.obj.action(url, action) { - Ok(s) => s, - Err(e) => { - set_err(&e); - return e.raw_code() as c_int; + + let mut transport = &mut *(raw_transport as *mut RawSmartSubtransport); + // Note: we only need to generate if rpc is on. Else, for receive-pack and upload-pack + // libgit2 reuses the stream generated for receive-pack-ls or upload-pack-ls. + let generate_stream = + transport.rpc || action == Service::UploadPackLs || action == Service::ReceivePackLs; + if generate_stream { + let obj = match transport.obj.action(url, action) { + Ok(s) => s, + Err(e) => { + set_err(&e); + return e.raw_code() as c_int; + } + }; + *stream = mem::transmute(Box::new(RawSmartSubtransportStream { + raw: raw::git_smart_subtransport_stream { + subtransport: raw_transport, + read: Some(stream_read), + write: Some(stream_write), + free: Some(stream_free), + }, + obj: obj, + })); + transport.stream = Some(*stream); + } else { + if transport.stream.is_none() { + return -1; } - }; - *stream = mem::transmute(Box::new(RawSmartSubtransportStream { - raw: raw::git_smart_subtransport_stream { - subtransport: raw_transport, - read: Some(stream_read), - write: Some(stream_write), - free: Some(stream_free), - }, - obj: obj, - })); + *stream = transport.stream.unwrap(); + } 0 }) .unwrap_or(-1) From ae256db3b27dd7dedab02fa5c051bd7adedf7de7 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Thu, 18 Mar 2021 19:27:20 +0100 Subject: [PATCH 555/860] expose diffline origin value so i do not need to hardcode char's but can use actual typed enum values (#679) --- src/diff.rs | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 2 +- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/src/diff.rs b/src/diff.rs index 2ac23e2c77..0c5150ca8c 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -951,6 +951,61 @@ impl<'diff> DoubleEndedIterator for Deltas<'diff> { } impl<'diff> ExactSizeIterator for Deltas<'diff> {} +/// Line origin constants. +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum DiffLineType { + /// These values will be sent to `git_diff_line_cb` along with the line + Context, + /// + Addition, + /// + Deletion, + /// Both files have no LF at end + ContextEOFNL, + /// Old has no LF at end, new does + AddEOFNL, + /// Old has LF at end, new does not + DeleteEOFNL, + /// The following values will only be sent to a `git_diff_line_cb` when + /// the content of a diff is being formatted through `git_diff_print`. + FileHeader, + /// + HunkHeader, + /// For "Binary files x and y differ" + Binary, +} + +impl Binding for DiffLineType { + type Raw = raw::git_diff_line_t; + unsafe fn from_raw(raw: raw::git_diff_line_t) -> Self { + match raw { + raw::GIT_DIFF_LINE_CONTEXT => DiffLineType::Context, + raw::GIT_DIFF_LINE_ADDITION => DiffLineType::Addition, + raw::GIT_DIFF_LINE_DELETION => DiffLineType::Deletion, + raw::GIT_DIFF_LINE_CONTEXT_EOFNL => DiffLineType::ContextEOFNL, + raw::GIT_DIFF_LINE_ADD_EOFNL => DiffLineType::AddEOFNL, + raw::GIT_DIFF_LINE_DEL_EOFNL => DiffLineType::DeleteEOFNL, + raw::GIT_DIFF_LINE_FILE_HDR => DiffLineType::FileHeader, + raw::GIT_DIFF_LINE_HUNK_HDR => DiffLineType::HunkHeader, + raw::GIT_DIFF_LINE_BINARY => DiffLineType::Binary, + _ => panic!("Unknown git diff line type"), + } + } + fn raw(&self) -> raw::git_diff_line_t { + match *self { + DiffLineType::Context => raw::GIT_DIFF_LINE_CONTEXT, + DiffLineType::Addition => raw::GIT_DIFF_LINE_ADDITION, + DiffLineType::Deletion => raw::GIT_DIFF_LINE_DELETION, + DiffLineType::ContextEOFNL => raw::GIT_DIFF_LINE_CONTEXT_EOFNL, + DiffLineType::AddEOFNL => raw::GIT_DIFF_LINE_ADD_EOFNL, + DiffLineType::DeleteEOFNL => raw::GIT_DIFF_LINE_DEL_EOFNL, + DiffLineType::FileHeader => raw::GIT_DIFF_LINE_FILE_HDR, + DiffLineType::HunkHeader => raw::GIT_DIFF_LINE_HUNK_HDR, + DiffLineType::Binary => raw::GIT_DIFF_LINE_BINARY, + } + } +} + impl<'a> DiffLine<'a> { /// Line number in old file or `None` for added line pub fn old_lineno(&self) -> Option { @@ -988,6 +1043,12 @@ impl<'a> DiffLine<'a> { } } + /// origin of this `DiffLine`. + /// + pub fn origin_value(&self) -> DiffLineType { + unsafe { Binding::from_raw((*self.raw).origin as raw::git_diff_line_t) } + } + /// Sigil showing the origin of this `DiffLine`. /// /// * ` ` - Line context @@ -1475,7 +1536,7 @@ impl DiffPatchidOptions { #[cfg(test)] mod tests { - use crate::{DiffOptions, Oid, Signature, Time}; + use crate::{DiffLineType, DiffOptions, Oid, Signature, Time}; use std::borrow::Borrow; use std::fs::File; use std::io::Write; @@ -1726,4 +1787,28 @@ mod tests { assert_eq!(line.trim(), "") } } + + #[test] + fn foreach_diff_line_origin_value() { + let foo_path = Path::new("foo"); + let (td, repo) = crate::test::repo_init(); + t!(t!(File::create(&td.path().join(foo_path))).write_all(b"bar\n")); + let mut index = t!(repo.index()); + t!(index.add_path(foo_path)); + let mut opts = DiffOptions::new(); + opts.include_untracked(true); + let diff = t!(repo.diff_tree_to_index(None, Some(&index), Some(&mut opts))); + let mut origin_values: Vec = Vec::new(); + t!(diff.foreach( + &mut |_file, _progress| { true }, + None, + None, + Some(&mut |_file, _hunk, line| { + origin_values.push(line.origin_value()); + true + }) + )); + assert_eq!(origin_values.len(), 1); + assert_eq!(origin_values[0], DiffLineType::Addition); + } } diff --git a/src/lib.rs b/src/lib.rs index 8689ff88ab..a68c90062d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,7 @@ pub use crate::cred::{Cred, CredentialHelper}; pub use crate::describe::{Describe, DescribeFormatOptions, DescribeOptions}; pub use crate::diff::{Deltas, Diff, DiffDelta, DiffFile, DiffOptions}; pub use crate::diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind}; -pub use crate::diff::{DiffFindOptions, DiffHunk, DiffLine, DiffStats}; +pub use crate::diff::{DiffFindOptions, DiffHunk, DiffLine, DiffLineType, DiffStats}; pub use crate::error::Error; pub use crate::index::{ Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath, From 64b8ba8fc6366f3e3f8bd74f068fede33826b702 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Thu, 25 Mar 2021 22:06:00 +0800 Subject: [PATCH 556/860] Get rid of `git_attr__*` symbols (#689) They are morally private, and it turns out they are unreliable, even just for testing purpose. --- src/attr.rs | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/src/attr.rs b/src/attr.rs index 77c66b1609..1e689d98ca 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -87,36 +87,26 @@ impl PartialEq for AttrValue<'_> { #[cfg(test)] mod tests { use super::AttrValue; - use std::ffi::CStr; - use std::os::raw::c_char; - - extern "C" { - // libgit2 defines them as mutable, so they are also declared mutable here. - // However, libgit2 never mutates them, thus it's always safe to access them in Rust. - static mut git_attr__true: *const c_char; - static mut git_attr__false: *const c_char; - static mut git_attr__unset: *const c_char; - } macro_rules! test_attr_value { ($function:ident, $variant:ident) => { - let attr_true = unsafe { CStr::from_ptr(git_attr__true) }.to_str().unwrap(); - let attr_false = unsafe { CStr::from_ptr(git_attr__false) }.to_str().unwrap(); - let attr_unset = unsafe { CStr::from_ptr(git_attr__unset) }.to_str().unwrap(); + const ATTR_TRUE: &str = "[internal]__TRUE__"; + const ATTR_FALSE: &str = "[internal]__FALSE__"; + const ATTR_UNSET: &str = "[internal]__UNSET__"; let as_bytes = AsRef::<[u8]>::as_ref; // Use `matches!` here since the `PartialEq` implementation does not differentiate // between `String` and `Bytes`. assert!(matches!( - AttrValue::$function(Some(attr_true.to_owned().as_ref())), - AttrValue::$variant(s) if as_bytes(s) == attr_true.as_bytes() + AttrValue::$function(Some(ATTR_TRUE.as_ref())), + AttrValue::$variant(s) if as_bytes(s) == ATTR_TRUE.as_bytes() )); assert!(matches!( - AttrValue::$function(Some(attr_false.to_owned().as_ref())), - AttrValue::$variant(s) if as_bytes(s) == attr_false.as_bytes() + AttrValue::$function(Some(ATTR_FALSE.as_ref())), + AttrValue::$variant(s) if as_bytes(s) == ATTR_FALSE.as_bytes() )); assert!(matches!( - AttrValue::$function(Some(attr_unset.to_owned().as_ref())), - AttrValue::$variant(s) if as_bytes(s) == attr_unset.as_bytes() + AttrValue::$function(Some(ATTR_UNSET.as_ref())), + AttrValue::$variant(s) if as_bytes(s) == ATTR_UNSET.as_bytes() )); assert!(matches!( AttrValue::$function(Some("foo".as_ref())), @@ -126,18 +116,6 @@ mod tests { AttrValue::$function(Some("bar".as_ref())), AttrValue::$variant(s) if as_bytes(s) == b"bar" )); - assert_eq!( - AttrValue::$function(Some(attr_true.as_ref())), - AttrValue::True - ); - assert_eq!( - AttrValue::$function(Some(attr_false.as_ref())), - AttrValue::False - ); - assert_eq!( - AttrValue::$function(Some(attr_unset.as_ref())), - AttrValue::Unspecified - ); assert_eq!(AttrValue::$function(None), AttrValue::Unspecified); }; } From 8e24a2ea7a540709251c15dde384ed3233e2e7de Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Mon, 29 Mar 2021 16:06:12 +0200 Subject: [PATCH 557/860] Add bindings for the transaction API (#686) Defined in `transaction.h`, this is essentially a way to place file locks on a set of refs, and update them in one (non-atomic) operation. Signed-off-by: Kim Altintop --- libgit2-sys/lib.rs | 27 +++++ src/lib.rs | 2 + src/repo.rs | 11 +- src/transaction.rs | 285 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 src/transaction.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a1b0e48946..ffcc1ec1e2 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -89,6 +89,7 @@ pub enum git_odb {} pub enum git_odb_stream {} pub enum git_odb_object {} pub enum git_worktree {} +pub enum git_transaction {} #[repr(C)] pub struct git_revspec { @@ -3914,6 +3915,32 @@ extern "C" { wt: *mut git_worktree, opts: *mut git_worktree_prune_options, ) -> c_int; + + // Ref transactions + pub fn git_transaction_new(out: *mut *mut git_transaction, repo: *mut git_repository) -> c_int; + pub fn git_transaction_lock_ref(tx: *mut git_transaction, refname: *const c_char) -> c_int; + pub fn git_transaction_set_target( + tx: *mut git_transaction, + refname: *const c_char, + target: *const git_oid, + sig: *const git_signature, + msg: *const c_char, + ) -> c_int; + pub fn git_transaction_set_symbolic_target( + tx: *mut git_transaction, + refname: *const c_char, + target: *const c_char, + sig: *const git_signature, + msg: *const c_char, + ) -> c_int; + pub fn git_transaction_set_reflog( + tx: *mut git_transaction, + refname: *const c_char, + reflog: *const git_reflog, + ) -> c_int; + pub fn git_transaction_remove(tx: *mut git_transaction, refname: *const c_char) -> c_int; + pub fn git_transaction_commit(tx: *mut git_transaction) -> c_int; + pub fn git_transaction_free(tx: *mut git_transaction); } pub fn init() { diff --git a/src/lib.rs b/src/lib.rs index a68c90062d..a467b7f589 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -129,6 +129,7 @@ pub use crate::status::{StatusEntry, StatusIter, StatusOptions, StatusShow, Stat pub use crate::submodule::{Submodule, SubmoduleUpdateOptions}; pub use crate::tag::Tag; pub use crate::time::{IndexTime, Time}; +pub use crate::transaction::Transaction; pub use crate::tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult}; pub use crate::treebuilder::TreeBuilder; pub use crate::util::IntoCString; @@ -687,6 +688,7 @@ mod submodule; mod tag; mod tagforeach; mod time; +mod transaction; mod tree; mod treebuilder; mod worktree; diff --git a/src/repo.rs b/src/repo.rs index 464c9289b4..5fc41b7b94 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -32,7 +32,7 @@ use crate::{Blame, BlameOptions, Reference, References, ResetType, Signature, Su use crate::{Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, Oid, Tree}; use crate::{Describe, IntoCString, Reflog, RepositoryInitMode, RevparseMode}; use crate::{DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder}; -use crate::{Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag}; +use crate::{Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag, Transaction}; /// An owned git repository, representing all state associated with the /// underlying filesystem. @@ -2953,6 +2953,15 @@ impl Repository { Ok(Binding::from_raw(raw)) } } + + /// Create a new transaction + pub fn transaction<'a>(&'a self) -> Result, Error> { + let mut raw = ptr::null_mut(); + unsafe { + try_call!(raw::git_transaction_new(&mut raw, self.raw)); + Ok(Binding::from_raw(raw)) + } + } } impl Binding for Repository { diff --git a/src/transaction.rs b/src/transaction.rs new file mode 100644 index 0000000000..80cb4dfe0f --- /dev/null +++ b/src/transaction.rs @@ -0,0 +1,285 @@ +use std::ffi::CString; +use std::marker; + +use crate::{raw, util::Binding, Error, Oid, Reflog, Repository, Signature}; + +/// A structure representing a transactional update of a repository's references. +/// +/// Transactions work by locking loose refs for as long as the [`Transaction`] +/// is held, and committing all changes to disk when [`Transaction::commit`] is +/// called. Note that comitting is not atomic: if an operation fails, the +/// transaction aborts, but previous successful operations are not rolled back. +pub struct Transaction<'repo> { + raw: *mut raw::git_transaction, + _marker: marker::PhantomData<&'repo Repository>, +} + +impl Drop for Transaction<'_> { + fn drop(&mut self) { + unsafe { raw::git_transaction_free(self.raw) } + } +} + +impl<'repo> Binding for Transaction<'repo> { + type Raw = *mut raw::git_transaction; + + unsafe fn from_raw(ptr: *mut raw::git_transaction) -> Transaction<'repo> { + Transaction { + raw: ptr, + _marker: marker::PhantomData, + } + } + + fn raw(&self) -> *mut raw::git_transaction { + self.raw + } +} + +impl<'repo> Transaction<'repo> { + /// Lock the specified reference by name. + pub fn lock_ref(&mut self, refname: &str) -> Result<(), Error> { + let refname = CString::new(refname).unwrap(); + unsafe { + try_call!(raw::git_transaction_lock_ref(self.raw, refname)); + } + + Ok(()) + } + + /// Set the target of the specified reference. + /// + /// The reference must have been locked via `lock_ref`. + /// + /// If `reflog_signature` is `None`, the [`Signature`] is read from the + /// repository config. + pub fn set_target( + &mut self, + refname: &str, + target: Oid, + reflog_signature: Option<&Signature<'_>>, + reflog_message: &str, + ) -> Result<(), Error> { + let refname = CString::new(refname).unwrap(); + let reflog_message = CString::new(reflog_message).unwrap(); + unsafe { + try_call!(raw::git_transaction_set_target( + self.raw, + refname, + target.raw(), + reflog_signature.map(|s| s.raw()), + reflog_message + )); + } + + Ok(()) + } + + /// Set the target of the specified symbolic reference. + /// + /// The reference must have been locked via `lock_ref`. + /// + /// If `reflog_signature` is `None`, the [`Signature`] is read from the + /// repository config. + pub fn set_symbolic_target( + &mut self, + refname: &str, + target: &str, + reflog_signature: Option<&Signature<'_>>, + reflog_message: &str, + ) -> Result<(), Error> { + let refname = CString::new(refname).unwrap(); + let target = CString::new(target).unwrap(); + let reflog_message = CString::new(reflog_message).unwrap(); + unsafe { + try_call!(raw::git_transaction_set_symbolic_target( + self.raw, + refname, + target, + reflog_signature.map(|s| s.raw()), + reflog_message + )); + } + + Ok(()) + } + + /// Add a [`Reflog`] to the transaction. + /// + /// This commit the in-memory [`Reflog`] to disk when the transaction commits. + /// Note that atomicty is **not* guaranteed: if the transaction fails to + /// modify `refname`, the reflog may still have been comitted to disk. + /// + /// If this is combined with setting the target, that update won't be + /// written to the log (ie. the `reflog_signature` and `reflog_message` + /// parameters will be ignored). + pub fn set_reflog(&mut self, refname: &str, reflog: Reflog) -> Result<(), Error> { + let refname = CString::new(refname).unwrap(); + unsafe { + try_call!(raw::git_transaction_set_reflog( + self.raw, + refname, + reflog.raw() + )); + } + + Ok(()) + } + + /// Remove a reference. + /// + /// The reference must have been locked via `lock_ref`. + pub fn remove(&mut self, refname: &str) -> Result<(), Error> { + let refname = CString::new(refname).unwrap(); + unsafe { + try_call!(raw::git_transaction_remove(self.raw, refname)); + } + + Ok(()) + } + + /// Commit the changes from the transaction. + /// + /// The updates will be made one by one, and the first failure will stop the + /// processing. + pub fn commit(self) -> Result<(), Error> { + unsafe { + try_call!(raw::git_transaction_commit(self.raw)); + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use crate::{Error, ErrorClass, ErrorCode, Oid, Repository}; + + #[test] + fn smoke() { + let (_td, repo) = crate::test::repo_init(); + + let mut tx = t!(repo.transaction()); + + t!(tx.lock_ref("refs/heads/main")); + t!(tx.lock_ref("refs/heads/next")); + + t!(tx.set_target("refs/heads/main", Oid::zero(), None, "set main to zero")); + t!(tx.set_symbolic_target( + "refs/heads/next", + "refs/heads/main", + None, + "set next to main", + )); + + t!(tx.commit()); + + assert_eq!(repo.refname_to_id("refs/heads/main").unwrap(), Oid::zero()); + assert_eq!( + repo.find_reference("refs/heads/next") + .unwrap() + .symbolic_target() + .unwrap(), + "refs/heads/main" + ); + } + + #[test] + fn locks_same_repo_handle() { + let (_td, repo) = crate::test::repo_init(); + + let mut tx1 = t!(repo.transaction()); + t!(tx1.lock_ref("refs/heads/seen")); + + let mut tx2 = t!(repo.transaction()); + assert!(matches!(tx2.lock_ref("refs/heads/seen"), Err(e) if e.code() == ErrorCode::Locked)) + } + + #[test] + fn locks_across_repo_handles() { + let (td, repo1) = crate::test::repo_init(); + let repo2 = t!(Repository::open(&td)); + + let mut tx1 = t!(repo1.transaction()); + t!(tx1.lock_ref("refs/heads/seen")); + + let mut tx2 = t!(repo2.transaction()); + assert!(matches!(tx2.lock_ref("refs/heads/seen"), Err(e) if e.code() == ErrorCode::Locked)) + } + + #[test] + fn drop_unlocks() { + let (_td, repo) = crate::test::repo_init(); + + let mut tx = t!(repo.transaction()); + t!(tx.lock_ref("refs/heads/seen")); + drop(tx); + + let mut tx2 = t!(repo.transaction()); + t!(tx2.lock_ref("refs/heads/seen")) + } + + #[test] + fn commit_unlocks() { + let (_td, repo) = crate::test::repo_init(); + + let mut tx = t!(repo.transaction()); + t!(tx.lock_ref("refs/heads/seen")); + t!(tx.commit()); + + let mut tx2 = t!(repo.transaction()); + t!(tx2.lock_ref("refs/heads/seen")); + } + + #[test] + fn prevents_non_transactional_updates() { + let (_td, repo) = crate::test::repo_init(); + let head = t!(repo.refname_to_id("HEAD")); + + let mut tx = t!(repo.transaction()); + t!(tx.lock_ref("refs/heads/seen")); + + assert!(matches!( + repo.reference("refs/heads/seen", head, true, "competing with lock"), + Err(e) if e.code() == ErrorCode::Locked + )); + } + + #[test] + fn remove() { + let (_td, repo) = crate::test::repo_init(); + let head = t!(repo.refname_to_id("HEAD")); + let next = "refs/heads/next"; + + t!(repo.reference( + next, + head, + true, + "refs/heads/next@{0}: branch: Created from HEAD" + )); + + { + let mut tx = t!(repo.transaction()); + t!(tx.lock_ref(next)); + t!(tx.remove(next)); + t!(tx.commit()); + } + assert!(matches!(repo.refname_to_id(next), Err(e) if e.code() == ErrorCode::NotFound)) + } + + #[test] + fn must_lock_ref() { + let (_td, repo) = crate::test::repo_init(); + + // 🤷 + fn is_not_locked_err(e: &Error) -> bool { + e.code() == ErrorCode::NotFound + && e.class() == ErrorClass::Reference + && e.message() == "the specified reference is not locked" + } + + let mut tx = t!(repo.transaction()); + assert!(matches!( + tx.set_target("refs/heads/main", Oid::zero(), None, "set main to zero"), + Err(e) if is_not_locked_err(&e) + )) + } +} From 7912c90991444abb00f9d0476939d48bc368516b Mon Sep 17 00:00:00 2001 From: Mikkel Kjeldsen Date: Wed, 31 Mar 2021 19:42:44 +0200 Subject: [PATCH 558/860] Add bindings for mailmap (#691) * Add several bindings for mailmap Add bindings for - git_mailmap_free - git_mailmap_from_repository - git_mailmap_resolve_signature - git_commit_author_with_mailmap - git_commit_committer_with_mailmap This is half the functions in the "mailmap" group and the two convenience functions in the "commit" group, which is enough to make mailmap support useful. I omitted git_mailmap_resolve because of the slightly awkward function signature. I also omitted - git_mailmap_new - git_mailmap_from_buffer - git_mailmap_add_entry which support in-memory manipulation of a mailmap representation: there appears to be no way to write the representation to disk, neither directly nor indirectly, so those functions seem a bit pointless. * Add more mailmap bindings Add bindings for - git_mailmap_new - git_mailmap_from_buffer - git_mailmap_add_entry to support in-memory manipulation of a mailmap representation. Commit c5fe47d (Add several bindings for mailmap, 2021-03-26) notes that these seem silly on account of offering no way to write the representation back to disk. However, they are easy to support and effectively enable an out-of-tree .mailmap file. --- libgit2-sys/lib.rs | 36 ++++++++++++ src/commit.rs | 30 +++++++++- src/lib.rs | 2 + src/mailmap.rs | 134 +++++++++++++++++++++++++++++++++++++++++++++ src/repo.rs | 104 ++++++++++++++++++++++++++++++++++- 5 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 src/mailmap.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index ffcc1ec1e2..050989fed9 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -90,6 +90,7 @@ pub enum git_odb_stream {} pub enum git_odb_object {} pub enum git_worktree {} pub enum git_transaction {} +pub enum git_mailmap {} #[repr(C)] pub struct git_revspec { @@ -2598,7 +2599,17 @@ extern "C" { // commit pub fn git_commit_author(commit: *const git_commit) -> *const git_signature; + pub fn git_commit_author_with_mailmap( + out: *mut *mut git_signature, + commit: *const git_commit, + mailmap: *const git_mailmap, + ) -> c_int; pub fn git_commit_committer(commit: *const git_commit) -> *const git_signature; + pub fn git_commit_committer_with_mailmap( + out: *mut *mut git_signature, + commit: *const git_commit, + mailmap: *const git_mailmap, + ) -> c_int; pub fn git_commit_free(commit: *mut git_commit); pub fn git_commit_id(commit: *const git_commit) -> *const git_oid; pub fn git_commit_lookup( @@ -3941,6 +3952,31 @@ extern "C" { pub fn git_transaction_remove(tx: *mut git_transaction, refname: *const c_char) -> c_int; pub fn git_transaction_commit(tx: *mut git_transaction) -> c_int; pub fn git_transaction_free(tx: *mut git_transaction); + + // Mailmap + pub fn git_mailmap_new(out: *mut *mut git_mailmap) -> c_int; + pub fn git_mailmap_from_buffer( + out: *mut *mut git_mailmap, + buf: *const c_char, + len: size_t, + ) -> c_int; + pub fn git_mailmap_from_repository( + out: *mut *mut git_mailmap, + repo: *mut git_repository, + ) -> c_int; + pub fn git_mailmap_free(mm: *mut git_mailmap); + pub fn git_mailmap_resolve_signature( + out: *mut *mut git_signature, + mm: *const git_mailmap, + sig: *const git_signature, + ) -> c_int; + pub fn git_mailmap_add_entry( + mm: *mut git_mailmap, + real_name: *const c_char, + real_email: *const c_char, + replace_name: *const c_char, + replace_email: *const c_char, + ) -> c_int; } pub fn init() { diff --git a/src/commit.rs b/src/commit.rs index ec5cff22ad..4df60f7d9c 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -6,7 +6,7 @@ use std::ptr; use std::str; use crate::util::Binding; -use crate::{raw, signature, Buf, Error, IntoCString, Object, Oid, Signature, Time, Tree}; +use crate::{raw, signature, Buf, Error, IntoCString, Mailmap, Object, Oid, Signature, Time, Tree}; /// A structure to represent a git [commit][1] /// @@ -183,6 +183,20 @@ impl<'repo> Commit<'repo> { } } + /// Get the author of this commit, using the mailmap to map names and email + /// addresses to canonical real names and email addresses. + pub fn author_with_mailmap(&self, mailmap: &Mailmap) -> Result, Error> { + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_commit_author_with_mailmap( + &mut ret, + &*self.raw, + &*mailmap.raw() + )); + Ok(Binding::from_raw(ret)) + } + } + /// Get the committer of this commit. pub fn committer(&self) -> Signature<'_> { unsafe { @@ -191,6 +205,20 @@ impl<'repo> Commit<'repo> { } } + /// Get the committer of this commit, using the mailmap to map names and email + /// addresses to canonical real names and email addresses. + pub fn committer_with_mailmap(&self, mailmap: &Mailmap) -> Result, Error> { + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_commit_committer_with_mailmap( + &mut ret, + &*self.raw, + &*mailmap.raw() + )); + Ok(Binding::from_raw(ret)) + } + } + /// Amend this existing commit with all non-`None` values /// /// This creates a new commit that is exactly the same as the old commit, diff --git a/src/lib.rs b/src/lib.rs index a467b7f589..52b49fd79f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,6 +98,7 @@ pub use crate::index::{ Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath, }; pub use crate::indexer::{IndexerProgress, Progress}; +pub use crate::mailmap::Mailmap; pub use crate::mempack::Mempack; pub use crate::merge::{AnnotatedCommit, MergeOptions}; pub use crate::message::{message_prettify, DEFAULT_COMMENT_CHAR}; @@ -660,6 +661,7 @@ mod diff; mod error; mod index; mod indexer; +mod mailmap; mod mempack; mod merge; mod message; diff --git a/src/mailmap.rs b/src/mailmap.rs new file mode 100644 index 0000000000..096b3227c7 --- /dev/null +++ b/src/mailmap.rs @@ -0,0 +1,134 @@ +use std::ffi::CString; +use std::ptr; + +use crate::util::Binding; +use crate::{raw, Error, Signature}; + +/// A structure to represent a repository's .mailmap file. +/// +/// The representation cannot be written to disk. +pub struct Mailmap { + raw: *mut raw::git_mailmap, +} + +impl Binding for Mailmap { + type Raw = *mut raw::git_mailmap; + + unsafe fn from_raw(ptr: *mut raw::git_mailmap) -> Mailmap { + Mailmap { raw: ptr } + } + + fn raw(&self) -> *mut raw::git_mailmap { + self.raw + } +} + +impl Drop for Mailmap { + fn drop(&mut self) { + unsafe { + raw::git_mailmap_free(self.raw); + } + } +} + +impl Mailmap { + /// Creates an empty, in-memory mailmap object. + pub fn new() -> Result { + crate::init(); + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_mailmap_new(&mut ret)); + Ok(Binding::from_raw(ret)) + } + } + + /// Creates an in-memory mailmap object representing the given buffer. + pub fn from_buffer(buf: &str) -> Result { + crate::init(); + let mut ret = ptr::null_mut(); + let len = buf.len(); + let buf = CString::new(buf)?; + unsafe { + try_call!(raw::git_mailmap_from_buffer(&mut ret, buf, len)); + Ok(Binding::from_raw(ret)) + } + } + + /// Adds a new entry to this in-memory mailmap object. + pub fn add_entry( + &mut self, + real_name: Option<&str>, + real_email: Option<&str>, + replace_name: Option<&str>, + replace_email: &str, + ) -> Result<(), Error> { + let real_name = crate::opt_cstr(real_name)?; + let real_email = crate::opt_cstr(real_email)?; + let replace_name = crate::opt_cstr(replace_name)?; + let replace_email = CString::new(replace_email)?; + unsafe { + try_call!(raw::git_mailmap_add_entry( + self.raw, + real_name, + real_email, + replace_name, + replace_email + )); + Ok(()) + } + } + + /// Resolves a signature to its real name and email address. + pub fn resolve_signature(&self, sig: &Signature<'_>) -> Result, Error> { + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_mailmap_resolve_signature( + &mut ret, + &*self.raw, + sig.raw() + )); + Ok(Binding::from_raw(ret)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn smoke() { + let sig_name = "name"; + let sig_email = "email"; + let sig = t!(Signature::now(sig_name, sig_email)); + + let mut mm = t!(Mailmap::new()); + + let mailmapped_sig = t!(mm.resolve_signature(&sig)); + assert_eq!(mailmapped_sig.name(), Some(sig_name)); + assert_eq!(mailmapped_sig.email(), Some(sig_email)); + + t!(mm.add_entry(None, None, None, sig_email)); + t!(mm.add_entry( + Some("real name"), + Some("real@email"), + Some(sig_name), + sig_email, + )); + + let mailmapped_sig = t!(mm.resolve_signature(&sig)); + assert_eq!(mailmapped_sig.name(), Some("real name")); + assert_eq!(mailmapped_sig.email(), Some("real@email")); + } + + #[test] + fn from_buffer() { + let buf = " "; + let mm = t!(Mailmap::from_buffer(&buf)); + + let sig = t!(Signature::now("name", "email")); + let mailmapped_sig = t!(mm.resolve_signature(&sig)); + assert_eq!(mailmapped_sig.name(), Some("name")); + assert_eq!(mailmapped_sig.email(), Some("prøper@emæil")); + } +} diff --git a/src/repo.rs b/src/repo.rs index 5fc41b7b94..539aafa8f2 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -11,6 +11,7 @@ use crate::build::{CheckoutBuilder, RepoBuilder}; use crate::diff::{ binary_cb_c, file_cb_c, hunk_cb_c, line_cb_c, BinaryCb, DiffCallbacks, FileCb, HunkCb, LineCb, }; +use crate::mailmap::Mailmap; use crate::oid_array::OidArray; use crate::stash::{stash_cb, StashApplyOptions, StashCbData}; use crate::string_array::StringArray; @@ -2962,6 +2963,15 @@ impl Repository { Ok(Binding::from_raw(raw)) } } + + /// Gets this repository's mailmap. + pub fn mailmap(&self) -> Result { + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_mailmap_from_repository(&mut ret, self.raw)); + Ok(Binding::from_raw(ret)) + } + } } impl Binding for Repository { @@ -3144,7 +3154,9 @@ impl RepositoryInitOptions { mod tests { use crate::build::CheckoutBuilder; use crate::CherrypickOptions; - use crate::{ObjectType, Oid, Repository, ResetType, SubmoduleIgnore, SubmoduleUpdate}; + use crate::{ + ObjectType, Oid, Repository, ResetType, Signature, SubmoduleIgnore, SubmoduleUpdate, + }; use std::ffi::OsStr; use std::fs; use std::path::Path; @@ -3836,4 +3848,94 @@ mod tests { Ok(()) } + + #[test] + fn smoke_mailmap_from_repository() { + let (_td, repo) = crate::test::repo_init(); + + let commit = { + let head = t!(repo.head()).target().unwrap(); + t!(repo.find_commit(head)) + }; + + // This is our baseline for HEAD. + let author = commit.author(); + let committer = commit.committer(); + assert_eq!(author.name(), Some("name")); + assert_eq!(author.email(), Some("email")); + assert_eq!(committer.name(), Some("name")); + assert_eq!(committer.email(), Some("email")); + + // There is no .mailmap file in the test repo so all signature identities are equal. + let mailmap = t!(repo.mailmap()); + let mailmapped_author = t!(commit.author_with_mailmap(&mailmap)); + let mailmapped_committer = t!(commit.committer_with_mailmap(&mailmap)); + assert_eq!(mailmapped_author.name(), author.name()); + assert_eq!(mailmapped_author.email(), author.email()); + assert_eq!(mailmapped_committer.name(), committer.name()); + assert_eq!(mailmapped_committer.email(), committer.email()); + + let commit = { + // - Add a .mailmap file to the repository. + // - Commit with a signature identity different from the author's. + // - Include entries for both author and committer to prove we call + // the right raw functions. + let mailmap_file = Path::new(".mailmap"); + let p = Path::new(repo.workdir().unwrap()).join(&mailmap_file); + t!(fs::write( + p, + r#" +Author Name name +Committer Name "#, + )); + let mut index = t!(repo.index()); + t!(index.add_path(&mailmap_file)); + let id_mailmap = t!(index.write_tree()); + let tree_mailmap = t!(repo.find_tree(id_mailmap)); + + let head = t!(repo.commit( + Some("HEAD"), + &author, + t!(&Signature::now("committer", "committer@email")), + "Add mailmap", + &tree_mailmap, + &[&commit], + )); + t!(repo.find_commit(head)) + }; + + // Sanity check that we're working with the right commit and that its + // author and committer identities differ. + let author = commit.author(); + let committer = commit.committer(); + assert_ne!(author.name(), committer.name()); + assert_ne!(author.email(), committer.email()); + assert_eq!(author.name(), Some("name")); + assert_eq!(author.email(), Some("email")); + assert_eq!(committer.name(), Some("committer")); + assert_eq!(committer.email(), Some("committer@email")); + + // Fetch the newly added .mailmap from the repository. + let mailmap = t!(repo.mailmap()); + let mailmapped_author = t!(commit.author_with_mailmap(&mailmap)); + let mailmapped_committer = t!(commit.committer_with_mailmap(&mailmap)); + + let mm_resolve_author = t!(mailmap.resolve_signature(&author)); + let mm_resolve_committer = t!(mailmap.resolve_signature(&committer)); + + // Mailmap Signature lifetime is independent of Commit lifetime. + drop(author); + drop(committer); + drop(commit); + + // author_with_mailmap() + committer_with_mailmap() work + assert_eq!(mailmapped_author.name(), Some("Author Name")); + assert_eq!(mailmapped_author.email(), Some("author.proper@email")); + assert_eq!(mailmapped_committer.name(), Some("Committer Name")); + assert_eq!(mailmapped_committer.email(), Some("committer.proper@email")); + + // resolve_signature() works + assert_eq!(mm_resolve_author.email(), mailmapped_author.email()); + assert_eq!(mm_resolve_committer.email(), mailmapped_committer.email()); + } } From 80ed7ce211f29ca057c7e5db631d68984df01c46 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 19 Apr 2021 07:24:23 -0700 Subject: [PATCH 559/860] Bump libgit2-sys to 0.12.19 --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4135894104..6cf60e0c89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.18" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.19" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 638c68b8aa..8cc6e65b0c 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.18+1.1.0" +version = "0.12.19+1.1.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 3b4d35d7e79a75b24c90a67c92a75d57c87cb790 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 19 Apr 2021 07:25:02 -0700 Subject: [PATCH 560/860] Bump to 0.13.18 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6cf60e0c89..1182647a9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.17" +version = "0.13.18" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From f46e8ff09dbf8c6d58d3b79d36f0dbd643fc128d Mon Sep 17 00:00:00 2001 From: Daniel Franklin Date: Wed, 21 Apr 2021 20:31:29 +0100 Subject: [PATCH 561/860] Use EUSER instead of generic error to stop foreach (#699) Previously foreach returned a generic generic error to signal the user asked to stop iterating. If a user got that error, they can't know for certain if it's because they asked to stop iterating, or if a legitimate error occurred. libgit2 provides EUSER as a reserved error code for this case, so we use it. Closes 698 --- src/diff.rs | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/diff.rs b/src/diff.rs index 0c5150ca8c..0debc045bc 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -338,9 +338,9 @@ pub extern "C" fn print_cb( (*data)(delta, hunk, line) }); if r == Some(true) { - 0 + raw::GIT_OK } else { - -1 + raw::GIT_EUSER } } } @@ -361,9 +361,9 @@ pub extern "C" fn file_cb_c( } }); if r == Some(true) { - 0 + raw::GIT_OK } else { - -1 + raw::GIT_EUSER } } } @@ -385,9 +385,9 @@ pub extern "C" fn binary_cb_c( } }); if r == Some(true) { - 0 + raw::GIT_OK } else { - -1 + raw::GIT_EUSER } } } @@ -409,9 +409,9 @@ pub extern "C" fn hunk_cb_c( } }); if r == Some(true) { - 0 + raw::GIT_OK } else { - -1 + raw::GIT_EUSER } } } @@ -435,9 +435,9 @@ pub extern "C" fn line_cb_c( } }); if r == Some(true) { - 0 + raw::GIT_OK } else { - -1 + raw::GIT_EUSER } } } @@ -1811,4 +1811,34 @@ mod tests { assert_eq!(origin_values.len(), 1); assert_eq!(origin_values[0], DiffLineType::Addition); } + + #[test] + fn foreach_exits_with_euser() { + let foo_path = Path::new("foo"); + let bar_path = Path::new("foo"); + + let (td, repo) = crate::test::repo_init(); + t!(t!(File::create(&td.path().join(foo_path))).write_all(b"bar\n")); + + let mut index = t!(repo.index()); + t!(index.add_path(foo_path)); + t!(index.add_path(bar_path)); + + let mut opts = DiffOptions::new(); + opts.include_untracked(true); + let diff = t!(repo.diff_tree_to_index(None, Some(&index), Some(&mut opts))); + + let mut calls = 0; + let result = diff.foreach( + &mut |_file, _progress| { + calls += 1; + false + }, + None, + None, + None, + ); + + assert_eq!(result.unwrap_err().code(), crate::ErrorCode::User); + } } From 90a45bb106a723259e2a0f0c3ff5fb4f70723fda Mon Sep 17 00:00:00 2001 From: Andres Suarez Date: Mon, 26 Apr 2021 10:10:26 -0400 Subject: [PATCH 562/860] Add a missing initialization in Diff::from_buffer (#701) --- src/diff.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/diff.rs b/src/diff.rs index 0debc045bc..656d5fbcfe 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -309,6 +309,7 @@ impl Diff<'static> { /// a patch file likely contains abbreviated object IDs, so the /// object IDs parsed by this function will also be abreviated. pub fn from_buffer(buffer: &[u8]) -> Result, Error> { + crate::init(); let mut diff: *mut raw::git_diff = std::ptr::null_mut(); unsafe { // NOTE: Doesn't depend on repo, so lifetime can be 'static From 1b1499a78dc04c042aa7789f81f0a3308b66261b Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Fri, 7 May 2021 16:29:56 +0200 Subject: [PATCH 563/860] update libgit2 submodule to recent main (#704) --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index f4b473fa84..4bd172087c 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit f4b473fa842a84147d8036a27bac5c026c44dad4 +Subproject commit 4bd172087c30e09e7720a7df11cace47ee002256 From 2358d2c30c54517cfa5e5ad5455c3d5f6ee1dfae Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Tue, 11 May 2021 16:14:24 +0200 Subject: [PATCH 564/860] added git_repository_mergehead_foreach (#707) --- libgit2-sys/lib.rs | 8 ++++++++ src/repo.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 050989fed9..16516197a3 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1889,6 +1889,9 @@ pub struct git_worktree_prune_options { pub const GIT_WORKTREE_PRUNE_OPTIONS_VERSION: c_uint = 1; +pub type git_repository_mergehead_foreach_cb = + Option c_int>; + extern "C" { // threads pub fn git_libgit2_init() -> c_int; @@ -1981,6 +1984,11 @@ extern "C" { repo: *mut git_repository, recurse_submodules: c_int, ) -> c_int; + pub fn git_repository_mergehead_foreach( + repo: *mut git_repository, + callback: git_repository_mergehead_foreach_cb, + payload: *mut c_void, + ) -> c_int; pub fn git_ignore_add_rule(repo: *mut git_repository, rules: *const c_char) -> c_int; pub fn git_ignore_clear_internal_rules(repo: *mut git_repository) -> c_int; pub fn git_ignore_path_is_ignored( diff --git a/src/repo.rs b/src/repo.rs index 539aafa8f2..82d37921c5 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -11,7 +11,6 @@ use crate::build::{CheckoutBuilder, RepoBuilder}; use crate::diff::{ binary_cb_c, file_cb_c, hunk_cb_c, line_cb_c, BinaryCb, DiffCallbacks, FileCb, HunkCb, LineCb, }; -use crate::mailmap::Mailmap; use crate::oid_array::OidArray; use crate::stash::{stash_cb, StashApplyOptions, StashCbData}; use crate::string_array::StringArray; @@ -20,6 +19,7 @@ use crate::util::{self, path_to_repo_path, Binding}; use crate::worktree::{Worktree, WorktreeAddOptions}; use crate::CherrypickOptions; use crate::RevertOptions; +use crate::{mailmap::Mailmap, panic}; use crate::{ raw, AttrCheckFlags, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, Revspec, StashFlags, @@ -35,6 +35,29 @@ use crate::{Describe, IntoCString, Reflog, RepositoryInitMode, RevparseMode}; use crate::{DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder}; use crate::{Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag, Transaction}; +type MergeheadForeachCb<'a> = dyn FnMut(&Oid) -> bool + 'a; + +struct MergeheadForeachCbData<'a> { + callback: &'a mut MergeheadForeachCb<'a>, +} + +extern "C" fn mergehead_foreach_cb(oid: *const raw::git_oid, payload: *mut c_void) -> c_int { + panic::wrap(|| unsafe { + let data = &mut *(payload as *mut MergeheadForeachCbData<'_>); + let res = { + let callback = &mut data.callback; + callback(&Binding::from_raw(oid)) + }; + + if res { + 0 + } else { + 1 + } + }) + .unwrap_or(1) +} + /// An owned git repository, representing all state associated with the /// underlying filesystem. /// @@ -2972,6 +2995,26 @@ impl Repository { Ok(Binding::from_raw(ret)) } } + + /// If a merge is in progress, invoke 'callback' for each commit ID in the + /// * MERGE_HEAD file. + pub fn mergehead_foreach(&mut self, mut callback: C) -> Result<(), Error> + where + C: FnMut(&Oid) -> bool, + { + unsafe { + let mut data = MergeheadForeachCbData { + callback: &mut callback, + }; + let cb: raw::git_repository_mergehead_foreach_cb = Some(mergehead_foreach_cb); + try_call!(raw::git_repository_mergehead_foreach( + self.raw(), + cb, + &mut data as *mut _ as *mut _ + )); + Ok(()) + } + } } impl Binding for Repository { From c32adc0572f3460ec87447459f0a27b7087ab7bd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 11 May 2021 07:15:16 -0700 Subject: [PATCH 565/860] Bump to 0.12.20+1.1.0 --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1182647a9a..3a52bcae6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.19" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.20" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 8cc6e65b0c..6404881417 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.19+1.1.0" +version = "0.12.20+1.1.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 9972c24281588a05f70adbcfe58d90280dc0b20a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 11 May 2021 07:15:37 -0700 Subject: [PATCH 566/860] Bump to 0.13.19 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3a52bcae6f..7733785b84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.18" +version = "0.13.19" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 81b9cf9cd03351bd1b4c0c6bd0feb30891ddb2b7 Mon Sep 17 00:00:00 2001 From: "Kartikaya Gupta (kats)" Date: Mon, 17 May 2021 18:29:29 -0400 Subject: [PATCH 567/860] Skip the systest tests on nightly rust (#709) These tests are failing now because the extprim crate required by the systest build-dependencies no longer compiles with nightly rust. --- .github/workflows/main.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 567a830852..528f118e8f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,7 +31,9 @@ jobs: shell: bash - run: cargo test --no-default-features - run: cargo test - - run: cargo run --manifest-path systest/Cargo.toml + # skip systest on nightly because it requires the extprim crate which fails to compile on nightly rust + - run: if [[ "${{ matrix.rust }}" != "nightly" ]]; then cargo run --manifest-path systest/Cargo.toml; fi + shell: bash - run: cargo test --manifest-path git2-curl/Cargo.toml rustfmt: From 0a64419db9fdca65f110e320d21d667d1d4a8ce0 Mon Sep 17 00:00:00 2001 From: "Kartikaya Gupta (kats)" Date: Mon, 17 May 2021 22:21:29 -0400 Subject: [PATCH 568/860] update libgit2 submodule to recent main (#708) This is specifically to pick up the fix at https://github.com/libgit2/libgit2/pull/5839 --- libgit2-sys/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 4bd172087c..be95f684da 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 4bd172087c30e09e7720a7df11cace47ee002256 +Subproject commit be95f684da5d05e59919448c1061febbd4ff6eb8 From e16e16a935949b739fc8e618106c5e7c4ce8a8a3 Mon Sep 17 00:00:00 2001 From: "Kartikaya Gupta (kats)" Date: Mon, 24 May 2021 10:37:20 -0400 Subject: [PATCH 569/860] Update git2 to compile with latest rustc nightly (#712) This works around the regression in https://github.com/rust-lang/rust/issues/85574 --- src/attr.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/attr.rs b/src/attr.rs index 1e689d98ca..33b1d2d4af 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -76,9 +76,9 @@ impl PartialEq for AttrValue<'_> { | (Self::False, AttrValue::False) | (Self::Unspecified, AttrValue::Unspecified) => true, (AttrValue::String(string), AttrValue::Bytes(bytes)) - | (Self::Bytes(bytes), AttrValue::String(string)) => string.as_bytes() == *bytes, - (Self::String(left), AttrValue::String(right)) => left == right, - (Self::Bytes(left), AttrValue::Bytes(right)) => left == right, + | (AttrValue::Bytes(bytes), AttrValue::String(string)) => string.as_bytes() == *bytes, + (AttrValue::String(left), AttrValue::String(right)) => left == right, + (AttrValue::Bytes(left), AttrValue::Bytes(right)) => left == right, _ => false, } } From b673a5cc4e5a75e10e91774f96c77615e8981b2b Mon Sep 17 00:00:00 2001 From: Arlo Siemsen Date: Mon, 24 May 2021 07:39:05 -0700 Subject: [PATCH 570/860] Add support for specifying additional custom headers on git push and fetch operations (#711) --- src/remote.rs | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/src/remote.rs b/src/remote.rs index 042a3caa45..13a28cd93d 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -1,11 +1,12 @@ use libc; -use std::ffi::CString; +use raw::git_strarray; use std::marker; use std::mem; use std::ops::Range; use std::ptr; use std::slice; use std::str; +use std::{ffi::CString, os::raw::c_char}; use crate::string_array::StringArray; use crate::util::Binding; @@ -43,6 +44,8 @@ pub struct FetchOptions<'cb> { prune: FetchPrune, update_fetchhead: bool, download_tags: AutotagOption, + custom_headers: Vec, + custom_headers_ptrs: Vec<*const c_char>, } /// Options to control the behavior of a git push. @@ -50,6 +53,8 @@ pub struct PushOptions<'cb> { callbacks: Option>, proxy: Option>, pb_parallelism: u32, + custom_headers: Vec, + custom_headers_ptrs: Vec<*const c_char>, } /// Holds callbacks for a connection to a `Remote`. Disconnects when dropped @@ -474,6 +479,8 @@ impl<'cb> FetchOptions<'cb> { prune: FetchPrune::Unspecified, update_fetchhead: true, download_tags: AutotagOption::Unspecified, + custom_headers: Vec::new(), + custom_headers_ptrs: Vec::new(), } } @@ -511,6 +518,16 @@ impl<'cb> FetchOptions<'cb> { self.download_tags = opt; self } + + /// Set extra headers for this fetch operation. + pub fn custom_headers(&mut self, custom_headers: &[&str]) -> &mut Self { + self.custom_headers = custom_headers + .iter() + .map(|&s| CString::new(s).unwrap()) + .collect(); + self.custom_headers_ptrs = self.custom_headers.iter().map(|s| s.as_ptr()).collect(); + self + } } impl<'cb> Binding for FetchOptions<'cb> { @@ -535,10 +552,9 @@ impl<'cb> Binding for FetchOptions<'cb> { prune: crate::call::convert(&self.prune), update_fetchhead: crate::call::convert(&self.update_fetchhead), download_tags: crate::call::convert(&self.download_tags), - // TODO: expose this as a builder option - custom_headers: raw::git_strarray { - count: 0, - strings: ptr::null_mut(), + custom_headers: git_strarray { + count: self.custom_headers_ptrs.len(), + strings: self.custom_headers_ptrs.as_ptr() as *mut _, }, } } @@ -557,6 +573,8 @@ impl<'cb> PushOptions<'cb> { callbacks: None, proxy: None, pb_parallelism: 1, + custom_headers: Vec::new(), + custom_headers_ptrs: Vec::new(), } } @@ -582,6 +600,16 @@ impl<'cb> PushOptions<'cb> { self.pb_parallelism = parallel; self } + + /// Set extra headers for this push operation. + pub fn custom_headers(&mut self, custom_headers: &[&str]) -> &mut Self { + self.custom_headers = custom_headers + .iter() + .map(|&s| CString::new(s).unwrap()) + .collect(); + self.custom_headers_ptrs = self.custom_headers.iter().map(|s| s.as_ptr()).collect(); + self + } } impl<'cb> Binding for PushOptions<'cb> { @@ -604,10 +632,9 @@ impl<'cb> Binding for PushOptions<'cb> { .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 { - count: 0, - strings: ptr::null_mut(), + custom_headers: git_strarray { + count: self.custom_headers_ptrs.len(), + strings: self.custom_headers_ptrs.as_ptr() as *mut _, }, } } From 290c68d020581f65e3776a267c0cb256e595fc9d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 24 May 2021 07:39:55 -0700 Subject: [PATCH 571/860] Bump libgit2-sys to 0.12.21+1.1.0 --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7733785b84..7b88fda655 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.20" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.21" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 6404881417..78f8d64c69 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.20+1.1.0" +version = "0.12.21+1.1.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 910394149da909ae5f2a2279b2f3a0a3b254c8f6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 24 May 2021 07:40:22 -0700 Subject: [PATCH 572/860] Bump to 0.13.20 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7b88fda655..3eaabd0a15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.19" +version = "0.13.20" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" From 0454efbaa0447a1d02eb11459a7db5e1c27d98e0 Mon Sep 17 00:00:00 2001 From: Francisco Demartino Date: Tue, 1 Jun 2021 12:11:05 -0300 Subject: [PATCH 573/860] add bindings for `git_branch_name_is_valid` (#715) --- libgit2-sys/lib.rs | 1 + src/branch.rs | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 16516197a3..9ab6c49d2d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2740,6 +2740,7 @@ extern "C" { force: c_int, ) -> c_int; pub fn git_branch_name(out: *mut *const c_char, branch: *const git_reference) -> c_int; + pub fn git_branch_name_is_valid(valid: *mut c_int, name: *const c_char) -> c_int; pub fn git_branch_remote_name( out: *mut git_buf, repo: *mut git_repository, diff --git a/src/branch.rs b/src/branch.rs index 276bc534ac..0e9c0239b2 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -28,6 +28,16 @@ impl<'repo> Branch<'repo> { Branch { inner: reference } } + /// Ensure the branch name is well-formed. + pub fn name_is_valid(name: &str) -> Result { + let name = CString::new(name)?; + let mut valid: libc::c_int = 0; + unsafe { + try_call!(raw::git_branch_name_is_valid(&mut valid, name.as_ptr())); + } + Ok(valid == 1) + } + /// Gain access to the reference that is this branch pub fn get(&self) -> &Reference<'repo> { &self.inner @@ -151,7 +161,7 @@ impl<'repo> Drop for Branches<'repo> { #[cfg(test)] mod tests { - use crate::BranchType; + use crate::{Branch, BranchType}; #[test] fn smoke() { @@ -175,4 +185,12 @@ mod tests { b1.delete().unwrap(); } + + #[test] + fn name_is_valid() { + assert!(Branch::name_is_valid("foo").unwrap()); + assert!(!Branch::name_is_valid("").unwrap()); + assert!(!Branch::name_is_valid("with spaces").unwrap()); + assert!(!Branch::name_is_valid("~tilde").unwrap()); + } } From db3799ad70e88262b4af05a4b4a699a104300613 Mon Sep 17 00:00:00 2001 From: Ivan Zvonimir Horvat Date: Fri, 4 Jun 2021 16:13:28 +0200 Subject: [PATCH 574/860] struct: remove redundant fields (#716) * struct: remove redundant fields * redundant: fix revspec fmt --- src/blame.rs | 4 ++-- src/blob.rs | 4 ++-- src/branch.rs | 2 +- src/cert.rs | 2 +- src/commit.rs | 2 +- src/config.rs | 8 ++++---- src/cred.rs | 2 +- src/describe.rs | 2 +- src/diff.rs | 16 ++++++++-------- src/error.rs | 8 ++++---- src/index.rs | 22 +++++++++++----------- src/mempack.rs | 2 +- src/merge.rs | 2 +- src/note.rs | 4 ++-- src/object.rs | 2 +- src/odb.rs | 8 ++++---- src/oid.rs | 4 ++-- src/oid_array.rs | 2 +- src/patch.rs | 2 +- src/pathspec.rs | 4 ++-- src/rebase.rs | 4 ++-- src/reference.rs | 4 ++-- src/reflog.rs | 4 ++-- src/refspec.rs | 2 +- src/remote.rs | 4 ++-- src/repo.rs | 2 +- src/revspec.rs | 6 +----- src/revwalk.rs | 7 ++++--- src/signature.rs | 2 +- src/status.rs | 6 +++--- src/string_array.rs | 2 +- src/submodule.rs | 2 +- src/tag.rs | 2 +- src/time.rs | 8 ++++---- src/transport.rs | 2 +- src/tree.rs | 4 ++-- src/treebuilder.rs | 2 +- 37 files changed, 81 insertions(+), 84 deletions(-) diff --git a/src/blame.rs b/src/blame.rs index 7db275229c..e7413dd5f8 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -247,7 +247,7 @@ impl<'repo> Binding for Blame<'repo> { unsafe fn from_raw(raw: *mut raw::git_blame) -> Blame<'repo> { Blame { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -268,7 +268,7 @@ impl<'blame> Binding for BlameHunk<'blame> { unsafe fn from_raw(raw: *mut raw::git_blame_hunk) -> BlameHunk<'blame> { BlameHunk { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/blob.rs b/src/blob.rs index ae7505a69e..5c4a6ce6b8 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -56,7 +56,7 @@ impl<'repo> Binding for Blob<'repo> { unsafe fn from_raw(raw: *mut raw::git_blob) -> Blob<'repo> { Blob { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -110,7 +110,7 @@ impl<'repo> Binding for BlobWriter<'repo> { unsafe fn from_raw(raw: *mut raw::git_writestream) -> BlobWriter<'repo> { BlobWriter { - raw: raw, + raw, need_cleanup: true, _marker: marker::PhantomData, } diff --git a/src/branch.rs b/src/branch.rs index 0e9c0239b2..de53d8c8ea 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -130,7 +130,7 @@ impl<'repo> Branches<'repo> { /// pointer. pub unsafe fn from_raw(raw: *mut raw::git_branch_iterator) -> Branches<'repo> { Branches { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/cert.rs b/src/cert.rs index 9153880b69..d62b8304ce 100644 --- a/src/cert.rs +++ b/src/cert.rs @@ -100,7 +100,7 @@ impl<'a> Binding for Cert<'a> { type Raw = *mut raw::git_cert; unsafe fn from_raw(raw: *mut raw::git_cert) -> Cert<'a> { Cert { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/commit.rs b/src/commit.rs index 4df60f7d9c..b7e900a7ae 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -313,7 +313,7 @@ impl<'repo> Binding for Commit<'repo> { type Raw = *mut raw::git_commit; unsafe fn from_raw(raw: *mut raw::git_commit) -> Commit<'repo> { Commit { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/config.rs b/src/config.rs index 66cd5bb4de..573fa358b7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -465,7 +465,7 @@ impl Config { impl Binding for Config { type Raw = *mut raw::git_config; unsafe fn from_raw(raw: *mut raw::git_config) -> Config { - Config { raw: raw } + Config { raw } } fn raw(&self) -> *mut raw::git_config { self.raw @@ -534,7 +534,7 @@ impl<'cfg> Binding for ConfigEntry<'cfg> { unsafe fn from_raw(raw: *mut raw::git_config_entry) -> ConfigEntry<'cfg> { ConfigEntry { - raw: raw, + raw, _marker: marker::PhantomData, owned: true, } @@ -549,7 +549,7 @@ impl<'cfg> Binding for ConfigEntries<'cfg> { unsafe fn from_raw(raw: *mut raw::git_config_iterator) -> ConfigEntries<'cfg> { ConfigEntries { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -571,7 +571,7 @@ impl<'cfg, 'b> Iterator for &'b ConfigEntries<'cfg> { try_call_iter!(raw::git_config_next(&mut raw, self.raw)); Some(Ok(ConfigEntry { owned: false, - raw: raw, + raw, _marker: marker::PhantomData, })) } diff --git a/src/cred.rs b/src/cred.rs index 41ff1c193b..ee686f123c 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -171,7 +171,7 @@ impl Binding for Cred { type Raw = *mut raw::git_cred; unsafe fn from_raw(raw: *mut raw::git_cred) -> Cred { - Cred { raw: raw } + Cred { raw } } fn raw(&self) -> *mut raw::git_cred { self.raw diff --git a/src/describe.rs b/src/describe.rs index efa66e826d..cbaa1893b6 100644 --- a/src/describe.rs +++ b/src/describe.rs @@ -44,7 +44,7 @@ impl<'repo> Binding for Describe<'repo> { unsafe fn from_raw(raw: *mut raw::git_describe_result) -> Describe<'repo> { Describe { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/diff.rs b/src/diff.rs index 656d5fbcfe..8303fd9c8b 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -447,7 +447,7 @@ impl<'repo> Binding for Diff<'repo> { type Raw = *mut raw::git_diff; unsafe fn from_raw(raw: *mut raw::git_diff) -> Diff<'repo> { Diff { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -545,7 +545,7 @@ impl<'a> Binding for DiffDelta<'a> { type Raw = *mut raw::git_diff_delta; unsafe fn from_raw(raw: *mut raw::git_diff_delta) -> DiffDelta<'a> { DiffDelta { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -630,7 +630,7 @@ impl<'a> Binding for DiffFile<'a> { type Raw = *const raw::git_diff_file; unsafe fn from_raw(raw: *const raw::git_diff_file) -> DiffFile<'a> { DiffFile { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -1081,7 +1081,7 @@ impl<'a> Binding for DiffLine<'a> { type Raw = *const raw::git_diff_line; unsafe fn from_raw(raw: *const raw::git_diff_line) -> DiffLine<'a> { DiffLine { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -1143,7 +1143,7 @@ impl<'a> Binding for DiffHunk<'a> { type Raw = *const raw::git_diff_hunk; unsafe fn from_raw(raw: *const raw::git_diff_hunk) -> DiffHunk<'a> { DiffHunk { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -1199,7 +1199,7 @@ impl Binding for DiffStats { type Raw = *mut raw::git_diff_stats; unsafe fn from_raw(raw: *mut raw::git_diff_stats) -> DiffStats { - DiffStats { raw: raw } + DiffStats { raw } } fn raw(&self) -> *mut raw::git_diff_stats { self.raw @@ -1248,7 +1248,7 @@ impl<'a> Binding for DiffBinary<'a> { type Raw = *const raw::git_diff_binary; unsafe fn from_raw(raw: *const raw::git_diff_binary) -> DiffBinary<'a> { DiffBinary { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -1280,7 +1280,7 @@ impl<'a> Binding for DiffBinaryFile<'a> { type Raw = *const raw::git_diff_binary_file; unsafe fn from_raw(raw: *const raw::git_diff_binary_file) -> DiffBinaryFile<'a> { DiffBinaryFile { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/error.rs b/src/error.rs index 4147d77391..f3ad9ad0e9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -69,12 +69,12 @@ impl Error { } unsafe fn from_raw(code: c_int, ptr: *const raw::git_error) -> Error { - let msg = CStr::from_ptr((*ptr).message as *const _).to_bytes(); - let msg = String::from_utf8_lossy(msg).into_owned(); + let message = CStr::from_ptr((*ptr).message as *const _).to_bytes(); + let message = String::from_utf8_lossy(message).into_owned(); Error { - code: code, + code, klass: (*ptr).klass, - message: msg, + message, } } diff --git a/src/index.rs b/src/index.rs index 5612f43a30..defc861eb8 100644 --- a/src/index.rs +++ b/src/index.rs @@ -166,7 +166,7 @@ impl Index { gid: entry.gid, file_size: entry.file_size, id: *entry.id.raw(), - flags: flags, + flags, flags_extended: entry.flags_extended, path: path.as_ptr(), mtime: raw::git_index_time { @@ -223,7 +223,7 @@ impl Index { gid: entry.gid, file_size: entry.file_size, id: *entry.id.raw(), - flags: flags, + flags, flags_extended: entry.flags_extended, path: path.as_ptr(), mtime: raw::git_index_time { @@ -600,7 +600,7 @@ impl Index { impl Binding for Index { type Raw = *mut raw::git_index; unsafe fn from_raw(raw: *mut raw::git_index) -> Index { - Index { raw: raw } + Index { raw } } fn raw(&self) -> *mut raw::git_index { self.raw @@ -718,15 +718,15 @@ impl Binding for IndexEntry { let path = slice::from_raw_parts(path as *const u8, pathlen); IndexEntry { - dev: dev, - ino: ino, - mode: mode, - uid: uid, - gid: gid, - file_size: file_size, + dev, + ino, + mode, + uid, + gid, + file_size, id: Binding::from_raw(&id as *const _), - flags: flags, - flags_extended: flags_extended, + flags, + flags_extended, path: path.to_vec(), mtime: Binding::from_raw(mtime), ctime: Binding::from_raw(ctime), diff --git a/src/mempack.rs b/src/mempack.rs index 2de9a27813..a780707913 100644 --- a/src/mempack.rs +++ b/src/mempack.rs @@ -16,7 +16,7 @@ impl<'odb> Binding for Mempack<'odb> { unsafe fn from_raw(raw: *mut raw::git_odb_backend) -> Mempack<'odb> { Mempack { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/merge.rs b/src/merge.rs index 4c2749bf9c..6bd30c10d1 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -178,7 +178,7 @@ impl<'repo> Binding for AnnotatedCommit<'repo> { type Raw = *mut raw::git_annotated_commit; unsafe fn from_raw(raw: *mut raw::git_annotated_commit) -> AnnotatedCommit<'repo> { AnnotatedCommit { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/note.rs b/src/note.rs index 99f7a686e8..50e5800fe7 100644 --- a/src/note.rs +++ b/src/note.rs @@ -53,7 +53,7 @@ impl<'repo> Binding for Note<'repo> { type Raw = *mut raw::git_note; unsafe fn from_raw(raw: *mut raw::git_note) -> Note<'repo> { Note { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -80,7 +80,7 @@ impl<'repo> Binding for Notes<'repo> { type Raw = *mut raw::git_note_iterator; unsafe fn from_raw(raw: *mut raw::git_note_iterator) -> Notes<'repo> { Notes { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/object.rs b/src/object.rs index 278c55d8c0..fcae0066cb 100644 --- a/src/object.rs +++ b/src/object.rs @@ -232,7 +232,7 @@ impl<'repo> Binding for Object<'repo> { unsafe fn from_raw(raw: *mut raw::git_object) -> Object<'repo> { Object { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/odb.rs b/src/odb.rs index 7c53e41d26..99392e052d 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -23,7 +23,7 @@ impl<'repo> Binding for Odb<'repo> { unsafe fn from_raw(raw: *mut raw::git_odb) -> Odb<'repo> { Odb { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -273,7 +273,7 @@ impl<'a> Binding for OdbObject<'a> { unsafe fn from_raw(raw: *mut raw::git_odb_object) -> OdbObject<'a> { OdbObject { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -327,7 +327,7 @@ impl<'repo> Binding for OdbReader<'repo> { unsafe fn from_raw(raw: *mut raw::git_odb_stream) -> OdbReader<'repo> { OdbReader { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -386,7 +386,7 @@ impl<'repo> Binding for OdbWriter<'repo> { unsafe fn from_raw(raw: *mut raw::git_odb_stream) -> OdbWriter<'repo> { OdbWriter { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/oid.rs b/src/oid.rs index 207ecd6840..145458aec0 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -35,7 +35,7 @@ impl Oid { s.len() as libc::size_t )); } - Ok(Oid { raw: raw }) + Ok(Oid { raw }) } /// Parse a raw object id into an Oid structure. @@ -52,7 +52,7 @@ impl Oid { unsafe { try_call!(raw::git_oid_fromraw(&mut raw, bytes.as_ptr())); } - Ok(Oid { raw: raw }) + Ok(Oid { raw }) } } diff --git a/src/oid_array.rs b/src/oid_array.rs index 914681ecc6..1640aaa221 100644 --- a/src/oid_array.rs +++ b/src/oid_array.rs @@ -32,7 +32,7 @@ impl Deref for OidArray { impl Binding for OidArray { type Raw = raw::git_oidarray; unsafe fn from_raw(raw: raw::git_oidarray) -> OidArray { - OidArray { raw: raw } + OidArray { raw } } fn raw(&self) -> raw::git_oidarray { self.raw diff --git a/src/patch.rs b/src/patch.rs index 2ff112b2c3..67b84c0f0a 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -21,7 +21,7 @@ impl<'buffers> Binding for Patch<'buffers> { type Raw = *mut raw::git_patch; unsafe fn from_raw(raw: Self::Raw) -> Self { Patch { - raw: raw, + raw, buffers: PhantomData, } } diff --git a/src/pathspec.rs b/src/pathspec.rs index e5fa0493d6..3df2e76812 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -168,7 +168,7 @@ impl Binding for Pathspec { type Raw = *mut raw::git_pathspec; unsafe fn from_raw(raw: *mut raw::git_pathspec) -> Pathspec { - Pathspec { raw: raw } + Pathspec { raw } } fn raw(&self) -> *mut raw::git_pathspec { self.raw @@ -268,7 +268,7 @@ impl<'ps> Binding for PathspecMatchList<'ps> { unsafe fn from_raw(raw: *mut raw::git_pathspec_match_list) -> PathspecMatchList<'ps> { PathspecMatchList { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/rebase.rs b/src/rebase.rs index e44470b820..2bf8fe3e8a 100644 --- a/src/rebase.rs +++ b/src/rebase.rs @@ -230,7 +230,7 @@ impl<'repo> Binding for Rebase<'repo> { type Raw = *mut raw::git_rebase; unsafe fn from_raw(raw: *mut raw::git_rebase) -> Rebase<'repo> { Rebase { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -324,7 +324,7 @@ impl<'rebase> Binding for RebaseOperation<'rebase> { type Raw = *const raw::git_rebase_operation; unsafe fn from_raw(raw: *const raw::git_rebase_operation) -> RebaseOperation<'rebase> { RebaseOperation { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/reference.rs b/src/reference.rs index cc08b0dfa6..479252a5cc 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -387,7 +387,7 @@ impl<'repo> Binding for Reference<'repo> { type Raw = *mut raw::git_reference; unsafe fn from_raw(raw: *mut raw::git_reference) -> Reference<'repo> { Reference { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -419,7 +419,7 @@ impl<'repo> Binding for References<'repo> { type Raw = *mut raw::git_reference_iterator; unsafe fn from_raw(raw: *mut raw::git_reference_iterator) -> References<'repo> { References { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/reflog.rs b/src/reflog.rs index 4bd6f90f06..61509191e9 100644 --- a/src/reflog.rs +++ b/src/reflog.rs @@ -103,7 +103,7 @@ impl Binding for Reflog { type Raw = *mut raw::git_reflog; unsafe fn from_raw(raw: *mut raw::git_reflog) -> Reflog { - Reflog { raw: raw } + Reflog { raw } } fn raw(&self) -> *mut raw::git_reflog { self.raw @@ -151,7 +151,7 @@ impl<'reflog> Binding for ReflogEntry<'reflog> { unsafe fn from_raw(raw: *const raw::git_reflog_entry) -> ReflogEntry<'reflog> { ReflogEntry { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/refspec.rs b/src/refspec.rs index dec71c3230..3f62e991c7 100644 --- a/src/refspec.rs +++ b/src/refspec.rs @@ -112,7 +112,7 @@ impl<'remote> Binding for Refspec<'remote> { unsafe fn from_raw(raw: *const raw::git_refspec) -> Refspec<'remote> { Refspec { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/remote.rs b/src/remote.rs index 13a28cd93d..b1cc4d3693 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -67,7 +67,7 @@ pub struct RemoteConnection<'repo, 'connection, 'cb> { pub fn remote_into_raw(remote: Remote<'_>) -> *mut raw::git_remote { let ret = remote.raw; mem::forget(remote); - return ret; + ret } impl<'repo> Remote<'repo> { @@ -406,7 +406,7 @@ impl<'repo> Binding for Remote<'repo> { unsafe fn from_raw(raw: *mut raw::git_remote) -> Remote<'repo> { Remote { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/repo.rs b/src/repo.rs index 82d37921c5..1304ecd74f 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2805,7 +2805,7 @@ impl Repository { let raw_opts = options.map(|o| o.raw()); let ptr_raw_opts = match raw_opts.as_ref() { Some(v) => v, - None => 0 as *const _, + None => std::ptr::null(), }; unsafe { try_call!(raw::git_cherrypick(self.raw(), commit.raw(), ptr_raw_opts)); diff --git a/src/revspec.rs b/src/revspec.rs index 120f83a359..d2e08670af 100644 --- a/src/revspec.rs +++ b/src/revspec.rs @@ -14,11 +14,7 @@ impl<'repo> Revspec<'repo> { to: Option>, mode: RevparseMode, ) -> Revspec<'repo> { - Revspec { - from: from, - to: to, - mode: mode, - } + Revspec { from, to, mode } } /// Access the `from` range of this revspec. diff --git a/src/revwalk.rs b/src/revwalk.rs index 7730551092..0cf4aa1253 100644 --- a/src/revwalk.rs +++ b/src/revwalk.rs @@ -28,9 +28,10 @@ where panic::wrap(|| unsafe { let hide_cb = payload as *mut C; if (*hide_cb)(Oid::from_raw(commit_id)) { - return 1; + 1 + } else { + 0 } - return 0; }) .unwrap_or(-1) } @@ -219,7 +220,7 @@ impl<'repo> Binding for Revwalk<'repo> { type Raw = *mut raw::git_revwalk; unsafe fn from_raw(raw: *mut raw::git_revwalk) -> Revwalk<'repo> { Revwalk { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/signature.rs b/src/signature.rs index 5677b7b577..32cfa2c812 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -105,7 +105,7 @@ impl<'a> Binding for Signature<'a> { type Raw = *mut raw::git_signature; unsafe fn from_raw(raw: *mut raw::git_signature) -> Signature<'a> { Signature { - raw: raw, + raw, _marker: marker::PhantomData, owned: true, } diff --git a/src/status.rs b/src/status.rs index 92858e48a5..d843458589 100644 --- a/src/status.rs +++ b/src/status.rs @@ -72,7 +72,7 @@ impl StatusOptions { let r = raw::git_status_init_options(&mut raw, raw::GIT_STATUS_OPTIONS_VERSION); assert_eq!(r, 0); StatusOptions { - raw: raw, + raw, pathspec: Vec::new(), ptrs: Vec::new(), } @@ -264,7 +264,7 @@ impl<'repo> Binding for Statuses<'repo> { type Raw = *mut raw::git_status_list; unsafe fn from_raw(raw: *mut raw::git_status_list) -> Statuses<'repo> { Statuses { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -340,7 +340,7 @@ impl<'statuses> Binding for StatusEntry<'statuses> { unsafe fn from_raw(raw: *const raw::git_status_entry) -> StatusEntry<'statuses> { StatusEntry { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/string_array.rs b/src/string_array.rs index b924e4033a..5c20d8c87e 100644 --- a/src/string_array.rs +++ b/src/string_array.rs @@ -79,7 +79,7 @@ impl StringArray { impl Binding for StringArray { type Raw = raw::git_strarray; unsafe fn from_raw(raw: raw::git_strarray) -> StringArray { - StringArray { raw: raw } + StringArray { raw } } fn raw(&self) -> raw::git_strarray { self.raw diff --git a/src/submodule.rs b/src/submodule.rs index c8f72efbde..d27f61ac36 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -233,7 +233,7 @@ impl<'repo> Binding for Submodule<'repo> { type Raw = *mut raw::git_submodule; unsafe fn from_raw(raw: *mut raw::git_submodule) -> Submodule<'repo> { Submodule { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/tag.rs b/src/tag.rs index 697e4f2757..ddc2d92828 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -118,7 +118,7 @@ impl<'repo> Binding for Tag<'repo> { type Raw = *mut raw::git_tag; unsafe fn from_raw(raw: *mut raw::git_tag) -> Tag<'repo> { Tag { - raw: raw, + raw, _marker: marker::PhantomData, } } diff --git a/src/time.rs b/src/time.rs index a01de7abb0..12a189e8b5 100644 --- a/src/time.rs +++ b/src/time.rs @@ -61,7 +61,7 @@ impl Ord for Time { impl Binding for Time { type Raw = raw::git_time; unsafe fn from_raw(raw: raw::git_time) -> Time { - Time { raw: raw } + Time { raw } } fn raw(&self) -> raw::git_time { self.raw @@ -73,8 +73,8 @@ impl IndexTime { pub fn new(seconds: i32, nanoseconds: u32) -> IndexTime { unsafe { Binding::from_raw(raw::git_index_time { - seconds: seconds, - nanoseconds: nanoseconds, + seconds, + nanoseconds, }) } } @@ -92,7 +92,7 @@ impl IndexTime { impl Binding for IndexTime { type Raw = raw::git_index_time; unsafe fn from_raw(raw: raw::git_index_time) -> IndexTime { - IndexTime { raw: raw } + IndexTime { raw } } fn raw(&self) -> raw::git_index_time { self.raw diff --git a/src/transport.rs b/src/transport.rs index db3fc3ef04..6872907847 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -271,7 +271,7 @@ extern "C" fn subtransport_action( write: Some(stream_write), free: Some(stream_free), }, - obj: obj, + obj, })); transport.stream = Some(*stream); } else { diff --git a/src/tree.rs b/src/tree.rs index 2f644833dc..68af61e335 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -225,7 +225,7 @@ impl<'repo> Binding for Tree<'repo> { unsafe fn from_raw(raw: *mut raw::git_tree) -> Tree<'repo> { Tree { - raw: raw, + raw, _marker: marker::PhantomData, } } @@ -334,7 +334,7 @@ impl<'a> Binding for TreeEntry<'a> { type Raw = *mut raw::git_tree_entry; unsafe fn from_raw(raw: *mut raw::git_tree_entry) -> TreeEntry<'a> { TreeEntry { - raw: raw, + raw, owned: true, _marker: marker::PhantomData, } diff --git a/src/treebuilder.rs b/src/treebuilder.rs index 5d40ea9b39..f88f074ca3 100644 --- a/src/treebuilder.rs +++ b/src/treebuilder.rs @@ -141,7 +141,7 @@ impl<'repo> Binding for TreeBuilder<'repo> { unsafe fn from_raw(raw: *mut raw::git_treebuilder) -> TreeBuilder<'repo> { TreeBuilder { - raw: raw, + raw, _marker: marker::PhantomData, } } From a6ea3e215b751eb3c71396469f80775d32b4afad Mon Sep 17 00:00:00 2001 From: Stephen Albert-Moore Date: Fri, 4 Jun 2021 16:29:06 -0400 Subject: [PATCH 575/860] Remove reference to old MSRV CI job in README (#717) The job was removed in abd3785084e3cc7accdd12afbc4eaae53d0135e7. --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 15e5b6d3f6..cabe88eafa 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,7 @@ git2 = "0.13" ## Rust version requirements git2-rs works with stable Rust, and typically works with the most recent prior -stable release as well. Check the MSRV job of [the CI script](.github/workflows/main.yml) to see the oldest -version of Rust known to pass tests. +stable release as well. ## Version of libgit2 From b055a28f0eebe491f4e2047be6dd3190e3c31060 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 7 Jun 2021 09:38:29 -0500 Subject: [PATCH 576/860] Fix vendored-openssl feature on macOS (#719) Turns out the git2 dependency on openssl-sys was conditional to happen everywhere but macOS, which means that vendored-openssl didn't work. The fix here is to forward the feature to the `libgit2-sys` crate which depends on `openssl-sys` even on macOS. Closes #718 --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3eaabd0a15..1de906fca3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ unstable = [] default = ["ssh", "https", "ssh_key_from_memory"] ssh = ["libgit2-sys/ssh"] https = ["libgit2-sys/https", "openssl-sys", "openssl-probe"] -vendored-openssl = ["openssl-sys/vendored"] +vendored-openssl = ["openssl-sys/vendored", "libgit2-sys/vendored-openssl"] ssh_key_from_memory = ["libgit2-sys/ssh_key_from_memory"] zlib-ng-compat = ["libgit2-sys/zlib-ng-compat"] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 78f8d64c69..44ef4b6e61 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -36,6 +36,7 @@ openssl-sys = { version = "0.9", optional = true } ssh = ["libssh2-sys"] https = ["openssl-sys"] ssh_key_from_memory = [] +vendored-openssl = ["openssl-sys/vendored"] # Cargo does not support requiring features on an optional dependency without # requiring the dependency. Rather than introduce additional complexity, we # just require libssh2 when using zlib-ng-compat. This will require building From 7d1240514f8b5a2de935bf2b5ae20229257b943f Mon Sep 17 00:00:00 2001 From: Waleed Khan Date: Mon, 14 Jun 2021 07:18:48 -0700 Subject: [PATCH 577/860] add binding for `git_apply_to_tree` (#720) --- src/repo.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index 1304ecd74f..43cf49f1e5 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2891,6 +2891,26 @@ impl Repository { } } + /// Apply a Diff to the provided tree, and return the resulting Index. + pub fn apply_to_tree( + &self, + tree: &Tree<'_>, + diff: &Diff<'_>, + options: Option<&mut ApplyOptions<'_>>, + ) -> Result { + let mut ret = ptr::null_mut(); + unsafe { + try_call!(raw::git_apply_to_tree( + &mut ret, + self.raw, + tree.raw(), + diff.raw(), + options.map(|s| s.raw()).unwrap_or(ptr::null()) + )); + Ok(Binding::from_raw(ret)) + } + } + /// Reverts the given commit, producing changes in the index and working directory. pub fn revert( &self, From 611fbf81fbe916e26c3968e67d5f489ade362958 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Fri, 23 Jul 2021 16:04:57 +0200 Subject: [PATCH 578/860] enable tracing and add tracing types and func (#730) * enable tracing and add tracing types and func * fix return value --- libgit2-sys/build.rs | 1 + libgit2-sys/lib.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 76aa687cf6..12831ec73b 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -107,6 +107,7 @@ fn main() { features.push_str("#ifndef INCLUDE_features_h\n"); features.push_str("#define INCLUDE_features_h\n"); features.push_str("#define GIT_THREADS 1\n"); + features.push_str("#define GIT_TRACE 1\n"); if !target.contains("android") { features.push_str("#define GIT_USE_NSEC 1\n"); diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 9ab6c49d2d..0d425e80c4 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1892,6 +1892,33 @@ pub const GIT_WORKTREE_PRUNE_OPTIONS_VERSION: c_uint = 1; pub type git_repository_mergehead_foreach_cb = Option c_int>; +git_enum! { + pub enum git_trace_level_t { + /* No tracing will be performed. */ + GIT_TRACE_NONE = 0, + + /* Severe errors that may impact the program's execution */ + GIT_TRACE_FATAL = 1, + + /* Errors that do not impact the program's execution */ + GIT_TRACE_ERROR = 2, + + /* Warnings that suggest abnormal data */ + GIT_TRACE_WARN = 3, + + /* Informational messages about program execution */ + GIT_TRACE_INFO = 4, + + /* Detailed data that allows for debugging */ + GIT_TRACE_DEBUG = 5, + + /* Exceptionally detailed debugging data */ + GIT_TRACE_TRACE = 6, + } +} + +pub type git_trace_cb = Option; + extern "C" { // threads pub fn git_libgit2_init() -> c_int; @@ -3986,6 +4013,8 @@ extern "C" { replace_name: *const c_char, replace_email: *const c_char, ) -> c_int; + + pub fn git_trace_set(level: git_trace_level_t, cb: git_trace_cb) -> c_int; } pub fn init() { From 26cb0b5ad81c9ca23d5b435dc2504dc36f2125d1 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Tue, 27 Jul 2021 17:05:58 +0200 Subject: [PATCH 579/860] Safe tracing (#732) * safe wrapper for tracing * try leaky pointer casting approach * get rid of box * fmt --- src/lib.rs | 2 ++ src/tracing.rs | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/tracing.rs diff --git a/src/lib.rs b/src/lib.rs index 52b49fd79f..6972adcb4a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -130,6 +130,7 @@ pub use crate::status::{StatusEntry, StatusIter, StatusOptions, StatusShow, Stat pub use crate::submodule::{Submodule, SubmoduleUpdateOptions}; pub use crate::tag::Tag; pub use crate::time::{IndexTime, Time}; +pub use crate::tracing::{trace_set, TraceLevel}; pub use crate::transaction::Transaction; pub use crate::tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult}; pub use crate::treebuilder::TreeBuilder; @@ -690,6 +691,7 @@ mod submodule; mod tag; mod tagforeach; mod time; +mod tracing; mod transaction; mod tree; mod treebuilder; diff --git a/src/tracing.rs b/src/tracing.rs new file mode 100644 index 0000000000..f348575774 --- /dev/null +++ b/src/tracing.rs @@ -0,0 +1,82 @@ +use std::sync::atomic::{AtomicUsize, Ordering}; + +use libc::c_char; + +use crate::{panic, raw, util::Binding}; + +/// Available tracing levels. When tracing is set to a particular level, +/// callers will be provided tracing at the given level and all lower levels. +#[derive(Copy, Clone, Debug)] +pub enum TraceLevel { + /// No tracing will be performed. + None, + + /// Severe errors that may impact the program's execution + Fatal, + + /// Errors that do not impact the program's execution + Error, + + /// Warnings that suggest abnormal data + Warn, + + /// Informational messages about program execution + Info, + + /// Detailed data that allows for debugging + Debug, + + /// Exceptionally detailed debugging data + Trace, +} + +impl Binding for TraceLevel { + type Raw = raw::git_trace_level_t; + unsafe fn from_raw(raw: raw::git_trace_level_t) -> Self { + match raw { + raw::GIT_TRACE_NONE => Self::None, + raw::GIT_TRACE_FATAL => Self::Fatal, + raw::GIT_TRACE_ERROR => Self::Error, + raw::GIT_TRACE_WARN => Self::Warn, + raw::GIT_TRACE_INFO => Self::Info, + raw::GIT_TRACE_DEBUG => Self::Debug, + raw::GIT_TRACE_TRACE => Self::Trace, + _ => panic!("Unknown git trace level"), + } + } + fn raw(&self) -> raw::git_trace_level_t { + match *self { + Self::None => raw::GIT_TRACE_NONE, + Self::Fatal => raw::GIT_TRACE_FATAL, + Self::Error => raw::GIT_TRACE_ERROR, + Self::Warn => raw::GIT_TRACE_WARN, + Self::Info => raw::GIT_TRACE_INFO, + Self::Debug => raw::GIT_TRACE_DEBUG, + Self::Trace => raw::GIT_TRACE_TRACE, + } + } +} + +pub type TracingCb = fn(TraceLevel, &str); + +static CALLBACK: AtomicUsize = AtomicUsize::new(0); + +/// +pub fn trace_set(level: TraceLevel, cb: TracingCb) -> bool { + CALLBACK.store(cb as usize, Ordering::SeqCst); + + unsafe { + raw::git_trace_set(level.raw(), Some(tracing_cb_c)); + } + + return true; +} + +extern "C" fn tracing_cb_c(level: raw::git_trace_level_t, msg: *const c_char) { + let cb = CALLBACK.load(Ordering::SeqCst); + panic::wrap(|| unsafe { + let cb: TracingCb = std::mem::transmute(cb); + let msg = std::ffi::CStr::from_ptr(msg).to_str().unwrap(); + cb(Binding::from_raw(level), msg); + }); +} From b863968301f0e889fa04afc590d7e2c9a4100dc3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 12 Aug 2021 13:51:35 -0700 Subject: [PATCH 580/860] Bump crate versions --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1de906fca3..191173bf02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.20" +version = "0.13.21" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.21" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.22" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 44ef4b6e61..99266f4a9c 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.21+1.1.0" +version = "0.12.22+1.1.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 8d2a86c9e9d8367a6706afef5dfe703ca6a714c9 Mon Sep 17 00:00:00 2001 From: Waleed Khan Date: Mon, 23 Aug 2021 11:42:33 -0700 Subject: [PATCH 581/860] Fix test `branch::tests::name_is_valid` The `Branch::name_is_valid` function allocates memory in `libgit2`, so we need to initialize the memory allocator first via `git_libgit2_init`. --- src/branch.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/branch.rs b/src/branch.rs index de53d8c8ea..e1eba99c2b 100644 --- a/src/branch.rs +++ b/src/branch.rs @@ -30,6 +30,7 @@ impl<'repo> Branch<'repo> { /// Ensure the branch name is well-formed. pub fn name_is_valid(name: &str) -> Result { + crate::init(); let name = CString::new(name)?; let mut valid: libc::c_int = 0; unsafe { From 97091c3f3e170e59b00f669a7f1a2043f4ffd735 Mon Sep 17 00:00:00 2001 From: Waleed Khan Date: Fri, 27 Aug 2021 12:30:05 -0700 Subject: [PATCH 582/860] Add `vendored` feature (#739) As per https://github.com/rust-lang/git2-rs/issues/721, some consumers may prefer to build `libgit2` themselves to simplify distribution. To test the vendored version, you can run: ``` cargo build --features vendored-libgit2` ``` That being said, the test `branch::tests::name_is_valid` fails on macOS. This test is currently broken as per https://github.com/rust-lang/git2-rs/issues/721#issuecomment-860256600 --- Cargo.toml | 1 + libgit2-sys/Cargo.toml | 1 + libgit2-sys/build.rs | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 191173bf02..7bdde1284d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ unstable = [] default = ["ssh", "https", "ssh_key_from_memory"] ssh = ["libgit2-sys/ssh"] https = ["libgit2-sys/https", "openssl-sys", "openssl-probe"] +vendored-libgit2 = ["libgit2-sys/vendored"] vendored-openssl = ["openssl-sys/vendored", "libgit2-sys/vendored-openssl"] ssh_key_from_memory = ["libgit2-sys/ssh_key_from_memory"] zlib-ng-compat = ["libgit2-sys/zlib-ng-compat"] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 99266f4a9c..ed4299a36c 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -36,6 +36,7 @@ openssl-sys = { version = "0.9", optional = true } ssh = ["libssh2-sys"] https = ["openssl-sys"] ssh_key_from_memory = [] +vendored = [] vendored-openssl = ["openssl-sys/vendored"] # Cargo does not support requiring features on an optional dependency without # requiring the dependency. Rather than introduce additional complexity, we diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 12831ec73b..3bd2ceb993 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -7,10 +7,12 @@ use std::process::Command; fn main() { let https = env::var("CARGO_FEATURE_HTTPS").is_ok(); let ssh = env::var("CARGO_FEATURE_SSH").is_ok(); + let vendored = env::var("CARGO_FEATURE_VENDORED").is_ok(); let zlib_ng_compat = env::var("CARGO_FEATURE_ZLIB_NG_COMPAT").is_ok(); // To use zlib-ng in zlib-compat mode, we have to build libgit2 ourselves. - if !zlib_ng_compat { + let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; + if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); if let Ok(lib) = cfg.atleast_version("1.1.0").probe("libgit2") { for include in &lib.include_paths { From ca6672bc3a8756fb099416c5bb73c094da7ba92a Mon Sep 17 00:00:00 2001 From: Andrew Hickman Date: Mon, 30 Aug 2021 15:15:07 +0100 Subject: [PATCH 583/860] Add binding for git_repository_fetchhead_foreach (#738) * Add binding for git_repository_fetchhead_foreach * Assert pointers are not null in fetchhead_foreach_cb * Pass through remote url in bytes in `fetchhead_foreach` * Document parameters for `fetchhead_foreach` * Fix formatting of docs for `mergehead_foreach` --- libgit2-sys/lib.rs | 9 +++++++ src/repo.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 0d425e80c4..4e2f9be0f9 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1892,6 +1892,10 @@ pub const GIT_WORKTREE_PRUNE_OPTIONS_VERSION: c_uint = 1; pub type git_repository_mergehead_foreach_cb = Option c_int>; +pub type git_repository_fetchhead_foreach_cb = Option< + extern "C" fn(*const c_char, *const c_char, *const git_oid, c_uint, *mut c_void) -> c_int, +>; + git_enum! { pub enum git_trace_level_t { /* No tracing will be performed. */ @@ -2016,6 +2020,11 @@ extern "C" { callback: git_repository_mergehead_foreach_cb, payload: *mut c_void, ) -> c_int; + pub fn git_repository_fetchhead_foreach( + repo: *mut git_repository, + callback: git_repository_fetchhead_foreach_cb, + payload: *mut c_void, + ) -> c_int; pub fn git_ignore_add_rule(repo: *mut git_repository, rules: *const c_char) -> c_int; pub fn git_ignore_clear_internal_rules(repo: *mut git_repository) -> c_int; pub fn git_ignore_path_is_ignored( diff --git a/src/repo.rs b/src/repo.rs index 43cf49f1e5..f2cc541604 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -36,6 +36,11 @@ use crate::{DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder}; use crate::{Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag, Transaction}; type MergeheadForeachCb<'a> = dyn FnMut(&Oid) -> bool + 'a; +type FetchheadForeachCb<'a> = dyn FnMut(&str, &[u8], &Oid, bool) -> bool + 'a; + +struct FetchheadForeachCbData<'a> { + callback: &'a mut FetchheadForeachCb<'a>, +} struct MergeheadForeachCbData<'a> { callback: &'a mut MergeheadForeachCb<'a>, @@ -58,6 +63,39 @@ extern "C" fn mergehead_foreach_cb(oid: *const raw::git_oid, payload: *mut c_voi .unwrap_or(1) } +extern "C" fn fetchhead_foreach_cb( + ref_name: *const c_char, + remote_url: *const c_char, + oid: *const raw::git_oid, + is_merge: c_uint, + payload: *mut c_void, +) -> c_int { + panic::wrap(|| unsafe { + let data = &mut *(payload as *mut FetchheadForeachCbData<'_>); + let res = { + let callback = &mut data.callback; + + assert!(!ref_name.is_null()); + assert!(!remote_url.is_null()); + assert!(!oid.is_null()); + + let ref_name = str::from_utf8(CStr::from_ptr(ref_name).to_bytes()).unwrap(); + let remote_url = CStr::from_ptr(remote_url).to_bytes(); + let oid = Binding::from_raw(oid); + let is_merge = is_merge == 1; + + callback(&ref_name, remote_url, &oid, is_merge) + }; + + if res { + 0 + } else { + 1 + } + }) + .unwrap_or(1) +} + /// An owned git repository, representing all state associated with the /// underlying filesystem. /// @@ -3017,7 +3055,7 @@ impl Repository { } /// If a merge is in progress, invoke 'callback' for each commit ID in the - /// * MERGE_HEAD file. + /// MERGE_HEAD file. pub fn mergehead_foreach(&mut self, mut callback: C) -> Result<(), Error> where C: FnMut(&Oid) -> bool, @@ -3035,6 +3073,32 @@ impl Repository { Ok(()) } } + + /// Invoke 'callback' for each entry in the given FETCH_HEAD file. + /// + /// `callback` will be called with with following arguments: + /// + /// - `&str`: the reference name + /// - `&[u8]`: the remote url + /// - `&Oid`: the reference target OID + /// - `bool`: was the reference the result of a merge + pub fn fetchhead_foreach(&self, mut callback: C) -> Result<(), Error> + where + C: FnMut(&str, &[u8], &Oid, bool) -> bool, + { + unsafe { + let mut data = FetchheadForeachCbData { + callback: &mut callback, + }; + let cb: raw::git_repository_fetchhead_foreach_cb = Some(fetchhead_foreach_cb); + try_call!(raw::git_repository_fetchhead_foreach( + self.raw(), + cb, + &mut data as *mut _ as *mut _ + )); + Ok(()) + } + } } impl Binding for Repository { From c273ed95357f39bea4234bc5880fd4bd6ff66e8b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 3 Sep 2021 12:26:48 -0500 Subject: [PATCH 584/860] Bump libgit2 submodule to 1.2.0 (#744) * Bump libgit2 submodule to 1.2.0 Follow the recent release of 1.2.0 * Update bindings --- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/lib.rs | 20 ++++++++++++++++++++ libgit2-sys/libgit2 | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index ed4299a36c..94e3f54994 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.22+1.1.0" +version = "0.12.22+1.2.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 4e2f9be0f9..d6f6356b6f 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -353,6 +353,8 @@ pub type git_indexer_progress_cb = )] pub type git_transfer_progress = git_indexer_progress; +pub type git_remote_ready_cb = Option c_int>; + #[repr(C)] pub struct git_remote_callbacks { pub version: c_uint, @@ -368,6 +370,7 @@ pub struct git_remote_callbacks { pub push_update_reference: git_push_update_reference_cb, pub push_negotiation: git_push_negotiation, pub transport: git_transport_cb, + pub remote_ready: git_remote_ready_cb, pub payload: *mut c_void, pub resolve_url: git_url_resolve_cb, } @@ -1486,6 +1489,8 @@ pub struct git_odb_backend { ) -> c_int, >, + pub writemidx: Option c_int>, + pub freshen: Option c_int>, pub free: Option, @@ -1745,6 +1750,20 @@ pub type git_commit_signing_cb = Option< ) -> c_int, >; +pub type git_commit_create_cb = Option< + extern "C" fn( + *mut git_oid, + *const git_signature, + *const git_signature, + *const c_char, + *const c_char, + *const git_tree, + usize, + *const git_commit, + *mut c_void, + ) -> c_int, +>; + pub const GIT_REBASE_NO_OPERATION: usize = usize::max_value(); #[repr(C)] @@ -1755,6 +1774,7 @@ pub struct git_rebase_options { pub rewrite_notes_ref: *const c_char, pub merge_options: git_merge_options, pub checkout_options: git_checkout_options, + pub commit_create_cb: git_commit_create_cb, pub signing_cb: git_commit_signing_cb, pub payload: *mut c_void, } diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index be95f684da..4fd32be01c 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit be95f684da5d05e59919448c1061febbd4ff6eb8 +Subproject commit 4fd32be01c79a5c003bb47674ac1d76d948518b7 From 94b6240106210f1804dd8e272e0a4c1349d31c81 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Wed, 8 Sep 2021 16:07:59 +0200 Subject: [PATCH 585/860] version bumps (#745) --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7bdde1284d..10fa35ef82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.21" +version = "0.13.22" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.22" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.23" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 94e3f54994..0905273241 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.22+1.2.0" +version = "0.12.23+1.2.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 337899793fd090e70f17d964a0865a5f07b770bc Mon Sep 17 00:00:00 2001 From: Alex Roper Date: Thu, 23 Sep 2021 11:07:56 -0700 Subject: [PATCH 586/860] Fix doc for `target_type`. --- src/tag.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tag.rs b/src/tag.rs index ddc2d92828..8cd328fdd2 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -86,7 +86,7 @@ impl<'repo> Tag<'repo> { unsafe { Binding::from_raw(raw::git_tag_target_id(&*self.raw)) } } - /// Get the OID of the tagged object of a tag + /// Get the ObjectType of the tagged object of a tag pub fn target_type(&self) -> Option { unsafe { ObjectType::from_raw(raw::git_tag_target_type(&*self.raw)) } } From 45536a112ee48d81f7f4a592a3d8ee8f83f631f8 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 27 Sep 2021 11:30:48 -0700 Subject: [PATCH 587/860] Add way to get build version information. (#748) --- libgit2-sys/build.rs | 2 + libgit2-sys/lib.rs | 17 ++++++++ src/lib.rs | 2 + src/version.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 src/version.rs diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 3bd2ceb993..36dc3d9b8f 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -22,6 +22,8 @@ fn main() { } } + println!("cargo:rustc-cfg=libgit2_vendored"); + if !Path::new("libgit2/.git").exists() { let _ = Command::new("git") .args(&["submodule", "update", "--init", "libgit2"]) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index d6f6356b6f..d9bd3392e6 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1943,6 +1943,15 @@ git_enum! { pub type git_trace_cb = Option; +git_enum! { + pub enum git_feature_t { + GIT_FEATURE_THREADS = 1 << 0, + GIT_FEATURE_HTTPS = 1 << 1, + GIT_FEATURE_SSH = 1 << 2, + GIT_FEATURE_NSEC = 1 << 3, + } +} + extern "C" { // threads pub fn git_libgit2_init() -> c_int; @@ -3948,6 +3957,9 @@ extern "C" { given_opts: *const git_revert_options, ) -> c_int; + // Common + pub fn git_libgit2_version(major: *mut c_int, minor: *mut c_int, rev: *mut c_int) -> c_int; + pub fn git_libgit2_features() -> c_int; pub fn git_libgit2_opts(option: c_int, ...) -> c_int; // Worktrees @@ -4092,3 +4104,8 @@ fn ssh_init() { #[cfg(not(feature = "ssh"))] fn ssh_init() {} + +#[doc(hidden)] +pub fn vendored() -> bool { + cfg!(libgit2_vendored) +} diff --git a/src/lib.rs b/src/lib.rs index 6972adcb4a..bcabcdf044 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -135,6 +135,7 @@ pub use crate::transaction::Transaction; pub use crate::tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult}; pub use crate::treebuilder::TreeBuilder; pub use crate::util::IntoCString; +pub use crate::version::Version; pub use crate::worktree::{Worktree, WorktreeAddOptions, WorktreeLockStatus, WorktreePruneOptions}; // Create a convinience method on bitflag struct which checks the given flag @@ -695,6 +696,7 @@ mod tracing; mod transaction; mod tree; mod treebuilder; +mod version; mod worktree; fn init() { diff --git a/src/version.rs b/src/version.rs new file mode 100644 index 0000000000..b5dd4fb123 --- /dev/null +++ b/src/version.rs @@ -0,0 +1,95 @@ +use crate::raw; +use libc::c_int; +use std::fmt; + +/// Version information about libgit2 and the capabilities it supports. +pub struct Version { + major: c_int, + minor: c_int, + rev: c_int, + features: c_int, +} + +macro_rules! flag_test { + ($features:expr, $flag:expr) => { + ($features as u32 & $flag as u32) != 0 + }; +} + +impl Version { + /// Returns a [`Version`] which provides information about libgit2. + pub fn get() -> Version { + let mut v = Version { + major: 0, + minor: 0, + rev: 0, + features: 0, + }; + unsafe { + raw::git_libgit2_version(&mut v.major, &mut v.minor, &mut v.rev); + v.features = raw::git_libgit2_features(); + } + v + } + + /// Returns the version of libgit2. + /// + /// The return value is a tuple of `(major, minor, rev)` + pub fn libgit2_version(&self) -> (u32, u32, u32) { + (self.major as u32, self.minor as u32, self.rev as u32) + } + + /// Returns the version of the libgit2-sys crate. + pub fn crate_version(&self) -> &'static str { + env!("CARGO_PKG_VERSION") + } + + /// Returns true if this was built with the vendored version of libgit2. + pub fn vendored(&self) -> bool { + raw::vendored() + } + + /// Returns true if libgit2 was built thread-aware and can be safely used + /// from multiple threads. + pub fn threads(&self) -> bool { + flag_test!(self.features, raw::GIT_FEATURE_THREADS) + } + + /// Returns true if libgit2 was built with and linked against a TLS implementation. + /// + /// Custom TLS streams may still be added by the user to support HTTPS + /// regardless of this. + pub fn https(&self) -> bool { + flag_test!(self.features, raw::GIT_FEATURE_HTTPS) + } + + /// Returns true if libgit2 was built with and linked against libssh2. + /// + /// A custom transport may still be added by the user to support libssh2 + /// regardless of this. + pub fn ssh(&self) -> bool { + flag_test!(self.features, raw::GIT_FEATURE_SSH) + } + + /// Returns true if libgit2 was built with support for sub-second + /// resolution in file modification times. + pub fn nsec(&self) -> bool { + flag_test!(self.features, raw::GIT_FEATURE_NSEC) + } +} + +impl fmt::Debug for Version { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + let mut f = f.debug_struct("Version"); + f.field("major", &self.major) + .field("minor", &self.minor) + .field("rev", &self.rev) + .field("crate_version", &self.crate_version()) + .field("vendored", &self.vendored()) + .field("threads", &self.threads()) + .field("https", &self.https()) + .field("ssh", &self.ssh()) + .field("nsec", &self.nsec()); + f.finish() + } +} From 353450e333d07f08802702bb16b4779fa7896967 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 28 Sep 2021 09:21:15 -0500 Subject: [PATCH 588/860] Bump libgit2 to 1.3.0 (#751) * Bump libgit2 to 1.3.0 * Change build metadata on version --- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/libgit2 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 0905273241..fce1d49bc3 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.23+1.2.0" +version = "0.12.23+1.3.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 4fd32be01c..b7bad55e4b 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 4fd32be01c79a5c003bb47674ac1d76d948518b7 +Subproject commit b7bad55e4bb0a285b073ba5e02b01d3f522fc95d From 6ca8b44fca4b60fca5c8b03c57372f6c72630a0e Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Tue, 28 Sep 2021 18:47:19 +0200 Subject: [PATCH 589/860] add missing diff option (#753) --- libgit2-sys/lib.rs | 1 + src/diff.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index d9bd3392e6..5e277b31ef 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1172,6 +1172,7 @@ pub const GIT_DIFF_UPDATE_INDEX: git_diff_option_t = 1 << 15; pub const GIT_DIFF_INCLUDE_UNREADABLE: git_diff_option_t = 1 << 16; pub const GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED: git_diff_option_t = 1 << 17; pub const GIT_DIFF_INDENT_HEURISTIC: git_diff_option_t = 1 << 18; +pub const GIT_DIFF_IGNORE_BLANK_LINES: git_diff_option_t = 1 << 19; pub const GIT_DIFF_FORCE_TEXT: git_diff_option_t = 1 << 20; pub const GIT_DIFF_FORCE_BINARY: git_diff_option_t = 1 << 21; pub const GIT_DIFF_IGNORE_WHITESPACE: git_diff_option_t = 1 << 22; diff --git a/src/diff.rs b/src/diff.rs index 8303fd9c8b..c71e0580fc 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -814,6 +814,11 @@ impl DiffOptions { self.flag(raw::GIT_DIFF_IGNORE_WHITESPACE_EOL, ignore) } + /// Ignore blank lines + pub fn ignore_blank_lines(&mut self, ignore: bool) -> &mut DiffOptions { + self.flag(raw::GIT_DIFF_IGNORE_BLANK_LINES, ignore) + } + /// When generating patch text, include the content of untracked files. /// /// This automatically turns on `include_untracked` but it does not turn on From 8e6660f9d7d641264fa5d212c1b1ad682e90e381 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 1 Oct 2021 10:28:42 -0700 Subject: [PATCH 590/860] Bump crate versions (#755) --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 10fa35ef82..59a1cc2bd9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.22" +version = "0.13.23" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.23" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.24" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index fce1d49bc3..58e1636d21 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.23+1.3.0" +version = "0.12.24+1.3.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 37f581a8c683e79ca0d653fe2f4f77319d27c97a Mon Sep 17 00:00:00 2001 From: saimen Date: Wed, 6 Oct 2021 19:28:37 +0200 Subject: [PATCH 591/860] Fix `DiffStat` doc typo --- src/diff.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diff.rs b/src/diff.rs index c71e0580fc..39623766e2 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -1170,7 +1170,7 @@ impl<'a> std::fmt::Debug for DiffHunk<'a> { } impl DiffStats { - /// Get the total number of files chaned in a diff. + /// Get the total number of files changed in a diff. pub fn files_changed(&self) -> usize { unsafe { raw::git_diff_stats_files_changed(&*self.raw) as usize } } From 4461b171f6a988f1b9a37e30addb82f7bf139454 Mon Sep 17 00:00:00 2001 From: Kristoffer Haugsbakk Date: Mon, 18 Oct 2021 17:20:30 +0200 Subject: [PATCH 592/860] Add binding for `git_message_trailers` (#749) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add binding for `git_message_trailers` * `cargo fmt` * Fix pointer mismatch error Fix error from `cargo run --manifest-path systest/Cargo.toml;`. You can’t just mix and match `*mut` and `*const` like that. * Remove a lot of unnecessary lifetimes Suggested-by: Alex Crichton See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r726550603 * Remove another unnecessary lifetime Suggested-by: Alex Crichton See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r726550919 * Use `Range` instead of `usize` I love it. Suggested-by: Alex Crichton See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r726551294 * `cargo fmt` * Inline one-off struct Suggested-by: Alex Crichton See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r726551473 * Implement more iterators Also change `to_str_tuple(…)` in order to share more code between two of the iterators. Suggested-by: Alex Crichton See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r726551780 * Undo accidental and unrelated edit * Less explicit lifetimes See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r729899152 * Don’t need `std::marker` any more See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r729899304 * Correct `len(…)` See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r729900328 * Remove unnecessary annotation See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r729900889 * Implement `size_hint()` Better than the default implementation. See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r729900533 * Split into “bytes” and “string” iterators Support both raw bytes messages as well as normal (UTF-8) messages by making two iterators. See: https://github.com/rust-lang/git2-rs/pull/749#discussion_r729951586 * Remove more lifetimes * Docs * `cargo fmt` * Undo accidental and unrelated edit (cherry picked from commit cd4c2dbee5f91610011913d3cd10e5786fbceef5) --- libgit2-sys/lib.rs | 21 ++++ src/lib.rs | 6 +- src/message.rs | 285 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 310 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5e277b31ef..7f128cd0db 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1953,6 +1953,20 @@ git_enum! { } } +#[repr(C)] +pub struct git_message_trailer { + pub key: *const c_char, + pub value: *const c_char, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct git_message_trailer_array { + pub trailers: *mut git_message_trailer, + pub count: size_t, + pub _trailer_block: *mut c_char, +} + extern "C" { // threads pub fn git_libgit2_init() -> c_int; @@ -3678,6 +3692,13 @@ extern "C" { comment_char: c_char, ) -> c_int; + pub fn git_message_trailers( + out: *mut git_message_trailer_array, + message: *const c_char, + ) -> c_int; + + pub fn git_message_trailer_array_free(trailer: *mut git_message_trailer_array); + // packbuilder pub fn git_packbuilder_new(out: *mut *mut git_packbuilder, repo: *mut git_repository) -> c_int; pub fn git_packbuilder_set_threads(pb: *mut git_packbuilder, n: c_uint) -> c_uint; diff --git a/src/lib.rs b/src/lib.rs index bcabcdf044..2456877f6a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,7 +101,11 @@ pub use crate::indexer::{IndexerProgress, Progress}; pub use crate::mailmap::Mailmap; pub use crate::mempack::Mempack; pub use crate::merge::{AnnotatedCommit, MergeOptions}; -pub use crate::message::{message_prettify, DEFAULT_COMMENT_CHAR}; +pub use crate::message::{ + message_prettify, message_trailers_bytes, message_trailers_strs, MessageTrailersBytes, + MessageTrailersBytesIterator, MessageTrailersStrs, MessageTrailersStrsIterator, + DEFAULT_COMMENT_CHAR, +}; pub use crate::note::{Note, Notes}; pub use crate::object::Object; pub use crate::odb::{Odb, OdbObject, OdbPackwriter, OdbReader, OdbWriter}; diff --git a/src/message.rs b/src/message.rs index 7c17eeffe0..398f11659f 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,4 +1,7 @@ +use core::ops::Range; +use std::ffi::CStr; use std::ffi::CString; +use std::ptr; use libc::{c_char, c_int}; @@ -31,12 +34,216 @@ fn _message_prettify(message: CString, comment_char: Option) -> Result = Some(b'#'); +/// Get the trailers for the given message. +/// +/// Use this function when you are dealing with a UTF-8-encoded message. +pub fn message_trailers_strs(message: &str) -> Result { + _message_trailers(message.into_c_string()?).map(|res| MessageTrailersStrs(res)) +} + +/// Get the trailers for the given message. +/// +/// Use this function when the message might not be UTF-8-encoded, +/// or if you want to handle the returned trailer key–value pairs +/// as bytes. +pub fn message_trailers_bytes(message: S) -> Result { + _message_trailers(message.into_c_string()?).map(|res| MessageTrailersBytes(res)) +} + +fn _message_trailers(message: CString) -> Result { + let ret = MessageTrailers::new(); + unsafe { + try_call!(raw::git_message_trailers(ret.raw(), message)); + } + Ok(ret) +} + +/// Collection of UTF-8-encoded trailers. +/// +/// Use `iter()` to get access to the values. +pub struct MessageTrailersStrs(MessageTrailers); + +impl MessageTrailersStrs { + /// Create a borrowed iterator. + pub fn iter(&self) -> MessageTrailersStrsIterator<'_> { + MessageTrailersStrsIterator(self.0.iter()) + } + /// The number of trailer key–value pairs. + pub fn len(&self) -> usize { + self.0.len() + } + /// Convert to the “bytes” variant. + pub fn to_bytes(self) -> MessageTrailersBytes { + MessageTrailersBytes(self.0) + } +} + +/// Collection of unencoded (bytes) trailers. +/// +/// Use `iter()` to get access to the values. +pub struct MessageTrailersBytes(MessageTrailers); + +impl MessageTrailersBytes { + /// Create a borrowed iterator. + pub fn iter(&self) -> MessageTrailersBytesIterator<'_> { + MessageTrailersBytesIterator(self.0.iter()) + } + /// The number of trailer key–value pairs. + pub fn len(&self) -> usize { + self.0.len() + } +} + +struct MessageTrailers { + raw: raw::git_message_trailer_array, +} + +impl MessageTrailers { + fn new() -> MessageTrailers { + crate::init(); + unsafe { + Binding::from_raw(&mut raw::git_message_trailer_array { + trailers: ptr::null_mut(), + count: 0, + _trailer_block: ptr::null_mut(), + } as *mut _) + } + } + fn iter(&self) -> MessageTrailersIterator<'_> { + MessageTrailersIterator { + trailers: self, + range: Range { + start: 0, + end: self.raw.count, + }, + } + } + fn len(&self) -> usize { + self.raw.count + } +} + +impl Drop for MessageTrailers { + fn drop(&mut self) { + unsafe { + raw::git_message_trailer_array_free(&mut self.raw); + } + } +} + +impl Binding for MessageTrailers { + type Raw = *mut raw::git_message_trailer_array; + unsafe fn from_raw(raw: *mut raw::git_message_trailer_array) -> MessageTrailers { + MessageTrailers { raw: *raw } + } + fn raw(&self) -> *mut raw::git_message_trailer_array { + &self.raw as *const _ as *mut _ + } +} + +struct MessageTrailersIterator<'a> { + trailers: &'a MessageTrailers, + range: Range, +} + +fn to_raw_tuple(trailers: &MessageTrailers, index: usize) -> (*const c_char, *const c_char) { + unsafe { + let addr = trailers.raw.trailers.wrapping_add(index); + ((*addr).key, (*addr).value) + } +} + +/// Borrowed iterator over the UTF-8-encoded trailers. +pub struct MessageTrailersStrsIterator<'a>(MessageTrailersIterator<'a>); + +impl<'pair> Iterator for MessageTrailersStrsIterator<'pair> { + type Item = (&'pair str, &'pair str); + + fn next(&mut self) -> Option { + self.0 + .range + .next() + .map(|index| to_str_tuple(&self.0.trailers, index)) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.range.size_hint() + } +} + +impl ExactSizeIterator for MessageTrailersStrsIterator<'_> { + fn len(&self) -> usize { + self.0.range.len() + } +} + +impl DoubleEndedIterator for MessageTrailersStrsIterator<'_> { + fn next_back(&mut self) -> Option { + self.0 + .range + .next_back() + .map(|index| to_str_tuple(&self.0.trailers, index)) + } +} + +fn to_str_tuple(trailers: &MessageTrailers, index: usize) -> (&str, &str) { + unsafe { + let (rkey, rvalue) = to_raw_tuple(&trailers, index); + let key = CStr::from_ptr(rkey).to_str().unwrap(); + let value = CStr::from_ptr(rvalue).to_str().unwrap(); + (key, value) + } +} + +/// Borrowed iterator over the raw (bytes) trailers. +pub struct MessageTrailersBytesIterator<'a>(MessageTrailersIterator<'a>); + +impl<'pair> Iterator for MessageTrailersBytesIterator<'pair> { + type Item = (&'pair [u8], &'pair [u8]); + + fn next(&mut self) -> Option { + self.0 + .range + .next() + .map(|index| to_bytes_tuple(&self.0.trailers, index)) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.range.size_hint() + } +} + +impl ExactSizeIterator for MessageTrailersBytesIterator<'_> { + fn len(&self) -> usize { + self.0.range.len() + } +} + +impl DoubleEndedIterator for MessageTrailersBytesIterator<'_> { + fn next_back(&mut self) -> Option { + self.0 + .range + .next_back() + .map(|index| to_bytes_tuple(&self.0.trailers, index)) + } +} + +fn to_bytes_tuple(trailers: &MessageTrailers, index: usize) -> (&[u8], &[u8]) { + unsafe { + let (rkey, rvalue) = to_raw_tuple(&trailers, index); + let key = CStr::from_ptr(rkey).to_bytes(); + let value = CStr::from_ptr(rvalue).to_bytes(); + (key, value) + } +} + #[cfg(test)] mod tests { - use crate::{message_prettify, DEFAULT_COMMENT_CHAR}; #[test] fn prettify() { + use crate::{message_prettify, DEFAULT_COMMENT_CHAR}; + // This does not attempt to duplicate the extensive tests for // git_message_prettify in libgit2, just a few representative values to // make sure the interface works as expected. @@ -58,4 +265,80 @@ mod tests { "1\n" ); } + + #[test] + fn trailers() { + use crate::{message_trailers_bytes, message_trailers_strs, MessageTrailersStrs}; + use std::collections::HashMap; + + // no trailers + let message1 = " +WHAT ARE WE HERE FOR + +What are we here for? + +Just to be eaten? +"; + let expected: HashMap<&str, &str> = HashMap::new(); + assert_eq!(expected, to_map(&message_trailers_strs(message1).unwrap())); + + // standard PSA + let message2 = " +Attention all + +We are out of tomatoes. + +Spoken-by: Major Turnips +Transcribed-by: Seargant Persimmons +Signed-off-by: Colonel Kale +"; + let expected: HashMap<&str, &str> = vec![ + ("Spoken-by", "Major Turnips"), + ("Transcribed-by", "Seargant Persimmons"), + ("Signed-off-by", "Colonel Kale"), + ] + .into_iter() + .collect(); + assert_eq!(expected, to_map(&message_trailers_strs(message2).unwrap())); + + // ignore everything after `---` + let message3 = " +The fate of Seargant Green-Peppers + +Seargant Green-Peppers was killed by Caterpillar Battalion 44. + +Signed-off-by: Colonel Kale +--- +I never liked that guy, anyway. + +Opined-by: Corporal Garlic +"; + let expected: HashMap<&str, &str> = vec![("Signed-off-by", "Colonel Kale")] + .into_iter() + .collect(); + assert_eq!(expected, to_map(&message_trailers_strs(message3).unwrap())); + + // Raw bytes message; not valid UTF-8 + // Source: https://stackoverflow.com/a/3886015/1725151 + let message4 = b" +Be honest guys + +Am I a malformed brussels sprout? + +Signed-off-by: Lieutenant \xe2\x28\xa1prout +"; + + let trailer = message_trailers_bytes(&message4[..]).unwrap(); + let expected = (&b"Signed-off-by"[..], &b"Lieutenant \xe2\x28\xa1prout"[..]); + let actual = trailer.iter().next().unwrap(); + assert_eq!(expected, actual); + + fn to_map(trailers: &MessageTrailersStrs) -> HashMap<&str, &str> { + let mut map = HashMap::with_capacity(trailers.len()); + for (key, value) in trailers.iter() { + map.insert(key, value); + } + map + } + } } From 2afab9f0845d803fea41dd184edd5143595548b1 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 8 Nov 2021 16:13:48 +0100 Subject: [PATCH 593/860] Derive `Debug` for `IndexEntry`, `IndexTime`, and `Time` (#762) Sometimes it's useful to quickly dump an IndexEntry for debugging; having a `Debug` impl helps. Derive `Debug` for several time-related types (as well as the underlying structures in libgit2-sys). --- libgit2-sys/lib.rs | 4 ++-- src/index.rs | 1 + src/time.rs | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 7f128cd0db..951397cc2c 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -143,7 +143,7 @@ pub struct git_signature { } #[repr(C)] -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct git_time { pub time: git_time_t, pub offset: c_int, @@ -817,7 +817,7 @@ pub const GIT_INDEX_ENTRY_STAGEMASK: u16 = 0x3000; pub const GIT_INDEX_ENTRY_STAGESHIFT: u16 = 12; #[repr(C)] -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct git_index_time { pub seconds: i32, pub nanoseconds: u32, diff --git a/src/index.rs b/src/index.rs index defc861eb8..22334d0c19 100644 --- a/src/index.rs +++ b/src/index.rs @@ -54,6 +54,7 @@ pub type IndexMatchedPath<'a> = dyn FnMut(&Path, &[u8]) -> i32 + 'a; /// All fields of an entry are public for modification and inspection. This is /// also how a new index entry is created. #[allow(missing_docs)] +#[derive(Debug)] pub struct IndexEntry { pub ctime: IndexTime, pub mtime: IndexTime, diff --git a/src/time.rs b/src/time.rs index 12a189e8b5..46b5bd3f94 100644 --- a/src/time.rs +++ b/src/time.rs @@ -6,13 +6,13 @@ use crate::raw; use crate::util::Binding; /// Time in a signature -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Time { raw: raw::git_time, } /// Time structure used in a git index entry. -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct IndexTime { raw: raw::git_index_time, } From 494964727ff77fe0699f8062585e3bd16f466464 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 11 Nov 2021 16:07:18 +0100 Subject: [PATCH 594/860] Consistently derive Copy, Clone, Debug, PartialEq, and Eq for types (#764) --- src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2456877f6a..b7f262e94c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -311,7 +311,7 @@ pub enum RepositoryState { } /// An enumeration of the possible directions for a remote. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Direction { /// Data will be fetched (read) from this remote. Fetch, @@ -321,7 +321,7 @@ pub enum Direction { /// An enumeration of the operations that can be performed for the `reset` /// method on a `Repository`. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ResetType { /// Move the head to the given commit. Soft, @@ -1213,7 +1213,7 @@ impl SubmoduleStatus { /// These values represent settings for the `submodule.$name.ignore` /// configuration value which says how deeply to look at the working /// directory when getting the submodule status. -#[derive(Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum SubmoduleIgnore { /// Use the submodule's configuration Unspecified, @@ -1233,7 +1233,7 @@ pub enum SubmoduleIgnore { /// configuration value which says how to handle `git submodule update` /// for this submodule. The value is usually set in the ".gitmodules" /// file and copied to ".git/config" when the submodule is initialized. -#[derive(Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum SubmoduleUpdate { /// The default; when a submodule is updated, checkout the new detached /// HEAD to the submodule directory. @@ -1322,7 +1322,7 @@ impl CheckoutNotificationType { } /// Possible output formats for diff data -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum DiffFormat { /// full git diff Patch, @@ -1386,7 +1386,7 @@ pub enum FetchPrune { } #[allow(missing_docs)] -#[derive(Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum StashApplyProgress { /// None None, From 33b14ce7f1da2b3b4c5452cf1a7fe52c8194db7b Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 11 Nov 2021 21:47:45 +0100 Subject: [PATCH 595/860] Make `Odb` `Send` and `Sync` (#763) * libgit2-sys: build.rs: require 1.3.0 This ensures that we can count on new APIs and behavior, whether we're building our vendored version or using a system library. * Make `Odb` `Send` and `Sync` As of libgit2 1.2.0, `git_odb` uses locking internally, and should be thread-safe. Mark it `Send` and `Sync` to allow access from multiple threads. --- libgit2-sys/build.rs | 2 +- src/odb.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 36dc3d9b8f..0046afafca 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,7 +14,7 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.atleast_version("1.1.0").probe("libgit2") { + if let Ok(lib) = cfg.atleast_version("1.3.0").probe("libgit2") { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } diff --git a/src/odb.rs b/src/odb.rs index 99392e052d..4186f4846a 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -18,6 +18,10 @@ pub struct Odb<'repo> { _marker: marker::PhantomData>, } +// `git_odb` uses locking and atomics internally. +unsafe impl<'repo> Send for Odb<'repo> {} +unsafe impl<'repo> Sync for Odb<'repo> {} + impl<'repo> Binding for Odb<'repo> { type Raw = *mut raw::git_odb; From 979d2d542a67503d4bd5467bba1aca2bfdfce4ed Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 15 Nov 2021 15:34:28 +0100 Subject: [PATCH 596/860] Mark `OdbReader` and `OdbWriter` `Send` (#765) The underlying `git_odb_stream` objects don't do anything that would prevent moving them to another thread and continuing to operate on them, as long as the original thread can no longer touch them. --- src/odb.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/odb.rs b/src/odb.rs index 4186f4846a..12f0707fa5 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -326,6 +326,10 @@ pub struct OdbReader<'repo> { _marker: marker::PhantomData>, } +// `git_odb_stream` is not thread-safe internally, so it can't use `Sync`, but moving it to another +// thread and continuing to read will work. +unsafe impl<'repo> Send for OdbReader<'repo> {} + impl<'repo> Binding for OdbReader<'repo> { type Raw = *mut raw::git_odb_stream; @@ -367,6 +371,10 @@ pub struct OdbWriter<'repo> { _marker: marker::PhantomData>, } +// `git_odb_stream` is not thread-safe internally, so it can't use `Sync`, but moving it to another +// thread and continuing to write will work. +unsafe impl<'repo> Send for OdbWriter<'repo> {} + impl<'repo> OdbWriter<'repo> { /// Finish writing to an ODB stream /// From 6f3905dcc80b6e01988cd96b66a54b261725c454 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 16 Nov 2021 01:35:13 +0100 Subject: [PATCH 597/860] Bump versions --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 59a1cc2bd9..7a385f6a41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.23" +version = "0.13.24" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.24" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.25" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 58e1636d21..bc8889a2ba 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.24+1.3.0" +version = "0.12.25+1.3.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 869790f218e8cbefad33ad09855da1a03fd8d3f9 Mon Sep 17 00:00:00 2001 From: Gibson Fahnestock Date: Sat, 20 Nov 2021 19:28:44 +0000 Subject: [PATCH 598/860] Fix stdout->stderr typo in cred.rs --- src/cred.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cred.rs b/src/cred.rs index ee686f123c..fdffd61540 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -427,7 +427,7 @@ impl CredentialHelper { let output = my_try!(p.wait_with_output()); if !output.status.success() { debug!( - "credential helper failed: {}\nstdout ---\n{}\nstdout ---\n{}", + "credential helper failed: {}\nstdout ---\n{}\nstderr ---\n{}", output.status, String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr) From 68eecf638134ff66fbbb8b611f0ff1933aba7d96 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Sun, 28 Nov 2021 10:03:44 +0100 Subject: [PATCH 599/860] remove unused dependency --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7a385f6a41..17808d6623 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,6 @@ openssl-probe = { version = "0.1", optional = true } structopt = "0.3" time = "0.1.39" tempfile = "3.1.0" -thread-id = "3.3.0" # remove when we work with minimal-versions without it paste = "1" [features] From 4979a868cf60f1f0853baf1221a38e9981c627f0 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Tue, 30 Nov 2021 16:11:59 +0100 Subject: [PATCH 600/860] we have to expect non-utf8 strings in tracing messages (#770) * we can expect non-utf8 strings in tracing messages * pass tracing msg as slice instead of &str * doc comment * Revert "pass tracing msg as slice instead of &str" This reverts commit 50a990fd81bc7f410292bc444dd667630406411c. # Conflicts: # src/tracing.rs * update doc comment and add todo --- src/tracing.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tracing.rs b/src/tracing.rs index f348575774..691410cfc3 100644 --- a/src/tracing.rs +++ b/src/tracing.rs @@ -57,6 +57,9 @@ impl Binding for TraceLevel { } } +//TODO: pass raw &[u8] and leave conversion to consumer (breaking API) +/// Callback type used to pass tracing events to the subscriber. +/// see `trace_set` to register a scubscriber. pub type TracingCb = fn(TraceLevel, &str); static CALLBACK: AtomicUsize = AtomicUsize::new(0); @@ -76,7 +79,7 @@ extern "C" fn tracing_cb_c(level: raw::git_trace_level_t, msg: *const c_char) { let cb = CALLBACK.load(Ordering::SeqCst); panic::wrap(|| unsafe { let cb: TracingCb = std::mem::transmute(cb); - let msg = std::ffi::CStr::from_ptr(msg).to_str().unwrap(); - cb(Binding::from_raw(level), msg); + let msg = std::ffi::CStr::from_ptr(msg).to_string_lossy(); + cb(Binding::from_raw(level), msg.as_ref()); }); } From 2c67635a5b181008e3c904ab578ecdd4c75cb048 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 1 Dec 2021 07:14:19 -0800 Subject: [PATCH 601/860] Provide a function to modify the GIT_OPT_ENABLE_CACHING option (#783) --- src/opts.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/opts.rs b/src/opts.rs index 789034d41d..007b272c1b 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -69,6 +69,23 @@ pub unsafe fn get_search_path(level: ConfigLevel) -> Result { buf.into_c_string() } +/// Controls whether or not libgit2 will cache loaded objects. Enabled by +/// default, but disabling this can improve performance and memory usage if +/// loading a large number of objects that will not be referenced again. +/// Disabling this will cause repository objects to clear their caches when next +/// accessed. +pub fn enable_caching(enabled: bool) { + let error = unsafe { + raw::git_libgit2_opts( + raw::GIT_OPT_ENABLE_CACHING as libc::c_int, + enabled as libc::c_int, + ) + }; + // This function cannot actually fail, but the function has an error return + // for other options that can. + debug_assert!(error >= 0); +} + /// Controls whether or not libgit2 will verify when writing an object that all /// objects it references are valid. Enabled by default, but disabling this can /// significantly improve performance, at the cost of potentially allowing the From 5383afcf6822daa6b6c3c574c03fa62b8352158c Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 1 Dec 2021 07:14:33 -0800 Subject: [PATCH 602/860] impl Send for TreeUpdateBuilder (#784) TreeUpdateBuilder does not have any interior mutability, and the underlying libgit2 data structures are safe to send to a different thread as long as the old doesn't have a copy anymore. --- src/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/build.rs b/src/build.rs index fd17848346..72e40ced5c 100644 --- a/src/build.rs +++ b/src/build.rs @@ -680,6 +680,8 @@ extern "C" fn notify_cb( .unwrap_or(2) } +unsafe impl Send for TreeUpdateBuilder {} + impl Default for TreeUpdateBuilder { fn default() -> Self { Self::new() From 29cbc03dda16d82a2a559d6c29a5f9727ac4b45c Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Wed, 1 Dec 2021 16:15:20 +0100 Subject: [PATCH 603/860] version bump (#781) --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 17808d6623..2f5a415a86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.24" +version = "0.13.25" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.25" } +libgit2-sys = { path = "libgit2-sys", version = "0.12.26" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index bc8889a2ba..dd91e9ff49 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.25+1.3.0" +version = "0.12.26+1.3.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From f37fee7e855d2a8ddca2932972e9f9192f027023 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Mon, 6 Dec 2021 11:18:39 +0530 Subject: [PATCH 604/860] blame: fix typo s/Widnows/Windows/ Signed-off-by: Muhammad Falak R Wani --- src/blame.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blame.rs b/src/blame.rs index e7413dd5f8..496efa9230 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -121,7 +121,7 @@ impl<'blame> BlameHunk<'blame> { /// Returns path to the file where this hunk originated. /// - /// Note: `None` could be returned for non-unicode paths on Widnows. + /// Note: `None` could be returned for non-unicode paths on Windows. pub fn path(&self) -> Option<&Path> { unsafe { if let Some(bytes) = crate::opt_bytes(self, (*self.raw).orig_path) { From 1a001ad00d72a2fa82494905e3aac783f306cc2b Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Sat, 1 Jan 2022 15:28:19 +0100 Subject: [PATCH 605/860] Fix readme: libgit2 version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cabe88eafa..998c5e5fd2 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ stable release as well. ## Version of libgit2 -Currently this library requires libgit2 1.1.0. The source for libgit2 is +Currently this library requires libgit2 1.3.0. The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. From 21f40b0200b751ebacb0ad3754f977abb8d26b6d Mon Sep 17 00:00:00 2001 From: Daniel O'Brien Date: Fri, 21 Jan 2022 17:16:10 +0000 Subject: [PATCH 606/860] Update build.rs (#792) std::path::Path is imported for use towards the bottom of the example. No point in using a fully qualified path --- src/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build.rs b/src/build.rs index 72e40ced5c..5b5cd15a31 100644 --- a/src/build.rs +++ b/src/build.rs @@ -28,7 +28,7 @@ use crate::{CheckoutNotificationType, DiffFile, FileMode, Remote}; /// Cred::ssh_key( /// username_from_url.unwrap(), /// None, -/// std::path::Path::new(&format!("{}/.ssh/id_rsa", env::var("HOME").unwrap())), +/// Path::new(&format!("{}/.ssh/id_rsa", env::var("HOME").unwrap())), /// None, /// ) /// }); From c55bd6dbdba52f90788150180ef124ef6c90daa6 Mon Sep 17 00:00:00 2001 From: Paul Horn Date: Mon, 24 Jan 2022 20:22:15 +0100 Subject: [PATCH 607/860] Add support for custom git extensions (#791) * Add support for custom git extensions This would allow one to use git worktrees together with sparse-checkout. Reference: https://github.com/libgit2/libgit2/pull/6031 * Mark extension methods unsafe * Replace custom spin-lock in tests with serial-test crate * Rewrite tests as integration tests --- libgit2-sys/lib.rs | 4 +++ src/opts.rs | 59 ++++++++++++++++++++++++++++++++++++++ tests/add_extensions.rs | 19 ++++++++++++ tests/get_extensions.rs | 14 +++++++++ tests/remove_extensions.rs | 19 ++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 tests/add_extensions.rs create mode 100644 tests/get_extensions.rs create mode 100644 tests/remove_extensions.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 951397cc2c..bade631b20 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1870,6 +1870,10 @@ git_enum! { GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, GIT_OPT_GET_MWINDOW_FILE_LIMIT, GIT_OPT_SET_MWINDOW_FILE_LIMIT, + GIT_OPT_SET_ODB_PACKED_PRIORITY, + GIT_OPT_SET_ODB_LOOSE_PRIORITY, + GIT_OPT_GET_EXTENSIONS, + GIT_OPT_SET_EXTENSIONS, } } diff --git a/src/opts.rs b/src/opts.rs index 007b272c1b..a89df4e1c9 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -1,7 +1,9 @@ //! Bindings to libgit2's git_libgit2_opts function. use std::ffi::CString; +use std::ptr; +use crate::string_array::StringArray; use crate::util::Binding; use crate::{raw, Buf, ConfigLevel, Error, IntoCString}; @@ -119,6 +121,63 @@ pub fn strict_hash_verification(enabled: bool) { debug_assert!(error >= 0); } +/// Returns the list of git extensions that are supported. This is the list of +/// built-in extensions supported by libgit2 and custom extensions that have +/// been added with [`set_extensions`]. Extensions that have been negated will +/// not be returned. +/// +/// # Safety +/// +/// libgit2 stores user extensions in a static variable. +/// This function is effectively reading a `static mut` and should be treated as such +pub unsafe fn get_extensions() -> Result { + crate::init(); + + let mut extensions = raw::git_strarray { + strings: ptr::null_mut(), + count: 0, + }; + + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_EXTENSIONS as libc::c_int, + &mut extensions + )); + + Ok(StringArray::from_raw(extensions)) +} + +/// Set that the given git extensions are supported by the caller. Extensions +/// supported by libgit2 may be negated by prefixing them with a `!`. +/// For example: setting extensions to `[ "!noop", "newext" ]` indicates that +/// the caller does not want to support repositories with the `noop` extension +/// but does want to support repositories with the `newext` extension. +/// +/// # Safety +/// +/// libgit2 stores user extensions in a static variable. +/// This function is effectively modifying a `static mut` and should be treated as such +pub unsafe fn set_extensions(extensions: &[E]) -> Result<(), Error> +where + for<'x> &'x E: IntoCString, +{ + crate::init(); + + let extensions = extensions + .iter() + .map(|e| e.into_c_string()) + .collect::, _>>()?; + + let extension_ptrs = extensions.iter().map(|e| e.as_ptr()).collect::>(); + + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_EXTENSIONS as libc::c_int, + extension_ptrs.as_ptr(), + extension_ptrs.len() as libc::size_t + )); + + Ok(()) +} + #[cfg(test)] mod test { use super::*; diff --git a/tests/add_extensions.rs b/tests/add_extensions.rs new file mode 100644 index 0000000000..fe37e1eeb7 --- /dev/null +++ b/tests/add_extensions.rs @@ -0,0 +1,19 @@ +//! Test for `set_extensions`, which writes a global state maintained by libgit2 + +use git2::opts::{get_extensions, set_extensions}; +use git2::Error; + +#[test] +fn test_add_extensions() -> Result<(), Error> { + unsafe { + set_extensions(&["custom"])?; + } + + let extensions = unsafe { get_extensions() }?; + + assert_eq!(extensions.len(), 2); + assert_eq!(extensions.get(0), Some("noop")); + assert_eq!(extensions.get(1), Some("custom")); + + Ok(()) +} diff --git a/tests/get_extensions.rs b/tests/get_extensions.rs new file mode 100644 index 0000000000..ac049c6816 --- /dev/null +++ b/tests/get_extensions.rs @@ -0,0 +1,14 @@ +//! Test for `get_extensions`, which reads a global state maintained by libgit2 + +use git2::opts::get_extensions; +use git2::Error; + +#[test] +fn test_get_extensions() -> Result<(), Error> { + let extensions = unsafe { get_extensions() }?; + + assert_eq!(extensions.len(), 1); + assert_eq!(extensions.get(0), Some("noop")); + + Ok(()) +} diff --git a/tests/remove_extensions.rs b/tests/remove_extensions.rs new file mode 100644 index 0000000000..366da7392b --- /dev/null +++ b/tests/remove_extensions.rs @@ -0,0 +1,19 @@ +//! Test for `set_extensions`, which writes a global state maintained by libgit2 + +use git2::opts::{get_extensions, set_extensions}; +use git2::Error; + +#[test] +fn test_remove_extensions() -> Result<(), Error> { + unsafe { + set_extensions(&["custom", "!ignore", "!noop", "other"])?; + } + + let extensions = unsafe { get_extensions() }?; + + assert_eq!(extensions.len(), 2); + assert_eq!(extensions.get(0), Some("custom")); + assert_eq!(extensions.get(1), Some("other")); + + Ok(()) +} From 74fd9609afe39fdd2c7e17878ae16aaeb5bbe2af Mon Sep 17 00:00:00 2001 From: sgasse <47532708+sgasse@users.noreply.github.com> Date: Mon, 7 Feb 2022 01:05:40 +0100 Subject: [PATCH 608/860] Fix typo in DiffFindOptions (#798) Co-authored-by: Simon Gasse --- src/diff.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diff.rs b/src/diff.rs index 39623766e2..0df6f85ea8 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -1452,7 +1452,7 @@ impl DiffFindOptions { self } - /// Similarity of modified to be glegible rename source (default 50) + /// Similarity of modified to be eligible rename source (default 50) pub fn rename_from_rewrite_threshold(&mut self, thresh: u16) -> &mut DiffFindOptions { self.raw.rename_from_rewrite_threshold = thresh; self From ae02afdbf0a8ab352aad9f18c726a70a1e7ecf0b Mon Sep 17 00:00:00 2001 From: sgasse <47532708+sgasse@users.noreply.github.com> Date: Mon, 7 Feb 2022 16:38:44 +0100 Subject: [PATCH 609/860] Harmonize commitish and committish in docstrings (#799) The git glossary mentions both verions. However in-code, only the first variant is used. This commit harmonizes the usages: https://git-scm.com/docs/gitglossary#Documentation/ gitglossary.txt-aiddefcommit-ishacommit-ishalsocommittish Co-authored-by: Simon Gasse --- src/repo.rs | 4 ++-- src/revwalk.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index f2cc541604..92fa948305 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -811,7 +811,7 @@ impl Repository { /// Make the repository HEAD directly point to the commit. /// - /// If the provided committish cannot be found in the repository, the HEAD + /// If the provided commitish cannot be found in the repository, the HEAD /// is unaltered and an error is returned. /// /// If the provided commitish cannot be peeled into a commit, the HEAD is @@ -831,7 +831,7 @@ impl Repository { /// Make the repository HEAD directly point to the commit. /// - /// If the provided committish cannot be found in the repository, the HEAD + /// If the provided commitish cannot be found in the repository, the HEAD /// is unaltered and an error is returned. /// If the provided commitish cannot be peeled into a commit, the HEAD is /// unaltered and an error is returned. diff --git a/src/revwalk.rs b/src/revwalk.rs index 0cf4aa1253..eec940f4b9 100644 --- a/src/revwalk.rs +++ b/src/revwalk.rs @@ -81,7 +81,7 @@ impl<'repo> Revwalk<'repo> { /// Mark a commit to start traversal from. /// - /// The given OID must belong to a committish on the walked repository. + /// The given OID must belong to a commitish on the walked repository. /// /// The given commit will be used as one of the roots when starting the /// revision walk. At least one commit must be pushed onto the walker before @@ -111,7 +111,7 @@ impl<'repo> Revwalk<'repo> { /// A leading 'refs/' is implied if not present as well as a trailing `/ \ /// *` if the glob lacks '?', ' \ *' or '['. /// - /// Any references matching this glob which do not point to a committish + /// Any references matching this glob which do not point to a commitish /// will be ignored. pub fn push_glob(&mut self, glob: &str) -> Result<(), Error> { let glob = CString::new(glob)?; @@ -136,7 +136,7 @@ impl<'repo> Revwalk<'repo> { /// Push the OID pointed to by a reference /// - /// The reference must point to a committish. + /// The reference must point to a commitish. pub fn push_ref(&mut self, reference: &str) -> Result<(), Error> { let reference = CString::new(reference)?; unsafe { @@ -194,7 +194,7 @@ impl<'repo> Revwalk<'repo> { /// A leading 'refs/' is implied if not present as well as a trailing `/ \ /// *` if the glob lacks '?', ' \ *' or '['. /// - /// Any references matching this glob which do not point to a committish + /// Any references matching this glob which do not point to a commitish /// will be ignored. pub fn hide_glob(&mut self, glob: &str) -> Result<(), Error> { let glob = CString::new(glob)?; @@ -206,7 +206,7 @@ impl<'repo> Revwalk<'repo> { /// Hide the OID pointed to by a reference. /// - /// The reference must point to a committish. + /// The reference must point to a commitish. pub fn hide_ref(&mut self, reference: &str) -> Result<(), Error> { let reference = CString::new(reference)?; unsafe { From 58ed9c32e1dff518c0d408f1fc08b543f35b1bd7 Mon Sep 17 00:00:00 2001 From: "Kirill A. Korinsky" Date: Mon, 7 Feb 2022 16:39:41 +0100 Subject: [PATCH 610/860] `libgit2-sys`: use `src` instead `.git` as vendored indicator (#801) When someone vendored `libgit2-sys` he may exclude `.git` folder. When such things happened an attempt to build it may lead to error like: `fatal: not a git repository (or any of the parent directories): .git`. The only way to fix it is using system's `libgit2` which may lead to `invalid version 0 on git_proxy_options; class=Invalid (3)` at some cases. --- libgit2-sys/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 0046afafca..41b6041721 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -24,7 +24,7 @@ fn main() { println!("cargo:rustc-cfg=libgit2_vendored"); - if !Path::new("libgit2/.git").exists() { + if !Path::new("libgit2/src").exists() { let _ = Command::new("git") .args(&["submodule", "update", "--init", "libgit2"]) .status(); From 509fe5832ea35f6a670333da9e98ba5571419318 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 15 Feb 2022 07:45:51 -0800 Subject: [PATCH 611/860] Bump libgit2 to 1.4.0 (#806) * Bump libgit2 to 1.4.0 * Libgit2 1.4.0 fixes --- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/lib.rs | 85 +++++++++++++++++++++++++----------------- libgit2-sys/libgit2 | 2 +- src/buf.rs | 2 +- src/index.rs | 3 -- src/lib.rs | 2 +- src/packbuilder.rs | 28 +++++++++++++- src/remote.rs | 57 ++++++++++++++++++++++++++++ src/status.rs | 8 ++++ 9 files changed, 147 insertions(+), 42 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index dd91e9ff49..fab3dbf868 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.26+1.3.0" +version = "0.12.26+1.4.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index bade631b20..760e966f90 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -383,6 +383,7 @@ pub struct git_fetch_options { pub update_fetchhead: c_int, pub download_tags: git_remote_autotag_option_t, pub proxy_opts: git_proxy_options, + pub follow_redirects: git_remote_redirect_t, pub custom_headers: git_strarray, } @@ -609,6 +610,7 @@ pub struct git_status_options { pub flags: c_uint, pub pathspec: git_strarray, pub baseline: *mut git_tree, + pub rename_threshold: u16, } #[repr(C)] @@ -728,7 +730,7 @@ pub struct git_tree_update { #[derive(Copy, Clone)] pub struct git_buf { pub ptr: *mut c_char, - pub asize: size_t, + pub reserved: size_t, pub size: size_t, } @@ -951,6 +953,7 @@ pub struct git_push_options { pub pb_parallelism: c_uint, pub callbacks: git_remote_callbacks, pub proxy_opts: git_proxy_options, + pub follow_redirects: git_remote_redirect_t, pub custom_headers: git_strarray, } @@ -1356,55 +1359,66 @@ pub type git_transport_cb = Option< #[repr(C)] pub struct git_transport { pub version: c_uint, - pub set_callbacks: Option< + pub connect: Option< extern "C" fn( - *mut git_transport, - git_transport_message_cb, - git_transport_message_cb, - git_transport_certificate_check_cb, - *mut c_void, + transport: *mut git_transport, + url: *const c_char, + direction: c_int, + connect_opts: *const git_remote_connect_options, ) -> c_int, >, - pub set_custom_headers: Option c_int>, - pub connect: Option< + pub set_connect_opts: Option< extern "C" fn( - *mut git_transport, - *const c_char, - git_cred_acquire_cb, - *mut c_void, - *const git_proxy_options, - c_int, - c_int, + transport: *mut git_transport, + connect_opts: *const git_remote_connect_options, ) -> c_int, >, + pub capabilities: + Option c_int>, pub ls: Option< - extern "C" fn(*mut *mut *const git_remote_head, *mut size_t, *mut git_transport) -> c_int, - >, - pub push: Option< - extern "C" fn(*mut git_transport, *mut git_push, *const git_remote_callbacks) -> c_int, + extern "C" fn( + out: *mut *mut *const git_remote_head, + size: *mut size_t, + transport: *mut git_transport, + ) -> c_int, >, + pub push: Option c_int>, pub negotiate_fetch: Option< extern "C" fn( - *mut git_transport, - *mut git_repository, - *const *const git_remote_head, - size_t, + transport: *mut git_transport, + repo: *mut git_repository, + refs: *const *const git_remote_head, + count: size_t, ) -> c_int, >, pub download_pack: Option< extern "C" fn( - *mut git_transport, - *mut git_repository, - *mut git_indexer_progress, - git_indexer_progress_cb, - *mut c_void, + transport: *mut git_transport, + repo: *mut git_repository, + stats: *mut git_indexer_progress, ) -> c_int, >, - pub is_connected: Option c_int>, - pub read_flags: Option c_int>, - pub cancel: Option, - pub close: Option c_int>, - pub free: Option, + pub is_connected: Option c_int>, + pub cancel: Option, + pub close: Option c_int>, + pub free: Option, +} + +#[repr(C)] +pub struct git_remote_connect_options { + pub version: c_uint, + pub callbacks: git_remote_callbacks, + pub proxy_opts: git_proxy_options, + pub follow_redirects: git_remote_redirect_t, + pub custom_headers: git_strarray, +} + +git_enum! { + pub enum git_remote_redirect_t { + GIT_REMOTE_REDIRECT_NONE = 1 << 0, + GIT_REMOTE_REDIRECT_INITIAL = 1 << 1, + GIT_REMOTE_REDIRECT_ALL = 1 << 2, + } } #[repr(C)] @@ -1891,6 +1905,7 @@ pub struct git_worktree_add_options { pub version: c_uint, pub lock: c_int, pub reference: *mut git_reference, + pub checkout_options: git_checkout_options, } pub const GIT_WORKTREE_ADD_OPTIONS_VERSION: c_uint = 1; @@ -3727,7 +3742,9 @@ extern "C" { progress_cb: git_indexer_progress_cb, progress_cb_payload: *mut c_void, ) -> c_int; + #[deprecated = "use `git_packbuilder_name` to retrieve the filename"] pub fn git_packbuilder_hash(pb: *mut git_packbuilder) -> *const git_oid; + pub fn git_packbuilder_name(pb: *mut git_packbuilder) -> *const c_char; pub fn git_packbuilder_foreach( pb: *mut git_packbuilder, cb: git_packbuilder_foreach_cb, diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index b7bad55e4b..1d5b9bd86d 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit b7bad55e4bb0a285b073ba5e02b01d3f522fc95d +Subproject commit 1d5b9bd86dccc7347aaadf5e3ab122eed9413404 diff --git a/src/buf.rs b/src/buf.rs index 0ab560ce80..fd2bcbf96f 100644 --- a/src/buf.rs +++ b/src/buf.rs @@ -28,7 +28,7 @@ impl Buf { Binding::from_raw(&mut raw::git_buf { ptr: ptr::null_mut(), size: 0, - asize: 0, + reserved: 0, } as *mut _) } } diff --git a/src/index.rs b/src/index.rs index 22334d0c19..b2e8dfe5c1 100644 --- a/src/index.rs +++ b/src/index.rs @@ -849,9 +849,6 @@ mod tests { #[test] fn add_then_read() { - let mut index = Index::new().unwrap(); - assert!(index.add(&entry()).is_err()); - let mut index = Index::new().unwrap(); let mut e = entry(); e.path = b"foobar".to_vec(); diff --git a/src/lib.rs b/src/lib.rs index b7f262e94c..1ba08d21de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -120,7 +120,7 @@ pub use crate::reference::{Reference, ReferenceNames, References}; pub use crate::reflog::{Reflog, ReflogEntry, ReflogIter}; pub use crate::refspec::Refspec; pub use crate::remote::{ - FetchOptions, PushOptions, Refspecs, Remote, RemoteConnection, RemoteHead, + FetchOptions, PushOptions, Refspecs, Remote, RemoteConnection, RemoteHead, RemoteRedirect, }; pub use crate::remote_callbacks::{Credentials, RemoteCallbacks}; pub use crate::remote_callbacks::{TransportMessage, UpdateTips}; diff --git a/src/packbuilder.rs b/src/packbuilder.rs index e20bf2a97c..9b93e7654b 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -2,6 +2,7 @@ use libc::{c_int, c_uint, c_void, size_t}; use std::marker; use std::ptr; use std::slice; +use std::str; use crate::util::Binding; use crate::{panic, raw, Buf, Error, Oid, Repository, Revwalk}; @@ -160,6 +161,8 @@ impl<'repo> PackBuilder<'repo> { /// Get the packfile's hash. A packfile's name is derived from the sorted /// hashing of all object names. This is only correct after the packfile /// has been written. + #[deprecated = "use `name()` to retrieve the filename"] + #[allow(deprecated)] pub fn hash(&self) -> Option { if self.object_count() == 0 { unsafe { Some(Binding::from_raw(raw::git_packbuilder_hash(self.raw))) } @@ -167,6 +170,25 @@ impl<'repo> PackBuilder<'repo> { None } } + + /// Get the unique name for the resulting packfile. + /// + /// The packfile's name is derived from the packfile's content. This is only + /// correct after the packfile has been written. + /// + /// Returns `None` if the packfile has not been written or if the name is + /// not valid utf-8. + pub fn name(&self) -> Option<&str> { + self.name_bytes().and_then(|s| str::from_utf8(s).ok()) + } + + /// Get the unique name for the resulting packfile, in bytes. + /// + /// The packfile's name is derived from the packfile's content. This is only + /// correct after the packfile has been written. + pub fn name_bytes(&self) -> Option<&[u8]> { + unsafe { crate::opt_bytes(self, raw::git_packbuilder_name(self.raw)) } + } } impl<'repo> Binding for PackBuilder<'repo> { @@ -284,7 +306,11 @@ mod tests { let mut builder = t!(repo.packbuilder()); let mut buf = Buf::new(); t!(builder.write_buf(&mut buf)); - assert!(builder.hash().unwrap().is_zero()); + #[allow(deprecated)] + { + assert!(builder.hash().unwrap().is_zero()); + } + assert!(builder.name().is_none()); assert_eq!(&*buf, &*empty_pack_header()); } diff --git a/src/remote.rs b/src/remote.rs index b1cc4d3693..59afa1363a 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -44,6 +44,7 @@ pub struct FetchOptions<'cb> { prune: FetchPrune, update_fetchhead: bool, download_tags: AutotagOption, + follow_redirects: RemoteRedirect, custom_headers: Vec, custom_headers_ptrs: Vec<*const c_char>, } @@ -53,6 +54,7 @@ pub struct PushOptions<'cb> { callbacks: Option>, proxy: Option>, pb_parallelism: u32, + follow_redirects: RemoteRedirect, custom_headers: Vec, custom_headers_ptrs: Vec<*const c_char>, } @@ -64,6 +66,21 @@ pub struct RemoteConnection<'repo, 'connection, 'cb> { remote: &'connection mut Remote<'repo>, } +/// Remote redirection settings; whether redirects to another host are +/// permitted. +/// +/// By default, git will follow a redirect on the initial request +/// (`/info/refs`), but not subsequent requests. +pub enum RemoteRedirect { + /// Do not follow any off-site redirects at any stage of the fetch or push. + None, + /// Allow off-site redirects only upon the initial request. This is the + /// default. + Initial, + /// Allow redirects at any stage in the fetch or push. + All, +} + pub fn remote_into_raw(remote: Remote<'_>) -> *mut raw::git_remote { let ret = remote.raw; mem::forget(remote); @@ -479,6 +496,7 @@ impl<'cb> FetchOptions<'cb> { prune: FetchPrune::Unspecified, update_fetchhead: true, download_tags: AutotagOption::Unspecified, + follow_redirects: RemoteRedirect::Initial, custom_headers: Vec::new(), custom_headers_ptrs: Vec::new(), } @@ -519,6 +537,16 @@ impl<'cb> FetchOptions<'cb> { self } + /// Set remote redirection settings; whether redirects to another host are + /// permitted. + /// + /// By default, git will follow a redirect on the initial request + /// (`/info/refs`), but not subsequent requests. + pub fn follow_redirects(&mut self, redirect: RemoteRedirect) -> &mut Self { + self.follow_redirects = redirect; + self + } + /// Set extra headers for this fetch operation. pub fn custom_headers(&mut self, custom_headers: &[&str]) -> &mut Self { self.custom_headers = custom_headers @@ -552,6 +580,7 @@ impl<'cb> Binding for FetchOptions<'cb> { prune: crate::call::convert(&self.prune), update_fetchhead: crate::call::convert(&self.update_fetchhead), download_tags: crate::call::convert(&self.download_tags), + follow_redirects: self.follow_redirects.raw(), custom_headers: git_strarray { count: self.custom_headers_ptrs.len(), strings: self.custom_headers_ptrs.as_ptr() as *mut _, @@ -573,6 +602,7 @@ impl<'cb> PushOptions<'cb> { callbacks: None, proxy: None, pb_parallelism: 1, + follow_redirects: RemoteRedirect::Initial, custom_headers: Vec::new(), custom_headers_ptrs: Vec::new(), } @@ -601,6 +631,16 @@ impl<'cb> PushOptions<'cb> { self } + /// Set remote redirection settings; whether redirects to another host are + /// permitted. + /// + /// By default, git will follow a redirect on the initial request + /// (`/info/refs`), but not subsequent requests. + pub fn follow_redirects(&mut self, redirect: RemoteRedirect) -> &mut Self { + self.follow_redirects = redirect; + self + } + /// Set extra headers for this push operation. pub fn custom_headers(&mut self, custom_headers: &[&str]) -> &mut Self { self.custom_headers = custom_headers @@ -632,6 +672,7 @@ impl<'cb> Binding for PushOptions<'cb> { .map(|m| m.raw()) .unwrap_or_else(|| ProxyOptions::new().raw()), pb_parallelism: self.pb_parallelism as libc::c_uint, + follow_redirects: self.follow_redirects.raw(), custom_headers: git_strarray { count: self.custom_headers_ptrs.len(), strings: self.custom_headers_ptrs.as_ptr() as *mut _, @@ -674,6 +715,22 @@ impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb> } } +impl Default for RemoteRedirect { + fn default() -> Self { + RemoteRedirect::Initial + } +} + +impl RemoteRedirect { + fn raw(&self) -> raw::git_remote_redirect_t { + match self { + RemoteRedirect::None => raw::GIT_REMOTE_REDIRECT_NONE, + RemoteRedirect::Initial => raw::GIT_REMOTE_REDIRECT_INITIAL, + RemoteRedirect::All => raw::GIT_REMOTE_REDIRECT_ALL, + } + } +} + #[cfg(test)] mod tests { use crate::{AutotagOption, PushOptions}; diff --git a/src/status.rs b/src/status.rs index d843458589..d9bfc07342 100644 --- a/src/status.rs +++ b/src/status.rs @@ -216,6 +216,14 @@ impl StatusOptions { self.flag(raw::GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED, include) } + /// Set threshold above which similar files will be considered renames. + /// + /// This is equivalent to the `-M` option. Defaults to 50. + pub fn rename_threshold(&mut self, threshold: u16) -> &mut StatusOptions { + self.raw.rename_threshold = threshold; + self + } + /// Get a pointer to the inner list of status options. /// /// This function is unsafe as the returned structure has interior pointers From af6fc41c2918c07d2c898c5630b552c2525c9951 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 15 Feb 2022 10:35:39 -0800 Subject: [PATCH 612/860] Bump libgit2 in version probe and readme (#808) --- README.md | 2 +- libgit2-sys/build.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 998c5e5fd2..6ee6c3c179 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ stable release as well. ## Version of libgit2 -Currently this library requires libgit2 1.3.0. The source for libgit2 is +Currently this library requires libgit2 1.4.0. The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 41b6041721..2752a5bc97 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,7 +14,7 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.atleast_version("1.3.0").probe("libgit2") { + if let Ok(lib) = cfg.atleast_version("1.4.0").probe("libgit2") { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } From 64d849b8436a6b77a2636693a7523b5cac9cd993 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 24 Feb 2022 07:14:37 -0800 Subject: [PATCH 613/860] Update to 1.4.1 (#811) --- CONTRIBUTING.md | 34 ++++++++++++++++++++++++++++++++++ Cargo.toml | 4 ++-- README.md | 2 +- git2-curl/Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/lib.rs | 2 +- libgit2-sys/libgit2 | 2 +- src/lib.rs | 2 +- 8 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..ceb1de44ce --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,34 @@ +# Contributing + +## Updating libgit2 + +The following steps can be used to update libgit2: + +1. Update the submodule. + There are several ways to go about this. + One way is to go to the `libgit2-sys/libgit2` directory and run `git fetch origin` to download the latest updates, and then check out a specific tag (such as `git checkout v1.4.1`). +2. Update all the references to the version: + * Update [`libgit2-sys/build.rs`](https://github.com/rust-lang/git2-rs/blob/master/libgit2-sys/build.rs). + There is a version probe (search for `cfg.atleast_version`) which should be updated. + * Update the version in + [`libgit2-sys/Cargo.toml`](https://github.com/rust-lang/git2-rs/blob/master/libgit2-sys/Cargo.toml). + Update the metadata portion (the part after the `+`) to match libgit2. + Also bump the Cargo version (the part before the `+`), keeping in mind + if this will be a SemVer breaking change or not. + * Update the dependency version in [`Cargo.toml`](https://github.com/rust-lang/git2-rs/blob/master/Cargo.toml) to match the version in the last step (do not include the `+` metadata). + Also update the version of the `git2` crate itself so it will pick up the change to `libgit2-sys` (also keeping in mind if it is a SemVer breaking release). + * Update the version in [`README.md`](https://github.com/rust-lang/git2-rs/blob/master/README.md) if needed. + * If there was a SemVer-breaking version bump for either library, also update the `html_root_url` attribute in the `lib.rs` of each library. +3. Run tests. + `cargo test -p git2 -p git2-curl` is a good starting point. +4. Run `systest`. + This will validate for any C-level API problems. + Unfortunately `systest` does not work on nightly, so you'll need to use stable. + + `cargo +stable run -p systest` + + The changelog at + can be helpful for seeing what has changed. + The project has recently started labeling API and ABI breaking changes with labels: + +4. Once you have everything functional, publish a PR with the updates. diff --git a/Cargo.toml b/Cargo.toml index 2f5a415a86..a29bdee5f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.13.25" +version = "0.14.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.12.26" } +libgit2-sys = { path = "libgit2-sys", version = "0.13.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/README.md b/README.md index 6ee6c3c179..b4ea1819eb 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ stable release as well. ## Version of libgit2 -Currently this library requires libgit2 1.4.0. The source for libgit2 is +Currently this library requires libgit2 1.4. The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 6b68488e3d..e85de4cde4 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -16,7 +16,7 @@ edition = "2018" curl = "0.4.33" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.13", default-features = false } +git2 = { path = "..", version = "0.14", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index fab3dbf868..68fc36a4be 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.12.26+1.4.0" +version = "0.13.0+1.4.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 760e966f90..d23c3ec4ff 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.12")] +#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.13")] #![allow(non_camel_case_types, unused_extern_crates)] // This is required to link libz when libssh2-sys is not included. diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 1d5b9bd86d..fdd15bcfca 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 1d5b9bd86dccc7347aaadf5e3ab122eed9413404 +Subproject commit fdd15bcfca6b2ec4b7ecad1aa11a396cb15bd064 diff --git a/src/lib.rs b/src/lib.rs index 1ba08d21de..60cfc3e071 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.13")] +#![doc(html_root_url = "https://docs.rs/git2/0.14")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] From ce54dacf986e4ce309f1d982987621f496c40c62 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 26 Feb 2022 14:44:38 +0800 Subject: [PATCH 614/860] Bump version of git2-curl --- git2-curl/Cargo.toml | 2 +- git2-curl/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index e85de4cde4..22eb343457 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2-curl" -version = "0.14.1" +version = "0.15.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 8f59bceb59..e8c2aac9d8 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -15,7 +15,7 @@ //! > **NOTE**: At this time this crate likely does not support a `git push` //! > operation, only clones. -#![doc(html_root_url = "https://docs.rs/git2-curl/0.14")] +#![doc(html_root_url = "https://docs.rs/git2-curl/0.15")] #![deny(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] From d703dd940f1302227a9efb6672dbdbf34f4cb0bc Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 28 Feb 2022 06:33:37 -0800 Subject: [PATCH 615/860] Update to 1.4.2 (#815) --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/libgit2 | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a29bdee5f2..f1c5f8674b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.14.0" +version = "0.14.1" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.13.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.13.1" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 68fc36a4be..844d14f7e2 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.13.0+1.4.1" +version = "0.13.1+1.4.2" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index fdd15bcfca..182d0d1ee9 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit fdd15bcfca6b2ec4b7ecad1aa11a396cb15bd064 +Subproject commit 182d0d1ee933de46bf0b5a6ec269bafa77aba9a2 From 871788d261f60b3b319f1d0d8a450b1cfc70c667 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 7 Mar 2022 08:04:20 -0800 Subject: [PATCH 616/860] Add binding for git_odb_exists_ext (#818) This allows checking for the existence of an object without refreshing the ODB if the lookup fails. Useful when doing a batch of lookup operations for objects that may legitimately not exist. --- libgit2-sys/lib.rs | 7 +++++++ src/lib.rs | 11 +++++++++++ src/odb.rs | 11 +++++++++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index d23c3ec4ff..195f1371e2 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1511,6 +1511,12 @@ pub struct git_odb_backend { pub free: Option, } +git_enum! { + pub enum git_odb_lookup_flags_t { + GIT_ODB_LOOKUP_NO_REFRESH = 1 << 0, + } +} + #[repr(C)] pub struct git_odb_writepack { pub backend: *mut git_odb_backend, @@ -3836,6 +3842,7 @@ extern "C" { ) -> c_int; pub fn git_odb_exists(odb: *mut git_odb, oid: *const git_oid) -> c_int; + pub fn git_odb_exists_ext(odb: *mut git_odb, oid: *const git_oid, flags: c_uint) -> c_int; pub fn git_odb_refresh(odb: *mut git_odb) -> c_int; diff --git a/src/lib.rs b/src/lib.rs index 60cfc3e071..cdc3648d83 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -637,6 +637,17 @@ impl MergePreference { is_bit_set!(is_fastforward_only, MergePreference::FASTFORWARD_ONLY); } +bitflags! { + /// Flags controlling the behavior of ODB lookup operations + pub struct OdbLookupFlags: u32 { + /// Don't call `git_odb_refresh` if the lookup fails. Useful when doing + /// a batch of lookup operations for objects that may legitimately not + /// exist. When using this flag, you may wish to manually call + /// `git_odb_refresh` before processing a batch of objects. + const NO_REFRESH = raw::GIT_ODB_LOOKUP_NO_REFRESH as u32; + } +} + #[cfg(test)] #[macro_use] mod test; diff --git a/src/odb.rs b/src/odb.rs index 12f0707fa5..f64a52c7e4 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -6,11 +6,13 @@ use std::slice; use std::ffi::CString; -use libc::{c_char, c_int, c_void, size_t}; +use libc::{c_char, c_int, c_uint, c_void, size_t}; use crate::panic; use crate::util::Binding; -use crate::{raw, Error, IndexerProgress, Mempack, Object, ObjectType, Oid, Progress}; +use crate::{ + raw, Error, IndexerProgress, Mempack, Object, ObjectType, OdbLookupFlags, Oid, Progress, +}; /// A structure to represent a git object database pub struct Odb<'repo> { @@ -186,6 +188,11 @@ impl<'repo> Odb<'repo> { unsafe { raw::git_odb_exists(self.raw, oid.raw()) != 0 } } + /// Checks if the object database has an object, with extended flags. + pub fn exists_ext(&self, oid: Oid, flags: OdbLookupFlags) -> bool { + unsafe { raw::git_odb_exists_ext(self.raw, oid.raw(), flags.bits() as c_uint) != 0 } + } + /// Potentially finds an object that starts with the given prefix. pub fn exists_prefix(&self, short_oid: Oid, len: usize) -> Result { unsafe { From 0443adb5388b2a529c042256e7716c36dc567220 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 10 Mar 2022 11:03:46 -0600 Subject: [PATCH 617/860] Bump libgit2-sys to 0.13.2 (#820) * Bump libgit2-sys to 0.13.2 * Bump git2 to 0.14.2 --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f1c5f8674b..b51524c391 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.14.1" +version = "0.14.2" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.13.1" } +libgit2-sys = { path = "libgit2-sys", version = "0.13.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 844d14f7e2..8e99666407 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.13.1+1.4.2" +version = "0.13.2+1.4.2" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From b9cbb445e0e08deb990c9bf605b0b0c45e9b462f Mon Sep 17 00:00:00 2001 From: Wilhelm Bierbaum Date: Wed, 16 Mar 2022 13:58:09 -0700 Subject: [PATCH 618/860] Support for building refactored libgit2 sources when using the vendored libgit2 (#822) Since https://github.com/libgit2/libgit2/commit/3a3ab065f0685202c854e13708ddfd2a93d75e2c libgit2 is refactored into a library and CLI. This change allows git2-rs to build those sources when the copy is used. This should not be integrated until a libgit2 release is made incorporating those sources. The libgit2 submodule has been updated at the current commit on libgit2's `main` branch. --- libgit2-sys/build.rs | 32 +++++++++++++++++++------------- libgit2-sys/libgit2 | 2 +- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 2752a5bc97..0ef3021c15 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -41,19 +41,21 @@ fn main() { cp_r("libgit2/include", &include); cfg.include(&include) - .include("libgit2/src") + .include("libgit2/src/libgit2") + .include("libgit2/src/util") .out_dir(dst.join("build")) .warnings(false); // Include all cross-platform C files - add_c_files(&mut cfg, "libgit2/src"); - add_c_files(&mut cfg, "libgit2/src/xdiff"); + add_c_files(&mut cfg, "libgit2/src/libgit2"); + add_c_files(&mut cfg, "libgit2/src/util"); + add_c_files(&mut cfg, "libgit2/src/libgit2/xdiff"); // These are activated by features, but they're all unconditionally always // compiled apparently and have internal #define's to make sure they're // compiled correctly. - add_c_files(&mut cfg, "libgit2/src/transports"); - add_c_files(&mut cfg, "libgit2/src/streams"); + add_c_files(&mut cfg, "libgit2/src/libgit2/transports"); + add_c_files(&mut cfg, "libgit2/src/libgit2/streams"); // Always use bundled http-parser for now cfg.include("libgit2/deps/http-parser") @@ -82,11 +84,11 @@ fn main() { // when when COMPILE_PCRE8 is not defined, which is the default. add_c_files(&mut cfg, "libgit2/deps/pcre"); - cfg.file("libgit2/src/allocators/failalloc.c"); - cfg.file("libgit2/src/allocators/stdalloc.c"); + cfg.file("libgit2/src/util/allocators/failalloc.c"); + cfg.file("libgit2/src/util/allocators/stdalloc.c"); if windows { - add_c_files(&mut cfg, "libgit2/src/win32"); + add_c_files(&mut cfg, "libgit2/src/util/win32"); cfg.define("STRSAFE_NO_DEPRECATE", None); cfg.define("WIN32", None); cfg.define("_WIN32_WINNT", Some("0x0600")); @@ -98,7 +100,7 @@ fn main() { cfg.define("__USE_MINGW_ANSI_STDIO", "1"); } } else { - add_c_files(&mut cfg, "libgit2/src/unix"); + add_c_files(&mut cfg, "libgit2/src/util/unix"); cfg.flag("-fvisibility=hidden"); } if target.contains("solaris") || target.contains("illumos") { @@ -156,9 +158,9 @@ fn main() { cfg.define("SHA1DC_NO_STANDARD_INCLUDES", "1"); cfg.define("SHA1DC_CUSTOM_INCLUDE_SHA1_C", "\"common.h\""); cfg.define("SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C", "\"common.h\""); - cfg.file("libgit2/src/hash/sha1/collisiondetect.c"); - cfg.file("libgit2/src/hash/sha1/sha1dc/sha1.c"); - cfg.file("libgit2/src/hash/sha1/sha1dc/ubc_check.c"); + cfg.file("libgit2/src/util/hash/sha1/collisiondetect.c"); + cfg.file("libgit2/src/util/hash/sha1/sha1dc/sha1.c"); + cfg.file("libgit2/src/util/hash/sha1/sha1dc/ubc_check.c"); if let Some(path) = env::var_os("DEP_Z_INCLUDE") { cfg.include(path); @@ -210,8 +212,12 @@ fn cp_r(from: impl AsRef, to: impl AsRef) { } fn add_c_files(build: &mut cc::Build, path: impl AsRef) { + let path = path.as_ref(); + if !path.exists() { + panic!("Path {} does not exist", path.display()); + } // sort the C files to ensure a deterministic build for reproducible builds - let dir = path.as_ref().read_dir().unwrap(); + let dir = path.read_dir().unwrap(); let mut paths = dir.collect::>>().unwrap(); paths.sort_by_key(|e| e.path()); diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 182d0d1ee9..2a0d0bd19b 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 182d0d1ee933de46bf0b5a6ec269bafa77aba9a2 +Subproject commit 2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7 From 86721d1ab0724138ceea2315f1fe481d11f521c0 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 3 Mar 2022 21:31:22 -0500 Subject: [PATCH 619/860] Respect libgit2's ABI instability libgit2 does not have a stable ABI across minor versions, as has been demonstrated in the last few minor releases, see #813 and #746. This pain is primarily suffered by users of rolling release distros, because they tend to get a new libgit2 version before the authors of libraries release versions that pull in the new libgit2-sys version which works with the new binary. This patch means that going forward, users don't need to rush to upgrade their version of libgit2-sys or suffer errors/UB in the meantime. If the system version changes, they will just start using the vendored version which has been tested against the bindings. --- libgit2-sys/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 0ef3021c15..cb30721e2b 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,7 +14,7 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.atleast_version("1.4.0").probe("libgit2") { + if let Ok(lib) = cfg.range_version("1.4.0".."1.5.0").probe("libgit2") { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } From 5c410259a5eb69787bd3a6343ffbeed68690b9b0 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Wed, 23 Mar 2022 22:23:55 +0800 Subject: [PATCH 620/860] Correct the lifetime of detached repo (#825) --- src/remote.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remote.rs b/src/remote.rs index 59afa1363a..831e108790 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -101,7 +101,7 @@ impl<'repo> Remote<'repo> { /// when you have a URL instead of a remote's name. /// Contrasted with an anonymous remote, a detached remote will not /// consider any repo configuration values. - pub fn create_detached(url: &str) -> Result, Error> { + pub fn create_detached>>(url: S) -> Result, Error> { crate::init(); let mut ret = ptr::null_mut(); let url = CString::new(url)?; From f269dc4739f7f4e15ed124ca3cd17f4de9a1bfa7 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 28 Mar 2022 18:35:17 -0700 Subject: [PATCH 621/860] Update version in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b4ea1819eb..36a68ad3a3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust ```toml [dependencies] -git2 = "0.13" +git2 = "0.14" ``` ## Rust version requirements From 3bc26404467d1abff04020d7ad111da767d61c76 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 13 Apr 2022 09:44:04 -0700 Subject: [PATCH 622/860] Don't let pkg-config add system lib dirs to the search path In its default configuration, pkg-config adds system-wide library directories to the linker search path (rust-lang/pkg-config-rs#11). This causes these directories to be searched before other paths added by later crates or by -Clink-arg in rustflags. If a library is present in the system-wide directory and a later build step wants to specifically link against a different version of that library in another path, the linker will choose the library from the first search directory it finds. If the linker doesn't find a library in any of the specified search directories, it falls back on system-wide paths, so we don't need to print the path we found libssh2 in if it is in one of those system paths. See rust-lang/libz-sys#50 for the same fix to libz that landed a while back. See also alexcrichton/curl-rust#441 for the same fix to libcurl-sys. --- libgit2-sys/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index cb30721e2b..26e3026cb2 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,7 +14,7 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.range_version("1.4.0".."1.5.0").probe("libgit2") { + if let Ok(lib) = cfg.range_version("1.4.0".."1.5.0").print_system_libs(false).probe("libgit2") { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } From 4d104dd80980786147da8dc1a018a7ebb2029a51 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 13 Apr 2022 09:45:49 -0700 Subject: [PATCH 623/860] rustfmt --- libgit2-sys/build.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 26e3026cb2..ef0468b40e 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,7 +14,11 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.range_version("1.4.0".."1.5.0").print_system_libs(false).probe("libgit2") { + if let Ok(lib) = cfg + .range_version("1.4.0".."1.5.0") + .print_system_libs(false) + .probe("libgit2") + { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } From 71a24667344eed2da862a62721d6e284c98bd2e7 Mon Sep 17 00:00:00 2001 From: David Hotham Date: Sat, 12 Feb 2022 00:39:57 +0000 Subject: [PATCH 624/860] clarify license --- Cargo.toml | 2 +- git2-curl/Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b51524c391..d0aaf8677d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "git2" version = "0.14.2" authors = ["Josh Triplett ", "Alex Crichton "] -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" readme = "README.md" keywords = ["git"] repository = "https://github.com/rust-lang/git2-rs" diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 22eb343457..a52bc21cfe 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -2,7 +2,7 @@ name = "git2-curl" version = "0.15.0" authors = ["Josh Triplett ", "Alex Crichton "] -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" documentation = "https://docs.rs/git2-curl" description = """ diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 8e99666407..9e7b0ca8a2 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Josh Triplett ", "Alex Crichton Date: Wed, 27 Apr 2022 07:17:26 -0700 Subject: [PATCH 625/860] Update Readme (#834) --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 36a68ad3a3..1168099e6d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [Documentation](https://docs.rs/git2) -libgit2 bindings for Rust +libgit2 bindings for Rust. ```toml [dependencies] @@ -37,23 +37,22 @@ pre-commit hook found [here][pre-commit-hook] and place it into the `.git/hooks/` with the name `pre-commit`. You may need to add execution permissions with `chmod +x`. - To skip tests on a simple commit or doc-fixes, use `git commit --no-verify`. -## Building on OSX 10.10+ +## Building on macOS 10.10+ If the `ssh` feature is enabled (and it is by default) then this library depends on libssh2 which depends on OpenSSL. To get OpenSSL working follow the -[`openssl` crate's instructions](https://github.com/sfackler/rust-openssl#macos). +[`openssl` crate's instructions](https://github.com/sfackler/rust-openssl/blob/master/openssl/src/lib.rs#L31). # License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or - http://www.apache.org/licenses/LICENSE-2.0) + https://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or - http://opensource.org/licenses/MIT) + https://opensource.org/licenses/MIT) at your option. From d8ee105a8f3ce4d5c57cd091b67943aab86b176a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 27 Apr 2022 07:17:42 -0700 Subject: [PATCH 626/860] Avoid unconditional dependency on libssh2-sys when using zlib-ng-compat (#833) Use a weak dependency feature to enable zlib-ng-compat on libssh2-sys without forcibly enabling libssh2-sys. --- libgit2-sys/Cargo.toml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 9e7b0ca8a2..8630f060be 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -38,9 +38,4 @@ https = ["openssl-sys"] ssh_key_from_memory = [] vendored = [] vendored-openssl = ["openssl-sys/vendored"] -# Cargo does not support requiring features on an optional dependency without -# requiring the dependency. Rather than introduce additional complexity, we -# just require libssh2 when using zlib-ng-compat. This will require building -# libssh2, but it will not add code to the final binary without the "ssh" -# feature enabled. -zlib-ng-compat = ["libz-sys/zlib-ng", "libssh2-sys/zlib-ng-compat"] +zlib-ng-compat = ["libz-sys/zlib-ng", "libssh2-sys?/zlib-ng-compat"] From 9d33858b649f2a2e930c841a53a7d99c21354856 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 27 Apr 2022 13:23:19 -0700 Subject: [PATCH 627/860] git2 0.14.3 and libgit2-sys 0.13.3 --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d0aaf8677d..84ca63a788 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.14.2" +version = "0.14.3" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.13.2" } +libgit2-sys = { path = "libgit2-sys", version = "0.13.3" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 8630f060be..8258c7a63d 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.13.2+1.4.2" +version = "0.13.3+1.4.2" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 31d3ff0fdf9e2e1d2232819d7d5331faa63f8f51 Mon Sep 17 00:00:00 2001 From: Archer Date: Fri, 29 Apr 2022 19:44:10 +0200 Subject: [PATCH 628/860] Add binding for git_commit_body This patch adds a binding for git_commit_body to retrieve the commit message without the summary paragraph. Additionally, this patch updates the test suite to test commits with a body paragraph. While the commit body was previously available via Commit::message, users would have to reimplement libgit2's behaviour to extract the commit body from it. --- libgit2-sys/lib.rs | 1 + src/commit.rs | 27 ++++++++++++++++++++++++++- src/remote.rs | 2 +- src/test.rs | 2 +- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 195f1371e2..259d5e8df1 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2747,6 +2747,7 @@ extern "C" { pub fn git_commit_parentcount(commit: *const git_commit) -> c_uint; pub fn git_commit_raw_header(commit: *const git_commit) -> *const c_char; pub fn git_commit_summary(commit: *mut git_commit) -> *const c_char; + pub fn git_commit_body(commit: *mut git_commit) -> *const c_char; pub fn git_commit_time(commit: *const git_commit) -> git_time_t; pub fn git_commit_time_offset(commit: *const git_commit) -> c_int; pub fn git_commit_tree(tree_out: *mut *mut git_tree, commit: *const git_commit) -> c_int; diff --git a/src/commit.rs b/src/commit.rs index b7e900a7ae..c6e2bd10e5 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -145,6 +145,29 @@ impl<'repo> Commit<'repo> { unsafe { crate::opt_bytes(self, raw::git_commit_summary(self.raw)) } } + /// Get the long "body" of the git commit message. + /// + /// The returned message is the body of the commit, comprising everything + /// but the first paragraph of the message. Leading and trailing whitespaces + /// are trimmed. + /// + /// `None` may be returned if an error occurs or if the summary is not valid + /// utf-8. + pub fn body(&self) -> Option<&str> { + self.body_bytes().and_then(|s| str::from_utf8(s).ok()) + } + + /// Get the long "body" of the git commit message. + /// + /// The returned message is the body of the commit, comprising everything + /// but the first paragraph of the message. Leading and trailing whitespaces + /// are trimmed. + /// + /// `None` may be returned if an error occurs. + pub fn body_bytes(&self) -> Option<&[u8]> { + unsafe { crate::opt_bytes(self, raw::git_commit_body(self.raw)) } + } + /// Get the commit time (i.e. committer time) of a commit. /// /// The first element of the tuple is the time, in seconds, since the epoch. @@ -399,12 +422,14 @@ mod tests { let head = repo.head().unwrap(); let target = head.target().unwrap(); let commit = repo.find_commit(target).unwrap(); - assert_eq!(commit.message(), Some("initial")); + assert_eq!(commit.message(), Some("initial\n\nbody")); + assert_eq!(commit.body(), Some("body")); assert_eq!(commit.id(), target); commit.message_raw().unwrap(); commit.raw_header().unwrap(); commit.message_encoding(); commit.summary().unwrap(); + commit.body().unwrap(); commit.tree_id(); commit.tree().unwrap(); assert_eq!(commit.parents().count(), 0); diff --git a/src/remote.rs b/src/remote.rs index 831e108790..4db06e7e11 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -956,7 +956,7 @@ mod tests { let repo = Repository::clone(&url, td3.path()).unwrap(); let commit = repo.head().unwrap().target().unwrap(); let commit = repo.find_commit(commit).unwrap(); - assert_eq!(commit.message(), Some("initial")); + assert_eq!(commit.message(), Some("initial\n\nbody")); } #[test] diff --git a/src/test.rs b/src/test.rs index 89a13beafe..c1ff1de21f 100644 --- a/src/test.rs +++ b/src/test.rs @@ -31,7 +31,7 @@ pub fn repo_init() -> (TempDir, Repository) { let tree = repo.find_tree(id).unwrap(); let sig = repo.signature().unwrap(); - repo.commit(Some("HEAD"), &sig, &sig, "initial", &tree, &[]) + repo.commit(Some("HEAD"), &sig, &sig, "initial\n\nbody", &tree, &[]) .unwrap(); } (td, repo) From 23a5340a2221fc0e4364dae285750f8b11509932 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 10 May 2022 01:14:26 -0700 Subject: [PATCH 629/860] Add `Tree::get_name_bytes` to handle non-UTF-8 entry names --- src/tree.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/tree.rs b/src/tree.rs index 68af61e335..cac66198d1 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -176,6 +176,21 @@ impl<'repo> Tree<'repo> { } } + /// Lookup a tree entry by its filename, specified as bytes. + /// + /// This allows for non-UTF-8 filenames. + pub fn get_name_bytes(&self, filename: &[u8]) -> Option> { + let filename = CString::new(filename).unwrap(); + unsafe { + let ptr = call!(raw::git_tree_entry_byname(&*self.raw(), filename)); + if ptr.is_null() { + None + } else { + Some(entry_from_raw_const(ptr)) + } + } + } + /// Retrieve a tree entry contained in a tree or in any of its subtrees, /// given its relative path. pub fn get_path(&self, path: &Path) -> Result, Error> { @@ -510,6 +525,7 @@ mod tests { let e1 = tree.get(0).unwrap(); assert!(e1 == tree.get_id(e1.id()).unwrap()); assert!(e1 == tree.get_name("foo").unwrap()); + assert!(e1 == tree.get_name_bytes(b"foo").unwrap()); assert!(e1 == tree.get_path(Path::new("foo")).unwrap()); assert_eq!(e1.name(), Some("foo")); e1.to_object(&repo).unwrap(); From 6316180ebf57e517e62b389eba9706f887ff0284 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 10 May 2022 09:15:56 -0700 Subject: [PATCH 630/860] Implement `Tree::get_name` using `Tree::get_name_bytes` to avoid duplication --- src/tree.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index cac66198d1..3d6b290c52 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -165,15 +165,7 @@ impl<'repo> Tree<'repo> { /// Lookup a tree entry by its filename pub fn get_name(&self, filename: &str) -> Option> { - let filename = CString::new(filename).unwrap(); - unsafe { - let ptr = call!(raw::git_tree_entry_byname(&*self.raw(), filename)); - if ptr.is_null() { - None - } else { - Some(entry_from_raw_const(ptr)) - } - } + self.get_name_bytes(filename.as_bytes()) } /// Lookup a tree entry by its filename, specified as bytes. From d6f45600a9b9ffd627dcf829ee152f1960892ede Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 10 May 2022 09:46:23 -0700 Subject: [PATCH 631/860] git2 0.14.4 and libgit2-sys 0.13.4 --- Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 84ca63a788..92db148433 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.14.3" +version = "0.14.4" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.13.3" } +libgit2-sys = { path = "libgit2-sys", version = "0.13.4" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 8258c7a63d..7edd14f199 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.13.3+1.4.2" +version = "0.13.4+1.4.2" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 61454c6d4017412f2c826efc45a746977137b6ee Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 10 May 2022 19:05:10 -0700 Subject: [PATCH 632/860] Fix copy-paste issue ("Commit" -> "Tree") --- src/tree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tree.rs b/src/tree.rs index 3d6b290c52..6fe72d8192 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -199,7 +199,7 @@ impl<'repo> Tree<'repo> { unsafe { &*(self as *const _ as *const Object<'repo>) } } - /// Consumes Commit to be returned as an `Object` + /// Consumes this Tree to be returned as an `Object` pub fn into_object(self) -> Object<'repo> { assert_eq!(mem::size_of_val(&self), mem::size_of::>()); unsafe { mem::transmute(self) } From fe7188586a58eb5b8beacfb14eedf1d511afabf3 Mon Sep 17 00:00:00 2001 From: Adam Szkoda Date: Tue, 31 May 2022 16:33:55 +0200 Subject: [PATCH 633/860] Add a binding for tag_annotation_create() (#845) --- src/repo.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index 92fa948305..3aeac2f1f5 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1818,6 +1818,38 @@ impl Repository { } } + /// Create a new tag in the repository from an object without creating a reference. + /// + /// The message will not be cleaned up. + /// + /// The tag name will be checked for validity. You must avoid the characters + /// '~', '^', ':', ' \ ', '?', '[', and '*', and the sequences ".." and " @ + /// {" which have special meaning to revparse. + pub fn tag_annotation_create( + &self, + name: &str, + target: &Object<'_>, + tagger: &Signature<'_>, + message: &str, + ) -> Result { + let name = CString::new(name)?; + let message = CString::new(message)?; + let mut raw_oid = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; + unsafe { + try_call!(raw::git_tag_annotation_create( + &mut raw_oid, + self.raw, + name, + target.raw(), + tagger.raw(), + message + )); + Ok(Binding::from_raw(&raw_oid as *const _)) + } + } + /// Create a new lightweight tag pointing at a target object /// /// A new direct reference will be created pointing to this target object. From fe55127a9f0fcf00b0fd9dc5611e373c5a2d18c3 Mon Sep 17 00:00:00 2001 From: koenw Date: Wed, 1 Jun 2022 16:06:08 +0200 Subject: [PATCH 634/860] Fix typo in PushOptions docs (#846) --- src/remote.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/remote.rs b/src/remote.rs index 4db06e7e11..d2a73858f7 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -608,13 +608,13 @@ impl<'cb> PushOptions<'cb> { } } - /// Set the callbacks to use for the fetch operation. + /// Set the callbacks to use for the push operation. pub fn remote_callbacks(&mut self, cbs: RemoteCallbacks<'cb>) -> &mut Self { self.callbacks = Some(cbs); self } - /// Set the proxy options to use for the fetch operation. + /// Set the proxy options to use for the push operation. pub fn proxy_options(&mut self, opts: ProxyOptions<'cb>) -> &mut Self { self.proxy = Some(opts); self From d5a56e9be2b3d708748946ca0b9dfba00835eac0 Mon Sep 17 00:00:00 2001 From: Volodymyr Fialko Date: Mon, 13 Jun 2022 15:39:29 +0200 Subject: [PATCH 635/860] Add bindings for git email create (#847) Add bindings for `git_email_create_from_diff()` and `git_email_create_from_commit()`. Deprecate `git_diff_format_email()` to reflect upstream changes. --- libgit2-sys/lib.rs | 41 ++++++++++ src/diff.rs | 9 +++ src/email.rs | 183 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + 4 files changed, 235 insertions(+) create mode 100644 src/email.rs diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 259d5e8df1..d5150ffa45 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1992,6 +1992,28 @@ pub struct git_message_trailer_array { pub _trailer_block: *mut c_char, } +#[repr(C)] +pub struct git_email_create_options { + pub version: c_uint, + pub flags: u32, + pub diff_opts: git_diff_options, + pub diff_find_opts: git_diff_find_options, + pub subject_prefix: *const c_char, + pub start_number: usize, + pub reroll_number: usize, +} + +pub const GIT_EMAIL_CREATE_OPTIONS_VERSION: c_uint = 1; + +git_enum! { + pub enum git_email_create_flags_t { + GIT_EMAIL_CREATE_DEFAULT = 0, + GIT_EMAIL_CREATE_OMIT_NUMBERS = 1 << 0, + GIT_EMAIL_CREATE_ALWAYS_NUMBER = 1 << 1, + GIT_EMAIL_CREATE_NO_RENAMES = 1 << 2, + } +} + extern "C" { // threads pub fn git_libgit2_init() -> c_int; @@ -4106,6 +4128,25 @@ extern "C" { replace_email: *const c_char, ) -> c_int; + // email + pub fn git_email_create_from_diff( + out: *mut git_buf, + diff: *mut git_diff, + patch_idx: usize, + patch_count: usize, + commit_id: *const git_oid, + summary: *const c_char, + body: *const c_char, + author: *const git_signature, + given_opts: *const git_email_create_options, + ) -> c_int; + + pub fn git_email_create_from_commit( + out: *mut git_buf, + commit: *mut git_commit, + given_opts: *const git_email_create_options, + ) -> c_int; + pub fn git_trace_set(level: git_trace_level_t, cb: git_trace_cb) -> c_int; } diff --git a/src/diff.rs b/src/diff.rs index 0df6f85ea8..3d5b42d9dc 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -254,6 +254,8 @@ impl<'repo> Diff<'repo> { /// Create an e-mail ready patch from a diff. /// /// Matches the format created by `git format-patch` + #[doc(hidden)] + #[deprecated(note = "refactored to `Email::from_diff` to match upstream")] pub fn format_email( &mut self, patch_no: usize, @@ -277,6 +279,7 @@ impl<'repo> Diff<'repo> { raw_opts.body = message.as_ptr() as *const _; raw_opts.author = commit.author().raw(); let buf = Buf::new(); + #[allow(deprecated)] unsafe { try_call!(raw::git_diff_format_email(buf.raw(), self.raw, &*raw_opts)); } @@ -1480,6 +1483,11 @@ impl DiffFindOptions { } // TODO: expose git_diff_similarity_metric + + /// Acquire a pointer to the underlying raw options. + pub unsafe fn raw(&mut self) -> *const raw::git_diff_find_options { + &self.raw + } } impl Default for DiffFormatEmailOptions { @@ -1775,6 +1783,7 @@ mod tests { None, ) .unwrap(); + #[allow(deprecated)] let actual_email = diff.format_email(1, 1, &updated_commit, None).unwrap(); let actual_email = actual_email.as_str().unwrap(); assert!( diff --git a/src/email.rs b/src/email.rs new file mode 100644 index 0000000000..d3ebc03842 --- /dev/null +++ b/src/email.rs @@ -0,0 +1,183 @@ +use std::ffi::CString; +use std::{mem, ptr}; + +use crate::util::Binding; +use crate::{raw, Buf, Commit, DiffFindOptions, DiffOptions, Error, IntoCString}; +use crate::{Diff, Oid, Signature}; + +/// A structure to represent patch in mbox format for sending via email +pub struct Email { + buf: Buf, +} + +/// Options for controlling the formatting of the generated e-mail. +pub struct EmailCreateOptions { + diff_options: DiffOptions, + diff_find_options: DiffFindOptions, + subject_prefix: Option, + raw: raw::git_email_create_options, +} + +impl Default for EmailCreateOptions { + fn default() -> Self { + // Defaults options created in corresponding to `GIT_EMAIL_CREATE_OPTIONS_INIT` + let default_options = raw::git_email_create_options { + version: raw::GIT_EMAIL_CREATE_OPTIONS_VERSION, + flags: raw::GIT_EMAIL_CREATE_DEFAULT as u32, + diff_opts: unsafe { mem::zeroed() }, + diff_find_opts: unsafe { mem::zeroed() }, + subject_prefix: ptr::null(), + start_number: 1, + reroll_number: 0, + }; + let mut diff_options = DiffOptions::new(); + diff_options.show_binary(true).context_lines(3); + Self { + diff_options, + diff_find_options: DiffFindOptions::new(), + subject_prefix: None, + raw: default_options, + } + } +} + +impl EmailCreateOptions { + /// Creates a new set of email create options + /// + /// By default, options include rename detection and binary + /// diffs to match `git format-patch`. + pub fn new() -> Self { + Self::default() + } + + fn flag(&mut self, opt: raw::git_email_create_flags_t, val: bool) -> &mut Self { + let opt = opt as u32; + if val { + self.raw.flags |= opt; + } else { + self.raw.flags &= !opt; + } + self + } + + /// Flag indicating whether patch numbers are included in the subject prefix. + pub fn omit_numbers(&mut self, omit: bool) -> &mut Self { + self.flag(raw::GIT_EMAIL_CREATE_OMIT_NUMBERS, omit) + } + + /// Flag indicating whether numbers included in the subject prefix even when + /// the patch is for a single commit (1/1). + pub fn always_number(&mut self, always: bool) -> &mut Self { + self.flag(raw::GIT_EMAIL_CREATE_ALWAYS_NUMBER, always) + } + + /// Flag indicating whether rename or similarity detection are ignored. + pub fn ignore_renames(&mut self, ignore: bool) -> &mut Self { + self.flag(raw::GIT_EMAIL_CREATE_NO_RENAMES, ignore) + } + + /// Get mutable access to `DiffOptions` that are used for creating diffs. + pub fn diff_options(&mut self) -> &mut DiffOptions { + &mut self.diff_options + } + + /// Get mutable access to `DiffFindOptions` that are used for finding + /// similarities within diffs. + pub fn diff_find_options(&mut self) -> &mut DiffFindOptions { + &mut self.diff_find_options + } + + /// Set the subject prefix + /// + /// The default value for this is "PATCH". If set to an empty string ("") + /// then only the patch numbers will be shown in the prefix. + /// If the subject_prefix is empty and patch numbers are not being shown, + /// the prefix will be omitted entirely. + pub fn subject_prefix(&mut self, t: T) -> &mut Self { + self.subject_prefix = Some(t.into_c_string().unwrap()); + self + } + + /// Set the starting patch number; this cannot be 0. + /// + /// The default value for this is 1. + pub fn start_number(&mut self, number: usize) -> &mut Self { + self.raw.start_number = number; + self + } + + /// Set the "re-roll" number. + /// + /// The default value for this is 0 (no re-roll). + pub fn reroll_number(&mut self, number: usize) -> &mut Self { + self.raw.reroll_number = number; + self + } + + /// Acquire a pointer to the underlying raw options. + /// + /// This function is unsafe as the pointer is only valid so long as this + /// structure is not moved, modified, or used elsewhere. + unsafe fn raw(&mut self) -> *const raw::git_email_create_options { + self.raw.subject_prefix = self + .subject_prefix + .as_ref() + .map(|s| s.as_ptr()) + .unwrap_or(ptr::null()); + self.raw.diff_opts = ptr::read(self.diff_options.raw()); + self.raw.diff_find_opts = ptr::read(self.diff_find_options.raw()); + &self.raw as *const _ + } +} + +impl Email { + /// Returns a byte slice with stored e-mail patch in. `Email` could be + /// created by one of the `from_*` functions. + pub fn as_slice(&self) -> &[u8] { + &self.buf + } + + /// Create a diff for a commit in mbox format for sending via email. + pub fn from_diff( + diff: &Diff<'_>, + patch_idx: usize, + patch_count: usize, + commit_id: &Oid, + summary: T, + body: T, + author: &Signature<'_>, + opts: &mut EmailCreateOptions, + ) -> Result { + let buf = Buf::new(); + let summary = summary.into_c_string()?; + let body = body.into_c_string()?; + unsafe { + try_call!(raw::git_email_create_from_diff( + buf.raw(), + Binding::raw(diff), + patch_idx, + patch_count, + Binding::raw(commit_id), + summary.as_ptr(), + body.as_ptr(), + Binding::raw(author), + opts.raw() + )); + Ok(Self { buf }) + } + } + + /// Create a diff for a commit in mbox format for sending via email. + /// The commit must not be a merge commit. + pub fn from_commit(commit: &Commit<'_>, opts: &mut EmailCreateOptions) -> Result { + let buf = Buf::new(); + unsafe { + try_call!(raw::git_email_create_from_commit( + buf.raw(), + commit.raw(), + opts.raw() + )); + Ok(Self { buf }) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index cdc3648d83..a9ec38d20d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,6 +93,7 @@ pub use crate::describe::{Describe, DescribeFormatOptions, DescribeOptions}; pub use crate::diff::{Deltas, Diff, DiffDelta, DiffFile, DiffOptions}; pub use crate::diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind}; pub use crate::diff::{DiffFindOptions, DiffHunk, DiffLine, DiffLineType, DiffStats}; +pub use crate::email::{Email, EmailCreateOptions}; pub use crate::error::Error; pub use crate::index::{ Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath, @@ -675,6 +676,7 @@ mod config; mod cred; mod describe; mod diff; +mod email; mod error; mod index; mod indexer; From 61f8afdd52e0168145dcc21b18d8824467d4d1c7 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 7 Jul 2022 07:59:01 -0700 Subject: [PATCH 636/860] Use custom config entry iterator. (#854) --- src/config.rs | 111 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 30 deletions(-) diff --git a/src/config.rs b/src/config.rs index 573fa358b7..580af833ae 100644 --- a/src/config.rs +++ b/src/config.rs @@ -23,8 +23,39 @@ pub struct ConfigEntry<'cfg> { } /// An iterator over the `ConfigEntry` values of a `Config` structure. +/// +/// Due to lifetime restrictions, `ConfigEntries` does not implement the +/// standard [`Iterator`] trait. It provides a [`next`] function which only +/// allows access to one entry at a time. [`for_each`] is available as a +/// convenience function. +/// +/// [`next`]: ConfigEntries::next +/// [`for_each`]: ConfigEntries::for_each +/// +/// # Example +/// +/// ``` +/// // Example of how to collect all entries. +/// use git2::Config; +/// +/// let config = Config::new()?; +/// let iter = config.entries(None)?; +/// let mut entries = Vec::new(); +/// iter +/// .for_each(|entry| { +/// let name = entry.name().unwrap().to_string(); +/// let value = entry.value().unwrap_or("").to_string(); +/// entries.push((name, value)) +/// })?; +/// for entry in &entries { +/// println!("{} = {}", entry.0, entry.1); +/// } +/// # Ok::<(), git2::Error>(()) +/// +/// ``` pub struct ConfigEntries<'cfg> { raw: *mut raw::git_config_iterator, + current: Option>, _marker: marker::PhantomData<&'cfg Config>, } @@ -280,15 +311,18 @@ impl Config { /// the variable name: the section and variable parts are lower-cased. The /// subsection is left unchanged. /// + /// Due to lifetime restrictions, the returned value does not implement + /// the standard [`Iterator`] trait. See [`ConfigEntries`] for more. + /// /// # Example /// /// ``` - /// # #![allow(unstable)] /// use git2::Config; /// /// let cfg = Config::new().unwrap(); /// - /// for entry in &cfg.entries(None).unwrap() { + /// let mut entries = cfg.entries(None).unwrap(); + /// while let Some(entry) = entries.next() { /// let entry = entry.unwrap(); /// println!("{} => {}", entry.name().unwrap(), entry.value().unwrap()); /// } @@ -317,6 +351,9 @@ impl Config { /// The regular expression is applied case-sensitively on the normalized form of /// the variable name: the section and variable parts are lower-cased. The /// subsection is left unchanged. + /// + /// Due to lifetime restrictions, the returned value does not implement + /// the standard [`Iterator`] trait. See [`ConfigEntries`] for more. pub fn multivar(&self, name: &str, regexp: Option<&str>) -> Result, Error> { let mut ret = ptr::null_mut(); let name = CString::new(name)?; @@ -550,6 +587,7 @@ impl<'cfg> Binding for ConfigEntries<'cfg> { unsafe fn from_raw(raw: *mut raw::git_config_iterator) -> ConfigEntries<'cfg> { ConfigEntries { raw, + current: None, _marker: marker::PhantomData, } } @@ -558,24 +596,33 @@ impl<'cfg> Binding for ConfigEntries<'cfg> { } } -// entries are only valid until the iterator is freed, so this impl is for -// `&'b T` instead of `T` to have a lifetime to tie them to. -// -// It's also not implemented for `&'b mut T` so we can have multiple entries -// (ok). -impl<'cfg, 'b> Iterator for &'b ConfigEntries<'cfg> { - type Item = Result, Error>; - fn next(&mut self) -> Option, Error>> { +impl<'cfg> ConfigEntries<'cfg> { + /// Advances the iterator and returns the next value. + /// + /// Returns `None` when iteration is finished. + pub fn next(&mut self) -> Option, Error>> { let mut raw = ptr::null_mut(); + drop(self.current.take()); unsafe { try_call_iter!(raw::git_config_next(&mut raw, self.raw)); - Some(Ok(ConfigEntry { + let entry = ConfigEntry { owned: false, raw, _marker: marker::PhantomData, - })) + }; + self.current = Some(entry); + Some(Ok(self.current.as_ref().unwrap())) } } + + /// Calls the given closure for each remaining entry in the iterator. + pub fn for_each)>(mut self, mut f: F) -> Result<(), Error> { + while let Some(entry) = self.next() { + let entry = entry?; + f(entry); + } + Ok(()) + } } impl<'cfg> Drop for ConfigEntries<'cfg> { @@ -628,7 +675,8 @@ mod tests { assert_eq!(cfg.get_i64("foo.k3").unwrap(), 2); assert_eq!(cfg.get_str("foo.k4").unwrap(), "bar"); - for entry in &cfg.entries(None).unwrap() { + let mut entries = cfg.entries(None).unwrap(); + while let Some(entry) = entries.next() { let entry = entry.unwrap(); entry.name(); entry.value(); @@ -649,39 +697,42 @@ mod tests { cfg.set_multivar("foo.baz", "^$", "oki").unwrap(); // `entries` filters by name - let mut entries: Vec = cfg - .entries(Some("foo.bar")) + let mut entries: Vec = Vec::new(); + cfg.entries(Some("foo.bar")) .unwrap() - .into_iter() - .map(|entry| entry.unwrap().value().unwrap().into()) - .collect(); + .for_each(|entry| entries.push(entry.value().unwrap().to_string())) + .unwrap(); entries.sort(); assert_eq!(entries, ["baz", "quux", "qux"]); // which is the same as `multivar` without a regex - let mut multivals: Vec = cfg - .multivar("foo.bar", None) + let mut multivals = Vec::new(); + cfg.multivar("foo.bar", None) .unwrap() - .into_iter() - .map(|entry| entry.unwrap().value().unwrap().into()) - .collect(); + .for_each(|entry| multivals.push(entry.value().unwrap().to_string())) + .unwrap(); multivals.sort(); assert_eq!(multivals, entries); // yet _with_ a regex, `multivar` filters by value - let mut quxish: Vec = cfg - .multivar("foo.bar", Some("qu.*x")) + let mut quxish = Vec::new(); + cfg.multivar("foo.bar", Some("qu.*x")) .unwrap() - .into_iter() - .map(|entry| entry.unwrap().value().unwrap().into()) - .collect(); + .for_each(|entry| quxish.push(entry.value().unwrap().to_string())) + .unwrap(); quxish.sort(); assert_eq!(quxish, ["quux", "qux"]); cfg.remove_multivar("foo.bar", ".*").unwrap(); - assert_eq!(cfg.entries(Some("foo.bar")).unwrap().count(), 0); - assert_eq!(cfg.multivar("foo.bar", None).unwrap().count(), 0); + let count = |entries: super::ConfigEntries<'_>| -> usize { + let mut c = 0; + entries.for_each(|_| c += 1).unwrap(); + c + }; + + assert_eq!(count(cfg.entries(Some("foo.bar")).unwrap()), 0); + assert_eq!(count(cfg.multivar("foo.bar", None).unwrap()), 0); } #[test] From e86aaf5af78ace4b36bc6ff17bb2316762e67069 Mon Sep 17 00:00:00 2001 From: David Knaack Date: Mon, 9 May 2022 09:32:15 +0200 Subject: [PATCH 637/860] update libgit2 to newer snapshot CVE 2022-24765 Co-Authored-By: Eric Huss <43198+ehuss@users.noreply.github.com> --- Cargo.toml | 4 ++-- git2-curl/Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 29 +++++++++++++++++++++-------- libgit2-sys/lib.rs | 5 ++++- libgit2-sys/libgit2 | 2 +- src/error.rs | 3 +++ src/lib.rs | 4 +++- src/opts.rs | 13 +++++++++++++ 9 files changed, 49 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 92db148433..27d9a92638 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.14.4" +version = "0.15.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.13.4" } +libgit2-sys = { path = "libgit2-sys", version = "0.14.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index a52bc21cfe..e249c7bca9 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -16,7 +16,7 @@ edition = "2018" curl = "0.4.33" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.14", default-features = false } +git2 = { path = "..", version = "0.15", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 7edd14f199..77112d409c 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.13.4+1.4.2" +version = "0.14.0+1.4.4" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index ef0468b40e..28207a9ba7 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,11 +14,7 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg - .range_version("1.4.0".."1.5.0") - .print_system_libs(false) - .probe("libgit2") - { + if let Ok(lib) = cfg.range_version("1.4.4".."1.5.0").probe("libgit2") { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } @@ -162,9 +158,26 @@ fn main() { cfg.define("SHA1DC_NO_STANDARD_INCLUDES", "1"); cfg.define("SHA1DC_CUSTOM_INCLUDE_SHA1_C", "\"common.h\""); cfg.define("SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C", "\"common.h\""); - cfg.file("libgit2/src/util/hash/sha1/collisiondetect.c"); - cfg.file("libgit2/src/util/hash/sha1/sha1dc/sha1.c"); - cfg.file("libgit2/src/util/hash/sha1/sha1dc/ubc_check.c"); + cfg.file("libgit2/src/util/hash/collisiondetect.c"); + cfg.file("libgit2/src/util/hash/sha1dc/sha1.c"); + cfg.file("libgit2/src/util/hash/sha1dc/ubc_check.c"); + + if https { + if windows { + features.push_str("#define GIT_SHA256_WIN32 1\n"); + cfg.file("libgit2/src/util/hash/win32.c"); + } else if target.contains("apple") { + features.push_str("#define GIT_SHA256_COMMON_CRYPTO 1\n"); + cfg.file("libgit2/src/util/hash/common_crypto.c"); + } else { + features.push_str("#define GIT_SHA256_OPENSSL 1\n"); + cfg.file("libgit2/src/util/hash/openssl.c"); + } + } else { + features.push_str("#define GIT_SHA256_BUILTIN 1\n"); + cfg.file("libgit2/src/util/hash/builtin.c"); + cfg.file("libgit2/src/util/hash/rfc6234/sha224-256.c"); + } if let Some(path) = env::var_os("DEP_Z_INCLUDE") { cfg.include(path); diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index d5150ffa45..a113a29526 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.13")] +#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.14")] #![allow(non_camel_case_types, unused_extern_crates)] // This is required to link libz when libssh2-sys is not included. @@ -195,6 +195,7 @@ git_enum! { GIT_EMISMATCH = -33, GIT_EINDEXDIRTY = -34, GIT_EAPPLYFAIL = -35, + GIT_EOWNER = -36, } } @@ -1894,6 +1895,8 @@ git_enum! { GIT_OPT_SET_ODB_LOOSE_PRIORITY, GIT_OPT_GET_EXTENSIONS, GIT_OPT_SET_EXTENSIONS, + GIT_OPT_GET_OWNER_VALIDATION, + GIT_OPT_SET_OWNER_VALIDATION, } } diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 2a0d0bd19b..53cfad9e4b 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7 +Subproject commit 53cfad9e4b0faeb4e2f6385cafd5298cbb81b82b diff --git a/src/error.rs b/src/error.rs index f3ad9ad0e9..779d785adf 100644 --- a/src/error.rs +++ b/src/error.rs @@ -127,6 +127,7 @@ impl Error { raw::GIT_EMISMATCH => super::ErrorCode::HashsumMismatch, raw::GIT_EINDEXDIRTY => super::ErrorCode::IndexDirty, raw::GIT_EAPPLYFAIL => super::ErrorCode::ApplyFail, + raw::GIT_EOWNER => super::ErrorCode::Owner, _ => super::ErrorCode::GenericError, } } @@ -163,6 +164,7 @@ impl Error { ErrorCode::HashsumMismatch => raw::GIT_EMISMATCH, ErrorCode::IndexDirty => raw::GIT_EINDEXDIRTY, ErrorCode::ApplyFail => raw::GIT_EAPPLYFAIL, + ErrorCode::Owner => raw::GIT_EOWNER, }; } @@ -293,6 +295,7 @@ impl Error { GIT_EMISMATCH, GIT_EINDEXDIRTY, GIT_EAPPLYFAIL, + GIT_EOWNER, ) } diff --git a/src/lib.rs b/src/lib.rs index a9ec38d20d..c297ffe444 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.14")] +#![doc(html_root_url = "https://docs.rs/git2/0.15")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] @@ -215,6 +215,8 @@ pub enum ErrorCode { IndexDirty, /// Patch application failed ApplyFail, + /// The object is not owned by the current user + Owner, } /// An enumeration of possible categories of things that can have diff --git a/src/opts.rs b/src/opts.rs index a89df4e1c9..dc902aee63 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -178,6 +178,19 @@ where Ok(()) } +/// Set wheter or not to verify ownership before performing a repository. +/// Enabled by default, but disabling this can lead to code execution vulnerabilities. +pub unsafe fn set_verify_owner_validation(enabled: bool) -> Result<(), Error> { + let error = raw::git_libgit2_opts( + raw::GIT_OPT_SET_OWNER_VALIDATION as libc::c_int, + enabled as libc::c_int, + ); + // This function cannot actually fail, but the function has an error return + // for other options that can. + debug_assert!(error >= 0); + Ok(()) +} + #[cfg(test)] mod test { use super::*; From 8871f8e9b38f600a499a4dd636840930c04b65bd Mon Sep 17 00:00:00 2001 From: David Knaack Date: Thu, 14 Jul 2022 09:44:09 +0200 Subject: [PATCH 638/860] bump libgit2 to 1.5.0 --- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 2 +- libgit2-sys/libgit2 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 77112d409c..1f5fe34e4d 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.14.0+1.4.4" +version = "0.14.0+1.5.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 28207a9ba7..442b196de0 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,7 +14,7 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.range_version("1.4.4".."1.5.0").probe("libgit2") { + if let Ok(lib) = cfg.range_version("1.4.4".."1.6.0").probe("libgit2") { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 53cfad9e4b..fbea439d4b 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 53cfad9e4b0faeb4e2f6385cafd5298cbb81b82b +Subproject commit fbea439d4b6fc91c6b619d01b85ab3b7746e4c19 From 46674cebd9089a6cf78e077fa621347f076705b1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 19 Jul 2022 09:03:05 -0700 Subject: [PATCH 639/860] Fix warning about unused_must_use for Box::from_raw (#860) --- src/odb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odb.rs b/src/odb.rs index f64a52c7e4..66166913fe 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -514,7 +514,7 @@ impl<'repo> Drop for OdbPackwriter<'repo> { None => (), }; - Box::from_raw(self.progress_payload_ptr); + drop(Box::from_raw(self.progress_payload_ptr)); } } } From e6aa6666b9f0f9110adf5bad56ea1d1dfa119d1c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 19 Jul 2022 09:03:38 -0700 Subject: [PATCH 640/860] Bump git2-curl version. (#861) --- git2-curl/Cargo.toml | 2 +- git2-curl/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index e249c7bca9..3dc80e4246 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2-curl" -version = "0.15.0" +version = "0.16.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index e8c2aac9d8..480c51c982 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -15,7 +15,7 @@ //! > **NOTE**: At this time this crate likely does not support a `git push` //! > operation, only clones. -#![doc(html_root_url = "https://docs.rs/git2-curl/0.15")] +#![doc(html_root_url = "https://docs.rs/git2-curl/0.16")] #![deny(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] From 0b340ffcdb21a7959f81c8ce77015723f5fc6037 Mon Sep 17 00:00:00 2001 From: Alex Touchet Date: Fri, 5 Aug 2022 08:57:07 -0700 Subject: [PATCH 641/860] Update version number in Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1168099e6d..7e11dcbfd9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.14" +git2 = "0.15" ``` ## Rust version requirements From 49879e9957a233b3149d66d6108878d70a1ca9be Mon Sep 17 00:00:00 2001 From: Steve Heindel Date: Mon, 12 Sep 2022 10:19:41 -0400 Subject: [PATCH 642/860] Implement IntoIterator for Statuses (#880) --- src/status.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/status.rs b/src/status.rs index d9bfc07342..024e9fcd62 100644 --- a/src/status.rs +++ b/src/status.rs @@ -305,6 +305,14 @@ impl<'a> DoubleEndedIterator for StatusIter<'a> { } impl<'a> ExactSizeIterator for StatusIter<'a> {} +impl<'a> IntoIterator for &'a Statuses<'a> { + type Item = StatusEntry<'a>; + type IntoIter = StatusIter<'a>; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + impl<'statuses> StatusEntry<'statuses> { /// Access the bytes for this entry's corresponding pathname pub fn path_bytes(&self) -> &[u8] { From 7f55b957cb83498208b20d0d80a0ebe2fb2a0879 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 21 Sep 2022 11:56:15 -0700 Subject: [PATCH 643/860] Add implementation and test for discover_path --- src/repo.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 3aeac2f1f5..21d621832a 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -3,7 +3,7 @@ use std::env; use std::ffi::{CStr, CString, OsStr}; use std::iter::IntoIterator; use std::mem; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::ptr; use std::str; @@ -259,6 +259,33 @@ impl Repository { Repository::open(util::bytes2path(&*buf)) } + /// Attempt to find the path to a git repo for a given path + /// + /// This starts at `path` and looks up the filesystem hierarchy + /// until it finds a repository, stopping if it finds a member of ceiling_dirs + pub fn discover_path, I, O>(path: P, ceiling_dirs: I) -> Result + where + O: AsRef, + I: IntoIterator, + { + crate::init(); + let buf = Buf::new(); + // Normal file path OK (does not need Windows conversion). + let path = path.as_ref().into_c_string()?; + let ceiling_dirs_os = env::join_paths(ceiling_dirs)?; + let ceiling_dirs = ceiling_dirs_os.into_c_string()?; + unsafe { + try_call!(raw::git_repository_discover( + buf.raw(), + path, + 1, + ceiling_dirs + )); + } + + Ok(util::bytes2path(&*buf).to_path_buf()) + } + /// Creates a new repository in the specified folder. /// /// This by default will create any necessary directories to create the @@ -3412,6 +3439,34 @@ mod tests { ); } + #[test] + fn smoke_discover_path() { + let td = TempDir::new().unwrap(); + let subdir = td.path().join("subdi"); + fs::create_dir(&subdir).unwrap(); + Repository::init_bare(td.path()).unwrap(); + let path = Repository::discover_path(&subdir, &[] as &[&OsStr]).unwrap(); + assert_eq!( + crate::test::realpath(&path).unwrap(), + crate::test::realpath(&td.path().join("")).unwrap() + ); + } + + #[test] + fn smoke_discover_path_ceiling_dir() { + let td = TempDir::new().unwrap(); + let subdir = td.path().join("subdi"); + fs::create_dir(&subdir).unwrap(); + let ceilingdir = subdir.join("ceiling"); + fs::create_dir(&ceilingdir).unwrap(); + let testdir = ceilingdir.join("testdi"); + fs::create_dir(&testdir).unwrap(); + Repository::init_bare(td.path()).unwrap(); + let path = Repository::discover_path(&testdir, &[ceilingdir.as_os_str()]); + + assert!(path.is_err()); + } + #[test] fn smoke_open_ext() { let td = TempDir::new().unwrap(); From 763e57633ab99c91fab4816573e6d313c5bd7e90 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 1 Oct 2022 12:34:04 +0200 Subject: [PATCH 644/860] note that a commit is not a descendant of itself --- src/repo.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index 3aeac2f1f5..92e1a7f9d5 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2418,6 +2418,9 @@ impl Repository { } /// Determine if a commit is the descendant of another commit + /// + /// Note that a commit is not considered a descendant of itself, in contrast + /// to `git merge-base --is-ancestor`. pub fn graph_descendant_of(&self, commit: Oid, ancestor: Oid) -> Result { unsafe { let rv = try_call!(raw::git_graph_descendant_of( From 5ab1d44b912075fc07ede1c8c8d3871d14619b1f Mon Sep 17 00:00:00 2001 From: Roman Podoliaka Date: Sun, 2 Oct 2022 18:49:33 +0100 Subject: [PATCH 645/860] Add support for GIT_FILEMODE_BLOB_GROUP_WRITABLE This type no longer exists in modern git, but there are existing git repositories out there with tree entries of this type (e.g. Linux kernel). Currently, traversing commits of a repository like that leads to a panic in DiffFile::mode(). --- libgit2-sys/lib.rs | 1 + src/diff.rs | 1 + src/lib.rs | 6 ++++++ systest/build.rs | 3 +++ 4 files changed, 11 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a113a29526..691753b26e 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -692,6 +692,7 @@ git_enum! { GIT_FILEMODE_UNREADABLE = 0o000000, GIT_FILEMODE_TREE = 0o040000, GIT_FILEMODE_BLOB = 0o100644, + GIT_FILEMODE_BLOB_GROUP_WRITABLE = 0o100664, GIT_FILEMODE_BLOB_EXECUTABLE = 0o100755, GIT_FILEMODE_LINK = 0o120000, GIT_FILEMODE_COMMIT = 0o160000, diff --git a/src/diff.rs b/src/diff.rs index 3d5b42d9dc..de1481d565 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -621,6 +621,7 @@ impl<'a> DiffFile<'a> { raw::GIT_FILEMODE_UNREADABLE => FileMode::Unreadable, raw::GIT_FILEMODE_TREE => FileMode::Tree, raw::GIT_FILEMODE_BLOB => FileMode::Blob, + raw::GIT_FILEMODE_BLOB_GROUP_WRITABLE => FileMode::BlobGroupWritable, raw::GIT_FILEMODE_BLOB_EXECUTABLE => FileMode::BlobExecutable, raw::GIT_FILEMODE_LINK => FileMode::Link, raw::GIT_FILEMODE_COMMIT => FileMode::Commit, diff --git a/src/lib.rs b/src/lib.rs index c297ffe444..df25092a9b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1098,6 +1098,8 @@ pub enum FileMode { Tree, /// Blob Blob, + /// Group writable blob. Obsolete mode kept for compatibility reasons + BlobGroupWritable, /// Blob executable BlobExecutable, /// Link @@ -1112,6 +1114,7 @@ impl From for i32 { FileMode::Unreadable => raw::GIT_FILEMODE_UNREADABLE as i32, FileMode::Tree => raw::GIT_FILEMODE_TREE as i32, FileMode::Blob => raw::GIT_FILEMODE_BLOB as i32, + FileMode::BlobGroupWritable => raw::GIT_FILEMODE_BLOB_GROUP_WRITABLE as i32, FileMode::BlobExecutable => raw::GIT_FILEMODE_BLOB_EXECUTABLE as i32, FileMode::Link => raw::GIT_FILEMODE_LINK as i32, FileMode::Commit => raw::GIT_FILEMODE_COMMIT as i32, @@ -1125,6 +1128,7 @@ impl From for u32 { FileMode::Unreadable => raw::GIT_FILEMODE_UNREADABLE as u32, FileMode::Tree => raw::GIT_FILEMODE_TREE as u32, FileMode::Blob => raw::GIT_FILEMODE_BLOB as u32, + FileMode::BlobGroupWritable => raw::GIT_FILEMODE_BLOB_GROUP_WRITABLE as u32, FileMode::BlobExecutable => raw::GIT_FILEMODE_BLOB_EXECUTABLE as u32, FileMode::Link => raw::GIT_FILEMODE_LINK as u32, FileMode::Commit => raw::GIT_FILEMODE_COMMIT as u32, @@ -1562,8 +1566,10 @@ mod tests { #[test] fn convert_filemode() { assert_eq!(i32::from(FileMode::Blob), 0o100644); + assert_eq!(i32::from(FileMode::BlobGroupWritable), 0o100664); assert_eq!(i32::from(FileMode::BlobExecutable), 0o100755); assert_eq!(u32::from(FileMode::Blob), 0o100644); + assert_eq!(u32::from(FileMode::BlobGroupWritable), 0o100664); assert_eq!(u32::from(FileMode::BlobExecutable), 0o100755); } } diff --git a/systest/build.rs b/systest/build.rs index eba93f3090..f0533cde25 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -39,6 +39,9 @@ fn main() { } }); + // GIT_FILEMODE_BLOB_GROUP_WRITABLE is not a public const in libgit2 + cfg.define("GIT_FILEMODE_BLOB_GROUP_WRITABLE", Some("0100664")); + // not entirely sure why this is failing... cfg.skip_roundtrip(|t| t == "git_clone_options" || t == "git_submodule_update_options"); From f03df45e599d1c327be010145a1a28e89126e2d2 Mon Sep 17 00:00:00 2001 From: Petr Novotnik Date: Thu, 13 Oct 2022 14:54:52 +0200 Subject: [PATCH 646/860] Allow AutotagOptions and FetchPrune enum to be copied and cloned --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index c297ffe444..b65581612d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1379,6 +1379,7 @@ impl DiffStatsFormat { } /// Automatic tag following options. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum AutotagOption { /// Use the setting from the remote's configuration Unspecified, @@ -1391,6 +1392,7 @@ pub enum AutotagOption { } /// Configuration for how pruning is done on a fetch +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum FetchPrune { /// Use the setting from the configuration Unspecified, From 4dd0bf61c9789e19eeb3ac043f217d661070f0da Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Fri, 28 Oct 2022 11:58:21 +0200 Subject: [PATCH 647/860] PartialEq, Eq for Signature Necessarily hand-derived structural equality, as the raw binding stores pointers for the string fields. --- src/signature.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/signature.rs b/src/signature.rs index 32cfa2c812..83fbbf5935 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -158,6 +158,16 @@ impl<'a> fmt::Display for Signature<'a> { } } +impl PartialEq for Signature<'_> { + fn eq(&self, other: &Self) -> bool { + self.when() == other.when() + && self.email_bytes() == other.email_bytes() + && self.name_bytes() == other.name_bytes() + } +} + +impl Eq for Signature<'_> {} + #[cfg(test)] mod tests { use crate::{Signature, Time}; From 9e51285308aca9e1fbadc6c5b8239c32910c05dd Mon Sep 17 00:00:00 2001 From: Alb Tam Date: Mon, 31 Oct 2022 20:32:43 +0100 Subject: [PATCH 648/860] Update RepositoryOpenFlags in doc --- src/repo.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index 92e1a7f9d5..f0be8c5a76 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -155,7 +155,7 @@ impl Repository { /// Find and open an existing repository, respecting git environment /// variables. This acts like `open_ext` with the - /// `REPOSITORY_OPEN_FROM_ENV` flag, but additionally respects `$GIT_DIR`. + /// [FROM_ENV](RepositoryOpenFlags::FROM_ENV) flag, but additionally respects `$GIT_DIR`. /// With `$GIT_DIR` unset, this will search for a repository starting in /// the current directory. pub fn open_from_env() -> Result { @@ -175,23 +175,23 @@ impl Repository { /// Find and open an existing repository, with additional options. /// - /// If flags contains REPOSITORY_OPEN_NO_SEARCH, the path must point + /// If flags contains [NO_SEARCH](RepositoryOpenFlags::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 + /// If flags contains [CROSS_FS](RepositoryOpenFlags::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 + /// If flags contains [BARE](RepositoryOpenFlags::BARE), force opening the repository as /// bare even if it isn't, ignoring any working directory, and defer /// loading the repository configuration for performance. /// - /// If flags contains REPOSITORY_OPEN_NO_DOTGIT, don't try appending + /// If flags contains [NO_DOTGIT](RepositoryOpenFlags::NO_DOTGIT), don't try appending /// `/.git` to `path`. /// - /// If flags contains REPOSITORY_OPEN_FROM_ENV, `open_ext` will ignore + /// If flags contains [FROM_ENV](RepositoryOpenFlags::FROM_ENV), `open_ext` will ignore /// other flags and `ceiling_dirs`, and respect the same environment /// variables git does. Note, however, that `path` overrides `$GIT_DIR`; to /// respect `$GIT_DIR` as well, use `open_from_env`. From 96f5057b17312dcb472592eade0c4e9dbc068f14 Mon Sep 17 00:00:00 2001 From: nasso Date: Sat, 12 Nov 2022 01:25:36 -0800 Subject: [PATCH 649/860] Add `Reference::symbolic_set_target` --- libgit2-sys/lib.rs | 6 ++++++ src/reference.rs | 37 +++++++++++++++++++++++++++++++++++++ src/repo.rs | 13 +++++++++++++ 3 files changed, 56 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a113a29526..5e943c0d09 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2437,6 +2437,12 @@ extern "C" { id: *const git_oid, log_message: *const c_char, ) -> c_int; + pub fn git_reference_symbolic_set_target( + out: *mut *mut git_reference, + r: *mut git_reference, + target: *const c_char, + log_message: *const c_char, + ) -> c_int; pub fn git_reference_type(r: *const git_reference) -> git_reference_t; pub fn git_reference_iterator_new( out: *mut *mut git_reference_iterator, diff --git a/src/reference.rs b/src/reference.rs index 479252a5cc..e017c8de4d 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -361,6 +361,35 @@ impl<'repo> Reference<'repo> { Ok(Binding::from_raw(raw)) } } + + /// Create a new reference with the same name as the given reference but a + /// different symbolic target. The reference must be a symbolic reference, + /// otherwise this will fail. + /// + /// The new reference will be written to disk, overwriting the given + /// reference. + /// + /// The target name will be checked for validity. See + /// [`Repository::reference_symbolic`] for rules about valid names. + /// + /// The message for the reflog will be ignored if the reference does not + /// belong in the standard set (HEAD, branches and remote-tracking + /// branches) and it does not have a reflog. + pub fn symbolic_set_target( + &mut self, + target: &str, + reflog_msg: &str, + ) -> Result, Error> { + let mut raw = ptr::null_mut(); + let target = CString::new(target)?; + let msg = CString::new(reflog_msg)?; + unsafe { + try_call!(raw::git_reference_symbolic_set_target( + &mut raw, self.raw, target, msg + )); + Ok(Binding::from_raw(raw)) + } + } } impl<'repo> PartialOrd for Reference<'repo> { @@ -512,6 +541,14 @@ mod tests { .reference_symbolic("refs/tags/tag1", "refs/heads/main", false, "test") .unwrap(); assert_eq!(sym1.kind().unwrap(), ReferenceType::Symbolic); + let mut sym2 = repo + .reference_symbolic("refs/tags/tag2", "refs/heads/main", false, "test") + .unwrap() + .symbolic_set_target("refs/tags/tag1", "test") + .unwrap(); + assert_eq!(sym2.kind().unwrap(), ReferenceType::Symbolic); + assert_eq!(sym2.symbolic_target().unwrap(), "refs/tags/tag1"); + sym2.delete().unwrap(); sym1.delete().unwrap(); { diff --git a/src/repo.rs b/src/repo.rs index f0be8c5a76..98d450a075 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1480,6 +1480,19 @@ impl Repository { /// Create a new symbolic reference. /// + /// A symbolic reference is a reference name that refers to another + /// reference name. If the other name moves, the symbolic name will move, + /// too. As a simple example, the "HEAD" reference might refer to + /// "refs/heads/master" while on the "master" branch of a repository. + /// + /// Valid reference names must follow one of two patterns: + /// + /// 1. Top-level names must contain only capital letters and underscores, + /// and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD"). + /// 2. Names prefixed with "refs/" can be almost anything. You must avoid + /// the characters '~', '^', ':', '\\', '?', '[', and '*', and the + /// sequences ".." and "@{" which have special meaning to revparse. + /// /// This function will return an error if a reference already exists with /// the given name unless force is true, in which case it will be /// overwritten. From 405b76bf38d71a1f3801b171198c18e830ea08bf Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 14 Nov 2022 07:13:05 -0800 Subject: [PATCH 650/860] Always initialize when setting global opts (#894) --- src/opts.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/opts.rs b/src/opts.rs index dc902aee63..c9c1c3e265 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -77,6 +77,7 @@ pub unsafe fn get_search_path(level: ConfigLevel) -> Result { /// Disabling this will cause repository objects to clear their caches when next /// accessed. pub fn enable_caching(enabled: bool) { + crate::init(); let error = unsafe { raw::git_libgit2_opts( raw::GIT_OPT_ENABLE_CACHING as libc::c_int, @@ -94,6 +95,7 @@ pub fn enable_caching(enabled: bool) { /// creation of objects that reference invalid objects (due to programming /// error or repository corruption). pub fn strict_object_creation(enabled: bool) { + crate::init(); let error = unsafe { raw::git_libgit2_opts( raw::GIT_OPT_ENABLE_STRICT_OBJECT_CREATION as libc::c_int, @@ -110,6 +112,7 @@ pub fn strict_object_creation(enabled: bool) { /// improve performance, at the cost of relying on repository integrity /// without checking it. pub fn strict_hash_verification(enabled: bool) { + crate::init(); let error = unsafe { raw::git_libgit2_opts( raw::GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION as libc::c_int, @@ -181,6 +184,7 @@ where /// Set wheter or not to verify ownership before performing a repository. /// Enabled by default, but disabling this can lead to code execution vulnerabilities. pub unsafe fn set_verify_owner_validation(enabled: bool) -> Result<(), Error> { + crate::init(); let error = raw::git_libgit2_opts( raw::GIT_OPT_SET_OWNER_VALIDATION as libc::c_int, enabled as libc::c_int, From f8ac2f79a2bc4828adc6b6e7a15c8d28bd17c241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20St=C4=99pie=C5=84?= Date: Mon, 12 Dec 2022 11:50:27 +0100 Subject: [PATCH 651/860] implement find_prefix for index --- src/index.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/index.rs b/src/index.rs index b2e8dfe5c1..9328b2c258 100644 --- a/src/index.rs +++ b/src/index.rs @@ -596,6 +596,26 @@ impl Index { Ok(Binding::from_raw(&raw as *const _)) } } + + /// Find the first position of any entries matching a prefix. + /// + /// To find the first position of a path inside a given folder, suffix the prefix with a '/'. + pub fn find_prefix(&self, path: &Path) -> Result, Error> { + unsafe { + let mut at_pos: size_t = 0; + let entry_path = path.into_c_string()?; + let result = call!(raw::git_index_find_prefix( + &mut at_pos, + self.raw, + entry_path + )); + if result == 0 { + Ok(Some(at_pos)) + } else { + Ok(None) + } + } + } } impl Binding for Index { @@ -857,6 +877,21 @@ mod tests { assert_eq!(e.path.len(), 6); } + #[test] + fn add_then_find() { + let mut index = Index::new().unwrap(); + let mut e = entry(); + e.path = b"foo/bar".to_vec(); + index.add(&e).unwrap(); + assert_eq!(index.get(0).unwrap().path, b"foo/bar"); + assert_eq!( + index.get_path(Path::new("foo/bar"), 0).unwrap().path, + b"foo/bar" + ); + assert_eq!(index.find_prefix(Path::new("foo/")).unwrap(), Some(0)); + assert_eq!(index.find_prefix(Path::new("empty/")).unwrap(), None); + } + #[test] fn add_frombuffer_then_read() { let (_td, repo) = crate::test::repo_init(); From c1e4ae1c47cd32f71c0976e231fb3112c717612d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20St=C4=99pie=C5=84?= Date: Mon, 12 Dec 2022 12:01:06 +0100 Subject: [PATCH 652/860] add git_index_find_prefix to raw --- libgit2-sys/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5e943c0d09..87855c85b1 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2953,6 +2953,11 @@ extern "C" { pub fn git_index_entrycount(entry: *const git_index) -> size_t; pub fn git_index_find(at_pos: *mut size_t, index: *mut git_index, path: *const c_char) -> c_int; + pub fn git_index_find_prefix( + at_pos: *mut size_t, + index: *mut git_index, + prefix: *const c_char, + ) -> c_int; pub fn git_index_free(index: *mut git_index); pub fn git_index_get_byindex(index: *mut git_index, n: size_t) -> *const git_index_entry; pub fn git_index_get_bypath( From 4a67c0ba3ba9d3fc9aac92285ca4b4549be7362c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20St=C4=99pie=C5=84?= Date: Tue, 13 Dec 2022 19:04:55 +0100 Subject: [PATCH 653/860] use generic IntoCString instead of only path as a prefix arg for find_prefix --- src/index.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/index.rs b/src/index.rs index 9328b2c258..69477497c1 100644 --- a/src/index.rs +++ b/src/index.rs @@ -600,10 +600,10 @@ impl Index { /// Find the first position of any entries matching a prefix. /// /// To find the first position of a path inside a given folder, suffix the prefix with a '/'. - pub fn find_prefix(&self, path: &Path) -> Result, Error> { + pub fn find_prefix(&self, prefix: T) -> Result, Error> { unsafe { let mut at_pos: size_t = 0; - let entry_path = path.into_c_string()?; + let entry_path = prefix.into_c_string()?; let result = call!(raw::git_index_find_prefix( &mut at_pos, self.raw, @@ -883,12 +883,15 @@ mod tests { let mut e = entry(); e.path = b"foo/bar".to_vec(); index.add(&e).unwrap(); + let mut e = entry(); + e.path = b"foo2/bar".to_vec(); + index.add(&e).unwrap(); assert_eq!(index.get(0).unwrap().path, b"foo/bar"); assert_eq!( index.get_path(Path::new("foo/bar"), 0).unwrap().path, b"foo/bar" ); - assert_eq!(index.find_prefix(Path::new("foo/")).unwrap(), Some(0)); + assert_eq!(index.find_prefix(Path::new("foo2/")).unwrap(), Some(1)); assert_eq!(index.find_prefix(Path::new("empty/")).unwrap(), None); } From 0174d01ad52ea897c3eb9ba718ea4250f547321f Mon Sep 17 00:00:00 2001 From: Adam Cvikl Date: Mon, 2 Jan 2023 15:00:20 +0100 Subject: [PATCH 654/860] fix typos --- examples/diff.rs | 4 ++-- examples/pull.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/diff.rs b/examples/diff.rs index c3026edb0e..62f165db39 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -96,7 +96,7 @@ struct Args { /// output condensed summary of header info flag_summary: bool, #[structopt(name = "find-renames", short = "M", long)] - /// set threshold for findind renames (default 50) + /// set threshold for finding renames (default 50) flag_find_renames: Option, #[structopt(name = "find-copies", short = "C", long)] /// set threshold for finding copies (default 50) @@ -120,7 +120,7 @@ struct Args { /// show given source prefix instead of 'a/' flag_src_prefix: Option, #[structopt(name = "dst-prefix", long)] - /// show given destinction prefix instead of 'b/' + /// show given destination prefix instead of 'b/' flag_dst_prefix: Option, #[structopt(name = "path", long = "git-dir")] /// path to git repository to use diff --git a/examples/pull.rs b/examples/pull.rs index 33f5cb1ef1..61251b481b 100644 --- a/examples/pull.rs +++ b/examples/pull.rs @@ -120,7 +120,7 @@ fn normal_merge( let mut idx = repo.merge_trees(&ancestor, &local_tree, &remote_tree, None)?; if idx.has_conflicts() { - println!("Merge conficts detected..."); + println!("Merge conflicts detected..."); repo.checkout_index(Some(&mut idx), None)?; return Ok(()); } @@ -152,7 +152,7 @@ fn do_merge<'a>( // 1. do a merge analysis let analysis = repo.merge_analysis(&[&fetch_commit])?; - // 2. Do the appopriate merge + // 2. Do the appropriate merge if analysis.0.is_fast_forward() { println!("Doing a fast forward"); // do a fast forward From d73c3f841290703fb447d4e76d81ab9187115067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20St=C4=99pie=C5=84?= Date: Mon, 9 Jan 2023 15:37:05 +0100 Subject: [PATCH 655/860] remove GIT_ENOTFOUND check and instead return it as an Err --- src/index.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/index.rs b/src/index.rs index 69477497c1..f214351891 100644 --- a/src/index.rs +++ b/src/index.rs @@ -600,20 +600,16 @@ impl Index { /// Find the first position of any entries matching a prefix. /// /// To find the first position of a path inside a given folder, suffix the prefix with a '/'. - pub fn find_prefix(&self, prefix: T) -> Result, Error> { + pub fn find_prefix(&self, prefix: T) -> Result { + let mut at_pos: size_t = 0; + let entry_path = prefix.into_c_string()?; unsafe { - let mut at_pos: size_t = 0; - let entry_path = prefix.into_c_string()?; - let result = call!(raw::git_index_find_prefix( + try_call!(raw::git_index_find_prefix( &mut at_pos, self.raw, entry_path )); - if result == 0 { - Ok(Some(at_pos)) - } else { - Ok(None) - } + Ok(at_pos) } } } @@ -766,7 +762,7 @@ mod tests { use std::path::Path; use tempfile::TempDir; - use crate::{Index, IndexEntry, IndexTime, Oid, Repository, ResetType}; + use crate::{ErrorCode, Index, IndexEntry, IndexTime, Oid, Repository, ResetType}; #[test] fn smoke() { @@ -891,8 +887,11 @@ mod tests { index.get_path(Path::new("foo/bar"), 0).unwrap().path, b"foo/bar" ); - assert_eq!(index.find_prefix(Path::new("foo2/")).unwrap(), Some(1)); - assert_eq!(index.find_prefix(Path::new("empty/")).unwrap(), None); + assert_eq!(index.find_prefix(Path::new("foo2/")), Ok(1)); + assert_eq!( + index.find_prefix(Path::new("empty/")).unwrap_err().code(), + ErrorCode::NotFound + ); } #[test] From 009c59e830921e045c70a73cd430d012d39cc7d6 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 10 Jan 2023 08:18:36 -0800 Subject: [PATCH 656/860] Merge pull request #909 from ehuss/ssh-keys Add ability to get the SSH host key and its type. --- Cargo.toml | 4 +- README.md | 2 +- git2-curl/Cargo.toml | 4 +- git2-curl/src/lib.rs | 2 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/lib.rs | 4 ++ src/cert.rs | 81 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 +- src/remote_callbacks.rs | 35 ++++++++++++++---- 9 files changed, 122 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 27d9a92638..dc5255f4a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.15.0" +version = "0.16.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.14.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.14.1" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/README.md b/README.md index 7e11dcbfd9..bf5daf5e47 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.15" +git2 = "0.16" ``` ## Rust version requirements diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 3dc80e4246..ac906367fc 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2-curl" -version = "0.16.0" +version = "0.17.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" @@ -16,7 +16,7 @@ edition = "2018" curl = "0.4.33" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.15", default-features = false } +git2 = { path = "..", version = "0.16", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 480c51c982..c0f0e30d19 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -15,7 +15,7 @@ //! > **NOTE**: At this time this crate likely does not support a `git push` //! > operation, only clones. -#![doc(html_root_url = "https://docs.rs/git2-curl/0.16")] +#![doc(html_root_url = "https://docs.rs/git2-curl/0.17")] #![deny(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 1f5fe34e4d..fd3e337f95 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.14.0+1.5.0" +version = "0.14.1+1.5.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5e943c0d09..ea66159f0c 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -489,6 +489,10 @@ git_enum! { GIT_CERT_SSH_RAW_TYPE_UNKNOWN = 0, GIT_CERT_SSH_RAW_TYPE_RSA = 1, GIT_CERT_SSH_RAW_TYPE_DSS = 2, + GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256 = 3, + GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384 = 4, + GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521 = 5, + GIT_CERT_SSH_RAW_TYPE_KEY_ED25519 = 6, } } diff --git a/src/cert.rs b/src/cert.rs index d62b8304ce..b232cc3ce8 100644 --- a/src/cert.rs +++ b/src/cert.rs @@ -27,6 +27,54 @@ pub struct CertX509<'a> { _marker: marker::PhantomData<&'a raw::git_cert>, } +/// The SSH host key type. +#[derive(Copy, Clone, Debug)] +#[non_exhaustive] +pub enum SshHostKeyType { + /// Unknown key type + Unknown = raw::GIT_CERT_SSH_RAW_TYPE_UNKNOWN as isize, + /// RSA key type + Rsa = raw::GIT_CERT_SSH_RAW_TYPE_RSA as isize, + /// DSS key type + Dss = raw::GIT_CERT_SSH_RAW_TYPE_DSS as isize, + /// ECDSA 256 key type + Ecdsa256 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256 as isize, + /// ECDSA 384 key type + Ecdsa384 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384 as isize, + /// ECDSA 521 key type + Ecdsa521 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521 as isize, + /// ED25519 key type + Ed255219 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ED25519 as isize, +} + +impl SshHostKeyType { + /// The name of the key type as encoded in the known_hosts file. + pub fn name(&self) -> &'static str { + match self { + SshHostKeyType::Unknown => "unknown", + SshHostKeyType::Rsa => "ssh-rsa", + SshHostKeyType::Dss => "ssh-dss", + SshHostKeyType::Ecdsa256 => "ecdsa-sha2-nistp256", + SshHostKeyType::Ecdsa384 => "ecdsa-sha2-nistp384", + SshHostKeyType::Ecdsa521 => "ecdsa-sha2-nistp521", + SshHostKeyType::Ed255219 => "ssh-ed25519", + } + } + + /// A short name of the key type, the colloquial form used as a human-readable description. + pub fn short_name(&self) -> &'static str { + match self { + SshHostKeyType::Unknown => "Unknown", + SshHostKeyType::Rsa => "RSA", + SshHostKeyType::Dss => "DSA", + SshHostKeyType::Ecdsa256 => "ECDSA", + SshHostKeyType::Ecdsa384 => "ECDSA", + SshHostKeyType::Ecdsa521 => "ECDSA", + SshHostKeyType::Ed255219 => "ED25519", + } + } +} + impl<'a> Cert<'a> { /// Attempt to view this certificate as an SSH hostkey. /// @@ -87,6 +135,39 @@ impl<'a> CertHostkey<'a> { } } } + + /// Returns the raw host key. + pub fn hostkey(&self) -> Option<&[u8]> { + unsafe { + if (*self.raw).kind & raw::GIT_CERT_SSH_RAW == 0 { + return None; + } + Some(slice::from_raw_parts( + (*self.raw).hostkey as *const u8, + (*self.raw).hostkey_len as usize, + )) + } + } + + /// Returns the type of the host key. + pub fn hostkey_type(&self) -> Option { + unsafe { + if (*self.raw).kind & raw::GIT_CERT_SSH_RAW == 0 { + return None; + } + let t = match (*self.raw).raw_type { + raw::GIT_CERT_SSH_RAW_TYPE_UNKNOWN => SshHostKeyType::Unknown, + raw::GIT_CERT_SSH_RAW_TYPE_RSA => SshHostKeyType::Rsa, + raw::GIT_CERT_SSH_RAW_TYPE_DSS => SshHostKeyType::Dss, + raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256 => SshHostKeyType::Ecdsa256, + raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384 => SshHostKeyType::Ecdsa384, + raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521 => SshHostKeyType::Ecdsa521, + raw::GIT_CERT_SSH_RAW_TYPE_KEY_ED25519 => SshHostKeyType::Ed255219, + t => panic!("unexpected host key type {:?}", t), + }; + Some(t) + } + } } impl<'a> CertX509<'a> { diff --git a/src/lib.rs b/src/lib.rs index b65581612d..40be0c4b5b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.15")] +#![doc(html_root_url = "https://docs.rs/git2/0.16")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] @@ -123,7 +123,7 @@ pub use crate::refspec::Refspec; pub use crate::remote::{ FetchOptions, PushOptions, Refspecs, Remote, RemoteConnection, RemoteHead, RemoteRedirect, }; -pub use crate::remote_callbacks::{Credentials, RemoteCallbacks}; +pub use crate::remote_callbacks::{CertificateCheckStatus, Credentials, RemoteCallbacks}; pub use crate::remote_callbacks::{TransportMessage, UpdateTips}; pub use crate::repo::{Repository, RepositoryInitOptions}; pub use crate::revert::RevertOptions; diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index bcc73e85e9..fe1802273b 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -51,7 +51,18 @@ pub type UpdateTips<'a> = dyn FnMut(&str, Oid, Oid) -> bool + 'a; /// /// The second argument is the hostname for the connection is passed as the last /// argument. -pub type CertificateCheck<'a> = dyn FnMut(&Cert<'_>, &str) -> bool + 'a; +pub type CertificateCheck<'a> = + dyn FnMut(&Cert<'_>, &str) -> Result + 'a; + +/// The return value for the [`CertificateCheck`] callback. +pub enum CertificateCheckStatus { + /// Indicates that the certificate should be accepted. + CertificateOk, + /// Indicates that the certificate callback is neither accepting nor + /// rejecting the certificate. The result of the certificate checks + /// built-in to libgit2 will be used instead. + CertificatePassthrough, +} /// Callback for each updated reference on push. /// @@ -162,7 +173,7 @@ impl<'a> RemoteCallbacks<'a> { /// connection to proceed. pub fn certificate_check(&mut self, cb: F) -> &mut RemoteCallbacks<'a> where - F: FnMut(&Cert<'_>, &str) -> bool + 'a, + F: FnMut(&Cert<'_>, &str) -> Result + 'a, { self.certificate_check = Some(Box::new(cb) as Box>); self @@ -371,16 +382,26 @@ extern "C" fn certificate_check_cb( let payload = &mut *(data as *mut RemoteCallbacks<'_>); let callback = match payload.certificate_check { Some(ref mut c) => c, - None => return true, + None => return Ok(CertificateCheckStatus::CertificatePassthrough), }; let cert = Binding::from_raw(cert); let hostname = str::from_utf8(CStr::from_ptr(hostname).to_bytes()).unwrap(); callback(&cert, hostname) }); - if ok == Some(true) { - 0 - } else { - -1 + match ok { + Some(Ok(CertificateCheckStatus::CertificateOk)) => 0, + Some(Ok(CertificateCheckStatus::CertificatePassthrough)) => raw::GIT_PASSTHROUGH as c_int, + Some(Err(e)) => { + let s = CString::new(e.message()).unwrap(); + unsafe { + raw::git_error_set_str(e.class() as c_int, s.as_ptr()); + } + e.raw_code() as c_int + } + None => { + // Panic. The *should* get resumed by some future call to check(). + -1 + } } } From f86234161ad0aa733846de8ed514cf199fc23525 Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Mon, 7 Nov 2022 09:35:13 +0100 Subject: [PATCH 657/860] Add bindings to git_indexer The indexer API is a lower-level interface for storing and indexing pack files, which, unlike `git_odb_write_pack`, allows the ouput to be written to an arbitrary directory. This can be useful when working with unusual validation requirements or non-standard repository layouts. --- libgit2-sys/lib.rs | 32 +++++++++ src/indexer.rs | 166 ++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 2 +- src/odb.rs | 8 ++- 4 files changed, 202 insertions(+), 6 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index ea66159f0c..4e18aeb32f 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -25,6 +25,7 @@ pub const GIT_REFDB_BACKEND_VERSION: c_uint = 1; pub const GIT_CHERRYPICK_OPTIONS_VERSION: c_uint = 1; pub const GIT_APPLY_OPTIONS_VERSION: c_uint = 1; pub const GIT_REVERT_OPTIONS_VERSION: c_uint = 1; +pub const GIT_INDEXER_OPTIONS_VERSION: c_uint = 1; macro_rules! git_enum { (pub enum $name:ident { $($variants:tt)* }) => { @@ -91,6 +92,7 @@ pub enum git_odb_object {} pub enum git_worktree {} pub enum git_transaction {} pub enum git_mailmap {} +pub enum git_indexer {} #[repr(C)] pub struct git_revspec { @@ -354,6 +356,14 @@ pub type git_indexer_progress_cb = )] pub type git_transfer_progress = git_indexer_progress; +#[repr(C)] +pub struct git_indexer_options { + pub version: c_uint, + pub progress_cb: git_indexer_progress_cb, + pub progress_cb_payload: *mut c_void, + pub verify: c_uchar, +} + pub type git_remote_ready_cb = Option c_int>; #[repr(C)] @@ -3801,6 +3811,28 @@ extern "C" { ) -> c_int; pub fn git_packbuilder_free(pb: *mut git_packbuilder); + // indexer + pub fn git_indexer_new( + out: *mut *mut git_indexer, + path: *const c_char, + mode: c_uint, + odb: *mut git_odb, + opts: *mut git_indexer_options, + ) -> c_int; + pub fn git_indexer_append( + idx: *mut git_indexer, + data: *const c_void, + size: size_t, + stats: *mut git_indexer_progress, + ) -> c_int; + pub fn git_indexer_commit(idx: *mut git_indexer, stats: *mut git_indexer_progress) -> c_int; + #[deprecated = "use `git_indexer_name` to retrieve the filename"] + pub fn git_indexer_hash(idx: *const git_indexer) -> *const git_oid; + pub fn git_indexer_name(idx: *const git_indexer) -> *const c_char; + pub fn git_indexer_free(idx: *mut git_indexer); + + pub fn git_indexer_options_init(opts: *mut git_indexer_options, version: c_uint) -> c_int; + // odb pub fn git_repository_odb(out: *mut *mut git_odb, repo: *mut git_repository) -> c_int; pub fn git_odb_new(db: *mut *mut git_odb) -> c_int; diff --git a/src/indexer.rs b/src/indexer.rs index 1003abeb76..46c5a2508a 100644 --- a/src/indexer.rs +++ b/src/indexer.rs @@ -1,7 +1,13 @@ -use std::marker; +use std::ffi::CStr; +use std::mem::MaybeUninit; +use std::path::Path; +use std::{io, marker, mem, ptr}; -use crate::raw; +use libc::c_void; + +use crate::odb::{write_pack_progress_cb, OdbPackwriterCb}; use crate::util::Binding; +use crate::{raw, Error, IntoCString, Odb}; /// Struct representing the progress by an in-flight transfer. pub struct Progress<'a> { @@ -94,3 +100,159 @@ impl<'a> Binding for Progress<'a> { )] #[allow(dead_code)] pub type TransportProgress<'a> = IndexerProgress<'a>; + +/// A stream to write and index a packfile +/// +/// This is equivalent to [`crate::OdbPackwriter`], but allows to store the pack +/// and index at an arbitrary path. It also does not require access to an object +/// database if, and only if, the pack file is self-contained (i.e. not "thin"). +pub struct Indexer<'odb> { + raw: *mut raw::git_indexer, + progress: MaybeUninit, + progress_payload_ptr: *mut OdbPackwriterCb<'odb>, +} + +impl<'a> Indexer<'a> { + /// Create a new indexer + /// + /// The [`Odb`] is used to resolve base objects when fixing thin packs. It + /// can be `None` if no thin pack is expected, in which case missing bases + /// will result in an error. + /// + /// `mode` is the permissions to use for the output files, use `0` for defaults. + /// + /// If `verify` is `false`, the indexer will bypass object connectivity checks. + pub fn new(odb: Option<&Odb<'a>>, path: &Path, mode: u32, verify: bool) -> Result { + let path = path.into_c_string()?; + + let odb = odb.map(Binding::raw).unwrap_or_else(ptr::null_mut); + + let mut out = ptr::null_mut(); + let progress = MaybeUninit::uninit(); + let progress_cb: raw::git_indexer_progress_cb = Some(write_pack_progress_cb); + let progress_payload = Box::new(OdbPackwriterCb { cb: None }); + let progress_payload_ptr = Box::into_raw(progress_payload); + + unsafe { + let mut opts = mem::zeroed(); + try_call!(raw::git_indexer_options_init( + &mut opts, + raw::GIT_INDEXER_OPTIONS_VERSION + )); + opts.progress_cb = progress_cb; + opts.progress_cb_payload = progress_payload_ptr as *mut c_void; + opts.verify = verify.into(); + + try_call!(raw::git_indexer_new(&mut out, path, mode, odb, &mut opts)); + } + + Ok(Self { + raw: out, + progress, + progress_payload_ptr, + }) + } + + /// Finalize the pack and index + /// + /// Resolves any pending deltas and writes out the index file. The returned + /// string is the hexadecimal checksum of the packfile, which is also used + /// to name the pack and index files (`pack-.pack` and + /// `pack-.idx` respectively). + pub fn commit(mut self) -> Result { + unsafe { + try_call!(raw::git_indexer_commit( + self.raw, + self.progress.as_mut_ptr() + )); + + let name = CStr::from_ptr(raw::git_indexer_name(self.raw)); + Ok(name.to_str().expect("pack name not utf8").to_owned()) + } + } + + /// The callback through which progress is monitored. Be aware that this is + /// called inline, so performance may be affected. + pub fn progress(&mut self, cb: F) -> &mut Self + where + F: FnMut(Progress<'_>) -> bool + 'a, + { + let progress_payload = + unsafe { &mut *(self.progress_payload_ptr as *mut OdbPackwriterCb<'_>) }; + progress_payload.cb = Some(Box::new(cb) as Box>); + + self + } +} + +impl io::Write for Indexer<'_> { + fn write(&mut self, buf: &[u8]) -> io::Result { + unsafe { + let ptr = buf.as_ptr() as *mut c_void; + let len = buf.len(); + + let res = raw::git_indexer_append(self.raw, ptr, len, self.progress.as_mut_ptr()); + + if res < 0 { + Err(io::Error::new(io::ErrorKind::Other, "Write error")) + } else { + Ok(buf.len()) + } + } + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl Drop for Indexer<'_> { + fn drop(&mut self) { + unsafe { + raw::git_indexer_free(self.raw); + drop(Box::from_raw(self.progress_payload_ptr)) + } + } +} + +#[cfg(test)] +mod tests { + use crate::{Buf, Indexer}; + use std::io::prelude::*; + + #[test] + fn indexer() { + let (_td, repo_source) = crate::test::repo_init(); + let (_td, repo_target) = crate::test::repo_init(); + + let mut progress_called = false; + + // Create an in-memory packfile + let mut builder = t!(repo_source.packbuilder()); + let mut buf = Buf::new(); + let (commit_source_id, _tree) = crate::test::commit(&repo_source); + t!(builder.insert_object(commit_source_id, None)); + t!(builder.write_buf(&mut buf)); + + // Write it to the standard location in the target repo, but via indexer + let odb = repo_source.odb().unwrap(); + let mut indexer = Indexer::new( + Some(&odb), + repo_target.path().join("objects").join("pack").as_path(), + 0o644, + true, + ) + .unwrap(); + indexer.progress(|_| { + progress_called = true; + true + }); + indexer.write(&buf).unwrap(); + indexer.commit().unwrap(); + + // Assert that target repo picks it up as valid + let commit_target = repo_target.find_commit(commit_source_id).unwrap(); + assert_eq!(commit_target.id(), commit_source_id); + assert!(progress_called); + } +} diff --git a/src/lib.rs b/src/lib.rs index 40be0c4b5b..6c33ddbb58 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,7 +98,7 @@ pub use crate::error::Error; pub use crate::index::{ Index, IndexConflict, IndexConflicts, IndexEntries, IndexEntry, IndexMatchedPath, }; -pub use crate::indexer::{IndexerProgress, Progress}; +pub use crate::indexer::{Indexer, IndexerProgress, Progress}; pub use crate::mailmap::Mailmap; pub use crate::mempack::Mempack; pub use crate::merge::{AnnotatedCommit, MergeOptions}; diff --git a/src/odb.rs b/src/odb.rs index 66166913fe..d7ae2b9515 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -1,6 +1,7 @@ use std::io; use std::marker; use std::mem::MaybeUninit; + use std::ptr; use std::slice; @@ -10,6 +11,7 @@ use libc::{c_char, c_int, c_uint, c_void, size_t}; use crate::panic; use crate::util::Binding; + use crate::{ raw, Error, IndexerProgress, Mempack, Object, ObjectType, OdbLookupFlags, Oid, Progress, }; @@ -438,8 +440,8 @@ impl<'repo> io::Write for OdbWriter<'repo> { } } -struct OdbPackwriterCb<'repo> { - cb: Option>>, +pub(crate) struct OdbPackwriterCb<'repo> { + pub(crate) cb: Option>>, } /// A stream to write a packfile to the ODB @@ -542,7 +544,7 @@ extern "C" fn foreach_cb(id: *const raw::git_oid, payload: *mut c_void) -> c_int .unwrap_or(1) } -extern "C" fn write_pack_progress_cb( +pub(crate) extern "C" fn write_pack_progress_cb( stats: *const raw::git_indexer_progress, payload: *mut c_void, ) -> c_int { From 865bf8b45a767ed120c144f9d5ab713cdf3386bb Mon Sep 17 00:00:00 2001 From: Skia Date: Wed, 18 Jan 2023 10:49:43 +0100 Subject: [PATCH 658/860] Bind git_submodule_repo_init --- libgit2-sys/lib.rs | 5 ++++ src/submodule.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index ea66159f0c..e6a5b54da9 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2569,6 +2569,11 @@ extern "C" { pub fn git_submodule_ignore(submodule: *mut git_submodule) -> git_submodule_ignore_t; pub fn git_submodule_index_id(submodule: *mut git_submodule) -> *const git_oid; pub fn git_submodule_init(submodule: *mut git_submodule, overwrite: c_int) -> c_int; + pub fn git_submodule_repo_init( + repo: *mut *mut git_repository, + submodule: *const git_submodule, + use_gitlink: c_int, + ) -> c_int; pub fn git_submodule_location(status: *mut c_uint, submodule: *mut git_submodule) -> c_int; pub fn git_submodule_lookup( out: *mut *mut git_submodule, diff --git a/src/submodule.rs b/src/submodule.rs index d27f61ac36..72b62e6e3e 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -139,6 +139,25 @@ impl<'repo> Submodule<'repo> { Ok(()) } + /// Set up the subrepository for a submodule in preparation for clone. + /// + /// This function can be called to init and set up a submodule repository + /// from a submodule in preparation to clone it from its remote. + + /// use_gitlink: Should the workdir contain a gitlink to the repo in + /// .git/modules vs. repo directly in workdir. + pub fn repo_init(&mut self, use_gitlink: bool) -> Result { + unsafe { + let mut raw_repo = ptr::null_mut(); + try_call!(raw::git_submodule_repo_init( + &mut raw_repo, + self.raw, + use_gitlink + )); + Ok(Binding::from_raw(raw_repo)) + } + } + /// Open the repository for a submodule. /// /// This will only work if the submodule is checked out into the working @@ -399,16 +418,54 @@ mod tests { let (_td, parent) = crate::test::repo_init(); let url1 = Url::from_file_path(&repo1.workdir().unwrap()).unwrap(); - let url3 = Url::from_file_path(&repo2.workdir().unwrap()).unwrap(); + let url2 = Url::from_file_path(&repo2.workdir().unwrap()).unwrap(); let mut s1 = parent .submodule(&url1.to_string(), Path::new("bar"), true) .unwrap(); let mut s2 = parent - .submodule(&url3.to_string(), Path::new("bar2"), true) + .submodule(&url2.to_string(), Path::new("bar2"), true) .unwrap(); // ----------------------------------- t!(s1.clone(Some(&mut SubmoduleUpdateOptions::default()))); t!(s2.clone(None)); } + + #[test] + fn repo_init_submodule() { + // ----------------------------------- + // Same as `clone_submodule()` + let (_td, child) = crate::test::repo_init(); + let (_td, parent) = crate::test::repo_init(); + + let url_child = Url::from_file_path(&child.workdir().unwrap()).unwrap(); + let url_parent = Url::from_file_path(&parent.workdir().unwrap()).unwrap(); + let mut sub = parent + .submodule(&url_child.to_string(), Path::new("bar"), true) + .unwrap(); + + // ----------------------------------- + // Let's commit the submodule for later clone + t!(sub.clone(None)); + t!(sub.add_to_index(true)); + t!(sub.add_finalize()); + + crate::test::commit(&parent); + + // Clone the parent to init its submodules + let td = TempDir::new().unwrap(); + let new_parent = Repository::clone(&url_parent.to_string(), &td).unwrap(); + + let mut submodules = new_parent.submodules().unwrap(); + let child = submodules.first_mut().unwrap(); + + // First init child + t!(child.init(false)); + assert_eq!(child.url().unwrap(), url_child.as_str()); + + // open() is not possible before initializing the repo + assert!(child.open().is_err()); + t!(child.repo_init(true)); + assert!(child.open().is_ok()); + } } From 87934f87d36753ed702792ec063be7246444a8e1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 20 Jan 2023 14:49:52 -0800 Subject: [PATCH 659/860] Update to libgit2 1.5.1 --- Cargo.toml | 4 ++-- README.md | 2 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 8 +++++++- libgit2-sys/libgit2 | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dc5255f4a8..8fc19cabe1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.16.0" +version = "0.16.1" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.14.1" } +libgit2-sys = { path = "libgit2-sys", version = "0.14.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/README.md b/README.md index bf5daf5e47..1a7842a960 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.16" +git2 = "0.16.1" ``` ## Rust version requirements diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index fd3e337f95..43a975948f 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.14.1+1.5.0" +version = "0.14.2+1.5.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 442b196de0..e888b94e16 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,7 +14,13 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.range_version("1.4.4".."1.6.0").probe("libgit2") { + // These version ranges specifically request a version that includes + // the SSH fixes for CVE-2023-22742 (1.5.1+ or 1.4.5+). + if let Ok(lib) = cfg + .range_version("1.5.1".."1.6.0") + .probe("libgit2") + .or_else(|_| cfg.range_version("1.4.5".."1.5.0").probe("libgit2")) + { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index fbea439d4b..42e5db98b9 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit fbea439d4b6fc91c6b619d01b85ab3b7746e4c19 +Subproject commit 42e5db98b963ae503229c63e44e06e439df50e56 From e52897a22a1cfc8c93fce6c6a14aad679fb27881 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 21 Jan 2023 09:06:09 -0800 Subject: [PATCH 660/860] Fix libgit2-sys rerun-if-changed on Windows --- libgit2-sys/build.rs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index e888b94e16..4cd3e1f945 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -205,7 +205,6 @@ fn main() { println!("cargo:rustc-link-lib=rpcrt4"); println!("cargo:rustc-link-lib=ole32"); println!("cargo:rustc-link-lib=crypt32"); - return; } if target.contains("apple") { @@ -214,9 +213,9 @@ fn main() { println!("cargo:rustc-link-lib=framework=CoreFoundation"); } - rerun_if(Path::new("libgit2/include")); - rerun_if(Path::new("libgit2/src")); - rerun_if(Path::new("libgit2/deps")); + println!("cargo:rerun-if-changed=libgit2/include"); + println!("cargo:rerun-if-changed=libgit2/src"); + println!("cargo:rerun-if-changed=libgit2/deps"); } fn cp_r(from: impl AsRef, to: impl AsRef) { @@ -253,13 +252,3 @@ fn add_c_files(build: &mut cc::Build, path: impl AsRef) { } } } - -fn rerun_if(path: &Path) { - if path.is_dir() { - for entry in fs::read_dir(path).expect("read_dir") { - rerun_if(&entry.expect("entry").path()); - } - } else { - println!("cargo:rerun-if-changed={}", path.display()); - } -} From 1d07656cc7463f968a8c9bf334a321c3022947f7 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 21 Jan 2023 14:48:10 -0800 Subject: [PATCH 661/860] Add changelogs --- CHANGELOG.md | 94 ++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 33 +++++++++++++- git2-curl/CHANGELOG.md | 16 +++++++ libgit2-sys/CHANGELOG.md | 92 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md create mode 100644 git2-curl/CHANGELOG.md create mode 100644 libgit2-sys/CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..7843dd3023 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,94 @@ +# Changelog + +## 0.16.1 - 2023-01-20 +[0.16.0...0.16.1](https://github.com/rust-lang/git2-rs/compare/0.16.0...0.16.1) + +### Changed +- Updated to [libgit2-sys 0.14.2+1.5.1](libgit2-sys/CHANGELOG.md#0142151---2023-01-20) + +## 0.16.0 - 2023-01-10 +[0.15.0...0.16.0](https://github.com/rust-lang/git2-rs/compare/0.15.0...0.16.0) + +### Changed +- Added ability to get the SSH host key and its type. + This includes an API breaking change to the `certificate_check` callback. + [#909](https://github.com/rust-lang/git2-rs/pull/909) +- Updated to [libgit2-sys 0.14.1+1.5.0](libgit2-sys/CHANGELOG.md#0141150---2023-01-10) + +## 0.15.0 - 2022-07-28 +[0.14.4...0.15.0](https://github.com/rust-lang/git2-rs/compare/0.14.4...0.15.0) + +### Added +- Added `Repository::tag_annotation_create` binding `git_tag_annotation_create`. + [#845](https://github.com/rust-lang/git2-rs/pull/845) +- Added the `Email` type which represents a patch in mbox format for sending via email. + Added the `EmailCreateOptions` struct to control formatting of the email. + Deprecates `Diff::format_email`, use `Email::from_diff` instead. + [#847](https://github.com/rust-lang/git2-rs/pull/847) +- Added `ErrorCode::Owner` to map to the new `GIT_EOWNER` errors. + [#839](https://github.com/rust-lang/git2-rs/pull/839) +- Added `opts::set_verify_owner_validation` to set whether or not ownership validation is performed. + [#839](https://github.com/rust-lang/git2-rs/pull/839) + +### Changed +- Updated to [libgit2-sys 0.14.0+1.5.0](libgit2-sys/CHANGELOG.md#0140150---2022-07-28) +- Removed the `Iterator` implementation for `ConfigEntries` due to the unsound usage of the API which allowed values to be used after free. + Added `ConfigEntries::next` and `ConfigEntries::for_each` for iterating over all entries in a safe manor. + [#854](https://github.com/rust-lang/git2-rs/pull/854) + +## 0.14.4 - 2022-05-19 +[0.14.3...0.14.4](https://github.com/rust-lang/git2-rs/compare/0.14.3...0.14.4) + +### Added +- Added `Commit::body` and `Commit::body_bytes` for retrieving the commit message body. + [#835](https://github.com/rust-lang/git2-rs/pull/835) +- Added `Tree::get_name_bytes` to handle non-UTF-8 entry names. + [#841](https://github.com/rust-lang/git2-rs/pull/841) + +### Changed +- Updated to [libgit2-sys 0.13.4+1.4.2](libgit2-sys/CHANGELOG.md#0134142---2022-05-10) + +## 0.14.3 - 2022-04-27 +[0.14.2...0.14.3](https://github.com/rust-lang/git2-rs/compare/0.14.2...0.14.3) + +### Changed +- Updated to [libgit2-sys 0.13.3+1.4.2](libgit2-sys/CHANGELOG.md#0133142---2022-04-27) + +### Fixed +- Fixed the lifetime of `Remote::create_detached`. + [#825](https://github.com/rust-lang/git2-rs/pull/825) + +## 0.14.2 - 2022-03-10 +[0.14.1...0.14.2](https://github.com/rust-lang/git2-rs/compare/0.14.1...0.14.2) + +### Added +- Added `Odb::exists_ext` to checks if an object database has an object, with extended flags. + [#818](https://github.com/rust-lang/git2-rs/pull/818) + +### Changed +- Updated to [libgit2-sys 0.13.2+1.4.2](libgit2-sys/CHANGELOG.md#0132142---2022-03-10) + +## 0.14.1 - 2022-02-28 +[0.14.0...0.14.1](https://github.com/rust-lang/git2-rs/compare/0.14.0...0.14.1) + +### Changed +- Updated to [libgit2-sys 0.13.1+1.4.2](libgit2-sys/CHANGELOG.md#0131142---2022-02-28) + +## 0.14.0 - 2022-02-24 +[0.13.25...0.14.0](https://github.com/rust-lang/git2-rs/compare/0.13.25...0.14.0) + +### Added +- Added `opts::get_extensions` and `opts::set_extensions` to support git extensions. + [#791](https://github.com/rust-lang/git2-rs/pull/791) +- Added `PackBuilder::name` and `PackBuilder::name_bytes`. + [#806](https://github.com/rust-lang/git2-rs/pull/806) + - Deprecated `PackBuilder::hash`, use `PackBuilder::name` instead. +- Added `FetchOptions::follow_redirects` and `PushOptions::follow_redirects`. + [#806](https://github.com/rust-lang/git2-rs/pull/806) +- Added `StatusOptions::rename_threshold`. + [#806](https://github.com/rust-lang/git2-rs/pull/806) + +### Changed +- Updated to [libgit2-sys 0.13.0+1.4.1](libgit2-sys/CHANGELOG.md#0130141---2022-02-24) + [#806](https://github.com/rust-lang/git2-rs/pull/806) + [#811](https://github.com/rust-lang/git2-rs/pull/811) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ceb1de44ce..bbbb673a68 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ The following steps can be used to update libgit2: One way is to go to the `libgit2-sys/libgit2` directory and run `git fetch origin` to download the latest updates, and then check out a specific tag (such as `git checkout v1.4.1`). 2. Update all the references to the version: * Update [`libgit2-sys/build.rs`](https://github.com/rust-lang/git2-rs/blob/master/libgit2-sys/build.rs). - There is a version probe (search for `cfg.atleast_version`) which should be updated. + There is a version probe (search for `cfg.range_version`) which should be updated. * Update the version in [`libgit2-sys/Cargo.toml`](https://github.com/rust-lang/git2-rs/blob/master/libgit2-sys/Cargo.toml). Update the metadata portion (the part after the `+`) to match libgit2. @@ -32,3 +32,34 @@ The following steps can be used to update libgit2: The project has recently started labeling API and ABI breaking changes with labels: 4. Once you have everything functional, publish a PR with the updates. + +## Release process + +Checklist for preparing for a release: + +- Make sure the versions have been bumped and are pointing at what is expected. + - Version of `libgit2-sys` + - Version of `git2` + - Version of `git2-curl` + - `git2`'s dependency on `libgit2-sys` + - `git2-curl`'s dependency on `git2` + - The libgit2 version probe in `libgit2-sys/build.rs` + - Update the version in `README.md` + - Check the `html_root_url` values in the source code. +- Update the change logs: + - [`CHANGELOG.md`](https://github.com/rust-lang/git2-rs/blob/master/CHANGELOG.md) + - [`libgit2-sys/CHANGELOG.md`](https://github.com/rust-lang/git2-rs/blob/master/libgit2-sys/CHANGELOG.md) + - [`git2-curl/CHANGELOG.md`](https://github.com/rust-lang/git2-rs/blob/master/git2-curl/CHANGELOG.md) + +To publish the new release: + +- In a fresh clone, make sure you run `git submodule update`. +- For each updated package, run `cargo publish` (`libgit2-sys` then `git2` then `git2-curl`). +- Set tags for each package that was update: + - `git tag 0.16.1` + - `git tag libgit2-sys-0.14.2+1.5.1` + - `git tag git2-curl-0.17.0` +- Push the tags (substitute the "origin" remote name if you are using a different name): + - `git push origin 0.16.1` + - `git push origin libgit2-sys-0.14.2+1.5.1` + - `git push origin git2-curl-0.17.0` diff --git a/git2-curl/CHANGELOG.md b/git2-curl/CHANGELOG.md new file mode 100644 index 0000000000..2ff61cb50a --- /dev/null +++ b/git2-curl/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +## 0.17.0 - 2023-01-10 +[0.16.0...0.17.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.16.0...git2-curl-0.17.0) + +- Updated to [git2 0.16.0](../CHANGELOG.md#0160---2023-01-10) + +## 0.16.0 - 2022-07-28 +[0.15.0...0.16.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.15.0...git2-curl-0.16.0) + +- Updated to [git2 0.15.0](../CHANGELOG.md#0150---2022-07-28) + +## 0.15.0 - 2022-02-28 +[0.14.1...0.15.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.14.1...git2-curl-0.15.0) + +- Updated to [git2 0.14.0](../CHANGELOG.md#0140---2022-02-24) diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md new file mode 100644 index 0000000000..75603b87ec --- /dev/null +++ b/libgit2-sys/CHANGELOG.md @@ -0,0 +1,92 @@ +# Changelog + +## 0.14.2+1.5.1 - 2023-01-20 +[0.14.1...0.14.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.14.1+1.5.0...libgit2-sys-0.14.2+1.5.1) + +### Changed +- Updated the bundled libgit2 to [1.5.1](https://github.com/libgit2/libgit2/releases/tag/v1.5.1). + [a233483a3952d6112653be86fb5ce65267e3d5ac](https://github.com/rust-lang/git2-rs/commit/a233483a3952d6112653be86fb5ce65267e3d5ac) + - Changes: [fbea439d4b6fc91c6b619d01b85ab3b7746e4c19...42e5db98b963ae503229c63e44e06e439df50e56](https://github.com/libgit2/libgit2/compare/fbea439d4b6fc91c6b619d01b85ab3b7746e4c19...42e5db98b963ae503229c63e44e06e439df50e56): + - Fixes [GHSA-8643-3wh5-rmjq](https://github.com/libgit2/libgit2/security/advisories/GHSA-8643-3wh5-rmjq) to validate SSH host keys. + - The supported libgit2 system library range is 1.5.1 to less than 1.6.0 or 1.4.5 to less than 1.5.0, which should include this fix. + +## 0.13.5+1.4.5 - 2023-01-20 +[0.13.4...0.13.5](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.4+1.4.2...libgit2-sys-0.13.5+1.4.5) + +### Changed +- Updated the bundled libgit2 to [1.4.5](https://github.com/libgit2/libgit2/releases/tag/v1.4.5). + - Changes: [2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7...cd6f679af401eda1f172402006ef8265f8bd58ea](https://github.com/libgit2/libgit2/compare/2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7...cd6f679af401eda1f172402006ef8265f8bd58ea): + - Fixes [GHSA-8643-3wh5-rmjq](https://github.com/libgit2/libgit2/security/advisories/GHSA-8643-3wh5-rmjq) to validate SSH host keys. + - The supported libgit2 system library range is 1.4.5 to less than 1.5.0. + +## 0.14.1+1.5.0 - 2023-01-10 +[0.14.0...0.14.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.14.0+1.5.0...libgit2-sys-0.14.1+1.5.0) + +### Added +- Added variants to `git_cert_ssh_raw_type_t`. + [#909](https://github.com/rust-lang/git2-rs/pull/909) + +## 0.14.0+1.5.0 - 2022-07-28 +[0.13.4...0.14.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.4+1.4.2...libgit2-sys-0.14.0+1.5.0) + +### Added +- Added bindings for ownership validation. + [#839](https://github.com/rust-lang/git2-rs/pull/839) + +### Changed + +- Updated the bundled libgit2 to [1.5.0](https://github.com/libgit2/libgit2/releases/tag/v1.5.0). + [#839](https://github.com/rust-lang/git2-rs/pull/839) + [#858](https://github.com/rust-lang/git2-rs/pull/858) + - Changes: [2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7...fbea439d4b6fc91c6b619d01b85ab3b7746e4c19](https://github.com/libgit2/libgit2/compare/2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7...fbea439d4b6fc91c6b619d01b85ab3b7746e4c19): + - The supported libgit2 system library range is 1.4.4 to less than 1.6.0. + - Fixes [CVE 2022-24765](https://github.com/libgit2/libgit2/releases/tag/v1.4.3). + +## 0.13.4+1.4.2 - 2022-05-10 +[0.13.3...0.13.4](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.3+1.4.2...libgit2-sys-0.13.4+1.4.2) + +### Added +- Added bindings for `git_commit_body` + [#835](https://github.com/rust-lang/git2-rs/pull/835) + +## 0.13.3+1.4.2 - 2022-04-27 +[0.13.2...0.13.3](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.2+1.4.2...libgit2-sys-0.13.3+1.4.2) + +### Changed +- Updated the bundled libgit2 to 1.5.0-alpha. + [#822](https://github.com/rust-lang/git2-rs/pull/822) + - Changes: [182d0d1ee933de46bf0b5a6ec269bafa77aba9a2...2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7](https://github.com/libgit2/libgit2/compare/182d0d1ee933de46bf0b5a6ec269bafa77aba9a2...2a0d0bd19b5d13e2ab7f3780e094404828cbb9a7) +- Changed the pkg-config probe to restrict linking against a version of a system-installed libgit2 to a version less than 1.5.0. + Previously it would allow any version above 1.4.0 which could pick up an API-breaking version. + [#817](https://github.com/rust-lang/git2-rs/pull/817) +- When using pkg-config to locate libgit2, the system lib dirs are no longer added to the search path. + [#831](https://github.com/rust-lang/git2-rs/pull/831) +- When using the `zlib-ng-compat` Cargo feature, `libssh2-sys` is no longer automatically included unless you also enable the `ssh` feature. + [#833](https://github.com/rust-lang/git2-rs/pull/833) + +## 0.13.2+1.4.2 - 2022-03-10 +[0.13.1...0.13.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.1+1.4.2...libgit2-sys-0.13.2+1.4.2) + +### Added +- Added bindings for `git_odb_exists_ext`. + [#818](https://github.com/rust-lang/git2-rs/pull/818) + +## 0.13.1+1.4.2 - 2022-02-28 +[0.13.0...0.13.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.13.0+1.4.1...libgit2-sys-0.13.1+1.4.2) + +### Changed +- Updated the bundled libgit2 to [1.4.2](https://github.com/libgit2/libgit2/releases/tag/v1.4.2). + [#815](https://github.com/rust-lang/git2-rs/pull/815) + - Changes: [fdd15bcfca6b2ec4b7ecad1aa11a396cb15bd064...182d0d1ee933de46bf0b5a6ec269bafa77aba9a2](https://github.com/libgit2/libgit2/compare/fdd15bcfca6b2ec4b7ecad1aa11a396cb15bd064...182d0d1ee933de46bf0b5a6ec269bafa77aba9a2). + +## 0.13.0+1.4.1 - 2022-02-24 +[0.12.26...0.13.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.12.26+1.3.0...libgit2-sys-0.13.0+1.4.1) + +### Changed +- Changed libgit2-sys to use the presence of the `src` directory instead of `.git` to determine if it has a git submodule that needs updating. + [#801](https://github.com/rust-lang/git2-rs/pull/801) +- Updated the bundled libgit2 to [1.4.1](https://github.com/libgit2/libgit2/releases/tag/v1.4.1) (see also [1.4.0](https://github.com/libgit2/libgit2/releases/tag/v1.4.0)) + [#806](https://github.com/rust-lang/git2-rs/pull/806) + [#811](https://github.com/rust-lang/git2-rs/pull/811) + - Changes: [b7bad55e4bb0a285b073ba5e02b01d3f522fc95d...fdd15bcfca6b2ec4b7ecad1aa11a396cb15bd064](https://github.com/libgit2/libgit2/compare/b7bad55e4bb0a285b073ba5e02b01d3f522fc95d...fdd15bcfca6b2ec4b7ecad1aa11a396cb15bd064) + - The supported libgit2 system library range is 1.4.0 or greater. From 50dcbe0963e07aa10a13ade3390e43049c78aba0 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 21 Jan 2023 15:59:55 -0800 Subject: [PATCH 662/860] Use correct class for credentials_cb error The first parameter of `git_error_set_str` is supposed to be an error class, not the raw error code. The main consequence is that the error message should show the class code instead of the error code (which would usually just be GIT_ERROR). --- src/remote_callbacks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index fe1802273b..e68f112acf 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -290,7 +290,7 @@ extern "C" fn credentials_cb( callback(url, username_from_url, cred_type).map_err(|e| { let s = CString::new(e.to_string()).unwrap(); - raw::git_error_set_str(e.raw_code() as c_int, s.as_ptr()); + raw::git_error_set_str(e.class() as c_int, s.as_ptr()); e.raw_code() as c_int }) }); From 68b12efd6463c57deff56f4f7488a042461049d3 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Sat, 21 Jan 2023 16:38:36 -0800 Subject: [PATCH 663/860] Update to libssh2-sys 0.3.0 --- libgit2-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 43a975948f..f4640b9b9a 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -22,7 +22,7 @@ path = "lib.rs" [dependencies] libc = "0.2" -libssh2-sys = { version = "0.2.19", optional = true } +libssh2-sys = { version = "0.3.0", optional = true } libz-sys = { version = "1.1.0", default-features = false, features = ["libc"] } [build-dependencies] From a3eae1ed124cbce761d7ba69628ca8296101ca69 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 22 Jan 2023 08:44:26 -0800 Subject: [PATCH 664/860] Add docs about Repository::index ownership. --- src/repo.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index a2f3745555..2febfffe93 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1012,6 +1012,11 @@ impl Repository { /// /// If a custom index has not been set, the default index for the repository /// will be returned (the one located in .git/index). + /// + /// **Caution**: If the [`Repository`] of this index is dropped, then this + /// [`Index`] will become detached, and most methods on it will fail. See + /// [`Index::open`]. Be sure the repository has a binding such as a local + /// variable to keep it alive at least as long as the index. pub fn index(&self) -> Result { let mut raw = ptr::null_mut(); unsafe { From 1bd987e08d13c95e69d1a3e30ac0384b3fcb242a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 22 Jan 2023 08:48:36 -0800 Subject: [PATCH 665/860] Fix intra-doc link for CertificateCheckStatus CertificateCheck is private, so use the proper link. --- src/remote_callbacks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index fe1802273b..c3a8bfdc5a 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -54,7 +54,7 @@ pub type UpdateTips<'a> = dyn FnMut(&str, Oid, Oid) -> bool + 'a; pub type CertificateCheck<'a> = dyn FnMut(&Cert<'_>, &str) -> Result + 'a; -/// The return value for the [`CertificateCheck`] callback. +/// The return value for the [`RemoteCallbacks::certificate_check`] callback. pub enum CertificateCheckStatus { /// Indicates that the certificate should be accepted. CertificateOk, From 17cd326c5daaea76e444b48fadf734ed02793bd9 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 23 Jan 2023 09:46:46 -0800 Subject: [PATCH 666/860] Fix some spelling issues --- src/build.rs | 12 ++++++------ src/config.rs | 10 +++++----- src/cred.rs | 8 ++++---- src/diff.rs | 4 ++-- src/error.rs | 6 +++--- src/index.rs | 2 +- src/lib.rs | 12 ++++++------ src/odb.rs | 4 ++-- src/oid_array.rs | 2 +- src/opts.rs | 2 +- src/remote.rs | 10 +++++----- src/remote_callbacks.rs | 6 +++--- src/repo.rs | 12 ++++++------ src/revwalk.rs | 2 +- src/string_array.rs | 2 +- src/submodule.rs | 8 ++++---- src/tracing.rs | 2 +- src/transaction.rs | 8 ++++---- src/transport.rs | 2 +- src/tree.rs | 10 +++++----- src/util.rs | 2 +- src/worktree.rs | 2 +- 22 files changed, 64 insertions(+), 64 deletions(-) diff --git a/src/build.rs b/src/build.rs index 5b5cd15a31..a822f0822e 100644 --- a/src/build.rs +++ b/src/build.rs @@ -60,7 +60,7 @@ pub struct RepoBuilder<'cb> { /// Type of callback passed to `RepoBuilder::remote_create`. /// -/// The second and third arguments are the remote's name and the remote's url. +/// The second and third arguments are the remote's name and the remote's URL. pub type RemoteCreate<'cb> = dyn for<'a> FnMut(&'a Repository, &str, &str) -> Result, Error> + 'cb; @@ -89,7 +89,7 @@ pub struct CheckoutBuilder<'cb> { /// Checkout progress notification callback. /// -/// The first argument is the path for the notification, the next is the numver +/// The first argument is the path for the notification, the next is the number /// of completed steps so far, and the final is the total number of steps. pub type Progress<'a> = dyn FnMut(Option<&Path>, usize, usize) + 'a; @@ -121,10 +121,10 @@ pub enum CloneLocal { /// Auto-detect (default) /// /// Here libgit2 will bypass the git-aware transport for local paths, but - /// use a normal fetch for `file://` urls. + /// use a normal fetch for `file://` URLs. Auto = raw::GIT_CLONE_LOCAL_AUTO as isize, - /// Bypass the git-aware transport even for `file://` urls. + /// Bypass the git-aware transport even for `file://` URLs. Local = raw::GIT_CLONE_LOCAL as isize, /// Never bypass the git-aware transport @@ -230,7 +230,7 @@ impl<'cb> RepoBuilder<'cb> { /// Clone a remote repository. /// - /// This will use the options configured so far to clone the specified url + /// This will use the options configured so far to clone the specified URL /// into the specified local path. pub fn clone(&mut self, url: &str, into: &Path) -> Result { let mut opts: raw::git_clone_options = unsafe { mem::zeroed() }; @@ -354,7 +354,7 @@ impl<'cb> CheckoutBuilder<'cb> { } /// Indicate that the checkout should be performed safely, allowing new - /// files to be created but not overwriting extisting files or changes. + /// files to be created but not overwriting existing files or changes. /// /// This is the default. pub fn safe(&mut self) -> &mut CheckoutBuilder<'cb> { diff --git a/src/config.rs b/src/config.rs index 580af833ae..ae5c4ff63a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -108,7 +108,7 @@ impl Config { /// exists. The returned path may be used on any method call to load /// the global configuration file. /// - /// This method will not guess the path to the xdg compatible config file + /// This method will not guess the path to the XDG compatible config file /// (`.config/git/config`). pub fn find_global() -> Result { crate::init(); @@ -121,7 +121,7 @@ impl Config { /// Locate the path to the system configuration file /// - /// If /etc/gitconfig doesn't exist, it will look for %PROGRAMFILES% + /// If /etc/gitconfig doesn't exist, it will look for `%PROGRAMFILES%` pub fn find_system() -> Result { crate::init(); let buf = Buf::new(); @@ -131,9 +131,9 @@ impl Config { Ok(util::bytes2path(&buf).to_path_buf()) } - /// Locate the path to the global xdg compatible configuration file + /// Locate the path to the global XDG compatible configuration file /// - /// The xdg compatible configuration file is usually located in + /// The XDG compatible configuration file is usually located in /// `$HOME/.config/git/config`. pub fn find_xdg() -> Result { crate::init(); @@ -369,7 +369,7 @@ impl Config { /// Open the global/XDG configuration file according to git's rules /// /// Git allows you to store your global configuration at `$HOME/.config` or - /// `$XDG_CONFIG_HOME/git/config`. For backwards compatability, the XDG file + /// `$XDG_CONFIG_HOME/git/config`. For backwards compatibility, the XDG file /// shouldn't be used unless the use has created it explicitly. With this /// function you'll open the correct one to write to. pub fn open_global(&mut self) -> Result { diff --git a/src/cred.rs b/src/cred.rs index fdffd61540..72d9485e82 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -113,7 +113,7 @@ impl Cred { /// /// This function will attempt to parse the user's `credential.helper` /// configuration, invoke the necessary processes, and read off what the - /// username/password should be for a particular url. + /// username/password should be for a particular URL. /// /// The returned credential type will be a username/password credential if /// successful. @@ -140,7 +140,7 @@ impl Cred { /// Create a credential to specify a username. /// /// This is used with ssh authentication to query for the username if none is - /// specified in the url. + /// specified in the URL. pub fn username(username: &str) -> Result { crate::init(); let username = CString::new(username)?; @@ -194,8 +194,8 @@ impl CredentialHelper { /// Create a new credential helper object which will be used to probe git's /// local credential configuration. /// - /// The url specified is the namespace on which this will query credentials. - /// Invalid urls are currently ignored. + /// The URL specified is the namespace on which this will query credentials. + /// Invalid URLs are currently ignored. pub fn new(url: &str) -> CredentialHelper { let mut ret = CredentialHelper { protocol: None, diff --git a/src/diff.rs b/src/diff.rs index 3d5b42d9dc..4dc895fa1b 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -286,7 +286,7 @@ impl<'repo> Diff<'repo> { Ok(buf) } - /// Create an patchid from a diff. + /// Create an patch ID from a diff. pub fn patchid(&self, opts: Option<&mut DiffPatchidOptions>) -> Result { let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], @@ -310,7 +310,7 @@ impl Diff<'static> { /// produced if you actually produced it computationally by comparing /// two trees, however there may be subtle differences. For example, /// a patch file likely contains abbreviated object IDs, so the - /// object IDs parsed by this function will also be abreviated. + /// object IDs parsed by this function will also be abbreviated. pub fn from_buffer(buffer: &[u8]) -> Result, Error> { crate::init(); let mut diff: *mut raw::git_diff = std::ptr::null_mut(); diff --git a/src/error.rs b/src/error.rs index 779d785adf..6f1c4d4c78 100644 --- a/src/error.rs +++ b/src/error.rs @@ -18,7 +18,7 @@ pub struct Error { impl Error { /// Creates a new error. /// - /// This is mainly intended for implementors of custom transports or + /// This is mainly intended for implementers of custom transports or /// database backends, where it is desirable to propagate an [`Error`] /// through `libgit2`. pub fn new>(code: ErrorCode, class: ErrorClass, message: S) -> Self { @@ -134,7 +134,7 @@ impl Error { /// Modify the error code associated with this error. /// - /// This is mainly intended to be used by implementors of custom transports + /// This is mainly intended to be used by implementers of custom transports /// or database backends, and should be used with care. pub fn set_code(&mut self, code: ErrorCode) { self.code = match code { @@ -216,7 +216,7 @@ impl Error { /// Modify the error class associated with this error. /// - /// This is mainly intended to be used by implementors of custom transports + /// This is mainly intended to be used by implementers of custom transports /// or database backends, and should be used with care. pub fn set_class(&mut self, class: ErrorClass) { self.klass = match class { diff --git a/src/index.rs b/src/index.rs index b2e8dfe5c1..f5ddd566ee 100644 --- a/src/index.rs +++ b/src/index.rs @@ -45,7 +45,7 @@ pub struct IndexConflict { /// A callback function to filter index matches. /// /// Used by `Index::{add_all,remove_all,update_all}`. The first argument is the -/// path, and the second is the patchspec that matched it. Return 0 to confirm +/// path, and the second is the pathspec that matched it. Return 0 to confirm /// the operation on the item, > 0 to skip the item, and < 0 to abort the scan. pub type IndexMatchedPath<'a> = dyn FnMut(&Path, &[u8]) -> i32 + 'a; diff --git a/src/lib.rs b/src/lib.rs index 40be0c4b5b..77cb523d15 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -249,7 +249,7 @@ pub enum ErrorClass { Object, /// Network error Net, - /// Error manpulating a tag + /// Error manipulating a tag Tag, /// Invalid value in tree Tree, @@ -257,7 +257,7 @@ pub enum ErrorClass { Indexer, /// Error from SSL Ssl, - /// Error involing submodules + /// Error involving submodules Submodule, /// Threading error Thread, @@ -349,7 +349,7 @@ pub enum ObjectType { Tag, } -/// An enumeration of all possile kinds of references. +/// An enumeration of all possible kinds of references. #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum ReferenceType { /// A reference which points at an object id. @@ -1172,7 +1172,7 @@ bitflags! { /// /// Lastly, the following will only be returned for ignore "NONE". /// - /// * WD_UNTRACKED - wd contains untracked files + /// * WD_UNTRACKED - workdir contains untracked files pub struct SubmoduleStatus: u32 { #[allow(missing_docs)] const IN_HEAD = raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32; @@ -1273,7 +1273,7 @@ bitflags! { /// Use the default pathspec matching configuration. const DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32; /// Force matching to ignore case, otherwise matching will use native - /// case sensitivity fo the platform filesystem. + /// case sensitivity of the platform filesystem. const IGNORE_CASE = raw::GIT_PATHSPEC_IGNORE_CASE as u32; /// Force case sensitive matches, otherwise match will use the native /// case sensitivity of the platform filesystem. @@ -1521,7 +1521,7 @@ bitflags! { pub struct ReferenceFormat: u32 { /// No particular normalization. const NORMAL = raw::GIT_REFERENCE_FORMAT_NORMAL as u32; - /// Constrol whether one-level refname are accepted (i.e., refnames that + /// Control whether one-level refname are accepted (i.e., refnames that /// do not contain multiple `/`-separated components). Those are /// expected to be written only using uppercase letters and underscore /// (e.g. `HEAD`, `FETCH_HEAD`). diff --git a/src/odb.rs b/src/odb.rs index 66166913fe..bb6879f77c 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -240,7 +240,7 @@ impl<'repo> Odb<'repo> { /// deletion of the mempack backend. /// /// Here is an example that fails to compile because it tries to hold the - /// mempack reference beyond the odb's lifetime: + /// mempack reference beyond the Odb's lifetime: /// /// ```compile_fail /// use git2::Odb; @@ -388,7 +388,7 @@ impl<'repo> OdbWriter<'repo> { /// This method can be used to finalize writing object to the database and get an identifier. /// The object will take its final name and will be available to the odb. /// This method will fail if the total number of received bytes differs from the size declared with odb_writer() - /// Attepting write after finishing will be ignored. + /// Attempting write after finishing will be ignored. pub fn finalize(&mut self) -> Result { let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], diff --git a/src/oid_array.rs b/src/oid_array.rs index 1640aaa221..0d87ce9954 100644 --- a/src/oid_array.rs +++ b/src/oid_array.rs @@ -10,7 +10,7 @@ use std::slice; /// An oid array structure used by libgit2 /// -/// Some apis return arrays of oids which originate from libgit2. This +/// Some APIs return arrays of OIDs which originate from libgit2. This /// wrapper type behaves a little like `Vec<&Oid>` but does so without copying /// the underlying Oids until necessary. pub struct OidArray { diff --git a/src/opts.rs b/src/opts.rs index c9c1c3e265..e90bea0b12 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -181,7 +181,7 @@ where Ok(()) } -/// Set wheter or not to verify ownership before performing a repository. +/// Set whether or not to verify ownership before performing a repository. /// Enabled by default, but disabling this can lead to code execution vulnerabilities. pub unsafe fn set_verify_owner_validation(enabled: bool) -> Result<(), Error> { crate::init(); diff --git a/src/remote.rs b/src/remote.rs index d2a73858f7..5ef38ee78e 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -97,7 +97,7 @@ impl<'repo> Remote<'repo> { /// Create a detached remote /// - /// Create a remote with the given url in-memory. You can use this + /// Create a remote with the given URL in-memory. You can use this /// when you have a URL instead of a remote's name. /// Contrasted with an anonymous remote, a detached remote will not /// consider any repo configuration values. @@ -126,14 +126,14 @@ impl<'repo> Remote<'repo> { unsafe { crate::opt_bytes(self, raw::git_remote_name(&*self.raw)) } } - /// Get the remote's url. + /// Get the remote's URL. /// - /// Returns `None` if the url is not valid utf-8 + /// Returns `None` if the URL is not valid utf-8 pub fn url(https://github.com/&self) -> Option<&str> { str::from_utf8(self.url_bytes()).ok() } - /// Get the remote's url as a byte array. + /// Get the remote's URL as a byte array. pub fn url_bytes(&self) -> &[u8] { unsafe { crate::opt_bytes(self, raw::git_remote_url(https://github.com/&*self.raw)).unwrap() } } @@ -246,7 +246,7 @@ impl<'repo> Remote<'repo> { /// Cancel the operation /// /// At certain points in its operation, the network code checks whether the - /// operation has been cancelled and if so stops the operation. + /// operation has been canceled and if so stops the operation. pub fn stop(&mut self) -> Result<(), Error> { unsafe { try_call!(raw::git_remote_stop(self.raw)); diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index fe1802273b..7bb58851a0 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -30,9 +30,9 @@ pub struct RemoteCallbacks<'a> { /// Callback used to acquire credentials for when a remote is fetched. /// /// * `url` - the resource for which the credentials are required. -/// * `username_from_url` - the username that was embedded in the url, or `None` +/// * `username_from_url` - the username that was embedded in the URL, or `None` /// if it was not included. -/// * `allowed_types` - a bitmask stating which cred types are ok to return. +/// * `allowed_types` - a bitmask stating which cred types are OK to return. pub type Credentials<'a> = dyn FnMut(&str, Option<&str>, CredentialType) -> Result + 'a; @@ -46,7 +46,7 @@ pub type UpdateTips<'a> = dyn FnMut(&str, Oid, Oid) -> bool + 'a; /// Callback for a custom certificate check. /// -/// The first argument is the certificate receved on the connection. +/// The first argument is the certificate received on the connection. /// Certificates are typically either an SSH or X509 certificate. /// /// The second argument is the hostname for the connection is passed as the last diff --git a/src/repo.rs b/src/repo.rs index a2f3745555..1fc550faca 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -626,7 +626,7 @@ impl Repository { /// Create an anonymous remote /// - /// Create a remote with the given url and refspec in memory. You can use + /// Create a remote with the given URL and refspec in memory. You can use /// this when you have a URL instead of a remote's name. Note that anonymous /// remotes cannot be converted to persisted remotes. pub fn remote_anonymous(&self, url: &str) -> Result, Error> { @@ -707,7 +707,7 @@ impl Repository { Ok(()) } - /// Set the remote's url in the configuration + /// Set the remote's URL in the configuration /// /// Remote objects already in memory will not be affected. This assumes /// the common case of a single-url remote and will otherwise return an @@ -721,7 +721,7 @@ impl Repository { Ok(()) } - /// Set the remote's url for pushing in the configuration. + /// Set the remote's URL for pushing in the configuration. /// /// Remote objects already in memory will not be affected. This assumes /// the common case of a single-url remote and will otherwise return an @@ -1211,7 +1211,7 @@ impl Repository { /// /// This behaves like `Repository::branch()` but takes /// an annotated commit, which lets you specify which - /// extended sha syntax string was specified by a user, + /// extended SHA syntax string was specified by a user, /// allowing for more exact reflog messages. /// /// See the documentation for `Repository::branch()` @@ -3154,7 +3154,7 @@ impl Repository { /// `callback` will be called with with following arguments: /// /// - `&str`: the reference name - /// - `&[u8]`: the remote url + /// - `&[u8]`: the remote URL /// - `&Oid`: the reference target OID /// - `bool`: was the reference the result of a merge pub fn fetchhead_foreach(&self, mut callback: C) -> Result<(), Error> @@ -3283,7 +3283,7 @@ impl RepositoryInitOptions { /// The path to the working directory. /// - /// If this is a relative path it will be evaulated relative to the repo + /// If this is a relative path it will be evaluated relative to the repo /// path. If this is not the "natural" working directory, a .git gitlink /// file will be created here linking to the repo path. pub fn workdir_path(&mut self, path: &Path) -> &mut RepositoryInitOptions { diff --git a/src/revwalk.rs b/src/revwalk.rs index eec940f4b9..04cf3f3e4f 100644 --- a/src/revwalk.rs +++ b/src/revwalk.rs @@ -12,7 +12,7 @@ pub struct Revwalk<'repo> { _marker: marker::PhantomData<&'repo Repository>, } -/// A `Revwalk` with an assiciated "hide callback", see `with_hide_callback` +/// A `Revwalk` with an associated "hide callback", see `with_hide_callback` pub struct RevwalkWithHideCb<'repo, 'cb, C> where C: FnMut(Oid) -> bool, diff --git a/src/string_array.rs b/src/string_array.rs index 5c20d8c87e..1aa6fbb411 100644 --- a/src/string_array.rs +++ b/src/string_array.rs @@ -8,7 +8,7 @@ use crate::util::Binding; /// A string array structure used by libgit2 /// -/// Some apis return arrays of strings which originate from libgit2. This +/// Some APIs return arrays of strings which originate from libgit2. This /// wrapper type behaves a little like `Vec<&str>` but does so without copying /// the underlying strings until necessary. pub struct StringArray { diff --git a/src/submodule.rs b/src/submodule.rs index 72b62e6e3e..06a6359400 100644 --- a/src/submodule.rs +++ b/src/submodule.rs @@ -52,21 +52,21 @@ impl<'repo> Submodule<'repo> { } } - /// Get the submodule's url. + /// Get the submodule's URL. /// - /// Returns `None` if the url is not valid utf-8 or if the URL isn't present + /// Returns `None` if the URL is not valid utf-8 or if the URL isn't present pub fn url(https://github.com/&self) -> Option<&str> { self.opt_url_bytes().and_then(|b| str::from_utf8(b).ok()) } - /// Get the url for the submodule. + /// Get the URL for the submodule. #[doc(hidden)] #[deprecated(note = "renamed to `opt_url_bytes`")] pub fn url_bytes(&self) -> &[u8] { self.opt_url_bytes().unwrap() } - /// Get the url for the submodule. + /// Get the URL for the submodule. /// /// Returns `None` if the URL isn't present // TODO: delete this method and fix the signature of `url_bytes` on next diff --git a/src/tracing.rs b/src/tracing.rs index 691410cfc3..5acae8a850 100644 --- a/src/tracing.rs +++ b/src/tracing.rs @@ -59,7 +59,7 @@ impl Binding for TraceLevel { //TODO: pass raw &[u8] and leave conversion to consumer (breaking API) /// Callback type used to pass tracing events to the subscriber. -/// see `trace_set` to register a scubscriber. +/// see `trace_set` to register a subscriber. pub type TracingCb = fn(TraceLevel, &str); static CALLBACK: AtomicUsize = AtomicUsize::new(0); diff --git a/src/transaction.rs b/src/transaction.rs index 80cb4dfe0f..4f661f1d48 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -7,7 +7,7 @@ use crate::{raw, util::Binding, Error, Oid, Reflog, Repository, Signature}; /// /// Transactions work by locking loose refs for as long as the [`Transaction`] /// is held, and committing all changes to disk when [`Transaction::commit`] is -/// called. Note that comitting is not atomic: if an operation fails, the +/// called. Note that committing is not atomic: if an operation fails, the /// transaction aborts, but previous successful operations are not rolled back. pub struct Transaction<'repo> { raw: *mut raw::git_transaction, @@ -106,11 +106,11 @@ impl<'repo> Transaction<'repo> { /// Add a [`Reflog`] to the transaction. /// /// This commit the in-memory [`Reflog`] to disk when the transaction commits. - /// Note that atomicty is **not* guaranteed: if the transaction fails to - /// modify `refname`, the reflog may still have been comitted to disk. + /// Note that atomicity is **not* guaranteed: if the transaction fails to + /// modify `refname`, the reflog may still have been committed to disk. /// /// If this is combined with setting the target, that update won't be - /// written to the log (ie. the `reflog_signature` and `reflog_message` + /// written to the log (i.e. the `reflog_signature` and `reflog_message` /// parameters will be ignored). pub fn set_reflog(&mut self, refname: &str, reflog: Reflog) -> Result<(), Error> { let refname = CString::new(refname).unwrap(); diff --git a/src/transport.rs b/src/transport.rs index 6872907847..5d46959486 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -25,7 +25,7 @@ pub struct Transport { /// Interface used by smart transports. /// -/// The full-fledged definiton of transports has to deal with lots of +/// The full-fledged definition of transports has to deal with lots of /// nitty-gritty details of the git protocol, but "smart transports" largely /// only need to deal with read() and write() of data over a channel. /// diff --git a/src/tree.rs b/src/tree.rs index 6fe72d8192..2a117b4ca1 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -36,9 +36,9 @@ pub struct TreeIter<'tree> { /// A binary indicator of whether a tree walk should be performed in pre-order /// or post-order. pub enum TreeWalkMode { - /// Runs the traversal in pre order. + /// Runs the traversal in pre-order. PreOrder = 0, - /// Runs the traversal in post order. + /// Runs the traversal in post-order. PostOrder = 1, } @@ -94,12 +94,12 @@ impl<'repo> Tree<'repo> { } } - /// Traverse the entries in a tree and its subtrees in post or pre order. + /// Traverse the entries in a tree and its subtrees in post or pre-order. /// The callback function will be run on each node of the tree that's /// walked. The return code of this function will determine how the walk /// continues. /// - /// libgit requires that the callback be an integer, where 0 indicates a + /// libgit2 requires that the callback be an integer, where 0 indicates a /// successful visit, 1 skips the node, and -1 aborts the traversal completely. /// You may opt to use the enum [`TreeWalkResult`](TreeWalkResult) instead. /// @@ -113,7 +113,7 @@ impl<'repo> Tree<'repo> { /// assert_eq!(ct, 1); /// ``` /// - /// See [libgit documentation][1] for more information. + /// See [libgit2 documentation][1] for more information. /// /// [1]: https://libgit2.org/libgit2/#HEAD/group/tree/git_tree_walk pub fn walk(&self, mode: TreeWalkMode, mut callback: C) -> Result<(), Error> diff --git a/src/util.rs b/src/util.rs index 1c6001ddbf..5f735bc004 100644 --- a/src/util.rs +++ b/src/util.rs @@ -199,7 +199,7 @@ pub fn c_cmp_to_ordering(cmp: c_int) -> Ordering { /// /// Checks if it is a relative path. /// -/// On Windows, this also requires the path to be valid unicode, and translates +/// On Windows, this also requires the path to be valid Unicode, and translates /// back slashes to forward slashes. pub fn path_to_repo_path(path: &Path) -> Result { macro_rules! err { diff --git a/src/worktree.rs b/src/worktree.rs index 3cb75c6edf..569b639cf9 100644 --- a/src/worktree.rs +++ b/src/worktree.rs @@ -218,7 +218,7 @@ impl WorktreePruneOptions { self.flag(raw::GIT_WORKTREE_PRUNE_LOCKED, locked) } - /// Controls whether the actual working tree on the fs is recursively removed + /// Controls whether the actual working tree on the filesystem is recursively removed /// /// Defaults to false pub fn working_tree(&mut self, working_tree: bool) -> &mut WorktreePruneOptions { From 75064253ea21b9f9888bde0e58eeceaf126ea4bd Mon Sep 17 00:00:00 2001 From: Sanjay <30881+sanjayts@users.noreply.github.com> Date: Tue, 13 Sep 2022 19:30:58 +0100 Subject: [PATCH 667/860] Add bindings for git_reference_name_is_valid, git_remote_name_is_valid & git_tag_name_is_valid --- libgit2-sys/lib.rs | 3 +++ src/reference.rs | 28 +++++++++++++++++++++++----- src/remote.rs | 20 +++++++++++++++++--- src/tag.rs | 40 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 82 insertions(+), 9 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a113a29526..226d6d6ea0 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2247,6 +2247,7 @@ extern "C" { ) -> c_int; pub fn git_remote_get_refspec(remote: *const git_remote, n: size_t) -> *const git_refspec; pub fn git_remote_is_valid_name(remote_name: *const c_char) -> c_int; + pub fn git_remote_name_is_valid(valid: *mut c_int, remote_name: *const c_char) -> c_int; pub fn git_remote_list(out: *mut git_strarray, repo: *mut git_repository) -> c_int; pub fn git_remote_rename( problems: *mut git_strarray, @@ -2398,6 +2399,7 @@ extern "C" { pub fn git_reference_is_remote(r: *const git_reference) -> c_int; pub fn git_reference_is_tag(r: *const git_reference) -> c_int; pub fn git_reference_is_valid_name(name: *const c_char) -> c_int; + pub fn git_reference_name_is_valid(valid: *mut c_int, refname: *const c_char) -> c_int; pub fn git_reference_lookup( out: *mut *mut git_reference, repo: *mut git_repository, @@ -3209,6 +3211,7 @@ extern "C" { pub fn git_tag_target(target_out: *mut *mut git_object, tag: *const git_tag) -> c_int; pub fn git_tag_target_id(tag: *const git_tag) -> *const git_oid; pub fn git_tag_target_type(tag: *const git_tag) -> git_object_t; + pub fn git_tag_name_is_valid(valid: *mut c_int, tag_name: *const c_char) -> c_int; // checkout pub fn git_checkout_head(repo: *mut git_repository, opts: *const git_checkout_options) diff --git a/src/reference.rs b/src/reference.rs index 479252a5cc..2af92edde4 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -8,8 +8,8 @@ use std::str; use crate::object::CastOrPanic; use crate::util::{c_cmp_to_ordering, Binding}; use crate::{ - raw, Blob, Commit, Error, Object, ObjectType, Oid, ReferenceFormat, ReferenceType, Repository, - Tag, Tree, + call, raw, Blob, Commit, Error, Object, ObjectType, Oid, ReferenceFormat, ReferenceType, + Repository, Tag, Tree, }; // Not in the public header files (yet?), but a hard limit used by libgit2 @@ -62,7 +62,15 @@ impl<'repo> Reference<'repo> { pub fn is_valid_name(refname: &str) -> bool { crate::init(); let refname = CString::new(refname).unwrap(); - unsafe { raw::git_reference_is_valid_name(refname.as_ptr()) == 1 } + let mut valid: libc::c_int = 0; + unsafe { + call::c_try(raw::git_reference_name_is_valid( + &mut valid, + refname.as_ptr(), + )) + .unwrap(); + } + valid == 1 } /// Normalize reference name and check validity. @@ -463,13 +471,23 @@ mod tests { use crate::{ObjectType, Reference, ReferenceType}; #[test] - fn smoke() { + fn is_valid_name() { assert!(Reference::is_valid_name("refs/foo")); assert!(!Reference::is_valid_name("foo")); + assert!(Reference::is_valid_name("FOO_BAR")); + + assert!(!Reference::is_valid_name("foo")); + assert!(!Reference::is_valid_name("_FOO_BAR")); } #[test] - fn smoke2() { + #[should_panic] + fn is_valid_name_for_invalid_ref() { + Reference::is_valid_name("ab\012"); + } + + #[test] + fn smoke() { let (_td, repo) = crate::test::repo_init(); let mut head = repo.head().unwrap(); assert!(head.is_branch()); diff --git a/src/remote.rs b/src/remote.rs index d2a73858f7..7418d1159d 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -10,7 +10,7 @@ use std::{ffi::CString, os::raw::c_char}; use crate::string_array::StringArray; use crate::util::Binding; -use crate::{raw, Buf, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec}; +use crate::{call, raw, Buf, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec}; use crate::{AutotagOption, Progress, RemoteCallbacks, Repository}; /// A structure representing a [remote][1] of a git repository. @@ -92,7 +92,15 @@ impl<'repo> Remote<'repo> { pub fn is_valid_name(remote_name: &str) -> bool { crate::init(); let remote_name = CString::new(remote_name).unwrap(); - unsafe { raw::git_remote_is_valid_name(remote_name.as_ptr()) == 1 } + let mut valid: libc::c_int = 0; + unsafe { + call::c_try(raw::git_remote_name_is_valid( + &mut valid, + remote_name.as_ptr(), + )) + .unwrap(); + } + valid == 1 } /// Create a detached remote @@ -851,11 +859,17 @@ mod tests { } #[test] - fn is_valid() { + fn is_valid_name() { assert!(Remote::is_valid_name("foobar")); assert!(!Remote::is_valid_name("\x01")); } + #[test] + #[should_panic] + fn is_valid_name_for_invalid_remote() { + Remote::is_valid_name("ab\012"); + } + #[test] fn transfer_cb() { let (td, _repo) = crate::test::repo_init(); diff --git a/src/tag.rs b/src/tag.rs index 8cd328fdd2..6986c7c160 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -1,10 +1,11 @@ +use std::ffi::CString; use std::marker; use std::mem; use std::ptr; use std::str; use crate::util::Binding; -use crate::{raw, signature, Error, Object, ObjectType, Oid, Signature}; +use crate::{call, raw, signature, Error, Object, ObjectType, Oid, Signature}; /// A structure to represent a git [tag][1] /// @@ -15,6 +16,19 @@ pub struct Tag<'repo> { } impl<'repo> Tag<'repo> { + /// Determine whether a tag name is valid, meaning that (when prefixed with refs/tags/) that + /// it is a valid reference name, and that any additional tag name restrictions are imposed + /// (eg, it cannot start with a -). + pub fn is_valid_name(tag_name: &str) -> bool { + crate::init(); + let tag_name = CString::new(tag_name).unwrap(); + let mut valid: libc::c_int = 0; + unsafe { + call::c_try(raw::git_tag_name_is_valid(&mut valid, tag_name.as_ptr())).unwrap(); + } + valid == 1 + } + /// Get the id (SHA1) of a repository tag pub fn id(&self) -> Oid { unsafe { Binding::from_raw(raw::git_tag_id(&*self.raw)) } @@ -141,6 +155,30 @@ impl<'repo> Drop for Tag<'repo> { #[cfg(test)] mod tests { + use crate::Tag; + + // Reference -- https://git-scm.com/docs/git-check-ref-format + #[test] + fn name_is_valid() { + assert_eq!(Tag::is_valid_name("blah_blah"), true); + assert_eq!(Tag::is_valid_name("v1.2.3"), true); + assert_eq!(Tag::is_valid_name("my/tag"), true); + assert_eq!(Tag::is_valid_name("@"), true); + + assert_eq!(Tag::is_valid_name("-foo"), false); + assert_eq!(Tag::is_valid_name("foo:bar"), false); + assert_eq!(Tag::is_valid_name("foo^bar"), false); + assert_eq!(Tag::is_valid_name("foo."), false); + assert_eq!(Tag::is_valid_name("@{"), false); + assert_eq!(Tag::is_valid_name("as\\cd"), false); + } + + #[test] + #[should_panic] + fn is_valid_name_for_invalid_tag() { + Tag::is_valid_name("ab\012"); + } + #[test] fn smoke() { let (_td, repo) = crate::test::repo_init(); From 2e95ccbb655e0fb47ef40b95d3073f750e270e05 Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Tue, 14 Feb 2023 07:43:52 +0100 Subject: [PATCH 668/860] Remove accidental newlines --- src/odb.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/odb.rs b/src/odb.rs index d7ae2b9515..4092e58c0c 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -1,7 +1,6 @@ use std::io; use std::marker; use std::mem::MaybeUninit; - use std::ptr; use std::slice; @@ -11,7 +10,6 @@ use libc::{c_char, c_int, c_uint, c_void, size_t}; use crate::panic; use crate::util::Binding; - use crate::{ raw, Error, IndexerProgress, Mempack, Object, ObjectType, OdbLookupFlags, Oid, Progress, }; From 318bf825df4113178bfef30622e2b2689065b322 Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Tue, 14 Feb 2023 08:46:35 +0100 Subject: [PATCH 669/860] Wrap native error in io::Error when write fails Unlike for `OdbPackwriter`, we always get the native error code here. --- src/indexer.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/indexer.rs b/src/indexer.rs index 46c5a2508a..ea7fbb9ab1 100644 --- a/src/indexer.rs +++ b/src/indexer.rs @@ -192,9 +192,11 @@ impl io::Write for Indexer<'_> { let len = buf.len(); let res = raw::git_indexer_append(self.raw, ptr, len, self.progress.as_mut_ptr()); - if res < 0 { - Err(io::Error::new(io::ErrorKind::Other, "Write error")) + Err(io::Error::new( + io::ErrorKind::Other, + Error::last_error(res).unwrap(), + )) } else { Ok(buf.len()) } From a3067e79cbc1142217a78854b6f8022e195b0403 Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Tue, 14 Feb 2023 17:44:48 +0100 Subject: [PATCH 670/860] Avoid UB by actually initialising git_indexer_progress --- libgit2-sys/lib.rs | 2 +- src/indexer.rs | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 4e18aeb32f..43cd1f5528 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -336,7 +336,7 @@ pub struct git_checkout_perfdata { } #[repr(C)] -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Default)] pub struct git_indexer_progress { pub total_objects: c_uint, pub indexed_objects: c_uint, diff --git a/src/indexer.rs b/src/indexer.rs index ea7fbb9ab1..0aaf353d53 100644 --- a/src/indexer.rs +++ b/src/indexer.rs @@ -1,5 +1,4 @@ use std::ffi::CStr; -use std::mem::MaybeUninit; use std::path::Path; use std::{io, marker, mem, ptr}; @@ -108,7 +107,7 @@ pub type TransportProgress<'a> = IndexerProgress<'a>; /// database if, and only if, the pack file is self-contained (i.e. not "thin"). pub struct Indexer<'odb> { raw: *mut raw::git_indexer, - progress: MaybeUninit, + progress: raw::git_indexer_progress, progress_payload_ptr: *mut OdbPackwriterCb<'odb>, } @@ -128,7 +127,6 @@ impl<'a> Indexer<'a> { let odb = odb.map(Binding::raw).unwrap_or_else(ptr::null_mut); let mut out = ptr::null_mut(); - let progress = MaybeUninit::uninit(); let progress_cb: raw::git_indexer_progress_cb = Some(write_pack_progress_cb); let progress_payload = Box::new(OdbPackwriterCb { cb: None }); let progress_payload_ptr = Box::into_raw(progress_payload); @@ -148,7 +146,7 @@ impl<'a> Indexer<'a> { Ok(Self { raw: out, - progress, + progress: Default::default(), progress_payload_ptr, }) } @@ -161,10 +159,7 @@ impl<'a> Indexer<'a> { /// `pack-.idx` respectively). pub fn commit(mut self) -> Result { unsafe { - try_call!(raw::git_indexer_commit( - self.raw, - self.progress.as_mut_ptr() - )); + try_call!(raw::git_indexer_commit(self.raw, &mut self.progress)); let name = CStr::from_ptr(raw::git_indexer_name(self.raw)); Ok(name.to_str().expect("pack name not utf8").to_owned()) @@ -191,7 +186,7 @@ impl io::Write for Indexer<'_> { let ptr = buf.as_ptr() as *mut c_void; let len = buf.len(); - let res = raw::git_indexer_append(self.raw, ptr, len, self.progress.as_mut_ptr()); + let res = raw::git_indexer_append(self.raw, ptr, len, &mut self.progress); if res < 0 { Err(io::Error::new( io::ErrorKind::Other, From f36cf676bf6f96c46c400dd10f13e87b9a259b20 Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Tue, 14 Feb 2023 17:49:27 +0100 Subject: [PATCH 671/860] Avoid MaybeUninit in OdbPackwriter, too --- src/odb.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/odb.rs b/src/odb.rs index 4092e58c0c..ab25c757fc 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -1,6 +1,5 @@ use std::io; use std::marker; -use std::mem::MaybeUninit; use std::ptr; use std::slice; @@ -162,7 +161,6 @@ impl<'repo> Odb<'repo> { /// Create stream for writing a pack file to the ODB pub fn packwriter(&self) -> Result, Error> { let mut out = ptr::null_mut(); - let progress = MaybeUninit::uninit(); let progress_cb: raw::git_indexer_progress_cb = Some(write_pack_progress_cb); let progress_payload = Box::new(OdbPackwriterCb { cb: None }); let progress_payload_ptr = Box::into_raw(progress_payload); @@ -178,7 +176,7 @@ impl<'repo> Odb<'repo> { Ok(OdbPackwriter { raw: out, - progress, + progress: Default::default(), progress_payload_ptr, }) } @@ -445,7 +443,7 @@ pub(crate) struct OdbPackwriterCb<'repo> { /// A stream to write a packfile to the ODB pub struct OdbPackwriter<'repo> { raw: *mut raw::git_odb_writepack, - progress: MaybeUninit, + progress: raw::git_indexer_progress, progress_payload_ptr: *mut OdbPackwriterCb<'repo>, } @@ -455,7 +453,7 @@ impl<'repo> OdbPackwriter<'repo> { unsafe { let writepack = &*self.raw; let res = match writepack.commit { - Some(commit) => commit(self.raw, self.progress.as_mut_ptr()), + Some(commit) => commit(self.raw, &mut self.progress), None => -1, }; @@ -489,7 +487,7 @@ impl<'repo> io::Write for OdbPackwriter<'repo> { let writepack = &*self.raw; let res = match writepack.append { - Some(append) => append(self.raw, ptr, len, self.progress.as_mut_ptr()), + Some(append) => append(self.raw, ptr, len, &mut self.progress), None => -1, }; From 6c0632724fb79b025e36a71f6dbfd8cb901aa6eb Mon Sep 17 00:00:00 2001 From: Michael Henry Date: Wed, 22 Feb 2023 11:18:20 -0500 Subject: [PATCH 672/860] Add `Repository::set_head_bytes()`; like `set_head()` but bytes-only. This allows setting `HEAD` to non-utf8 reference names. --- src/repo.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index e6b2421fbd..0c029693ba 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -817,6 +817,22 @@ impl Repository { /// Otherwise, the HEAD will be detached and will directly point to the /// commit. pub fn set_head(&self, refname: &str) -> Result<(), Error> { + self.set_head_bytes(refname.as_bytes()) + } + + /// Make the repository HEAD point to the specified reference as a byte array. + /// + /// If the provided reference points to a tree or a blob, the HEAD is + /// unaltered and an error is returned. + /// + /// If the provided reference points to a branch, the HEAD will point to + /// that branch, staying attached, or become attached if it isn't yet. If + /// the branch doesn't exist yet, no error will be returned. The HEAD will + /// then be attached to an unborn branch. + /// + /// Otherwise, the HEAD will be detached and will directly point to the + /// commit. + pub fn set_head_bytes(&self, refname: &[u8]) -> Result<(), Error> { let refname = CString::new(refname)?; unsafe { try_call!(raw::git_repository_set_head(self.raw, refname)); @@ -3602,6 +3618,19 @@ mod tests { assert!(repo.set_head("*").is_err()); } + #[test] + fn smoke_set_head_bytes() { + let (_td, repo) = crate::test::repo_init(); + + assert!(repo.set_head_bytes(b"refs/heads/does-not-exist").is_ok()); + assert!(repo.head().is_err()); + + assert!(repo.set_head_bytes(b"refs/heads/main").is_ok()); + assert!(repo.head().is_ok()); + + assert!(repo.set_head_bytes(b"*").is_err()); + } + #[test] fn smoke_set_head_detached() { let (_td, repo) = crate::test::repo_init(); From 47f0071b61157e23bdae333f229d9f4d571151b9 Mon Sep 17 00:00:00 2001 From: klensy Date: Sat, 25 Feb 2023 14:00:57 +0300 Subject: [PATCH 673/860] drop unused paste crate --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 8fc19cabe1..c4af9dba02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,6 @@ openssl-probe = { version = "0.1", optional = true } structopt = "0.3" time = "0.1.39" tempfile = "3.1.0" -paste = "1" [features] unstable = [] From 22ef3591ed95e9cabbb6958dbaa398ea1ed4e1db Mon Sep 17 00:00:00 2001 From: Kristoffer Haugsbakk Date: Wed, 22 Mar 2023 21:58:46 +0100 Subject: [PATCH 674/860] Add an empty-iterator example argument --- src/repo.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 0c029693ba..a794939be7 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -198,7 +198,9 @@ impl Repository { /// /// 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. + /// to construct or manipulate such a path list. (You can use `&[] as + /// &[&std::ffi::OsStr]` as an argument if there are no ceiling + /// directories.) pub fn open_ext( path: P, flags: RepositoryOpenFlags, From 855b8de491f73b475f3f0f8bbb986e5732b04262 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 28 Feb 2023 12:52:16 -0800 Subject: [PATCH 675/860] Update to libgit2 1.6.3 --- Cargo.toml | 4 +-- README.md | 2 +- git2-curl/Cargo.toml | 4 +-- git2-curl/src/lib.rs | 2 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 10 ++---- libgit2-sys/lib.rs | 67 ++++++++++++++++++++------------------ libgit2-sys/libgit2 | 2 +- src/diff.rs | 2 +- src/lib.rs | 2 +- systest/build.rs | 16 +++------ tests/add_extensions.rs | 6 ++-- tests/get_extensions.rs | 4 ++- tests/remove_extensions.rs | 2 +- 14 files changed, 60 insertions(+), 65 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c4af9dba02..526e29800a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.16.1" +version = "0.17.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.14.2" } +libgit2-sys = { path = "libgit2-sys", version = "0.15.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/README.md b/README.md index 1a7842a960..d94ff5a9f1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.16.1" +git2 = "0.17.0" ``` ## Rust version requirements diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index ac906367fc..8e30c69052 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2-curl" -version = "0.17.0" +version = "0.18.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" @@ -16,7 +16,7 @@ edition = "2018" curl = "0.4.33" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.16", default-features = false } +git2 = { path = "..", version = "0.17", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index c0f0e30d19..a0a6c98719 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -15,7 +15,7 @@ //! > **NOTE**: At this time this crate likely does not support a `git push` //! > operation, only clones. -#![doc(html_root_url = "https://docs.rs/git2-curl/0.17")] +#![doc(html_root_url = "https://docs.rs/git2-curl/0.18")] #![deny(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index f4640b9b9a..b21169ad1e 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.14.2+1.5.1" +version = "0.15.0+1.6.3" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 4cd3e1f945..c050fb3874 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,13 +14,7 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - // These version ranges specifically request a version that includes - // the SSH fixes for CVE-2023-22742 (1.5.1+ or 1.4.5+). - if let Ok(lib) = cfg - .range_version("1.5.1".."1.6.0") - .probe("libgit2") - .or_else(|_| cfg.range_version("1.4.5".."1.5.0").probe("libgit2")) - { + if let Ok(lib) = cfg.range_version("1.6.3".."1.7.0").probe("libgit2") { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } @@ -194,7 +188,7 @@ fn main() { } features.push_str("#endif\n"); - fs::write(include.join("git2/sys/features.h"), features).unwrap(); + fs::write(include.join("git2_features.h"), features).unwrap(); cfg.compile("git2"); diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 26502eccdf..0f8fb73f74 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.14")] +#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.15")] #![allow(non_camel_case_types, unused_extern_crates)] // This is required to link libz when libssh2-sys is not included. @@ -1160,37 +1160,40 @@ pub type git_diff_notify_cb = Option< pub type git_diff_progress_cb = Option c_int>; -pub type git_diff_option_t = i32; -pub const GIT_DIFF_NORMAL: git_diff_option_t = 0; -pub const GIT_DIFF_REVERSE: git_diff_option_t = 1 << 0; -pub const GIT_DIFF_INCLUDE_IGNORED: git_diff_option_t = 1 << 1; -pub const GIT_DIFF_RECURSE_IGNORED_DIRS: git_diff_option_t = 1 << 2; -pub const GIT_DIFF_INCLUDE_UNTRACKED: git_diff_option_t = 1 << 3; -pub const GIT_DIFF_RECURSE_UNTRACKED_DIRS: git_diff_option_t = 1 << 4; -pub const GIT_DIFF_INCLUDE_UNMODIFIED: git_diff_option_t = 1 << 5; -pub const GIT_DIFF_INCLUDE_TYPECHANGE: git_diff_option_t = 1 << 6; -pub const GIT_DIFF_INCLUDE_TYPECHANGE_TREES: git_diff_option_t = 1 << 7; -pub const GIT_DIFF_IGNORE_FILEMODE: git_diff_option_t = 1 << 8; -pub const GIT_DIFF_IGNORE_SUBMODULES: git_diff_option_t = 1 << 9; -pub const GIT_DIFF_IGNORE_CASE: git_diff_option_t = 1 << 10; -pub const GIT_DIFF_DISABLE_PATHSPEC_MATCH: git_diff_option_t = 1 << 12; -pub const GIT_DIFF_SKIP_BINARY_CHECK: git_diff_option_t = 1 << 13; -pub const GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS: git_diff_option_t = 1 << 14; -pub const GIT_DIFF_UPDATE_INDEX: git_diff_option_t = 1 << 15; -pub const GIT_DIFF_INCLUDE_UNREADABLE: git_diff_option_t = 1 << 16; -pub const GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED: git_diff_option_t = 1 << 17; -pub const GIT_DIFF_INDENT_HEURISTIC: git_diff_option_t = 1 << 18; -pub const GIT_DIFF_IGNORE_BLANK_LINES: git_diff_option_t = 1 << 19; -pub const GIT_DIFF_FORCE_TEXT: git_diff_option_t = 1 << 20; -pub const GIT_DIFF_FORCE_BINARY: git_diff_option_t = 1 << 21; -pub const GIT_DIFF_IGNORE_WHITESPACE: git_diff_option_t = 1 << 22; -pub const GIT_DIFF_IGNORE_WHITESPACE_CHANGE: git_diff_option_t = 1 << 23; -pub const GIT_DIFF_IGNORE_WHITESPACE_EOL: git_diff_option_t = 1 << 24; -pub const GIT_DIFF_SHOW_UNTRACKED_CONTENT: git_diff_option_t = 1 << 25; -pub const GIT_DIFF_SHOW_UNMODIFIED: git_diff_option_t = 1 << 26; -pub const GIT_DIFF_PATIENCE: git_diff_option_t = 1 << 28; -pub const GIT_DIFF_MINIMAL: git_diff_option_t = 1 << 29; -pub const GIT_DIFF_SHOW_BINARY: git_diff_option_t = 1 << 30; +git_enum! { + pub enum git_diff_option_t { + GIT_DIFF_NORMAL = 0, + GIT_DIFF_REVERSE = 1 << 0, + GIT_DIFF_INCLUDE_IGNORED = 1 << 1, + GIT_DIFF_RECURSE_IGNORED_DIRS = 1 << 2, + GIT_DIFF_INCLUDE_UNTRACKED = 1 << 3, + GIT_DIFF_RECURSE_UNTRACKED_DIRS = 1 << 4, + GIT_DIFF_INCLUDE_UNMODIFIED = 1 << 5, + GIT_DIFF_INCLUDE_TYPECHANGE = 1 << 6, + GIT_DIFF_INCLUDE_TYPECHANGE_TREES = 1 << 7, + GIT_DIFF_IGNORE_FILEMODE = 1 << 8, + GIT_DIFF_IGNORE_SUBMODULES = 1 << 9, + GIT_DIFF_IGNORE_CASE = 1 << 10, + GIT_DIFF_DISABLE_PATHSPEC_MATCH = 1 << 12, + GIT_DIFF_SKIP_BINARY_CHECK = 1 << 13, + GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS = 1 << 14, + GIT_DIFF_UPDATE_INDEX = 1 << 15, + GIT_DIFF_INCLUDE_UNREADABLE = 1 << 16, + GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED = 1 << 17, + GIT_DIFF_INDENT_HEURISTIC = 1 << 18, + GIT_DIFF_IGNORE_BLANK_LINES = 1 << 19, + GIT_DIFF_FORCE_TEXT = 1 << 20, + GIT_DIFF_FORCE_BINARY = 1 << 21, + GIT_DIFF_IGNORE_WHITESPACE = 1 << 22, + GIT_DIFF_IGNORE_WHITESPACE_CHANGE = 1 << 23, + GIT_DIFF_IGNORE_WHITESPACE_EOL = 1 << 24, + GIT_DIFF_SHOW_UNTRACKED_CONTENT = 1 << 25, + GIT_DIFF_SHOW_UNMODIFIED = 1 << 26, + GIT_DIFF_PATIENCE = 1 << 28, + GIT_DIFF_MINIMAL = 1 << 29, + GIT_DIFF_SHOW_BINARY = 1 << 30, + } +} #[repr(C)] pub struct git_diff_find_options { diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 42e5db98b9..c058aa87dc 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 42e5db98b963ae503229c63e44e06e439df50e56 +Subproject commit c058aa87dce4c67a3b86b3349beebd64b7bedcd3 diff --git a/src/diff.rs b/src/diff.rs index 4dc895fa1b..cb7d033896 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -679,7 +679,7 @@ impl DiffOptions { opts } - fn flag(&mut self, opt: i32, val: bool) -> &mut DiffOptions { + fn flag(&mut self, opt: raw::git_diff_option_t, val: bool) -> &mut DiffOptions { let opt = opt as u32; if val { self.raw.flags |= opt; diff --git a/src/lib.rs b/src/lib.rs index 77cb523d15..3671b2859a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.16")] +#![doc(html_root_url = "https://docs.rs/git2/0.17")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] diff --git a/systest/build.rs b/systest/build.rs index eba93f3090..58837ee013 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -26,17 +26,11 @@ fn main() { // the real name of this field is ref but that is a reserved keyword (struct_ == "git_worktree_add_options" && f == "reference") }); - cfg.skip_signededness(|s| { - match s { - s if s.ends_with("_cb") => true, - s if s.ends_with("_callback") => true, - "git_push_transfer_progress" | "git_push_negotiation" | "git_packbuilder_progress" => { - true - } - // TODO: fix this on the next major update of libgit2-sys - "git_diff_option_t" => true, - _ => false, - } + cfg.skip_signededness(|s| match s { + s if s.ends_with("_cb") => true, + s if s.ends_with("_callback") => true, + "git_push_transfer_progress" | "git_push_negotiation" | "git_packbuilder_progress" => true, + _ => false, }); // not entirely sure why this is failing... diff --git a/tests/add_extensions.rs b/tests/add_extensions.rs index fe37e1eeb7..7d80b705db 100644 --- a/tests/add_extensions.rs +++ b/tests/add_extensions.rs @@ -11,9 +11,11 @@ fn test_add_extensions() -> Result<(), Error> { let extensions = unsafe { get_extensions() }?; - assert_eq!(extensions.len(), 2); + assert_eq!(extensions.len(), 3); assert_eq!(extensions.get(0), Some("noop")); - assert_eq!(extensions.get(1), Some("custom")); + // The objectformat extension was added in 1.6 + assert_eq!(extensions.get(1), Some("objectformat")); + assert_eq!(extensions.get(2), Some("custom")); Ok(()) } diff --git a/tests/get_extensions.rs b/tests/get_extensions.rs index ac049c6816..d8dd55fe0a 100644 --- a/tests/get_extensions.rs +++ b/tests/get_extensions.rs @@ -7,8 +7,10 @@ use git2::Error; fn test_get_extensions() -> Result<(), Error> { let extensions = unsafe { get_extensions() }?; - assert_eq!(extensions.len(), 1); + assert_eq!(extensions.len(), 2); assert_eq!(extensions.get(0), Some("noop")); + // The objectformat extension was added in 1.6 + assert_eq!(extensions.get(1), Some("objectformat")); Ok(()) } diff --git a/tests/remove_extensions.rs b/tests/remove_extensions.rs index 366da7392b..5f632a8809 100644 --- a/tests/remove_extensions.rs +++ b/tests/remove_extensions.rs @@ -6,7 +6,7 @@ use git2::Error; #[test] fn test_remove_extensions() -> Result<(), Error> { unsafe { - set_extensions(&["custom", "!ignore", "!noop", "other"])?; + set_extensions(&["custom", "!ignore", "!noop", "!objectformat", "other"])?; } let extensions = unsafe { get_extensions() }?; From c5432c780c9f4584c668f65aaa010fba6768e96a Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 28 Jun 2021 17:05:20 +0100 Subject: [PATCH 676/860] TreeUpdateBuilder: Remove confusing note re libgit2 function It seems obvious from the rest of the docs what to do with a `TreeUpdateBuilder`. The reference to `git_tree_create_updated` is certainloy not helpful since that's a C function. Signed-off-by: Ian Jackson --- src/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build.rs b/src/build.rs index a822f0822e..617ba2c3c5 100644 --- a/src/build.rs +++ b/src/build.rs @@ -64,7 +64,7 @@ pub struct RepoBuilder<'cb> { pub type RemoteCreate<'cb> = dyn for<'a> FnMut(&'a Repository, &str, &str) -> Result, Error> + 'cb; -/// A builder struct for git tree updates, for use with `git_tree_create_updated`. +/// A builder struct for git tree updates. pub struct TreeUpdateBuilder { updates: Vec, paths: Vec, From f625d14fd24e20574b0b80cd4de95b646bd5de97 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 28 Jun 2021 17:17:28 +0100 Subject: [PATCH 677/860] TreeUpdateBuilder/TreeBuilder: Document and cross-reference Signed-off-by: Ian Jackson --- src/build.rs | 8 ++++++++ src/treebuilder.rs | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/build.rs b/src/build.rs index 617ba2c3c5..12c80d78ae 100644 --- a/src/build.rs +++ b/src/build.rs @@ -65,6 +65,14 @@ pub type RemoteCreate<'cb> = dyn for<'a> FnMut(&'a Repository, &str, &str) -> Result, Error> + 'cb; /// A builder struct for git tree updates. +/// +/// Paths passed to `remove` and `upsert` can be multi-component paths, ie they +/// may contain slashes. +/// +/// This is the more-cooked tree update facility. There is also [`TreeBuilder`] +/// which is lower-level (and operates only on one level of the tree at a time). +/// +/// [`TreeBuilder`]: crate::TreeBuilder pub struct TreeUpdateBuilder { updates: Vec, paths: Vec, diff --git a/src/treebuilder.rs b/src/treebuilder.rs index f88f074ca3..1548a048cf 100644 --- a/src/treebuilder.rs +++ b/src/treebuilder.rs @@ -6,7 +6,15 @@ use libc::{c_int, c_void}; use crate::util::{Binding, IntoCString}; use crate::{panic, raw, tree, Error, Oid, Repository, TreeEntry}; -/// Constructor for in-memory trees +/// Constructor for in-memory trees (low-level) +/// +/// You probably want to use [`build::TreeUpdateBuilder`] instead. +/// +/// This is the more raw of the two tree update facilities. It +/// handles only one level of a nested tree structure at a time. Each +/// path passed to `insert` etc. must be a single component. +/// +/// [`build::TreeUpdateBuilder`]: crate::build::TreeUpdateBuilder pub struct TreeBuilder<'repo> { raw: *mut raw::git_treebuilder, _marker: marker::PhantomData<&'repo Repository>, From 16cb29b037e50bebebc87f9583d57b5a791e8dc1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 1 Apr 2023 13:31:21 -0700 Subject: [PATCH 678/860] Minor doc wording update. --- src/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/build.rs b/src/build.rs index 12c80d78ae..d3c95f6559 100644 --- a/src/build.rs +++ b/src/build.rs @@ -66,10 +66,10 @@ pub type RemoteCreate<'cb> = /// A builder struct for git tree updates. /// -/// Paths passed to `remove` and `upsert` can be multi-component paths, ie they +/// Paths passed to `remove` and `upsert` can be multi-component paths, i.e. they /// may contain slashes. /// -/// This is the more-cooked tree update facility. There is also [`TreeBuilder`] +/// This is a higher-level tree update facility. There is also [`TreeBuilder`] /// which is lower-level (and operates only on one level of the tree at a time). /// /// [`TreeBuilder`]: crate::TreeBuilder From 920c8380007b6e86a63773758085c07a3f17f514 Mon Sep 17 00:00:00 2001 From: karin0 Date: Wed, 1 Feb 2023 19:18:24 +0800 Subject: [PATCH 679/860] add bindings for push_negotiation callback --- src/lib.rs | 2 ++ src/push_update.rs | 55 +++++++++++++++++++++++++++++++++++++++++ src/remote_callbacks.rs | 45 +++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 src/push_update.rs diff --git a/src/lib.rs b/src/lib.rs index b1c80de306..ef8cb2c9c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -116,6 +116,7 @@ pub use crate::patch::Patch; pub use crate::pathspec::{Pathspec, PathspecFailedEntries, PathspecMatchList}; pub use crate::pathspec::{PathspecDiffEntries, PathspecEntries}; pub use crate::proxy_options::ProxyOptions; +pub use crate::push_update::PushUpdate; pub use crate::rebase::{Rebase, RebaseOperation, RebaseOperationType, RebaseOptions}; pub use crate::reference::{Reference, ReferenceNames, References}; pub use crate::reflog::{Reflog, ReflogEntry, ReflogIter}; @@ -694,6 +695,7 @@ mod packbuilder; mod patch; mod pathspec; mod proxy_options; +mod push_update; mod rebase; mod reference; mod reflog; diff --git a/src/push_update.rs b/src/push_update.rs new file mode 100644 index 0000000000..3f74a2506b --- /dev/null +++ b/src/push_update.rs @@ -0,0 +1,55 @@ +use crate::util::Binding; +use crate::{raw, Oid}; +use std::marker; +use std::str; + +/// Represents an update which will be performed on the remote during push. +pub struct PushUpdate<'a> { + raw: *const raw::git_push_update, + _marker: marker::PhantomData<&'a raw::git_push_update>, +} + +impl<'a> Binding for PushUpdate<'a> { + type Raw = *const raw::git_push_update; + unsafe fn from_raw(raw: *const raw::git_push_update) -> PushUpdate<'a> { + PushUpdate { + raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> Self::Raw { + self.raw + } +} + +impl PushUpdate<'_> { + /// Returns the source name of the reference as a byte slice. + pub fn src_refname_bytes(&self) -> &[u8] { + unsafe { crate::opt_bytes(self, (*self.raw).src_refname).unwrap() } + } + + /// Returns the source name of the reference. + pub fn src_refname(&self) -> Option<&str> { + str::from_utf8(self.src_refname_bytes()).ok() + } + + /// Returns the destination name of the reference as a byte slice. + pub fn dst_refname_bytes(&self) -> &[u8] { + unsafe { crate::opt_bytes(self, (*self.raw).dst_refname).unwrap() } + } + + /// Returns the destination name of the reference. + pub fn dst_refname(&self) -> Option<&str> { + str::from_utf8(self.dst_refname_bytes()).ok() + } + + /// Returns the current target of the reference. + pub fn src(&self) -> Oid { + unsafe { Binding::from_raw(&(*self.raw).src as *const _) } + } + + /// Returns the new target for the reference. + pub fn dst(&self) -> Oid { + unsafe { Binding::from_raw(&(*self.raw).dst as *const _) } + } +} diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index b35bbe183e..1169420bda 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -9,6 +9,7 @@ use crate::cert::Cert; use crate::util::Binding; use crate::{ panic, raw, Cred, CredentialType, Error, IndexerProgress, Oid, PackBuilderStage, Progress, + PushUpdate, }; /// A structure to contain the callbacks which are invoked when a repository is @@ -25,6 +26,7 @@ pub struct RemoteCallbacks<'a> { update_tips: Option>>, certificate_check: Option>>, push_update_reference: Option>>, + push_negotiation: Option>>, } /// Callback used to acquire credentials for when a remote is fetched. @@ -87,6 +89,14 @@ pub type PushTransferProgress<'a> = dyn FnMut(usize, usize, usize) + 'a; /// * total pub type PackProgress<'a> = dyn FnMut(PackBuilderStage, usize, usize) + 'a; +/// Callback used to inform of upcoming updates. +/// +/// The argument is a slice containing the updates which will be sent as +/// commands to the destination. +/// +/// The push is cancelled if an error is returned. +pub type PushNegotiation<'a> = dyn FnMut(&[PushUpdate<'_>]) -> Result<(), Error> + 'a; + impl<'a> Default for RemoteCallbacks<'a> { fn default() -> Self { Self::new() @@ -105,6 +115,7 @@ impl<'a> RemoteCallbacks<'a> { certificate_check: None, push_update_reference: None, push_progress: None, + push_negotiation: None, } } @@ -211,6 +222,16 @@ impl<'a> RemoteCallbacks<'a> { self.pack_progress = Some(Box::new(cb) as Box>); self } + + /// The callback is called once between the negotiation step and the upload. + /// It provides information about what updates will be performed. + pub fn push_negotiation(&mut self, cb: F) -> &mut RemoteCallbacks<'a> + where + F: FnMut(&[PushUpdate<'_>]) -> Result<(), Error> + 'a, + { + self.push_negotiation = Some(Box::new(cb) as Box>); + self + } } impl<'a> Binding for RemoteCallbacks<'a> { @@ -256,6 +277,9 @@ impl<'a> Binding for RemoteCallbacks<'a> { ) -> c_int = update_tips_cb; callbacks.update_tips = Some(f); } + if self.push_negotiation.is_some() { + callbacks.push_negotiation = Some(push_negotiation_cb); + } callbacks.payload = self as *const _ as *mut _; callbacks } @@ -471,3 +495,24 @@ extern "C" fn pack_progress_cb( }) .unwrap_or(-1) } + +extern "C" fn push_negotiation_cb( + updates: *mut *const raw::git_push_update, + len: size_t, + payload: *mut c_void, +) -> c_int { + panic::wrap(|| unsafe { + let payload = &mut *(payload as *mut RemoteCallbacks<'_>); + let callback = match payload.push_negotiation { + Some(ref mut c) => c, + None => return 0, + }; + + let updates = slice::from_raw_parts(updates as *mut PushUpdate<'_>, len); + match callback(updates) { + Ok(()) => 0, + Err(e) => e.raw_code(), + } + }) + .unwrap_or(-1) +} From a638e23c8dcf07ed2f71b093a30f52a5fe8c3207 Mon Sep 17 00:00:00 2001 From: karin0 Date: Wed, 1 Feb 2023 22:48:54 +0800 Subject: [PATCH 680/860] add a test for push_negotiation --- src/remote.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/src/remote.rs b/src/remote.rs index 7c0670ffaa..98f4cd8b6e 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -1014,4 +1014,94 @@ mod tests { remote.prune(Some(callbacks)).unwrap(); assert_branch_count(&repo, 0); } + + #[test] + fn push_negotiation() { + let (_td, repo) = crate::test::repo_init(); + let oid = repo.head().unwrap().target().unwrap(); + + let td2 = TempDir::new().unwrap(); + let url = crate::test::path2url(https://github.com/td2.path()); + let mut opts = crate::RepositoryInitOptions::new(); + opts.bare(true); + opts.initial_head("main"); + let remote_repo = Repository::init_opts(td2.path(), &opts).unwrap(); + + // reject pushing a branch + let mut remote = repo.remote("origin", &url).unwrap(); + let mut updated = false; + { + let mut callbacks = RemoteCallbacks::new(); + callbacks.push_negotiation(|updates| { + assert!(!updated); + updated = true; + assert_eq!(updates.len(), 1); + let u = &updates[0]; + assert_eq!(u.src_refname().unwrap(), "refs/heads/main"); + assert!(u.src().is_zero()); + assert_eq!(u.dst_refname().unwrap(), "refs/heads/main"); + assert_eq!(u.dst(), oid); + Err(crate::Error::from_str("rejected")) + }); + let mut options = PushOptions::new(); + options.remote_callbacks(callbacks); + assert!(remote + .push(&["refs/heads/main"], Some(&mut options)) + .is_err()); + } + assert!(updated); + assert_eq!(remote_repo.branches(None).unwrap().count(), 0); + + // push 3 branches + let commit = repo.find_commit(oid).unwrap(); + repo.branch("new1", &commit, true).unwrap(); + repo.branch("new2", &commit, true).unwrap(); + let mut flag = 0; + updated = false; + { + let mut callbacks = RemoteCallbacks::new(); + callbacks.push_negotiation(|updates| { + assert!(!updated); + updated = true; + assert_eq!(updates.len(), 3); + for u in updates { + assert!(u.src().is_zero()); + assert_eq!(u.dst(), oid); + let src_name = u.src_refname().unwrap(); + let dst_name = u.dst_refname().unwrap(); + match src_name { + "refs/heads/main" => { + assert_eq!(dst_name, src_name); + flag |= 1; + } + "refs/heads/new1" => { + assert_eq!(dst_name, "refs/heads/dev1"); + flag |= 2; + } + "refs/heads/new2" => { + assert_eq!(dst_name, "refs/heads/dev2"); + flag |= 4; + } + _ => panic!("unexpected refname: {}", src_name), + } + } + Ok(()) + }); + let mut options = PushOptions::new(); + options.remote_callbacks(callbacks); + remote + .push( + &[ + "refs/heads/main", + "refs/heads/new1:refs/heads/dev1", + "refs/heads/new2:refs/heads/dev2", + ], + Some(&mut options), + ) + .unwrap(); + } + assert!(updated); + assert_eq!(flag, 7); + assert_eq!(remote_repo.branches(None).unwrap().count(), 3); + } } From e586a7db82082b56c7a8bc1a6a27540f20b0823b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 2 Apr 2023 14:54:25 -0700 Subject: [PATCH 681/860] Update changelogs --- CHANGELOG.md | 45 ++++++++++++++++++++++++++++++++++++++++ git2-curl/CHANGELOG.md | 5 +++++ libgit2-sys/CHANGELOG.md | 31 +++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7843dd3023..d23f46239c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,50 @@ # Changelog +## 0.17.0 - 2023-04-02 +[0.16.1...0.17.0](https://github.com/rust-lang/git2-rs/compare/0.16.1...0.17.0) + +### Added + +- Added `IntoIterator` implementation for `Statuses`. + [#880](https://github.com/rust-lang/git2-rs/pull/880) +- Added `Reference::symbolic_set_target` + [#893](https://github.com/rust-lang/git2-rs/pull/893) +- Added `Copy`, `Clone`, `Debug`, `PartialEq`, and `Eq` implementations for `AutotagOption` and `FetchPrune`. + [#889](https://github.com/rust-lang/git2-rs/pull/889) +- Added `Eq` and `PartialEq` implementations for `Signature`. + [#890](https://github.com/rust-lang/git2-rs/pull/890) +- Added `Repository::discover_path`. + [#883](https://github.com/rust-lang/git2-rs/pull/883) +- Added `Submodule::repo_init`. + [#914](https://github.com/rust-lang/git2-rs/pull/914) +- Added `Tag::is_valid_name`. + [#882](https://github.com/rust-lang/git2-rs/pull/882) +- Added `Repository::set_head_bytes`. + [#931](https://github.com/rust-lang/git2-rs/pull/931) +- Added the `Indexer` type which is a low-level API for storing and indexing pack files. + [#911](https://github.com/rust-lang/git2-rs/pull/911) +- Added `Index::find_prefix`. + [#903](https://github.com/rust-lang/git2-rs/pull/903) +- Added support for the deprecated group-writeable blob mode. This adds a new variant to `FileMode`. + [#887](https://github.com/rust-lang/git2-rs/pull/887) +- Added `PushCallbacks::push_negotiation` callback and the corresponding `PushUpdate` type for getting receiving information about the updates to perform. + [#926](https://github.com/rust-lang/git2-rs/pull/926) + +### Changed + +- Updated to libgit2 [1.6.3](https://github.com/libgit2/libgit2/blob/main/docs/changelog.md#v163). + This brings in many changes, including better SSH host key support on Windows and better SSH host key algorithm negotiation. + 1.6.3 is now the minimum supported version. + [#935](https://github.com/rust-lang/git2-rs/pull/935) +- Updated libssh2-sys from 0.2 to 0.3. + This brings in numerous changes, including SHA2 algorithm support with RSA. + [#919](https://github.com/rust-lang/git2-rs/pull/919) +- Changed `RemoteCallbacks::credentials` callback error handler to correctly set the libgit2 error class. + [#918](https://github.com/rust-lang/git2-rs/pull/918) +- `DiffOptions::flag` now takes a `git_diff_option_t` type. + [#935](https://github.com/rust-lang/git2-rs/pull/935) + + ## 0.16.1 - 2023-01-20 [0.16.0...0.16.1](https://github.com/rust-lang/git2-rs/compare/0.16.0...0.16.1) diff --git a/git2-curl/CHANGELOG.md b/git2-curl/CHANGELOG.md index 2ff61cb50a..f20930568e 100644 --- a/git2-curl/CHANGELOG.md +++ b/git2-curl/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.18.0 - 2023-04-02 +[0.17.0...0.18.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.17.0...git2-curl-0.18.0) + +- Updated to [git2 0.17.0](../CHANGELOG.md#0170---2023-04-02) + ## 0.17.0 - 2023-01-10 [0.16.0...0.17.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.16.0...git2-curl-0.17.0) diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index 75603b87ec..24989fdcdd 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## 0.15.0+1.6.3 - 2023-04-02 +[0.14.2...0.15.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.14.2+1.5.1...libgit2-sys-0.15.0+1.6.3) + +### Added + +- Added bindings for `git_remote_name_is_valid`, `git_reference_name_is_valid`, and `git_tag_name_is_valid`. + [#882](https://github.com/rust-lang/git2-rs/pull/882) +- Added bindings for `git_indexer` support. + [#911](https://github.com/rust-lang/git2-rs/pull/911) +- Added bindings for `git_index_find_prefix`. + [#903](https://github.com/rust-lang/git2-rs/pull/903) +- Added support for the deprecated group-writeable blob file mode. + [#887](https://github.com/rust-lang/git2-rs/pull/887) + +### Changed + +- Updated libssh2-sys from 0.2 to 0.3. + This brings in numerous changes, including SHA2 algorithm support with RSA. + [#919](https://github.com/rust-lang/git2-rs/pull/919) +- Updated to libgit2 [1.6.3](https://github.com/libgit2/libgit2/blob/main/docs/changelog.md#v163). + This brings in many changes, including better SSH host key support on Windows and better SSH host key algorithm negotiation. + 1.6.3 is now the minimum supported version. + [#935](https://github.com/rust-lang/git2-rs/pull/935) +- The `GIT_DIFF_` constants have been changed to be a `git_diff_option_t` type. + [#935](https://github.com/rust-lang/git2-rs/pull/935) + +### Fixed + +- Fixed the rerun-if-changed build script support on Windows. This is only relevant for those working within the git2-rs source tree. + [#916](https://github.com/rust-lang/git2-rs/pull/916) + ## 0.14.2+1.5.1 - 2023-01-20 [0.14.1...0.14.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.14.1+1.5.0...libgit2-sys-0.14.2+1.5.1) From 16e5696544edba788744abb0218cbd2f2252a77a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 10 Apr 2023 09:49:17 -0700 Subject: [PATCH 682/860] Update reference to libgit2 version in README. --- CONTRIBUTING.md | 1 + README.md | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bbbb673a68..d8ab922325 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,6 +18,7 @@ The following steps can be used to update libgit2: * Update the dependency version in [`Cargo.toml`](https://github.com/rust-lang/git2-rs/blob/master/Cargo.toml) to match the version in the last step (do not include the `+` metadata). Also update the version of the `git2` crate itself so it will pick up the change to `libgit2-sys` (also keeping in mind if it is a SemVer breaking release). * Update the version in [`README.md`](https://github.com/rust-lang/git2-rs/blob/master/README.md) if needed. + There are two places, the `Cargo.toml` example and the description of the libgit2 version it binds with. * If there was a SemVer-breaking version bump for either library, also update the `html_root_url` attribute in the `lib.rs` of each library. 3. Run tests. `cargo test -p git2 -p git2-curl` is a good starting point. diff --git a/README.md b/README.md index d94ff5a9f1..a5321126a3 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,10 @@ stable release as well. ## Version of libgit2 -Currently this library requires libgit2 1.4. The source for libgit2 is -included in the libgit2-sys crate so there's no need to pre-install the libgit2 -library, the libgit2-sys crate will figure that and/or build that for you. +Currently this library requires libgit2 1.6.3 (or newer patch versions). The +source for libgit2 is included in the libgit2-sys crate so there's no need to +pre-install the libgit2 library, the libgit2-sys crate will figure that and/or +build that for you. ## Building git2-rs From 3bd681c8e35f2760015a12992ed96dbe22374b95 Mon Sep 17 00:00:00 2001 From: Ximo Guanter Date: Thu, 13 Apr 2023 08:25:13 +0200 Subject: [PATCH 683/860] Bump libgit2 to 1.6.4 --- CHANGELOG.md | 8 ++++++++ Cargo.toml | 4 ++-- README.md | 4 ++-- libgit2-sys/CHANGELOG.md | 10 ++++++++++ libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 2 +- libgit2-sys/libgit2 | 2 +- 7 files changed, 25 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d23f46239c..36ee314179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.17.1 - 2023-04-13 +[0.17.0...0.17.1](https://github.com/rust-lang/git2-rs/compare/0.17.0...0.17.1) + +### Changed + +- Updated to libgit2 [1.6.4](https://github.com/libgit2/libgit2/releases/tag/v1.6.4). + [#935](TODO) + ## 0.17.0 - 2023-04-02 [0.16.1...0.17.0](https://github.com/rust-lang/git2-rs/compare/0.16.1...0.17.0) diff --git a/Cargo.toml b/Cargo.toml index 526e29800a..c3f13f55c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.17.0" +version = "0.17.1" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.15.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.15.1" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/README.md b/README.md index a5321126a3..e17d94324f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.17.0" +git2 = "0.17.1" ``` ## Rust version requirements @@ -16,7 +16,7 @@ stable release as well. ## Version of libgit2 -Currently this library requires libgit2 1.6.3 (or newer patch versions). The +Currently this library requires libgit2 1.6.4 (or newer patch versions). The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index 24989fdcdd..19918bfab2 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.15.1+1.6.4 - 2023-04-13 +[0.15.0...0.15.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.15.0+1.6.3...libgit2-sys-0.15.1+1.6.4) + +### Changed + +- Updated to libgit2 [1.6.4](https://github.com/libgit2/libgit2/releases/tag/v1.6.4). + This brings in many changes, including better SSH host key support on Windows and better SSH host key algorithm negotiation. + 1.6.3 is now the minimum supported version. + [#935](TODO) + ## 0.15.0+1.6.3 - 2023-04-02 [0.14.2...0.15.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.14.2+1.5.1...libgit2-sys-0.15.0+1.6.3) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index b21169ad1e..28a1fec657 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.15.0+1.6.3" +version = "0.15.1+1.6.4" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index c050fb3874..24df572ef6 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,7 +14,7 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.range_version("1.6.3".."1.7.0").probe("libgit2") { + if let Ok(lib) = cfg.range_version("1.6.4".."1.7.0").probe("libgit2") { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index c058aa87dc..e6325351ce 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit c058aa87dce4c67a3b86b3349beebd64b7bedcd3 +Subproject commit e6325351ceee58cf56f58bdce61b38907805544f From 55d0e671d7b2357297c9119b821cb87200ab8bef Mon Sep 17 00:00:00 2001 From: Ximo Guanter Date: Thu, 13 Apr 2023 08:27:46 +0200 Subject: [PATCH 684/860] Add links to this PR in changelog --- CHANGELOG.md | 2 +- libgit2-sys/CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36ee314179..c77626b6a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ ### Changed - Updated to libgit2 [1.6.4](https://github.com/libgit2/libgit2/releases/tag/v1.6.4). - [#935](TODO) + [#948](https://github.com/rust-lang/git2-rs/pull/948) ## 0.17.0 - 2023-04-02 [0.16.1...0.17.0](https://github.com/rust-lang/git2-rs/compare/0.16.1...0.17.0) diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index 19918bfab2..ed43fb686c 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -8,7 +8,7 @@ - Updated to libgit2 [1.6.4](https://github.com/libgit2/libgit2/releases/tag/v1.6.4). This brings in many changes, including better SSH host key support on Windows and better SSH host key algorithm negotiation. 1.6.3 is now the minimum supported version. - [#935](TODO) + [#948](https://github.com/rust-lang/git2-rs/pull/948) ## 0.15.0+1.6.3 - 2023-04-02 [0.14.2...0.15.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.14.2+1.5.1...libgit2-sys-0.15.0+1.6.3) From 8656d0e024b5e902c5e8b0dd50498502e8dd9c40 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 16 Apr 2023 10:46:49 -0700 Subject: [PATCH 685/860] Update 1.6.4 changelog entry. The previous looked to be a copy/paste from the previous one. --- libgit2-sys/CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index ed43fb686c..c92232431a 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -6,8 +6,7 @@ ### Changed - Updated to libgit2 [1.6.4](https://github.com/libgit2/libgit2/releases/tag/v1.6.4). - This brings in many changes, including better SSH host key support on Windows and better SSH host key algorithm negotiation. - 1.6.3 is now the minimum supported version. + This brings in a minor fix on Windows when the ProgramData directory does not exist. [#948](https://github.com/rust-lang/git2-rs/pull/948) ## 0.15.0+1.6.3 - 2023-04-02 From 672a0f32db0e2c6acb5892e1e57e7c0b91db7963 Mon Sep 17 00:00:00 2001 From: extrawurst Date: Fri, 17 Feb 2023 13:00:00 +0000 Subject: [PATCH 686/860] support partial stashing #929 try getting tests to work again fix tests cleanup safe api fix unittest --- libgit2-sys/lib.rs | 21 +++++++++ src/lib.rs | 2 + src/repo.rs | 21 ++++++++- src/stash.rs | 111 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 148 insertions(+), 7 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index ad04cac7ed..611e30db87 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1731,6 +1731,7 @@ git_enum! { GIT_STASH_KEEP_INDEX = 1 << 0, GIT_STASH_INCLUDE_UNTRACKED = 1 << 1, GIT_STASH_INCLUDE_IGNORED = 1 << 2, + GIT_STASH_KEEP_ALL = 1 << 3, } } @@ -1754,6 +1755,17 @@ git_enum! { } } +#[repr(C)] +pub struct git_stash_save_options { + pub version: c_uint, + pub flags: c_uint, + pub stasher: *const git_signature, + pub message: *const c_char, + pub paths: git_strarray, +} + +pub const GIT_STASH_SAVE_OPTIONS_VERSION: c_uint = 1; + #[repr(C)] pub struct git_stash_apply_options { pub version: c_uint, @@ -2534,6 +2546,15 @@ extern "C" { flags: c_uint, ) -> c_int; + pub fn git_stash_save_options_init(opts: *mut git_stash_save_options, version: c_uint) + -> c_int; + + pub fn git_stash_save_with_opts( + out: *mut git_oid, + repo: *mut git_repository, + options: *const git_stash_save_options, + ) -> c_int; + pub fn git_stash_apply_init_options( opts: *mut git_stash_apply_options, version: c_uint, diff --git a/src/lib.rs b/src/lib.rs index ef8cb2c9c1..d2bc6f5994 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1465,6 +1465,8 @@ bitflags! { /// All ignored files are also stashed and then cleaned up from /// the working directory const INCLUDE_IGNORED = raw::GIT_STASH_INCLUDE_IGNORED as u32; + /// All changes in the index and working directory are left intact + const KEEP_ALL = raw::GIT_STASH_KEEP_ALL as u32; } } diff --git a/src/repo.rs b/src/repo.rs index a794939be7..79ab0cbbcc 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -12,7 +12,7 @@ use crate::diff::{ binary_cb_c, file_cb_c, hunk_cb_c, line_cb_c, BinaryCb, DiffCallbacks, FileCb, HunkCb, LineCb, }; use crate::oid_array::OidArray; -use crate::stash::{stash_cb, StashApplyOptions, StashCbData}; +use crate::stash::{stash_cb, StashApplyOptions, StashCbData, StashSaveOptions}; use crate::string_array::StringArray; use crate::tagforeach::{tag_foreach_cb, TagForeachCB, TagForeachData}; use crate::util::{self, path_to_repo_path, Binding}; @@ -2844,6 +2844,25 @@ impl Repository { } } + /// + pub fn stash_save_ext( + &mut self, + opts: Option<&mut StashSaveOptions<'_>>, + ) -> Result { + unsafe { + let mut raw_oid = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; + let opts = opts.map(|opts| opts.raw()); + try_call!(raw::git_stash_save_with_opts( + &mut raw_oid, + self.raw(), + opts + )); + Ok(Binding::from_raw(&raw_oid as *const _)) + } + } + /// Apply a single stashed state from the stash list. pub fn stash_apply( &mut self, diff --git a/src/stash.rs b/src/stash.rs index 97e02b5de6..9466247cb9 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -1,10 +1,73 @@ use crate::build::CheckoutBuilder; -use crate::util::Binding; -use crate::{panic, raw, Oid, StashApplyProgress}; +use crate::util::{self, Binding}; +use crate::{panic, raw, IntoCString, Oid, Signature, StashApplyProgress, StashFlags}; use libc::{c_char, c_int, c_void, size_t}; -use std::ffi::CStr; +use std::ffi::{c_uint, CStr, CString}; use std::mem; +#[allow(unused)] +/// Stash application options structure +pub struct StashSaveOptions<'a> { + message: Option, + flags: Option, + stasher: Signature<'a>, + pathspec: Vec, + pathspec_ptrs: Vec<*const c_char>, + raw_opts: raw::git_stash_save_options, +} + +impl<'a> StashSaveOptions<'a> { + /// Creates a default + pub fn new(stasher: Signature<'a>) -> Self { + let mut opts = Self { + message: None, + flags: None, + stasher, + pathspec: Vec::new(), + pathspec_ptrs: Vec::new(), + raw_opts: unsafe { mem::zeroed() }, + }; + assert_eq!( + unsafe { + raw::git_stash_save_options_init( + &mut opts.raw_opts, + raw::GIT_STASH_SAVE_OPTIONS_VERSION, + ) + }, + 0 + ); + opts + } + + /// + pub fn flags(&mut self, flags: Option) -> &mut Self { + self.flags = flags; + self + } + + /// Add to the array of paths patterns to build the stash. + pub fn pathspec(&mut self, pathspec: T) -> &mut Self { + let s = util::cstring_to_repo_path(pathspec).unwrap(); + self.pathspec_ptrs.push(s.as_ptr()); + self.pathspec.push(s); + self + } + + /// Acquire a pointer to the underlying raw options. + /// + /// This function is unsafe as the pointer is only valid so long as this + /// structure is not moved, modified, or used elsewhere. + pub unsafe fn raw(&mut self) -> *const raw::git_stash_save_options { + self.raw_opts.flags = self.flags.unwrap_or_else(StashFlags::empty).bits as c_uint; + self.raw_opts.message = crate::call::convert(&self.message); + self.raw_opts.paths.count = self.pathspec_ptrs.len() as size_t; + self.raw_opts.paths.strings = self.pathspec_ptrs.as_ptr() as *mut _; + self.raw_opts.stasher = self.stasher.raw(); + + &self.raw_opts as *const _ + } +} + /// Stash application progress notification function. /// /// Return `true` to continue processing, or `false` to @@ -151,12 +214,12 @@ extern "C" fn stash_apply_progress_cb( #[cfg(test)] mod tests { - use crate::stash::StashApplyOptions; + use crate::stash::{StashApplyOptions, StashSaveOptions}; use crate::test::repo_init; - use crate::{Repository, StashFlags, Status}; + use crate::{IndexAddOption, Repository, StashFlags, Status}; use std::fs; use std::io::Write; - use std::path::Path; + use std::path::{Path, PathBuf}; fn make_stash(next: C) where @@ -258,4 +321,40 @@ mod tests { assert!(stash_name.starts_with("WIP on main:")); } + + fn create_file(r: &Repository, name: &str, data: &str) -> PathBuf { + let p = Path::new(r.workdir().unwrap()).join(name); + fs::File::create(&p) + .unwrap() + .write(data.as_bytes()) + .unwrap(); + p + } + + #[test] + fn test_stash_save_ext() { + let (_td, mut repo) = repo_init(); + let signature = repo.signature().unwrap(); + + create_file(&repo, "file_a", "foo"); + create_file(&repo, "file_b", "foo"); + + let mut index = repo.index().unwrap(); + index + .add_all(["*"].iter(), IndexAddOption::DEFAULT, None) + .unwrap(); + index.write().unwrap(); + + assert_eq!(repo.statuses(None).unwrap().len(), 2); + + let mut opt = StashSaveOptions::new(signature); + opt.pathspec("file_a"); + repo.stash_save_ext(Some(&mut opt)).unwrap(); + + assert_eq!(repo.statuses(None).unwrap().len(), 0); + + repo.stash_pop(0, None).unwrap(); + + assert_eq!(repo.statuses(None).unwrap().len(), 1); + } } From 088881fa11e3f03bec215dbd53bdcad10de27cd5 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 5 May 2023 12:38:41 -0700 Subject: [PATCH 687/860] Remove mut when not needed A false negative for unused_mut was fixed in https://github.com/rust-lang/rust/pull/110960. --- src/diff.rs | 2 +- src/transport.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/diff.rs b/src/diff.rs index 6949d094e2..e039c76d59 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -266,7 +266,7 @@ impl<'repo> Diff<'repo> { assert!(patch_no > 0); assert!(patch_no <= total_patches); let mut default = DiffFormatEmailOptions::default(); - let mut raw_opts = opts.map_or(&mut default.raw, |opts| &mut opts.raw); + let raw_opts = opts.map_or(&mut default.raw, |opts| &mut opts.raw); let summary = commit.summary_bytes().unwrap(); let mut message = commit.message_bytes(); assert!(message.starts_with(summary)); diff --git a/src/transport.rs b/src/transport.rs index 5d46959486..74446d0caf 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -251,7 +251,7 @@ extern "C" fn subtransport_action( n => panic!("unknown action: {}", n), }; - let mut transport = &mut *(raw_transport as *mut RawSmartSubtransport); + let transport = &mut *(raw_transport as *mut RawSmartSubtransport); // Note: we only need to generate if rpc is on. Else, for receive-pack and upload-pack // libgit2 reuses the stream generated for receive-pack-ls or upload-pack-ls. let generate_stream = From 4d3811afba443517518acd24af3050ce7a4ca5cf Mon Sep 17 00:00:00 2001 From: extrawurst <776816+extrawurst@users.noreply.github.com> Date: Wed, 17 May 2023 19:42:56 -0600 Subject: [PATCH 688/860] Update libgit2-sys/lib.rs Co-authored-by: Eric Huss --- libgit2-sys/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 611e30db87..3dd11978b9 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1758,7 +1758,7 @@ git_enum! { #[repr(C)] pub struct git_stash_save_options { pub version: c_uint, - pub flags: c_uint, + pub flags: u32, pub stasher: *const git_signature, pub message: *const c_char, pub paths: git_strarray, From dfd4abe05f323343efb0299af4576395de48725c Mon Sep 17 00:00:00 2001 From: extrawurst Date: Thu, 25 May 2023 13:39:03 +0200 Subject: [PATCH 689/860] addresses PR review feedback --- src/repo.rs | 2 +- src/stash.rs | 19 +++++-------------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index 79ab0cbbcc..921e2b30e2 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2844,7 +2844,7 @@ impl Repository { } } - /// + /// Like `stash_save` but with more options like selective statshing via path patterns. pub fn stash_save_ext( &mut self, opts: Option<&mut StashSaveOptions<'_>>, diff --git a/src/stash.rs b/src/stash.rs index 9466247cb9..bff9e49dee 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -39,7 +39,7 @@ impl<'a> StashSaveOptions<'a> { opts } - /// + /// Customize optional `flags` field pub fn flags(&mut self, flags: Option) -> &mut Self { self.flags = flags; self @@ -218,7 +218,6 @@ mod tests { use crate::test::repo_init; use crate::{IndexAddOption, Repository, StashFlags, Status}; use std::fs; - use std::io::Write; use std::path::{Path, PathBuf}; fn make_stash(next: C) @@ -230,10 +229,8 @@ mod tests { let p = Path::new(repo.workdir().unwrap()).join("file_b.txt"); println!("using path {:?}", p); - fs::File::create(&p) - .unwrap() - .write("data".as_bytes()) - .unwrap(); + + fs::write(&p, "data".as_bytes()).unwrap(); let rel_p = Path::new("file_b.txt"); assert!(repo.status_file(&rel_p).unwrap() == Status::WT_NEW); @@ -303,10 +300,7 @@ mod tests { let p = Path::new(repo.workdir().unwrap()).join("file_b.txt"); - fs::File::create(&p) - .unwrap() - .write("data".as_bytes()) - .unwrap(); + fs::write(&p, "data".as_bytes()).unwrap(); repo.stash_save2(&signature, None, Some(StashFlags::INCLUDE_UNTRACKED)) .unwrap(); @@ -324,10 +318,7 @@ mod tests { fn create_file(r: &Repository, name: &str, data: &str) -> PathBuf { let p = Path::new(r.workdir().unwrap()).join(name); - fs::File::create(&p) - .unwrap() - .write(data.as_bytes()) - .unwrap(); + fs::write(&p, data).unwrap(); p } From 5807a5afc8731c2447fffc30d30b1a18284f9413 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 27 May 2023 17:21:59 -0700 Subject: [PATCH 690/860] Bump version --- CHANGELOG.md | 7 +++++++ Cargo.toml | 4 ++-- README.md | 2 +- libgit2-sys/CHANGELOG.md | 8 ++++++++ libgit2-sys/Cargo.toml | 2 +- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c77626b6a4..b58bae0baf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 0.17.2 - 2023-05-27 +[0.17.1...0.17.2](https://github.com/rust-lang/git2-rs/compare/0.17.1...0.17.2) + +### Added +- Added support for stashing with options (which can support partial stashing). + [#930](https://github.com/rust-lang/git2-rs/pull/930) + ## 0.17.1 - 2023-04-13 [0.17.0...0.17.1](https://github.com/rust-lang/git2-rs/compare/0.17.0...0.17.1) diff --git a/Cargo.toml b/Cargo.toml index c3f13f55c7..a151754f9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.17.1" +version = "0.17.2" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.15.1" } +libgit2-sys = { path = "libgit2-sys", version = "0.15.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.0", optional = true } diff --git a/README.md b/README.md index e17d94324f..b4cf4f1e69 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.17.1" +git2 = "0.17.2" ``` ## Rust version requirements diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index c92232431a..64ecdec4bb 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.15.2+1.6.4 - 2023-05-27 +[0.15.1...0.15.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.15.1+1.6.4...libgit2-sys-0.15.2+1.6.4) + +### Added + +- Added bindings for stash options. + [#930](https://github.com/rust-lang/git2-rs/pull/930) + ## 0.15.1+1.6.4 - 2023-04-13 [0.15.0...0.15.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.15.0+1.6.3...libgit2-sys-0.15.1+1.6.4) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 28a1fec657..6b0e261707 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.15.1+1.6.4" +version = "0.15.2+1.6.4" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From e672ef457a78c045d622e27eed44db4221619530 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 4 Jun 2023 14:12:41 -0400 Subject: [PATCH 691/860] Fix compilation with specified minimal versions Verified with `cargo +nightly test -Zminimal-versions`. --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a151754f9d..1731a162ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4.8" libgit2-sys = { path = "libgit2-sys", version = "0.15.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] -openssl-sys = { version = "0.9.0", optional = true } +openssl-sys = { version = "0.9.45", optional = true } openssl-probe = { version = "0.1", optional = true } [dev-dependencies] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 6b0e261707..0080c5c09f 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -26,11 +26,11 @@ libssh2-sys = { version = "0.3.0", optional = true } libz-sys = { version = "1.1.0", default-features = false, features = ["libc"] } [build-dependencies] -pkg-config = "0.3.7" +pkg-config = "0.3.15" cc = { version = "1.0.43", features = ['parallel'] } [target.'cfg(unix)'.dependencies] -openssl-sys = { version = "0.9", optional = true } +openssl-sys = { version = "0.9.45", optional = true } [features] ssh = ["libssh2-sys"] From 06fabce04614f0b68f88a753f431b2e196e31db6 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 21 Jul 2023 17:35:54 +0100 Subject: [PATCH 692/860] chore: switch from ctest to ctest2 ctest is nearly unmaintained and emits lots of warnings. Switch to ctest2 to fix those. --- systest/Cargo.toml | 2 +- systest/build.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/systest/Cargo.toml b/systest/Cargo.toml index 9047e7f307..fe5cabcf23 100644 --- a/systest/Cargo.toml +++ b/systest/Cargo.toml @@ -10,4 +10,4 @@ libgit2-sys = { path = "../libgit2-sys", features = ['https', 'ssh'] } libc = "0.2" [build-dependencies] -ctest = "0.2.17" +ctest2 = "0.4" diff --git a/systest/build.rs b/systest/build.rs index ed854e9d09..bb34d9de80 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -2,7 +2,7 @@ use std::env; use std::path::PathBuf; fn main() { - let mut cfg = ctest::TestGenerator::new(); + let mut cfg = ctest2::TestGenerator::new(); if let Some(root) = env::var_os("DEP_GIT2_ROOT") { cfg.include(PathBuf::from(root).join("include")); } From 679e1d776a63f466ee89a158d92f053d14eb5d21 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 21 Jul 2023 17:42:37 +0100 Subject: [PATCH 693/860] chore: run systest on nightly and beta as well with `ctest2` we won't be blocked on gnzlbg/ctest#90. --- .github/workflows/main.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 528f118e8f..567a830852 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,9 +31,7 @@ jobs: shell: bash - run: cargo test --no-default-features - run: cargo test - # skip systest on nightly because it requires the extprim crate which fails to compile on nightly rust - - run: if [[ "${{ matrix.rust }}" != "nightly" ]]; then cargo run --manifest-path systest/Cargo.toml; fi - shell: bash + - run: cargo run --manifest-path systest/Cargo.toml - run: cargo test --manifest-path git2-curl/Cargo.toml rustfmt: From 1a6e0a1e4a1b2c857d617775dc525ff76516ba66 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 21 Jul 2023 17:44:26 +0100 Subject: [PATCH 694/860] chore: specify workspace member directly by `--package/-p` --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 567a830852..dc69771f27 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,8 +31,8 @@ jobs: shell: bash - run: cargo test --no-default-features - run: cargo test - - run: cargo run --manifest-path systest/Cargo.toml - - run: cargo test --manifest-path git2-curl/Cargo.toml + - run: cargo run -p systest + - run: cargo test -p git2-curl rustfmt: name: Rustfmt From ac827bb15e5d68cfa7ded8688fce541507beb079 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 24 Jul 2023 20:19:47 -0700 Subject: [PATCH 695/860] Prepare CI workflows to support merge queues. --- .github/workflows/main.yml | 44 +++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dc69771f27..2fc15f4683 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,7 @@ name: CI -on: [push, pull_request] +on: + pull_request: + merge_group: jobs: test: @@ -42,3 +44,43 @@ jobs: - name: Install Rust run: rustup update stable && rustup default stable && rustup component add rustfmt - run: cargo fmt -- --check + + # These success/failure jobs are here to consolidate the total + # success/failure state of all other jobs. These jobs are then included in + # the GitHub branch protection rule which prevents merges unless all other + # jobs are passing. This makes it easier to manage the list of jobs via this + # yml file and to prevent accidentally adding new jobs without also updating + # the branch protections. + # + # Unfortunately this requires two jobs because the branch protection + # considers skipped jobs as successful. The status check functions like + # success() can only be in an `if` condition. + # + # Beware that success() is false if any dependent job is skipped. See + # https://github.com/orgs/community/discussions/45058. This means there + # cannot be optional jobs. One workaround is to check for all other + # statuses: + # (contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') || contains(needs.*.result, 'failure')) + # but that is a mess. + success: + name: Success gate + runs-on: ubuntu-latest + needs: + - test + - rustfmt + if: "success()" + steps: + - name: mark the job as a success + run: echo success + failure: + name: Failure gate + runs-on: ubuntu-latest + needs: + - test + - rustfmt + if: "!success()" + steps: + - name: mark the job as a failure + run: | + echo One or more jobs failed + exit 1 From c69236c027b7a47bc6c4d19ef407839ac65b7ca0 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 21 Jul 2023 00:59:43 +0100 Subject: [PATCH 696/860] Bump semver incompat versions for all crates --- Cargo.toml | 4 ++-- README.md | 4 ++-- git2-curl/Cargo.toml | 4 ++-- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 2 +- libgit2-sys/libgit2 | 2 +- src/lib.rs | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1731a162ab..b55f759aad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.17.2" +version = "0.18.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "1.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.15.2" } +libgit2-sys = { path = "libgit2-sys", version = "0.16.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.45", optional = true } diff --git a/README.md b/README.md index b4cf4f1e69..7a756bae9a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.17.2" +git2 = "0.18.0" ``` ## Rust version requirements @@ -16,7 +16,7 @@ stable release as well. ## Version of libgit2 -Currently this library requires libgit2 1.6.4 (or newer patch versions). The +Currently this library requires libgit2 1.7.0 (or newer patch versions). The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 8e30c69052..8e4fda1c69 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2-curl" -version = "0.18.0" +version = "0.19.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" @@ -16,7 +16,7 @@ edition = "2018" curl = "0.4.33" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.17", default-features = false } +git2 = { path = "..", version = "0.18", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 0080c5c09f..0667fddc2a 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.15.2+1.6.4" +version = "0.16.0+1.7.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 24df572ef6..af38b0f444 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -14,7 +14,7 @@ fn main() { let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; if try_to_use_system_libgit2 { let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.range_version("1.6.4".."1.7.0").probe("libgit2") { + if let Ok(lib) = cfg.range_version("1.7.0".."1.8.0").probe("libgit2") { for include in &lib.include_paths { println!("cargo:root={}", include.display()); } diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index e6325351ce..3e2baa6d0b 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit e6325351ceee58cf56f58bdce61b38907805544f +Subproject commit 3e2baa6d0bfb42f9016e24cba1733a6ae26a8ae6 diff --git a/src/lib.rs b/src/lib.rs index d2bc6f5994..fd23bad2d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.17")] +#![doc(html_root_url = "https://docs.rs/git2/0.18")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] From 756fa42a3021818ec96d2b27048bd740e89cd9db Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 21 Jul 2023 01:00:04 +0100 Subject: [PATCH 697/860] Update test add_extensions as extentsions are sorted in 1.7. https://github.com/libgit2/libgit2/commit/e25f9a9bb85e062aeff3d0713e35dd1ad31962d3 --- tests/add_extensions.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/add_extensions.rs b/tests/add_extensions.rs index 7d80b705db..57c0eb9762 100644 --- a/tests/add_extensions.rs +++ b/tests/add_extensions.rs @@ -12,10 +12,10 @@ fn test_add_extensions() -> Result<(), Error> { let extensions = unsafe { get_extensions() }?; assert_eq!(extensions.len(), 3); - assert_eq!(extensions.get(0), Some("noop")); + assert_eq!(extensions.get(0), Some("custom")); // The objectformat extension was added in 1.6 - assert_eq!(extensions.get(1), Some("objectformat")); - assert_eq!(extensions.get(2), Some("custom")); + assert_eq!(extensions.get(1), Some("noop")); + assert_eq!(extensions.get(2), Some("objectformat")); Ok(()) } From 500cc9dc45d5e12cf6d3202d9c1b248cd79e41d1 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 21 Jul 2023 01:13:34 +0100 Subject: [PATCH 698/860] xdiff has been moved to `deps` but external xdiff is not supported --- libgit2-sys/build.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index af38b0f444..12b8ad027c 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -49,7 +49,6 @@ fn main() { // Include all cross-platform C files add_c_files(&mut cfg, "libgit2/src/libgit2"); add_c_files(&mut cfg, "libgit2/src/util"); - add_c_files(&mut cfg, "libgit2/src/libgit2/xdiff"); // These are activated by features, but they're all unconditionally always // compiled apparently and have internal #define's to make sure they're @@ -61,6 +60,10 @@ fn main() { cfg.include("libgit2/deps/http-parser") .file("libgit2/deps/http-parser/http_parser.c"); + // external/system xdiff is not yet supported + cfg.include("libgit2/deps/xdiff"); + add_c_files(&mut cfg, "libgit2/deps/xdiff"); + // Use the included PCRE regex backend. // // Ideally these defines would be specific to the pcre files (or placed in From aa17617c96dff0e0f43726a0181ddf408ef6bc72 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 21 Jul 2023 01:13:58 +0100 Subject: [PATCH 699/860] Support new libgit2 IO poll features This change came with Windows schannel support. * GIT_IO_WSAPOLL * GIT_IO_POLL * GIT_IO_SELECT --- libgit2-sys/build.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 12b8ad027c..2506d02486 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -122,6 +122,14 @@ fn main() { features.push_str("#define GIT_USE_NSEC 1\n"); } + if windows { + features.push_str("#define GIT_IO_WSAPOLL 1\n"); + } else { + // Should we fallback to `select` as more systems have that? + features.push_str("#define GIT_IO_POLL 1\n"); + features.push_str("#define GIT_IO_SELECT 1\n"); + } + if target.contains("apple") { features.push_str("#define GIT_USE_STAT_MTIMESPEC 1\n"); } else { From f8ef6b0b20415d0db20ecdd8de89e8dbd8a14d01 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 21 Jul 2023 01:15:54 +0100 Subject: [PATCH 700/860] New system lib dependency `secur32` on Windows This change came with Windows schannel support. --- libgit2-sys/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 2506d02486..6917ed9348 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -210,6 +210,7 @@ fn main() { println!("cargo:rustc-link-lib=rpcrt4"); println!("cargo:rustc-link-lib=ole32"); println!("cargo:rustc-link-lib=crypt32"); + println!("cargo:rustc-link-lib=secur32"); } if target.contains("apple") { From f5d96ab5a4294fbd8e85fa33f3f2cb447186f0f5 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 21 Jul 2023 01:01:21 +0100 Subject: [PATCH 701/860] struct defs changes for supporting shallow clone * New struct `git_fetch_negotiation` * New field `depth` for `git_fetch_options` * New callback `git_transport->shallow_roots`. * Updated `git_transport->negotiate_fetch` param with `git_fetch_negotiation`. * --- libgit2-sys/lib.rs | 15 +++++++++++++-- src/remote.rs | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 3dd11978b9..a77eff5617 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -394,10 +394,20 @@ pub struct git_fetch_options { pub update_fetchhead: c_int, pub download_tags: git_remote_autotag_option_t, pub proxy_opts: git_proxy_options, + pub depth: c_int, pub follow_redirects: git_remote_redirect_t, pub custom_headers: git_strarray, } +#[repr(C)] +pub struct git_fetch_negotiation { + refs: *const *const git_remote_head, + refs_len: size_t, + shallow_roots: *mut git_oid, + shallow_roots_len: size_t, + depth: c_int, +} + git_enum! { pub enum git_remote_autotag_option_t { GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, @@ -1406,10 +1416,11 @@ pub struct git_transport { extern "C" fn( transport: *mut git_transport, repo: *mut git_repository, - refs: *const *const git_remote_head, - count: size_t, + fetch_data: *const git_fetch_negotiation, ) -> c_int, >, + pub shallow_roots: + Option c_int>, pub download_pack: Option< extern "C" fn( transport: *mut git_transport, diff --git a/src/remote.rs b/src/remote.rs index 98f4cd8b6e..757b518600 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -588,6 +588,7 @@ impl<'cb> Binding for FetchOptions<'cb> { prune: crate::call::convert(&self.prune), update_fetchhead: crate::call::convert(&self.update_fetchhead), download_tags: crate::call::convert(&self.download_tags), + depth: 0, // GIT_FETCH_DEPTH_FULL. follow_redirects: self.follow_redirects.raw(), custom_headers: git_strarray { count: self.custom_headers_ptrs.len(), From fdb30224832557706291259358652a93a088077b Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 21 Jul 2023 01:11:51 +0100 Subject: [PATCH 702/860] `git_oid_t` enum to differentiate sha1/sha256 support --- libgit2-sys/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a77eff5617..bd8db8d618 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1147,12 +1147,21 @@ pub struct git_diff_options { pub payload: *mut c_void, pub context_lines: u32, pub interhunk_lines: u32, + pub oid_type: git_oid_t, pub id_abbrev: u16, pub max_size: git_off_t, pub old_prefix: *const c_char, pub new_prefix: *const c_char, } +git_enum! { + pub enum git_oid_t { + GIT_OID_SHA1 = 1, + // SHA256 is still experimental so we are not going to enable it. + /* GIT_OID_SHA256 = 2, */ + } +} + git_enum! { pub enum git_diff_format_t { GIT_DIFF_FORMAT_PATCH = 1, From d92023ddb75ad38cdb38cf061a8a85a840a9bf37 Mon Sep 17 00:00:00 2001 From: Richard Cook Date: Sun, 23 Apr 2023 18:41:12 -0700 Subject: [PATCH 703/860] Update to bitflags 2.1.0 --- Cargo.toml | 2 +- src/lib.rs | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b55f759aad..3cd87eb69d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ edition = "2018" [dependencies] url = "2.0" -bitflags = "1.1.0" +bitflags = "2.1.0" libc = "0.2" log = "0.4.8" libgit2-sys = { path = "libgit2-sys", version = "0.16.0" } diff --git a/src/lib.rs b/src/lib.rs index fd23bad2d3..6dd75093b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -415,6 +415,7 @@ pub enum FileFavor { bitflags! { /// Orderings that may be specified for Revwalk iteration. + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Sort: u32 { /// Sort the repository contents in no particular ordering. /// @@ -449,6 +450,7 @@ impl Sort { bitflags! { /// Types of credentials that can be requested by a credential callback. + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct CredentialType: u32 { #[allow(missing_docs)] const USER_PASS_PLAINTEXT = raw::GIT_CREDTYPE_USERPASS_PLAINTEXT as u32; @@ -485,6 +487,7 @@ impl Default for CredentialType { bitflags! { /// Flags for the `flags` field of an IndexEntry. + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct IndexEntryFlag: u16 { /// Set when the `extended_flags` field is valid. const EXTENDED = raw::GIT_INDEX_ENTRY_EXTENDED as u16; @@ -500,6 +503,7 @@ impl IndexEntryFlag { bitflags! { /// Flags for the `extended_flags` field of an IndexEntry. + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct IndexEntryExtendedFlag: u16 { /// An "intent to add" entry from "git add -N" const INTENT_TO_ADD = raw::GIT_INDEX_ENTRY_INTENT_TO_ADD as u16; @@ -519,6 +523,7 @@ impl IndexEntryExtendedFlag { bitflags! { /// Flags for APIs that add files matching pathspec + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct IndexAddOption: u32 { #[allow(missing_docs)] const DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32; @@ -550,6 +555,7 @@ impl Default for IndexAddOption { bitflags! { /// Flags for `Repository::open_ext` + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct RepositoryOpenFlags: u32 { /// Only open the specified path; don't walk upward searching. const NO_SEARCH = raw::GIT_REPOSITORY_OPEN_NO_SEARCH as u32; @@ -574,6 +580,7 @@ impl RepositoryOpenFlags { bitflags! { /// Flags for the return value of `Repository::revparse` + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct RevparseMode: u32 { /// The spec targeted a single object const SINGLE = raw::GIT_REVPARSE_SINGLE as u32; @@ -592,6 +599,7 @@ impl RevparseMode { bitflags! { /// The results of `merge_analysis` indicating the merge opportunities. + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct MergeAnalysis: u32 { /// No merge is possible. const ANALYSIS_NONE = raw::GIT_MERGE_ANALYSIS_NONE as u32; @@ -622,6 +630,7 @@ impl MergeAnalysis { bitflags! { /// The user's stated preference for merges. + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct MergePreference: u32 { /// No configuration was found that suggests a preferred behavior for /// merge. @@ -643,6 +652,7 @@ impl MergePreference { bitflags! { /// Flags controlling the behavior of ODB lookup operations + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct OdbLookupFlags: u32 { /// Don't call `git_odb_refresh` if the lookup fails. Useful when doing /// a batch of lookup operations for objects that may legitimately not @@ -997,6 +1007,7 @@ bitflags! { /// represents the status of file in the index relative to the HEAD, and the /// `STATUS_WT_*` set of flags represent the status of the file in the /// working directory relative to the index. + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Status: u32 { #[allow(missing_docs)] const CURRENT = raw::GIT_STATUS_CURRENT as u32; @@ -1047,6 +1058,7 @@ impl Status { bitflags! { /// Mode options for RepositoryInitOptions + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct RepositoryInitMode: u32 { /// Use permissions configured by umask - the default const SHARED_UMASK = raw::GIT_REPOSITORY_INIT_SHARED_UMASK as u32; @@ -1179,6 +1191,7 @@ bitflags! { /// Lastly, the following will only be returned for ignore "NONE". /// /// * WD_UNTRACKED - workdir contains untracked files + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct SubmoduleStatus: u32 { #[allow(missing_docs)] const IN_HEAD = raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32; @@ -1275,6 +1288,7 @@ pub enum SubmoduleUpdate { bitflags! { /// ... + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct PathspecFlags: u32 { /// Use the default pathspec matching configuration. const DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32; @@ -1320,6 +1334,7 @@ impl Default for PathspecFlags { bitflags! { /// Types of notifications emitted from checkouts. + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct CheckoutNotificationType: u32 { /// Notification about a conflict. const CONFLICT = raw::GIT_CHECKOUT_NOTIFY_CONFLICT as u32; @@ -1361,6 +1376,7 @@ pub enum DiffFormat { bitflags! { /// Formatting options for diff stats + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct DiffStatsFormat: raw::git_diff_stats_format_t { /// Don't generate any stats const NONE = raw::GIT_DIFF_STATS_NONE; @@ -1431,6 +1447,7 @@ pub enum StashApplyProgress { bitflags! { #[allow(missing_docs)] + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct StashApplyFlags: u32 { #[allow(missing_docs)] const DEFAULT = raw::GIT_STASH_APPLY_DEFAULT as u32; @@ -1453,6 +1470,7 @@ impl Default for StashApplyFlags { bitflags! { #[allow(missing_docs)] + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct StashFlags: u32 { #[allow(missing_docs)] const DEFAULT = raw::GIT_STASH_DEFAULT as u32; @@ -1485,6 +1503,7 @@ impl Default for StashFlags { bitflags! { #[allow(missing_docs)] + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct AttrCheckFlags: u32 { /// Check the working directory, then the index. const FILE_THEN_INDEX = raw::GIT_ATTR_CHECK_FILE_THEN_INDEX as u32; @@ -1505,6 +1524,7 @@ impl Default for AttrCheckFlags { bitflags! { #[allow(missing_docs)] + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct DiffFlags: u32 { /// File(s) treated as binary data. const BINARY = raw::GIT_DIFF_FLAG_BINARY as u32; @@ -1526,6 +1546,7 @@ impl DiffFlags { bitflags! { /// Options for [`Reference::normalize_name`]. + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct ReferenceFormat: u32 { /// No particular normalization. const NORMAL = raw::GIT_REFERENCE_FORMAT_NORMAL as u32; @@ -1578,4 +1599,70 @@ mod tests { assert_eq!(u32::from(FileMode::BlobGroupWritable), 0o100664); assert_eq!(u32::from(FileMode::BlobExecutable), 0o100755); } + + #[test] + fn bitflags_partial_eq() { + use super::{ + AttrCheckFlags, CheckoutNotificationType, CredentialType, DiffFlags, DiffStatsFormat, + IndexAddOption, IndexEntryExtendedFlag, IndexEntryFlag, MergeAnalysis, MergePreference, + OdbLookupFlags, PathspecFlags, ReferenceFormat, RepositoryInitMode, + RepositoryOpenFlags, RevparseMode, Sort, StashApplyFlags, StashFlags, Status, + SubmoduleStatus, + }; + + assert_eq!( + AttrCheckFlags::FILE_THEN_INDEX, + AttrCheckFlags::FILE_THEN_INDEX + ); + assert_eq!( + CheckoutNotificationType::CONFLICT, + CheckoutNotificationType::CONFLICT + ); + assert_eq!( + CredentialType::USER_PASS_PLAINTEXT, + CredentialType::USER_PASS_PLAINTEXT + ); + assert_eq!(DiffFlags::BINARY, DiffFlags::BINARY); + assert_eq!( + DiffStatsFormat::INCLUDE_SUMMARY, + DiffStatsFormat::INCLUDE_SUMMARY + ); + assert_eq!( + IndexAddOption::CHECK_PATHSPEC, + IndexAddOption::CHECK_PATHSPEC + ); + assert_eq!( + IndexEntryExtendedFlag::INTENT_TO_ADD, + IndexEntryExtendedFlag::INTENT_TO_ADD + ); + assert_eq!(IndexEntryFlag::EXTENDED, IndexEntryFlag::EXTENDED); + assert_eq!( + MergeAnalysis::ANALYSIS_FASTFORWARD, + MergeAnalysis::ANALYSIS_FASTFORWARD + ); + assert_eq!( + MergePreference::FASTFORWARD_ONLY, + MergePreference::FASTFORWARD_ONLY + ); + assert_eq!(OdbLookupFlags::NO_REFRESH, OdbLookupFlags::NO_REFRESH); + assert_eq!(PathspecFlags::FAILURES_ONLY, PathspecFlags::FAILURES_ONLY); + assert_eq!( + ReferenceFormat::ALLOW_ONELEVEL, + ReferenceFormat::ALLOW_ONELEVEL + ); + assert_eq!( + RepositoryInitMode::SHARED_ALL, + RepositoryInitMode::SHARED_ALL + ); + assert_eq!(RepositoryOpenFlags::CROSS_FS, RepositoryOpenFlags::CROSS_FS); + assert_eq!(RevparseMode::RANGE, RevparseMode::RANGE); + assert_eq!(Sort::REVERSE, Sort::REVERSE); + assert_eq!( + StashApplyFlags::REINSTATE_INDEX, + StashApplyFlags::REINSTATE_INDEX + ); + assert_eq!(StashFlags::INCLUDE_IGNORED, StashFlags::INCLUDE_IGNORED); + assert_eq!(Status::WT_MODIFIED, Status::WT_MODIFIED); + assert_eq!(SubmoduleStatus::WD_ADDED, SubmoduleStatus::WD_ADDED); + } } From 59a81cac9ada22b5ea6ca2841f5bd1229f1dd659 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 11 Jul 2023 00:46:38 +0100 Subject: [PATCH 704/860] build: `LIBGIT2_NO_VENDOR` to force to use system libgit2 Specify `LIBGIT2_NO_VENDOR` to force to use system libgit2. Due to the additive nature of Cargo features, if some crate in the dependency graph activates `vendored` feature, there is no way to revert it back. This env var serves as a workaround for this purpose. An alternative is having `no_vendored` feature. We still need to modify `build.rs` to make both `vendored` and `no_vendored` play nice with each other (or bail out as they are mutual-exclusive). However, there is no way to activate a Cargo feature via environment variable (see rust-lang/cargo#4829). Altering environment variables may be the only way to interact with some external build systems. It is also pretty common that people don't want to vendor anything and rather to see the build fail than vendoring. Some prior arts: * `OPENSSL_NO_VENDOR` in `openssl` crate, which serves the exact purpose of `LIBGIT2_NO_VENDOR` [^1]. * Crate `ssh2` has a similar `LIBSSH2_SYS_USE_PKG_CONFIG`, but it doesn't force to do so. It still falls back to vendored lib [^2]. * Crate `curl` has a feature `force-system-lib-on-osx` to trump all others features. It was created primarily for Rust releases [^3]. More motivations why this is something we want: * We have no control over transitive dependencies that accidentally activate the vendored feature. And there is no way to turn it off. * If the build environment has the wrong system libgit2, we want build to always fail because that is a real mistake. For example, libgit2 expects a range 1.6.4..1.7.0 and it silently goes vendoring if nothing found. We may want an explicit error like "your system needs a newer libgit2 to proceed". [^1]: https://github.com/sfackler/rust-openssl/blob/50787ed35bf9efa9dd3cbb1993a2564014b67489/openssl/src/lib.rs#L65 [^2]: https://github.com/alexcrichton/ssh2-rs/blob/d9a1dfac4b8c09c5437eb477606b82aa4f67b092/libssh2-sys/build.rs#L22-L33 [^3]: https://github.com/alexcrichton/curl-rust/blob/431babf1dffe205641793353d3d57fdd36fe8534/curl-sys/build.rs#L15-L20 --- README.md | 5 +++++ libgit2-sys/build.rs | 49 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7a756bae9a..01e0353062 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,11 @@ source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. +You can enable the Cargo feature `vendored-libgit2` to always compile and +statically link to a copy of libgit2. Sometimes the libgit2 on the system is +required to be found and used even when `vendored-libgit2` is activated. In +this case, you shall set the environment variable `LIBGIT2_NO_VENDOR=1`. + ## Building git2-rs ```sh diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 6917ed9348..364123bf4e 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -4,22 +4,55 @@ use std::io; use std::path::{Path, PathBuf}; use std::process::Command; +/// Tries to use system libgit2 and emits necessary build script instructions. +fn try_system_libgit2() -> Result { + let mut cfg = pkg_config::Config::new(); + match cfg.range_version("1.7.0".."1.8.0").probe("libgit2") { + Ok(lib) => { + for include in &lib.include_paths { + println!("cargo:root={}", include.display()); + } + Ok(lib) + } + Err(e) => { + println!("cargo:warning=failed to probe system libgit2: {e}"); + Err(e) + } + } +} + fn main() { let https = env::var("CARGO_FEATURE_HTTPS").is_ok(); let ssh = env::var("CARGO_FEATURE_SSH").is_ok(); let vendored = env::var("CARGO_FEATURE_VENDORED").is_ok(); let zlib_ng_compat = env::var("CARGO_FEATURE_ZLIB_NG_COMPAT").is_ok(); + // Specify `LIBGIT2_NO_VENDOR` to force to use system libgit2. + // Due to the additive nature of Cargo features, if some crate in the + // dependency graph activates `vendored` feature, there is no way to revert + // it back. This env var serves as a workaround for this purpose. + println!("cargo:rerun-if-env-changed=LIBGIT2_NO_VENDOR"); + let forced_no_vendor = env::var_os("LIBGIT2_NO_VENDOR").map_or(false, |s| s != "0"); + + if forced_no_vendor { + if try_system_libgit2().is_err() { + panic!( + "\ +The environment variable `LIBGIT2_NO_VENDOR` has been set but no compatible system libgit2 could be found. +The build is now aborting. To disable, unset the variable or use `LIBGIT2_NO_VENDOR=0`. +", + ); + } + + // We've reached here, implying we're using system libgit2. + return; + } + // To use zlib-ng in zlib-compat mode, we have to build libgit2 ourselves. let try_to_use_system_libgit2 = !vendored && !zlib_ng_compat; - if try_to_use_system_libgit2 { - let mut cfg = pkg_config::Config::new(); - if let Ok(lib) = cfg.range_version("1.7.0".."1.8.0").probe("libgit2") { - for include in &lib.include_paths { - println!("cargo:root={}", include.display()); - } - return; - } + if try_to_use_system_libgit2 && try_system_libgit2().is_ok() { + // using system libgit2 has worked + return; } println!("cargo:rustc-cfg=libgit2_vendored"); From 280ced8494558d63888532c06783977215cfe77c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 29 Jul 2023 08:10:23 -0700 Subject: [PATCH 705/860] Fix build error due to bitflags update --- src/stash.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stash.rs b/src/stash.rs index bff9e49dee..6fcd525d2e 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -58,7 +58,7 @@ impl<'a> StashSaveOptions<'a> { /// This function is unsafe as the pointer is only valid so long as this /// structure is not moved, modified, or used elsewhere. pub unsafe fn raw(&mut self) -> *const raw::git_stash_save_options { - self.raw_opts.flags = self.flags.unwrap_or_else(StashFlags::empty).bits as c_uint; + self.raw_opts.flags = self.flags.unwrap_or_else(StashFlags::empty).bits() as c_uint; self.raw_opts.message = crate::call::convert(&self.message); self.raw_opts.paths.count = self.pathspec_ptrs.len() as size_t; self.raw_opts.paths.strings = self.pathspec_ptrs.as_ptr() as *mut _; From fb53225190bf9abfa8becc980fa9150d76555a95 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 29 Jul 2023 09:11:45 -0700 Subject: [PATCH 706/860] Use a better merge-queue success check. --- .github/workflows/main.yml | 41 +++++++++----------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2fc15f4683..30d91e4456 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -45,42 +45,19 @@ jobs: run: rustup update stable && rustup default stable && rustup component add rustfmt - run: cargo fmt -- --check - # These success/failure jobs are here to consolidate the total - # success/failure state of all other jobs. These jobs are then included in - # the GitHub branch protection rule which prevents merges unless all other - # jobs are passing. This makes it easier to manage the list of jobs via this - # yml file and to prevent accidentally adding new jobs without also updating - # the branch protections. - # - # Unfortunately this requires two jobs because the branch protection - # considers skipped jobs as successful. The status check functions like - # success() can only be in an `if` condition. - # - # Beware that success() is false if any dependent job is skipped. See - # https://github.com/orgs/community/discussions/45058. This means there - # cannot be optional jobs. One workaround is to check for all other - # statuses: - # (contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') || contains(needs.*.result, 'failure')) - # but that is a mess. + # The success job is here to consolidate the total success/failure state of + # all other jobs. This job is then included in the GitHub branch protection + # rule which prevents merges unless all other jobs are passing. This makes + # it easier to manage the list of jobs via this yml file and to prevent + # accidentally adding new jobs without also updating the branch protections. success: name: Success gate - runs-on: ubuntu-latest + if: always() needs: - test - rustfmt - if: "success()" - steps: - - name: mark the job as a success - run: echo success - failure: - name: Failure gate runs-on: ubuntu-latest - needs: - - test - - rustfmt - if: "!success()" steps: - - name: mark the job as a failure - run: | - echo One or more jobs failed - exit 1 + - run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' + - name: Done + run: exit 0 From 92008c4696b0c408610b0ba71bc9de78caab2157 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 30 Jul 2023 16:47:52 -0700 Subject: [PATCH 707/860] Publish via GitHub Actions --- .github/workflows/publish.yml | 33 +++++++++++++++++++++++++ CONTRIBUTING.md | 21 +++++++--------- ci/publish.sh | 46 +++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/publish.yml create mode 100755 ci/publish.sh diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000000..a8fa16637d --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,33 @@ +name: Publish +on: + workflow_dispatch: + inputs: + git2: + description: "Publish git2" + type: boolean + default: true + git2_curl: + description: "Publish git2-curl" + type: boolean + default: true + libgit2_sys: + description: "Publish libgit2-sys" + type: boolean + default: true + +permissions: + contents: write + +jobs: + publish: + name: Publish to crates.io + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Publish + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + PUBLISH_GIT2: ${{ inputs.git2 }} + PUBLISH_GIT2_CURL: ${{ inputs.git2_curl }} + PUBLISH_LIBGIT2_SYS: ${{ inputs.libgit2_sys }} + run: ./ci/publish.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d8ab922325..fc5f214d5c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,15 +52,12 @@ Checklist for preparing for a release: - [`libgit2-sys/CHANGELOG.md`](https://github.com/rust-lang/git2-rs/blob/master/libgit2-sys/CHANGELOG.md) - [`git2-curl/CHANGELOG.md`](https://github.com/rust-lang/git2-rs/blob/master/git2-curl/CHANGELOG.md) -To publish the new release: - -- In a fresh clone, make sure you run `git submodule update`. -- For each updated package, run `cargo publish` (`libgit2-sys` then `git2` then `git2-curl`). -- Set tags for each package that was update: - - `git tag 0.16.1` - - `git tag libgit2-sys-0.14.2+1.5.1` - - `git tag git2-curl-0.17.0` -- Push the tags (substitute the "origin" remote name if you are using a different name): - - `git push origin 0.16.1` - - `git push origin libgit2-sys-0.14.2+1.5.1` - - `git push origin git2-curl-0.17.0` +There is a GitHub workflow to handle publishing to crates.io and tagging the release. There are two different ways to run it: + +- In the GitHub web UI: + 1. Go to (you can navigate here via the "Actions" tab at the top). + 2. Click the "Run workflow" drop-down on the right. + 3. Choose which crates to publish. It's OK to leave everything checked, it will skip if it is already published. Uncheck a crate if the version has been bumped in git, but you don't want to publish that particular one, yet. + 4. Click "Run workflow" +- In the CLI: + 1. Run `gh workflow run publish.yml -R rust-lang/git2-rs` diff --git a/ci/publish.sh b/ci/publish.sh new file mode 100755 index 0000000000..69c2556bca --- /dev/null +++ b/ci/publish.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +set -e + +function publish { + publish_this="$1" + crate_name="$2" + manifest="$3" + + if [ "$publish_this" != "true" ] + then + echo "Skipping $crate_name, publish not requested." + return + fi + + # Get the version from Cargo.toml + version=`sed -n -E 's/^version = "(.*)"/\1/p' $manifest` + + # Check crates.io if it is already published + set +e + output=`curl --fail --silent --head https://crates.io/api/v1/crates/$crate_name/$version/download` + res="$?" + set -e + case $res in + 0) + echo "${crate_name}@${version} appears to already be published" + return + ;; + 22) ;; + *) + echo "Failed to check ${crate_name}@${version} res: $res" + echo "$output" + exit 1 + ;; + esac + + cargo publish --manifest-path $manifest --no-verify + + tag="${crate_name}-${version}" + git tag $tag + git push origin "$tag" +} + +publish $PUBLISH_LIBGIT2_SYS libgit2-sys libgit2-sys/Cargo.toml +publish $PUBLISH_GIT2 git2 Cargo.toml +publish $PUBLISH_GIT2_CURL git2-curl git2-curl/Cargo.toml From f371996538b3b389baa5d48d1838bddfce7fae6f Mon Sep 17 00:00:00 2001 From: EFanZh Date: Mon, 24 Jul 2023 10:36:12 +0800 Subject: [PATCH 708/860] Mutable reference should be used with an `FnMut` type --- src/revwalk.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/revwalk.rs b/src/revwalk.rs index 04cf3f3e4f..7837f00d63 100644 --- a/src/revwalk.rs +++ b/src/revwalk.rs @@ -157,7 +157,7 @@ impl<'repo> Revwalk<'repo> { /// the walk. pub fn with_hide_callback<'cb, C>( self, - callback: &'cb C, + callback: &'cb mut C, ) -> Result, Error> where C: FnMut(Oid) -> bool, @@ -170,7 +170,7 @@ impl<'repo> Revwalk<'repo> { raw::git_revwalk_add_hide_cb( r.revwalk.raw(), Some(revwalk_hide_cb::), - callback as *const _ as *mut c_void, + callback as *mut _ as *mut c_void, ); }; Ok(r) @@ -304,8 +304,8 @@ mod tests { walk.reset().unwrap(); walk.push_head().unwrap(); - let hide_cb = |oid| oid == target; - let mut walk = walk.with_hide_callback(&hide_cb).unwrap(); + let mut hide_cb = |oid| oid == target; + let mut walk = walk.with_hide_callback(&mut hide_cb).unwrap(); assert_eq!(walk.by_ref().count(), 0); From f0d52d3127ca1bbf6300b097f6c776c8e42e3a05 Mon Sep 17 00:00:00 2001 From: vallentin Date: Sat, 27 May 2023 12:49:20 +0200 Subject: [PATCH 709/860] Implemented FusedIterator for various iterators --- src/blame.rs | 3 +++ src/commit.rs | 5 +++++ src/diff.rs | 3 +++ src/message.rs | 5 +++++ src/pathspec.rs | 5 ++++- src/reflog.rs | 2 ++ src/remote.rs | 2 ++ src/status.rs | 2 ++ src/string_array.rs | 3 +++ src/tree.rs | 2 ++ 10 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/blame.rs b/src/blame.rs index 496efa9230..337abae83d 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -1,5 +1,6 @@ use crate::util::{self, Binding}; use crate::{raw, signature, Oid, Repository, Signature}; +use std::iter::FusedIterator; use std::marker; use std::mem; use std::ops::Range; @@ -307,6 +308,8 @@ impl<'blame> DoubleEndedIterator for BlameIter<'blame> { } } +impl<'blame> FusedIterator for BlameIter<'blame> {} + impl<'blame> ExactSizeIterator for BlameIter<'blame> {} #[cfg(test)] diff --git a/src/commit.rs b/src/commit.rs index c6e2bd10e5..4887e927e6 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -1,4 +1,5 @@ use libc; +use std::iter::FusedIterator; use std::marker; use std::mem; use std::ops::Range; @@ -376,6 +377,8 @@ impl<'repo, 'commit> DoubleEndedIterator for Parents<'commit, 'repo> { } } +impl<'repo, 'commit> FusedIterator for Parents<'commit, 'repo> {} + impl<'repo, 'commit> ExactSizeIterator for Parents<'commit, 'repo> {} /// Aborts iteration when a commit cannot be found @@ -400,6 +403,8 @@ impl<'commit> DoubleEndedIterator for ParentIds<'commit> { } } +impl<'commit> FusedIterator for ParentIds<'commit> {} + impl<'commit> ExactSizeIterator for ParentIds<'commit> {} impl<'repo> Clone for Commit<'repo> { diff --git a/src/diff.rs b/src/diff.rs index e039c76d59..16595509d3 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -1,5 +1,6 @@ use libc::{c_char, c_int, c_void, size_t}; use std::ffi::CString; +use std::iter::FusedIterator; use std::marker; use std::mem; use std::ops::Range; @@ -959,6 +960,8 @@ impl<'diff> DoubleEndedIterator for Deltas<'diff> { self.range.next_back().and_then(|i| self.diff.get_delta(i)) } } +impl<'diff> FusedIterator for Deltas<'diff> {} + impl<'diff> ExactSizeIterator for Deltas<'diff> {} /// Line origin constants. diff --git a/src/message.rs b/src/message.rs index 398f11659f..a7041da3ae 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,6 +1,7 @@ use core::ops::Range; use std::ffi::CStr; use std::ffi::CString; +use std::iter::FusedIterator; use std::ptr; use libc::{c_char, c_int}; @@ -171,6 +172,8 @@ impl<'pair> Iterator for MessageTrailersStrsIterator<'pair> { } } +impl FusedIterator for MessageTrailersStrsIterator<'_> {} + impl ExactSizeIterator for MessageTrailersStrsIterator<'_> { fn len(&self) -> usize { self.0.range.len() @@ -213,6 +216,8 @@ impl<'pair> Iterator for MessageTrailersBytesIterator<'pair> { } } +impl FusedIterator for MessageTrailersBytesIterator<'_> {} + impl ExactSizeIterator for MessageTrailersBytesIterator<'_> { fn len(&self) -> usize { self.0.range.len() diff --git a/src/pathspec.rs b/src/pathspec.rs index 3df2e76812..48174fcc19 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -1,5 +1,5 @@ use libc::size_t; -use std::iter::IntoIterator; +use std::iter::{FusedIterator, IntoIterator}; use std::marker; use std::ops::Range; use std::path::Path; @@ -297,6 +297,7 @@ impl<'list> DoubleEndedIterator for PathspecEntries<'list> { self.range.next_back().and_then(|i| self.list.entry(i)) } } +impl<'list> FusedIterator for PathspecEntries<'list> {} impl<'list> ExactSizeIterator for PathspecEntries<'list> {} impl<'list> Iterator for PathspecDiffEntries<'list> { @@ -313,6 +314,7 @@ impl<'list> DoubleEndedIterator for PathspecDiffEntries<'list> { self.range.next_back().and_then(|i| self.list.diff_entry(i)) } } +impl<'list> FusedIterator for PathspecDiffEntries<'list> {} impl<'list> ExactSizeIterator for PathspecDiffEntries<'list> {} impl<'list> Iterator for PathspecFailedEntries<'list> { @@ -331,6 +333,7 @@ impl<'list> DoubleEndedIterator for PathspecFailedEntries<'list> { .and_then(|i| self.list.failed_entry(i)) } } +impl<'list> FusedIterator for PathspecFailedEntries<'list> {} impl<'list> ExactSizeIterator for PathspecFailedEntries<'list> {} #[cfg(test)] diff --git a/src/reflog.rs b/src/reflog.rs index 61509191e9..bbd2140ab2 100644 --- a/src/reflog.rs +++ b/src/reflog.rs @@ -1,4 +1,5 @@ use libc::size_t; +use std::iter::FusedIterator; use std::marker; use std::ops::Range; use std::str; @@ -174,6 +175,7 @@ impl<'reflog> DoubleEndedIterator for ReflogIter<'reflog> { self.range.next_back().and_then(|i| self.reflog.get(i)) } } +impl<'reflog> FusedIterator for ReflogIter<'reflog> {} impl<'reflog> ExactSizeIterator for ReflogIter<'reflog> {} #[cfg(test)] diff --git a/src/remote.rs b/src/remote.rs index 757b518600..f36db6844b 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -1,5 +1,6 @@ use libc; use raw::git_strarray; +use std::iter::FusedIterator; use std::marker; use std::mem; use std::ops::Range; @@ -462,6 +463,7 @@ impl<'repo> DoubleEndedIterator for Refspecs<'repo> { .and_then(|i| self.remote.get_refspec(i)) } } +impl<'repo> FusedIterator for Refspecs<'repo> {} impl<'repo> ExactSizeIterator for Refspecs<'repo> {} #[allow(missing_docs)] // not documented in libgit2 :( diff --git a/src/status.rs b/src/status.rs index 024e9fcd62..a5a8cffd39 100644 --- a/src/status.rs +++ b/src/status.rs @@ -1,5 +1,6 @@ use libc::{c_char, c_uint, size_t}; use std::ffi::CString; +use std::iter::FusedIterator; use std::marker; use std::mem; use std::ops::Range; @@ -303,6 +304,7 @@ impl<'a> DoubleEndedIterator for StatusIter<'a> { self.range.next_back().and_then(|i| self.statuses.get(i)) } } +impl<'a> FusedIterator for StatusIter<'a> {} impl<'a> ExactSizeIterator for StatusIter<'a> {} impl<'a> IntoIterator for &'a Statuses<'a> { diff --git a/src/string_array.rs b/src/string_array.rs index 1aa6fbb411..c77ccdab96 100644 --- a/src/string_array.rs +++ b/src/string_array.rs @@ -1,5 +1,6 @@ //! Bindings to libgit2's raw `git_strarray` type +use std::iter::FusedIterator; use std::ops::Range; use std::str; @@ -108,6 +109,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> { self.range.next_back().map(|i| self.arr.get(i)) } } +impl<'a> FusedIterator for Iter<'a> {} impl<'a> ExactSizeIterator for Iter<'a> {} impl<'a> Iterator for IterBytes<'a> { @@ -124,6 +126,7 @@ impl<'a> DoubleEndedIterator for IterBytes<'a> { self.range.next_back().and_then(|i| self.arr.get_bytes(i)) } } +impl<'a> FusedIterator for IterBytes<'a> {} impl<'a> ExactSizeIterator for IterBytes<'a> {} impl Drop for StringArray { diff --git a/src/tree.rs b/src/tree.rs index 2a117b4ca1..78b2413841 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,6 +1,7 @@ use libc::{self, c_char, c_int, c_void}; use std::cmp::Ordering; use std::ffi::{CStr, CString}; +use std::iter::FusedIterator; use std::marker; use std::mem; use std::ops::Range; @@ -401,6 +402,7 @@ impl<'tree> DoubleEndedIterator for TreeIter<'tree> { self.range.next_back().and_then(|i| self.tree.get(i)) } } +impl<'tree> FusedIterator for TreeIter<'tree> {} impl<'tree> ExactSizeIterator for TreeIter<'tree> {} #[cfg(test)] From 18f8ad16b6fccd79d80b6d7ccd93fc6ba8e1f969 Mon Sep 17 00:00:00 2001 From: Paul van der Meijs Date: Sun, 13 Aug 2023 17:48:08 +0200 Subject: [PATCH 710/860] Add binding for `git_blame_buffer` --- libgit2-sys/lib.rs | 6 ++++++ src/blame.rs | 32 +++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index bd8db8d618..6813f18ba4 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -3406,6 +3406,12 @@ extern "C" { ) -> c_int; // blame + pub fn git_blame_buffer( + out: *mut *mut git_blame, + reference: *mut git_blame, + buffer: *const c_char, + buffer_len: size_t, + ) -> c_int; pub fn git_blame_file( out: *mut *mut git_blame, repo: *mut git_repository, diff --git a/src/blame.rs b/src/blame.rs index 337abae83d..4bf41fed1e 100644 --- a/src/blame.rs +++ b/src/blame.rs @@ -1,10 +1,11 @@ use crate::util::{self, Binding}; -use crate::{raw, signature, Oid, Repository, Signature}; +use crate::{raw, signature, Error, Oid, Repository, Signature}; +use libc::c_char; use std::iter::FusedIterator; -use std::marker; use std::mem; use std::ops::Range; use std::path::Path; +use std::{marker, ptr}; /// Opaque structure to hold blame results. pub struct Blame<'repo> { @@ -30,6 +31,24 @@ pub struct BlameIter<'blame> { } impl<'repo> Blame<'repo> { + /// Get blame data for a file that has been modified in memory. + /// + /// Lines that differ between the buffer and the committed version are + /// marked as having a zero OID for their final_commit_id. + pub fn blame_buffer(&self, buffer: &[u8]) -> Result, Error> { + let mut raw = ptr::null_mut(); + + unsafe { + try_call!(raw::git_blame_buffer( + &mut raw, + self.raw, + buffer.as_ptr() as *const c_char, + buffer.len() + )); + Ok(Binding::from_raw(raw)) + } + } + /// Gets the number of hunks that exist in the blame structure. pub fn len(&self) -> usize { unsafe { raw::git_blame_get_hunk_count(self.raw) as usize } @@ -348,6 +367,13 @@ mod tests { assert_eq!(hunk.final_start_line(), 1); assert_eq!(hunk.path(), Some(Path::new("foo/bar"))); assert_eq!(hunk.lines_in_hunk(), 0); - assert!(!hunk.is_boundary()) + assert!(!hunk.is_boundary()); + + let blame_buffer = blame.blame_buffer("\n".as_bytes()).unwrap(); + let line = blame_buffer.get_line(1).unwrap(); + + assert_eq!(blame_buffer.len(), 2); + assert_eq!(blame_buffer.iter().count(), 2); + assert!(line.final_commit_id().is_zero()); } } From e0a329eed1a59668352dfc59cb5008b2576d3eca Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 17 Aug 2023 10:58:32 -0700 Subject: [PATCH 711/860] Update to libgit2 1.7.1 --- README.md | 2 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 2 +- libgit2-sys/libgit2 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 01e0353062..e10fbcbdb4 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ stable release as well. ## Version of libgit2 -Currently this library requires libgit2 1.7.0 (or newer patch versions). The +Currently this library requires libgit2 1.7.1 (or newer patch versions). The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 0667fddc2a..fd2eacc84d 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.16.0+1.7.0" +version = "0.16.0+1.7.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 364123bf4e..b497005832 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -7,7 +7,7 @@ use std::process::Command; /// Tries to use system libgit2 and emits necessary build script instructions. fn try_system_libgit2() -> Result { let mut cfg = pkg_config::Config::new(); - match cfg.range_version("1.7.0".."1.8.0").probe("libgit2") { + match cfg.range_version("1.7.1".."1.8.0").probe("libgit2") { Ok(lib) => { for include in &lib.include_paths { println!("cargo:root={}", include.display()); diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 3e2baa6d0b..a2bde63741 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 3e2baa6d0bfb42f9016e24cba1733a6ae26a8ae6 +Subproject commit a2bde63741977ca0f4ef7db2f609df320be67a08 From 390c6d6cdfa3a64f21cf92bbd00f7717d1f6c460 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 17 Aug 2023 10:58:47 -0700 Subject: [PATCH 712/860] Systest no longer requires stable. --- CONTRIBUTING.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc5f214d5c..1ab0961f1f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,9 +24,8 @@ The following steps can be used to update libgit2: `cargo test -p git2 -p git2-curl` is a good starting point. 4. Run `systest`. This will validate for any C-level API problems. - Unfortunately `systest` does not work on nightly, so you'll need to use stable. - `cargo +stable run -p systest` + `cargo run -p systest` The changelog at can be helpful for seeing what has changed. From e22951ccda903e505b98fcf642d03754c1210485 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 28 Aug 2023 10:19:43 -0700 Subject: [PATCH 713/860] Update changelog for next release. --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ git2-curl/CHANGELOG.md | 5 +++++ libgit2-sys/CHANGELOG.md | 23 +++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b58bae0baf..6cc0d7396c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## 0.18.0 - 2023-08-28 +[0.17.2...0.18.0](https://github.com/rust-lang/git2-rs/compare/0.17.2...git2-0.18.0) + +### Added + +- Added `Blame::blame_buffer` for getting blame data for a file that has been modified in memory. + [#981](https://github.com/rust-lang/git2-rs/pull/981) + +### Changed + +- Updated to libgit2 [1.7.0](https://github.com/libgit2/libgit2/releases/tag/v1.7.0). + [#968](https://github.com/rust-lang/git2-rs/pull/968) +- Updated to libgit2 [1.7.1](https://github.com/libgit2/libgit2/releases/tag/v1.7.1). + [#982](https://github.com/rust-lang/git2-rs/pull/982) +- Switched from bitflags 1.x to 2.1. This brings some small changes to types generated by bitflags. + [#973](https://github.com/rust-lang/git2-rs/pull/973) +- Changed `Revwalk::with_hide_callback` to take a mutable reference to its callback to enforce type safety. + [#970](https://github.com/rust-lang/git2-rs/pull/970) +- Implemented `FusedIterator` for many iterators that can support it. + [#955](https://github.com/rust-lang/git2-rs/pull/955) + +### Fixed + +- Fixed builds with cargo's `-Zminimal-versions`. + [#960](https://github.com/rust-lang/git2-rs/pull/960) + ## 0.17.2 - 2023-05-27 [0.17.1...0.17.2](https://github.com/rust-lang/git2-rs/compare/0.17.1...0.17.2) diff --git a/git2-curl/CHANGELOG.md b/git2-curl/CHANGELOG.md index f20930568e..98867bc28f 100644 --- a/git2-curl/CHANGELOG.md +++ b/git2-curl/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.19.0 - 2023-08-28 +[0.18.0...0.19.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.18.0...git2-curl-0.19.0) + +- Updated to [git2 0.18.0](../CHANGELOG.md#0180---2023-08-26) + ## 0.18.0 - 2023-04-02 [0.17.0...0.18.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.17.0...git2-curl-0.18.0) diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index 64ecdec4bb..3b653bf6a4 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 0.16.0+1.7.1 - 2023-08-28 +[0.15.2...0.16.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.15.2+1.6.4...libgit2-sys-0.16.0+1.7.1) + +### Added + +- Added LIBGIT2_NO_VENDOR environment variable to force using the system libgit2. + [#966](https://github.com/rust-lang/git2-rs/pull/966) +- Added binding for `git_blame_buffer`. + [#981](https://github.com/rust-lang/git2-rs/pull/981) + +### Changed + +- Updated to libgit2 [1.7.0](https://github.com/libgit2/libgit2/releases/tag/v1.7.0). + [#968](https://github.com/rust-lang/git2-rs/pull/968) +- Updated to libgit2 [1.7.1](https://github.com/libgit2/libgit2/releases/tag/v1.7.1). + [#982](https://github.com/rust-lang/git2-rs/pull/982) + +### Fixed + +- Fixed builds with cargo's `-Zminimal-versions`. + [#960](https://github.com/rust-lang/git2-rs/pull/960) + + ## 0.15.2+1.6.4 - 2023-05-27 [0.15.1...0.15.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.15.1+1.6.4...libgit2-sys-0.15.2+1.6.4) From 2aafd803fb40bb0c37b028a6b1d44d811274fc02 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 28 Aug 2023 10:22:14 -0700 Subject: [PATCH 714/860] Fix html_root_url for next release --- git2-curl/src/lib.rs | 2 +- libgit2-sys/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index a0a6c98719..dbdbdc4a6c 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -15,7 +15,7 @@ //! > **NOTE**: At this time this crate likely does not support a `git push` //! > operation, only clones. -#![doc(html_root_url = "https://docs.rs/git2-curl/0.18")] +#![doc(html_root_url = "https://docs.rs/git2-curl/0.19")] #![deny(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 6813f18ba4..6c42d70d2d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.15")] +#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.16")] #![allow(non_camel_case_types, unused_extern_crates)] // This is required to link libz when libssh2-sys is not included. From 8775a6855bf000c93cd5e5ac6232ebe2d0a7ab8f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 28 Aug 2023 12:43:48 -0700 Subject: [PATCH 715/860] Fix publish of submodule. --- .github/workflows/main.yml | 2 ++ .github/workflows/publish.yml | 2 ++ libgit2-sys/CHANGELOG.md | 7 +++++++ libgit2-sys/Cargo.toml | 2 +- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 30d91e4456..97ba7a8d47 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,6 +28,8 @@ jobs: rust: stable steps: - uses: actions/checkout@master + with: + submodules: true - name: Install Rust (rustup) run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} shell: bash diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a8fa16637d..eb3b578f1a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,6 +24,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@master + with: + submodules: true - name: Publish env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index 3b653bf6a4..5f159825f5 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 0.16.1+1.7.1 - 2023-08-28 +[0.16.0...0.16.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.0+1.7.1...libgit2-sys-0.16.1+1.7.1) + +### Fixed + +- Fixed publish of 0.16.0 missing the libgit2 submodule. + ## 0.16.0+1.7.1 - 2023-08-28 [0.15.2...0.16.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.15.2+1.6.4...libgit2-sys-0.16.0+1.7.1) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index fd2eacc84d..78888b9ee6 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.16.0+1.7.1" +version = "0.16.1+1.7.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 952ada3e5ad877d485975abf75ba4c590fdb8fdb Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 16 Sep 2023 09:21:34 -0700 Subject: [PATCH 716/860] Fix visibility of StashSaveOptions and DiffPatchidOptions. --- src/lib.rs | 4 ++-- src/stash.rs | 19 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6dd75093b9..3dd6fe92ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,7 +91,7 @@ pub use crate::config::{Config, ConfigEntries, ConfigEntry}; pub use crate::cred::{Cred, CredentialHelper}; pub use crate::describe::{Describe, DescribeFormatOptions, DescribeOptions}; pub use crate::diff::{Deltas, Diff, DiffDelta, DiffFile, DiffOptions}; -pub use crate::diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind}; +pub use crate::diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind, DiffPatchidOptions}; pub use crate::diff::{DiffFindOptions, DiffHunk, DiffLine, DiffLineType, DiffStats}; pub use crate::email::{Email, EmailCreateOptions}; pub use crate::error::Error; @@ -131,7 +131,7 @@ pub use crate::revert::RevertOptions; pub use crate::revspec::Revspec; pub use crate::revwalk::Revwalk; pub use crate::signature::Signature; -pub use crate::stash::{StashApplyOptions, StashApplyProgressCb, StashCb}; +pub use crate::stash::{StashApplyOptions, StashApplyProgressCb, StashCb, StashSaveOptions}; pub use crate::status::{StatusEntry, StatusIter, StatusOptions, StatusShow, Statuses}; pub use crate::submodule::{Submodule, SubmoduleUpdateOptions}; pub use crate::tag::Tag; diff --git a/src/stash.rs b/src/stash.rs index 6fcd525d2e..ea898e46ba 100644 --- a/src/stash.rs +++ b/src/stash.rs @@ -5,7 +5,6 @@ use libc::{c_char, c_int, c_void, size_t}; use std::ffi::{c_uint, CStr, CString}; use std::mem; -#[allow(unused)] /// Stash application options structure pub struct StashSaveOptions<'a> { message: Option, @@ -72,13 +71,14 @@ impl<'a> StashSaveOptions<'a> { /// /// Return `true` to continue processing, or `false` to /// abort the stash application. +// FIXME: This probably should have been pub(crate) since it is not used anywhere. pub type StashApplyProgressCb<'a> = dyn FnMut(StashApplyProgress) -> bool + 'a; /// This is a callback function you can provide to iterate over all the /// stashed states that will be invoked per entry. +// FIXME: This probably should have been pub(crate) since it is not used anywhere. pub type StashCb<'a> = dyn FnMut(usize, &str, &Oid) -> bool + 'a; -#[allow(unused)] /// Stash application options structure pub struct StashApplyOptions<'cb> { progress: Option>>, @@ -144,22 +144,20 @@ impl<'cb> StashApplyOptions<'cb> { } } -#[allow(unused)] -pub struct StashCbData<'a> { +pub(crate) struct StashCbData<'a> { pub callback: &'a mut StashCb<'a>, } -#[allow(unused)] -pub extern "C" fn stash_cb( +pub(crate) extern "C" fn stash_cb( index: size_t, message: *const c_char, stash_id: *const raw::git_oid, payload: *mut c_void, ) -> c_int { panic::wrap(|| unsafe { - let mut data = &mut *(payload as *mut StashCbData<'_>); + let data = &mut *(payload as *mut StashCbData<'_>); let res = { - let mut callback = &mut data.callback; + let callback = &mut data.callback; callback( index, CStr::from_ptr(message).to_str().unwrap(), @@ -191,15 +189,14 @@ fn convert_progress(progress: raw::git_stash_apply_progress_t) -> StashApplyProg } } -#[allow(unused)] extern "C" fn stash_apply_progress_cb( progress: raw::git_stash_apply_progress_t, payload: *mut c_void, ) -> c_int { panic::wrap(|| unsafe { - let mut options = &mut *(payload as *mut StashApplyOptions<'_>); + let options = &mut *(payload as *mut StashApplyOptions<'_>); let res = { - let mut callback = options.progress.as_mut().unwrap(); + let callback = options.progress.as_mut().unwrap(); callback(convert_progress(progress)) }; From 60086511bc2c334f1c33cf9a7f89abd82878009d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 16 Sep 2023 09:23:11 -0700 Subject: [PATCH 717/860] Don't pretend that TreeWalkCbData is transparent. --- src/tree.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index 78b2413841..9a38244cfa 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -122,10 +122,6 @@ impl<'repo> Tree<'repo> { C: FnMut(&str, &TreeEntry<'_>) -> T, T: Into, { - #[allow(unused)] - struct TreeWalkCbData<'a, T> { - pub callback: &'a mut TreeWalkCb<'a, T>, - } unsafe { let mut data = TreeWalkCbData { callback: &mut callback, @@ -209,6 +205,10 @@ impl<'repo> Tree<'repo> { type TreeWalkCb<'a, T> = dyn FnMut(&str, &TreeEntry<'_>) -> T + 'a; +struct TreeWalkCbData<'a, T> { + callback: &'a mut TreeWalkCb<'a, T>, +} + extern "C" fn treewalk_cb>( root: *const c_char, entry: *const raw::git_tree_entry, @@ -220,8 +220,9 @@ extern "C" fn treewalk_cb>( _ => return -1, }; let entry = entry_from_raw_const(entry); - let payload = payload as *mut &mut TreeWalkCb<'_, T>; - (*payload)(root, &entry).into() + let payload = &mut *(payload as *mut TreeWalkCbData<'_, T>); + let callback = &mut payload.callback; + callback(root, &entry).into() }) { Some(value) => value, None => -1, From 7a80cc202d1e0315c1b38ac459a5d29e207a583f Mon Sep 17 00:00:00 2001 From: blyxyas Date: Wed, 9 Aug 2023 01:35:06 +0200 Subject: [PATCH 718/860] Add shallow cloneing capability --- src/remote.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/remote.rs b/src/remote.rs index f36db6844b..c8f5a935a6 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -41,6 +41,7 @@ pub struct RemoteHead<'remote> { /// Options which can be specified to various fetch operations. pub struct FetchOptions<'cb> { callbacks: Option>, + depth: i32, proxy: Option>, prune: FetchPrune, update_fetchhead: bool, @@ -509,6 +510,7 @@ impl<'cb> FetchOptions<'cb> { follow_redirects: RemoteRedirect::Initial, custom_headers: Vec::new(), custom_headers_ptrs: Vec::new(), + depth: 0, // Not limited depth } } @@ -538,6 +540,17 @@ impl<'cb> FetchOptions<'cb> { self } + /// Set fetch depth, a value less or equal to 0 is interpreted as pull + /// everything (effectively the same as not declaring a limit depth). + + // FIXME(blyxyas): We currently don't have a test for shallow functions + // because libgit2 doesn't support local shallow clones. + // https://github.com/rust-lang/git2-rs/pull/979#issuecomment-1716299900 + pub fn depth(&mut self, depth: i32) -> &mut Self { + self.depth = depth.max(0); + self + } + /// Set how to behave regarding tags on the remote, such as auto-downloading /// tags for objects we're downloading or downloading all of them. /// @@ -590,7 +603,7 @@ impl<'cb> Binding for FetchOptions<'cb> { prune: crate::call::convert(&self.prune), update_fetchhead: crate::call::convert(&self.update_fetchhead), download_tags: crate::call::convert(&self.download_tags), - depth: 0, // GIT_FETCH_DEPTH_FULL. + depth: self.depth, follow_redirects: self.follow_redirects.raw(), custom_headers: git_strarray { count: self.custom_headers_ptrs.len(), From 83c0d98a64188e70e868f9fe8a3bdde0cc09c632 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 20 Sep 2023 11:13:41 -0700 Subject: [PATCH 719/860] Release 0.18.1 --- CHANGELOG.md | 15 +++++++++++++++ Cargo.toml | 2 +- README.md | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cc0d7396c..efdcfcace5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.18.1 - 2023-09-20 +[0.18.0...0.18.1](https://github.com/rust-lang/git2-rs/compare/git2-0.18.0...git2-0.18.1) + +### Added + +- Added `FetchOptions::depth` to set the depth of a fetch or clone, adding support for shallow clones. + [#979](https://github.com/rust-lang/git2-rs/pull/979) + +### Fixed + +- Fixed an internal data type (`TreeWalkCbData`) to not assume it is a transparent type while casting. + [#989](https://github.com/rust-lang/git2-rs/pull/989) +- Fixed so that `DiffPatchidOptions` and `StashSaveOptions` are publicly exported allowing the corresponding APIs to actually be used. + [#988](https://github.com/rust-lang/git2-rs/pull/988) + ## 0.18.0 - 2023-08-28 [0.17.2...0.18.0](https://github.com/rust-lang/git2-rs/compare/0.17.2...git2-0.18.0) diff --git a/Cargo.toml b/Cargo.toml index 3cd87eb69d..316e28b0fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.18.0" +version = "0.18.1" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/README.md b/README.md index e10fbcbdb4..ba75127acc 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.18.0" +git2 = "0.18.1" ``` ## Rust version requirements From f43a7e288708ef2a6d4f1d284b07926d702ed931 Mon Sep 17 00:00:00 2001 From: Aidan Harbison Date: Tue, 31 Oct 2023 14:20:08 -0400 Subject: [PATCH 720/860] Add binding for GIT_OPT_SET_SSL_CERT_LOCATIONS --- src/opts.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/opts.rs b/src/opts.rs index e90bea0b12..270333b6c1 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -195,6 +195,28 @@ pub unsafe fn set_verify_owner_validation(enabled: bool) -> Result<(), Error> { Ok(()) } +/// Set the SSL certificate-authority locations. `file` is the location of a file containing +/// several certificates concatenated together. `path` is the location of a directory holding +/// several certificates, one per file. Either parameter may be `None`, but not both. +pub unsafe fn set_ssl_cert_locations

(file: Option

, path: Option

) -> Result<(), Error> +where + P: IntoCString, +{ + crate::init(); + let file = crate::opt_cstr(file)?; + let path = crate::opt_cstr(path)?; + + unsafe { + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_SSL_CERT_LOCATIONS as libc::c_int, + file, + path + )); + } + + Ok(()) +} + #[cfg(test)] mod test { use super::*; From 7520761f4e2727db5c0cc9a21e72b5a606a2e3e7 Mon Sep 17 00:00:00 2001 From: Aidan Harbison Date: Fri, 3 Nov 2023 12:41:15 -0400 Subject: [PATCH 721/860] Separate functions for SSL CA file / path --- src/opts.rs | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/opts.rs b/src/opts.rs index 270333b6c1..c709fd0c22 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -195,22 +195,38 @@ pub unsafe fn set_verify_owner_validation(enabled: bool) -> Result<(), Error> { Ok(()) } -/// Set the SSL certificate-authority locations. `file` is the location of a file containing -/// several certificates concatenated together. `path` is the location of a directory holding -/// several certificates, one per file. Either parameter may be `None`, but not both. -pub unsafe fn set_ssl_cert_locations

(file: Option

, path: Option

) -> Result<(), Error> +/// Set the SSL certificate-authority location to `file`. `file` is the location +/// of a file containing several certificates concatenated together. +pub unsafe fn set_ssl_cert_file

(file: P) -> Result<(), Error> where P: IntoCString, { crate::init(); - let file = crate::opt_cstr(file)?; - let path = crate::opt_cstr(path)?; unsafe { try_call!(raw::git_libgit2_opts( raw::GIT_OPT_SET_SSL_CERT_LOCATIONS as libc::c_int, - file, - path + file.into_c_string()?.as_ptr(), + core::ptr::null::() + )); + } + + Ok(()) +} + +/// Set the SSL certificate-authority location to `path`. `path` is the location +/// of a directory holding several certificates, one per file. +pub unsafe fn set_ssl_cert_dir

(path: P) -> Result<(), Error> +where + P: IntoCString, +{ + crate::init(); + + unsafe { + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_SSL_CERT_LOCATIONS as libc::c_int, + core::ptr::null::(), + path.into_c_string()?.as_ptr() )); } From 6ab773fa738c0b9db6f49b3a70decf7e7485e61a Mon Sep 17 00:00:00 2001 From: One <43485962+c-git@users.noreply.github.com> Date: Sun, 5 Nov 2023 14:32:11 -0500 Subject: [PATCH 722/860] Update init.rs Add comment indicating that there is more content than init --- examples/init.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/init.rs b/examples/init.rs index 3e447cbdee..ee827087f1 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -1,5 +1,5 @@ /* - * libgit2 "init" example - shows how to initialize a new repo + * libgit2 "init" example - shows how to initialize a new repo (also includes how to do an initial commit) * * Written by the libgit2 contributors * From 210c661d987b6835cc028b2acd2e08264ae9d1db Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 31 Dec 2023 13:10:40 -0800 Subject: [PATCH 723/860] tree: tests: Make the test tree have 8 entries, to allow more thorough testing This will allow testing advancement by more than 1 at a time. --- src/tree.rs | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index 9a38244cfa..55f0254500 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -472,7 +472,7 @@ mod tests { let tree = repo.find_tree(commit.tree_id()).unwrap(); assert_eq!(tree.id(), commit.tree_id()); - assert_eq!(tree.len(), 1); + assert_eq!(tree.len(), 8); for entry in tree_iter(&tree, &repo) { println!("iter entry {:?}", entry.name()); @@ -481,11 +481,14 @@ mod tests { fn setup_repo(td: &TempDir, repo: &Repository) { let mut index = repo.index().unwrap(); - File::create(&td.path().join("foo")) - .unwrap() - .write_all(b"foo") - .unwrap(); - index.add_path(Path::new("foo")).unwrap(); + for n in 0..8 { + let name = format!("f{n}"); + File::create(&td.path().join(&name)) + .unwrap() + .write_all(name.as_bytes()) + .unwrap(); + index.add_path(Path::new(&name)).unwrap(); + } let id = index.write_tree().unwrap(); let sig = repo.signature().unwrap(); let tree = repo.find_tree(id).unwrap(); @@ -515,14 +518,22 @@ mod tests { let tree = repo.find_tree(commit.tree_id()).unwrap(); assert_eq!(tree.id(), commit.tree_id()); - assert_eq!(tree.len(), 1); + assert_eq!(tree.len(), 8); { - let e1 = tree.get(0).unwrap(); + let e0 = tree.get(0).unwrap(); + assert!(e0 == tree.get_id(e0.id()).unwrap()); + assert!(e0 == tree.get_name("f0").unwrap()); + assert!(e0 == tree.get_name_bytes(b"f0").unwrap()); + assert!(e0 == tree.get_path(Path::new("f0")).unwrap()); + assert_eq!(e0.name(), Some("f0")); + e0.to_object(&repo).unwrap(); + + let e1 = tree.get(1).unwrap(); assert!(e1 == tree.get_id(e1.id()).unwrap()); - assert!(e1 == tree.get_name("foo").unwrap()); - assert!(e1 == tree.get_name_bytes(b"foo").unwrap()); - assert!(e1 == tree.get_path(Path::new("foo")).unwrap()); - assert_eq!(e1.name(), Some("foo")); + assert!(e1 == tree.get_name("f1").unwrap()); + assert!(e1 == tree.get_name_bytes(b"f1").unwrap()); + assert!(e1 == tree.get_path(Path::new("f1")).unwrap()); + assert_eq!(e1.name(), Some("f1")); e1.to_object(&repo).unwrap(); } tree.into_object(); @@ -551,20 +562,20 @@ mod tests { let mut ct = 0; tree.walk(TreeWalkMode::PreOrder, |_, entry| { - assert_eq!(entry.name(), Some("foo")); + assert_eq!(entry.name(), Some(format!("f{ct}").as_str())); ct += 1; 0 }) .unwrap(); - assert_eq!(ct, 1); + assert_eq!(ct, 8); let mut ct = 0; tree.walk(TreeWalkMode::PreOrder, |_, entry| { - assert_eq!(entry.name(), Some("foo")); + assert_eq!(entry.name(), Some(format!("f{ct}").as_str())); ct += 1; TreeWalkResult::Ok }) .unwrap(); - assert_eq!(ct, 1); + assert_eq!(ct, 8); } } From 2be11ddb5de2fb2023541e13f037d17db5ee52a0 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 31 Dec 2023 13:11:23 -0800 Subject: [PATCH 724/860] tree::TreeIter: Implement `nth` to make jumping ahead more efficient This means `skip` (which uses `nth`) will also be more efficient. --- src/tree.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tree.rs b/src/tree.rs index 55f0254500..a9ddca0802 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -397,6 +397,9 @@ impl<'tree> Iterator for TreeIter<'tree> { fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + fn nth(&mut self, n: usize) -> Option> { + self.range.nth(n).and_then(|i| self.tree.get(i)) + } } impl<'tree> DoubleEndedIterator for TreeIter<'tree> { fn next_back(&mut self) -> Option> { From 5d0628e6a6958b4695e3b2f50ae29f602d0a1db2 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 31 Dec 2023 13:15:16 -0800 Subject: [PATCH 725/860] tree: tests: Test `TreeIter::nth` --- src/tree.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/tree.rs b/src/tree.rs index a9ddca0802..916cf83c5f 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -482,6 +482,24 @@ mod tests { } } + #[test] + fn smoke_tree_nth() { + let (td, repo) = crate::test::repo_init(); + + setup_repo(&td, &repo); + + let head = repo.head().unwrap(); + let target = head.target().unwrap(); + let commit = repo.find_commit(target).unwrap(); + + let tree = repo.find_tree(commit.tree_id()).unwrap(); + assert_eq!(tree.id(), commit.tree_id()); + assert_eq!(tree.len(), 8); + let mut it = tree.iter(); + let e = it.nth(4).unwrap(); + assert_eq!(e.name(), Some("f4")); + } + fn setup_repo(td: &TempDir, repo: &Repository) { let mut index = repo.index().unwrap(); for n in 0..8 { From c4e033a1c1097f960c0884d46d5cc0910265e7b7 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sun, 7 Jan 2024 11:29:36 -0500 Subject: [PATCH 726/860] Appease latest rustc nightly See https://github.com/rust-lang/rust/pull/118297. --- src/reference.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reference.rs b/src/reference.rs index 92eb18c635..70b22d9f2d 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -16,7 +16,7 @@ use crate::{ // internally const GIT_REFNAME_MAX: usize = 1024; -struct Refdb<'repo>(&'repo Repository); +struct Refdb<'repo>(#[allow(dead_code)] &'repo Repository); /// A structure to represent a git [reference][1]. /// From a316f79c5574e7dfb540234aa7224d438e78bc26 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 11 Jan 2024 07:57:43 -0800 Subject: [PATCH 727/860] Explain reason for `Refdb`. --- src/reference.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/reference.rs b/src/reference.rs index 70b22d9f2d..0af845d7c5 100644 --- a/src/reference.rs +++ b/src/reference.rs @@ -16,6 +16,12 @@ use crate::{ // internally const GIT_REFNAME_MAX: usize = 1024; +/// This is used to logically indicate that a [`raw::git_reference`] or +/// [`raw::git_reference_iterator`] holds a reference to [`raw::git_refdb`]. +/// It is not necessary to have a wrapper like this in the +/// [`marker::PhantomData`], since all that matters is that it is tied to the +/// lifetime of the [`Repository`], but this helps distinguish the actual +/// references involved. struct Refdb<'repo>(#[allow(dead_code)] &'repo Repository); /// A structure to represent a git [reference][1]. From 0885aba72fd7d2542fd7f28b29a3f5ec010dc395 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 11 Jan 2024 08:02:24 -0800 Subject: [PATCH 728/860] Fix some rustdoc warnings --- git2-curl/src/lib.rs | 2 +- src/tree.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index dbdbdc4a6c..99d782ec41 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -35,7 +35,7 @@ use url::Url; struct CurlTransport { handle: Arc>, - /// The URL of the remote server, e.g. "https://github.com/user/repo" + /// The URL of the remote server, e.g. `https://github.com/user/repo` /// /// This is an empty string until the first action is performed. /// If there is an HTTP redirect, this will be updated with the new URL. diff --git a/src/tree.rs b/src/tree.rs index 916cf83c5f..31170ab5e1 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -102,7 +102,7 @@ impl<'repo> Tree<'repo> { /// /// libgit2 requires that the callback be an integer, where 0 indicates a /// successful visit, 1 skips the node, and -1 aborts the traversal completely. - /// You may opt to use the enum [`TreeWalkResult`](TreeWalkResult) instead. + /// You may opt to use the enum [`TreeWalkResult`] instead. /// /// ```ignore /// let mut ct = 0; From 8c92f9f96b31d229ee827f0cbe79250840239764 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sun, 7 Jan 2024 11:20:31 -0500 Subject: [PATCH 729/860] examples: replace structopt with clap See https://github.com/TeXitoi/structopt/issues/525. Currently git2 is the most downloaded dependent of structopt: https://crates.io/crates/structopt/reverse_dependencies. --- Cargo.toml | 2 +- examples/add.rs | 8 ++++---- examples/blame.rs | 12 ++++++------ examples/cat-file.rs | 14 +++++++------- examples/clone.rs | 6 +++--- examples/diff.rs | 22 +++++++++++----------- examples/fetch.rs | 6 +++--- examples/init.rs | 6 +++--- examples/log.rs | 8 ++++---- examples/ls-remote.rs | 6 +++--- examples/pull.rs | 6 +++--- examples/rev-list.rs | 6 +++--- examples/rev-parse.rs | 6 +++--- examples/status.rs | 6 +++--- examples/tag.rs | 6 +++--- 15 files changed, 60 insertions(+), 60 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 316e28b0fc..bcefe8d9b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ openssl-sys = { version = "0.9.45", optional = true } openssl-probe = { version = "0.1", optional = true } [dev-dependencies] -structopt = "0.3" +clap = { version = "4.4.13", features = ["derive"] } time = "0.1.39" tempfile = "3.1.0" diff --git a/examples/add.rs b/examples/add.rs index 25e972c7aa..57c9bb10a9 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -15,15 +15,15 @@ #![deny(warnings)] #![allow(trivial_casts)] +use clap::Parser; use git2::Repository; use std::path::Path; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "spec")] arg_spec: Vec, - #[structopt(name = "dry_run", short = "n", long)] + #[structopt(name = "dry_run", short = 'n', long)] /// dry run flag_dry_run: bool, #[structopt(name = "verbose", short, long)] @@ -73,7 +73,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/blame.rs b/examples/blame.rs index 7cb1b69470..202989b3f0 100644 --- a/examples/blame.rs +++ b/examples/blame.rs @@ -14,25 +14,25 @@ #![deny(warnings)] +use clap::Parser; use git2::{BlameOptions, Repository}; use std::io::{BufRead, BufReader}; use std::path::Path; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] #[allow(non_snake_case)] struct Args { #[structopt(name = "path")] arg_path: String, #[structopt(name = "spec")] arg_spec: Option, - #[structopt(short = "M")] + #[structopt(short = 'M')] /// find line moves within and across files flag_M: bool, - #[structopt(short = "C")] + #[structopt(short = 'C')] /// find line copies within and across files flag_C: bool, - #[structopt(short = "F")] + #[structopt(short = 'F')] /// follow only the first parent commits flag_F: bool, } @@ -96,7 +96,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/cat-file.rs b/examples/cat-file.rs index 0ce21b34aa..6196b9bb9f 100644 --- a/examples/cat-file.rs +++ b/examples/cat-file.rs @@ -16,23 +16,23 @@ use std::io::{self, Write}; +use clap::Parser; use git2::{Blob, Commit, ObjectType, Repository, Signature, Tag, Tree}; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "object")] arg_object: String, - #[structopt(short = "t")] + #[structopt(short = 't')] /// show the object type flag_t: bool, - #[structopt(short = "s")] + #[structopt(short = 's')] /// show the object size flag_s: bool, - #[structopt(short = "e")] + #[structopt(short = 'e')] /// suppress all output flag_e: bool, - #[structopt(short = "p")] + #[structopt(short = 'p')] /// pretty print the contents of the object flag_p: bool, #[structopt(name = "quiet", short, long)] @@ -141,7 +141,7 @@ fn show_sig(header: &str, sig: Option) { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/clone.rs b/examples/clone.rs index 5af73222f0..f6d00b14b6 100644 --- a/examples/clone.rs +++ b/examples/clone.rs @@ -14,14 +14,14 @@ #![deny(warnings)] +use clap::Parser; use git2::build::{CheckoutBuilder, RepoBuilder}; use git2::{FetchOptions, Progress, RemoteCallbacks}; use std::cell::RefCell; use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "url")] arg_url: String, @@ -118,7 +118,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/diff.rs b/examples/diff.rs index 62f165db39..7440149ba0 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -14,12 +14,12 @@ #![deny(warnings)] +use clap::Parser; use git2::{Blob, Diff, DiffOptions, Error, Object, ObjectType, Oid, Repository}; use git2::{DiffDelta, DiffFindOptions, DiffFormat, DiffHunk, DiffLine}; use std::str; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] #[allow(non_snake_case)] struct Args { #[structopt(name = "from_oid")] @@ -56,19 +56,19 @@ struct Args { #[structopt(name = "no-color", long)] /// never use color output flag_no_color: bool, - #[structopt(short = "R")] + #[structopt(short = 'R')] /// swap two inputs flag_R: bool, - #[structopt(name = "text", short = "a", long)] + #[structopt(name = "text", short = 'a', long)] /// treat all files as text flag_text: bool, #[structopt(name = "ignore-space-at-eol", long)] /// ignore changes in whitespace at EOL flag_ignore_space_at_eol: bool, - #[structopt(name = "ignore-space-change", short = "b", long)] + #[structopt(name = "ignore-space-change", short = 'b', long)] /// ignore changes in amount of whitespace flag_ignore_space_change: bool, - #[structopt(name = "ignore-all-space", short = "w", long)] + #[structopt(name = "ignore-all-space", short = 'w', long)] /// ignore whitespace when comparing lines flag_ignore_all_space: bool, #[structopt(name = "ignored", long)] @@ -95,19 +95,19 @@ struct Args { #[structopt(name = "summary", long)] /// output condensed summary of header info flag_summary: bool, - #[structopt(name = "find-renames", short = "M", long)] + #[structopt(name = "find-renames", short = 'M', long)] /// set threshold for finding renames (default 50) flag_find_renames: Option, - #[structopt(name = "find-copies", short = "C", long)] + #[structopt(name = "find-copies", short = 'C', long)] /// set threshold for finding copies (default 50) flag_find_copies: Option, #[structopt(name = "find-copies-harder", long)] /// inspect unmodified files for sources of copies flag_find_copies_harder: bool, - #[structopt(name = "break_rewrites", short = "B", long)] + #[structopt(name = "break_rewrites", short = 'B', long)] /// break complete rewrite changes into pairs flag_break_rewrites: bool, - #[structopt(name = "unified", short = "U", long)] + #[structopt(name = "unified", short = 'U', long)] /// lints of context to show flag_unified: Option, #[structopt(name = "inter-hunk-context", long)] @@ -360,7 +360,7 @@ impl Args { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/fetch.rs b/examples/fetch.rs index 64374a6d48..f3a11dffbd 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -14,12 +14,12 @@ #![deny(warnings)] +use clap::Parser; use git2::{AutotagOption, FetchOptions, RemoteCallbacks, Repository}; use std::io::{self, Write}; use std::str; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "remote")] arg_remote: Option, @@ -119,7 +119,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/init.rs b/examples/init.rs index ee827087f1..3ae79082d7 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -14,11 +14,11 @@ #![deny(warnings)] +use clap::Parser; use git2::{Error, Repository, RepositoryInitMode, RepositoryInitOptions}; use std::path::{Path, PathBuf}; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "directory")] arg_directory: String, @@ -137,7 +137,7 @@ fn parse_shared(shared: &str) -> Result { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/log.rs b/examples/log.rs index ad3bb354d0..8e459cc6f3 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -14,12 +14,12 @@ #![deny(warnings)] +use clap::Parser; use git2::{Commit, DiffOptions, ObjectType, Repository, Signature, Time}; use git2::{DiffFormat, Error, Pathspec}; use std::str; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "topo-order", long)] /// sort commits in topological order @@ -45,7 +45,7 @@ struct Args { #[structopt(name = "skip", long)] /// number of commits to skip flag_skip: Option, - #[structopt(name = "max-count", short = "n", long)] + #[structopt(name = "max-count", short = 'n', long)] /// maximum number of commits to show flag_max_count: Option, #[structopt(name = "merges", long)] @@ -302,7 +302,7 @@ impl Args { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/ls-remote.rs b/examples/ls-remote.rs index 1808459416..f88baaf906 100644 --- a/examples/ls-remote.rs +++ b/examples/ls-remote.rs @@ -14,10 +14,10 @@ #![deny(warnings)] +use clap::Parser; use git2::{Direction, Repository}; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "remote")] arg_remote: String, @@ -43,7 +43,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/pull.rs b/examples/pull.rs index 61251b481b..27f461e546 100644 --- a/examples/pull.rs +++ b/examples/pull.rs @@ -12,12 +12,12 @@ * . */ +use clap::Parser; use git2::Repository; use std::io::{self, Write}; use std::str; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { arg_remote: Option, arg_branch: Option, @@ -200,7 +200,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/rev-list.rs b/examples/rev-list.rs index 9b49877283..2eaed78e9a 100644 --- a/examples/rev-list.rs +++ b/examples/rev-list.rs @@ -15,10 +15,10 @@ #![deny(warnings)] +use clap::Parser; use git2::{Error, Oid, Repository, Revwalk}; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "topo-order", long)] /// sort commits in topological order @@ -97,7 +97,7 @@ fn push(revwalk: &mut Revwalk, id: Oid, hide: bool) -> Result<(), Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/rev-parse.rs b/examples/rev-parse.rs index a465f15a4d..8d3934ea8c 100644 --- a/examples/rev-parse.rs +++ b/examples/rev-parse.rs @@ -14,10 +14,10 @@ #![deny(warnings)] +use clap::Parser; use git2::Repository; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "spec")] arg_spec: String, @@ -52,7 +52,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/status.rs b/examples/status.rs index 4f7bc791c0..0ed61711c8 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -14,12 +14,12 @@ #![deny(warnings)] +use clap::Parser; use git2::{Error, ErrorCode, Repository, StatusOptions, SubmoduleIgnore}; use std::str; use std::time::Duration; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { arg_spec: Vec, #[structopt(name = "long", long)] @@ -433,7 +433,7 @@ impl Args { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/tag.rs b/examples/tag.rs index c44c2887d2..5d2af02063 100644 --- a/examples/tag.rs +++ b/examples/tag.rs @@ -14,11 +14,11 @@ #![deny(warnings)] +use clap::Parser; use git2::{Commit, Error, Repository, Tag}; use std::str; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { arg_tagname: Option, arg_object: Option, @@ -119,7 +119,7 @@ fn print_list_lines(message: Option<&str>, args: &Args) { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), From ed5ac5f0f73b1d61dc418bad20e212d61a7be52a Mon Sep 17 00:00:00 2001 From: LongYinan Date: Tue, 23 Jan 2024 18:15:49 +0800 Subject: [PATCH 730/860] Allow find commit by short hash prefix --- libgit2-sys/lib.rs | 6 ++++++ src/repo.rs | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 6c42d70d2d..420ca6d7d3 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2827,6 +2827,12 @@ extern "C" { repo: *mut git_repository, id: *const git_oid, ) -> c_int; + pub fn git_commit_lookup_prefix( + commit: *mut *mut git_commit, + repo: *mut git_repository, + id: *const git_oid, + len: size_t, + ) -> c_int; pub fn git_commit_message(commit: *const git_commit) -> *const c_char; pub fn git_commit_message_encoding(commit: *const git_commit) -> *const c_char; pub fn git_commit_message_raw(commit: *const git_commit) -> *const c_char; diff --git a/src/repo.rs b/src/repo.rs index 921e2b30e2..6d3b20f8f8 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1418,6 +1418,20 @@ impl Repository { } } + /// Lookup a reference to one of the commits in a repository by short hash. + pub fn find_commit_by_prefix(&self, prefix_hash: &str) -> Result, Error> { + let mut raw = ptr::null_mut(); + unsafe { + try_call!(raw::git_commit_lookup_prefix( + &mut raw, + self.raw(), + Oid::from_str(prefix_hash)?.raw(), + prefix_hash.len() + )); + Ok(Binding::from_raw(raw)) + } + } + /// Creates an `AnnotatedCommit` from the given commit id. pub fn find_annotated_commit(&self, id: Oid) -> Result, Error> { unsafe { From db5c0378c9a21d7c04ac45b09689ab408b936c8a Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 27 Jan 2024 20:03:32 +0200 Subject: [PATCH 731/860] Fix minor typo --- src/diff.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diff.rs b/src/diff.rs index 16595509d3..3070550390 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -287,7 +287,7 @@ impl<'repo> Diff<'repo> { Ok(buf) } - /// Create an patch ID from a diff. + /// Create a patch ID from a diff. pub fn patchid(&self, opts: Option<&mut DiffPatchidOptions>) -> Result { let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], From 3d5fb21508dfdc58a3e8175bb47160d56bd71d0f Mon Sep 17 00:00:00 2001 From: Ewan Breakey Date: Sat, 3 Feb 2024 17:34:03 +1100 Subject: [PATCH 732/860] Fix syntax of example `git fetch` --- src/remote.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remote.rs b/src/remote.rs index c8f5a935a6..807c108e1d 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -290,7 +290,7 @@ impl<'repo> Remote<'repo> { /// /// # Examples /// - /// Example of functionality similar to `git fetch origin/main`: + /// Example of functionality similar to `git fetch origin main`: /// /// ```no_run /// fn fetch_origin_main(repo: git2::Repository) -> Result<(), git2::Error> { From 15e61e406c8b6d045b57fcc0b37594decb35c0d9 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 2 Feb 2024 17:13:06 +0800 Subject: [PATCH 733/860] Allow find tag by prefix hash --- src/repo.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index 6d3b20f8f8..246aa381f5 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1963,6 +1963,20 @@ impl Repository { } } + /// Lookup a tag object by prefix hash from the repository. + pub fn find_tag_by_prefix(&self, prefix_hash: &str) -> Result, Error> { + let mut raw = ptr::null_mut(); + unsafe { + try_call!(raw::git_tag_lookup_prefix( + &mut raw, + self.raw, + Oid::from_str(prefix_hash)?.raw(), + prefix_hash.len() + )); + Ok(Binding::from_raw(raw)) + } + } + /// Delete an existing tag reference. /// /// The tag name will be checked for validity, see `tag` for some rules @@ -4237,4 +4251,26 @@ Committer Name "#, assert_eq!(mm_resolve_author.email(), mailmapped_author.email()); assert_eq!(mm_resolve_committer.email(), mailmapped_committer.email()); } + + #[test] + fn smoke_find_tag_by_prefix() { + let (_td, repo) = crate::test::repo_init(); + let head = repo.head().unwrap(); + let tag_oid = repo + .tag( + "tag", + &repo + .find_object(head.peel_to_commit().unwrap().id(), None) + .unwrap(), + &repo.signature().unwrap(), + "message", + false, + ) + .unwrap(); + let tag = repo.find_tag(tag_oid).unwrap(); + let found_tag = repo + .find_tag_by_prefix(&tag.id().to_string()[0..7]) + .unwrap(); + assert_eq!(tag.id(), found_tag.id()); + } } From 223945f232ab9ddf59dea7b502db0aecfa75cdc2 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 2 Feb 2024 16:41:43 +0800 Subject: [PATCH 734/860] Allow find object by prefix --- libgit2-sys/lib.rs | 7 +++++++ src/repo.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 420ca6d7d3..3de6881842 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2205,6 +2205,13 @@ extern "C" { id: *const git_oid, kind: git_object_t, ) -> c_int; + pub fn git_object_lookup_prefix( + dest: *mut *mut git_object, + repo: *mut git_repository, + id: *const git_oid, + len: size_t, + kind: git_object_t, + ) -> c_int; pub fn git_object_type(obj: *const git_object) -> git_object_t; pub fn git_object_peel( peeled: *mut *mut git_object, diff --git a/src/repo.rs b/src/repo.rs index 6d3b20f8f8..5026923a4e 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1459,6 +1459,25 @@ impl Repository { } } + /// Lookup a reference to one of the objects by id prefix in a repository. + pub fn find_object_by_prefix( + &self, + prefix_hash: &str, + kind: Option, + ) -> Result, Error> { + let mut raw = ptr::null_mut(); + unsafe { + try_call!(raw::git_object_lookup_prefix( + &mut raw, + self.raw(), + Oid::from_str(prefix_hash)?.raw(), + prefix_hash.len(), + kind + )); + Ok(Binding::from_raw(raw)) + } + } + /// Create a new direct reference. /// /// This function will return an error if a reference already exists with @@ -3678,6 +3697,17 @@ mod tests { assert_eq!(repo.head().unwrap().target().unwrap(), main_oid); } + #[test] + fn smoke_find_object_by_prefix() { + let (_td, repo) = crate::test::repo_init(); + let head = repo.head().unwrap().target().unwrap(); + let head = repo.find_commit(head).unwrap(); + let head_id = head.id(); + let head_prefix = &head_id.to_string()[..7]; + let obj = repo.find_object_by_prefix(head_prefix, None).unwrap(); + assert_eq!(obj.id(), head_id); + } + /// create the following: /// /---o4 /// /---o3 From e4cba794784e9a76965641c1b2c3e59290c8c2ff Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 6 Feb 2024 16:08:39 -0500 Subject: [PATCH 735/860] chore: update libgit2 submodule to 1.7.2 libgit2 v1.7.2 includes two CVE fixes: * CVE-2024-24575: https://github.com/libgit2/libgit2/security/advisories/GHSA-54mf-x2rh-hq9v * CVE-2024-24577: https://github.com/libgit2/libgit2/security/advisories/GHSA-j2v7-4f6v-gpg8 --- CHANGELOG.md | 8 ++++++++ Cargo.toml | 4 ++-- README.md | 4 ++-- libgit2-sys/CHANGELOG.md | 3 +++ libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 2 +- libgit2-sys/libgit2 | 2 +- 7 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efdcfcace5..e0176e5836 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.18.2 - 2024-02-06 +[0.18.1...0.18.2](https://github.com/rust-lang/git2-rs/compare/git2-0.18.1...git2-0.18.2) + +### Changed + +- Updated to libgit2 [1.7.2](https://github.com/libgit2/libgit2/releases/tag/v1.7.2). + [#1017](https://github.com/rust-lang/git2-rs/pull/1017) + ## 0.18.1 - 2023-09-20 [0.18.0...0.18.1](https://github.com/rust-lang/git2-rs/compare/git2-0.18.0...git2-0.18.1) diff --git a/Cargo.toml b/Cargo.toml index 316e28b0fc..76c4a62f48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.18.1" +version = "0.18.2" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "2.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.16.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.16.2" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.45", optional = true } diff --git a/README.md b/README.md index ba75127acc..46b56b022f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.18.1" +git2 = "0.18.2" ``` ## Rust version requirements @@ -16,7 +16,7 @@ stable release as well. ## Version of libgit2 -Currently this library requires libgit2 1.7.1 (or newer patch versions). The +Currently this library requires libgit2 1.7.2 (or newer patch versions). The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index 5f159825f5..fb6a0c8a59 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.16.2+1.7.2 - 2024-02-06 +[0.16.1...0.16.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.1+1.7.1...libgit2-sys-0.16.2+1.7.2) + ## 0.16.1+1.7.1 - 2023-08-28 [0.16.0...0.16.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.0+1.7.1...libgit2-sys-0.16.1+1.7.1) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 78888b9ee6..67eaf8dc8e 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.16.1+1.7.1" +version = "0.16.2+1.7.2" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index b497005832..88fce00d6e 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -7,7 +7,7 @@ use std::process::Command; /// Tries to use system libgit2 and emits necessary build script instructions. fn try_system_libgit2() -> Result { let mut cfg = pkg_config::Config::new(); - match cfg.range_version("1.7.1".."1.8.0").probe("libgit2") { + match cfg.range_version("1.7.2".."1.8.0").probe("libgit2") { Ok(lib) => { for include in &lib.include_paths { println!("cargo:root={}", include.display()); diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index a2bde63741..a418d9d4ab 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit a2bde63741977ca0f4ef7db2f609df320be67a08 +Subproject commit a418d9d4ab87bae16b87d8f37143a4687ae0e4b2 From e10093eacfaa33467bf04ccfb3a089a318eeaa6a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 6 Feb 2024 19:09:22 -0800 Subject: [PATCH 736/860] Add link to libgit2 in sys changelog. --- libgit2-sys/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index fb6a0c8a59..236faecd9c 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -3,6 +3,9 @@ ## 0.16.2+1.7.2 - 2024-02-06 [0.16.1...0.16.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.1+1.7.1...libgit2-sys-0.16.2+1.7.2) +- Updated to libgit2 [1.7.2](https://github.com/libgit2/libgit2/releases/tag/v1.7.2). + [#1017](https://github.com/rust-lang/git2-rs/pull/1017) + ## 0.16.1+1.7.1 - 2023-08-28 [0.16.0...0.16.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.0+1.7.1...libgit2-sys-0.16.1+1.7.1) From 57dc89c79c2dd9b127b042abaa3152bedb63aed9 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 6 Feb 2024 19:47:44 -0800 Subject: [PATCH 737/860] Update changelog for next release. --- CHANGELOG.md | 16 +++++++++++++++- libgit2-sys/CHANGELOG.md | 12 +++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0176e5836..5f8de14154 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,23 @@ ## 0.18.2 - 2024-02-06 [0.18.1...0.18.2](https://github.com/rust-lang/git2-rs/compare/git2-0.18.1...git2-0.18.2) +### Added + +- Added `opts::set_ssl_cert_file` and `opts::set_ssl_cert_dir` for setting Certificate Authority file locations. + [#997](https://github.com/rust-lang/git2-rs/pull/997) +- Added `TreeIter::nth` which makes jumping ahead in the iterator more efficient. + [#1004](https://github.com/rust-lang/git2-rs/pull/1004) +- Added `Repository::find_commit_by_prefix` to find a commit by a shortened hash. + [#1011](https://github.com/rust-lang/git2-rs/pull/1011) +- Added `Repository::find_tag_by_prefix` to find a tag by a shortened hash. + [#1015](https://github.com/rust-lang/git2-rs/pull/1015) +- Added `Repository::find_object_by_prefix` to find an object by a shortened hash. + [#1014](https://github.com/rust-lang/git2-rs/pull/1014) + ### Changed -- Updated to libgit2 [1.7.2](https://github.com/libgit2/libgit2/releases/tag/v1.7.2). +- ❗ Updated to libgit2 [1.7.2](https://github.com/libgit2/libgit2/releases/tag/v1.7.2). + This fixes [CVE-2024-24575](https://github.com/libgit2/libgit2/security/advisories/GHSA-54mf-x2rh-hq9v) and [CVE-2024-24577](https://github.com/libgit2/libgit2/security/advisories/GHSA-j2v7-4f6v-gpg8). [#1017](https://github.com/rust-lang/git2-rs/pull/1017) ## 0.18.1 - 2023-09-20 diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index 236faecd9c..fa9bddd441 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -3,7 +3,17 @@ ## 0.16.2+1.7.2 - 2024-02-06 [0.16.1...0.16.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.1+1.7.1...libgit2-sys-0.16.2+1.7.2) -- Updated to libgit2 [1.7.2](https://github.com/libgit2/libgit2/releases/tag/v1.7.2). +### Added + +- Added binding for `git_commit_lookup_prefix`. + [#1011](https://github.com/rust-lang/git2-rs/pull/1011) +- Added binding for `git_object_lookup_prefix`. + [#1014](https://github.com/rust-lang/git2-rs/pull/1014) + +### Changed + +- ❗ Updated to libgit2 [1.7.2](https://github.com/libgit2/libgit2/releases/tag/v1.7.2). + This fixes [CVE-2024-24575](https://github.com/libgit2/libgit2/security/advisories/GHSA-54mf-x2rh-hq9v) and [CVE-2024-24577](https://github.com/libgit2/libgit2/security/advisories/GHSA-j2v7-4f6v-gpg8). [#1017](https://github.com/rust-lang/git2-rs/pull/1017) ## 0.16.1+1.7.1 - 2023-08-28 From d9f2f572a49316e9faf1fa9d6588e95ded4fcacd Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 15 Feb 2024 12:01:34 -0800 Subject: [PATCH 738/860] Temporarily limit systest to stable. --- .github/workflows/main.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 97ba7a8d47..46a71806c4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,7 +35,11 @@ jobs: shell: bash - run: cargo test --no-default-features - run: cargo test + # NOTE: ctest2 is currently failing on 1.78 nightly. Pinning the toolchain + # for now, but we'll need either a new release of ctest2 or some other + # solution soon. - run: cargo run -p systest + if: matrix.rust == 'stable' - run: cargo test -p git2-curl rustfmt: From ea1ad5c7c559a680793f5c793fafad2270329698 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 15 Feb 2024 11:41:32 -0800 Subject: [PATCH 739/860] Create FUNDING.json --- FUNDING.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 FUNDING.json diff --git a/FUNDING.json b/FUNDING.json new file mode 100644 index 0000000000..480d41540c --- /dev/null +++ b/FUNDING.json @@ -0,0 +1,7 @@ +{ + "drips": { + "ethereum": { + "ownedBy": "0x298f6e7CC02D6aa94E2b135f46F1761da7A44E58" + } + } +} From d41851602e0be989ada14ebe6b5ecffcb2e89d86 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 19 Feb 2024 10:48:39 -0800 Subject: [PATCH 740/860] Remove redundant imports. --- src/call.rs | 3 --- src/commit.rs | 1 - src/config.rs | 1 - src/cred.rs | 1 - src/oid.rs | 1 - src/pathspec.rs | 2 +- src/remote.rs | 1 - src/repo.rs | 1 - src/signature.rs | 1 - src/tree.rs | 2 +- src/util.rs | 1 - 11 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/call.rs b/src/call.rs index d9fd234681..95350d2690 100644 --- a/src/call.rs +++ b/src/call.rs @@ -1,5 +1,4 @@ #![macro_use] -use libc; use crate::Error; @@ -54,8 +53,6 @@ mod impls { use std::ffi::CString; use std::ptr; - use libc; - use crate::call::Convert; use crate::{raw, BranchType, ConfigLevel, Direction, ObjectType, ResetType}; use crate::{ diff --git a/src/commit.rs b/src/commit.rs index 4887e927e6..7fef508096 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -1,4 +1,3 @@ -use libc; use std::iter::FusedIterator; use std::marker; use std::mem; diff --git a/src/config.rs b/src/config.rs index ae5c4ff63a..6f12efc322 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,3 @@ -use libc; use std::ffi::CString; use std::marker; use std::path::{Path, PathBuf}; diff --git a/src/cred.rs b/src/cred.rs index 72d9485e82..fc4af1e4eb 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -5,7 +5,6 @@ use std::mem; use std::path::Path; use std::process::{Command, Stdio}; use std::ptr; -use url; use crate::util::Binding; use crate::{raw, Config, Error, IntoCString}; diff --git a/src/oid.rs b/src/oid.rs index 145458aec0..35516cb181 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -1,4 +1,3 @@ -use libc; use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; diff --git a/src/pathspec.rs b/src/pathspec.rs index 48174fcc19..16850dc210 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -1,5 +1,5 @@ use libc::size_t; -use std::iter::{FusedIterator, IntoIterator}; +use std::iter::FusedIterator; use std::marker; use std::ops::Range; use std::path::Path; diff --git a/src/remote.rs b/src/remote.rs index 807c108e1d..a15a095010 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -1,4 +1,3 @@ -use libc; use raw::git_strarray; use std::iter::FusedIterator; use std::marker; diff --git a/src/repo.rs b/src/repo.rs index 93176183fb..b41b42480c 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1,7 +1,6 @@ use libc::{c_char, c_int, c_uint, c_void, size_t}; use std::env; use std::ffi::{CStr, CString, OsStr}; -use std::iter::IntoIterator; use std::mem; use std::path::{Path, PathBuf}; use std::ptr; diff --git a/src/signature.rs b/src/signature.rs index 83fbbf5935..7c9ffb3933 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -1,4 +1,3 @@ -use libc; use std::ffi::CString; use std::fmt; use std::marker; diff --git a/src/tree.rs b/src/tree.rs index 31170ab5e1..ae8fe3b4c5 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,4 +1,4 @@ -use libc::{self, c_char, c_int, c_void}; +use libc::{c_char, c_int, c_void}; use std::cmp::Ordering; use std::ffi::{CStr, CString}; use std::iter::FusedIterator; diff --git a/src/util.rs b/src/util.rs index 5f735bc004..4065492f76 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,6 @@ use libc::{c_char, c_int, size_t}; use std::cmp::Ordering; use std::ffi::{CString, OsStr, OsString}; -use std::iter::IntoIterator; use std::path::{Component, Path, PathBuf}; use crate::{raw, Error}; From 9be523ebb45fc31efbee0b8c0a5570fe9058ddf0 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 19 Feb 2024 10:37:49 -0800 Subject: [PATCH 741/860] Revert "Merge pull request #1021 from ehuss/stable-ctest2" This reverts commit 81a1f16b81e1248df8e3399894af8c4f38dcc3fb, reversing changes made to 987c4e60d3e0e69d58e830527e4c727c776c2c9e. --- .github/workflows/main.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 46a71806c4..97ba7a8d47 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,11 +35,7 @@ jobs: shell: bash - run: cargo test --no-default-features - run: cargo test - # NOTE: ctest2 is currently failing on 1.78 nightly. Pinning the toolchain - # for now, but we'll need either a new release of ctest2 or some other - # solution soon. - run: cargo run -p systest - if: matrix.rust == 'stable' - run: cargo test -p git2-curl rustfmt: From 8d18374343cfb63e67e5dfb207aea6545ebb4966 Mon Sep 17 00:00:00 2001 From: Ronan Pelliard Date: Mon, 11 Mar 2024 16:56:25 +0100 Subject: [PATCH 742/860] Add bindings for mwindow opts --- src/opts.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/opts.rs b/src/opts.rs index c709fd0c22..6c023399c9 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -233,6 +233,99 @@ where Ok(()) } +/// Get the maximum mmap window size +pub fn get_mwindow_size() -> Result { + crate::init(); + + let mut size = 0; + + unsafe { + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_MWINDOW_SIZE as libc::c_int, + &mut size + )); + } + + Ok(size) +} + +/// Set the maximum mmap window size +pub fn set_mwindow_size(size: usize) -> Result<(), Error> { + crate::init(); + + unsafe { + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_MWINDOW_SIZE as libc::c_int, + size + )); + } + + Ok(()) +} + +/// Get the maximum memory that will be mapped in total by the library +pub fn get_mwindow_mapped_limit() -> Result { + crate::init(); + + let mut limit = 0; + + unsafe { + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_MWINDOW_MAPPED_LIMIT as libc::c_int, + &mut limit + )); + } + + Ok(limit) +} + +/// Set the maximum amount of memory that can be mapped at any time +/// by the library. +pub fn set_mwindow_mapped_limit(limit: usize) -> Result<(), Error> { + crate::init(); + + unsafe { + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_MWINDOW_MAPPED_LIMIT as libc::c_int, + limit + )); + } + + Ok(()) +} + +/// Get the maximum number of files that will be mapped at any time by the +/// library. +pub fn get_mwindow_file_limit() -> Result { + crate::init(); + + let mut limit = 0; + + unsafe { + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_MWINDOW_FILE_LIMIT as libc::c_int, + &mut limit + )); + } + + Ok(limit) +} + +/// Set the maximum number of files that can be mapped at any time +/// by the library. The default (0) is unlimited. +pub fn set_mwindow_file_limit(limit: usize) -> Result<(), Error> { + crate::init(); + + unsafe { + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_MWINDOW_FILE_LIMIT as libc::c_int, + limit + )); + } + + Ok(()) +} + #[cfg(test)] mod test { use super::*; @@ -241,4 +334,22 @@ mod test { fn smoke() { strict_hash_verification(false); } + + #[test] + fn mwindow_size() { + assert!(set_mwindow_size(1024).is_ok()); + assert!(get_mwindow_size().unwrap() == 1024); + } + + #[test] + fn mwindow_mapped_limit() { + assert!(set_mwindow_mapped_limit(1024).is_ok()); + assert!(get_mwindow_mapped_limit().unwrap() == 1024); + } + + #[test] + fn mwindow_file_limit() { + assert!(set_mwindow_file_limit(1024).is_ok()); + assert!(get_mwindow_file_limit().unwrap() == 1024); + } } From 1e6524ec0615ef94a775c83532baf21e4b045b66 Mon Sep 17 00:00:00 2001 From: Ronan Pelliard Date: Wed, 13 Mar 2024 20:34:47 +0100 Subject: [PATCH 743/860] use libc::size_t as param type --- src/opts.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/opts.rs b/src/opts.rs index 6c023399c9..acac9a5083 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -234,7 +234,7 @@ where } /// Get the maximum mmap window size -pub fn get_mwindow_size() -> Result { +pub fn get_mwindow_size() -> Result { crate::init(); let mut size = 0; @@ -250,7 +250,7 @@ pub fn get_mwindow_size() -> Result { } /// Set the maximum mmap window size -pub fn set_mwindow_size(size: usize) -> Result<(), Error> { +pub fn set_mwindow_size(size: libc::size_t) -> Result<(), Error> { crate::init(); unsafe { @@ -264,7 +264,7 @@ pub fn set_mwindow_size(size: usize) -> Result<(), Error> { } /// Get the maximum memory that will be mapped in total by the library -pub fn get_mwindow_mapped_limit() -> Result { +pub fn get_mwindow_mapped_limit() -> Result { crate::init(); let mut limit = 0; @@ -281,7 +281,7 @@ pub fn get_mwindow_mapped_limit() -> Result { /// Set the maximum amount of memory that can be mapped at any time /// by the library. -pub fn set_mwindow_mapped_limit(limit: usize) -> Result<(), Error> { +pub fn set_mwindow_mapped_limit(limit: libc::size_t) -> Result<(), Error> { crate::init(); unsafe { @@ -296,7 +296,7 @@ pub fn set_mwindow_mapped_limit(limit: usize) -> Result<(), Error> { /// Get the maximum number of files that will be mapped at any time by the /// library. -pub fn get_mwindow_file_limit() -> Result { +pub fn get_mwindow_file_limit() -> Result { crate::init(); let mut limit = 0; @@ -313,7 +313,7 @@ pub fn get_mwindow_file_limit() -> Result { /// Set the maximum number of files that can be mapped at any time /// by the library. The default (0) is unlimited. -pub fn set_mwindow_file_limit(limit: usize) -> Result<(), Error> { +pub fn set_mwindow_file_limit(limit: libc::size_t) -> Result<(), Error> { crate::init(); unsafe { From 68880b2644f635ae3e73dfd88a56ca66971e463d Mon Sep 17 00:00:00 2001 From: Ronan Pelliard Date: Mon, 18 Mar 2024 13:51:17 +0100 Subject: [PATCH 744/860] make functions unsafe --- src/opts.rs | 114 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 48 deletions(-) diff --git a/src/opts.rs b/src/opts.rs index acac9a5083..88f4eb74b7 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -234,94 +234,106 @@ where } /// Get the maximum mmap window size -pub fn get_mwindow_size() -> Result { +/// +/// # Safety +/// This function is reading a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn get_mwindow_size() -> Result { crate::init(); let mut size = 0; - unsafe { - try_call!(raw::git_libgit2_opts( - raw::GIT_OPT_GET_MWINDOW_SIZE as libc::c_int, - &mut size - )); - } + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_MWINDOW_SIZE as libc::c_int, + &mut size + )); Ok(size) } /// Set the maximum mmap window size -pub fn set_mwindow_size(size: libc::size_t) -> Result<(), Error> { +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn set_mwindow_size(size: libc::size_t) -> Result<(), Error> { crate::init(); - unsafe { - try_call!(raw::git_libgit2_opts( - raw::GIT_OPT_SET_MWINDOW_SIZE as libc::c_int, - size - )); - } + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_MWINDOW_SIZE as libc::c_int, + size + )); Ok(()) } /// Get the maximum memory that will be mapped in total by the library -pub fn get_mwindow_mapped_limit() -> Result { +/// +/// # Safety +/// This function is reading a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn get_mwindow_mapped_limit() -> Result { crate::init(); let mut limit = 0; - unsafe { - try_call!(raw::git_libgit2_opts( - raw::GIT_OPT_GET_MWINDOW_MAPPED_LIMIT as libc::c_int, - &mut limit - )); - } + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_MWINDOW_MAPPED_LIMIT as libc::c_int, + &mut limit + )); Ok(limit) } /// Set the maximum amount of memory that can be mapped at any time /// by the library. -pub fn set_mwindow_mapped_limit(limit: libc::size_t) -> Result<(), Error> { +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn set_mwindow_mapped_limit(limit: libc::size_t) -> Result<(), Error> { crate::init(); - unsafe { - try_call!(raw::git_libgit2_opts( - raw::GIT_OPT_SET_MWINDOW_MAPPED_LIMIT as libc::c_int, - limit - )); - } + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_MWINDOW_MAPPED_LIMIT as libc::c_int, + limit + )); Ok(()) } /// Get the maximum number of files that will be mapped at any time by the /// library. -pub fn get_mwindow_file_limit() -> Result { +/// +/// # Safety +/// This function is reading a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn get_mwindow_file_limit() -> Result { crate::init(); let mut limit = 0; - unsafe { - try_call!(raw::git_libgit2_opts( - raw::GIT_OPT_GET_MWINDOW_FILE_LIMIT as libc::c_int, - &mut limit - )); - } + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_MWINDOW_FILE_LIMIT as libc::c_int, + &mut limit + )); Ok(limit) } /// Set the maximum number of files that can be mapped at any time /// by the library. The default (0) is unlimited. -pub fn set_mwindow_file_limit(limit: libc::size_t) -> Result<(), Error> { +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn set_mwindow_file_limit(limit: libc::size_t) -> Result<(), Error> { crate::init(); - unsafe { - try_call!(raw::git_libgit2_opts( - raw::GIT_OPT_SET_MWINDOW_FILE_LIMIT as libc::c_int, - limit - )); - } + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_MWINDOW_FILE_LIMIT as libc::c_int, + limit + )); Ok(()) } @@ -337,19 +349,25 @@ mod test { #[test] fn mwindow_size() { - assert!(set_mwindow_size(1024).is_ok()); - assert!(get_mwindow_size().unwrap() == 1024); + unsafe { + assert!(set_mwindow_size(1024).is_ok()); + assert!(get_mwindow_size().unwrap() == 1024); + } } #[test] fn mwindow_mapped_limit() { - assert!(set_mwindow_mapped_limit(1024).is_ok()); - assert!(get_mwindow_mapped_limit().unwrap() == 1024); + unsafe { + assert!(set_mwindow_mapped_limit(1024).is_ok()); + assert!(get_mwindow_mapped_limit().unwrap() == 1024); + } } #[test] fn mwindow_file_limit() { - assert!(set_mwindow_file_limit(1024).is_ok()); - assert!(get_mwindow_file_limit().unwrap() == 1024); + unsafe { + assert!(set_mwindow_file_limit(1024).is_ok()); + assert!(get_mwindow_file_limit().unwrap() == 1024); + } } } From 1456fcd4b1ba5198132a97116c2581595b7b28b4 Mon Sep 17 00:00:00 2001 From: Ronan Pelliard Date: Mon, 18 Mar 2024 17:45:39 +0100 Subject: [PATCH 745/860] Release 0.18.3 --- CHANGELOG.md | 15 +++++++++++++++ Cargo.toml | 2 +- README.md | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f8de14154..d5704d9355 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog + +## 0.18.3 - 2024-03-18 +[0.18.2...0.18.3](https://github.com/rust-lang/git2-rs/compare/git2-0.18.2...git2-0.18.3) + +### Added + +- Added `opts::` functions to get / set libgit2 mwindow options + [#1035](https://github.com/rust-lang/git2-rs/pull/1035) + + +### Changed + +- Updated examples to use clap instead of structopt + [#1007](https://github.com/rust-lang/git2-rs/pull/1007) + ## 0.18.2 - 2024-02-06 [0.18.1...0.18.2](https://github.com/rust-lang/git2-rs/compare/git2-0.18.1...git2-0.18.2) diff --git a/Cargo.toml b/Cargo.toml index 3054f976e2..6359ac058c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.18.2" +version = "0.18.3" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/README.md b/README.md index 46b56b022f..70c2247b64 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.18.2" +git2 = "0.18.3" ``` ## Rust version requirements From 389a06f58033e04bc40a1d6321904f5e9005e671 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 19 Mar 2024 08:36:11 -0700 Subject: [PATCH 746/860] Fix publish not following redirect --- ci/publish.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/publish.sh b/ci/publish.sh index 69c2556bca..cfc084699c 100755 --- a/ci/publish.sh +++ b/ci/publish.sh @@ -18,7 +18,7 @@ function publish { # Check crates.io if it is already published set +e - output=`curl --fail --silent --head https://crates.io/api/v1/crates/$crate_name/$version/download` + output=`curl --fail --silent --head --location https://static.crates.io/crates/$crate_name/$version/download` res="$?" set -e case $res in From 18bfc89a4c5badd3869b218caa83e0a422d8e4b4 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 13 Apr 2024 15:21:45 -0700 Subject: [PATCH 747/860] Consistently use the error message from a callback error. --- src/error.rs | 13 ++++++++++++- src/remote_callbacks.rs | 20 +++++--------------- src/transport.rs | 10 +--------- 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/error.rs b/src/error.rs index 6f1c4d4c78..32f943c73f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,7 +1,7 @@ use libc::c_int; use std::env::JoinPathsError; use std::error; -use std::ffi::{CStr, NulError}; +use std::ffi::{CStr, CString, NulError}; use std::fmt; use std::str; @@ -350,6 +350,17 @@ impl Error { pub fn message(&self) -> &str { &self.message } + + /// A low-level convenience to call [`raw::git_error_set_str`] with the + /// information from this error. + /// + /// Returns the [`Error::raw_code`] value of this error, which is often + /// needed from a C callback. + pub(crate) unsafe fn raw_set_git_error(&self) -> raw::git_error_code { + let s = CString::new(self.message()).unwrap(); + raw::git_error_set_str(self.class() as c_int, s.as_ptr()); + self.raw_code() + } } impl error::Error for Error {} diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 1169420bda..4a5f76d853 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -1,5 +1,5 @@ use libc::{c_char, c_int, c_uint, c_void, size_t}; -use std::ffi::{CStr, CString}; +use std::ffi::CStr; use std::mem; use std::ptr; use std::slice; @@ -312,11 +312,7 @@ extern "C" fn credentials_cb( let cred_type = CredentialType::from_bits_truncate(allowed_types as u32); - callback(url, username_from_url, cred_type).map_err(|e| { - let s = CString::new(e.to_string()).unwrap(); - raw::git_error_set_str(e.class() as c_int, s.as_ptr()); - e.raw_code() as c_int - }) + callback(url, username_from_url, cred_type).map_err(|e| e.raw_set_git_error()) }); match ok { Some(Ok(cred)) => { @@ -415,13 +411,7 @@ extern "C" fn certificate_check_cb( match ok { Some(Ok(CertificateCheckStatus::CertificateOk)) => 0, Some(Ok(CertificateCheckStatus::CertificatePassthrough)) => raw::GIT_PASSTHROUGH as c_int, - Some(Err(e)) => { - let s = CString::new(e.message()).unwrap(); - unsafe { - raw::git_error_set_str(e.class() as c_int, s.as_ptr()); - } - e.raw_code() as c_int - } + Some(Err(e)) => unsafe { e.raw_set_git_error() }, None => { // Panic. The *should* get resumed by some future call to check(). -1 @@ -448,7 +438,7 @@ extern "C" fn push_update_reference_cb( }; match callback(refname, status) { Ok(()) => 0, - Err(e) => e.raw_code(), + Err(e) => e.raw_set_git_error(), } }) .unwrap_or(-1) @@ -511,7 +501,7 @@ extern "C" fn push_negotiation_cb( let updates = slice::from_raw_parts(updates as *mut PushUpdate<'_>, len); match callback(updates) { Ok(()) => 0, - Err(e) => e.raw_code(), + Err(e) => e.raw_set_git_error(), } }) .unwrap_or(-1) diff --git a/src/transport.rs b/src/transport.rs index 74446d0caf..3a4660627f 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -259,10 +259,7 @@ extern "C" fn subtransport_action( if generate_stream { let obj = match transport.obj.action(url, action) { Ok(s) => s, - Err(e) => { - set_err(&e); - return e.raw_code() as c_int; - } + Err(e) => return e.raw_set_git_error(), }; *stream = mem::transmute(Box::new(RawSmartSubtransportStream { raw: raw::git_smart_subtransport_stream { @@ -363,11 +360,6 @@ unsafe fn set_err_io(e: &io::Error) { raw::git_error_set_str(raw::GIT_ERROR_NET as c_int, s.as_ptr()); } -unsafe fn set_err(e: &Error) { - let s = CString::new(e.message()).unwrap(); - raw::git_error_set_str(e.raw_class() as c_int, s.as_ptr()); -} - // callback used by smart transports to free a `SmartSubtransportStream` // object. extern "C" fn stream_free(stream: *mut raw::git_smart_subtransport_stream) { From 5a5c86da9e054ca6cc52c2ad1f3d54dca581a039 Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Sat, 13 Apr 2024 20:08:42 -0700 Subject: [PATCH 748/860] Improve docs for PushUpdate I took some of the phrasing from https://libgit2.org/libgit2/#HEAD/type/git_push_update Before looking at the code, I didn't realize that the functions returning `None` means the reference name is not UTF-8, as opposed to the reference not existing. --- src/push_update.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/push_update.rs b/src/push_update.rs index 3f74a2506b..97bebb1921 100644 --- a/src/push_update.rs +++ b/src/push_update.rs @@ -28,17 +28,17 @@ impl PushUpdate<'_> { unsafe { crate::opt_bytes(self, (*self.raw).src_refname).unwrap() } } - /// Returns the source name of the reference. + /// Returns the source name of the reference, or None if it is not valid UTF-8. pub fn src_refname(&self) -> Option<&str> { str::from_utf8(self.src_refname_bytes()).ok() } - /// Returns the destination name of the reference as a byte slice. + /// Returns the name of the reference to update on the server as a byte slice. pub fn dst_refname_bytes(&self) -> &[u8] { unsafe { crate::opt_bytes(self, (*self.raw).dst_refname).unwrap() } } - /// Returns the destination name of the reference. + /// Returns the name of the reference to update on the server, or None if it is not valid UTF-8. pub fn dst_refname(&self) -> Option<&str> { str::from_utf8(self.dst_refname_bytes()).ok() } From 08c18edf9039c506725cfc7d919c96761c0af359 Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Sat, 13 Apr 2024 20:34:40 -0700 Subject: [PATCH 749/860] docs: unify docs for callback types and functions that set callbacks This was motivated by the observations that: - The [`PushNegotiation` docstring] was previously much more informative than the docstring for `push_negotiation`. - The `PushNegotiation` docstring does not seem to be accessible via https://docs.rs/git2/0.18.3/git2/index.html. Only the less helpful docstring is accessible at https://docs.rs/git2/0.18.3/git2/struct.RemoteCallbacks.html#method.push_negotiation. [`PushNegotiation` docstring]: https://github.com/rust-lang/git2-rs/commit/920c8380007b6e86a63773758085c07a3f17f514#diff-ccd8cf48c67bd6cc71379f93a6b51abdb10954497a0db353908a7cf20995ef61R92-R99 --- src/remote_callbacks.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index 1169420bda..ade11bd471 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -83,13 +83,16 @@ pub type PushTransferProgress<'a> = dyn FnMut(usize, usize, usize) + 'a; /// Callback for pack progress /// +/// Be aware that this is called inline with pack building operations, +/// so performance may be affected. +/// /// Parameters: /// * stage /// * current /// * total pub type PackProgress<'a> = dyn FnMut(PackBuilderStage, usize, usize) + 'a; -/// Callback used to inform of upcoming updates. +/// The callback is called once between the negotiation step and the upload. /// /// The argument is a slice containing the updates which will be sent as /// commands to the destination. @@ -204,6 +207,11 @@ impl<'a> RemoteCallbacks<'a> { } /// The callback through which progress of push transfer is monitored + /// + /// Parameters: + /// * current + /// * total + /// * bytes pub fn push_transfer_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> where F: FnMut(usize, usize, usize) + 'a, @@ -213,8 +221,14 @@ impl<'a> RemoteCallbacks<'a> { } /// Function to call with progress information during pack building. + /// /// Be aware that this is called inline with pack building operations, /// so performance may be affected. + /// + /// Parameters: + /// * stage + /// * current + /// * total pub fn pack_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> where F: FnMut(PackBuilderStage, usize, usize) + 'a, @@ -224,7 +238,11 @@ impl<'a> RemoteCallbacks<'a> { } /// The callback is called once between the negotiation step and the upload. - /// It provides information about what updates will be performed. + /// + /// The argument to the callback is a slice containing the updates which + /// will be sent as commands to the destination. + /// + /// The push is cancelled if the callback returns an error. pub fn push_negotiation(&mut self, cb: F) -> &mut RemoteCallbacks<'a> where F: FnMut(&[PushUpdate<'_>]) -> Result<(), Error> + 'a, From 9c9305e7c57a9f9691ac2fe3a26a985f1219be88 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 15 Apr 2024 10:12:19 -0700 Subject: [PATCH 750/860] Fix indentation in documentation of callbacks. --- src/remote_callbacks.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/remote_callbacks.rs b/src/remote_callbacks.rs index ade11bd471..0f741035db 100644 --- a/src/remote_callbacks.rs +++ b/src/remote_callbacks.rs @@ -76,9 +76,9 @@ pub type PushUpdateReference<'a> = dyn FnMut(&str, Option<&str>) -> Result<(), E /// Callback for push transfer progress /// /// Parameters: -/// * current -/// * total -/// * bytes +/// * current +/// * total +/// * bytes pub type PushTransferProgress<'a> = dyn FnMut(usize, usize, usize) + 'a; /// Callback for pack progress @@ -87,9 +87,9 @@ pub type PushTransferProgress<'a> = dyn FnMut(usize, usize, usize) + 'a; /// so performance may be affected. /// /// Parameters: -/// * stage -/// * current -/// * total +/// * stage +/// * current +/// * total pub type PackProgress<'a> = dyn FnMut(PackBuilderStage, usize, usize) + 'a; /// The callback is called once between the negotiation step and the upload. @@ -209,9 +209,9 @@ impl<'a> RemoteCallbacks<'a> { /// The callback through which progress of push transfer is monitored /// /// Parameters: - /// * current - /// * total - /// * bytes + /// * current + /// * total + /// * bytes pub fn push_transfer_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> where F: FnMut(usize, usize, usize) + 'a, @@ -226,9 +226,9 @@ impl<'a> RemoteCallbacks<'a> { /// so performance may be affected. /// /// Parameters: - /// * stage - /// * current - /// * total + /// * stage + /// * current + /// * total pub fn pack_progress(&mut self, cb: F) -> &mut RemoteCallbacks<'a> where F: FnMut(PackBuilderStage, usize, usize) + 'a, From b534e13f38c65f1c70b90f6510872f28d3520023 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Fri, 1 Mar 2024 23:42:48 +0800 Subject: [PATCH 751/860] libgit2: Bump to v1.8.0 --- libgit2-sys/build.rs | 2 +- libgit2-sys/libgit2 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 88fce00d6e..6f85060512 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -7,7 +7,7 @@ use std::process::Command; /// Tries to use system libgit2 and emits necessary build script instructions. fn try_system_libgit2() -> Result { let mut cfg = pkg_config::Config::new(); - match cfg.range_version("1.7.2".."1.8.0").probe("libgit2") { + match cfg.range_version("1.8.0".."1.9.0").probe("libgit2") { Ok(lib) => { for include in &lib.include_paths { println!("cargo:root={}", include.display()); diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index a418d9d4ab..d74d491481 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit a418d9d4ab87bae16b87d8f37143a4687ae0e4b2 +Subproject commit d74d491481831ddcd23575d376e56d2197e95910 From 7fa64c619f67cb6035330bd71b798b8e114f6f02 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sat, 2 Mar 2024 21:08:50 +0800 Subject: [PATCH 752/860] remote: Update struct representation for `git_push_options` See https://github.com/libgit2/libgit2/pull/6439. --- libgit2-sys/lib.rs | 1 + src/remote.rs | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 3de6881842..5d997bc059 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -981,6 +981,7 @@ pub struct git_push_options { pub proxy_opts: git_proxy_options, pub follow_redirects: git_remote_redirect_t, pub custom_headers: git_strarray, + pub remote_push_options: git_strarray, } pub type git_tag_foreach_cb = diff --git a/src/remote.rs b/src/remote.rs index a15a095010..1909766c76 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -58,6 +58,8 @@ pub struct PushOptions<'cb> { follow_redirects: RemoteRedirect, custom_headers: Vec, custom_headers_ptrs: Vec<*const c_char>, + remote_push_options: Vec, + remote_push_options_ptrs: Vec<*const c_char>, } /// Holds callbacks for a connection to a `Remote`. Disconnects when dropped @@ -628,6 +630,8 @@ impl<'cb> PushOptions<'cb> { follow_redirects: RemoteRedirect::Initial, custom_headers: Vec::new(), custom_headers_ptrs: Vec::new(), + remote_push_options: Vec::new(), + remote_push_options_ptrs: Vec::new(), } } @@ -673,6 +677,20 @@ impl<'cb> PushOptions<'cb> { self.custom_headers_ptrs = self.custom_headers.iter().map(|s| s.as_ptr()).collect(); self } + + /// Set "push options" to deliver to the remote. + pub fn remote_push_options(&mut self, remote_push_options: &[&str]) -> &mut Self { + self.remote_push_options = remote_push_options + .iter() + .map(|&s| CString::new(s).unwrap()) + .collect(); + self.remote_push_options_ptrs = self + .remote_push_options + .iter() + .map(|s| s.as_ptr()) + .collect(); + self + } } impl<'cb> Binding for PushOptions<'cb> { @@ -700,6 +718,10 @@ impl<'cb> Binding for PushOptions<'cb> { count: self.custom_headers_ptrs.len(), strings: self.custom_headers_ptrs.as_ptr() as *mut _, }, + remote_push_options: git_strarray { + count: self.remote_push_options.len(), + strings: self.remote_push_options_ptrs.as_ptr() as *mut _, + }, } } } From cb8bbc611390764e3d7e6397759864dc2f67833d Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sat, 2 Mar 2024 22:28:11 +0800 Subject: [PATCH 753/860] lib: Add `RemoteUpdateFlags` bitflag --- libgit2-sys/lib.rs | 7 +++++++ src/lib.rs | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5d997bc059..5f72b0c39a 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -366,6 +366,13 @@ pub struct git_indexer_options { pub type git_remote_ready_cb = Option c_int>; +git_enum! { + pub enum git_remote_update_flags { + GIT_REMOTE_UPDATE_FETCHHEAD = 1 << 0, + GIT_REMOTE_UPDATE_REPORT_UNCHANGED = 1 << 1, + } +} + #[repr(C)] pub struct git_remote_callbacks { pub version: c_uint, diff --git a/src/lib.rs b/src/lib.rs index 3dd6fe92ee..48ec7c01cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -662,6 +662,17 @@ bitflags! { } } +bitflags! { + /// How to handle reference updates. + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + pub struct RemoteUpdateFlags: u32 { + /// Write the fetch results to FETCH_HEAD. + const UPDATE_FETCHHEAD = raw::GIT_REMOTE_UPDATE_FETCHHEAD as u32; + /// Report unchanged tips in the update_tips callback. + const REPORT_UNCHANGED = raw::GIT_REMOTE_UPDATE_REPORT_UNCHANGED as u32; + } +} + #[cfg(test)] #[macro_use] mod test; From 6cb97bcba835f349ac9cc38b105e8b13115b8e0d Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sat, 2 Mar 2024 22:28:11 +0800 Subject: [PATCH 754/860] remote: Update `git_remote_update_tips` to use `RemoteUpdateFlags` --- examples/fetch.rs | 9 +++++++-- libgit2-sys/lib.rs | 2 +- src/remote.rs | 23 +++++++++++++++++------ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/examples/fetch.rs b/examples/fetch.rs index f3a11dffbd..af4aa98eb9 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -15,7 +15,7 @@ #![deny(warnings)] use clap::Parser; -use git2::{AutotagOption, FetchOptions, RemoteCallbacks, Repository}; +use git2::{AutotagOption, FetchOptions, RemoteCallbacks, RemoteUpdateFlags, Repository}; use std::io::{self, Write}; use std::str; @@ -113,7 +113,12 @@ fn run(args: &Args) -> Result<(), git2::Error> { // commits. This may be needed even if there was no packfile to download, // which can happen e.g. when the branches have been changed but all the // needed objects are available locally. - remote.update_tips(None, true, AutotagOption::Unspecified, None)?; + remote.update_tips( + None, + RemoteUpdateFlags::UPDATE_FETCHHEAD, + AutotagOption::Unspecified, + None, + )?; Ok(()) } diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5f72b0c39a..ff1b6444e9 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2334,7 +2334,7 @@ extern "C" { pub fn git_remote_update_tips( remote: *mut git_remote, callbacks: *const git_remote_callbacks, - update_fetchead: c_int, + update_flags: c_uint, download_tags: git_remote_autotag_option_t, reflog_message: *const c_char, ) -> c_int; diff --git a/src/remote.rs b/src/remote.rs index 1909766c76..c52db6e287 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -3,6 +3,7 @@ use std::iter::FusedIterator; use std::marker; use std::mem; use std::ops::Range; +use std::os::raw::c_uint; use std::ptr; use std::slice; use std::str; @@ -11,7 +12,7 @@ use std::{ffi::CString, os::raw::c_char}; use crate::string_array::StringArray; use crate::util::Binding; use crate::{call, raw, Buf, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec}; -use crate::{AutotagOption, Progress, RemoteCallbacks, Repository}; +use crate::{AutotagOption, Progress, RemoteCallbacks, RemoteUpdateFlags, Repository}; /// A structure representing a [remote][1] of a git repository. /// @@ -320,7 +321,7 @@ impl<'repo> Remote<'repo> { pub fn update_tips( &mut self, callbacks: Option<&mut RemoteCallbacks<'_>>, - update_fetchhead: bool, + update_flags: RemoteUpdateFlags, download_tags: AutotagOption, msg: Option<&str>, ) -> Result<(), Error> { @@ -330,7 +331,7 @@ impl<'repo> Remote<'repo> { try_call!(raw::git_remote_update_tips( self.raw, cbs.as_ref(), - update_fetchhead, + update_flags.bits() as c_uint, download_tags, msg )); @@ -778,7 +779,7 @@ impl RemoteRedirect { #[cfg(test)] mod tests { - use crate::{AutotagOption, PushOptions}; + use crate::{AutotagOption, PushOptions, RemoteUpdateFlags}; use crate::{Direction, FetchOptions, Remote, RemoteCallbacks, Repository}; use std::cell::Cell; use tempfile::TempDir; @@ -867,10 +868,20 @@ mod tests { origin.fetch(&[] as &[&str], None, None).unwrap(); origin.fetch(&[] as &[&str], None, Some("foo")).unwrap(); origin - .update_tips(None, true, AutotagOption::Unspecified, None) + .update_tips( + None, + RemoteUpdateFlags::UPDATE_FETCHHEAD, + AutotagOption::Unspecified, + None, + ) .unwrap(); origin - .update_tips(None, true, AutotagOption::All, Some("foo")) + .update_tips( + None, + RemoteUpdateFlags::UPDATE_FETCHHEAD, + AutotagOption::All, + Some("foo"), + ) .unwrap(); t!(repo.remote_add_fetch("https://github.com/origin", "foo")); From 3433353e659e284cb86c0fd230afeaf774244e43 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sat, 2 Mar 2024 22:28:11 +0800 Subject: [PATCH 755/860] remote: Update `git_fetch_options` to use `RemoteUpdateFlags` This includes a hacky solution since the `update_flag` field uses C bitfields, which are not natively supported in Rust. --- libgit2-sys/lib.rs | 2 +- src/remote.rs | 22 ++++++++++++++++++---- systest/build.rs | 4 +++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index ff1b6444e9..f5d4acd76d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -398,7 +398,7 @@ pub struct git_fetch_options { pub version: c_int, pub callbacks: git_remote_callbacks, pub prune: git_fetch_prune_t, - pub update_fetchhead: c_int, + pub update_flags: c_uint, pub download_tags: git_remote_autotag_option_t, pub proxy_opts: git_proxy_options, pub depth: c_int, diff --git a/src/remote.rs b/src/remote.rs index c52db6e287..0211493507 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -44,7 +44,7 @@ pub struct FetchOptions<'cb> { depth: i32, proxy: Option>, prune: FetchPrune, - update_fetchhead: bool, + update_flags: RemoteUpdateFlags, download_tags: AutotagOption, follow_redirects: RemoteRedirect, custom_headers: Vec, @@ -507,7 +507,7 @@ impl<'cb> FetchOptions<'cb> { callbacks: None, proxy: None, prune: FetchPrune::Unspecified, - update_fetchhead: true, + update_flags: RemoteUpdateFlags::UPDATE_FETCHHEAD, download_tags: AutotagOption::Unspecified, follow_redirects: RemoteRedirect::Initial, custom_headers: Vec::new(), @@ -538,7 +538,17 @@ impl<'cb> FetchOptions<'cb> { /// /// Defaults to `true`. pub fn update_fetchhead(&mut self, update: bool) -> &mut Self { - self.update_fetchhead = update; + self.update_flags + .set(RemoteUpdateFlags::UPDATE_FETCHHEAD, update); + self + } + + /// Set whether to report unchanged tips in the update_tips callback. + /// + /// Defaults to `false`. + pub fn report_unchanged(&mut self, update: bool) -> &mut Self { + self.update_flags + .set(RemoteUpdateFlags::REPORT_UNCHANGED, update); self } @@ -603,7 +613,11 @@ impl<'cb> Binding for FetchOptions<'cb> { .map(|m| m.raw()) .unwrap_or_else(|| ProxyOptions::new().raw()), prune: crate::call::convert(&self.prune), - update_fetchhead: crate::call::convert(&self.update_fetchhead), + // HACK: `libgit2` uses C bitfields, which do not have a guaranteed memory layout. + // Reversing the bits ensures that the bitfields are set whether the bits are laid out + // from left to right or right to left, but will not work on other memory layouts. + update_flags: (self.update_flags.bits() | self.update_flags.bits().reverse_bits()) + as c_uint, download_tags: crate::call::convert(&self.download_tags), depth: self.depth, follow_redirects: self.follow_redirects.raw(), diff --git a/systest/build.rs b/systest/build.rs index bb34d9de80..5b2dac8016 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -24,7 +24,9 @@ fn main() { // this field is marked as const which ctest complains about (struct_ == "git_rebase_operation" && f == "id") || // the real name of this field is ref but that is a reserved keyword - (struct_ == "git_worktree_add_options" && f == "reference") + (struct_ == "git_worktree_add_options" && f == "reference") || + // the `update_flags` field consists of 2 bitfields + (struct_ == "git_fetch_options" && f == "update_flags") }); cfg.skip_signededness(|s| match s { s if s.ends_with("_cb") => true, From b7662914df9937e74ce1cc8e5a7cc8fa02bc36c2 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sat, 2 Mar 2024 22:29:13 +0800 Subject: [PATCH 756/860] libgit2-sys: Update struct representation for `git_config_entry` --- libgit2-sys/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index f5d4acd76d..9ae74c4718 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -862,10 +862,11 @@ pub struct git_index_time { pub struct git_config_entry { pub name: *const c_char, pub value: *const c_char, + pub backend_type: *const c_char, + pub origin_path: *const c_char, pub include_depth: c_uint, pub level: git_config_level_t, pub free: Option, - pub payload: *mut c_void, } git_enum! { From 202b38c0bfabedecc884331d81af2782022f33f9 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sat, 2 Mar 2024 22:29:13 +0800 Subject: [PATCH 757/860] libgit2-sys: Add new git error code enums --- libgit2-sys/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 9ae74c4718..a317183d5d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -198,6 +198,10 @@ git_enum! { GIT_EINDEXDIRTY = -34, GIT_EAPPLYFAIL = -35, GIT_EOWNER = -36, + GIT_TIMEOUT = -37, + GIT_EUNCHANGED = -38, + GIT_ENOTSUPPORTED = -39, + GIT_EREADONLY = -40, } } From ee69ec57450d64695ab2412cb930fd3a66ac13a1 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sun, 3 Mar 2024 02:49:05 +0800 Subject: [PATCH 758/860] repo: Update `git_commit_create` and `git_commit_create_buffer` --- libgit2-sys/lib.rs | 4 ++-- src/repo.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a317183d5d..be6a092ebc 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2895,7 +2895,7 @@ extern "C" { message: *const c_char, tree: *const git_tree, parent_count: size_t, - parents: *mut *const git_commit, + parents: *const *mut git_commit, ) -> c_int; pub fn git_commit_create_buffer( out: *mut git_buf, @@ -2906,7 +2906,7 @@ extern "C" { message: *const c_char, tree: *const git_tree, parent_count: size_t, - parents: *mut *const git_commit, + parents: *const *mut git_commit, ) -> c_int; pub fn git_commit_header_field( out: *mut git_buf, diff --git a/src/repo.rs b/src/repo.rs index b41b42480c..db00545e4f 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1290,9 +1290,9 @@ impl Repository { parents: &[&Commit<'_>], ) -> Result { let update_ref = crate::opt_cstr(update_ref)?; - let mut parent_ptrs = parents + let parent_ptrs = parents .iter() - .map(|p| p.raw() as *const raw::git_commit) + .map(|p| p.raw() as *mut raw::git_commit) .collect::>(); let message = CString::new(message)?; let mut raw = raw::git_oid { @@ -1309,7 +1309,7 @@ impl Repository { message, tree.raw(), parents.len() as size_t, - parent_ptrs.as_mut_ptr() + parent_ptrs.as_ptr() )); Ok(Binding::from_raw(&raw as *const _)) } @@ -1328,9 +1328,9 @@ impl Repository { tree: &Tree<'_>, parents: &[&Commit<'_>], ) -> Result { - let mut parent_ptrs = parents + let parent_ptrs = parents .iter() - .map(|p| p.raw() as *const raw::git_commit) + .map(|p| p.raw() as *mut raw::git_commit) .collect::>(); let message = CString::new(message)?; let buf = Buf::new(); @@ -1344,7 +1344,7 @@ impl Repository { message, tree.raw(), parents.len() as size_t, - parent_ptrs.as_mut_ptr() + parent_ptrs.as_ptr() )); Ok(buf) } From 8b5fba7452c13b9bd967a71f9a649721152b76f1 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Fri, 22 Mar 2024 19:32:02 +0800 Subject: [PATCH 759/860] lib: Add `ConfigLevel::Worktree` --- libgit2-sys/lib.rs | 3 ++- src/call.rs | 1 + src/lib.rs | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index be6a092ebc..aece88991c 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -880,7 +880,8 @@ git_enum! { GIT_CONFIG_LEVEL_XDG = 3, GIT_CONFIG_LEVEL_GLOBAL = 4, GIT_CONFIG_LEVEL_LOCAL = 5, - GIT_CONFIG_LEVEL_APP = 6, + GIT_CONFIG_LEVEL_WORKTREE = 6, + GIT_CONFIG_LEVEL_APP = 7, GIT_CONFIG_HIGHEST_LEVEL = -1, } } diff --git a/src/call.rs b/src/call.rs index 95350d2690..a18f05da91 100644 --- a/src/call.rs +++ b/src/call.rs @@ -166,6 +166,7 @@ mod impls { ConfigLevel::XDG => raw::GIT_CONFIG_LEVEL_XDG, ConfigLevel::Global => raw::GIT_CONFIG_LEVEL_GLOBAL, ConfigLevel::Local => raw::GIT_CONFIG_LEVEL_LOCAL, + ConfigLevel::Worktree => raw::GIT_CONFIG_LEVEL_WORKTREE, ConfigLevel::App => raw::GIT_CONFIG_LEVEL_APP, ConfigLevel::Highest => raw::GIT_CONFIG_HIGHEST_LEVEL, } diff --git a/src/lib.rs b/src/lib.rs index 48ec7c01cf..689dcfb37e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -385,6 +385,8 @@ pub enum ConfigLevel { Global, /// Repository specific config, e.g. $PWD/.git/config Local, + /// Worktree specific configuration file, e.g. $GIT_DIR/config.worktree + Worktree, /// Application specific configuration file App, /// Highest level available @@ -974,6 +976,7 @@ impl ConfigLevel { raw::GIT_CONFIG_LEVEL_XDG => ConfigLevel::XDG, raw::GIT_CONFIG_LEVEL_GLOBAL => ConfigLevel::Global, raw::GIT_CONFIG_LEVEL_LOCAL => ConfigLevel::Local, + raw::GIT_CONFIG_LEVEL_WORKTREE => ConfigLevel::Worktree, raw::GIT_CONFIG_LEVEL_APP => ConfigLevel::App, raw::GIT_CONFIG_HIGHEST_LEVEL => ConfigLevel::Highest, n => panic!("unknown config level: {}", n), From c074cabdbf1108492e0f53acf4b9fc9bd726d948 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Fri, 22 Mar 2024 19:32:02 +0800 Subject: [PATCH 760/860] worktree: Update struct representation for `git_worktree_add_options` --- libgit2-sys/lib.rs | 1 + src/worktree.rs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index aece88991c..2ea565284f 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1977,6 +1977,7 @@ git_enum! { pub struct git_worktree_add_options { pub version: c_uint, pub lock: c_int, + pub checkout_existing: c_int, pub reference: *mut git_reference, pub checkout_options: git_checkout_options, } diff --git a/src/worktree.rs b/src/worktree.rs index 569b639cf9..fc32902db1 100644 --- a/src/worktree.rs +++ b/src/worktree.rs @@ -165,6 +165,12 @@ impl<'a> WorktreeAddOptions<'a> { self } + /// If enabled, this will checkout the existing branch matching the worktree name. + pub fn checkout_existing(&mut self, enabled: bool) -> &mut WorktreeAddOptions<'a> { + self.raw.checkout_existing = enabled as c_int; + self + } + /// reference to use for the new worktree HEAD pub fn reference( &mut self, From 3bde019aed6780bc47e96c3509f68d7a1246dde9 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sat, 2 Mar 2024 22:37:42 +0800 Subject: [PATCH 761/860] libgit2-sys: Fix build issue with libssh2 --- libgit2-sys/build.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 6f85060512..3cece57076 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -180,7 +180,8 @@ The build is now aborting. To disable, unset the variable or use `LIBGIT2_NO_VEN cfg.include(path); } features.push_str("#define GIT_SSH 1\n"); - features.push_str("#define GIT_SSH_MEMORY_CREDENTIALS 1\n"); + features.push_str("#define GIT_SSH_LIBSSH2 1\n"); + features.push_str("#define GIT_SSH_LIBSSH2_MEMORY_CREDENTIALS 1\n"); } if https { features.push_str("#define GIT_HTTPS 1\n"); From 26853d90ffc029cb39c8d33781a99ba24a2d2f17 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Fri, 22 Mar 2024 20:48:27 +0800 Subject: [PATCH 762/860] tests: Account for new `worktreeconfig` extension added --- tests/add_extensions.rs | 6 ++++-- tests/get_extensions.rs | 4 +++- tests/remove_extensions.rs | 9 ++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/add_extensions.rs b/tests/add_extensions.rs index 57c0eb9762..f3e2c42ae3 100644 --- a/tests/add_extensions.rs +++ b/tests/add_extensions.rs @@ -11,11 +11,13 @@ fn test_add_extensions() -> Result<(), Error> { let extensions = unsafe { get_extensions() }?; - assert_eq!(extensions.len(), 3); + assert_eq!(extensions.len(), 4); assert_eq!(extensions.get(0), Some("custom")); - // The objectformat extension was added in 1.6 assert_eq!(extensions.get(1), Some("noop")); + // The objectformat extension was added in 1.6 assert_eq!(extensions.get(2), Some("objectformat")); + // The worktreeconfig extension was added in 1.8 + assert_eq!(extensions.get(3), Some("worktreeconfig")); Ok(()) } diff --git a/tests/get_extensions.rs b/tests/get_extensions.rs index d8dd55fe0a..3a9148f20b 100644 --- a/tests/get_extensions.rs +++ b/tests/get_extensions.rs @@ -7,10 +7,12 @@ use git2::Error; fn test_get_extensions() -> Result<(), Error> { let extensions = unsafe { get_extensions() }?; - assert_eq!(extensions.len(), 2); + assert_eq!(extensions.len(), 3); assert_eq!(extensions.get(0), Some("noop")); // The objectformat extension was added in 1.6 assert_eq!(extensions.get(1), Some("objectformat")); + // The worktreeconfig extension was added in 1.8 + assert_eq!(extensions.get(2), Some("worktreeconfig")); Ok(()) } diff --git a/tests/remove_extensions.rs b/tests/remove_extensions.rs index 5f632a8809..5384daea5c 100644 --- a/tests/remove_extensions.rs +++ b/tests/remove_extensions.rs @@ -6,7 +6,14 @@ use git2::Error; #[test] fn test_remove_extensions() -> Result<(), Error> { unsafe { - set_extensions(&["custom", "!ignore", "!noop", "!objectformat", "other"])?; + set_extensions(&[ + "custom", + "!ignore", + "!noop", + "!objectformat", + "!worktreeconfig", + "other", + ])?; } let extensions = unsafe { get_extensions() }?; From eeb04b97cbdabb58c3dc23e18758cf7fefc3c6c2 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Fri, 22 Mar 2024 20:48:27 +0800 Subject: [PATCH 763/860] cred/tests: Account for changes in `git_config` --- src/cred.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cred.rs b/src/cred.rs index fc4af1e4eb..fc0b941935 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -482,7 +482,7 @@ mod test { macro_rules! test_cfg( ($($k:expr => $v:expr),*) => ({ let td = TempDir::new().unwrap(); let mut cfg = Config::new().unwrap(); - cfg.add_file(&td.path().join("cfg"), ConfigLevel::Highest, false).unwrap(); + cfg.add_file(&td.path().join("cfg"), ConfigLevel::App, false).unwrap(); $(cfg.set_str($k, $v).unwrap();)* cfg }) ); From e21a5de2bcc6bab0545674e40790b75a89e7000b Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sun, 24 Mar 2024 04:57:26 +0800 Subject: [PATCH 764/860] test: Fix `realpath` failure on Windows --- src/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test.rs b/src/test.rs index c1ff1de21f..57a590f519 100644 --- a/src/test.rs +++ b/src/test.rs @@ -66,7 +66,7 @@ pub fn worktrees_env_init(repo: &Repository) -> (TempDir, Branch<'_>) { #[cfg(windows)] pub fn realpath(original: &Path) -> io::Result { - Ok(original.to_path_buf()) + Ok(original.canonicalize()?.to_path_buf()) } #[cfg(unix)] pub fn realpath(original: &Path) -> io::Result { From 2a617b683a1acc63ce3f2952b3256ae8663e4b77 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Sun, 3 Mar 2024 02:49:26 +0800 Subject: [PATCH 765/860] systest: Add `errors.h` header file --- systest/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/systest/build.rs b/systest/build.rs index 5b2dac8016..0a22a5b396 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -7,6 +7,7 @@ fn main() { cfg.include(PathBuf::from(root).join("include")); } cfg.header("git2.h") + .header("git2/sys/errors.h") .header("git2/sys/transport.h") .header("git2/sys/refs.h") .header("git2/sys/refdb_backend.h") From a65e7a45f0db8bf3dcf4c9624ec5016df3b28a8f Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Fri, 22 Mar 2024 19:32:02 +0800 Subject: [PATCH 766/860] libgit2-sys: Bump versions --- Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6359ac058c..987479b633 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ url = "2.0" bitflags = "2.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.16.2" } +libgit2-sys = { path = "libgit2-sys", version = "0.17.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.45", optional = true } diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 67eaf8dc8e..b3adf89ddc 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.16.2+1.7.2" +version = "0.17.0+1.8.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 449c6bec33477e57b6c84bcf57297409798dfc73 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Wed, 15 May 2024 17:00:20 +0800 Subject: [PATCH 767/860] libgit2: Bump to v1.8.1 --- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 2 +- libgit2-sys/libgit2 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index b3adf89ddc..ff911c99f5 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.17.0+1.8.0" +version = "0.17.0+1.8.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 3cece57076..1fd1caea41 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -7,7 +7,7 @@ use std::process::Command; /// Tries to use system libgit2 and emits necessary build script instructions. fn try_system_libgit2() -> Result { let mut cfg = pkg_config::Config::new(); - match cfg.range_version("1.8.0".."1.9.0").probe("libgit2") { + match cfg.range_version("1.8.1".."1.9.0").probe("libgit2") { Ok(lib) => { for include in &lib.include_paths { println!("cargo:root={}", include.display()); diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index d74d491481..36f7e21ad7 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit d74d491481831ddcd23575d376e56d2197e95910 +Subproject commit 36f7e21ad757a3dacc58cf7944329da6bc1d6e96 From 8640496eab353b173b46a9403209b0ba57a4d258 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Wed, 15 May 2024 17:00:24 +0800 Subject: [PATCH 768/860] libgit2-sys: Switch to new bundled llhttp HTTP parser --- libgit2-sys/build.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 1fd1caea41..1abf628c6e 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -89,9 +89,9 @@ The build is now aborting. To disable, unset the variable or use `LIBGIT2_NO_VEN add_c_files(&mut cfg, "libgit2/src/libgit2/transports"); add_c_files(&mut cfg, "libgit2/src/libgit2/streams"); - // Always use bundled http-parser for now - cfg.include("libgit2/deps/http-parser") - .file("libgit2/deps/http-parser/http_parser.c"); + // Always use bundled HTTP parser (llhttp) for now + cfg.include("libgit2/deps/llhttp"); + add_c_files(&mut cfg, "libgit2/deps/llhttp"); // external/system xdiff is not yet supported cfg.include("libgit2/deps/xdiff"); @@ -150,6 +150,7 @@ The build is now aborting. To disable, unset the variable or use `LIBGIT2_NO_VEN features.push_str("#define INCLUDE_features_h\n"); features.push_str("#define GIT_THREADS 1\n"); features.push_str("#define GIT_TRACE 1\n"); + features.push_str("#define GIT_HTTPPARSER_BUILTIN 1\n"); if !target.contains("android") { features.push_str("#define GIT_USE_NSEC 1\n"); From 78872dda70a3962e6269debe569265759518c8c6 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Wed, 15 May 2024 17:16:26 +0800 Subject: [PATCH 769/860] remote: Update `git_fetch_options` to use bitflags instead of bitfields See: - https://github.com/libgit2/libgit2/issues/6800 - https://github.com/libgit2/libgit2/pull/6806 --- libgit2-sys/lib.rs | 2 +- src/remote.rs | 9 ++++----- systest/build.rs | 4 +--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 2ea565284f..c94d0d446a 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -402,7 +402,7 @@ pub struct git_fetch_options { pub version: c_int, pub callbacks: git_remote_callbacks, pub prune: git_fetch_prune_t, - pub update_flags: c_uint, + pub update_fetchhead: c_uint, pub download_tags: git_remote_autotag_option_t, pub proxy_opts: git_proxy_options, pub depth: c_int, diff --git a/src/remote.rs b/src/remote.rs index 0211493507..13c275ae2e 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -613,11 +613,10 @@ impl<'cb> Binding for FetchOptions<'cb> { .map(|m| m.raw()) .unwrap_or_else(|| ProxyOptions::new().raw()), prune: crate::call::convert(&self.prune), - // HACK: `libgit2` uses C bitfields, which do not have a guaranteed memory layout. - // Reversing the bits ensures that the bitfields are set whether the bits are laid out - // from left to right or right to left, but will not work on other memory layouts. - update_flags: (self.update_flags.bits() | self.update_flags.bits().reverse_bits()) - as c_uint, + // `update_fetchhead` is an incorrectly named option which contains both + // the `UPDATE_FETCHHEAD` and `REPORT_UNCHANGED` flags. + // See https://github.com/libgit2/libgit2/pull/6806 + update_fetchhead: self.update_flags.bits() as c_uint, download_tags: crate::call::convert(&self.download_tags), depth: self.depth, follow_redirects: self.follow_redirects.raw(), diff --git a/systest/build.rs b/systest/build.rs index 0a22a5b396..85e8b4b437 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -25,9 +25,7 @@ fn main() { // this field is marked as const which ctest complains about (struct_ == "git_rebase_operation" && f == "id") || // the real name of this field is ref but that is a reserved keyword - (struct_ == "git_worktree_add_options" && f == "reference") || - // the `update_flags` field consists of 2 bitfields - (struct_ == "git_fetch_options" && f == "update_flags") + (struct_ == "git_worktree_add_options" && f == "reference") }); cfg.skip_signededness(|s| match s { s if s.ends_with("_cb") => true, From 938df213d29e90b1275b548403517186afdec89b Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Thu, 16 May 2024 19:20:37 +0800 Subject: [PATCH 770/860] libgit2-sys: Add updated enum values for `git_libgit2_opt_t` --- libgit2-sys/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index c94d0d446a..af1dff048b 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1961,6 +1961,14 @@ git_enum! { GIT_OPT_SET_EXTENSIONS, GIT_OPT_GET_OWNER_VALIDATION, GIT_OPT_SET_OWNER_VALIDATION, + GIT_OPT_GET_HOMEDIR, + GIT_OPT_SET_HOMEDIR, + GIT_OPT_SET_SERVER_CONNECT_TIMEOUT, + GIT_OPT_GET_SERVER_CONNECT_TIMEOUT, + GIT_OPT_SET_SERVER_TIMEOUT, + GIT_OPT_GET_SERVER_TIMEOUT, + GIT_OPT_SET_USER_AGENT_PRODUCT, + GIT_OPT_GET_USER_AGENT_PRODUCT, } } From 76ecfe7d821d8cdb5ba13f1ce6b05736bdc922ee Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Fri, 22 Mar 2024 19:32:02 +0800 Subject: [PATCH 771/860] contributing: Add note about `git diff` --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1ab0961f1f..c842f1eec5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,6 +31,7 @@ The following steps can be used to update libgit2: can be helpful for seeing what has changed. The project has recently started labeling API and ABI breaking changes with labels: + Alternatively, running `git diff [PREV_VERSION]..[NEW_VERSION] --ignore-all-space -- include/` can provide an overview of changes made to the API. 4. Once you have everything functional, publish a PR with the updates. ## Release process From 0715c33cef95a16b4f06391855fc5004a2b97525 Mon Sep 17 00:00:00 2001 From: Kornel Date: Sun, 19 May 2024 23:44:51 +0100 Subject: [PATCH 772/860] Reduce Error size with Box --- src/error.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/error.rs b/src/error.rs index 6f1c4d4c78..54383b37bd 100644 --- a/src/error.rs +++ b/src/error.rs @@ -12,7 +12,7 @@ use crate::{raw, ErrorClass, ErrorCode}; pub struct Error { code: c_int, klass: c_int, - message: String, + message: Box, } impl Error { @@ -70,7 +70,7 @@ impl Error { unsafe fn from_raw(code: c_int, ptr: *const raw::git_error) -> Error { let message = CStr::from_ptr((*ptr).message as *const _).to_bytes(); - let message = String::from_utf8_lossy(message).into_owned(); + let message = String::from_utf8_lossy(message).into_owned().into(); Error { code, klass: (*ptr).klass, @@ -86,7 +86,7 @@ impl Error { Error { code: raw::GIT_ERROR as c_int, klass: raw::GIT_ERROR_NONE as c_int, - message: s.to_string(), + message: s.into(), } } From e17e77c56702dfe05015d4a15fce33da2e89b066 Mon Sep 17 00:00:00 2001 From: Melvin Zottola Date: Thu, 16 May 2024 01:04:29 +0200 Subject: [PATCH 773/860] Add global opts related to server timeouts --- src/error.rs | 3 ++ src/lib.rs | 2 ++ src/opts.rs | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/src/error.rs b/src/error.rs index 7b9802a403..e57bae27dd 100644 --- a/src/error.rs +++ b/src/error.rs @@ -128,6 +128,7 @@ impl Error { raw::GIT_EINDEXDIRTY => super::ErrorCode::IndexDirty, raw::GIT_EAPPLYFAIL => super::ErrorCode::ApplyFail, raw::GIT_EOWNER => super::ErrorCode::Owner, + raw::GIT_TIMEOUT => super::ErrorCode::Timeout, _ => super::ErrorCode::GenericError, } } @@ -165,6 +166,7 @@ impl Error { ErrorCode::IndexDirty => raw::GIT_EINDEXDIRTY, ErrorCode::ApplyFail => raw::GIT_EAPPLYFAIL, ErrorCode::Owner => raw::GIT_EOWNER, + ErrorCode::Timeout => raw::GIT_TIMEOUT, }; } @@ -296,6 +298,7 @@ impl Error { GIT_EINDEXDIRTY, GIT_EAPPLYFAIL, GIT_EOWNER, + GIT_TIMEOUT, ) } diff --git a/src/lib.rs b/src/lib.rs index 689dcfb37e..3caaabc43a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -218,6 +218,8 @@ pub enum ErrorCode { ApplyFail, /// The object is not owned by the current user Owner, + /// Timeout + Timeout, } /// An enumeration of possible categories of things that can have diff --git a/src/opts.rs b/src/opts.rs index 88f4eb74b7..ab63661023 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -338,6 +338,82 @@ pub unsafe fn set_mwindow_file_limit(limit: libc::size_t) -> Result<(), Error> { Ok(()) } +/// Get server connect timeout in milliseconds +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn get_server_connect_timeout_in_milliseconds() -> Result { + crate::init(); + + let mut server_connect_timeout = 0; + + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_SERVER_CONNECT_TIMEOUT as libc::c_int, + &mut server_connect_timeout + )); + + Ok(server_connect_timeout) +} + +/// Set server connect timeout in milliseconds +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn set_server_connect_timeout_in_milliseconds( + timeout: libc::c_int, +) -> Result<(), Error> { + crate::init(); + + let error = raw::git_libgit2_opts( + raw::GIT_OPT_SET_SERVER_CONNECT_TIMEOUT as libc::c_int, + timeout, + ); + // This function cannot actually fail, but the function has an error return + // for other options that can. + debug_assert!(error >= 0); + + Ok(()) +} + +/// Get server timeout in milliseconds +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn get_server_timeout_in_milliseconds() -> Result { + crate::init(); + + let mut server_timeout = 0; + + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_SERVER_TIMEOUT as libc::c_int, + &mut server_timeout + )); + + Ok(server_timeout) +} + +/// Set server timeout in milliseconds +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn set_server_timeout_in_milliseconds(timeout: libc::c_int) -> Result<(), Error> { + crate::init(); + + let error = raw::git_libgit2_opts( + raw::GIT_OPT_SET_SERVER_TIMEOUT as libc::c_int, + timeout as libc::c_int, + ); + // This function cannot actually fail, but the function has an error return + // for other options that can. + debug_assert!(error >= 0); + + Ok(()) +} + #[cfg(test)] mod test { use super::*; @@ -370,4 +446,20 @@ mod test { assert!(get_mwindow_file_limit().unwrap() == 1024); } } + + #[test] + fn server_connect_timeout() { + unsafe { + assert!(set_server_connect_timeout_in_milliseconds(5000).is_ok()); + assert!(get_server_connect_timeout_in_milliseconds().unwrap() == 5000); + } + } + + #[test] + fn server_timeout() { + unsafe { + assert!(set_server_timeout_in_milliseconds(10_000).is_ok()); + assert!(get_server_timeout_in_milliseconds().unwrap() == 10_000); + } + } } From 79b1bed394b0476c81f51e9a5d6ffe83523e283b Mon Sep 17 00:00:00 2001 From: Eric Park Date: Mon, 27 May 2024 14:19:09 +0900 Subject: [PATCH 774/860] repo: add branch_upstream_remote refname doc (#1055) Adds the full refname format for the documentation Closes #1055 --- src/repo.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index db00545e4f..b94b4007db 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -3060,6 +3060,8 @@ impl Repository { } /// Retrieve the name of the upstream remote of a local branch. + /// + /// `refname` must be in the form `refs/heads/{branch_name}` pub fn branch_upstream_remote(&self, refname: &str) -> Result { let refname = CString::new(refname)?; unsafe { From db3a3cebbab60847541b63a3c293bd13161a7115 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 13 Jun 2024 17:12:42 -0700 Subject: [PATCH 775/860] Bump versions for 1.8.1 --- CHANGELOG.md | 19 +++++++++++++++++++ Cargo.toml | 2 +- README.md | 2 +- git2-curl/CHANGELOG.md | 5 +++++ git2-curl/Cargo.toml | 4 ++-- git2-curl/src/lib.rs | 2 +- libgit2-sys/CHANGELOG.md | 8 ++++++++ libgit2-sys/lib.rs | 2 +- src/lib.rs | 2 +- 9 files changed, 39 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5704d9355..f76c3ba150 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.19.0 - 2024-06-13 +[0.18.3...0.19.0](https://github.com/rust-lang/git2-rs/compare/git2-0.18.3...git2-0.19.0) + +### Added + +- Added `opts` functions to control server timeouts (`get_server_connect_timeout_in_milliseconds`, `set_server_connect_timeout_in_milliseconds`, `get_server_timeout_in_milliseconds`, `set_server_timeout_in_milliseconds`), and add `ErrorCode::Timeout`. + [#1052](https://github.com/rust-lang/git2-rs/pull/1052) + +### Changed + +- ❗ Updated to libgit2 [1.8.1](https://github.com/libgit2/libgit2/releases/tag/v1.8.1) + [#1032](https://github.com/rust-lang/git2-rs/pull/1032) +- Reduced size of the `Error` struct. + [#1053](https://github.com/rust-lang/git2-rs/pull/1053) + +### Fixed + +- Fixed some callbacks to relay the error from the callback to libgit2. + [#1043](https://github.com/rust-lang/git2-rs/pull/1043) ## 0.18.3 - 2024-03-18 [0.18.2...0.18.3](https://github.com/rust-lang/git2-rs/compare/git2-0.18.2...git2-0.18.3) diff --git a/Cargo.toml b/Cargo.toml index 987479b633..9e6fd81f56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.18.3" +version = "0.19.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/README.md b/README.md index 70c2247b64..e66c049d37 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.18.3" +git2 = "0.19.0" ``` ## Rust version requirements diff --git a/git2-curl/CHANGELOG.md b/git2-curl/CHANGELOG.md index 98867bc28f..1d51c646f7 100644 --- a/git2-curl/CHANGELOG.md +++ b/git2-curl/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.20.0 - 2024-06-13 +[0.19.0...0.20.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.19.0...git2-curl-0.20.0) + +- Updated to [git2 0.19.0](../CHANGELOG.md#0190---2024-06-13) + ## 0.19.0 - 2023-08-28 [0.18.0...0.19.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.18.0...git2-curl-0.19.0) diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 8e4fda1c69..f63819149d 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2-curl" -version = "0.19.0" +version = "0.20.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" @@ -16,7 +16,7 @@ edition = "2018" curl = "0.4.33" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.18", default-features = false } +git2 = { path = "..", version = "0.19", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index 99d782ec41..f480ffc71c 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -15,7 +15,7 @@ //! > **NOTE**: At this time this crate likely does not support a `git push` //! > operation, only clones. -#![doc(html_root_url = "https://docs.rs/git2-curl/0.19")] +#![doc(html_root_url = "https://docs.rs/git2-curl/0.20")] #![deny(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index fa9bddd441..02f82b00d7 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.17.0+1.8.1 - 2024-06-13 +[0.16.2...0.17.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.2+1.7.2...libgit2-sys-0.17.0+1.8.1) + +### Changed + +- ❗ Updated to libgit2 [1.8.1](https://github.com/libgit2/libgit2/releases/tag/v1.8.1) + [#1032](https://github.com/rust-lang/git2-rs/pull/1032) + ## 0.16.2+1.7.2 - 2024-02-06 [0.16.1...0.16.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.1+1.7.1...libgit2-sys-0.16.2+1.7.2) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index af1dff048b..f7175f4140 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.16")] +#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.17")] #![allow(non_camel_case_types, unused_extern_crates)] // This is required to link libz when libssh2-sys is not included. diff --git a/src/lib.rs b/src/lib.rs index 3caaabc43a..e52efb3734 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.18")] +#![doc(html_root_url = "https://docs.rs/git2/0.19")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] From b1b2f55e4f5c34378b1852bb0d7219ea73111046 Mon Sep 17 00:00:00 2001 From: gensmusic Date: Sat, 22 Jun 2024 09:30:43 +0800 Subject: [PATCH 776/860] odb: fix OdbReader read return value git_odb_stream_read return the number of bytes read. --- src/odb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odb.rs b/src/odb.rs index 7f6da5eb30..c64964943a 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -364,7 +364,7 @@ impl<'repo> io::Read for OdbReader<'repo> { if res < 0 { Err(io::Error::new(io::ErrorKind::Other, "Read error")) } else { - Ok(len) + Ok(res as _) } } } From c3c226a3313e52d47be288e9c77eb5e90f0e852a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 25 Jun 2024 08:20:11 -0700 Subject: [PATCH 777/860] Add test for OdbReader read impl. --- src/odb.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/odb.rs b/src/odb.rs index c64964943a..d01c70ae67 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -726,4 +726,45 @@ mod tests { t!(repo.reset(commit1.as_object(), ResetType::Hard, None)); assert!(foo_file.exists()); } + + #[test] + fn stream_read() { + // Test for read impl of OdbReader. + const FOO_TEXT: &[u8] = b"this is a test"; + let (_td, repo) = crate::test::repo_init(); + let p = repo.path().parent().unwrap().join("foo"); + std::fs::write(&p, FOO_TEXT).unwrap(); + let mut index = repo.index().unwrap(); + index.add_path(std::path::Path::new("foo")).unwrap(); + let tree_id = index.write_tree().unwrap(); + let tree = repo.find_tree(tree_id).unwrap(); + let sig = repo.signature().unwrap(); + let head_id = repo.refname_to_id("HEAD").unwrap(); + let parent = repo.find_commit(head_id).unwrap(); + let _commit = repo + .commit(Some("HEAD"), &sig, &sig, "commit", &tree, &[&parent]) + .unwrap(); + + // Try reading from a commit object. + let odb = repo.odb().unwrap(); + let oid = repo.refname_to_id("HEAD").unwrap(); + let (mut reader, size, ty) = odb.reader(oid).unwrap(); + assert!(ty == ObjectType::Commit); + let mut x = [0; 10000]; + let r = reader.read(&mut x).unwrap(); + assert!(r == size); + + // Try reading from a blob. This assumes it is a loose object (packed + // objects can't read). + let commit = repo.find_commit(oid).unwrap(); + let tree = commit.tree().unwrap(); + let entry = tree.get_name("foo").unwrap(); + let (mut reader, size, ty) = odb.reader(entry.id()).unwrap(); + assert_eq!(size, FOO_TEXT.len()); + assert!(ty == ObjectType::Blob); + let mut x = [0; 10000]; + let r = reader.read(&mut x).unwrap(); + assert_eq!(r, 14); + assert_eq!(&x[..FOO_TEXT.len()], FOO_TEXT); + } } From 52fc8d03476b946ad754d893c56366ebe075ad39 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Mon, 22 Jul 2024 15:26:24 -0400 Subject: [PATCH 778/860] (Breaking Changes) Re-implement tracing wrapper in a safer way, add smoke test, update tracing callback to use `&[u8]` instead of `&str`. --- src/tracing.rs | 96 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 21 deletions(-) diff --git a/src/tracing.rs b/src/tracing.rs index 5acae8a850..6ff671d951 100644 --- a/src/tracing.rs +++ b/src/tracing.rs @@ -1,8 +1,8 @@ -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::{ffi::CStr, sync::atomic::{AtomicPtr, Ordering}}; -use libc::c_char; +use libc::{c_char, c_int}; -use crate::{panic, raw, util::Binding}; +use crate::{panic, raw, util::Binding, Error}; /// Available tracing levels. When tracing is set to a particular level, /// callers will be provided tracing at the given level and all lower levels. @@ -57,29 +57,83 @@ impl Binding for TraceLevel { } } -//TODO: pass raw &[u8] and leave conversion to consumer (breaking API) /// Callback type used to pass tracing events to the subscriber. /// see `trace_set` to register a subscriber. -pub type TracingCb = fn(TraceLevel, &str); - -static CALLBACK: AtomicUsize = AtomicUsize::new(0); - -/// -pub fn trace_set(level: TraceLevel, cb: TracingCb) -> bool { - CALLBACK.store(cb as usize, Ordering::SeqCst); - - unsafe { - raw::git_trace_set(level.raw(), Some(tracing_cb_c)); +pub type TracingCb = fn(TraceLevel, &[u8]); + +/// Use an atomic pointer to store the global tracing subscriber function. +static CALLBACK: AtomicPtr<()> = AtomicPtr::new(std::ptr::null_mut()); + +/// Set the global subscriber called when libgit2 produces a tracing message. +pub fn trace_set(level: TraceLevel, cb: TracingCb) -> Result<(), Error> { + // Store the callback in the global atomic. + CALLBACK.store(cb as *mut (), Ordering::SeqCst); + + // git_trace_set returns 0 if there was no error. + let return_code: c_int = unsafe { + raw::git_trace_set(level.raw(), Some(tracing_cb_c)) + }; + + if return_code != 0 { + // Unwrap here is fine since `Error::last_error` always returns `Some`. + Err(Error::last_error(return_code).unwrap()) + } else { + Ok(()) } - - return true; } +/// The tracing callback we pass to libgit2 (C ABI compatible). extern "C" fn tracing_cb_c(level: raw::git_trace_level_t, msg: *const c_char) { - let cb = CALLBACK.load(Ordering::SeqCst); - panic::wrap(|| unsafe { - let cb: TracingCb = std::mem::transmute(cb); - let msg = std::ffi::CStr::from_ptr(msg).to_string_lossy(); - cb(Binding::from_raw(level), msg.as_ref()); + // Load the callback function pointer from the global atomic. + let cb: *mut () = CALLBACK.load(Ordering::SeqCst); + + // Transmute the callback pointer into the function pointer we know it to be. + // + // SAFETY: We only ever set the callback pointer with something cast from a TracingCb + // so transmuting back to a TracingCb is safe. This is notably not an integer-to-pointer + // transmute as described in the mem::transmute documentation and is in-line with the + // example in that documentation for casing between *const () to fn pointers. + let cb: TracingCb = unsafe { std::mem::transmute(cb) }; + + // If libgit2 passes us a message that is null, drop it and do not pass it to the callback. + // This is to avoid ever exposing rust code to a null ref, which would be Undefined Behavior. + if msg.is_null() { + return; + } + + // Convert the message from a *const c_char to a &[u8] and pass it to the callback. + // + // SAFETY: We've just checked that the pointer is not null. The other safety requirements are left to + // libgit2 to enforce -- namely that it gives us a valid, nul-terminated, C string, that that string exists + // entirely in one allocation, that the string will not be mutated once passed to us, and that the nul-terminator is + // within isize::MAX bytes from the given pointers data address. + let msg: &CStr = unsafe { CStr::from_ptr(msg) }; + + // Convert from a CStr to &[u8] to pass to the rust code callback. + let msg: &[u8] = CStr::to_bytes(msg); + + // Do the remaining part of this function in a panic wrapper, to catch any panics it produces. + panic::wrap(|| { + // Convert the raw trace level into a type we can pass to the rust callback fn. + // + // SAFETY: Currently the implementation of this function (above) may panic, but is only marked as unsafe to match + // the trait definition, thus we can consider this call safe. + let level: TraceLevel = unsafe { Binding::from_raw(level) }; + + // Call the user-supplied callback (which may panic). + (cb)(level, msg); }); } + +#[cfg(test)] +mod tests { + use super::TraceLevel; + + // Test that using the above function to set a tracing callback doesn't panic. + #[test] + fn smoke() { + super::trace_set(TraceLevel::Trace, |level, msg| { + dbg!(level, msg); + }).expect("libgit2 can set global trace callback"); + } +} From 7be752595440748152ced84363773c9c5c207960 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Mon, 22 Jul 2024 15:34:31 -0400 Subject: [PATCH 779/860] Cargo fmt --- src/tracing.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/tracing.rs b/src/tracing.rs index 6ff671d951..f06460d240 100644 --- a/src/tracing.rs +++ b/src/tracing.rs @@ -1,4 +1,7 @@ -use std::{ffi::CStr, sync::atomic::{AtomicPtr, Ordering}}; +use std::{ + ffi::CStr, + sync::atomic::{AtomicPtr, Ordering}, +}; use libc::{c_char, c_int}; @@ -61,7 +64,7 @@ impl Binding for TraceLevel { /// see `trace_set` to register a subscriber. pub type TracingCb = fn(TraceLevel, &[u8]); -/// Use an atomic pointer to store the global tracing subscriber function. +/// Use an atomic pointer to store the global tracing subscriber function. static CALLBACK: AtomicPtr<()> = AtomicPtr::new(std::ptr::null_mut()); /// Set the global subscriber called when libgit2 produces a tracing message. @@ -69,10 +72,8 @@ pub fn trace_set(level: TraceLevel, cb: TracingCb) -> Result<(), Error> { // Store the callback in the global atomic. CALLBACK.store(cb as *mut (), Ordering::SeqCst); - // git_trace_set returns 0 if there was no error. - let return_code: c_int = unsafe { - raw::git_trace_set(level.raw(), Some(tracing_cb_c)) - }; + // git_trace_set returns 0 if there was no error. + let return_code: c_int = unsafe { raw::git_trace_set(level.raw(), Some(tracing_cb_c)) }; if return_code != 0 { // Unwrap here is fine since `Error::last_error` always returns `Some`. @@ -88,10 +89,10 @@ extern "C" fn tracing_cb_c(level: raw::git_trace_level_t, msg: *const c_char) { let cb: *mut () = CALLBACK.load(Ordering::SeqCst); // Transmute the callback pointer into the function pointer we know it to be. - // - // SAFETY: We only ever set the callback pointer with something cast from a TracingCb - // so transmuting back to a TracingCb is safe. This is notably not an integer-to-pointer - // transmute as described in the mem::transmute documentation and is in-line with the + // + // SAFETY: We only ever set the callback pointer with something cast from a TracingCb + // so transmuting back to a TracingCb is safe. This is notably not an integer-to-pointer + // transmute as described in the mem::transmute documentation and is in-line with the // example in that documentation for casing between *const () to fn pointers. let cb: TracingCb = unsafe { std::mem::transmute(cb) }; @@ -102,10 +103,10 @@ extern "C" fn tracing_cb_c(level: raw::git_trace_level_t, msg: *const c_char) { } // Convert the message from a *const c_char to a &[u8] and pass it to the callback. - // - // SAFETY: We've just checked that the pointer is not null. The other safety requirements are left to + // + // SAFETY: We've just checked that the pointer is not null. The other safety requirements are left to // libgit2 to enforce -- namely that it gives us a valid, nul-terminated, C string, that that string exists - // entirely in one allocation, that the string will not be mutated once passed to us, and that the nul-terminator is + // entirely in one allocation, that the string will not be mutated once passed to us, and that the nul-terminator is // within isize::MAX bytes from the given pointers data address. let msg: &CStr = unsafe { CStr::from_ptr(msg) }; @@ -116,7 +117,7 @@ extern "C" fn tracing_cb_c(level: raw::git_trace_level_t, msg: *const c_char) { panic::wrap(|| { // Convert the raw trace level into a type we can pass to the rust callback fn. // - // SAFETY: Currently the implementation of this function (above) may panic, but is only marked as unsafe to match + // SAFETY: Currently the implementation of this function (above) may panic, but is only marked as unsafe to match // the trait definition, thus we can consider this call safe. let level: TraceLevel = unsafe { Binding::from_raw(level) }; @@ -134,6 +135,7 @@ mod tests { fn smoke() { super::trace_set(TraceLevel::Trace, |level, msg| { dbg!(level, msg); - }).expect("libgit2 can set global trace callback"); + }) + .expect("libgit2 can set global trace callback"); } } From fa33a26cec2b866b52880b133a8c72573934e671 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Mon, 22 Jul 2024 15:39:28 -0400 Subject: [PATCH 780/860] (Breaking Change) remove unnecessary `Option` wrapper on `Error::last_error`. --- src/call.rs | 4 +--- src/error.rs | 9 ++------- src/indexer.rs | 2 +- src/odb.rs | 2 +- src/repo.rs | 2 +- src/tracing.rs | 3 +-- 6 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/call.rs b/src/call.rs index a18f05da91..9aa3ae667f 100644 --- a/src/call.rs +++ b/src/call.rs @@ -44,9 +44,7 @@ pub fn c_try(ret: libc::c_int) -> Result { } pub fn last_error(code: libc::c_int) -> Error { - // nowadays this unwrap is safe as `Error::last_error` always returns - // `Some`. - Error::last_error(code).unwrap() + Error::last_error(code) } mod impls { diff --git a/src/error.rs b/src/error.rs index e57bae27dd..076667af98 100644 --- a/src/error.rs +++ b/src/error.rs @@ -32,12 +32,7 @@ impl Error { /// /// The `code` argument typically comes from the return value of a function /// call. This code will later be returned from the `code` function. - /// - /// Historically this function returned `Some` or `None` based on the return - /// value of `git_error_last` but nowadays it always returns `Some` so it's - /// safe to unwrap the return value. This API will change in the next major - /// version. - pub fn last_error(code: c_int) -> Option { + pub fn last_error(code: c_int) -> Error { crate::init(); unsafe { // Note that whenever libgit2 returns an error any negative value @@ -64,7 +59,7 @@ impl Error { Error::from_raw(code, ptr) }; raw::git_error_clear(); - Some(err) + err } } diff --git a/src/indexer.rs b/src/indexer.rs index 0aaf353d53..1078d2f06b 100644 --- a/src/indexer.rs +++ b/src/indexer.rs @@ -190,7 +190,7 @@ impl io::Write for Indexer<'_> { if res < 0 { Err(io::Error::new( io::ErrorKind::Other, - Error::last_error(res).unwrap(), + Error::last_error(res), )) } else { Ok(buf.len()) diff --git a/src/odb.rs b/src/odb.rs index d01c70ae67..2019908c48 100644 --- a/src/odb.rs +++ b/src/odb.rs @@ -458,7 +458,7 @@ impl<'repo> OdbPackwriter<'repo> { }; if res < 0 { - Err(Error::last_error(res).unwrap()) + Err(Error::last_error(res)) } else { Ok(res) } diff --git a/src/repo.rs b/src/repo.rs index b94b4007db..2b3e60b2af 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -848,7 +848,7 @@ impl Repository { match value { 0 => Ok(false), 1 => Ok(true), - _ => Err(Error::last_error(value).unwrap()), + _ => Err(Error::last_error(value)), } } } diff --git a/src/tracing.rs b/src/tracing.rs index f06460d240..9872571dd3 100644 --- a/src/tracing.rs +++ b/src/tracing.rs @@ -76,8 +76,7 @@ pub fn trace_set(level: TraceLevel, cb: TracingCb) -> Result<(), Error> { let return_code: c_int = unsafe { raw::git_trace_set(level.raw(), Some(tracing_cb_c)) }; if return_code != 0 { - // Unwrap here is fine since `Error::last_error` always returns `Some`. - Err(Error::last_error(return_code).unwrap()) + Err(Error::last_error(return_code)) } else { Ok(()) } From 788306c1e04a429677918dc0b83241510eb3e28e Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Mon, 22 Jul 2024 15:39:55 -0400 Subject: [PATCH 781/860] cargo fmt --- src/indexer.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/indexer.rs b/src/indexer.rs index 1078d2f06b..ddca5fa2d5 100644 --- a/src/indexer.rs +++ b/src/indexer.rs @@ -188,10 +188,7 @@ impl io::Write for Indexer<'_> { let res = raw::git_indexer_append(self.raw, ptr, len, &mut self.progress); if res < 0 { - Err(io::Error::new( - io::ErrorKind::Other, - Error::last_error(res), - )) + Err(io::Error::new(io::ErrorKind::Other, Error::last_error(res))) } else { Ok(buf.len()) } From 3cef4119f368b9df9cb65523898e0405ae75f987 Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Thu, 25 Jul 2024 16:53:39 -0700 Subject: [PATCH 782/860] README: document when libgit2 is statically linked I found the previous paragraph in the current version of the README quite confusing. The text follows my understanding of https://github.com/rust-lang/git2-rs/blob/f1f09cee7b332d2b494d14d46fd2ec8e5203916a/libgit2-sys/build.rs#L25-L56. I hope it's OK to hide the bit about `zlib` under the case where an "appropriate version of libgit2 cannot be found". Feel free to edit this further. Cc: commit 59a81cac I looked into this because I was confused that, after upgrading the Homebrew version of libgit2, my builds of https://github.com/martinvonz/jj started linking libgit2 statically. I'm planning to try enabling `vendored_libgit2` in that project permanently and recommending that people use the environment variable `LIBGIT2_NO_VENDOR=1` if they want dynamic linking. --- README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e66c049d37..e909e4a53b 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,17 @@ stable release as well. Currently this library requires libgit2 1.7.2 (or newer patch versions). The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or -build that for you. +build that for you. On the other hand, if an appropriate version of `libgit2` +is present, `git2` will attempt to dynamically link it. -You can enable the Cargo feature `vendored-libgit2` to always compile and -statically link to a copy of libgit2. Sometimes the libgit2 on the system is -required to be found and used even when `vendored-libgit2` is activated. In -this case, you shall set the environment variable `LIBGIT2_NO_VENDOR=1`. +To be more precise, the vendored `libgit2` is linked statically if two +conditions both hold: + +- The enviornment variable `LIBGIT2_NO_VENDOR=1` is **not** set +- **and** either a) The Cargo feature `vendored-libgit2` is set or b) an + appropriate version of `libgit2` cannot be found on the system. + +In particular, note that the environment variable overrides the Cargo feature. ## Building git2-rs From fc1556add810a11195ff78849c82fbea9c1c1f89 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Thu, 1 Aug 2024 17:07:28 -0400 Subject: [PATCH 783/860] derive `Debug` for `transport::Service` --- src/transport.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transport.rs b/src/transport.rs index 3a4660627f..b1ca3f8b80 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -54,7 +54,7 @@ pub trait SmartSubtransport: Send + 'static { } /// Actions that a smart transport can ask a subtransport to perform -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, PartialEq, Debug)] #[allow(missing_docs)] pub enum Service { UploadPackLs, From 4e763c7be6c5acaa43937b5535e8b00d99749c4a Mon Sep 17 00:00:00 2001 From: Fedor Sheremetyev Date: Sun, 11 Aug 2024 17:18:26 +0100 Subject: [PATCH 784/860] Don't show console on Windows When used inside GUI application, git2 causes console window to appear temporarily, due to execution of sh. Command needs special flags to prevent that. More details: https://stackoverflow.com/a/60958956 --- src/cred.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/cred.rs b/src/cred.rs index fc0b941935..b1f15cab13 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -372,6 +372,12 @@ impl CredentialHelper { // If that fails then it's up to the user to put `sh` in path and make // sure it works. let mut c = Command::new("sh"); + #[cfg(windows)] + { + use std::os::windows::process::CommandExt; + const CREATE_NO_WINDOW: u32 = 0x08000000; + c.creation_flags(CREATE_NO_WINDOW); + } c.arg("-c") .arg(&format!("{} get", cmd)) .stdin(Stdio::piped()) @@ -384,6 +390,12 @@ impl CredentialHelper { debug!("`sh` failed to spawn: {}", e); let mut parts = cmd.split_whitespace(); let mut c = Command::new(parts.next().unwrap()); + #[cfg(windows)] + { + use std::os::windows::process::CommandExt; + const CREATE_NO_WINDOW: u32 = 0x08000000; + c.creation_flags(CREATE_NO_WINDOW); + } for arg in parts { c.arg(arg); } From 9e03d66ede4d092cdb1469e4ebeddd51f80e94e2 Mon Sep 17 00:00:00 2001 From: Martin Joerg Date: Thu, 15 Aug 2024 13:13:30 +0000 Subject: [PATCH 785/860] README: update reference to libgit2 version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e909e4a53b..ee335435e8 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ stable release as well. ## Version of libgit2 -Currently this library requires libgit2 1.7.2 (or newer patch versions). The +Currently this library requires libgit2 1.8.1 (or newer patch versions). The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. On the other hand, if an appropriate version of `libgit2` From f4c69140e3f77afb3d46026390309ac1e1c2fc12 Mon Sep 17 00:00:00 2001 From: Richard Steinmetz Date: Wed, 21 Aug 2024 21:21:51 +0200 Subject: [PATCH 786/860] repo: implement git_repository_commondir --- libgit2-sys/lib.rs | 1 + src/repo.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index f7175f4140..0909d15994 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -2148,6 +2148,7 @@ extern "C" { pub fn git_repository_is_empty(repo: *mut git_repository) -> c_int; pub fn git_repository_is_shallow(repo: *mut git_repository) -> c_int; pub fn git_repository_path(repo: *const git_repository) -> *const c_char; + pub fn git_repository_commondir(repo: *const git_repository) -> *const c_char; pub fn git_repository_state(repo: *mut git_repository) -> c_int; pub fn git_repository_workdir(repo: *const git_repository) -> *const c_char; pub fn git_repository_set_workdir( diff --git a/src/repo.rs b/src/repo.rs index b94b4007db..13a5fb8670 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -456,6 +456,16 @@ impl Repository { } } + /// If the repository is bare, it is the root directory for the repository. + /// If the repository is a worktree, it is the parent repo's gitdir. + /// Otherwise, it is the gitdir. + pub fn commondir(&self) -> &Path { + unsafe { + let ptr = raw::git_repository_commondir(self.raw); + util::bytes2path(crate::opt_bytes(self, ptr).unwrap()) + } + } + /// Returns the current state of this repository pub fn state(&self) -> RepositoryState { let state = unsafe { raw::git_repository_state(self.raw) }; @@ -4304,4 +4314,22 @@ Committer Name "#, .unwrap(); assert_eq!(tag.id(), found_tag.id()); } + + #[test] + fn smoke_commondir() { + let (td, repo) = crate::test::repo_init(); + assert_eq!( + crate::test::realpath(repo.path()).unwrap(), + crate::test::realpath(repo.commondir()).unwrap() + ); + + let worktree = repo + .worktree("test", &td.path().join("worktree"), None) + .unwrap(); + let worktree_repo = Repository::open_from_worktree(&worktree).unwrap(); + assert_eq!( + crate::test::realpath(repo.path()).unwrap(), + crate::test::realpath(worktree_repo.commondir()).unwrap() + ); + } } From cb4ea6ec4e3323682b248da5d1e9323865df4d83 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 21 Aug 2024 13:31:51 -0700 Subject: [PATCH 787/860] Add description line for commondir --- src/repo.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index 13a5fb8670..3924b2aa14 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -456,6 +456,8 @@ impl Repository { } } + /// Returns the path of the shared common directory for this repository. + /// /// If the repository is bare, it is the root directory for the repository. /// If the repository is a worktree, it is the parent repo's gitdir. /// Otherwise, it is the gitdir. From 91907f9ee83cb49d69f5f4d655ec456b8b26dd50 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Tue, 1 Oct 2024 21:11:26 -0700 Subject: [PATCH 788/860] delete ineffective ssh_key_from_memory crate feature The ssh_key_from_memory crate feature was added in commit 8ca0e92 (2018-07-26). Then it was accidentally made always-on in commit 76f4b74 (2018-09013). Since it seems like no one has missed the ability to turn it off since then (not enough to send a PR anyway), let's just delete the crate feature. Closes #363 --- Cargo.toml | 3 +-- libgit2-sys/Cargo.toml | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9e6fd81f56..4d8d633271 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,12 +33,11 @@ tempfile = "3.1.0" [features] unstable = [] -default = ["ssh", "https", "ssh_key_from_memory"] +default = ["ssh", "https"] ssh = ["libgit2-sys/ssh"] https = ["libgit2-sys/https", "openssl-sys", "openssl-probe"] vendored-libgit2 = ["libgit2-sys/vendored"] vendored-openssl = ["openssl-sys/vendored", "libgit2-sys/vendored-openssl"] -ssh_key_from_memory = ["libgit2-sys/ssh_key_from_memory"] zlib-ng-compat = ["libgit2-sys/zlib-ng-compat"] [workspace] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index ff911c99f5..5b5d92278a 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -35,7 +35,6 @@ openssl-sys = { version = "0.9.45", optional = true } [features] ssh = ["libssh2-sys"] https = ["openssl-sys"] -ssh_key_from_memory = [] vendored = [] vendored-openssl = ["openssl-sys/vendored"] zlib-ng-compat = ["libz-sys/zlib-ng", "libssh2-sys?/zlib-ng-compat"] From 5dd077a0f795b19b2e5199fb8e9b1f1711dad333 Mon Sep 17 00:00:00 2001 From: Caleb Owens Date: Wed, 2 Oct 2024 13:57:52 +0200 Subject: [PATCH 789/860] Added merge_base_octopus --- libgit2-sys/lib.rs | 7 ++++++ src/repo.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 0909d15994..383db6c37e 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -3506,6 +3506,13 @@ extern "C" { input_array: *const git_oid, ) -> c_int; + pub fn git_merge_base_octopus( + out: *mut git_oid, + repo: *mut git_repository, + length: size_t, + input_array: *const git_oid, + ) -> c_int; + pub fn git_merge_bases( out: *mut git_oidarray, repo: *mut git_repository, diff --git a/src/repo.rs b/src/repo.rs index 3924b2aa14..cae4e90b2f 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2467,6 +2467,38 @@ impl Repository { } /// Find a merge base given a list of commits + /// + /// This behaves similar to [`git merge-base`](https://git-scm.com/docs/git-merge-base#_discussion). + /// Given three commits `a`, `b`, and `c`, `merge_base_many(&[a, b, c])` + /// will compute a hypothetical commit `m`, which is a merge between `b` + /// and `c`. + /// + /// For example, with the following topology: + /// ```text + /// o---o---o---o---C + /// / + /// / o---o---o---B + /// / / + /// ---2---1---o---o---o---A + /// ``` + /// + /// the result of `merge_base_many(&[a, b, c])` is 1. This is because the + /// equivalent topology with a merge commit `m` between `b` and `c` would + /// is: + /// ```text + /// o---o---o---o---o + /// / \ + /// / o---o---o---o---M + /// / / + /// ---2---1---o---o---o---A + /// ``` + /// + /// and the result of `merge_base_many(&[a, m])` is 1. + /// + /// --- + /// + /// If you're looking to recieve the common merge base between all the + /// given commits, use [`Self::merge_base_octopus`]. pub fn merge_base_many(&self, oids: &[Oid]) -> Result { let mut raw = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ], @@ -2483,6 +2515,23 @@ impl Repository { } } + /// Find a common merge base between all given a list of commits + pub fn merge_base_octopus(&self, oids: &[Oid]) -> Result { + let mut raw = raw::git_oid { + id: [0; raw::GIT_OID_RAWSZ], + }; + + unsafe { + try_call!(raw::git_merge_base_octopus( + &mut raw, + self.raw, + oids.len() as size_t, + oids.as_ptr() as *const raw::git_oid + )); + Ok(Binding::from_raw(&raw as *const _)) + } + } + /// Find all merge bases between two commits pub fn merge_bases(&self, one: Oid, two: Oid) -> Result { let mut arr = raw::git_oidarray { @@ -3825,6 +3874,10 @@ mod tests { // the merge base of (oid2,oid3,oid4) should be oid1 let merge_base = repo.merge_base_many(&[oid2, oid3, oid4]).unwrap(); assert_eq!(merge_base, oid1); + + // the octopus merge base of (oid2,oid3,oid4) should be oid1 + let merge_base = repo.merge_base_octopus(&[oid2, oid3, oid4]).unwrap(); + assert_eq!(merge_base, oid1); } /// create an octopus: From 4639d788063d639d4f4ce1a8d640b9a649543854 Mon Sep 17 00:00:00 2001 From: Philip Johansson Date: Tue, 12 Nov 2024 12:14:55 +0100 Subject: [PATCH 790/860] Maintain backwards compatibility for bitflags types --- src/lib.rs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e52efb3734..f5ee545adc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -419,7 +419,7 @@ pub enum FileFavor { bitflags! { /// Orderings that may be specified for Revwalk iteration. - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct Sort: u32 { /// Sort the repository contents in no particular ordering. /// @@ -454,7 +454,7 @@ impl Sort { bitflags! { /// Types of credentials that can be requested by a credential callback. - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct CredentialType: u32 { #[allow(missing_docs)] const USER_PASS_PLAINTEXT = raw::GIT_CREDTYPE_USERPASS_PLAINTEXT as u32; @@ -491,7 +491,7 @@ impl Default for CredentialType { bitflags! { /// Flags for the `flags` field of an IndexEntry. - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct IndexEntryFlag: u16 { /// Set when the `extended_flags` field is valid. const EXTENDED = raw::GIT_INDEX_ENTRY_EXTENDED as u16; @@ -507,7 +507,7 @@ impl IndexEntryFlag { bitflags! { /// Flags for the `extended_flags` field of an IndexEntry. - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct IndexEntryExtendedFlag: u16 { /// An "intent to add" entry from "git add -N" const INTENT_TO_ADD = raw::GIT_INDEX_ENTRY_INTENT_TO_ADD as u16; @@ -527,7 +527,7 @@ impl IndexEntryExtendedFlag { bitflags! { /// Flags for APIs that add files matching pathspec - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct IndexAddOption: u32 { #[allow(missing_docs)] const DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32; @@ -559,7 +559,7 @@ impl Default for IndexAddOption { bitflags! { /// Flags for `Repository::open_ext` - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct RepositoryOpenFlags: u32 { /// Only open the specified path; don't walk upward searching. const NO_SEARCH = raw::GIT_REPOSITORY_OPEN_NO_SEARCH as u32; @@ -584,7 +584,7 @@ impl RepositoryOpenFlags { bitflags! { /// Flags for the return value of `Repository::revparse` - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct RevparseMode: u32 { /// The spec targeted a single object const SINGLE = raw::GIT_REVPARSE_SINGLE as u32; @@ -603,7 +603,7 @@ impl RevparseMode { bitflags! { /// The results of `merge_analysis` indicating the merge opportunities. - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct MergeAnalysis: u32 { /// No merge is possible. const ANALYSIS_NONE = raw::GIT_MERGE_ANALYSIS_NONE as u32; @@ -634,7 +634,7 @@ impl MergeAnalysis { bitflags! { /// The user's stated preference for merges. - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct MergePreference: u32 { /// No configuration was found that suggests a preferred behavior for /// merge. @@ -656,7 +656,7 @@ impl MergePreference { bitflags! { /// Flags controlling the behavior of ODB lookup operations - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct OdbLookupFlags: u32 { /// Don't call `git_odb_refresh` if the lookup fails. Useful when doing /// a batch of lookup operations for objects that may legitimately not @@ -668,7 +668,7 @@ bitflags! { bitflags! { /// How to handle reference updates. - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct RemoteUpdateFlags: u32 { /// Write the fetch results to FETCH_HEAD. const UPDATE_FETCHHEAD = raw::GIT_REMOTE_UPDATE_FETCHHEAD as u32; @@ -1023,7 +1023,7 @@ bitflags! { /// represents the status of file in the index relative to the HEAD, and the /// `STATUS_WT_*` set of flags represent the status of the file in the /// working directory relative to the index. - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct Status: u32 { #[allow(missing_docs)] const CURRENT = raw::GIT_STATUS_CURRENT as u32; @@ -1074,7 +1074,7 @@ impl Status { bitflags! { /// Mode options for RepositoryInitOptions - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct RepositoryInitMode: u32 { /// Use permissions configured by umask - the default const SHARED_UMASK = raw::GIT_REPOSITORY_INIT_SHARED_UMASK as u32; @@ -1207,7 +1207,7 @@ bitflags! { /// Lastly, the following will only be returned for ignore "NONE". /// /// * WD_UNTRACKED - workdir contains untracked files - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct SubmoduleStatus: u32 { #[allow(missing_docs)] const IN_HEAD = raw::GIT_SUBMODULE_STATUS_IN_HEAD as u32; @@ -1304,7 +1304,7 @@ pub enum SubmoduleUpdate { bitflags! { /// ... - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct PathspecFlags: u32 { /// Use the default pathspec matching configuration. const DEFAULT = raw::GIT_PATHSPEC_DEFAULT as u32; @@ -1350,7 +1350,7 @@ impl Default for PathspecFlags { bitflags! { /// Types of notifications emitted from checkouts. - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct CheckoutNotificationType: u32 { /// Notification about a conflict. const CONFLICT = raw::GIT_CHECKOUT_NOTIFY_CONFLICT as u32; @@ -1392,7 +1392,7 @@ pub enum DiffFormat { bitflags! { /// Formatting options for diff stats - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct DiffStatsFormat: raw::git_diff_stats_format_t { /// Don't generate any stats const NONE = raw::GIT_DIFF_STATS_NONE; @@ -1463,7 +1463,7 @@ pub enum StashApplyProgress { bitflags! { #[allow(missing_docs)] - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct StashApplyFlags: u32 { #[allow(missing_docs)] const DEFAULT = raw::GIT_STASH_APPLY_DEFAULT as u32; @@ -1486,7 +1486,7 @@ impl Default for StashApplyFlags { bitflags! { #[allow(missing_docs)] - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct StashFlags: u32 { #[allow(missing_docs)] const DEFAULT = raw::GIT_STASH_DEFAULT as u32; @@ -1519,7 +1519,7 @@ impl Default for StashFlags { bitflags! { #[allow(missing_docs)] - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct AttrCheckFlags: u32 { /// Check the working directory, then the index. const FILE_THEN_INDEX = raw::GIT_ATTR_CHECK_FILE_THEN_INDEX as u32; @@ -1540,7 +1540,7 @@ impl Default for AttrCheckFlags { bitflags! { #[allow(missing_docs)] - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct DiffFlags: u32 { /// File(s) treated as binary data. const BINARY = raw::GIT_DIFF_FLAG_BINARY as u32; @@ -1562,7 +1562,7 @@ impl DiffFlags { bitflags! { /// Options for [`Reference::normalize_name`]. - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct ReferenceFormat: u32 { /// No particular normalization. const NORMAL = raw::GIT_REFERENCE_FORMAT_NORMAL as u32; From 41d8e0679d56ab634e771c26cb3a4fb16c396a1e Mon Sep 17 00:00:00 2001 From: Ximo Guanter Date: Tue, 19 Nov 2024 08:55:46 -0500 Subject: [PATCH 791/860] Propagate errors on Tree::walk --- libgit2-sys/lib.rs | 2 +- src/call.rs | 11 +++++++++++ src/tree.rs | 36 ++++++++++++++++++++---------------- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 383db6c37e..54d384afc9 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -742,7 +742,7 @@ git_enum! { } pub type git_treewalk_cb = - Option c_int>; + *const extern "C" fn(*const c_char, *const git_tree_entry, *mut c_void) -> c_int; pub type git_treebuilder_filter_cb = Option c_int>; diff --git a/src/call.rs b/src/call.rs index a18f05da91..57aaa26dbd 100644 --- a/src/call.rs +++ b/src/call.rs @@ -116,6 +116,17 @@ mod impls { } } + impl Convert for crate::TreeWalkMode { + #[cfg(target_env = "msvc")] + fn convert(&self) -> raw::git_treewalk_mode { + *self as i32 + } + #[cfg(not(target_env = "msvc"))] + fn convert(&self) -> raw::git_treewalk_mode { + *self as u32 + } + } + impl Convert for Direction { fn convert(&self) -> raw::git_direction { match *self { diff --git a/src/tree.rs b/src/tree.rs index ae8fe3b4c5..376ca9aa2d 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -36,6 +36,7 @@ pub struct TreeIter<'tree> { /// A binary indicator of whether a tree walk should be performed in pre-order /// or post-order. +#[derive(Clone, Copy)] pub enum TreeWalkMode { /// Runs the traversal in pre-order. PreOrder = 0, @@ -60,17 +61,6 @@ impl Into for TreeWalkResult { } } -impl Into for TreeWalkMode { - #[cfg(target_env = "msvc")] - fn into(self) -> raw::git_treewalk_mode { - self as i32 - } - #[cfg(not(target_env = "msvc"))] - fn into(self) -> raw::git_treewalk_mode { - self as u32 - } -} - impl<'repo> Tree<'repo> { /// Get the id (SHA1) of a repository object pub fn id(&self) -> Oid { @@ -126,12 +116,12 @@ impl<'repo> Tree<'repo> { let mut data = TreeWalkCbData { callback: &mut callback, }; - raw::git_tree_walk( + try_call!(raw::git_tree_walk( self.raw(), - mode.into(), - Some(treewalk_cb::), - &mut data as *mut _ as *mut c_void, - ); + mode, + treewalk_cb:: as raw::git_treewalk_cb, + &mut data as *mut _ as *mut c_void + )); Ok(()) } } @@ -599,4 +589,18 @@ mod tests { .unwrap(); assert_eq!(ct, 8); } + + #[test] + fn tree_walk_error() { + let (td, repo) = crate::test::repo_init(); + + setup_repo(&td, &repo); + + let head = repo.head().unwrap(); + let target = head.target().unwrap(); + let commit = repo.find_commit(target).unwrap(); + let tree = repo.find_tree(commit.tree_id()).unwrap(); + + assert!(tree.walk(TreeWalkMode::PreOrder, |_, _| { -1 }).is_err()); + } } From 40559981ed743616ef7283ac977dd0ab9caaa2fa Mon Sep 17 00:00:00 2001 From: aviac Date: Wed, 27 Nov 2024 20:02:31 +0100 Subject: [PATCH 792/860] docs(config): add link to snapshot method We noticed that the docs around config are not as helpful yet as they could be. Newer rust users tend to assume that using `get_str` wouldn't be as hard to use and that it instead would work the same way as the other getters. This commit: - Adds a link to `snapshot` method documentation to provide additional guidance for newer Rust users. - Extends the error explanation with a vague reason to enhance understanding of the current behavior. Co-authored-by: gytic <149968794+gytic@users.noreply.github.com> --- src/config.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/config.rs b/src/config.rs index 6f12efc322..9ba0a6da64 100644 --- a/src/config.rs +++ b/src/config.rs @@ -237,7 +237,10 @@ impl Config { /// This is the same as `get_bytes` except that it may return `Err` if /// the bytes are not valid utf-8. /// - /// This method will return an error if this `Config` is not a snapshot. + /// For consistency reasons, this method can only be called on a [`snapshot`]. + /// An error will be returned otherwise. + /// + /// [`snapshot`]: `crate::Config::snapshot` pub fn get_str(&self, name: &str) -> Result<&str, Error> { str::from_utf8(self.get_bytes(name)?) .map_err(|_| Error::from_str("configuration value is not valid utf8")) @@ -245,7 +248,10 @@ impl Config { /// Get the value of a string config variable as a byte slice. /// - /// This method will return an error if this `Config` is not a snapshot. + /// For consistency reasons, this method can only be called on a [`snapshot`]. + /// An error will be returned otherwise. + /// + /// [`snapshot`]: `crate::Config::snapshot` pub fn get_bytes(&self, name: &str) -> Result<&[u8], Error> { let mut ret = ptr::null(); let name = CString::new(name)?; From 91980d9f631b20bb9f44727fc2314196ad4578e5 Mon Sep 17 00:00:00 2001 From: leopardracer <136604165+leopardracer@users.noreply.github.com> Date: Mon, 2 Dec 2024 15:15:34 +0200 Subject: [PATCH 793/860] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ee335435e8..b23b24e35d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ is present, `git2` will attempt to dynamically link it. To be more precise, the vendored `libgit2` is linked statically if two conditions both hold: -- The enviornment variable `LIBGIT2_NO_VENDOR=1` is **not** set +- The environment variable `LIBGIT2_NO_VENDOR=1` is **not** set - **and** either a) The Cargo feature `vendored-libgit2` is set or b) an appropriate version of `libgit2` cannot be found on the system. From 7db456d60f7344dae1ce7b25ba46b6639a8c4116 Mon Sep 17 00:00:00 2001 From: yuanyan Date: Wed, 18 Dec 2024 15:40:24 +0800 Subject: [PATCH 794/860] add GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH support --- src/build.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/build.rs b/src/build.rs index d3c95f6559..1cf3f98d96 100644 --- a/src/build.rs +++ b/src/build.rs @@ -491,6 +491,11 @@ impl<'cb> CheckoutBuilder<'cb> { self.flag(raw::GIT_CHECKOUT_CONFLICT_STYLE_DIFF3, on) } + /// Treat paths as a simple list. + pub fn disable_pathspec_match(&mut self, on: bool) -> &mut CheckoutBuilder<'cb> { + self.flag(raw::GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH, on) + } + /// Indicate whether to apply filters like CRLF conversion. pub fn disable_filters(&mut self, disable: bool) -> &mut CheckoutBuilder<'cb> { self.disable_filters = disable; From 9ae249f53d07982e04017eb26cc976c99ec1c571 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Dec 2024 09:06:45 -0800 Subject: [PATCH 795/860] Clarify disable_pathspec_match docs --- src/build.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/build.rs b/src/build.rs index 1cf3f98d96..4ac62439b7 100644 --- a/src/build.rs +++ b/src/build.rs @@ -491,7 +491,8 @@ impl<'cb> CheckoutBuilder<'cb> { self.flag(raw::GIT_CHECKOUT_CONFLICT_STYLE_DIFF3, on) } - /// Treat paths as a simple list. + /// Treat paths specified in [`CheckoutBuilder::path`] as exact file paths + /// instead of as pathspecs. pub fn disable_pathspec_match(&mut self, on: bool) -> &mut CheckoutBuilder<'cb> { self.flag(raw::GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH, on) } @@ -520,8 +521,13 @@ impl<'cb> CheckoutBuilder<'cb> { /// Add a path to be checked out. /// + /// The path is a [pathspec] pattern, unless + /// [`CheckoutBuilder::disable_pathspec_match`] is set. + /// /// If no paths are specified, then all files are checked out. Otherwise /// only these specified paths are checked out. + /// + /// [pathspec]: https://git-scm.com/docs/gitglossary.html#Documentation/gitglossary.txt-aiddefpathspecapathspec pub fn path(&mut self, path: T) -> &mut CheckoutBuilder<'cb> { let path = util::cstring_to_repo_path(path).unwrap(); self.path_ptrs.push(path.as_ptr()); From 3e2c8ceac8a66542218bf51559e74a85684cbd7f Mon Sep 17 00:00:00 2001 From: Leo Sale Date: Tue, 31 Dec 2024 10:55:12 +0100 Subject: [PATCH 796/860] Expose git_packbuilder_write fn --- src/packbuilder.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/packbuilder.rs b/src/packbuilder.rs index 9b93e7654b..643aa4f4ed 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -1,10 +1,13 @@ use libc::{c_int, c_uint, c_void, size_t}; use std::marker; +use std::path::Path; use std::ptr; use std::slice; use std::str; +use crate::odb::{write_pack_progress_cb, OdbPackwriterCb}; use crate::util::Binding; +use crate::IntoCString; use crate::{panic, raw, Buf, Error, Oid, Repository, Revwalk}; #[derive(PartialEq, Eq, Clone, Debug, Copy)] @@ -84,6 +87,27 @@ impl<'repo> PackBuilder<'repo> { Ok(()) } + /// Write the contents of the packfile to the specified path. The contents + /// of the buffer will become a valid packfile, even though there will be + /// no attached index. + pub fn write(&mut self, path: &Path, mode: u32) -> Result<(), Error> { + let path = path.into_c_string()?; + let progress_cb: raw::git_indexer_progress_cb = Some(write_pack_progress_cb); + let progress_payload = Box::new(OdbPackwriterCb { cb: None }); + let progress_payload_ptr = Box::into_raw(progress_payload); + + unsafe { + try_call!(raw::git_packbuilder_write( + self.raw, + path, + mode, + progress_cb, + progress_payload_ptr as *mut _ + )); + } + Ok(()) + } + /// Create the new pack and pass each object to the callback. pub fn foreach(&mut self, mut cb: F) -> Result<(), Error> where From a1dabe6c6a14cc2fba1a9e83af3ff9d3d8a24212 Mon Sep 17 00:00:00 2001 From: Leo Sale Date: Thu, 2 Jan 2025 16:29:21 +0100 Subject: [PATCH 797/860] Update comment and add tests --- src/packbuilder.rs | 74 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 4 deletions(-) diff --git a/src/packbuilder.rs b/src/packbuilder.rs index 643aa4f4ed..de47bbce32 100644 --- a/src/packbuilder.rs +++ b/src/packbuilder.rs @@ -87,9 +87,8 @@ impl<'repo> PackBuilder<'repo> { Ok(()) } - /// Write the contents of the packfile to the specified path. The contents - /// of the buffer will become a valid packfile, even though there will be - /// no attached index. + /// Write the new pack and corresponding index file to path. + /// To set a progress callback, use `set_progress_callback` before calling this method. pub fn write(&mut self, path: &Path, mode: u32) -> Result<(), Error> { let path = path.into_c_string()?; let progress_cb: raw::git_indexer_progress_cb = Some(write_pack_progress_cb); @@ -294,7 +293,10 @@ extern "C" fn progress_c( #[cfg(test)] mod tests { - use crate::Buf; + use crate::{Buf, Oid}; + + // hash of a packfile constructed without any objects in it + const EMPTY_PACKFILE_OID: &str = "029d08823bd8a8eab510ad6ac75c823cfd3ed31e"; fn pack_header(len: u8) -> Vec { [].iter() @@ -338,6 +340,18 @@ mod tests { assert_eq!(&*buf, &*empty_pack_header()); } + #[test] + fn smoke_write() { + let (_td, repo) = crate::test::repo_init(); + let mut builder = t!(repo.packbuilder()); + t!(builder.write(repo.path(), 0)); + #[allow(deprecated)] + { + assert!(builder.hash().unwrap() == Oid::from_str(EMPTY_PACKFILE_OID).unwrap()); + } + assert!(builder.name().unwrap() == EMPTY_PACKFILE_OID); + } + #[test] fn smoke_foreach() { let (_td, repo) = crate::test::repo_init(); @@ -391,6 +405,41 @@ mod tests { assert_eq!(&buf[0..12], &*pack_header(3)); } + #[test] + fn insert_write() { + let (_td, repo) = crate::test::repo_init(); + let mut builder = t!(repo.packbuilder()); + let (commit, _tree) = crate::test::commit(&repo); + t!(builder.insert_object(commit, None)); + assert_eq!(builder.object_count(), 1); + t!(builder.write(repo.path(), 0)); + t!(repo.find_commit(commit)); + } + + #[test] + fn insert_tree_write() { + let (_td, repo) = crate::test::repo_init(); + let mut builder = t!(repo.packbuilder()); + let (_commit, tree) = crate::test::commit(&repo); + // will insert the tree itself and the blob, 2 objects + t!(builder.insert_tree(tree)); + assert_eq!(builder.object_count(), 2); + t!(builder.write(repo.path(), 0)); + t!(repo.find_tree(tree)); + } + + #[test] + fn insert_commit_write() { + let (_td, repo) = crate::test::repo_init(); + let mut builder = t!(repo.packbuilder()); + let (commit, _tree) = crate::test::commit(&repo); + // will insert the commit, its tree and the blob, 3 objects + t!(builder.insert_commit(commit)); + assert_eq!(builder.object_count(), 3); + t!(builder.write(repo.path(), 0)); + t!(repo.find_commit(commit)); + } + #[test] fn progress_callback() { let mut progress_called = false; @@ -426,6 +475,23 @@ mod tests { assert_eq!(progress_called, false); } + #[test] + fn progress_callback_with_write() { + let mut progress_called = false; + { + let (_td, repo) = crate::test::repo_init(); + let mut builder = t!(repo.packbuilder()); + let (commit, _tree) = crate::test::commit(&repo); + t!(builder.set_progress_callback(|_, _, _| { + progress_called = true; + true + })); + t!(builder.insert_commit(commit)); + t!(builder.write(repo.path(), 0)); + } + assert_eq!(progress_called, true); + } + #[test] fn set_threads() { let (_td, repo) = crate::test::repo_init(); From a660082a733237cb876d5a01b0d5cc4d7c4d7ebc Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 4 Jan 2025 11:23:29 -0800 Subject: [PATCH 798/860] Update libgit2 to 1.9 --- Cargo.toml | 4 ++-- README.md | 4 ++-- git2-curl/Cargo.toml | 4 ++-- git2-curl/src/lib.rs | 2 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/build.rs | 2 +- libgit2-sys/lib.rs | 23 +++++++++++++++++------ libgit2-sys/libgit2 | 2 +- src/lib.rs | 2 +- src/repo.rs | 12 ++++++------ systest/build.rs | 1 + tests/add_extensions.rs | 21 ++++++++++++++------- tests/get_extensions.rs | 19 +++++++++++++------ tests/remove_extensions.rs | 6 +++--- 14 files changed, 65 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9e6fd81f56..80fbd142bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.19.0" +version = "0.20.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.0" bitflags = "2.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.17.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.18.0" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.45", optional = true } diff --git a/README.md b/README.md index b23b24e35d..ae1c377da9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.19.0" +git2 = "0.20.0" ``` ## Rust version requirements @@ -16,7 +16,7 @@ stable release as well. ## Version of libgit2 -Currently this library requires libgit2 1.8.1 (or newer patch versions). The +Currently this library requires libgit2 1.9.0 (or newer patch versions). The source for libgit2 is included in the libgit2-sys crate so there's no need to pre-install the libgit2 library, the libgit2-sys crate will figure that and/or build that for you. On the other hand, if an appropriate version of `libgit2` diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index f63819149d..11dae7f8a4 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2-curl" -version = "0.20.0" +version = "0.21.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" @@ -16,7 +16,7 @@ edition = "2018" curl = "0.4.33" url = "2.0" log = "0.4" -git2 = { path = "..", version = "0.19", default-features = false } +git2 = { path = "..", version = "0.20", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/git2-curl/src/lib.rs b/git2-curl/src/lib.rs index f480ffc71c..6fa4532772 100644 --- a/git2-curl/src/lib.rs +++ b/git2-curl/src/lib.rs @@ -15,7 +15,7 @@ //! > **NOTE**: At this time this crate likely does not support a `git push` //! > operation, only clones. -#![doc(html_root_url = "https://docs.rs/git2-curl/0.20")] +#![doc(html_root_url = "https://docs.rs/git2-curl/0.21")] #![deny(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index ff911c99f5..68bf0c0048 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.17.0+1.8.1" +version = "0.18.0+1.9.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 1abf628c6e..57686ad5cf 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -7,7 +7,7 @@ use std::process::Command; /// Tries to use system libgit2 and emits necessary build script instructions. fn try_system_libgit2() -> Result { let mut cfg = pkg_config::Config::new(); - match cfg.range_version("1.8.1".."1.9.0").probe("libgit2") { + match cfg.range_version("1.9.0".."1.10.0").probe("libgit2") { Ok(lib) => { for include in &lib.include_paths { println!("cargo:root={}", include.display()); diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 383db6c37e..03c4a0a34f 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.17")] +#![doc(html_root_url = "https://docs.rs/libgit2-sys/0.18")] #![allow(non_camel_case_types, unused_extern_crates)] // This is required to link libz when libssh2-sys is not included. @@ -395,6 +395,15 @@ pub struct git_remote_callbacks { pub remote_ready: git_remote_ready_cb, pub payload: *mut c_void, pub resolve_url: git_url_resolve_cb, + pub update_refs: Option< + extern "C" fn( + *const c_char, + *const git_oid, + *const git_oid, + *mut git_refspec, + *mut c_void, + ) -> c_int, + >, } #[repr(C)] @@ -668,8 +677,7 @@ pub struct git_status_entry { git_enum! { pub enum git_checkout_strategy_t { - GIT_CHECKOUT_NONE = 0, - GIT_CHECKOUT_SAFE = 1 << 0, + GIT_CHECKOUT_SAFE = 0, GIT_CHECKOUT_FORCE = 1 << 1, GIT_CHECKOUT_RECREATE_MISSING = 1 << 2, GIT_CHECKOUT_ALLOW_CONFLICTS = 1 << 4, @@ -686,6 +694,7 @@ git_enum! { GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = 1 << 19, GIT_CHECKOUT_CONFLICT_STYLE_MERGE = 1 << 20, GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = 1 << 21, + GIT_CHECKOUT_NONE = 1 << 30, GIT_CHECKOUT_UPDATE_SUBMODULES = 1 << 16, GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = 1 << 17, @@ -808,10 +817,13 @@ pub struct git_blame_hunk { pub final_commit_id: git_oid, pub final_start_line_number: usize, pub final_signature: *mut git_signature, + pub final_committer: *mut git_signature, pub orig_commit_id: git_oid, pub orig_path: *const c_char, pub orig_start_line_number: usize, pub orig_signature: *mut git_signature, + pub orig_committer: *mut git_signature, + pub summary: *const c_char, pub boundary: c_char, } @@ -870,7 +882,6 @@ pub struct git_config_entry { pub origin_path: *const c_char, pub include_depth: c_uint, pub level: git_config_level_t, - pub free: Option, } git_enum! { @@ -2906,7 +2917,7 @@ extern "C" { message: *const c_char, tree: *const git_tree, parent_count: size_t, - parents: *const *mut git_commit, + parents: *mut *const git_commit, ) -> c_int; pub fn git_commit_create_buffer( out: *mut git_buf, @@ -2917,7 +2928,7 @@ extern "C" { message: *const c_char, tree: *const git_tree, parent_count: size_t, - parents: *const *mut git_commit, + parents: *mut *const git_commit, ) -> c_int; pub fn git_commit_header_field( out: *mut git_buf, diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 36f7e21ad7..338e6fb681 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 36f7e21ad757a3dacc58cf7944329da6bc1d6e96 +Subproject commit 338e6fb681369ff0537719095e22ce9dc602dbf0 diff --git a/src/lib.rs b/src/lib.rs index f5ee545adc..01c9a93517 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.19")] +#![doc(html_root_url = "https://docs.rs/git2/0.20")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] diff --git a/src/repo.rs b/src/repo.rs index cae4e90b2f..efdb49259e 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1302,9 +1302,9 @@ impl Repository { parents: &[&Commit<'_>], ) -> Result { let update_ref = crate::opt_cstr(update_ref)?; - let parent_ptrs = parents + let mut parent_ptrs = parents .iter() - .map(|p| p.raw() as *mut raw::git_commit) + .map(|p| p.raw() as *const raw::git_commit) .collect::>(); let message = CString::new(message)?; let mut raw = raw::git_oid { @@ -1321,7 +1321,7 @@ impl Repository { message, tree.raw(), parents.len() as size_t, - parent_ptrs.as_ptr() + parent_ptrs.as_mut_ptr() )); Ok(Binding::from_raw(&raw as *const _)) } @@ -1340,9 +1340,9 @@ impl Repository { tree: &Tree<'_>, parents: &[&Commit<'_>], ) -> Result { - let parent_ptrs = parents + let mut parent_ptrs = parents .iter() - .map(|p| p.raw() as *mut raw::git_commit) + .map(|p| p.raw() as *const raw::git_commit) .collect::>(); let message = CString::new(message)?; let buf = Buf::new(); @@ -1356,7 +1356,7 @@ impl Repository { message, tree.raw(), parents.len() as size_t, - parent_ptrs.as_ptr() + parent_ptrs.as_mut_ptr() )); Ok(buf) } diff --git a/systest/build.rs b/systest/build.rs index 85e8b4b437..9503af7e10 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -15,6 +15,7 @@ fn main() { .header("git2/sys/mempack.h") .header("git2/sys/repository.h") .header("git2/sys/cred.h") + .header("git2/sys/email.h") .header("git2/cred_helpers.h") .type_name(|s, _, _| s.to_string()); cfg.field_name(|_, f| match f { diff --git a/tests/add_extensions.rs b/tests/add_extensions.rs index f3e2c42ae3..d49c33cf79 100644 --- a/tests/add_extensions.rs +++ b/tests/add_extensions.rs @@ -10,14 +10,21 @@ fn test_add_extensions() -> Result<(), Error> { } let extensions = unsafe { get_extensions() }?; + let extensions: Vec<_> = extensions.iter().collect(); - assert_eq!(extensions.len(), 4); - assert_eq!(extensions.get(0), Some("custom")); - assert_eq!(extensions.get(1), Some("noop")); - // The objectformat extension was added in 1.6 - assert_eq!(extensions.get(2), Some("objectformat")); - // The worktreeconfig extension was added in 1.8 - assert_eq!(extensions.get(3), Some("worktreeconfig")); + assert_eq!( + extensions, + [ + Some("custom"), + Some("noop"), + // The objectformat extension was added in 1.6 + Some("objectformat"), + // The preciousobjects extension was added in 1.9 + Some("preciousobjects"), + // The worktreeconfig extension was added in 1.8 + Some("worktreeconfig") + ] + ); Ok(()) } diff --git a/tests/get_extensions.rs b/tests/get_extensions.rs index 3a9148f20b..2ac362d0ba 100644 --- a/tests/get_extensions.rs +++ b/tests/get_extensions.rs @@ -6,13 +6,20 @@ use git2::Error; #[test] fn test_get_extensions() -> Result<(), Error> { let extensions = unsafe { get_extensions() }?; + let extensions: Vec<_> = extensions.iter().collect(); - assert_eq!(extensions.len(), 3); - assert_eq!(extensions.get(0), Some("noop")); - // The objectformat extension was added in 1.6 - assert_eq!(extensions.get(1), Some("objectformat")); - // The worktreeconfig extension was added in 1.8 - assert_eq!(extensions.get(2), Some("worktreeconfig")); + assert_eq!( + extensions, + [ + Some("noop"), + // The objectformat extension was added in 1.6 + Some("objectformat"), + // The preciousobjects extension was added in 1.9 + Some("preciousobjects"), + // The worktreeconfig extension was added in 1.8 + Some("worktreeconfig") + ] + ); Ok(()) } diff --git a/tests/remove_extensions.rs b/tests/remove_extensions.rs index 5384daea5c..3e54b427b7 100644 --- a/tests/remove_extensions.rs +++ b/tests/remove_extensions.rs @@ -11,16 +11,16 @@ fn test_remove_extensions() -> Result<(), Error> { "!ignore", "!noop", "!objectformat", + "!preciousobjects", "!worktreeconfig", "other", ])?; } let extensions = unsafe { get_extensions() }?; + let extensions: Vec<_> = extensions.iter().collect(); - assert_eq!(extensions.len(), 2); - assert_eq!(extensions.get(0), Some("custom")); - assert_eq!(extensions.get(1), Some("other")); + assert_eq!(extensions, [Some("custom"), Some("other")]); Ok(()) } From e0d7dae804a93d2782733d5817b06449163bc10c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 4 Jan 2025 14:26:32 -0800 Subject: [PATCH 799/860] Simplify some of the tree_walk changes * I'm pretty sure the fn pointer doesn't need to have `*const`. * No need to move `Convert` around, can just use `as` for an enum (can maybe just remove this impl?). * Verify the actual error in the test. --- libgit2-sys/lib.rs | 2 +- src/call.rs | 11 ----------- src/tree.rs | 19 +++++++++++++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 54d384afc9..2cc53bf92d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -742,7 +742,7 @@ git_enum! { } pub type git_treewalk_cb = - *const extern "C" fn(*const c_char, *const git_tree_entry, *mut c_void) -> c_int; + extern "C" fn(*const c_char, *const git_tree_entry, *mut c_void) -> c_int; pub type git_treebuilder_filter_cb = Option c_int>; diff --git a/src/call.rs b/src/call.rs index 57aaa26dbd..a18f05da91 100644 --- a/src/call.rs +++ b/src/call.rs @@ -116,17 +116,6 @@ mod impls { } } - impl Convert for crate::TreeWalkMode { - #[cfg(target_env = "msvc")] - fn convert(&self) -> raw::git_treewalk_mode { - *self as i32 - } - #[cfg(not(target_env = "msvc"))] - fn convert(&self) -> raw::git_treewalk_mode { - *self as u32 - } - } - impl Convert for Direction { fn convert(&self) -> raw::git_direction { match *self { diff --git a/src/tree.rs b/src/tree.rs index 376ca9aa2d..e683257436 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -61,6 +61,17 @@ impl Into for TreeWalkResult { } } +impl Into for TreeWalkMode { + #[cfg(target_env = "msvc")] + fn into(self) -> raw::git_treewalk_mode { + self as i32 + } + #[cfg(not(target_env = "msvc"))] + fn into(self) -> raw::git_treewalk_mode { + self as u32 + } +} + impl<'repo> Tree<'repo> { /// Get the id (SHA1) of a repository object pub fn id(&self) -> Oid { @@ -118,8 +129,8 @@ impl<'repo> Tree<'repo> { }; try_call!(raw::git_tree_walk( self.raw(), - mode, - treewalk_cb:: as raw::git_treewalk_cb, + mode as raw::git_treewalk_mode, + treewalk_cb::, &mut data as *mut _ as *mut c_void )); Ok(()) @@ -600,7 +611,7 @@ mod tests { let target = head.target().unwrap(); let commit = repo.find_commit(target).unwrap(); let tree = repo.find_tree(commit.tree_id()).unwrap(); - - assert!(tree.walk(TreeWalkMode::PreOrder, |_, _| { -1 }).is_err()); + let e = tree.walk(TreeWalkMode::PreOrder, |_, _| -1).unwrap_err(); + assert_eq!(e.class(), crate::ErrorClass::Callback); } } From 8ce89e2a3a511e2f0eb199fbfde5b1531ef50459 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 4 Jan 2025 15:54:40 -0800 Subject: [PATCH 800/860] Squelch the warning about libgit2_vendored check-cfg --- libgit2-sys/build.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 57686ad5cf..77cd4eac64 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -22,6 +22,12 @@ fn try_system_libgit2() -> Result { } fn main() { + println!( + "cargo:rustc-check-cfg=cfg(\ + libgit2_vendored,\ + )" + ); + let https = env::var("CARGO_FEATURE_HTTPS").is_ok(); let ssh = env::var("CARGO_FEATURE_SSH").is_ok(); let vendored = env::var("CARGO_FEATURE_VENDORED").is_ok(); From f538a995ef6175209f8dae2a2275fd1a2bcfb2ac Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 4 Jan 2025 15:56:31 -0800 Subject: [PATCH 801/860] Add a Cargo.lock --- .gitignore | 1 - Cargo.lock | 1254 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1254 insertions(+), 1 deletion(-) create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore index 2a729c83fa..ad91b1e09a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ target -Cargo.lock src/main.rs diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000..a474890208 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1254 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" +dependencies = [ + "memchr 0.1.11", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "cc" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "civet" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9eff374cee04626041189bff6944fc204242250fe1c03c4feac5202fe6cc3fd" +dependencies = [ + "civet-sys", + "conduit", + "libc", + "semver 0.5.1", +] + +[[package]] +name = "civet-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876910de2615a24211fee8b88e62e2d5f81183ef1af2d827df4471c20319c4a2" +dependencies = [ + "cc", +] + +[[package]] +name = "clap" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "cmake" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" +dependencies = [ + "cc", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "conduit" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db0caa30f78c207dc14c071b62512253ece5c4459897815682786aff1028bc82" +dependencies = [ + "semver 0.5.1", +] + +[[package]] +name = "conduit-git-http-backend" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "027a1900afd70becd52b5061afc85a24de6af0d9199f39d4e1af8b7ac55fbe6e" +dependencies = [ + "conduit", + "flate2", +] + +[[package]] +name = "ctest2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9176b0b37841111e734e749155ab95669bdfcbd5ac3a971f7afb1a217857b625" +dependencies = [ + "cc", + "garando_syntax", + "rustc_version", +] + +[[package]] +name = "curl" +version = "0.4.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9fb4d13a1be2b58f14d60adba57c9834b78c62fd86c3e76a148f732686e9265" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "curl-sys" +version = "0.4.78+curl-8.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eec768341c5c7789611ae51cf6c459099f22e64a5d5d0ce4892434e33821eaf" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "windows-sys 0.52.0", +] + +[[package]] +name = "dirs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +dependencies = [ + "cfg-if 0.1.10", + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi 0.3.9", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "flate2" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" +dependencies = [ + "libc", + "miniz-sys", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "garando_errors" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18495ec4aced5922809efe4d2862918ff0e8d75e122bde57bba9bae45965256a" +dependencies = [ + "garando_pos", + "libc", + "serde", + "term", + "unicode-xid", +] + +[[package]] +name = "garando_pos" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9386fc75dca486daefbbf5a8d2ea6f379237f95c9b982776159cd66f220aaf" +dependencies = [ + "serde", +] + +[[package]] +name = "garando_syntax" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8a383861d12fc78c251bbcb1ec252dd8338714ce02ab0cc393cfd02f40d32b" +dependencies = [ + "bitflags 1.3.2", + "garando_errors", + "garando_pos", + "log", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "git2" +version = "0.20.0" +dependencies = [ + "bitflags 2.6.0", + "clap", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "tempfile", + "time", + "url", +] + +[[package]] +name = "git2-curl" +version = "0.21.0" +dependencies = [ + "civet", + "conduit", + "conduit-git-http-backend", + "curl", + "git2", + "log", + "tempfile", + "url", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "lazy_static" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libgit2-sys" +version = "0.18.0+1.9.0" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + +[[package]] +name = "libssh2-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +dependencies = [ + "cc", + "cmake", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz-sys" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-src" +version = "300.4.1+3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" +dependencies = [ + "aho-corasick", + "memchr 0.1.11", + "regex-syntax", + "thread_local", + "utf8-ranges", +] + +[[package]] +name = "regex-syntax" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.24", +] + +[[package]] +name = "rustix" +version = "0.38.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "semver" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae2ff60ecdb19c255841c066cbfa5f8c2a4ada1eb3ae47c77ab6667128da71f5" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + +[[package]] +name = "semver-parser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8fff3c9c5a54636ab95acd8c1349926e04cb1eb8cd70b5adced8a1d1f703a67" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.134" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +dependencies = [ + "itoa", + "memchr 2.7.4", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "systest" +version = "0.1.0" +dependencies = [ + "ctest2", + "libc", + "libgit2-sys", +] + +[[package]] +name = "tempfile" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" +dependencies = [ + "cfg-if 1.0.0", + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "term" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" +dependencies = [ + "dirs", + "winapi 0.3.9", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread-id" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" +dependencies = [ + "kernel32-sys", + "libc", +] + +[[package]] +name = "thread_local" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" +dependencies = [ + "thread-id", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8-ranges" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] From a4bd932a19a625ee69212c77994c2290d650a7c2 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 4 Jan 2025 16:28:27 -0800 Subject: [PATCH 802/860] Update the `time` dev-dependency --- Cargo.lock | 59 +++++++++++++++++++++++++++++++++++++++---------- Cargo.toml | 2 +- examples/log.rs | 21 ++++++------------ 3 files changed, 55 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a474890208..e0a14ba89b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,6 +231,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "dirs" version = "2.0.2" @@ -343,7 +352,7 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -656,6 +665,12 @@ dependencies = [ "libc", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "once_cell" version = "1.20.2" @@ -702,6 +717,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "proc-macro2" version = "1.0.92" @@ -974,13 +995,33 @@ dependencies = [ [[package]] name = "time" -version = "0.1.45" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", ] [[package]] @@ -1046,12 +1087,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 4a55492c50..54708542d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ openssl-probe = { version = "0.1", optional = true } [dev-dependencies] clap = { version = "4.4.13", features = ["derive"] } -time = "0.1.39" +time = { version = "0.3.37", features = ["formatting"] } tempfile = "3.1.0" [features] diff --git a/examples/log.rs b/examples/log.rs index 8e459cc6f3..5f6fe0f210 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -253,22 +253,15 @@ fn print_commit(commit: &Commit) { } fn print_time(time: &Time, prefix: &str) { - let (offset, sign) = match time.offset_minutes() { - n if n < 0 => (-n, '-'), - n => (n, '+'), - }; + let offset = time.offset_minutes(); let (hours, minutes) = (offset / 60, offset % 60); - let ts = time::Timespec::new(time.seconds() + (time.offset_minutes() as i64) * 60, 0); - let time = time::at(ts); + let dt = time::OffsetDateTime::from_unix_timestamp(time.seconds()).unwrap(); + let dto = dt.to_offset(time::UtcOffset::from_hms(hours as i8, minutes as i8, 0).unwrap()); + let format = time::format_description::parse("[weekday repr:short] [month repr:short] [day padding:space] [hour]:[minute]:[second] [year] [offset_hour sign:mandatory][offset_minute]") + .unwrap(); + let time_str = dto.format(&format).unwrap(); - println!( - "{}{} {}{:02}{:02}", - prefix, - time.strftime("%a %b %e %T %Y").unwrap(), - sign, - hours, - minutes - ); + println!("{}{}", prefix, time_str); } fn match_with_parent( From e46a1f956e2223db21e36d40c03208bfc38d60c4 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 4 Jan 2025 16:26:15 -0800 Subject: [PATCH 803/860] Check that Cargo.lock is not outdated in CI --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 97ba7a8d47..19309bcd79 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,6 +37,8 @@ jobs: - run: cargo test - run: cargo run -p systest - run: cargo test -p git2-curl + - name: Verify Cargo.lock is up-to-date + run: cargo update -p git2 --locked rustfmt: name: Rustfmt From 7173e500bebc24fef3a8986c77fd3d26ea0b237c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 4 Jan 2025 16:36:30 -0800 Subject: [PATCH 804/860] Add release notes for 1.9 changes --- CHANGELOG.md | 38 ++++++++++++++++++++++++++++++++++++++ git2-curl/CHANGELOG.md | 5 +++++ libgit2-sys/CHANGELOG.md | 17 +++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f76c3ba150..c9e4089928 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,43 @@ # Changelog +## 0.20.0 - 2025-01-04 +[0.19.0...0.20.0](https://github.com/rust-lang/git2-rs/compare/git2-0.19.0...git2-0.20.0) + +### Added + +- `Debug` is now implemented for `transport::Service` + [#1074](https://github.com/rust-lang/git2-rs/pull/1074) +- Added `Repository::commondir` + [#1079](https://github.com/rust-lang/git2-rs/pull/1079) +- Added `Repository::merge_base_octopus` + [#1088](https://github.com/rust-lang/git2-rs/pull/1088) +- Restored impls for `PartialOrd`, `Ord`, and `Hash` for bitflags types that were inadvertently removed in a prior release. + [#1096](https://github.com/rust-lang/git2-rs/pull/1096) +- Added `CheckoutBuilder::disable_pathspec_match` + [#1107](https://github.com/rust-lang/git2-rs/pull/1107) +- Added `PackBuilder::write` + [#1110](https://github.com/rust-lang/git2-rs/pull/1110) + +### Changed + +- ❗ Updated to libgit2 [1.9.0](https://github.com/libgit2/libgit2/releases/tag/v1.9.0) + [#1111](https://github.com/rust-lang/git2-rs/pull/1111) +- ❗ Removed the `ssh_key_from_memory` Cargo feature, it was unused. + [#1087](https://github.com/rust-lang/git2-rs/pull/1087) +- ❗ Errors from `Tree::walk` are now correctly reported to the caller. + [#1098](https://github.com/rust-lang/git2-rs/pull/1098) +- ❗ The `trace_set` callback now takes a `&[u8]` instead of a `&str`. + [#1071](https://github.com/rust-lang/git2-rs/pull/1071) +- ❗ `Error::last_error` now returns `Error` instead of `Option`. + [#1072](https://github.com/rust-lang/git2-rs/pull/1072) + +### Fixed + +- Fixed `OdbReader::read` return value. + [#1061](https://github.com/rust-lang/git2-rs/pull/1061) +- When a credential helper executes a shell command, don't pop open a console window on Windows. + [#1075](https://github.com/rust-lang/git2-rs/pull/1075) + ## 0.19.0 - 2024-06-13 [0.18.3...0.19.0](https://github.com/rust-lang/git2-rs/compare/git2-0.18.3...git2-0.19.0) diff --git a/git2-curl/CHANGELOG.md b/git2-curl/CHANGELOG.md index 1d51c646f7..a2eb29eef2 100644 --- a/git2-curl/CHANGELOG.md +++ b/git2-curl/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.21.0 - 2025-01-04 +[0.20.0...0.21.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.20.0...git2-curl-0.21.0) + +- Updated to [git2 0.20.0](../CHANGELOG.md#0200---2025-01-04) + ## 0.20.0 - 2024-06-13 [0.19.0...0.20.0](https://github.com/rust-lang/git2-rs/compare/git2-curl-0.19.0...git2-curl-0.20.0) diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index 02f82b00d7..cb4dc53cb5 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## 0.18.0+1.9.0 - 2025-01-04 +[0.16.2...0.17.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.17.0+1.8.1...libgit2-sys-0.18.0+1.9.0) + +### Added + +- Added bindings for `git_repository_commondir` + [#1079](https://github.com/rust-lang/git2-rs/pull/1079) +- Added bindings for `git_merge_base_octopus` + [#1088](https://github.com/rust-lang/git2-rs/pull/1088) + +### Changed + +- ❗ Updated to libgit2 [1.9.0](https://github.com/libgit2/libgit2/releases/tag/v1.9.0) + [#1111](https://github.com/rust-lang/git2-rs/pull/1111) +- ❗ Removed the `ssh_key_from_memory` Cargo feature, it was unused. + [#1087](https://github.com/rust-lang/git2-rs/pull/1087) + ## 0.17.0+1.8.1 - 2024-06-13 [0.16.2...0.17.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.16.2+1.7.2...libgit2-sys-0.17.0+1.8.1) From 8c1865843664b5c7e835d794364533a3c3c5d3ab Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 20 Jan 2025 08:21:47 -0800 Subject: [PATCH 805/860] Add triagebot --- triagebot.toml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 triagebot.toml diff --git a/triagebot.toml b/triagebot.toml new file mode 100644 index 0000000000..253fdd0bcd --- /dev/null +++ b/triagebot.toml @@ -0,0 +1,26 @@ +[relabel] +allow-unauthenticated = [ + "*", +] + +[assign] + +[shortcut] + +[transfer] + +[merge-conflicts] +remove = [] +add = ["S-waiting-on-author"] +unless = ["S-blocked", "S-waiting-on-review"] + +[autolabel."S-waiting-on-review"] +new_pr = true + +[review-submitted] +reviewed_label = "S-waiting-on-author" +review_labels = ["S-waiting-on-review"] + +[review-requested] +remove_labels = ["S-waiting-on-author"] +add_labels = ["S-waiting-on-review"] From f0a296cdc285e987947c26708697456faf4d824f Mon Sep 17 00:00:00 2001 From: qaqland Date: Mon, 20 Jan 2025 02:30:37 +0800 Subject: [PATCH 806/860] Add binding for GIT_OPT_SET_CACHE_OBJECT_LIMIT --- src/opts.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/opts.rs b/src/opts.rs index ab63661023..af5bb0cf9f 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -5,7 +5,7 @@ use std::ptr; use crate::string_array::StringArray; use crate::util::Binding; -use crate::{raw, Buf, ConfigLevel, Error, IntoCString}; +use crate::{raw, Buf, ConfigLevel, Error, IntoCString, ObjectType}; /// Set the search path for a level of config data. The search path applied to /// shared attributes and ignore files, too. @@ -89,6 +89,28 @@ pub fn enable_caching(enabled: bool) { debug_assert!(error >= 0); } +/// Set the maximum data size for the given type of object to be considered +/// eligible for caching in memory. Setting to value to zero means that that +/// type of object will not be cached. Defaults to 0 for [`ObjectType::Blob`] +/// (i.e. won't cache blobs) and 4k for [`ObjectType::Commit`], +/// [`ObjectType::Tree`], and [`ObjectType::Tag`]. +/// +/// `kind` must be one of [`ObjectType::Blob`], [`ObjectType::Commit`], +/// [`ObjectType::Tree`], and [`ObjectType::Tag`]. +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn set_cache_object_limit(kind: ObjectType, size: libc::size_t) -> Result<(), Error> { + crate::init(); + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_CACHE_OBJECT_LIMIT as libc::c_int, + kind as libc::c_int, + size + )); + Ok(()) +} + /// Controls whether or not libgit2 will verify when writing an object that all /// objects it references are valid. Enabled by default, but disabling this can /// significantly improve performance, at the cost of potentially allowing the From f0847fc4eef266ac2bf42efee313a30014b1fff0 Mon Sep 17 00:00:00 2001 From: Divine <48183131+divine@users.noreply.github.com> Date: Wed, 22 Jan 2025 11:13:47 +0000 Subject: [PATCH 807/860] fix: prevent crash when repository url is empty --- src/remote.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remote.rs b/src/remote.rs index 13c275ae2e..9e15b351dc 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -147,7 +147,7 @@ impl<'repo> Remote<'repo> { /// Get the remote's URL as a byte array. pub fn url_bytes(&self) -> &[u8] { - unsafe { crate::opt_bytes(self, raw::git_remote_url(https://github.com/&*self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_remote_url(https://github.com/&*self.raw)).unwrap_or(&[]) } } /// Get the remote's pushurl. From 09ad565719f9d2eb48d3195f4d9679980da13380 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Fri, 24 Jan 2025 23:02:32 -0500 Subject: [PATCH 808/860] Remove panic wrapper in tracing callback. --- src/tracing.rs | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/tracing.rs b/src/tracing.rs index 9872571dd3..8ca176ffee 100644 --- a/src/tracing.rs +++ b/src/tracing.rs @@ -112,17 +112,32 @@ extern "C" fn tracing_cb_c(level: raw::git_trace_level_t, msg: *const c_char) { // Convert from a CStr to &[u8] to pass to the rust code callback. let msg: &[u8] = CStr::to_bytes(msg); - // Do the remaining part of this function in a panic wrapper, to catch any panics it produces. - panic::wrap(|| { - // Convert the raw trace level into a type we can pass to the rust callback fn. - // - // SAFETY: Currently the implementation of this function (above) may panic, but is only marked as unsafe to match - // the trait definition, thus we can consider this call safe. - let level: TraceLevel = unsafe { Binding::from_raw(level) }; - - // Call the user-supplied callback (which may panic). - (cb)(level, msg); - }); + // Do not bother with wrapping any of the following calls in `panic::wrap`: + // + // The previous implementation used `panic::wrap` here but never called `panic::check` to determine if the + // trace callback had panicked, much less what caused it. + // + // This had the potential to lead to lost errors/unwinds, confusing to debugging situations, and potential issues + // catching panics in other parts of the `git2-rs` codebase. + // + // Instead, we simply call the next two lines, both of which may panic, directly. We can rely on the + // `extern "C"` semantics to appropriately catch the panics generated here and abort the process: + // + // Per : + // > Rust functions that are expected to be called from foreign code that does not support + // > unwinding (such as C compiled with -fno-exceptions) should be defined using extern "C", which ensures + // > that if the Rust code panics, it is automatically caught and the process is aborted. If this is the desired + // > behavior, it is not necessary to use catch_unwind explicitly. This function should instead be used when + // > more graceful error-handling is needed. + + // Convert the raw trace level into a type we can pass to the rust callback fn. + // + // SAFETY: Currently the implementation of this function (above) may panic, but is only marked as unsafe to match + // the trait definition, thus we can consider this call safe. + let level: TraceLevel = unsafe { Binding::from_raw(level) }; + + // Call the user-supplied callback (which may panic). + (cb)(level, msg); } #[cfg(test)] From c54f4485d1ab39afac0f4b4b10a8bb7da32e9ad2 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Fri, 24 Jan 2025 23:08:01 -0500 Subject: [PATCH 809/860] nit: remove unused import --- src/tracing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracing.rs b/src/tracing.rs index 8ca176ffee..038ccd0438 100644 --- a/src/tracing.rs +++ b/src/tracing.rs @@ -5,7 +5,7 @@ use std::{ use libc::{c_char, c_int}; -use crate::{panic, raw, util::Binding, Error}; +use crate::{raw, util::Binding, Error}; /// Available tracing levels. When tracing is set to a particular level, /// callers will be provided tracing at the given level and all lower levels. From 5e09a91b96e33f53a9ac6fa1787eba55cc240560 Mon Sep 17 00:00:00 2001 From: Finn Evers Date: Tue, 4 Feb 2025 17:44:59 +0100 Subject: [PATCH 810/860] docs: Update link to libgit2 homepage --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 01c9a93517..fd2db63432 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ //! to manage git repositories. The library itself is a work in progress and is //! likely lacking some bindings here and there, so be warned. //! -//! [1]: https://libgit2.github.com/ +//! [1]: https://libgit2.org/ //! //! The git2-rs library strives to be as close to libgit2 as possible, but also //! strives to make using libgit2 as safe as possible. All resource management From 09bb3a723d0d09c2943c48ed571f38830d4002b3 Mon Sep 17 00:00:00 2001 From: xtex Date: Thu, 6 Feb 2025 17:45:44 +0800 Subject: [PATCH 811/860] docs: Document that pushurl_bytes returns null if no push url is set --- src/remote.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/remote.rs b/src/remote.rs index 9e15b351dc..0c13a53fcf 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -152,12 +152,14 @@ impl<'repo> Remote<'repo> { /// Get the remote's pushurl. /// - /// Returns `None` if the pushurl is not valid utf-8 + /// Returns `None` if the pushurl is not valid utf-8 or no special url for pushing is set. pub fn pushurl(https://github.com/&self) -> Option<&str> { self.pushurl_bytes().and_then(|s| str::from_utf8(s).ok()) } /// Get the remote's pushurl as a byte array. + /// + /// Returns `None` if no special url for pushing is set. pub fn pushurl_bytes(&self) -> Option<&[u8]> { unsafe { crate::opt_bytes(self, raw::git_remote_pushurl(https://github.com/&*self.raw)) } } From c6dd1ac1a2983825a78f38308a26998f30a57049 Mon Sep 17 00:00:00 2001 From: Eric Park Date: Fri, 21 Feb 2025 18:47:13 -0500 Subject: [PATCH 812/860] Update url to 2.5.4 This also resolves the security warning that comes from idna 0.5.0 being vulnerable. --- Cargo.toml | 2 +- git2-curl/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 54708542d7..721286c60e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ categories = ["api-bindings"] edition = "2018" [dependencies] -url = "2.0" +url = "2.5.4" bitflags = "2.1.0" libc = "0.2" log = "0.4.8" diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 11dae7f8a4..fad60e2755 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -14,7 +14,7 @@ edition = "2018" [dependencies] curl = "0.4.33" -url = "2.0" +url = "2.5.4" log = "0.4" git2 = { path = "..", version = "0.20", default-features = false } From fb614e00ab933b34eeaf9a302dd68cbc53394964 Mon Sep 17 00:00:00 2001 From: vlad-anger Date: Thu, 27 Feb 2025 22:32:57 -0300 Subject: [PATCH 813/860] expose libgit2 `git_branch_upstream_merge` --- libgit2-sys/lib.rs | 5 +++++ src/repo.rs | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index bf0f107755..06b75cbc4d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -3018,6 +3018,11 @@ extern "C" { repo: *mut git_repository, refname: *const c_char, ) -> c_int; + pub fn git_branch_upstream_merge( + out: *mut git_buf, + repo: *mut git_repository, + refname: *const c_char, + ) -> c_int; // index pub fn git_index_version(index: *mut git_index) -> c_uint; diff --git a/src/repo.rs b/src/repo.rs index 074955f623..dd8ae50d0f 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -3136,6 +3136,23 @@ impl Repository { } } + /// Retrieve the upstream merge of a local branch, + /// configured in "branch.*.merge" + /// + /// `refname` must be in the form `refs/heads/{branch_name}` + pub fn branch_upstream_merge(&self, refname: &str) -> Result { + let refname = CString::new(refname)?; + unsafe { + let buf = Buf::new(); + try_call!(raw::git_branch_upstream_merge( + buf.raw(), + self.raw, + refname + )); + Ok(buf) + } + } + /// Apply a Diff to the given repo, making changes directly in the working directory, the index, or both. pub fn apply( &self, From 84e39e49d9ca2f7a65f58a94aec60f5568640ff4 Mon Sep 17 00:00:00 2001 From: vlad-anger Date: Thu, 27 Feb 2025 22:40:35 -0300 Subject: [PATCH 814/860] fix formatting --- src/repo.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index dd8ae50d0f..19f8c1f511 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -3138,17 +3138,13 @@ impl Repository { /// Retrieve the upstream merge of a local branch, /// configured in "branch.*.merge" - /// + /// /// `refname` must be in the form `refs/heads/{branch_name}` pub fn branch_upstream_merge(&self, refname: &str) -> Result { let refname = CString::new(refname)?; unsafe { let buf = Buf::new(); - try_call!(raw::git_branch_upstream_merge( - buf.raw(), - self.raw, - refname - )); + try_call!(raw::git_branch_upstream_merge(buf.raw(), self.raw, refname)); Ok(buf) } } From 0088ea0db8c9b7e32993cdd2f9faf3a781732f48 Mon Sep 17 00:00:00 2001 From: yuanyan3060 <1846865993@qq.com> Date: Tue, 4 Mar 2025 17:03:35 +0800 Subject: [PATCH 815/860] Added git_index_conflict_get --- src/index.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/index.rs b/src/index.rs index 0291d3cb95..712c7f887b 100644 --- a/src/index.rs +++ b/src/index.rs @@ -412,6 +412,39 @@ impl Index { unsafe { raw::git_index_has_conflicts(self.raw) == 1 } } + /// Get the index entries that represent a conflict of a single file. + pub fn conflict_get(&self, path: &Path) -> Result { + let path = path_to_repo_path(path)?; + let mut ancestor = ptr::null(); + let mut our = ptr::null(); + let mut their = ptr::null(); + + unsafe { + try_call!(raw::git_index_conflict_get( + &mut ancestor, + &mut our, + &mut their, + self.raw, + path + )); + + Ok(IndexConflict { + ancestor: match ancestor.is_null() { + false => Some(IndexEntry::from_raw(*ancestor)), + true => None, + }, + our: match our.is_null() { + false => Some(IndexEntry::from_raw(*our)), + true => None, + }, + their: match their.is_null() { + false => Some(IndexEntry::from_raw(*their)), + true => None, + }, + }) + } + } + /// Get the full path to the index file on disk. /// /// Returns `None` if this is an in-memory index. From adbbbf46f2711bd07eb9760b9cdd4c5da73e07e7 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Mon, 10 Mar 2025 10:39:15 +0000 Subject: [PATCH 816/860] Add test case for credential.helper containing slashes --- src/cred.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cred.rs b/src/cred.rs index b1f15cab13..b2fa8a64ce 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -578,13 +578,13 @@ echo username=c return; } // shell scripts don't work on Windows let td = TempDir::new().unwrap(); - let path = td.path().join("git-credential-script"); + let path = td.path().join("git-credential-some-script"); File::create(&path) .unwrap() .write( br"\ #!/bin/sh -echo username=c +echo username=$1 ", ) .unwrap(); @@ -596,14 +596,14 @@ echo username=c env::set_var("PATH", &env::join_paths(paths).unwrap()); let cfg = test_cfg! { - "credential.https://example.com.helper" => "script", + "credential.https://example.com.helper" => "some-script \"value/with\\slashes\"", "credential.helper" => "!f() { echo username=a; echo password=b; }; f" }; let (u, p) = CredentialHelper::new("https://example.com/foo/bar") .config(&cfg) .execute() .unwrap(); - assert_eq!(u, "c"); + assert_eq!(u, "value/with\\slashes"); assert_eq!(p, "b"); } From c776e8d688ff2772f80a2dd440a986896a6c29b4 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Wed, 5 Mar 2025 11:33:33 +0100 Subject: [PATCH 817/860] Fix CredentialHelper::add_command Fixes https://github.com/rust-lang/git2-rs/issues/1136 --- src/cred.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cred.rs b/src/cred.rs index b2fa8a64ce..3def56ab6e 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -299,7 +299,7 @@ impl CredentialHelper { if cmd.starts_with('!') { self.commands.push(cmd[1..].to_string()); - } else if cmd.contains("/") || cmd.contains("\\") { + } else if is_absolute_path(cmd) { self.commands.push(cmd.to_string()); } else { self.commands.push(format!("git credential-{}", cmd)); @@ -481,6 +481,12 @@ impl CredentialHelper { } } +fn is_absolute_path(path: &str) -> bool { + path.starts_with('/') + || path.starts_with('\\') + || cfg!(windows) && path.chars().nth(1).is_some_and(|x| x == ':') +} + #[cfg(test)] mod test { use std::env; From 4c92a5ce3993da56ca8a9ca497a7ccd460d24c05 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 12 Mar 2025 08:03:48 -0700 Subject: [PATCH 818/860] Fix lifetimes of outputs for Patch --- src/patch.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/patch.rs b/src/patch.rs index 67b84c0f0a..d44e87e925 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -125,7 +125,7 @@ impl<'buffers> Patch<'buffers> { } /// Get the DiffDelta associated with the Patch. - pub fn delta(&self) -> DiffDelta<'buffers> { + pub fn delta<'a>(&'a self) -> DiffDelta<'a> { unsafe { Binding::from_raw(raw::git_patch_get_delta(self.raw) as *mut _) } } @@ -151,7 +151,7 @@ impl<'buffers> Patch<'buffers> { } /// Get a DiffHunk and its total line count from the Patch. - pub fn hunk(&self, hunk_idx: usize) -> Result<(DiffHunk<'buffers>, usize), Error> { + pub fn hunk<'a>(&'a self, hunk_idx: usize) -> Result<(DiffHunk<'a>, usize), Error> { let mut ret = ptr::null(); let mut lines = 0; unsafe { @@ -168,11 +168,11 @@ impl<'buffers> Patch<'buffers> { } /// Get a DiffLine from a hunk of the Patch. - pub fn line_in_hunk( - &self, + pub fn line_in_hunk<'a>( + &'a self, hunk_idx: usize, line_of_hunk: usize, - ) -> Result, Error> { + ) -> Result, Error> { let mut ret = ptr::null(); unsafe { try_call!(raw::git_patch_get_line_in_hunk( From 892215d50911bf0a3986ad1d4b6e0a6092407f97 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 17 Mar 2025 11:25:49 -0700 Subject: [PATCH 819/860] Fix advapi32 linking on Windows --- libgit2-sys/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/libgit2-sys/build.rs b/libgit2-sys/build.rs index 77cd4eac64..7b5a374e9b 100644 --- a/libgit2-sys/build.rs +++ b/libgit2-sys/build.rs @@ -252,6 +252,7 @@ The build is now aborting. To disable, unset the variable or use `LIBGIT2_NO_VEN println!("cargo:rustc-link-lib=ole32"); println!("cargo:rustc-link-lib=crypt32"); println!("cargo:rustc-link-lib=secur32"); + println!("cargo:rustc-link-lib=advapi32"); } if target.contains("apple") { From c979b22771f9574b339092f0aa727c7e0ede3941 Mon Sep 17 00:00:00 2001 From: yuanyan3060 <1846865993@qq.com> Date: Tue, 4 Mar 2025 15:04:01 +0800 Subject: [PATCH 820/860] Added index_conflict_remove --- src/index.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/index.rs b/src/index.rs index 712c7f887b..5625ba91ac 100644 --- a/src/index.rs +++ b/src/index.rs @@ -518,6 +518,15 @@ impl Index { Ok(()) } + /// Removes the index entries that represent a conflict of a single file. + pub fn conflict_remove(&mut self, path: &Path) -> Result<(), Error> { + let path = path_to_repo_path(path)?; + unsafe { + try_call!(raw::git_index_conflict_remove(self.raw, path)); + } + Ok(()) + } + /// Remove all matching index entries. /// /// If you provide a callback function, it will be invoked on each matching From 2572c23144e5fa6b722ab0481d636b05c2de2774 Mon Sep 17 00:00:00 2001 From: Mike Jerred Date: Sun, 23 Jun 2024 18:03:41 +0100 Subject: [PATCH 821/860] feat(merge): add merge_file_from_index --- libgit2-sys/lib.rs | 42 ++++++++- src/lib.rs | 2 +- src/merge.rs | 224 ++++++++++++++++++++++++++++++++++++++++++++- src/repo.rs | 174 ++++++++++++++++++++++++++++++++++- 4 files changed, 435 insertions(+), 7 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 06b75cbc4d..e7bfefc1cb 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -4,7 +4,7 @@ // This is required to link libz when libssh2-sys is not included. extern crate libz_sys as libz; -use libc::{c_char, c_int, c_uchar, c_uint, c_void, size_t}; +use libc::{c_char, c_int, c_uchar, c_uint, c_ushort, c_void, size_t}; #[cfg(feature = "ssh")] use libssh2_sys as libssh2; use std::ffi::CStr; @@ -1361,6 +1361,32 @@ pub struct git_merge_options { pub file_flags: u32, } +#[repr(C)] +pub struct git_merge_file_options { + pub version: c_uint, + pub ancestor_label: *const c_char, + pub our_label: *const c_char, + pub their_label: *const c_char, + pub favor: git_merge_file_favor_t, + pub flags: u32, + pub marker_size: c_ushort, +} + +#[repr(C)] +#[derive(Copy)] +pub struct git_merge_file_result { + pub automergeable: c_uint, + pub path: *const c_char, + pub mode: c_uint, + pub ptr: *const c_char, + pub len: size_t, +} +impl Clone for git_merge_file_result { + fn clone(&self) -> git_merge_file_result { + *self + } +} + git_enum! { pub enum git_merge_flag_t { GIT_MERGE_FIND_RENAMES = 1 << 0, @@ -1390,6 +1416,8 @@ git_enum! { GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL = 1 << 5, GIT_MERGE_FILE_DIFF_PATIENCE = 1 << 6, GIT_MERGE_FILE_DIFF_MINIMAL = 1 << 7, + GIT_MERGE_FILE_STYLE_ZDIFF3 = 1 << 8, + GIT_MERGE_FILE_ACCEPT_CONFLICTS = 1 << 9, } } @@ -3395,6 +3423,7 @@ extern "C" { their_tree: *const git_tree, opts: *const git_merge_options, ) -> c_int; + pub fn git_merge_file_options_init(opts: *mut git_merge_file_options, version: c_uint) -> c_int; pub fn git_repository_state_cleanup(repo: *mut git_repository) -> c_int; // merge analysis @@ -3543,6 +3572,17 @@ extern "C" { input_array: *const git_oid, ) -> c_int; + pub fn git_merge_file_from_index( + out: *mut git_merge_file_result, + repo: *mut git_repository, + ancestor: *const git_index_entry, + ours: *const git_index_entry, + theirs: *const git_index_entry, + opts: *const git_merge_file_options, + ) -> c_int; + + pub fn git_merge_file_result_free(file_result: *mut git_merge_file_result); + // pathspec pub fn git_pathspec_free(ps: *mut git_pathspec); pub fn git_pathspec_match_diff( diff --git a/src/lib.rs b/src/lib.rs index fd2db63432..25bc9872e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,7 +101,7 @@ pub use crate::index::{ pub use crate::indexer::{Indexer, IndexerProgress, Progress}; pub use crate::mailmap::Mailmap; pub use crate::mempack::Mempack; -pub use crate::merge::{AnnotatedCommit, MergeOptions}; +pub use crate::merge::{AnnotatedCommit, MergeOptions, MergeFileOptions, MergeFileResult}; pub use crate::message::{ message_prettify, message_trailers_bytes, message_trailers_strs, MessageTrailersBytes, MessageTrailersBytesIterator, MessageTrailersStrs, MessageTrailersStrsIterator, diff --git a/src/merge.rs b/src/merge.rs index 6bd30c10d1..1892638437 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -1,11 +1,14 @@ -use libc::c_uint; +use libc::{c_uint, c_ushort}; +use std::ffi::CString; use std::marker; use std::mem; +use std::ptr; use std::str; use crate::call::Convert; use crate::util::Binding; use crate::{raw, Commit, FileFavor, Oid}; +use crate::IntoCString; /// A structure to represent an annotated commit, the input to merge and rebase. /// @@ -22,6 +25,20 @@ pub struct MergeOptions { raw: raw::git_merge_options, } +/// Options for merging a file. +pub struct MergeFileOptions { + ancestor_label: Option, + our_label: Option, + their_label: Option, + raw: raw::git_merge_file_options, +} + +/// Information about file-level merging. +pub struct MergeFileResult<'repo> { + raw: raw::git_merge_file_result, + _marker: marker::PhantomData<&'repo str>, +} + impl<'repo> AnnotatedCommit<'repo> { /// Gets the commit ID that the given git_annotated_commit refers to pub fn id(&self) -> Oid { @@ -192,3 +209,208 @@ impl<'repo> Drop for AnnotatedCommit<'repo> { unsafe { raw::git_annotated_commit_free(self.raw) } } } + +impl Default for MergeFileOptions { + fn default() -> Self { + Self::new() + } +} + +impl MergeFileOptions { + /// Creates a default set of merge file options. + pub fn new() -> MergeFileOptions { + let mut opts = MergeFileOptions { + ancestor_label: None, + our_label: None, + their_label: None, + raw: unsafe { mem::zeroed() }, + }; + assert_eq!(unsafe { raw::git_merge_file_options_init(&mut opts.raw, 1) }, 0); + opts + } + + /// Label for the ancestor file side of the conflict which will be prepended + /// to labels in diff3-format merge files. + pub fn ancestor_label(&mut self, t: T) -> &mut MergeFileOptions { + self.ancestor_label = Some(t.into_c_string().unwrap()); + + self.raw.ancestor_label = self + .ancestor_label + .as_ref() + .map(|s| s.as_ptr()) + .unwrap_or(ptr::null()); + + self + } + + /// Label for our file side of the conflict which will be prepended to labels + /// in merge files. + pub fn our_label(&mut self, t: T) -> &mut MergeFileOptions { + self.our_label = Some(t.into_c_string().unwrap()); + + self.raw.our_label = self + .our_label + .as_ref() + .map(|s| s.as_ptr()) + .unwrap_or(ptr::null()); + + self + } + + /// Label for their file side of the conflict which will be prepended to labels + /// in merge files. + pub fn their_label(&mut self, t: T) -> &mut MergeFileOptions { + self.their_label = Some(t.into_c_string().unwrap()); + + self.raw.their_label = self + .their_label + .as_ref() + .map(|s| s.as_ptr()) + .unwrap_or(ptr::null()); + + self + } + + /// Specify a side to favor for resolving conflicts + pub fn favor(&mut self, favor: FileFavor) -> &mut MergeFileOptions { + self.raw.favor = favor.convert(); + self + } + + fn flag(&mut self, opt: u32, val: bool) -> &mut MergeFileOptions { + if val { + self.raw.flags |= opt; + } else { + self.raw.flags &= !opt; + } + self + } + + /// Create standard conflicted merge files + pub fn style_standard(&mut self, standard: bool) -> &mut MergeFileOptions { + self.flag(raw::GIT_MERGE_FILE_STYLE_MERGE as u32, standard) + } + + /// Create diff3-style file + pub fn style_diff3(&mut self, diff3: bool) -> &mut MergeFileOptions { + self.flag(raw::GIT_MERGE_FILE_STYLE_DIFF3 as u32, diff3) + } + + /// Condense non-alphanumeric regions for simplified diff file + pub fn simplify_alnum(&mut self, simplify: bool) -> &mut MergeFileOptions { + self.flag(raw::GIT_MERGE_FILE_SIMPLIFY_ALNUM as u32, simplify) + } + + /// Ignore all whitespace + pub fn ignore_whitespace(&mut self, ignore: bool) -> &mut MergeFileOptions { + self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE as u32, ignore) + } + + /// Ignore changes in amount of whitespace + pub fn ignore_whitespace_change(&mut self, ignore: bool) -> &mut MergeFileOptions { + self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE as u32, ignore) + } + + /// Ignore whitespace at end of line + pub fn ignore_whitespace_eol(&mut self, ignore: bool) -> &mut MergeFileOptions { + self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL as u32, ignore) + } + + /// Use the "patience diff" algorithm + pub fn patience(&mut self, patience: bool) -> &mut MergeFileOptions { + self.flag(raw::GIT_MERGE_FILE_DIFF_PATIENCE as u32, patience) + } + + /// Take extra time to find minimal diff + pub fn minimal(&mut self, minimal: bool) -> &mut MergeFileOptions { + self.flag(raw::GIT_MERGE_FILE_DIFF_MINIMAL as u32, minimal) + } + + /// Create zdiff3 ("zealous diff3")-style files + pub fn style_zdiff3(&mut self, zdiff3: bool) -> &mut MergeFileOptions { + self.flag(raw::GIT_MERGE_FILE_STYLE_ZDIFF3 as u32, zdiff3) + } + + /// Do not produce file conflicts when common regions have changed + pub fn accept_conflicts(&mut self, accept: bool) -> &mut MergeFileOptions { + self.flag(raw::GIT_MERGE_FILE_ACCEPT_CONFLICTS as u32, accept) + } + + /// The size of conflict markers (eg, "<<<<<<<"). Default is 7. + pub fn marker_size(&mut self, size: u16) -> &mut MergeFileOptions { + self.raw.marker_size = size as c_ushort; + self + } + + /// Acquire a pointer to the underlying raw options. + pub unsafe fn raw(&mut self) -> *const raw::git_merge_file_options { + &self.raw as *const _ + } +} + +impl<'repo> MergeFileResult<'repo> { + /// True if the output was automerged, false if the output contains + /// conflict markers. + pub fn is_automergeable(&self) -> bool { + self.raw.automergeable > 0 + } + + /// The path that the resultant merge file should use. + /// + /// returns `None` if a filename conflict would occur, + /// or if the path is not valid utf-8 + pub fn path(&self) -> Option<&str> { + self.path_bytes().and_then(|bytes| str::from_utf8(bytes).ok()) + } + + /// Gets the path as a byte slice. + pub fn path_bytes(&self) -> Option<&[u8]> { + unsafe { crate::opt_bytes(self, self.raw.path) } + } + + /// The mode that the resultant merge file should use. + pub fn mode(&self) -> u32 { + self.raw.mode as u32 + } + + /// The contents of the merge. + pub fn content(&self) -> &'repo [u8] { + unsafe { + std::slice::from_raw_parts( + self.raw.ptr as *const u8, + self.raw.len as usize, + ) + } + } +} + +impl<'repo> Binding for MergeFileResult<'repo> { + type Raw = raw::git_merge_file_result; + unsafe fn from_raw(raw: raw::git_merge_file_result) -> MergeFileResult<'repo> { + MergeFileResult { + raw, + _marker: marker::PhantomData, + } + } + fn raw(&self) -> raw::git_merge_file_result { + self.raw + } +} + +impl<'repo> Drop for MergeFileResult<'repo> { + fn drop(&mut self) { + unsafe { raw::git_merge_file_result_free(&mut self.raw) } + } +} + +impl<'repo> std::fmt::Display for MergeFileResult<'repo> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut ds = f.debug_struct("MergeFileResult"); + if let Some(path) = &self.path() { + ds.field("path", path); + } + ds.field("automergeable", &self.is_automergeable()); + ds.field("mode", &self.mode()); + ds.finish() + } +} diff --git a/src/repo.rs b/src/repo.rs index 19f8c1f511..169b931832 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -24,12 +24,12 @@ use crate::{ StashFlags, }; use crate::{ - AnnotatedCommit, MergeAnalysis, MergeOptions, MergePreference, SubmoduleIgnore, - SubmoduleStatus, SubmoduleUpdate, + AnnotatedCommit, MergeAnalysis, MergeOptions, MergeFileOptions, MergeFileResult, MergePreference, + SubmoduleIgnore, SubmoduleStatus, SubmoduleUpdate, }; use crate::{ApplyLocation, ApplyOptions, Rebase, RebaseOptions}; use crate::{Blame, BlameOptions, Reference, References, ResetType, Signature, Submodule}; -use crate::{Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, Oid, Tree}; +use crate::{Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, IndexEntry, Oid, Tree}; use crate::{Describe, IntoCString, Reflog, RepositoryInitMode, RevparseMode}; use crate::{DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder}; use crate::{Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag, Transaction}; @@ -2566,6 +2566,79 @@ impl Repository { } } + /// Merge two files as they exist in the index, using the given common ancestor + /// as the baseline. + pub fn merge_file_from_index( + &self, + ancestor: &IndexEntry, + ours: &IndexEntry, + theirs: &IndexEntry, + opts: Option<&mut MergeFileOptions>, + ) -> Result, Error> { + let create_raw_entry = |entry: &IndexEntry| -> Result { + let path = CString::new(&entry.path[..])?; + + // libgit2 encodes the length of the path in the lower bits of the + // `flags` entry, so mask those out and recalculate here to ensure we + // don't corrupt anything. + let mut flags = entry.flags & !raw::GIT_INDEX_ENTRY_NAMEMASK; + + if entry.path.len() < raw::GIT_INDEX_ENTRY_NAMEMASK as usize { + flags |= entry.path.len() as u16; + } else { + flags |= raw::GIT_INDEX_ENTRY_NAMEMASK; + } + + unsafe { + let raw = raw::git_index_entry { + dev: entry.dev, + ino: entry.ino, + mode: entry.mode, + uid: entry.uid, + gid: entry.gid, + file_size: entry.file_size, + id: *entry.id.raw(), + flags, + flags_extended: entry.flags_extended, + path: path.as_ptr(), + mtime: raw::git_index_time { + seconds: entry.mtime.seconds(), + nanoseconds: entry.mtime.nanoseconds(), + }, + ctime: raw::git_index_time { + seconds: entry.ctime.seconds(), + nanoseconds: entry.ctime.nanoseconds(), + }, + }; + + Ok(raw) + } + }; + + let mut ret = raw::git_merge_file_result { + automergeable: 0, + path: ptr::null_mut(), + mode: 0, + ptr: ptr::null_mut(), + len: 0, + }; + let ancestor = create_raw_entry(ancestor)?; + let ours = create_raw_entry(ours)?; + let theirs = create_raw_entry(theirs)?; + + unsafe { + try_call!(raw::git_merge_file_from_index( + &mut ret, + self.raw(), + &ancestor, + &ours, + &theirs, + opts.map(|o| o.raw()).unwrap_or(ptr::null()) + )); + Ok(Binding::from_raw(ret)) + } + } + /// Count the number of unique commits between two commit objects /// /// There is no need for branches containing the commits to have any @@ -3519,7 +3592,7 @@ impl RepositoryInitOptions { #[cfg(test)] mod tests { use crate::build::CheckoutBuilder; - use crate::CherrypickOptions; + use crate::{CherrypickOptions, MergeFileOptions}; use crate::{ ObjectType, Oid, Repository, ResetType, Signature, SubmoduleIgnore, SubmoduleUpdate, }; @@ -4025,6 +4098,99 @@ mod tests { assert_eq!(merge_bases.len(), 2); } + #[test] + fn smoke_merge_file_from_index() { + let (_td, repo) = crate::test::repo_init(); + + let head_commit = { + let head = t!(repo.head()).target().unwrap(); + t!(repo.find_commit(head)) + }; + + let file_path = Path::new("file"); + let author = t!(Signature::now("committer", "committer@email")); + + let base_commit = { + t!(fs::write(repo.workdir().unwrap().join(&file_path), "base")); + let mut index = t!(repo.index()); + t!(index.add_path(&file_path)); + let tree_id = t!(index.write_tree()); + let tree = t!(repo.find_tree(tree_id)); + + let commit_id = t!(repo.commit( + Some("HEAD"), + &author, + &author, + r"Add file with contents 'base'", + &tree, + &[&head_commit], + )); + t!(repo.find_commit(commit_id)) + }; + + let foo_commit = { + t!(fs::write(repo.workdir().unwrap().join(&file_path), "foo")); + let mut index = t!(repo.index()); + t!(index.add_path(&file_path)); + let tree_id = t!(index.write_tree()); + let tree = t!(repo.find_tree(tree_id)); + + let commit_id = t!(repo.commit( + Some("refs/heads/foo"), + &author, + &author, + r"Update file with contents 'foo'", + &tree, + &[&base_commit], + )); + t!(repo.find_commit(commit_id)) + }; + + let bar_commit = { + t!(fs::write(repo.workdir().unwrap().join(&file_path), "bar")); + let mut index = t!(repo.index()); + t!(index.add_path(&file_path)); + let tree_id = t!(index.write_tree()); + let tree = t!(repo.find_tree(tree_id)); + + let commit_id = t!(repo.commit( + Some("refs/heads/bar"), + &author, + &author, + r"Update file with contents 'bar'", + &tree, + &[&base_commit], + )); + t!(repo.find_commit(commit_id)) + }; + + let index = t!(repo.merge_commits(&foo_commit, &bar_commit, None)); + + let base = index.get_path(file_path, 1).unwrap(); + let ours = index.get_path(file_path, 2).unwrap(); + let theirs = index.get_path(file_path, 3).unwrap(); + + let mut opts = MergeFileOptions::new(); + opts.ancestor_label("ancestor"); + opts.our_label("ours"); + opts.their_label("theirs"); + opts.style_diff3(true); + let merge_file_result = repo.merge_file_from_index(&base, &ours, &theirs, Some(&mut opts)).unwrap(); + + assert!(!merge_file_result.is_automergeable()); + assert_eq!( + String::from_utf8_lossy(merge_file_result.content()).to_string(), +r"<<<<<<< ours +foo +||||||| ancestor +base +======= +bar +>>>>>>> theirs +", + ); + } + #[test] fn smoke_revparse_ext() { let (_td, repo) = graph_repo_init(); From e80d1ab0152207454ba4bf897d54f36cdc49c2ec Mon Sep 17 00:00:00 2001 From: Mike Jerred Date: Sun, 23 Jun 2024 18:35:04 +0100 Subject: [PATCH 822/860] style: fix code formatting --- libgit2-sys/lib.rs | 3 ++- src/lib.rs | 2 +- src/merge.rs | 17 ++++++++--------- src/repo.rs | 14 +++++++++----- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index e7bfefc1cb..50939f0226 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -3423,7 +3423,8 @@ extern "C" { their_tree: *const git_tree, opts: *const git_merge_options, ) -> c_int; - pub fn git_merge_file_options_init(opts: *mut git_merge_file_options, version: c_uint) -> c_int; + pub fn git_merge_file_options_init(opts: *mut git_merge_file_options, version: c_uint) + -> c_int; pub fn git_repository_state_cleanup(repo: *mut git_repository) -> c_int; // merge analysis diff --git a/src/lib.rs b/src/lib.rs index 25bc9872e8..4b26b8c023 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,7 +101,7 @@ pub use crate::index::{ pub use crate::indexer::{Indexer, IndexerProgress, Progress}; pub use crate::mailmap::Mailmap; pub use crate::mempack::Mempack; -pub use crate::merge::{AnnotatedCommit, MergeOptions, MergeFileOptions, MergeFileResult}; +pub use crate::merge::{AnnotatedCommit, MergeFileOptions, MergeFileResult, MergeOptions}; pub use crate::message::{ message_prettify, message_trailers_bytes, message_trailers_strs, MessageTrailersBytes, MessageTrailersBytesIterator, MessageTrailersStrs, MessageTrailersStrsIterator, diff --git a/src/merge.rs b/src/merge.rs index 1892638437..64880603fa 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -7,8 +7,8 @@ use std::str; use crate::call::Convert; use crate::util::Binding; -use crate::{raw, Commit, FileFavor, Oid}; use crate::IntoCString; +use crate::{raw, Commit, FileFavor, Oid}; /// A structure to represent an annotated commit, the input to merge and rebase. /// @@ -225,7 +225,10 @@ impl MergeFileOptions { their_label: None, raw: unsafe { mem::zeroed() }, }; - assert_eq!(unsafe { raw::git_merge_file_options_init(&mut opts.raw, 1) }, 0); + assert_eq!( + unsafe { raw::git_merge_file_options_init(&mut opts.raw, 1) }, + 0 + ); opts } @@ -360,7 +363,8 @@ impl<'repo> MergeFileResult<'repo> { /// returns `None` if a filename conflict would occur, /// or if the path is not valid utf-8 pub fn path(&self) -> Option<&str> { - self.path_bytes().and_then(|bytes| str::from_utf8(bytes).ok()) + self.path_bytes() + .and_then(|bytes| str::from_utf8(bytes).ok()) } /// Gets the path as a byte slice. @@ -375,12 +379,7 @@ impl<'repo> MergeFileResult<'repo> { /// The contents of the merge. pub fn content(&self) -> &'repo [u8] { - unsafe { - std::slice::from_raw_parts( - self.raw.ptr as *const u8, - self.raw.len as usize, - ) - } + unsafe { std::slice::from_raw_parts(self.raw.ptr as *const u8, self.raw.len as usize) } } } diff --git a/src/repo.rs b/src/repo.rs index 169b931832..a1a3285b44 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -24,12 +24,14 @@ use crate::{ StashFlags, }; use crate::{ - AnnotatedCommit, MergeAnalysis, MergeOptions, MergeFileOptions, MergeFileResult, MergePreference, - SubmoduleIgnore, SubmoduleStatus, SubmoduleUpdate, + AnnotatedCommit, MergeAnalysis, MergeFileOptions, MergeFileResult, MergeOptions, + MergePreference, SubmoduleIgnore, SubmoduleStatus, SubmoduleUpdate, }; use crate::{ApplyLocation, ApplyOptions, Rebase, RebaseOptions}; use crate::{Blame, BlameOptions, Reference, References, ResetType, Signature, Submodule}; -use crate::{Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, IndexEntry, Oid, Tree}; +use crate::{ + Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, IndexEntry, Oid, Tree, +}; use crate::{Describe, IntoCString, Reflog, RepositoryInitMode, RevparseMode}; use crate::{DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder}; use crate::{Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag, Transaction}; @@ -4175,12 +4177,14 @@ mod tests { opts.our_label("ours"); opts.their_label("theirs"); opts.style_diff3(true); - let merge_file_result = repo.merge_file_from_index(&base, &ours, &theirs, Some(&mut opts)).unwrap(); + let merge_file_result = repo + .merge_file_from_index(&base, &ours, &theirs, Some(&mut opts)) + .unwrap(); assert!(!merge_file_result.is_automergeable()); assert_eq!( String::from_utf8_lossy(merge_file_result.content()).to_string(), -r"<<<<<<< ours + r"<<<<<<< ours foo ||||||| ancestor base From 742c6305c31aa8bc3c3d627f64febd6efcb81448 Mon Sep 17 00:00:00 2001 From: Mike Jerred Date: Tue, 5 Nov 2024 10:52:10 +0000 Subject: [PATCH 823/860] fix: review comments --- libgit2-sys/lib.rs | 7 +----- src/index.rs | 46 ++++++++++++++++++++++++++++++++++++++ src/merge.rs | 2 +- src/repo.rs | 55 +++++----------------------------------------- 4 files changed, 53 insertions(+), 57 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 50939f0226..05f71a4ad3 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1373,7 +1373,7 @@ pub struct git_merge_file_options { } #[repr(C)] -#[derive(Copy)] +#[derive(Clone, Copy)] pub struct git_merge_file_result { pub automergeable: c_uint, pub path: *const c_char, @@ -1381,11 +1381,6 @@ pub struct git_merge_file_result { pub ptr: *const c_char, pub len: size_t, } -impl Clone for git_merge_file_result { - fn clone(&self) -> git_merge_file_result { - *self - } -} git_enum! { pub enum git_merge_flag_t { diff --git a/src/index.rs b/src/index.rs index 5625ba91ac..1f0e79a104 100644 --- a/src/index.rs +++ b/src/index.rs @@ -656,6 +656,52 @@ impl Index { } } +impl IndexEntry { + /// Create a raw index entry. + /// + /// The returned `raw::git_index_entry` contains a pointer to a `CString` path, which is also + /// returned because it's lifetime must exceed the lifetime of the `raw::git_index_entry`. + pub fn to_raw(&self) -> Result<(raw::git_index_entry, CString), Error> { + let path = CString::new(&self.path[..])?; + + // libgit2 encodes the length of the path in the lower bits of the + // `flags` entry, so mask those out and recalculate here to ensure we + // don't corrupt anything. + let mut flags = self.flags & !raw::GIT_INDEX_ENTRY_NAMEMASK; + + if self.path.len() < raw::GIT_INDEX_ENTRY_NAMEMASK as usize { + flags |= self.path.len() as u16; + } else { + flags |= raw::GIT_INDEX_ENTRY_NAMEMASK; + } + + unsafe { + let raw = raw::git_index_entry { + dev: self.dev, + ino: self.ino, + mode: self.mode, + uid: self.uid, + gid: self.gid, + file_size: self.file_size, + id: *self.id.raw(), + flags, + flags_extended: self.flags_extended, + path: path.as_ptr(), + mtime: raw::git_index_time { + seconds: self.mtime.seconds(), + nanoseconds: self.mtime.nanoseconds(), + }, + ctime: raw::git_index_time { + seconds: self.ctime.seconds(), + nanoseconds: self.ctime.nanoseconds(), + }, + }; + + Ok((raw, path)) + } + } +} + impl Binding for Index { type Raw = *mut raw::git_index; unsafe fn from_raw(raw: *mut raw::git_index) -> Index { diff --git a/src/merge.rs b/src/merge.rs index 64880603fa..06c3c1e223 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -402,7 +402,7 @@ impl<'repo> Drop for MergeFileResult<'repo> { } } -impl<'repo> std::fmt::Display for MergeFileResult<'repo> { +impl<'repo> std::fmt::Debug for MergeFileResult<'repo> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut ds = f.debug_struct("MergeFileResult"); if let Some(path) = &self.path() { diff --git a/src/repo.rs b/src/repo.rs index a1a3285b44..1c7b8c19c9 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2577,58 +2577,12 @@ impl Repository { theirs: &IndexEntry, opts: Option<&mut MergeFileOptions>, ) -> Result, Error> { - let create_raw_entry = |entry: &IndexEntry| -> Result { - let path = CString::new(&entry.path[..])?; - - // libgit2 encodes the length of the path in the lower bits of the - // `flags` entry, so mask those out and recalculate here to ensure we - // don't corrupt anything. - let mut flags = entry.flags & !raw::GIT_INDEX_ENTRY_NAMEMASK; - - if entry.path.len() < raw::GIT_INDEX_ENTRY_NAMEMASK as usize { - flags |= entry.path.len() as u16; - } else { - flags |= raw::GIT_INDEX_ENTRY_NAMEMASK; - } - - unsafe { - let raw = raw::git_index_entry { - dev: entry.dev, - ino: entry.ino, - mode: entry.mode, - uid: entry.uid, - gid: entry.gid, - file_size: entry.file_size, - id: *entry.id.raw(), - flags, - flags_extended: entry.flags_extended, - path: path.as_ptr(), - mtime: raw::git_index_time { - seconds: entry.mtime.seconds(), - nanoseconds: entry.mtime.nanoseconds(), - }, - ctime: raw::git_index_time { - seconds: entry.ctime.seconds(), - nanoseconds: entry.ctime.nanoseconds(), - }, - }; - - Ok(raw) - } - }; - - let mut ret = raw::git_merge_file_result { - automergeable: 0, - path: ptr::null_mut(), - mode: 0, - ptr: ptr::null_mut(), - len: 0, - }; - let ancestor = create_raw_entry(ancestor)?; - let ours = create_raw_entry(ours)?; - let theirs = create_raw_entry(theirs)?; + let (ancestor, _ancestor_path) = ancestor.to_raw()?; + let (ours, _ours_path) = ours.to_raw()?; + let (theirs, _theirs_path) = theirs.to_raw()?; unsafe { + let mut ret = mem::zeroed(); try_call!(raw::git_merge_file_from_index( &mut ret, self.raw(), @@ -4182,6 +4136,7 @@ mod tests { .unwrap(); assert!(!merge_file_result.is_automergeable()); + assert_eq!(merge_file_result.path(), Some("file")); assert_eq!( String::from_utf8_lossy(merge_file_result.content()).to_string(), r"<<<<<<< ours From b76c8becb0d760bcdcdf230ac90773c312c3edd8 Mon Sep 17 00:00:00 2001 From: Mike Jerred Date: Sun, 5 Jan 2025 09:58:53 +0000 Subject: [PATCH 824/860] fix: use correct typings for git_merge_file_flag_t --- libgit2-sys/lib.rs | 2 +- src/merge.rs | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 05f71a4ad3..065be08596 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1368,7 +1368,7 @@ pub struct git_merge_file_options { pub our_label: *const c_char, pub their_label: *const c_char, pub favor: git_merge_file_favor_t, - pub flags: u32, + pub flags: git_merge_file_flag_t, pub marker_size: c_ushort, } diff --git a/src/merge.rs b/src/merge.rs index 06c3c1e223..6329b8f597 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -280,7 +280,7 @@ impl MergeFileOptions { self } - fn flag(&mut self, opt: u32, val: bool) -> &mut MergeFileOptions { + fn flag(&mut self, opt: raw::git_merge_file_flag_t, val: bool) -> &mut MergeFileOptions { if val { self.raw.flags |= opt; } else { @@ -291,52 +291,52 @@ impl MergeFileOptions { /// Create standard conflicted merge files pub fn style_standard(&mut self, standard: bool) -> &mut MergeFileOptions { - self.flag(raw::GIT_MERGE_FILE_STYLE_MERGE as u32, standard) + self.flag(raw::GIT_MERGE_FILE_STYLE_MERGE, standard) } /// Create diff3-style file pub fn style_diff3(&mut self, diff3: bool) -> &mut MergeFileOptions { - self.flag(raw::GIT_MERGE_FILE_STYLE_DIFF3 as u32, diff3) + self.flag(raw::GIT_MERGE_FILE_STYLE_DIFF3, diff3) } /// Condense non-alphanumeric regions for simplified diff file pub fn simplify_alnum(&mut self, simplify: bool) -> &mut MergeFileOptions { - self.flag(raw::GIT_MERGE_FILE_SIMPLIFY_ALNUM as u32, simplify) + self.flag(raw::GIT_MERGE_FILE_SIMPLIFY_ALNUM, simplify) } /// Ignore all whitespace pub fn ignore_whitespace(&mut self, ignore: bool) -> &mut MergeFileOptions { - self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE as u32, ignore) + self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE, ignore) } /// Ignore changes in amount of whitespace pub fn ignore_whitespace_change(&mut self, ignore: bool) -> &mut MergeFileOptions { - self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE as u32, ignore) + self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE, ignore) } /// Ignore whitespace at end of line pub fn ignore_whitespace_eol(&mut self, ignore: bool) -> &mut MergeFileOptions { - self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL as u32, ignore) + self.flag(raw::GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL, ignore) } /// Use the "patience diff" algorithm pub fn patience(&mut self, patience: bool) -> &mut MergeFileOptions { - self.flag(raw::GIT_MERGE_FILE_DIFF_PATIENCE as u32, patience) + self.flag(raw::GIT_MERGE_FILE_DIFF_PATIENCE, patience) } /// Take extra time to find minimal diff pub fn minimal(&mut self, minimal: bool) -> &mut MergeFileOptions { - self.flag(raw::GIT_MERGE_FILE_DIFF_MINIMAL as u32, minimal) + self.flag(raw::GIT_MERGE_FILE_DIFF_MINIMAL, minimal) } /// Create zdiff3 ("zealous diff3")-style files pub fn style_zdiff3(&mut self, zdiff3: bool) -> &mut MergeFileOptions { - self.flag(raw::GIT_MERGE_FILE_STYLE_ZDIFF3 as u32, zdiff3) + self.flag(raw::GIT_MERGE_FILE_STYLE_ZDIFF3, zdiff3) } /// Do not produce file conflicts when common regions have changed pub fn accept_conflicts(&mut self, accept: bool) -> &mut MergeFileOptions { - self.flag(raw::GIT_MERGE_FILE_ACCEPT_CONFLICTS as u32, accept) + self.flag(raw::GIT_MERGE_FILE_ACCEPT_CONFLICTS, accept) } /// The size of conflict markers (eg, "<<<<<<<"). Default is 7. From e1e933b0f4300d48d6f56318d470c6422d0ff362 Mon Sep 17 00:00:00 2001 From: Mike Jerred Date: Sun, 5 Jan 2025 10:26:36 +0000 Subject: [PATCH 825/860] fix: mark to_raw as `unsafe` --- src/index.rs | 2 +- src/repo.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/index.rs b/src/index.rs index 1f0e79a104..c0d9294520 100644 --- a/src/index.rs +++ b/src/index.rs @@ -661,7 +661,7 @@ impl IndexEntry { /// /// The returned `raw::git_index_entry` contains a pointer to a `CString` path, which is also /// returned because it's lifetime must exceed the lifetime of the `raw::git_index_entry`. - pub fn to_raw(&self) -> Result<(raw::git_index_entry, CString), Error> { + pub(crate) unsafe fn to_raw(&self) -> Result<(raw::git_index_entry, CString), Error> { let path = CString::new(&self.path[..])?; // libgit2 encodes the length of the path in the lower bits of the diff --git a/src/repo.rs b/src/repo.rs index 1c7b8c19c9..b03aaba350 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2577,11 +2577,11 @@ impl Repository { theirs: &IndexEntry, opts: Option<&mut MergeFileOptions>, ) -> Result, Error> { - let (ancestor, _ancestor_path) = ancestor.to_raw()?; - let (ours, _ours_path) = ours.to_raw()?; - let (theirs, _theirs_path) = theirs.to_raw()?; - unsafe { + let (ancestor, _ancestor_path) = ancestor.to_raw()?; + let (ours, _ours_path) = ours.to_raw()?; + let (theirs, _theirs_path) = theirs.to_raw()?; + let mut ret = mem::zeroed(); try_call!(raw::git_merge_file_from_index( &mut ret, From 3cc3e25a9d6896690a3f50f1d6dfdb55d6f66f4f Mon Sep 17 00:00:00 2001 From: Mike Jerred Date: Sun, 5 Jan 2025 10:49:16 +0000 Subject: [PATCH 826/860] fix: type mismatch error --- libgit2-sys/lib.rs | 2 +- src/merge.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 065be08596..05f71a4ad3 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1368,7 +1368,7 @@ pub struct git_merge_file_options { pub our_label: *const c_char, pub their_label: *const c_char, pub favor: git_merge_file_favor_t, - pub flags: git_merge_file_flag_t, + pub flags: u32, pub marker_size: c_ushort, } diff --git a/src/merge.rs b/src/merge.rs index 6329b8f597..69ebd7ca11 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -282,9 +282,9 @@ impl MergeFileOptions { fn flag(&mut self, opt: raw::git_merge_file_flag_t, val: bool) -> &mut MergeFileOptions { if val { - self.raw.flags |= opt; + self.raw.flags |= opt as u32; } else { - self.raw.flags &= !opt; + self.raw.flags &= !opt as u32; } self } From 8381b72453f6b7c38ec3e1c8fed041f3202e17d5 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 17 Mar 2025 14:26:14 -0700 Subject: [PATCH 827/860] Make MergeFileOptions::raw pub(crate) For now I feel more comfortable not exposing this unless it is needed. --- src/merge.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/merge.rs b/src/merge.rs index 69ebd7ca11..bb6ffabd0e 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -346,8 +346,11 @@ impl MergeFileOptions { } /// Acquire a pointer to the underlying raw options. - pub unsafe fn raw(&mut self) -> *const raw::git_merge_file_options { - &self.raw as *const _ + /// + /// # Safety + /// The pointer used here (or its contents) should not outlive self. + pub(crate) unsafe fn raw(&mut self) -> *const raw::git_merge_file_options { + &self.raw } } From 197106b3606f3bfb8a02d5a6c7f422d960334723 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 17 Mar 2025 14:28:07 -0700 Subject: [PATCH 828/860] Drop Copy/Clone from git_merge_file_result I don't feel comfortable making this copy, since it could accidentally lead to creating multiple copies, which could then be confused as the memory of these needs to be managed. --- libgit2-sys/lib.rs | 1 - src/merge.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 05f71a4ad3..5b7ae56bd8 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -1373,7 +1373,6 @@ pub struct git_merge_file_options { } #[repr(C)] -#[derive(Clone, Copy)] pub struct git_merge_file_result { pub automergeable: c_uint, pub path: *const c_char, diff --git a/src/merge.rs b/src/merge.rs index bb6ffabd0e..d91fbed36d 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -395,7 +395,7 @@ impl<'repo> Binding for MergeFileResult<'repo> { } } fn raw(&self) -> raw::git_merge_file_result { - self.raw + unimplemented!() } } From d1b40aa0b7b8f53da56acd49fc99cd1adfa6f644 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 17 Mar 2025 14:30:12 -0700 Subject: [PATCH 829/860] Drop lifetime for MergeFileResult I feel comfortable not tying the lifetime here, since libgit2 fairly clearly keeps only owned data in git_merge_file_result, without any pointers to anything outside of it. --- src/merge.rs | 20 ++++++++------------ src/repo.rs | 2 +- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/merge.rs b/src/merge.rs index d91fbed36d..bdb32970a9 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -34,9 +34,8 @@ pub struct MergeFileOptions { } /// Information about file-level merging. -pub struct MergeFileResult<'repo> { +pub struct MergeFileResult { raw: raw::git_merge_file_result, - _marker: marker::PhantomData<&'repo str>, } impl<'repo> AnnotatedCommit<'repo> { @@ -354,7 +353,7 @@ impl MergeFileOptions { } } -impl<'repo> MergeFileResult<'repo> { +impl MergeFileResult { /// True if the output was automerged, false if the output contains /// conflict markers. pub fn is_automergeable(&self) -> bool { @@ -381,31 +380,28 @@ impl<'repo> MergeFileResult<'repo> { } /// The contents of the merge. - pub fn content(&self) -> &'repo [u8] { + pub fn content(&self) -> &[u8] { unsafe { std::slice::from_raw_parts(self.raw.ptr as *const u8, self.raw.len as usize) } } } -impl<'repo> Binding for MergeFileResult<'repo> { +impl Binding for MergeFileResult { type Raw = raw::git_merge_file_result; - unsafe fn from_raw(raw: raw::git_merge_file_result) -> MergeFileResult<'repo> { - MergeFileResult { - raw, - _marker: marker::PhantomData, - } + unsafe fn from_raw(raw: raw::git_merge_file_result) -> MergeFileResult { + MergeFileResult { raw } } fn raw(&self) -> raw::git_merge_file_result { unimplemented!() } } -impl<'repo> Drop for MergeFileResult<'repo> { +impl Drop for MergeFileResult { fn drop(&mut self) { unsafe { raw::git_merge_file_result_free(&mut self.raw) } } } -impl<'repo> std::fmt::Debug for MergeFileResult<'repo> { +impl std::fmt::Debug for MergeFileResult { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut ds = f.debug_struct("MergeFileResult"); if let Some(path) = &self.path() { diff --git a/src/repo.rs b/src/repo.rs index b03aaba350..464530332e 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2576,7 +2576,7 @@ impl Repository { ours: &IndexEntry, theirs: &IndexEntry, opts: Option<&mut MergeFileOptions>, - ) -> Result, Error> { + ) -> Result { unsafe { let (ancestor, _ancestor_path) = ancestor.to_raw()?; let (ours, _ours_path) = ours.to_raw()?; From 8980c617c29157761c37fff144e69bfd99d8bd6c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 17 Mar 2025 15:18:04 -0700 Subject: [PATCH 830/860] Bump versions of git2 and libgit2-sys --- CHANGELOG.md | 35 +++++++++++++++++++++++++++++++++++ Cargo.lock | 4 ++-- Cargo.toml | 4 ++-- README.md | 2 +- libgit2-sys/CHANGELOG.md | 15 +++++++++++++++ libgit2-sys/Cargo.toml | 2 +- 6 files changed, 56 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9e4089928..dca4981310 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,40 @@ # Changelog +## 0.20.1 - 2025-03-17 +[0.20.0...0.20.1](https://github.com/rust-lang/git2-rs/compare/git2-0.20.0...git2-0.20.1) + +### Added + +- Added `Repository::branch_upstream_merge()` + [#1131](https://github.com/rust-lang/git2-rs/pull/1131) +- Added `Index::conflict_get()` + [#1134](https://github.com/rust-lang/git2-rs/pull/1134) +- Added `Index::conflict_remove()` + [#1133](https://github.com/rust-lang/git2-rs/pull/1133) +- Added `opts::set_cache_object_limit()` + [#1118](https://github.com/rust-lang/git2-rs/pull/1118) +- Added `Repo::merge_file_from_index()` and associated `MergeFileOptions` and `MergeFileResult`. + [#1062](https://github.com/rust-lang/git2-rs/pull/1062) + +### Changed + +- The `url` dependency minimum raised to 2.5.4 + [#1128](https://github.com/rust-lang/git2-rs/pull/1128) +- Changed the tracing callback to abort the process if the callback panics instead of randomly detecting the panic in some other function. + [#1121](https://github.com/rust-lang/git2-rs/pull/1121) +- Credential helper config (loaded with `CredentialHelper::config`) now checks for helpers that start with something that looks like an absolute path, rather than checking for a `/` or `\` anywhere in the helper string (which resolves an issue if the helper had arguments with `/` or `\`). + [#1137](https://github.com/rust-lang/git2-rs/pull/1137) + +### Fixed + +- Fixed panic in `Remote::url_bytes` if the url is empty. + [#1120](https://github.com/rust-lang/git2-rs/pull/1120) +- Fixed incorrect lifetimes on `Patch::delta`, `Patch::hunk`, and `Patch::line_in_hunk`. The return values must not outlive the `Patch`. + [#1141](https://github.com/rust-lang/git2-rs/pull/1141) +- Bumped requirement to libgit2-sys 0.18.1, which fixes linking of advapi32 on Windows. + [#1143](https://github.com/rust-lang/git2-rs/pull/1143) + + ## 0.20.0 - 2025-01-04 [0.19.0...0.20.0](https://github.com/rust-lang/git2-rs/compare/git2-0.19.0...git2-0.20.0) diff --git a/Cargo.lock b/Cargo.lock index e0a14ba89b..8df8c64719 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -357,7 +357,7 @@ dependencies = [ [[package]] name = "git2" -version = "0.20.0" +version = "0.20.1" dependencies = [ "bitflags 2.6.0", "clap", @@ -575,7 +575,7 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libgit2-sys" -version = "0.18.0+1.9.0" +version = "0.18.1+1.9.0" dependencies = [ "cc", "libc", diff --git a/Cargo.toml b/Cargo.toml index 721286c60e..d0620d7466 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.20.0" +version = "0.20.1" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -20,7 +20,7 @@ url = "2.5.4" bitflags = "2.1.0" libc = "0.2" log = "0.4.8" -libgit2-sys = { path = "libgit2-sys", version = "0.18.0" } +libgit2-sys = { path = "libgit2-sys", version = "0.18.1" } [target."cfg(all(unix, not(target_os = \"macos\")))".dependencies] openssl-sys = { version = "0.9.45", optional = true } diff --git a/README.md b/README.md index ae1c377da9..7ac0c33826 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.20.0" +git2 = "0.20.1" ``` ## Rust version requirements diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index cb4dc53cb5..e3ea7ea189 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.18.1+1.9.0 - 2025-03-17 +[0.18.0...0.18.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.18.0+1.9.0...libgit2-sys-0.18.1+1.9.0) + +### Added + +- Added binding for `git_branch_upstream_merge` + [#1131](https://github.com/rust-lang/git2-rs/pull/1131) +- Added bindings for `git_merge_file_options` and `git_merge_file_result`, `git_merge_file_options_init`, `git_merge_file_from_index`, `git_merge_file_result_free`, and updated `git_merge_file_flag_t`. + [#1062](https://github.com/rust-lang/git2-rs/pull/1062) + +### Fixed + +- Fixed linking to advapi32 on Windows for recent nightly versions of Rust. + [#1143](https://github.com/rust-lang/git2-rs/pull/1143) + ## 0.18.0+1.9.0 - 2025-01-04 [0.16.2...0.17.0](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.17.0+1.8.1...libgit2-sys-0.18.0+1.9.0) diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index c056377f93..9612dcab75 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.18.0+1.9.0" +version = "0.18.1+1.9.0" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" From 0c3cba1dfe12f719ea67ca7d8bf3e60f198745c8 Mon Sep 17 00:00:00 2001 From: Seokju Na Date: Sat, 29 Mar 2025 12:14:12 +0900 Subject: [PATCH 831/860] add a missing status field --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 4b26b8c023..541277bfba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1049,6 +1049,8 @@ bitflags! { const WT_TYPECHANGE = raw::GIT_STATUS_WT_TYPECHANGE as u32; #[allow(missing_docs)] const WT_RENAMED = raw::GIT_STATUS_WT_RENAMED as u32; + #[allow(missing_docs)] + const WT_UNREADABLE = raw::GIT_STATUS_WT_UNREADABLE as u32; #[allow(missing_docs)] const IGNORED = raw::GIT_STATUS_IGNORED as u32; From 00faf61fdbddc976a180ec3490f442bc1bdbd35b Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Thu, 3 Apr 2025 16:28:55 +0200 Subject: [PATCH 832/860] Add missing code checks to Error::raw_code() These codes are both already handled by Error::code(), but because they weren't listed in Error::raw_code(), it would return -1, and so the paths in Error::code() for them would never be hit. This fixes the code of errors from Repository::merge_commits() with fail_on_conflict set for me. --- src/error.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/error.rs b/src/error.rs index 076667af98..ecc7f4f776 100644 --- a/src/error.rs +++ b/src/error.rs @@ -286,6 +286,8 @@ impl Error { GIT_EEOF, GIT_EINVALID, GIT_EUNCOMMITTED, + GIT_EDIRECTORY, + GIT_EMERGECONFLICT, GIT_PASSTHROUGH, GIT_ITEROVER, GIT_RETRY, @@ -294,6 +296,9 @@ impl Error { GIT_EAPPLYFAIL, GIT_EOWNER, GIT_TIMEOUT, + GIT_EUNCHANGED, + GIT_ENOTSUPPORTED, + GIT_EREADONLY, ) } From 38681b13d8ad1cbd056c07336772bcaabf920ba8 Mon Sep 17 00:00:00 2001 From: Redddy Date: Tue, 22 Apr 2025 10:37:34 +0900 Subject: [PATCH 833/860] fix: add a backtick --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index 464530332e..eaabbbf89b 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2137,7 +2137,7 @@ impl Repository { /// /// For compatibility with git, the repository is put into a merging state. /// Once the commit is done (or if the user wishes to abort), you should - /// clear this state by calling cleanup_state(). + /// clear this state by calling `cleanup_state()`. pub fn merge( &self, annotated_commits: &[&AnnotatedCommit<'_>], From ba5e1b33483755df7962f5c5771295d12cc6db15 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 22 Apr 2025 06:43:01 -0700 Subject: [PATCH 834/860] Make link an intra-doc link --- src/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repo.rs b/src/repo.rs index eaabbbf89b..061078d670 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2137,7 +2137,7 @@ impl Repository { /// /// For compatibility with git, the repository is put into a merging state. /// Once the commit is done (or if the user wishes to abort), you should - /// clear this state by calling `cleanup_state()`. + /// clear this state by calling [`cleanup_state()`][Repository::cleanup_state]. pub fn merge( &self, annotated_commits: &[&AnnotatedCommit<'_>], From 1774e57b6d11039e04274c0ade9c27d2c768af09 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 5 May 2025 07:45:23 -0700 Subject: [PATCH 835/860] Call init in Indexer::new Otherwise calling `Indexer::new` as the first thing in the program will result in "no error" errors. --- src/indexer.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/indexer.rs b/src/indexer.rs index ddca5fa2d5..be8618b5c6 100644 --- a/src/indexer.rs +++ b/src/indexer.rs @@ -122,6 +122,7 @@ impl<'a> Indexer<'a> { /// /// If `verify` is `false`, the indexer will bypass object connectivity checks. pub fn new(odb: Option<&Odb<'a>>, path: &Path, mode: u32, verify: bool) -> Result { + crate::init(); let path = path.into_c_string()?; let odb = odb.map(Binding::raw).unwrap_or_else(ptr::null_mut); From 7f42b7a08c2fc6fb54e107c357e2b9811e03fe9d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 5 May 2025 07:49:43 -0700 Subject: [PATCH 836/860] Clarify Indexer::new `path` parameter This updates the docs to clarify that the path is a *directory*. --- src/indexer.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/indexer.rs b/src/indexer.rs index be8618b5c6..3a3ff62a5a 100644 --- a/src/indexer.rs +++ b/src/indexer.rs @@ -118,6 +118,8 @@ impl<'a> Indexer<'a> { /// can be `None` if no thin pack is expected, in which case missing bases /// will result in an error. /// + /// `path` is the directory where the packfile should be stored. + /// /// `mode` is the permissions to use for the output files, use `0` for defaults. /// /// If `verify` is `false`, the indexer will bypass object connectivity checks. From 26bfd30ef25e6f7d7eab361f0ab118df3d1f6161 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 5 May 2025 08:07:56 -0700 Subject: [PATCH 837/860] Update version of git2 to 0.20.2 --- CHANGELOG.md | 15 +++++++++++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dca4981310..55ccdc3b4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.20.2 - 2025-05-05 +[0.20.1...0.20.2](https://github.com/rust-lang/git2-rs/compare/git2-0.20.1...git2-0.20.2) + +### Added + +- Added `Status::WT_UNREADABLE`. + [#1151](https://github.com/rust-lang/git2-rs/pull/1151) + +### Fixed + +- Added missing codes for `GIT_EDIRECTORY`, `GIT_EMERGECONFLICT`, `GIT_EUNCHANGED`, `GIT_ENOTSUPPORTED`, and `GIT_EREADONLY` to `Error::raw_code`. + [#1153](https://github.com/rust-lang/git2-rs/pull/1153) +- Fixed missing initialization in `Indexer::new`. + [#1160](https://github.com/rust-lang/git2-rs/pull/1160) + ## 0.20.1 - 2025-03-17 [0.20.0...0.20.1](https://github.com/rust-lang/git2-rs/compare/git2-0.20.0...git2-0.20.1) diff --git a/Cargo.lock b/Cargo.lock index 8df8c64719..1d4d2f2fc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -357,7 +357,7 @@ dependencies = [ [[package]] name = "git2" -version = "0.20.1" +version = "0.20.2" dependencies = [ "bitflags 2.6.0", "clap", diff --git a/Cargo.toml b/Cargo.toml index d0620d7466..02b4ddea8e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.20.1" +version = "0.20.2" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/README.md b/README.md index 7ac0c33826..b96234a095 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.20.1" +git2 = "0.20.2" ``` ## Rust version requirements From ba43121d235a6c85388738552a63a9c11488b650 Mon Sep 17 00:00:00 2001 From: Caleb Owens Date: Thu, 15 May 2025 23:20:08 +0200 Subject: [PATCH 838/860] Added comments to describe the add flags --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 541277bfba..28f0887b82 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -529,9 +529,9 @@ bitflags! { /// Flags for APIs that add files matching pathspec #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct IndexAddOption: u32 { - #[allow(missing_docs)] + /// Adds files that are not ignored to the index const DEFAULT = raw::GIT_INDEX_ADD_DEFAULT as u32; - #[allow(missing_docs)] + /// Allows adding otherwise ignored files to the index const FORCE = raw::GIT_INDEX_ADD_FORCE as u32; #[allow(missing_docs)] const DISABLE_PATHSPEC_MATCH = From da9c98d0c2b1527371e9ada0cf6f0f28835a4ea3 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 17 Jun 2025 20:07:41 -0700 Subject: [PATCH 839/860] Make url optional via a new "cred" feature gate for credential helpers Add an enabled-by-default feature flag for credential helpers, which are the only uses of the `url` crate. This reduces a `default-features = false` build of git2 from 54 dependencies to 17, for a configuration that many tools (e.g. anything that only cares about local repositories) can happily use. In addition to enabling it by default, make the "https" and "ssh" features depend on "cred". --- Cargo.toml | 11 +++++++---- src/cred.rs | 26 +++++++++++++++++--------- src/lib.rs | 4 +++- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 02b4ddea8e..220e7d2d6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ categories = ["api-bindings"] edition = "2018" [dependencies] -url = "2.5.4" +url = { version = "2.5.4", optional = true } bitflags = "2.1.0" libc = "0.2" log = "0.4.8" @@ -30,12 +30,15 @@ openssl-probe = { version = "0.1", optional = true } clap = { version = "4.4.13", features = ["derive"] } time = { version = "0.3.37", features = ["formatting"] } tempfile = "3.1.0" +url = "2.5.4" [features] unstable = [] -default = ["ssh", "https"] -ssh = ["libgit2-sys/ssh"] -https = ["libgit2-sys/https", "openssl-sys", "openssl-probe"] +default = ["ssh", "https", "cred"] +ssh = ["libgit2-sys/ssh", "cred"] +https = ["libgit2-sys/https", "openssl-sys", "openssl-probe", "cred"] +# Include support for credentials, which pulls in the `url` crate and all its dependencies +cred = ["dep:url"] vendored-libgit2 = ["libgit2-sys/vendored"] vendored-openssl = ["openssl-sys/vendored", "libgit2-sys/vendored-openssl"] zlib-ng-compat = ["libgit2-sys/zlib-ng-compat"] diff --git a/src/cred.rs b/src/cred.rs index 3def56ab6e..adf621b5d8 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -1,13 +1,14 @@ +#[cfg(feature = "cred")] use log::{debug, trace}; use std::ffi::CString; -use std::io::Write; use std::mem; use std::path::Path; -use std::process::{Command, Stdio}; use std::ptr; use crate::util::Binding; -use crate::{raw, Config, Error, IntoCString}; +#[cfg(feature = "cred")] +use crate::Config; +use crate::{raw, Error, IntoCString}; /// A structure to represent git credentials in libgit2. pub struct Cred { @@ -15,6 +16,7 @@ pub struct Cred { } /// Management of the gitcredentials(7) interface. +#[cfg(feature = "cred")] pub struct CredentialHelper { /// A public field representing the currently discovered username from /// configuration. @@ -118,6 +120,7 @@ impl Cred { /// successful. /// /// [1]: https://www.kernel.org/pub/software/scm/git/docs/gitcredentials.html + #[cfg(feature = "cred")] pub fn credential_helper( config: &Config, url: &str, @@ -189,6 +192,7 @@ impl Drop for Cred { } } +#[cfg(feature = "cred")] impl CredentialHelper { /// Create a new credential helper object which will be used to probe git's /// local credential configuration. @@ -292,6 +296,12 @@ impl CredentialHelper { // see https://www.kernel.org/pub/software/scm/git/docs/technical // /api-credentials.html#_credential_helpers fn add_command(&mut self, cmd: Option<&str>) { + fn is_absolute_path(path: &str) -> bool { + path.starts_with('/') + || path.starts_with('\\') + || cfg!(windows) && path.chars().nth(1).is_some_and(|x| x == ':') + } + let cmd = match cmd { Some("") | None => return, Some(s) => s, @@ -352,6 +362,9 @@ impl CredentialHelper { cmd: &str, username: &Option, ) -> (Option, Option) { + use std::io::Write; + use std::process::{Command, Stdio}; + macro_rules! my_try( ($e:expr) => ( match $e { Ok(e) => e, @@ -481,13 +494,8 @@ impl CredentialHelper { } } -fn is_absolute_path(path: &str) -> bool { - path.starts_with('/') - || path.starts_with('\\') - || cfg!(windows) && path.chars().nth(1).is_some_and(|x| x == ':') -} - #[cfg(test)] +#[cfg(feature = "cred")] mod test { use std::env; use std::fs::File; diff --git a/src/lib.rs b/src/lib.rs index 28f0887b82..62f4362f18 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,7 +88,9 @@ pub use crate::buf::Buf; pub use crate::cherrypick::CherrypickOptions; pub use crate::commit::{Commit, Parents}; pub use crate::config::{Config, ConfigEntries, ConfigEntry}; -pub use crate::cred::{Cred, CredentialHelper}; +pub use crate::cred::Cred; +#[cfg(feature = "cred")] +pub use crate::cred::CredentialHelper; pub use crate::describe::{Describe, DescribeFormatOptions, DescribeOptions}; pub use crate::diff::{Deltas, Diff, DiffDelta, DiffFile, DiffOptions}; pub use crate::diff::{DiffBinary, DiffBinaryFile, DiffBinaryKind, DiffPatchidOptions}; From cc9beb64a6313180e1980a1bb0ce4bc02f380930 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 21 Jun 2025 13:27:44 -0700 Subject: [PATCH 840/860] Update to libgit2 1.9.1 --- Cargo.lock | 2 +- libgit2-sys/Cargo.toml | 2 +- libgit2-sys/libgit2 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d4d2f2fc2..12115d77c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -575,7 +575,7 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libgit2-sys" -version = "0.18.1+1.9.0" +version = "0.18.2+1.9.1" dependencies = [ "cc", "libc", diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 9612dcab75..2bbbd5338c 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libgit2-sys" -version = "0.18.1+1.9.0" +version = "0.18.2+1.9.1" authors = ["Josh Triplett ", "Alex Crichton "] links = "git2" build = "build.rs" diff --git a/libgit2-sys/libgit2 b/libgit2-sys/libgit2 index 338e6fb681..0060d9cf56 160000 --- a/libgit2-sys/libgit2 +++ b/libgit2-sys/libgit2 @@ -1 +1 @@ -Subproject commit 338e6fb681369ff0537719095e22ce9dc602dbf0 +Subproject commit 0060d9cf5666f015b1067129bd874c6cc4c9c7ac From 2f3a8b9077dad099d9d41af543e2b7d072cd9503 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Tue, 25 Mar 2025 02:28:07 -0400 Subject: [PATCH 841/860] docs(#1148): Add note regarding potentially confusing behavior of `git_checkout_head`. --- src/repo.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/repo.rs b/src/repo.rs index 464530332e..34fc0798dd 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2065,6 +2065,13 @@ impl Repository { /// Updates files in the index and the working tree to match the content of /// the commit pointed at by HEAD. + /// + /// Note that this is _not_ the correct mechanism used to switch branches; + /// do not change your `HEAD` and then call this method, that would leave + /// you with checkout conflicts since your working directory would then + /// appear to be dirty. Instead, checkout the target of the branch and + /// then update `HEAD` using [`Repository::set_head`] to point to the + /// branch you checked out. pub fn checkout_head(&self, opts: Option<&mut CheckoutBuilder<'_>>) -> Result<(), Error> { unsafe { let mut raw_opts = mem::zeroed(); From 75af0be22a5fc88834699c5074ce54e7b4bfa00c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 21 Jun 2025 15:53:16 -0700 Subject: [PATCH 842/860] Drop civet/conduit from dev dependencies These don't seem to be maintained anymore, and they brought a lot of weight for just one test. I replaced them with a bare-bones http/cgi server using just the standard library. --- Cargo.lock | 180 +---------------------------------------- git2-curl/Cargo.toml | 3 - git2-curl/tests/all.rs | 135 +++++++++++++++++++++++++++++-- 3 files changed, 131 insertions(+), 187 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d4d2f2fc2..ff2ddfb530 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "aho-corasick" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" -dependencies = [ - "memchr 0.1.11", -] - [[package]] name = "anstream" version = "0.6.18" @@ -95,27 +86,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "civet" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9eff374cee04626041189bff6944fc204242250fe1c03c4feac5202fe6cc3fd" -dependencies = [ - "civet-sys", - "conduit", - "libc", - "semver 0.5.1", -] - -[[package]] -name = "civet-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876910de2615a24211fee8b88e62e2d5f81183ef1af2d827df4471c20319c4a2" -dependencies = [ - "cc", -] - [[package]] name = "clap" version = "4.5.23" @@ -171,25 +141,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" -[[package]] -name = "conduit" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0caa30f78c207dc14c071b62512253ece5c4459897815682786aff1028bc82" -dependencies = [ - "semver 0.5.1", -] - -[[package]] -name = "conduit-git-http-backend" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027a1900afd70becd52b5061afc85a24de6af0d9199f39d4e1af8b7ac55fbe6e" -dependencies = [ - "conduit", - "flate2", -] - [[package]] name = "ctest2" version = "0.4.9" @@ -258,7 +209,7 @@ checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -288,16 +239,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "flate2" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" -dependencies = [ - "libc", - "miniz-sys", -] - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -375,9 +316,6 @@ dependencies = [ name = "git2-curl" version = "0.21.0" dependencies = [ - "civet", - "conduit", - "conduit-git-http-backend", "curl", "git2", "log", @@ -551,22 +489,6 @@ dependencies = [ "libc", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" - [[package]] name = "libc" version = "0.2.169" @@ -640,31 +562,12 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -[[package]] -name = "memchr" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" -dependencies = [ - "libc", -] - [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "miniz-sys" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "num-conv" version = "0.1.0" @@ -752,32 +655,13 @@ dependencies = [ "thiserror", ] -[[package]] -name = "regex" -version = "0.1.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -dependencies = [ - "aho-corasick", - "memchr 0.1.11", - "regex-syntax", - "thread_local", - "utf8-ranges", -] - -[[package]] -name = "regex-syntax" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" - [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.24", + "semver", ] [[package]] @@ -808,31 +692,12 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "semver" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae2ff60ecdb19c255841c066cbfa5f8c2a4ada1eb3ae47c77ab6667128da71f5" -dependencies = [ - "semver-parser", -] - [[package]] name = "semver" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" -[[package]] -name = "semver-parser" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fff3c9c5a54636ab95acd8c1349926e04cb1eb8cd70b5adced8a1d1f703a67" -dependencies = [ - "lazy_static", - "regex", -] - [[package]] name = "serde" version = "1.0.217" @@ -860,7 +725,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa", - "memchr 2.7.4", + "memchr", "ryu", "serde", ] @@ -951,7 +816,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" dependencies = [ "dirs", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -974,25 +839,6 @@ dependencies = [ "syn", ] -[[package]] -name = "thread-id" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -dependencies = [ - "kernel32-sys", - "libc", -] - -[[package]] -name = "thread_local" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" -dependencies = [ - "thread-id", -] - [[package]] name = "time" version = "0.3.37" @@ -1063,12 +909,6 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" -[[package]] -name = "utf8-ranges" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -1093,12 +933,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -1109,12 +943,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index fad60e2755..3ce384f3d3 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -19,9 +19,6 @@ log = "0.4" git2 = { path = "..", version = "0.20", default-features = false } [dev-dependencies] -civet = "0.11" -conduit = "0.8" -conduit-git-http-backend = "0.8" tempfile = "3.0" [features] diff --git a/git2-curl/tests/all.rs b/git2-curl/tests/all.rs index c7f09dd40a..6b6fe9aca4 100644 --- a/git2-curl/tests/all.rs +++ b/git2-curl/tests/all.rs @@ -1,22 +1,141 @@ -use civet::{Config, Server}; -use conduit_git_http_backend as git_backend; +//! A simple test to verify that git2-curl can communicate to git over HTTP. + use std::fs::File; +use std::io::{BufRead, BufReader, Read, Write}; +use std::net::{TcpListener, TcpStream}; use std::path::Path; +use std::process::{Command, Stdio}; use tempfile::TempDir; const PORT: u16 = 7848; +/// This is a very bare-bones HTTP server, enough to run git-http-backend as a CGI. +fn handle_client(stream: TcpStream, working_dir: &Path) { + let mut buf = BufReader::new(stream); + let mut line = String::new(); + if buf.read_line(&mut line).unwrap() == 0 { + panic!("unexpected termination"); + } + // Read the "METHOD path HTTP/1.1" line. + let mut parts = line.split_ascii_whitespace(); + let method = parts.next().unwrap(); + let path = parts.next().unwrap(); + let (path, query) = path.split_once('?').unwrap_or_else(|| (path, "")); + let mut content_length = 0; + let mut content_type = String::new(); + // Read headers. + loop { + let mut header = String::new(); + if buf.read_line(&mut header).unwrap() == 0 { + panic!("unexpected header"); + } + if header == "\r\n" { + break; + } + let (name, value) = header.split_once(':').unwrap(); + let name = name.to_ascii_lowercase(); + match name.as_str() { + "content-length" => content_length = value.trim().parse().unwrap_or(0), + "content-type" => content_type = value.trim().to_owned(), + _ => {} + } + } + let mut body = vec![0u8; content_length]; + if content_length > 0 { + buf.read_exact(&mut body).unwrap(); + } + + let mut cgi_env = vec![ + ("GIT_PROJECT_ROOT", "."), + ("GIT_HTTP_EXPORT_ALL", "1"), + ("REQUEST_METHOD", method), + ("PATH_INFO", path), + ("QUERY_STRING", query), + ("CONTENT_TYPE", &content_type), + ("REMOTE_USER", ""), + ("REMOTE_ADDR", "127.0.0.1"), + ("AUTH_TYPE", ""), + ("REMOTE_HOST", ""), + ("SERVER_PROTOCOL", "HTTP/1.1"), + ("REQUEST_URI", path), + ]; + + let cl = content_length.to_string(); + cgi_env.push(("CONTENT_LENGTH", cl.as_str())); + + // Spawn git-http-backend + let mut cmd = Command::new("git"); + cmd.current_dir(working_dir); + cmd.arg("http-backend"); + for (k, v) in &cgi_env { + cmd.env(k, v); + } + cmd.stdin(Stdio::piped()).stdout(Stdio::piped()); + + let mut child = cmd.spawn().expect("failed to spawn git-http-backend"); + + if content_length > 0 { + child.stdin.as_mut().unwrap().write_all(&body).unwrap(); + } + + let mut cgi_output = Vec::new(); + child + .stdout + .as_mut() + .unwrap() + .read_to_end(&mut cgi_output) + .unwrap(); + + // Split CGI output into headers and body. + let index = cgi_output + .windows(4) + .position(|w| w == b"\r\n\r\n") + .unwrap_or(0); + let (headers, body) = (&cgi_output[..index], &cgi_output[index + 4..]); + let content_length = body.len(); + + // Write HTTP response + let mut stream = buf.into_inner(); + stream + .write_all( + &format!( + "HTTP/1.1 200 ok\r\n\ + Connection: close\r\n\ + Content-Length: {content_length}\r\n" + ) + .into_bytes(), + ) + .unwrap(); + stream.write_all(headers).unwrap(); + stream.write_all(b"\r\n\r\n").unwrap(); + stream.write_all(body).unwrap(); + stream.flush().unwrap(); +} + fn main() { + let td = TempDir::new().unwrap(); + let td_path = td.path().to_owned(); + + // Spin up a server for git-http-backend + std::thread::spawn(move || { + let listener = TcpListener::bind(("localhost", PORT)).unwrap(); + for stream in listener.incoming() { + match stream { + Ok(stream) => { + let td_path = td_path.clone(); + std::thread::spawn(move || handle_client(stream, &td_path)); + } + Err(e) => { + panic!("Connection failed: {}", e); + } + } + } + }); + unsafe { git2_curl::register(curl::easy::Easy::new()); } - // Spin up a server for git-http-backend - let td = TempDir::new().unwrap(); - let mut cfg = Config::new(); - cfg.port(PORT).threads(1); - let _a = Server::start(cfg, git_backend::Serve(td.path().to_path_buf())); - // Prep a repo with one file called `foo` let sig = git2::Signature::now("foo", "bar").unwrap(); let r1 = git2::Repository::init(td.path()).unwrap(); From 7b93e89541f9e96e45cb877133798c534d362ca6 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 21 Jun 2025 16:09:10 -0700 Subject: [PATCH 843/860] Update dependencies Updating anstream v0.6.18 -> v0.6.19 Updating anstyle v1.0.10 -> v1.0.11 Updating anstyle-parse v0.2.6 -> v0.2.7 Updating anstyle-query v1.1.2 -> v1.1.3 Updating anstyle-wincon v3.0.6 -> v3.0.9 Updating bitflags v2.6.0 -> v2.9.1 Updating cc v1.2.7 -> v1.2.27 Updating cfg-if v1.0.0 -> v1.0.1 Updating clap v4.5.23 -> v4.5.40 Updating clap_builder v4.5.23 -> v4.5.40 Updating clap_derive v4.5.18 -> v4.5.40 Updating clap_lex v0.7.4 -> v0.7.5 Updating cmake v0.1.52 -> v0.1.54 Updating colorchoice v1.0.3 -> v1.0.4 Updating ctest2 v0.4.9 -> v0.4.10 Updating curl v0.4.47 -> v0.4.48 Updating curl-sys v0.4.78+curl-8.11.0 -> v0.4.82+curl-8.14.1 Updating deranged v0.3.11 -> v0.4.0 Updating errno v0.3.10 -> v0.3.13 Removing getrandom v0.2.15 Adding getrandom v0.2.16 Adding getrandom v0.3.3 Updating icu_collections v1.5.0 -> v2.0.0 Adding icu_locale_core v2.0.0 Removing icu_locid v1.5.0 Removing icu_locid_transform v1.5.0 Removing icu_locid_transform_data v1.5.0 Updating icu_normalizer v1.5.0 -> v2.0.0 Updating icu_normalizer_data v1.5.0 -> v2.0.0 Updating icu_properties v1.5.1 -> v2.0.1 Updating icu_properties_data v1.5.0 -> v2.0.1 Updating icu_provider v1.5.0 -> v2.0.0 Removing icu_provider_macros v1.5.0 Updating idna_adapter v1.2.0 -> v1.2.1 Updating itoa v1.0.14 -> v1.0.15 Updating jobserver v0.1.32 -> v0.1.33 Updating libc v0.2.169 -> v0.2.174 Updating libssh2-sys v0.3.0 -> v0.3.1 Updating libz-sys v1.1.20 -> v1.1.22 Updating linux-raw-sys v0.4.14 -> v0.9.4 Updating litemap v0.7.4 -> v0.8.0 Updating log v0.4.22 -> v0.4.27 Updating memchr v2.7.4 -> v2.7.5 Updating once_cell v1.20.2 -> v1.21.3 Adding once_cell_polyfill v1.70.1 Updating openssl-probe v0.1.5 -> v0.1.6 Updating openssl-src v300.4.1+3.4.0 -> v300.5.0+3.5.0 Updating openssl-sys v0.9.104 -> v0.9.109 Updating pkg-config v0.3.31 -> v0.3.32 Adding potential_utf v0.1.2 Updating proc-macro2 v1.0.92 -> v1.0.95 Updating quote v1.0.38 -> v1.0.40 Adding r-efi v5.3.0 Updating rustix v0.38.42 -> v1.0.7 Updating ryu v1.0.18 -> v1.0.20 Updating semver v1.0.24 -> v1.0.26 Updating serde v1.0.217 -> v1.0.219 Updating serde_derive v1.0.217 -> v1.0.219 Updating serde_json v1.0.134 -> v1.0.140 Updating smallvec v1.13.2 -> v1.15.1 Updating socket2 v0.5.8 -> v0.5.10 Updating syn v2.0.94 -> v2.0.104 Updating synstructure v0.13.1 -> v0.13.2 Updating tempfile v3.15.0 -> v3.20.0 Updating time v0.3.37 -> v0.3.41 Updating time-core v0.1.2 -> v0.1.4 Updating time-macros v0.2.19 -> v0.2.22 Updating tinystr v0.7.6 -> v0.8.1 Updating unicode-ident v1.0.14 -> v1.0.18 Removing utf16_iter v1.0.5 Removing wasi v0.11.0+wasi-snapshot-preview1 Adding wasi v0.11.1+wasi-snapshot-preview1 Adding wasi v0.14.2+wasi-0.2.4 Adding windows-sys v0.60.2 Adding windows-targets v0.53.2 Adding windows_aarch64_gnullvm v0.53.0 Adding windows_aarch64_msvc v0.53.0 Adding windows_i686_gnu v0.53.0 Adding windows_i686_gnullvm v0.53.0 Adding windows_i686_msvc v0.53.0 Adding windows_x86_64_gnu v0.53.0 Adding windows_x86_64_gnullvm v0.53.0 Adding windows_x86_64_msvc v0.53.0 Adding wit-bindgen-rt v0.39.0 Removing write16 v1.0.0 Updating writeable v0.5.5 -> v0.6.1 Updating yoke v0.7.5 -> v0.8.0 Updating yoke-derive v0.7.5 -> v0.8.0 Updating zerofrom v0.1.5 -> v0.1.6 Updating zerofrom-derive v0.1.5 -> v0.1.6 Adding zerotrie v0.2.2 Updating zerovec v0.10.4 -> v0.11.2 Updating zerovec-derive v0.10.3 -> v0.11.1 --- Cargo.lock | 502 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 297 insertions(+), 205 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acc8a634be..02bde7eddf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -19,35 +19,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", + "once_cell_polyfill", "windows-sys 0.59.0", ] @@ -59,15 +60,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "cc" -version = "1.2.7" +version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ "jobserver", "libc", @@ -82,15 +83,15 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "clap" -version = "4.5.23" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", "clap_derive", @@ -98,9 +99,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstream", "anstyle", @@ -110,9 +111,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" dependencies = [ "heck", "proc-macro2", @@ -122,30 +123,30 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "cmake" -version = "0.1.52" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" dependencies = [ "cc", ] [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "ctest2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9176b0b37841111e734e749155ab95669bdfcbd5ac3a971f7afb1a217857b625" +checksum = "7cf53ed2a9e25d98cd444fd6e73eae7de0a26a8cb9e3f998170c6901a1afa0e5" dependencies = [ "cc", "garando_syntax", @@ -154,9 +155,9 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.47" +version = "0.4.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fb4d13a1be2b58f14d60adba57c9834b78c62fd86c3e76a148f732686e9265" +checksum = "9e2d5c8f48d9c0c23250e52b55e82a6ab4fdba6650c931f5a0a57a43abda812b" dependencies = [ "curl-sys", "libc", @@ -164,14 +165,14 @@ dependencies = [ "openssl-sys", "schannel", "socket2", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "curl-sys" -version = "0.4.78+curl-8.11.0" +version = "0.4.82+curl-8.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eec768341c5c7789611ae51cf6c459099f22e64a5d5d0ce4892434e33821eaf" +checksum = "c4d63638b5ec65f1a4ae945287b3fd035be4554bbaf211901159c9a2a74fb5be" dependencies = [ "cc", "libc", @@ -179,14 +180,14 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", ] @@ -225,12 +226,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.10" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -287,20 +288,32 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if 1.0.1", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.1", "libc", - "wasi", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] name = "git2" version = "0.20.2" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.1", "clap", "libc", "libgit2-sys", @@ -331,21 +344,22 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -354,31 +368,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -386,67 +380,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "idna" version = "1.0.3" @@ -460,9 +441,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -476,24 +457,25 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "libc", ] [[package]] name = "libc" -version = "0.2.169" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libgit2-sys" @@ -513,15 +495,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.1", "libc", ] [[package]] name = "libssh2-sys" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" +checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9" dependencies = [ "cc", "libc", @@ -533,9 +515,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.20" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" dependencies = [ "cc", "cmake", @@ -546,27 +528,27 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "num-conv" @@ -576,30 +558,36 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-src" -version = "300.4.1+3.4.0" +version = "300.5.0+3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" +checksum = "e8ce546f549326b0e6052b649198487d91320875da901e7bd11a06d1ee3f9c2f" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.104" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -616,9 +604,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "potential_utf" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] [[package]] name = "powerfmt" @@ -628,29 +625,35 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "redox_users" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.16", "libredox", "thiserror", ] @@ -666,11 +669,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.42" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys", @@ -679,9 +682,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "schannel" @@ -694,24 +697,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -720,9 +723,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.134" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -738,15 +741,15 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -766,9 +769,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.94" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -777,9 +780,9 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", @@ -797,13 +800,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.15.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if 1.0.0", "fastrand", - "getrandom", + "getrandom 0.3.3", "once_cell", "rustix", "windows-sys 0.59.0", @@ -841,9 +843,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.37" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -856,15 +858,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.19" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -872,9 +874,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -882,9 +884,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-xid" @@ -903,12 +905,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -929,9 +925,18 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] [[package]] name = "winapi" @@ -961,7 +966,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -970,7 +975,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", ] [[package]] @@ -979,14 +993,30 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -995,42 +1025,84 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -1038,22 +1110,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "write16" -version = "1.0.0" +name = "windows_x86_64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -1063,9 +1144,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", @@ -1075,18 +1156,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", @@ -1094,11 +1175,22 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -1107,9 +1199,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", From 79e74d09e2b8c1d16c2e8b09ad4181fe0c017700 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 21 Jun 2025 16:15:02 -0700 Subject: [PATCH 844/860] Allow init_ssl_cert_env_vars for now This is deprecated, someone should investigate how to switch to the preferred version instead. --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index 28f0887b82..e4bc8f9917 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -873,6 +873,7 @@ fn openssl_env_init() { // OS X the OpenSSL binaries are stable enough that we can just rely on // dynamic linkage (plus they have some weird modifications to OpenSSL which // means we wouldn't want to link statically). + #[allow(deprecated)] // FIXME: use init_openssl_env_vars instead openssl_probe::init_ssl_cert_env_vars(); } From 48b46f8a50cb1eacf2eea937780d5a26330b5a8f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 21 Jun 2025 16:16:06 -0700 Subject: [PATCH 845/860] Update libgit2-sys changelog for 0.18.2+1.9.1 --- libgit2-sys/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libgit2-sys/CHANGELOG.md b/libgit2-sys/CHANGELOG.md index e3ea7ea189..06ce1a7253 100644 --- a/libgit2-sys/CHANGELOG.md +++ b/libgit2-sys/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 0.18.2+1.9.1 - 2025-06-21 +[0.18.1...0.18.2](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.18.1+1.9.0...libgit2-sys-0.18.2+1.9.1) + +### Changed +- Updated to libgit2 [1.9.1](https://github.com/libgit2/libgit2/releases/tag/v1.9.1) + [#1169](https://github.com/rust-lang/git2-rs/pull/1169) + ## 0.18.1+1.9.0 - 2025-03-17 [0.18.0...0.18.1](https://github.com/rust-lang/git2-rs/compare/libgit2-sys-0.18.0+1.9.0...libgit2-sys-0.18.1+1.9.0) From b221928f41e6595a179bf4b540368643d279297a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 21 Jun 2025 17:01:44 -0700 Subject: [PATCH 846/860] Update to 2021 edition This updates all workspace members to the 2021 edition. --- Cargo.toml | 2 +- git2-curl/Cargo.toml | 2 +- libgit2-sys/Cargo.toml | 2 +- systest/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 02b4ddea8e..72f385f9c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ both threadsafe and memory safe and allows both reading and writing git repositories. """ categories = ["api-bindings"] -edition = "2018" +edition = "2021" [dependencies] url = "2.5.4" diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index 3ce384f3d3..2c5ca141e0 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -10,7 +10,7 @@ Backend for an HTTP transport in libgit2 powered by libcurl. Intended to be used with the git2 crate. """ -edition = "2018" +edition = "2021" [dependencies] curl = "0.4.33" diff --git a/libgit2-sys/Cargo.toml b/libgit2-sys/Cargo.toml index 2bbbd5338c..b2df3ca828 100644 --- a/libgit2-sys/Cargo.toml +++ b/libgit2-sys/Cargo.toml @@ -14,7 +14,7 @@ exclude = [ "libgit2/fuzzers/*", "libgit2/tests/*", ] -edition = "2018" +edition = "2021" [lib] name = "libgit2_sys" diff --git a/systest/Cargo.toml b/systest/Cargo.toml index fe5cabcf23..708cda4303 100644 --- a/systest/Cargo.toml +++ b/systest/Cargo.toml @@ -3,7 +3,7 @@ name = "systest" version = "0.1.0" authors = ["Alex Crichton "] build = "build.rs" -edition = "2018" +edition = "2021" [dependencies] libgit2-sys = { path = "../libgit2-sys", features = ['https', 'ssh'] } From 03ef1a7acde773b662f772fe66091b54acc92400 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 10 Aug 2025 17:59:31 -0700 Subject: [PATCH 847/860] Stop enabling "ssh", "https", and "cred" by default Many users of the git2 crate want to operate exclusively on local repositories, but if they don't use `default-features = false` they'll get a large set of additional dependencies they don't need. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 220e7d2d6d..05de72bcce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ url = "2.5.4" [features] unstable = [] -default = ["ssh", "https", "cred"] +default = [] ssh = ["libgit2-sys/ssh", "cred"] https = ["libgit2-sys/https", "openssl-sys", "openssl-probe", "cred"] # Include support for credentials, which pulls in the `url` crate and all its dependencies From 875a4cca7e229f5fe10f992d9ac6b96a011630fd Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 10 Aug 2025 17:58:24 -0700 Subject: [PATCH 848/860] Bump git2 to 0.21.0 due to change in default feature flags --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 2 +- git2-curl/Cargo.toml | 4 ++-- src/lib.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d4d2f2fc2..62d096c5ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -357,7 +357,7 @@ dependencies = [ [[package]] name = "git2" -version = "0.20.2" +version = "0.21.0" dependencies = [ "bitflags 2.6.0", "clap", diff --git a/Cargo.toml b/Cargo.toml index 05de72bcce..16d1da36d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.20.2" +version = "0.21.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/README.md b/README.md index b96234a095..ca00ad9672 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.20.2" +git2 = "0.21" ``` ## Rust version requirements diff --git a/git2-curl/Cargo.toml b/git2-curl/Cargo.toml index fad60e2755..5d90885f18 100644 --- a/git2-curl/Cargo.toml +++ b/git2-curl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2-curl" -version = "0.21.0" +version = "0.22.0" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/git2-rs" @@ -16,7 +16,7 @@ edition = "2018" curl = "0.4.33" url = "2.5.4" log = "0.4" -git2 = { path = "..", version = "0.20", default-features = false } +git2 = { path = "..", version = "0.21", default-features = false } [dev-dependencies] civet = "0.11" diff --git a/src/lib.rs b/src/lib.rs index 62f4362f18..ca96b06cd8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ //! source `Repository`, to ensure that they do not outlive the repository //! itself. -#![doc(html_root_url = "https://docs.rs/git2/0.20")] +#![doc(html_root_url = "https://docs.rs/git2/0.21")] #![allow(trivial_numeric_casts, trivial_casts)] #![deny(missing_docs)] #![warn(rust_2018_idioms)] From 3a29eda47a422b16d5a23f85afaec507134beb56 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 12 Aug 2025 10:35:19 -0700 Subject: [PATCH 849/860] CI: Fix lockfile verification The lockfile verification step wasn't work because it was running after other commands which would have updated the lockfile. This just moves it to the front, and no need for a separate step. --- .github/workflows/main.yml | 4 +--- Cargo.lock | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 19309bcd79..88c3c6c9f1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -33,12 +33,10 @@ jobs: - name: Install Rust (rustup) run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} shell: bash - - run: cargo test --no-default-features + - run: cargo test --no-default-features --locked - run: cargo test - run: cargo run -p systest - run: cargo test -p git2-curl - - name: Verify Cargo.lock is up-to-date - run: cargo update -p git2 --locked rustfmt: name: Rustfmt diff --git a/Cargo.lock b/Cargo.lock index 1c5498ccc9..d302b33c3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -327,7 +327,7 @@ dependencies = [ [[package]] name = "git2-curl" -version = "0.21.0" +version = "0.22.0" dependencies = [ "curl", "git2", From 1c94d61b14df4dd02ee965098348a973cc03bc05 Mon Sep 17 00:00:00 2001 From: Ximo Guanter Date: Thu, 23 Mar 2023 11:07:02 +0100 Subject: [PATCH 850/860] Make Binding public --- src/lib.rs | 2 +- src/util.rs | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index aeda2972b2..675680a8e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -142,7 +142,7 @@ pub use crate::tracing::{trace_set, TraceLevel}; pub use crate::transaction::Transaction; pub use crate::tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult}; pub use crate::treebuilder::TreeBuilder; -pub use crate::util::IntoCString; +pub use crate::util::{Binding, IntoCString}; pub use crate::version::Version; pub use crate::worktree::{Worktree, WorktreeAddOptions, WorktreeLockStatus, WorktreePruneOptions}; diff --git a/src/util.rs b/src/util.rs index 4065492f76..1315f0bd7a 100644 --- a/src/util.rs +++ b/src/util.rs @@ -20,13 +20,27 @@ impl IsNull for *mut T { } } -#[doc(hidden)] +/// Provides access to the raw libgit2 pointer to be able to interact with libgit2-sys. +/// +/// If you are going to depend on this trait on your code, do consider contributing to the git2 +/// project to add the missing capabilities to git2. pub trait Binding: Sized { + /// The raw type that allows you to interact with libgit2-sys. type Raw; + /// Build a git2 struct from its [Binding::Raw] value. unsafe fn from_raw(raw: Self::Raw) -> Self; + + /// Access the [Binding::Raw] value for a struct. + /// + /// The returned value is only safe to use while its associated git2 struct is in scope. + /// Once the associated git2 struct is destroyed, the raw value can point to an invalid memory address. fn raw(&self) -> Self::Raw; + /// A null-handling version of [Binding::from_raw]. + /// + /// If the input parameter is null, then the funtion returns None. Otherwise, it + /// calls [Binding::from_raw]. unsafe fn from_raw_opt(raw: T) -> Option where T: Copy + IsNull, From a934af2248a4cbf4f1f393cb4756495937a471ca Mon Sep 17 00:00:00 2001 From: tecc Date: Fri, 15 Aug 2025 16:44:38 +0200 Subject: [PATCH 851/860] feat: Add `git_odb_backend_data_malloc` and `git_odb_backend_data_free` Added `git_odb_backend_data_malloc` and `git_odb_backend_data_free`. Deprecated `git_odb_backend_malloc` in favour of the above two functions as it has been deprecated for over 6 years. --- libgit2-sys/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 5b7ae56bd8..901c3e896d 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -4115,8 +4115,12 @@ extern "C" { priority: c_int, ) -> c_int; + #[deprecated(note = "only kept for compatibility; prefer git_odb_backend_data_alloc")] pub fn git_odb_backend_malloc(backend: *mut git_odb_backend, len: size_t) -> *mut c_void; + pub fn git_odb_backend_data_alloc(backend: *mut git_odb_backend, len: size_t) -> *mut c_void; + pub fn git_odb_backend_data_free(backend: *mut git_odb_backend, data: *mut c_void); + pub fn git_odb_num_backends(odb: *mut git_odb) -> size_t; pub fn git_odb_get_backend( backend: *mut *mut git_odb_backend, @@ -4124,6 +4128,7 @@ extern "C" { position: size_t, ) -> c_int; + // mempack pub fn git_mempack_new(out: *mut *mut git_odb_backend) -> c_int; pub fn git_mempack_reset(backend: *mut git_odb_backend) -> c_int; From 53485da00720c2ffe6562cc41362d983e52f8a74 Mon Sep 17 00:00:00 2001 From: tecc Date: Sat, 16 Aug 2025 12:05:08 +0200 Subject: [PATCH 852/860] format: Fix formatting in libgit2-sys/lib.rs --- libgit2-sys/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 901c3e896d..7e1ac1e998 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -4128,7 +4128,6 @@ extern "C" { position: size_t, ) -> c_int; - // mempack pub fn git_mempack_new(out: *mut *mut git_odb_backend) -> c_int; pub fn git_mempack_reset(backend: *mut git_odb_backend) -> c_int; From 26981f32f6492d17df2d7f4243d78ad671791d15 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 22 Aug 2025 16:23:55 -0700 Subject: [PATCH 853/860] Test features in CI --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 88c3c6c9f1..98ed1523a4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -33,8 +33,8 @@ jobs: - name: Install Rust (rustup) run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} shell: bash - - run: cargo test --no-default-features --locked - - run: cargo test + - run: cargo test --locked + - run: cargo test --features https,ssh - run: cargo run -p systest - run: cargo test -p git2-curl From fd6d70f9972c4a1961045eb405e0a82c5f895c53 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 22 Aug 2025 16:24:17 -0700 Subject: [PATCH 854/860] Add docs.rs metadata for features --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 4f53a90c03..d56d5a196c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,3 +45,6 @@ zlib-ng-compat = ["libgit2-sys/zlib-ng-compat"] [workspace] members = ["systest", "git2-curl"] + +[package.metadata.docs.rs] +features = ["https", "ssh"] From 05fa593f9404c5d99d1cebfbef7cd35af9a9a60a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 22 Aug 2025 16:24:28 -0700 Subject: [PATCH 855/860] Add required features for examples --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index d56d5a196c..30a496deaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,3 +48,6 @@ members = ["systest", "git2-curl"] [package.metadata.docs.rs] features = ["https", "ssh"] + +[[examples]] +required-features = ["https", "ssh"] From dfd9b91461b9e512b5ce94822eb04774bfa5e542 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 22 Aug 2025 16:27:54 -0700 Subject: [PATCH 856/860] README.md: Add feature documentation --- README.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ca00ad9672..bbbeb54820 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,20 @@ libgit2 bindings for Rust. -```toml -[dependencies] -git2 = "0.21" +``` +cargo add git2 +``` + +## Features + +By default, git2 includes support for working with local repositories, but does +not include network support (e.g. cloning remote repositories). If you want to +use features that require network support, you may need the `"https"` and/or +`"ssh"` features. If you support user-provided repository URLs, you probably +want to enable both. + +``` +cargo add git2 --features https,ssh ``` ## Rust version requirements From 09b34c9a665b4efd175c76a1ee1eca2f1f4897a4 Mon Sep 17 00:00:00 2001 From: Christopher McClellan Date: Mon, 29 Sep 2025 11:02:22 -0400 Subject: [PATCH 857/860] Update README note about ssh feature According to the Cargo.toml file, the ssh feature is not enabled by default. https://github.com/rust-lang/git2-rs/blob/d58c7ce8f9dfd10d25389791a54fe54e7bfd3b6f/Cargo.toml#L37 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bbbeb54820..516a087a6e 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ To skip tests on a simple commit or doc-fixes, use `git commit --no-verify`. ## Building on macOS 10.10+ -If the `ssh` feature is enabled (and it is by default) then this library depends +If the `ssh` feature is enabled then this library depends on libssh2 which depends on OpenSSL. To get OpenSSL working follow the [`openssl` crate's instructions](https://github.com/sfackler/rust-openssl/blob/master/openssl/src/lib.rs#L31). From 4c982fb14c7b37faba2b8f3b13c48b5acd85a560 Mon Sep 17 00:00:00 2001 From: Ronan Pelliard Date: Mon, 6 Oct 2025 07:12:04 +0200 Subject: [PATCH 858/860] Add bindings for cache size options --- src/opts.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/opts.rs b/src/opts.rs index af5bb0cf9f..d0364399dd 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -111,6 +111,41 @@ pub unsafe fn set_cache_object_limit(kind: ObjectType, size: libc::size_t) -> Re Ok(()) } +/// Set the maximum total data size that will be cached in memory across all +/// repositories before libgit2 starts evicting objects from the cache. This +/// is a soft limit, in that the library might briefly exceed it, but will start +/// aggressively evicting objects from cache when that happens. The default +/// cache size is 256MB. +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn set_cache_max_size(size: libc::size_t) -> Result<(), Error> { + crate::init(); + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_CACHE_MAX_SIZE as libc::c_int, + size + )); + Ok(()) +} + +/// Get the current bytes in cache and the maximum that would be allowed in the cache. +/// +/// # Safety +/// This function is reading a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn get_cached_memory() -> Result<(libc::size_t, libc::size_t), Error> { + crate::init(); + let mut current = 0; + let mut allowed = 0; + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_CACHED_MEMORY as libc::c_int, + &mut current, + &mut allowed + )); + Ok((current, allowed)) +} + /// Controls whether or not libgit2 will verify when writing an object that all /// objects it references are valid. Enabled by default, but disabling this can /// significantly improve performance, at the cost of potentially allowing the From 87ec58bdef633378e75e99d4037a1eaf1f0d40bf Mon Sep 17 00:00:00 2001 From: Ronan Pelliard Date: Mon, 6 Oct 2025 20:16:54 +0200 Subject: [PATCH 859/860] use signed type and add tests --- src/opts.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/opts.rs b/src/opts.rs index d0364399dd..232d81e996 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -120,7 +120,7 @@ pub unsafe fn set_cache_object_limit(kind: ObjectType, size: libc::size_t) -> Re /// # Safety /// This function is modifying a C global without synchronization, so it is not /// thread safe, and should only be called before any thread is spawned. -pub unsafe fn set_cache_max_size(size: libc::size_t) -> Result<(), Error> { +pub unsafe fn set_cache_max_size(size: libc::ssize_t) -> Result<(), Error> { crate::init(); try_call!(raw::git_libgit2_opts( raw::GIT_OPT_SET_CACHE_MAX_SIZE as libc::c_int, @@ -134,7 +134,7 @@ pub unsafe fn set_cache_max_size(size: libc::size_t) -> Result<(), Error> { /// # Safety /// This function is reading a C global without synchronization, so it is not /// thread safe, and should only be called before any thread is spawned. -pub unsafe fn get_cached_memory() -> Result<(libc::size_t, libc::size_t), Error> { +pub unsafe fn get_cached_memory() -> Result<(libc::ssize_t, libc::ssize_t), Error> { crate::init(); let mut current = 0; let mut allowed = 0; @@ -519,4 +519,12 @@ mod test { assert!(get_server_timeout_in_milliseconds().unwrap() == 10_000); } } + + #[test] + fn cache_size() { + unsafe { + assert!(set_cache_max_size(20 * 1024 * 1024).is_ok()); + assert!(get_cached_memory().is_ok_and(|m| m.1 == 20 * 1024 * 1024)); + } + } } From 4d19f248b01cc1f7ac898ad6a32e410df0142ecb Mon Sep 17 00:00:00 2001 From: cyqsimon <28627918+cyqsimon@users.noreply.github.com> Date: Sun, 19 Oct 2025 21:02:42 +0800 Subject: [PATCH 860/860] Improve function docs for `Repository::tag_foreach` --- src/repo.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/repo.rs b/src/repo.rs index ed24e67529..07d3a7c55f 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -2043,8 +2043,10 @@ impl Repository { } } - /// iterate over all tags calling `cb` on each. - /// the callback is provided the tag id and name + /// Iterate over all tags, calling the callback `cb` on each. + /// The arguments of `cb` are the tag id and name, in this order. + /// + /// Returning `false` from `cb` causes the iteration to break early. pub fn tag_foreach(&self, cb: T) -> Result<(), Error> where T: FnMut(Oid, &[u8]) -> bool,