@@ -11,20 +11,20 @@ use super::CommitId;
11
11
fn rebase_branch_repo (
12
12
repo : & Repository ,
13
13
branch_name : & str ,
14
- ) -> Result < CommitId > {
14
+ ) -> Result < RebaseState > {
15
15
let branch = repo. find_branch ( branch_name, BranchType :: Local ) ?;
16
16
17
17
let annotated =
18
18
repo. reference_to_annotated_commit ( & branch. into_reference ( ) ) ?;
19
19
20
- conflict_free_rebase ( repo, & annotated)
20
+ rebase ( repo, & annotated)
21
21
}
22
22
23
23
///
24
24
pub fn rebase_branch (
25
25
repo_path : & str ,
26
26
branch : & str ,
27
- ) -> Result < CommitId > {
27
+ ) -> Result < RebaseState > {
28
28
scope_time ! ( "rebase_branch" ) ;
29
29
30
30
let repo = utils:: repo ( repo_path) ?;
@@ -67,16 +67,85 @@ pub fn conflict_free_rebase(
67
67
} )
68
68
}
69
69
70
- #[ cfg( test) ]
71
- mod tests {
72
- use crate :: sync:: {
73
- checkout_branch, create_branch,
74
- rebase:: rebase_branch,
75
- repo_state,
76
- tests:: { repo_init, write_commit_file} ,
77
- CommitId , RepoState ,
70
+ ///
71
+ #[ derive( PartialEq , Debug ) ]
72
+ pub enum RebaseState {
73
+ ///
74
+ Finished ,
75
+ ///
76
+ Conflicted ,
77
+ }
78
+
79
+ /// rebase
80
+ #[ allow( dead_code) ]
81
+ fn rebase (
82
+ repo : & git2:: Repository ,
83
+ commit : & git2:: AnnotatedCommit ,
84
+ ) -> Result < RebaseState > {
85
+ let mut rebase = repo. rebase ( None , Some ( commit) , None , None ) ?;
86
+ let signature =
87
+ crate :: sync:: commit:: signature_allow_undefined_name ( repo) ?;
88
+
89
+ while let Some ( op) = rebase. next ( ) {
90
+ let _op = op?;
91
+ // dbg!(op.id());
92
+
93
+ if repo. index ( ) ?. has_conflicts ( ) {
94
+ return Ok ( RebaseState :: Conflicted ) ;
95
+ }
96
+
97
+ rebase. commit ( None , & signature, None ) ?;
98
+ }
99
+
100
+ if repo. index ( ) ?. has_conflicts ( ) {
101
+ return Ok ( RebaseState :: Conflicted ) ;
102
+ }
103
+
104
+ rebase. finish ( Some ( & signature) ) ?;
105
+
106
+ Ok ( RebaseState :: Finished )
107
+ }
108
+
109
+ ///
110
+ #[ derive( PartialEq , Debug ) ]
111
+ pub struct RebaseProgress {
112
+ ///
113
+ pub steps : usize ,
114
+ ///
115
+ pub current : usize ,
116
+ }
117
+
118
+ ///
119
+ #[ allow( dead_code) ]
120
+ pub fn get_rebase_progress (
121
+ repo : & git2:: Repository ,
122
+ ) -> Result < RebaseProgress > {
123
+ let mut rebase = repo. open_rebase ( None ) ?;
124
+
125
+ let progress = RebaseProgress {
126
+ steps : rebase. len ( ) ,
127
+ current : rebase. operation_current ( ) . unwrap_or_default ( ) ,
78
128
} ;
79
- use git2:: Repository ;
129
+
130
+ Ok ( progress)
131
+ }
132
+
133
+ ///
134
+ #[ allow( dead_code) ]
135
+ pub fn abort_rebase ( repo : & git2:: Repository ) -> Result < ( ) > {
136
+ let mut rebase = repo. open_rebase ( None ) ?;
137
+
138
+ rebase. abort ( ) ?;
139
+
140
+ Ok ( ( ) )
141
+ }
142
+
143
+ #[ cfg( test) ]
144
+ mod test_conflict_free_rebase {
145
+ use crate :: sync:: { CommitId , RepoState , checkout_branch, create_branch, rebase:: { RebaseState , rebase_branch} , repo_state, tests:: { repo_init, write_commit_file} , utils} ;
146
+ use git2:: { BranchType , Repository } ;
147
+
148
+ use super :: conflict_free_rebase;
80
149
81
150
fn parent_ids ( repo : & Repository , c : CommitId ) -> Vec < CommitId > {
82
151
let foo = repo
@@ -89,6 +158,23 @@ mod tests {
89
158
foo
90
159
}
91
160
161
+ ///
162
+ fn test_rebase_branch_repo (
163
+ repo_path : & str ,
164
+ branch_name : & str ,
165
+ ) -> CommitId {
166
+ let repo = utils:: repo ( repo_path) . unwrap ( ) ;
167
+
168
+ let branch =
169
+ repo. find_branch ( branch_name, BranchType :: Local ) . unwrap ( ) ;
170
+
171
+ let annotated = repo
172
+ . reference_to_annotated_commit ( & branch. into_reference ( ) )
173
+ . unwrap ( ) ;
174
+
175
+ conflict_free_rebase ( & repo, & annotated) . unwrap ( )
176
+ }
177
+
92
178
#[ test]
93
179
fn test_smoke ( ) {
94
180
let ( _td, repo) = repo_init ( ) . unwrap ( ) ;
@@ -112,7 +198,7 @@ mod tests {
112
198
113
199
checkout_branch ( repo_path, "refs/heads/foo" ) . unwrap ( ) ;
114
200
115
- let r = rebase_branch ( repo_path, "master" ) . unwrap ( ) ;
201
+ let r = test_rebase_branch_repo ( repo_path, "master" ) ;
116
202
117
203
assert_eq ! ( parent_ids( & repo, r) , vec![ c3] ) ;
118
204
}
@@ -137,7 +223,62 @@ mod tests {
137
223
138
224
let res = rebase_branch ( repo_path, "master" ) ;
139
225
140
- assert ! ( res. is_err( ) ) ;
226
+ assert ! ( matches!( res. unwrap( ) , RebaseState :: Conflicted ) ) ;
227
+
228
+ assert_eq ! ( repo_state( repo_path) . unwrap( ) , RepoState :: Rebase ) ;
229
+ }
230
+ }
231
+
232
+ #[ cfg( test) ]
233
+ mod test_rebase {
234
+ use crate :: sync:: {
235
+ checkout_branch, create_branch,
236
+ rebase:: {
237
+ abort_rebase, get_rebase_progress, RebaseProgress ,
238
+ RebaseState ,
239
+ } ,
240
+ rebase_branch, repo_state,
241
+ tests:: { repo_init, write_commit_file} ,
242
+ RepoState ,
243
+ } ;
244
+
245
+ #[ test]
246
+ fn test_conflicted_abort ( ) {
247
+ let ( _td, repo) = repo_init ( ) . unwrap ( ) ;
248
+ let root = repo. path ( ) . parent ( ) . unwrap ( ) ;
249
+ let repo_path = root. as_os_str ( ) . to_str ( ) . unwrap ( ) ;
250
+
251
+ write_commit_file ( & repo, "test.txt" , "test1" , "commit1" ) ;
252
+
253
+ create_branch ( repo_path, "foo" ) . unwrap ( ) ;
254
+
255
+ write_commit_file ( & repo, "test.txt" , "test2" , "commit2" ) ;
256
+
257
+ checkout_branch ( repo_path, "refs/heads/master" ) . unwrap ( ) ;
258
+
259
+ write_commit_file ( & repo, "test.txt" , "test3" , "commit3" ) ;
260
+
261
+ checkout_branch ( repo_path, "refs/heads/foo" ) . unwrap ( ) ;
262
+
263
+ assert ! ( get_rebase_progress( & repo) . is_err( ) ) ;
264
+
265
+ // rebase
266
+
267
+ let r = rebase_branch ( repo_path, "master" ) . unwrap ( ) ;
268
+
269
+ assert_eq ! ( r, RebaseState :: Conflicted ) ;
270
+ assert_eq ! ( repo_state( repo_path) . unwrap( ) , RepoState :: Rebase ) ;
271
+ assert_eq ! (
272
+ get_rebase_progress( & repo) . unwrap( ) ,
273
+ RebaseProgress {
274
+ current: 0 ,
275
+ steps: 1
276
+ }
277
+ ) ;
278
+
279
+ // abort
280
+
281
+ abort_rebase ( & repo) . unwrap ( ) ;
141
282
142
283
assert_eq ! ( repo_state( repo_path) . unwrap( ) , RepoState :: Clean ) ;
143
284
}
0 commit comments