@@ -61,7 +61,7 @@ export default class BackportSession extends Session {
61
61
cli . stopSpinner ( `${ file } does not exist in current working tree` ,
62
62
cli . SPINNER_STATUS . WARN ) ;
63
63
continue ;
64
- } ;
64
+ }
65
65
if ( ancestors . length === 0 ) {
66
66
cli . stopSpinner ( `Cannot find ancestor commits of ${ file } ` ,
67
67
cli . SPINNER_STATUS . INFO ) ;
@@ -155,12 +155,33 @@ export default class BackportSession extends Session {
155
155
cli . log ( ` - ${ commit . sha } ${ commit . title } ` ) ;
156
156
}
157
157
158
+ if ( ! this . isLocalBranchExists ( this . stagingBranch ) ) {
159
+ const shouldCreateStagingBranch = await cli . prompt (
160
+ `It seems like ${ this . stagingBranch } is missing locally, ` +
161
+ 'do you want to create it locally to get ready for backporting?' , {
162
+ defaultAnswer : true
163
+ } ) ;
164
+
165
+ if ( shouldCreateStagingBranch ) {
166
+ this . syncBranchWithUpstream ( this . stagingBranch ) ;
167
+ }
168
+ } else if ( ! this . isBranchUpToDateWithUpstream ( this . stagingBranch ) ) {
169
+ const shouldSyncBranch = await cli . prompt (
170
+ `It seems like your ${ this . stagingBranch } is behind the ${ this . upstream } remote` +
171
+ 'do you want to sync it?' , { defaultAnswer : true } ) ;
172
+
173
+ if ( shouldSyncBranch ) {
174
+ this . syncBranchWithUpstream ( this . stagingBranch ) ;
175
+ }
176
+ }
177
+
158
178
const newBranch = `backport-${ this . prid } -to-${ this . target } ` ;
159
179
const shouldCheckout = await cli . prompt (
160
180
`Do you want to checkout to a new branch \`${ newBranch } \`` +
161
181
' to start backporting?' , { defaultAnswer : false } ) ;
182
+
162
183
if ( shouldCheckout ) {
163
- await runAsync ( 'git' , [ 'checkout' , '-b' , newBranch ] ) ;
184
+ await runAsync ( 'git' , [ 'checkout' , '-b' , newBranch , this . stagingBranch ] ) ;
164
185
}
165
186
166
187
const shouldAnalyze = await cli . prompt (
@@ -226,4 +247,56 @@ export default class BackportSession extends Session {
226
247
} ;
227
248
} ) ;
228
249
}
250
+
251
+ getCurrentBranch ( ) {
252
+ return runSync ( 'git' ,
253
+ [ 'rev-parse' , '--abbrev-ref' , 'HEAD' ]
254
+ ) . trim ( ) ;
255
+ }
256
+
257
+ updateUpstreamRefs ( branchName ) {
258
+ runSync ( 'git' ,
259
+ [ 'fetch' , this . upstream , branchName ]
260
+ ) ;
261
+ }
262
+
263
+ getBranchCommit ( branch ) {
264
+ return runSync ( 'git' ,
265
+ [ 'rev-parse' , branch ]
266
+ ) . trim ( ) ;
267
+ }
268
+
269
+ isBranchUpToDateWithUpstream ( branch ) {
270
+ this . updateUpstreamRefs ( branch ) ;
271
+
272
+ const localCommit = this . getBranchCommit ( branch ) ;
273
+ const upstreamCommit = this . getBranchCommit ( `${ this . upstream } /${ branch } ` ) ;
274
+
275
+ return localCommit === upstreamCommit ;
276
+ } ;
277
+
278
+ isLocalBranchExists ( branch ) {
279
+ try {
280
+ // will exit with code 1 if branch does not exist
281
+ runSync ( 'git' ,
282
+ [ 'rev-parse' , '--verify' , '--quiet' , branch ]
283
+ ) ;
284
+ return true ;
285
+ } catch ( e ) {
286
+ return false ;
287
+ }
288
+ }
289
+
290
+ syncBranchWithUpstream ( branch ) {
291
+ const currentBranch = this . getCurrentBranch ( ) ;
292
+
293
+ runSync ( 'git' ,
294
+ [
295
+ currentBranch !== branch ? 'fetch' : 'pull' ,
296
+ this . upstream ,
297
+ `${ branch } :${ branch } ` ,
298
+ '-f'
299
+ ]
300
+ ) ;
301
+ }
229
302
}
0 commit comments