@@ -412,6 +412,16 @@ class ManualSyncTask extends Disposable implements IManualSyncTask {
412412
413413 private isDisposed : boolean = false ;
414414
415+ get status ( ) : SyncStatus {
416+ if ( this . synchronisers . some ( s => s . status === SyncStatus . HasConflicts ) ) {
417+ return SyncStatus . HasConflicts ;
418+ }
419+ if ( this . synchronisers . some ( s => s . status === SyncStatus . Syncing ) ) {
420+ return SyncStatus . Syncing ;
421+ }
422+ return SyncStatus . Idle ;
423+ }
424+
415425 constructor (
416426 readonly id : string ,
417427 readonly manifest : IUserDataManifest | null ,
@@ -429,22 +439,110 @@ class ManualSyncTask extends Disposable implements IManualSyncTask {
429439 if ( ! this . previewsPromise ) {
430440 this . previewsPromise = createCancelablePromise ( token => this . getPreviews ( token ) ) ;
431441 }
432- this . previews = await this . previewsPromise ;
442+ if ( ! this . previews ) {
443+ this . previews = await this . previewsPromise ;
444+ }
433445 return this . previews ;
434446 }
435447
436448 async accept ( resource : URI , content ?: string | null ) : Promise < [ SyncResource , ISyncResourcePreview ] [ ] > {
437449 return this . performAction ( resource , sychronizer => sychronizer . accept ( resource , content ) ) ;
438450 }
439451
440- async merge ( resource : URI ) : Promise < [ SyncResource , ISyncResourcePreview ] [ ] > {
441- return this . performAction ( resource , sychronizer => sychronizer . merge ( resource ) ) ;
452+ async merge ( resource ?: URI ) : Promise < [ SyncResource , ISyncResourcePreview ] [ ] > {
453+ if ( resource ) {
454+ return this . performAction ( resource , sychronizer => sychronizer . merge ( resource ) ) ;
455+ } else {
456+ return this . doMerge ( false ) ;
457+ }
442458 }
443459
444460 async discard ( resource : URI ) : Promise < [ SyncResource , ISyncResourcePreview ] [ ] > {
445461 return this . performAction ( resource , sychronizer => sychronizer . discard ( resource ) ) ;
446462 }
447463
464+ async discardConflicts ( ) : Promise < [ SyncResource , ISyncResourcePreview ] [ ] > {
465+ if ( ! this . previews ) {
466+ throw new Error ( 'Missing preview. Create preview and try again.' ) ;
467+ }
468+ if ( this . synchronizingResources . length ) {
469+ throw new Error ( 'Cannot discard while synchronizing resources' ) ;
470+ }
471+
472+ const conflictResources : URI [ ] = [ ] ;
473+ for ( const [ , syncResourcePreview ] of this . previews ) {
474+ for ( const resourcePreview of syncResourcePreview . resourcePreviews ) {
475+ if ( resourcePreview . mergeState === MergeState . Conflict ) {
476+ conflictResources . push ( resourcePreview . previewResource ) ;
477+ }
478+ }
479+ }
480+
481+ for ( const resource of conflictResources ) {
482+ await this . discard ( resource ) ;
483+ }
484+ return this . previews ;
485+ }
486+
487+ async apply ( ) : Promise < [ SyncResource , ISyncResourcePreview ] [ ] > {
488+ return this . doMerge ( true ) ;
489+ }
490+
491+ async pull ( ) : Promise < void > {
492+ if ( ! this . previews ) {
493+ throw new Error ( 'You need to create preview before applying' ) ;
494+ }
495+ if ( this . synchronizingResources . length ) {
496+ throw new Error ( 'Cannot pull while synchronizing resources' ) ;
497+ }
498+ for ( const [ syncResource , preview ] of this . previews ) {
499+ this . synchronizingResources . push ( [ syncResource , preview . resourcePreviews . map ( r => r . localResource ) ] ) ;
500+ this . _onSynchronizeResources . fire ( this . synchronizingResources ) ;
501+ const synchroniser = this . synchronisers . find ( s => s . resource === syncResource ) ! ;
502+ for ( const resourcePreview of preview . resourcePreviews ) {
503+ await synchroniser . accept ( resourcePreview . remoteResource ) ;
504+ }
505+ await synchroniser . apply ( true , this . syncHeaders ) ;
506+ this . synchronizingResources . splice ( this . synchronizingResources . findIndex ( s => s [ 0 ] === syncResource ) , 1 ) ;
507+ this . _onSynchronizeResources . fire ( this . synchronizingResources ) ;
508+ }
509+ this . previews = [ ] ;
510+ }
511+
512+ async push ( ) : Promise < void > {
513+ if ( ! this . previews ) {
514+ throw new Error ( 'You need to create preview before applying' ) ;
515+ }
516+ if ( this . synchronizingResources . length ) {
517+ throw new Error ( 'Cannot pull while synchronizing resources' ) ;
518+ }
519+ for ( const [ syncResource , preview ] of this . previews ) {
520+ this . synchronizingResources . push ( [ syncResource , preview . resourcePreviews . map ( r => r . localResource ) ] ) ;
521+ this . _onSynchronizeResources . fire ( this . synchronizingResources ) ;
522+ const synchroniser = this . synchronisers . find ( s => s . resource === syncResource ) ! ;
523+ for ( const resourcePreview of preview . resourcePreviews ) {
524+ await synchroniser . accept ( resourcePreview . localResource ) ;
525+ }
526+ await synchroniser . apply ( true , this . syncHeaders ) ;
527+ this . synchronizingResources . splice ( this . synchronizingResources . findIndex ( s => s [ 0 ] === syncResource ) , 1 ) ;
528+ this . _onSynchronizeResources . fire ( this . synchronizingResources ) ;
529+ }
530+ this . previews = [ ] ;
531+ }
532+
533+ async stop ( ) : Promise < void > {
534+ for ( const synchroniser of this . synchronisers ) {
535+ try {
536+ await synchroniser . stop ( ) ;
537+ } catch ( error ) {
538+ if ( ! isPromiseCanceledError ( error ) ) {
539+ this . logService . error ( error ) ;
540+ }
541+ }
542+ }
543+ this . reset ( ) ;
544+ }
545+
448546 private async performAction ( resource : URI , action : ( synchroniser : IUserDataSynchroniser ) => Promise < ISyncResourcePreview | null > ) : Promise < [ SyncResource , ISyncResourcePreview ] [ ] > {
449547 if ( ! this . previews ) {
450548 throw new Error ( 'Missing preview. Create preview and try again.' ) ;
@@ -486,12 +584,12 @@ class ManualSyncTask extends Disposable implements IManualSyncTask {
486584 return this . previews ;
487585 }
488586
489- async apply ( ) : Promise < [ SyncResource , ISyncResourcePreview ] [ ] > {
587+ private async doMerge ( apply : boolean ) : Promise < [ SyncResource , ISyncResourcePreview ] [ ] > {
490588 if ( ! this . previews ) {
491- throw new Error ( 'You need to create preview before applying' ) ;
589+ throw new Error ( 'You need to create preview before merging or applying' ) ;
492590 }
493591 if ( this . synchronizingResources . length ) {
494- throw new Error ( 'Cannot pull while synchronizing resources' ) ;
592+ throw new Error ( 'Cannot merge or apply while synchronizing resources' ) ;
495593 }
496594 const previews : [ SyncResource , ISyncResourcePreview ] [ ] = [ ] ;
497595 for ( const [ syncResource , preview ] of this . previews ) {
@@ -501,14 +599,18 @@ class ManualSyncTask extends Disposable implements IManualSyncTask {
501599 const synchroniser = this . synchronisers . find ( s => s . resource === syncResource ) ! ;
502600
503601 /* merge those which are not yet merged */
602+ let newPreview : ISyncResourcePreview | null = null ;
504603 for ( const resourcePreview of preview . resourcePreviews ) {
505604 if ( ( resourcePreview . localChange !== Change . None || resourcePreview . remoteChange !== Change . None ) && resourcePreview . mergeState === MergeState . Preview ) {
506- await synchroniser . merge ( resourcePreview . previewResource ) ;
605+ newPreview = await synchroniser . merge ( resourcePreview . previewResource ) ;
507606 }
508607 }
509608
510609 /* apply */
511- const newPreview = await synchroniser . apply ( false , this . syncHeaders ) ;
610+ if ( apply ) {
611+ newPreview = await synchroniser . apply ( false , this . syncHeaders ) ;
612+ }
613+
512614 if ( newPreview ) {
513615 previews . push ( this . toSyncResourcePreview ( synchroniser . resource , newPreview ) ) ;
514616 }
@@ -520,61 +622,6 @@ class ManualSyncTask extends Disposable implements IManualSyncTask {
520622 return this . previews ;
521623 }
522624
523- async pull ( ) : Promise < void > {
524- if ( ! this . previews ) {
525- throw new Error ( 'You need to create preview before applying' ) ;
526- }
527- if ( this . synchronizingResources . length ) {
528- throw new Error ( 'Cannot pull while synchronizing resources' ) ;
529- }
530- for ( const [ syncResource , preview ] of this . previews ) {
531- this . synchronizingResources . push ( [ syncResource , preview . resourcePreviews . map ( r => r . localResource ) ] ) ;
532- this . _onSynchronizeResources . fire ( this . synchronizingResources ) ;
533- const synchroniser = this . synchronisers . find ( s => s . resource === syncResource ) ! ;
534- for ( const resourcePreview of preview . resourcePreviews ) {
535- await synchroniser . accept ( resourcePreview . remoteResource ) ;
536- }
537- await synchroniser . apply ( true , this . syncHeaders ) ;
538- this . synchronizingResources . splice ( this . synchronizingResources . findIndex ( s => s [ 0 ] === syncResource ) , 1 ) ;
539- this . _onSynchronizeResources . fire ( this . synchronizingResources ) ;
540- }
541- this . previews = [ ] ;
542- }
543-
544- async push ( ) : Promise < void > {
545- if ( ! this . previews ) {
546- throw new Error ( 'You need to create preview before applying' ) ;
547- }
548- if ( this . synchronizingResources . length ) {
549- throw new Error ( 'Cannot pull while synchronizing resources' ) ;
550- }
551- for ( const [ syncResource , preview ] of this . previews ) {
552- this . synchronizingResources . push ( [ syncResource , preview . resourcePreviews . map ( r => r . localResource ) ] ) ;
553- this . _onSynchronizeResources . fire ( this . synchronizingResources ) ;
554- const synchroniser = this . synchronisers . find ( s => s . resource === syncResource ) ! ;
555- for ( const resourcePreview of preview . resourcePreviews ) {
556- await synchroniser . accept ( resourcePreview . localResource ) ;
557- }
558- await synchroniser . apply ( true , this . syncHeaders ) ;
559- this . synchronizingResources . splice ( this . synchronizingResources . findIndex ( s => s [ 0 ] === syncResource ) , 1 ) ;
560- this . _onSynchronizeResources . fire ( this . synchronizingResources ) ;
561- }
562- this . previews = [ ] ;
563- }
564-
565- async stop ( ) : Promise < void > {
566- for ( const synchroniser of this . synchronisers ) {
567- try {
568- await synchroniser . stop ( ) ;
569- } catch ( error ) {
570- if ( ! isPromiseCanceledError ( error ) ) {
571- this . logService . error ( error ) ;
572- }
573- }
574- }
575- this . reset ( ) ;
576- }
577-
578625 private async getPreviews ( token : CancellationToken ) : Promise < [ SyncResource , ISyncResourcePreview ] [ ] > {
579626 const result : [ SyncResource , ISyncResourcePreview ] [ ] = [ ] ;
580627 for ( const synchroniser of this . synchronisers ) {
0 commit comments