diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler.ts b/src/vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler.ts index 7d04ebe6d5dce..066e0372c6be3 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler.ts @@ -9,7 +9,7 @@ import { basename, isEqual } from 'vs/base/common/resources'; import { Action } from 'vs/base/common/actions'; import { URI } from 'vs/base/common/uri'; import { FileOperationError, FileOperationResult, IWriteFileOptions } from 'vs/platform/files/common/files'; -import { ITextFileService, ISaveErrorHandler, ITextFileEditorModel, ITextFileSaveAsOptions } from 'vs/workbench/services/textfile/common/textfiles'; +import { ITextFileService, ISaveErrorHandler, ITextFileEditorModel, ITextFileSaveAsOptions, ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; @@ -99,7 +99,7 @@ export class TextFileSaveErrorHandler extends Disposable implements ISaveErrorHa } } - onSaveError(error: unknown, model: ITextFileEditorModel): void { + onSaveError(error: unknown, model: ITextFileEditorModel, options: ITextFileSaveOptions): void { const fileOperationError = error as FileOperationError; const resource = model.resource; @@ -127,7 +127,7 @@ export class TextFileSaveErrorHandler extends Disposable implements ISaveErrorHa message = localize('staleSaveError', "Failed to save '{0}': The content of the file is newer. Please compare your version with the file contents or overwrite the content of the file with your changes.", basename(resource)); primaryActions.push(this.instantiationService.createInstance(ResolveSaveConflictAction, model)); - primaryActions.push(this.instantiationService.createInstance(SaveModelIgnoreModifiedSinceAction, model)); + primaryActions.push(this.instantiationService.createInstance(SaveModelIgnoreModifiedSinceAction, model, options)); secondaryActions.push(this.instantiationService.createInstance(ConfigureSaveConflictAction)); } @@ -142,17 +142,17 @@ export class TextFileSaveErrorHandler extends Disposable implements ISaveErrorHa // Save Elevated if (canSaveElevated && (isPermissionDenied || triedToUnlock)) { - primaryActions.push(this.instantiationService.createInstance(SaveModelElevatedAction, model, !!triedToUnlock)); + primaryActions.push(this.instantiationService.createInstance(SaveModelElevatedAction, model, options, !!triedToUnlock)); } // Unlock else if (isWriteLocked) { - primaryActions.push(this.instantiationService.createInstance(UnlockModelAction, model)); + primaryActions.push(this.instantiationService.createInstance(UnlockModelAction, model, options)); } // Retry else { - primaryActions.push(this.instantiationService.createInstance(RetrySaveModelAction, model)); + primaryActions.push(this.instantiationService.createInstance(RetrySaveModelAction, model, options)); } // Save As @@ -272,6 +272,7 @@ class SaveModelElevatedAction extends Action { constructor( private model: ITextFileEditorModel, + private options: ITextFileSaveOptions, private triedToUnlock: boolean ) { super('workbench.files.action.saveModelElevated', triedToUnlock ? isWindows ? localize('overwriteElevated', "Overwrite as Admin...") : localize('overwriteElevatedSudo', "Overwrite as Sudo...") : isWindows ? localize('saveElevated', "Retry as Admin...") : localize('saveElevatedSudo', "Retry as Sudo...")); @@ -280,6 +281,7 @@ class SaveModelElevatedAction extends Action { override async run(): Promise { if (!this.model.isDisposed()) { await this.model.save({ + ...this.options, writeElevated: true, writeUnlock: this.triedToUnlock, reason: SaveReason.EXPLICIT @@ -291,14 +293,15 @@ class SaveModelElevatedAction extends Action { class RetrySaveModelAction extends Action { constructor( - private model: ITextFileEditorModel + private model: ITextFileEditorModel, + private options: ITextFileSaveOptions ) { super('workbench.files.action.saveModel', localize('retry', "Retry")); } override async run(): Promise { if (!this.model.isDisposed()) { - await this.model.save({ reason: SaveReason.EXPLICIT }); + await this.model.save({ ...this.options, reason: SaveReason.EXPLICIT }); } } } @@ -360,14 +363,15 @@ class SaveModelAsAction extends Action { class UnlockModelAction extends Action { constructor( - private model: ITextFileEditorModel + private model: ITextFileEditorModel, + private options: ITextFileSaveOptions ) { super('workbench.files.action.unlock', localize('overwrite', "Overwrite")); } override async run(): Promise { if (!this.model.isDisposed()) { - await this.model.save({ writeUnlock: true, reason: SaveReason.EXPLICIT }); + await this.model.save({ ...this.options, writeUnlock: true, reason: SaveReason.EXPLICIT }); } } } @@ -375,14 +379,15 @@ class UnlockModelAction extends Action { class SaveModelIgnoreModifiedSinceAction extends Action { constructor( - private model: ITextFileEditorModel + private model: ITextFileEditorModel, + private options: ITextFileSaveOptions ) { super('workbench.files.action.saveIgnoreModifiedSince', localize('overwrite', "Overwrite")); } override async run(): Promise { if (!this.model.isDisposed()) { - await this.model.save({ ignoreModifiedSince: true, reason: SaveReason.EXPLICIT }); + await this.model.save({ ...this.options, ignoreModifiedSince: true, reason: SaveReason.EXPLICIT }); } } } diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 4fb09ccd01506..b127ae7b7ca74 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -963,7 +963,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } // Show to user - this.textFileService.files.saveErrorHandler.onSaveError(error, this); + this.textFileService.files.saveErrorHandler.onSaveError(error, this, options); // Emit as event this._onDidSaveError.fire(); diff --git a/src/vs/workbench/services/textfile/common/textfiles.ts b/src/vs/workbench/services/textfile/common/textfiles.ts index 306bca1e19c86..d126c88df6e8f 100644 --- a/src/vs/workbench/services/textfile/common/textfiles.ts +++ b/src/vs/workbench/services/textfile/common/textfiles.ts @@ -195,7 +195,7 @@ export interface ISaveErrorHandler { /** * Called whenever a save fails. */ - onSaveError(error: Error, model: ITextFileEditorModel): void; + onSaveError(error: Error, model: ITextFileEditorModel, options: ITextFileSaveAsOptions): void; } /** diff --git a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts index 7da85b4899c64..979d47aa8ea0f 100644 --- a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts +++ b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts @@ -1100,13 +1100,13 @@ export class StoredFileWorkingCopy extend } // Show save error to user for handling - this.doHandleSaveError(error); + this.doHandleSaveError(error, options); // Emit as event this._onDidSaveError.fire(); } - private doHandleSaveError(error: Error): void { + private doHandleSaveError(error: Error, options: IStoredFileWorkingCopySaveAsOptions): void { const fileOperationError = error as FileOperationError; const primaryActions: IAction[] = []; @@ -1116,7 +1116,7 @@ export class StoredFileWorkingCopy extend if (fileOperationError.fileOperationResult === FileOperationResult.FILE_MODIFIED_SINCE) { message = localize('staleSaveError', "Failed to save '{0}': The content of the file is newer. Do you want to overwrite the file with your changes?", this.name); - primaryActions.push(toAction({ id: 'fileWorkingCopy.overwrite', label: localize('overwrite', "Overwrite"), run: () => this.save({ ignoreModifiedSince: true }) })); + primaryActions.push(toAction({ id: 'fileWorkingCopy.overwrite', label: localize('overwrite', "Overwrite"), run: () => this.save({ ...options, ignoreModifiedSince: true, reason: SaveReason.EXPLICIT }) })); primaryActions.push(toAction({ id: 'fileWorkingCopy.revert', label: localize('discard', "Discard"), run: () => this.revert() })); } @@ -1140,19 +1140,19 @@ export class StoredFileWorkingCopy extend isWindows ? localize('overwriteElevated', "Overwrite as Admin...") : localize('overwriteElevatedSudo', "Overwrite as Sudo...") : isWindows ? localize('saveElevated', "Retry as Admin...") : localize('saveElevatedSudo', "Retry as Sudo..."), run: () => { - this.save({ writeElevated: true, writeUnlock: triedToUnlock, reason: SaveReason.EXPLICIT }); + this.save({ ...options, writeElevated: true, writeUnlock: triedToUnlock, reason: SaveReason.EXPLICIT }); } })); } // Unlock else if (isWriteLocked) { - primaryActions.push(toAction({ id: 'fileWorkingCopy.unlock', label: localize('overwrite', "Overwrite"), run: () => this.save({ writeUnlock: true, reason: SaveReason.EXPLICIT }) })); + primaryActions.push(toAction({ id: 'fileWorkingCopy.unlock', label: localize('overwrite', "Overwrite"), run: () => this.save({ ...options, writeUnlock: true, reason: SaveReason.EXPLICIT }) })); } // Retry else { - primaryActions.push(toAction({ id: 'fileWorkingCopy.retry', label: localize('retry', "Retry"), run: () => this.save({ reason: SaveReason.EXPLICIT }) })); + primaryActions.push(toAction({ id: 'fileWorkingCopy.retry', label: localize('retry', "Retry"), run: () => this.save({ ...options, reason: SaveReason.EXPLICIT }) })); } // Save As @@ -1164,7 +1164,7 @@ export class StoredFileWorkingCopy extend if (editor) { const result = await this.editorService.save(editor, { saveAs: true, reason: SaveReason.EXPLICIT }); if (!result.success) { - this.doHandleSaveError(error); // show error again given the operation failed + this.doHandleSaveError(error, options); // show error again given the operation failed } } }