From 90a45bb106a723259e2a0f0c3ff5fb4f70723fda Mon Sep 17 00:00:00 2001 From: Andres Suarez Date: Mon, 26 Apr 2021 10:10:26 -0400 Subject: [PATCH 001/299] 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 002/299] 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 003/299] 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 004/299] 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 005/299] 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 006/299] 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 007/299] 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 008/299] 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 009/299] 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 010/299] 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 011/299] 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 012/299] 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 013/299] 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 014/299] 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 015/299] 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 016/299] 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 017/299] 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 018/299] 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 019/299] 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 020/299] 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 021/299] 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 022/299] 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 023/299] 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 024/299] 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 025/299] 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 026/299] 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 027/299] 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 028/299] 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 029/299] 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 030/299] 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 031/299] 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 032/299] 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 033/299] 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 034/299] 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 035/299] 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 036/299] 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 037/299] 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 038/299] 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 039/299] 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 040/299] 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 041/299] 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 042/299] 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 043/299] 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 044/299] 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 045/299] 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 046/299] 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 047/299] 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 048/299] 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 049/299] `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 050/299] 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 051/299] 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 052/299] 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 053/299] 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 054/299] 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 055/299] 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 056/299] 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 057/299] 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 058/299] 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 059/299] 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 060/299] 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 061/299] 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 062/299] 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 063/299] 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 064/299] 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 065/299] 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 066/299] 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 067/299] 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 068/299] 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 069/299] 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 070/299] 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 071/299] 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 072/299] 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 073/299] 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 074/299] 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 075/299] 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 076/299] 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 077/299] 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 078/299] 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 079/299] 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 080/299] 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 081/299] 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 082/299] 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 083/299] 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 084/299] 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 085/299] 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 086/299] 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 087/299] 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 088/299] 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 089/299] 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 090/299] 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 091/299] 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 092/299] 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 093/299] 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 094/299] 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 095/299] 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 096/299] 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 097/299] 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 098/299] 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 099/299] 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 100/299] 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 101/299] 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 102/299] 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 103/299] 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 104/299] 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 105/299] 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(&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(&*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(&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 106/299] 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 107/299] 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 108/299] 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 109/299] 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 110/299] 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 111/299] 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 112/299] 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 113/299] 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 114/299] 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 115/299] 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 116/299] 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 117/299] 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 118/299] 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 119/299] 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(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 120/299] 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 121/299] 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 122/299] 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 123/299] 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 124/299] 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 125/299] 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 126/299] 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 127/299] 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 128/299] 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 129/299] 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 130/299] 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 131/299] 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 132/299] 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 133/299] 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 134/299] 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 135/299] 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 136/299] 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 137/299] 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 138/299] 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 139/299] 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 140/299] 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 141/299] `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 142/299] 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 143/299] 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 144/299] 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 145/299] 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 146/299] 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 147/299] 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 148/299] 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 149/299] 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 150/299] 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 151/299] 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 152/299] 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 153/299] 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 154/299] 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 155/299] 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 156/299] 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 157/299] 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 158/299] 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 159/299] 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 160/299] 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 161/299] 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 162/299] 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 163/299] 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 164/299] 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 165/299] 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 166/299] 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 167/299] 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 168/299] 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 169/299] 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 170/299] 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 171/299] 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 172/299] 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 173/299] 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 174/299] 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 175/299] 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 176/299] 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 177/299] 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 178/299] 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 179/299] 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 180/299] 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 181/299] 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 182/299] 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 183/299] 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 184/299] 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 185/299] 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 186/299] 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 187/299] 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 188/299] 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 189/299] 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 190/299] 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 191/299] 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 192/299] 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 193/299] 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("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 194/299] 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 195/299] 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 196/299] 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 197/299] 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 198/299] 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 199/299] 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 200/299] 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 201/299] 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 202/299] 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 203/299] 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 204/299] 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 205/299] 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 206/299] 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 207/299] 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 208/299] 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 209/299] 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 210/299] 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 211/299] 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 212/299] 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 213/299] 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 214/299] 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 215/299] 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 216/299] 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 217/299] (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 218/299] 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 219/299] (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 220/299] 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 221/299] 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 222/299] 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 223/299] 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 224/299] 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 225/299] 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 226/299] 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 227/299] 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 228/299] 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 229/299] 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 230/299] 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 231/299] 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 232/299] 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 233/299] 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 234/299] 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 235/299] 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 236/299] 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 237/299] 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 238/299] 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 239/299] 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 240/299] 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 241/299] 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 242/299] 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 243/299] 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 244/299] 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 245/299] 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 246/299] 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(&*self.raw)).unwrap() } + unsafe { crate::opt_bytes(self, raw::git_remote_url(&*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 247/299] 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 248/299] 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 249/299] 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 250/299] 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(&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(&*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 251/299] 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 252/299] 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 253/299] 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 254/299] 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 255/299] 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 256/299] 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 257/299] 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 258/299] 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 259/299] 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 260/299] 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 261/299] 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 262/299] 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 263/299] 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 264/299] 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 265/299] 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 266/299] 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 267/299] 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 268/299] 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 269/299] 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 270/299] 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 271/299] 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 272/299] 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 273/299] 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 274/299] 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 275/299] 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 276/299] 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 277/299] 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 278/299] 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 279/299] 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 280/299] 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 281/299] 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 282/299] 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 283/299] 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 284/299] 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 285/299] 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 286/299] 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 287/299] 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 288/299] 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 289/299] 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 290/299] 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 291/299] 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 292/299] 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 293/299] 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 294/299] 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 295/299] 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 296/299] 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 297/299] 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 298/299] 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 299/299] 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,