@@ -10,7 +10,6 @@ import {autobind} from 'core-decorators';
10
10
import Switchboard from '../switchboard' ;
11
11
import FilePatchView from '../views/file-patch-view' ;
12
12
import ModelObserver from '../models/model-observer' ;
13
- import FilePatch from '../models/file-patch' ;
14
13
15
14
export default class FilePatchController extends React . Component {
16
15
static propTypes = {
@@ -134,10 +133,13 @@ export default class FilePatchController extends React.Component {
134
133
this . resolveFilePatchLoadedPromise ( ) ;
135
134
if ( ! this . destroyed ) { this . setState ( { filePatch, isPartiallyStaged} ) ; }
136
135
} else {
137
- // TODO: Prevent flicker after staging/unstaging
138
136
const oldFilePatch = this . state . filePatch ;
139
137
if ( oldFilePatch ) {
140
- filePatch = new FilePatch ( oldFilePatch . getOldPath ( ) , oldFilePatch . getNewPath ( ) , oldFilePatch . getStatus ( ) , [ ] ) ;
138
+ filePatch = oldFilePatch . clone ( {
139
+ oldFile : oldFilePatch . oldFile . clone ( { mode : null , symlink : null } ) ,
140
+ newFile : oldFilePatch . newFile . clone ( { mode : null , symlink : null } ) ,
141
+ patch : oldFilePatch . getPatch ( ) . clone ( { hunks : [ ] } ) ,
142
+ } ) ;
141
143
if ( ! this . destroyed ) { this . setState ( { filePatch, isPartiallyStaged} ) ; }
142
144
}
143
145
}
@@ -164,7 +166,18 @@ export default class FilePatchController extends React.Component {
164
166
}
165
167
166
168
render ( ) {
167
- const hunks = this . state . filePatch ? this . state . filePatch . getHunks ( ) : [ ] ;
169
+ const fp = this . state . filePatch ;
170
+ const hunks = fp ? fp . getHunks ( ) : [ ] ;
171
+ const executableModeChange = fp && fp . didChangeExecutableMode ( ) ?
172
+ { oldMode : fp . getOldMode ( ) , newMode : fp . getNewMode ( ) } :
173
+ null ;
174
+ const symlinkChange = fp && fp . hasSymlink ( ) ?
175
+ {
176
+ oldSymlink : fp . getOldSymlink ( ) ,
177
+ newSymlink : fp . getNewSymlink ( ) ,
178
+ typechange : fp . hasTypechange ( ) ,
179
+ filePatchStatus : fp . getStatus ( ) ,
180
+ } : null ;
168
181
const repository = this . repositoryObserver . getActiveModel ( ) ;
169
182
if ( repository . isUndetermined ( ) || repository . isLoading ( ) ) {
170
183
return (
@@ -193,12 +206,17 @@ export default class FilePatchController extends React.Component {
193
206
lineCount = { this . lineCount }
194
207
handleShowDiffClick = { this . handleShowDiffClick }
195
208
hunks = { hunks }
209
+ executableModeChange = { executableModeChange }
210
+ symlinkChange = { symlinkChange }
196
211
filePath = { this . props . filePath }
197
212
workingDirectoryPath = { this . getWorkingDirectory ( ) }
198
213
stagingStatus = { this . state . stagingStatus }
199
214
isPartiallyStaged = { this . state . isPartiallyStaged }
200
215
attemptLineStageOperation = { this . attemptLineStageOperation }
201
216
attemptHunkStageOperation = { this . attemptHunkStageOperation }
217
+ attemptFileStageOperation = { this . attemptFileStageOperation }
218
+ attemptModeStageOperation = { this . attemptModeStageOperation }
219
+ attemptSymlinkStageOperation = { this . attemptSymlinkStageOperation }
202
220
didSurfaceFile = { this . didSurfaceFile }
203
221
didDiveIntoCorrespondingFilePatch = { this . diveIntoCorrespondingFilePatch }
204
222
switchboard = { this . props . switchboard }
@@ -269,6 +287,98 @@ export default class FilePatchController extends React.Component {
269
287
}
270
288
}
271
289
290
+ async stageFile ( ) {
291
+ this . props . switchboard . didBeginStageOperation ( { stage : true , file : true } ) ;
292
+
293
+ await this . repositoryObserver . getActiveModel ( ) . stageFiles ( [ this . props . filePath ] ) ;
294
+ this . props . switchboard . didFinishStageOperation ( { stage : true , file : true } ) ;
295
+ }
296
+
297
+ async unstageFile ( ) {
298
+ this . props . switchboard . didBeginStageOperation ( { unstage : true , file : true } ) ;
299
+
300
+ await this . repositoryObserver . getActiveModel ( ) . unstageFiles ( [ this . props . filePath ] ) ;
301
+
302
+ this . props . switchboard . didFinishStageOperation ( { unstage : true , file : true } ) ;
303
+ }
304
+
305
+ stageOrUnstageFile ( ) {
306
+ const stagingStatus = this . state . stagingStatus ;
307
+ if ( stagingStatus === 'unstaged' ) {
308
+ return this . stageFile ( ) ;
309
+ } else if ( stagingStatus === 'staged' ) {
310
+ return this . unstageFile ( ) ;
311
+ } else {
312
+ throw new Error ( `Unknown stagingStatus: ${ stagingStatus } ` ) ;
313
+ }
314
+ }
315
+
316
+ async stageModeChange ( mode ) {
317
+ this . props . switchboard . didBeginStageOperation ( { stage : true , mode : true } ) ;
318
+
319
+ await this . repositoryObserver . getActiveModel ( ) . stageFileModeChange (
320
+ this . props . filePath , mode ,
321
+ ) ;
322
+ this . props . switchboard . didFinishStageOperation ( { stage : true , mode : true } ) ;
323
+ }
324
+
325
+ async unstageModeChange ( mode ) {
326
+ this . props . switchboard . didBeginStageOperation ( { unstage : true , mode : true } ) ;
327
+
328
+ await this . repositoryObserver . getActiveModel ( ) . stageFileModeChange (
329
+ this . props . filePath , mode ,
330
+ ) ;
331
+ this . props . switchboard . didFinishStageOperation ( { unstage : true , mode : true } ) ;
332
+ }
333
+
334
+ stageOrUnstageModeChange ( ) {
335
+ const stagingStatus = this . state . stagingStatus ;
336
+ const oldMode = this . state . filePatch . getOldMode ( ) ;
337
+ const newMode = this . state . filePatch . getNewMode ( ) ;
338
+ if ( stagingStatus === 'unstaged' ) {
339
+ return this . stageModeChange ( newMode ) ;
340
+ } else if ( stagingStatus === 'staged' ) {
341
+ return this . unstageModeChange ( oldMode ) ;
342
+ } else {
343
+ throw new Error ( `Unknown stagingStatus: ${ stagingStatus } ` ) ;
344
+ }
345
+ }
346
+
347
+ async stageSymlinkChange ( ) {
348
+ this . props . switchboard . didBeginStageOperation ( { stage : true , symlink : true } ) ;
349
+
350
+ const filePatch = this . state . filePatch ;
351
+ if ( filePatch . hasTypechange ( ) && filePatch . getStatus ( ) === 'added' ) {
352
+ await this . repositoryObserver . getActiveModel ( ) . stageFileSymlinkChange ( this . props . filePath ) ;
353
+ } else {
354
+ await this . repositoryObserver . getActiveModel ( ) . stageFiles ( [ this . props . filePath ] ) ;
355
+ }
356
+ this . props . switchboard . didFinishStageOperation ( { stage : true , symlink : true } ) ;
357
+ }
358
+
359
+ async unstageSymlinkChange ( ) {
360
+ this . props . switchboard . didBeginStageOperation ( { unstage : true , symlink : true } ) ;
361
+
362
+ const filePatch = this . state . filePatch ;
363
+ if ( filePatch . hasTypechange ( ) && filePatch . getStatus ( ) === 'deleted' ) {
364
+ await this . repositoryObserver . getActiveModel ( ) . stageFileSymlinkChange ( this . props . filePath ) ;
365
+ } else {
366
+ await this . repositoryObserver . getActiveModel ( ) . unstageFiles ( [ this . props . filePath ] ) ;
367
+ }
368
+ this . props . switchboard . didFinishStageOperation ( { unstage : true , symlink : true } ) ;
369
+ }
370
+
371
+ stageOrUnstageSymlinkChange ( ) {
372
+ const stagingStatus = this . state . stagingStatus ;
373
+ if ( stagingStatus === 'unstaged' ) {
374
+ return this . stageSymlinkChange ( ) ;
375
+ } else if ( stagingStatus === 'staged' ) {
376
+ return this . unstageSymlinkChange ( ) ;
377
+ } else {
378
+ throw new Error ( `Unknown stagingStatus: ${ stagingStatus } ` ) ;
379
+ }
380
+ }
381
+
272
382
@autobind
273
383
attemptHunkStageOperation ( hunk ) {
274
384
if ( this . stagingOperationInProgress ) {
@@ -283,6 +393,48 @@ export default class FilePatchController extends React.Component {
283
393
this . stageOrUnstageHunk ( hunk ) ;
284
394
}
285
395
396
+ @autobind
397
+ attemptFileStageOperation ( ) {
398
+ if ( this . stagingOperationInProgress ) {
399
+ return ;
400
+ }
401
+
402
+ this . stagingOperationInProgress = true ;
403
+ this . props . switchboard . getChangePatchPromise ( ) . then ( ( ) => {
404
+ this . stagingOperationInProgress = false ;
405
+ } ) ;
406
+
407
+ this . stageOrUnstageFile ( ) ;
408
+ }
409
+
410
+ @autobind
411
+ attemptModeStageOperation ( ) {
412
+ if ( this . stagingOperationInProgress ) {
413
+ return ;
414
+ }
415
+
416
+ this . stagingOperationInProgress = true ;
417
+ this . props . switchboard . getChangePatchPromise ( ) . then ( ( ) => {
418
+ this . stagingOperationInProgress = false ;
419
+ } ) ;
420
+
421
+ this . stageOrUnstageModeChange ( ) ;
422
+ }
423
+
424
+ @autobind
425
+ attemptSymlinkStageOperation ( ) {
426
+ if ( this . stagingOperationInProgress ) {
427
+ return ;
428
+ }
429
+
430
+ this . stagingOperationInProgress = true ;
431
+ this . props . switchboard . getChangePatchPromise ( ) . then ( ( ) => {
432
+ this . stagingOperationInProgress = false ;
433
+ } ) ;
434
+
435
+ this . stageOrUnstageSymlinkChange ( ) ;
436
+ }
437
+
286
438
async stageLines ( lines ) {
287
439
this . props . switchboard . didBeginStageOperation ( { stage : true , line : true } ) ;
288
440
0 commit comments