1
1
use crate :: build:: CheckoutBuilder ;
2
- use crate :: util:: Binding ;
3
- use crate :: { panic, raw, Oid , StashApplyProgress } ;
2
+ use crate :: util:: { self , Binding } ;
3
+ use crate :: { panic, raw, IntoCString , Oid , Signature , StashApplyProgress , StashFlags } ;
4
4
use libc:: { c_char, c_int, c_void, size_t} ;
5
- use std:: ffi:: CStr ;
5
+ use std:: ffi:: { c_uint , CStr , CString } ;
6
6
use std:: mem;
7
7
8
+ #[ allow( unused) ]
9
+ /// Stash application options structure
10
+ pub struct StashSaveOptions < ' a > {
11
+ message : Option < CString > ,
12
+ flags : Option < StashFlags > ,
13
+ stasher : Signature < ' a > ,
14
+ pathspec : Vec < CString > ,
15
+ pathspec_ptrs : Vec < * const c_char > ,
16
+ raw_opts : raw:: git_stash_save_options ,
17
+ }
18
+
19
+ impl < ' a > StashSaveOptions < ' a > {
20
+ /// Creates a default
21
+ pub fn new ( stasher : Signature < ' a > ) -> Self {
22
+ let mut opts = Self {
23
+ message : None ,
24
+ flags : None ,
25
+ stasher,
26
+ pathspec : Vec :: new ( ) ,
27
+ pathspec_ptrs : Vec :: new ( ) ,
28
+ raw_opts : unsafe { mem:: zeroed ( ) } ,
29
+ } ;
30
+ assert_eq ! (
31
+ unsafe {
32
+ raw:: git_stash_save_options_init(
33
+ & mut opts. raw_opts,
34
+ raw:: GIT_STASH_SAVE_OPTIONS_VERSION ,
35
+ )
36
+ } ,
37
+ 0
38
+ ) ;
39
+ opts
40
+ }
41
+
42
+ /// Customize optional `flags` field
43
+ pub fn flags ( & mut self , flags : Option < StashFlags > ) -> & mut Self {
44
+ self . flags = flags;
45
+ self
46
+ }
47
+
48
+ /// Add to the array of paths patterns to build the stash.
49
+ pub fn pathspec < T : IntoCString > ( & mut self , pathspec : T ) -> & mut Self {
50
+ let s = util:: cstring_to_repo_path ( pathspec) . unwrap ( ) ;
51
+ self . pathspec_ptrs . push ( s. as_ptr ( ) ) ;
52
+ self . pathspec . push ( s) ;
53
+ self
54
+ }
55
+
56
+ /// Acquire a pointer to the underlying raw options.
57
+ ///
58
+ /// This function is unsafe as the pointer is only valid so long as this
59
+ /// structure is not moved, modified, or used elsewhere.
60
+ pub unsafe fn raw ( & mut self ) -> * const raw:: git_stash_save_options {
61
+ self . raw_opts . flags = self . flags . unwrap_or_else ( StashFlags :: empty) . bits as c_uint ;
62
+ self . raw_opts . message = crate :: call:: convert ( & self . message ) ;
63
+ self . raw_opts . paths . count = self . pathspec_ptrs . len ( ) as size_t ;
64
+ self . raw_opts . paths . strings = self . pathspec_ptrs . as_ptr ( ) as * mut _ ;
65
+ self . raw_opts . stasher = self . stasher . raw ( ) ;
66
+
67
+ & self . raw_opts as * const _
68
+ }
69
+ }
70
+
8
71
/// Stash application progress notification function.
9
72
///
10
73
/// Return `true` to continue processing, or `false` to
@@ -151,12 +214,11 @@ extern "C" fn stash_apply_progress_cb(
151
214
152
215
#[ cfg( test) ]
153
216
mod tests {
154
- use crate :: stash:: StashApplyOptions ;
217
+ use crate :: stash:: { StashApplyOptions , StashSaveOptions } ;
155
218
use crate :: test:: repo_init;
156
- use crate :: { Repository , StashFlags , Status } ;
219
+ use crate :: { IndexAddOption , Repository , StashFlags , Status } ;
157
220
use std:: fs;
158
- use std:: io:: Write ;
159
- use std:: path:: Path ;
221
+ use std:: path:: { Path , PathBuf } ;
160
222
161
223
fn make_stash < C > ( next : C )
162
224
where
@@ -167,10 +229,8 @@ mod tests {
167
229
168
230
let p = Path :: new ( repo. workdir ( ) . unwrap ( ) ) . join ( "file_b.txt" ) ;
169
231
println ! ( "using path {:?}" , p) ;
170
- fs:: File :: create ( & p)
171
- . unwrap ( )
172
- . write ( "data" . as_bytes ( ) )
173
- . unwrap ( ) ;
232
+
233
+ fs:: write ( & p, "data" . as_bytes ( ) ) . unwrap ( ) ;
174
234
175
235
let rel_p = Path :: new ( "file_b.txt" ) ;
176
236
assert ! ( repo. status_file( & rel_p) . unwrap( ) == Status :: WT_NEW ) ;
@@ -240,10 +300,7 @@ mod tests {
240
300
241
301
let p = Path :: new ( repo. workdir ( ) . unwrap ( ) ) . join ( "file_b.txt" ) ;
242
302
243
- fs:: File :: create ( & p)
244
- . unwrap ( )
245
- . write ( "data" . as_bytes ( ) )
246
- . unwrap ( ) ;
303
+ fs:: write ( & p, "data" . as_bytes ( ) ) . unwrap ( ) ;
247
304
248
305
repo. stash_save2 ( & signature, None , Some ( StashFlags :: INCLUDE_UNTRACKED ) )
249
306
. unwrap ( ) ;
@@ -258,4 +315,37 @@ mod tests {
258
315
259
316
assert ! ( stash_name. starts_with( "WIP on main:" ) ) ;
260
317
}
318
+
319
+ fn create_file ( r : & Repository , name : & str , data : & str ) -> PathBuf {
320
+ let p = Path :: new ( r. workdir ( ) . unwrap ( ) ) . join ( name) ;
321
+ fs:: write ( & p, data) . unwrap ( ) ;
322
+ p
323
+ }
324
+
325
+ #[ test]
326
+ fn test_stash_save_ext ( ) {
327
+ let ( _td, mut repo) = repo_init ( ) ;
328
+ let signature = repo. signature ( ) . unwrap ( ) ;
329
+
330
+ create_file ( & repo, "file_a" , "foo" ) ;
331
+ create_file ( & repo, "file_b" , "foo" ) ;
332
+
333
+ let mut index = repo. index ( ) . unwrap ( ) ;
334
+ index
335
+ . add_all ( [ "*" ] . iter ( ) , IndexAddOption :: DEFAULT , None )
336
+ . unwrap ( ) ;
337
+ index. write ( ) . unwrap ( ) ;
338
+
339
+ assert_eq ! ( repo. statuses( None ) . unwrap( ) . len( ) , 2 ) ;
340
+
341
+ let mut opt = StashSaveOptions :: new ( signature) ;
342
+ opt. pathspec ( "file_a" ) ;
343
+ repo. stash_save_ext ( Some ( & mut opt) ) . unwrap ( ) ;
344
+
345
+ assert_eq ! ( repo. statuses( None ) . unwrap( ) . len( ) , 0 ) ;
346
+
347
+ repo. stash_pop ( 0 , None ) . unwrap ( ) ;
348
+
349
+ assert_eq ! ( repo. statuses( None ) . unwrap( ) . len( ) , 1 ) ;
350
+ }
261
351
}
0 commit comments