1 use {raw, panic, Oid, StashApplyProgress}
;
4 use libc
::{c_int, c_char, size_t, c_void}
;
5 use build
::{CheckoutBuilder}
;
8 /// Stash application progress notification function.
10 /// Return `true` to continue processing, or `false` to
11 /// abort the stash application.
12 pub type StashApplyProgressCb
<'a
> = FnMut(StashApplyProgress
) -> bool
+ 'a
;
14 /// This is a callback function you can provide to iterate over all the
15 /// stashed states that will be invoked per entry.
16 pub type StashCb
<'a
> = FnMut(usize, &str, &Oid
) -> bool
+ 'a
;
19 /// Stash application options structure
20 pub struct StashApplyOptions
<'cb
> {
21 progress
: Option
<Box
<StashApplyProgressCb
<'cb
>>>,
22 checkout_options
: Option
<CheckoutBuilder
<'cb
>>,
23 raw_opts
: raw
::git_stash_apply_options
26 impl<'cb
> Default
for StashApplyOptions
<'cb
> {
27 fn default() -> Self {
32 impl<'cb
> StashApplyOptions
<'cb
> {
33 /// Creates a default set of merge options.
34 pub fn new() -> StashApplyOptions
<'cb
> {
35 let mut opts
= StashApplyOptions
{
37 checkout_options
: None
,
38 raw_opts
: unsafe { mem::zeroed() }
,
41 raw
::git_stash_apply_init_options(&mut opts
.raw_opts
, 1)
46 /// Set stash application flag to GIT_STASH_APPLY_REINSTATE_INDEX
47 pub fn reinstantiate_index(&mut self) -> &mut StashApplyOptions
<'cb
> {
48 self.raw_opts
.flags
= raw
::GIT_STASH_APPLY_REINSTATE_INDEX
;
52 /// Options to use when writing files to the working directory
53 pub fn checkout_options(&mut self, opts
: CheckoutBuilder
<'cb
>) -> &mut StashApplyOptions
<'cb
> {
54 self.checkout_options
= Some(opts
);
58 /// Optional callback to notify the consumer of application progress.
60 /// Return `true` to continue processing, or `false` to
61 /// abort the stash application.
62 pub fn progress_cb
<C
>(&mut self, callback
: C
) -> &mut StashApplyOptions
<'cb
>
63 where C
: FnMut(StashApplyProgress
) -> bool
+ 'cb
65 self.progress
= Some(Box
::new(callback
) as Box
<StashApplyProgressCb
<'cb
>>);
66 self.raw_opts
.progress_cb
= stash_apply_progress_cb
;
67 self.raw_opts
.progress_payload
= self as *mut _
as *mut _
;
71 /// Pointer to a raw git_stash_apply_options
72 pub fn raw(&mut self) -> &raw
::git_stash_apply_options
{
74 if let Some(opts
) = self.checkout_options
.as_mut() {
75 opts
.configure(&mut self.raw_opts
.checkout_options
);
83 pub struct StashCbData
<'a
> {
84 pub callback
: &'a
mut StashCb
<'a
>
88 pub extern fn stash_cb(index
: size_t
,
89 message
: *const c_char
,
90 stash_id
: *const raw
::git_oid
,
94 panic
::wrap(|| unsafe {
95 let mut data
= &mut *(payload
as *mut StashCbData
);
97 let mut callback
= &mut data
.callback
;
99 CStr
::from_ptr(message
).to_str().unwrap(),
100 &Binding
::from_raw(stash_id
))
103 if res { 0 }
else { 1 }
107 fn convert_progress(progress
: raw
::git_stash_apply_progress_t
) -> StashApplyProgress
{
109 raw
::GIT_STASH_APPLY_PROGRESS_NONE
=> StashApplyProgress
::None
,
110 raw
::GIT_STASH_APPLY_PROGRESS_LOADING_STASH
=> StashApplyProgress
::LoadingStash
,
111 raw
::GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX
=> StashApplyProgress
::AnalyzeIndex
,
112 raw
::GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED
=> StashApplyProgress
::AnalyzeModified
,
113 raw
::GIT_STASH_APPLY_PROGRESS_ANALYZE_UNTRACKED
=> StashApplyProgress
::AnalyzeUntracked
,
114 raw
::GIT_STASH_APPLY_PROGRESS_CHECKOUT_UNTRACKED
=> StashApplyProgress
::CheckoutUntracked
,
115 raw
::GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED
=> StashApplyProgress
::CheckoutModified
,
116 raw
::GIT_STASH_APPLY_PROGRESS_DONE
=> StashApplyProgress
::Done
,
118 _
=> StashApplyProgress
::None
123 extern fn stash_apply_progress_cb(progress
: raw
::git_stash_apply_progress_t
,
124 payload
: *mut c_void
)
127 panic
::wrap(|| unsafe {
128 let mut options
= &mut *(payload
as *mut StashApplyOptions
);
130 let mut callback
= options
.progress
.as_mut().unwrap();
131 callback(convert_progress(progress
))
134 if res { 0 }
else { -1 }
140 use stash
::{StashApplyOptions}
;
141 use std
::io
::{Write}
;
144 use test
::{repo_init}
;
145 use {Repository, STATUS_WT_NEW, STASH_INCLUDE_UNTRACKED}
;
147 fn make_stash
<C
>(next
: C
) where C
: FnOnce(&mut Repository
) {
148 let (_td
, mut repo
) = repo_init();
149 let signature
= repo
.signature().unwrap();
151 let p
= Path
::new(repo
.workdir().unwrap()).join("file_b.txt");
152 println
!("using path {:?}", p
);
153 fs
::File
::create(&p
).unwrap()
154 .write("data".as_bytes()).unwrap();
156 let rel_p
= Path
::new("file_b.txt");
157 assert
!(repo
.status_file(&rel_p
).unwrap() == STATUS_WT_NEW
);
159 repo
.stash_save(&signature
, "msg1", Some(STASH_INCLUDE_UNTRACKED
)).unwrap();
161 assert
!(repo
.status_file(&rel_p
).is_err());
164 repo
.stash_foreach(|index
, name
, _oid
| {
167 assert
!(name
== "On master: msg1");
175 fn count_stash(repo
: &mut Repository
) -> usize {
177 repo
.stash_foreach(|_
, _
, _
| { count += 1; true }
).unwrap();
182 fn smoke_stash_save_drop() {
184 repo
.stash_drop(0).unwrap();
185 assert
!(count_stash(repo
) == 0)
190 fn smoke_stash_save_pop() {
192 repo
.stash_pop(0, None
).unwrap();
193 assert
!(count_stash(repo
) == 0)
198 fn smoke_stash_save_apply() {
200 let mut options
= StashApplyOptions
::new();
201 options
.progress_cb(|progress
| {
202 println
!("{:?}", progress
);
206 repo
.stash_apply(0, Some(&mut options
)).unwrap();
207 assert
!(count_stash(repo
) == 1)