From dc0db358abe19481e475e10c32149b53370f1a1c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:57:31 +0200 Subject: Merging upstream version 1.72.1+dfsg1. Signed-off-by: Daniel Baumann --- vendor/git2/src/diff.rs | 2 +- vendor/git2/src/lib.rs | 2 + vendor/git2/src/repo.rs | 21 +++++++- vendor/git2/src/stash.rs | 120 +++++++++++++++++++++++++++++++++++++------ vendor/git2/src/transport.rs | 2 +- 5 files changed, 129 insertions(+), 18 deletions(-) (limited to 'vendor/git2/src') diff --git a/vendor/git2/src/diff.rs b/vendor/git2/src/diff.rs index 6949d094e..e039c76d5 100644 --- a/vendor/git2/src/diff.rs +++ b/vendor/git2/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/vendor/git2/src/lib.rs b/vendor/git2/src/lib.rs index ef8cb2c9c..d2bc6f599 100644 --- a/vendor/git2/src/lib.rs +++ b/vendor/git2/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/vendor/git2/src/repo.rs b/vendor/git2/src/repo.rs index a794939be..921e2b30e 100644 --- a/vendor/git2/src/repo.rs +++ b/vendor/git2/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 { } } + /// Like `stash_save` but with more options like selective statshing via path patterns. + 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/vendor/git2/src/stash.rs b/vendor/git2/src/stash.rs index 97e02b5de..bff9e49de 100644 --- a/vendor/git2/src/stash.rs +++ b/vendor/git2/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 + } + + /// Customize optional `flags` field + 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,11 @@ 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 @@ -167,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); @@ -240,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(); @@ -258,4 +315,37 @@ 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::write(&p, data).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); + } } diff --git a/vendor/git2/src/transport.rs b/vendor/git2/src/transport.rs index 5d4695948..74446d0ca 100644 --- a/vendor/git2/src/transport.rs +++ b/vendor/git2/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 = -- cgit v1.2.3