@@ -15,6 +15,7 @@ import { IWorkingCopyService, IWorkingCopy } from 'vs/workbench/services/working
1515import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity' ;
1616import { IProgress , IProgressStep } from 'vs/platform/progress/common/progress' ;
1717import { WorkingCopyFileOperationParticipant } from 'vs/workbench/services/workingCopy/common/workingCopyFileOperationParticipant' ;
18+ import { VSBuffer } from 'vs/base/common/buffer' ;
1819
1920export const IWorkingCopyFileService = createDecorator < IWorkingCopyFileService > ( 'workingCopyFileService' ) ;
2021
@@ -128,14 +129,22 @@ export interface IWorkingCopyFileService {
128129
129130 //#region File operations
130131
132+ /**
133+ * Will create a resource with the provided optional contents, optionally overwriting any target.
134+ *
135+ * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
136+ * `onDidRunWorkingCopyFileOperation` events to participate.
137+ */
138+ create ( resource : URI , contents ?: VSBuffer , options ?: { overwrite ?: boolean } ) : Promise < void > ;
139+
131140 /**
132141 * Will move working copies matching the provided resources and corresponding children
133142 * to the target resources using the associated file service for those resources.
134143 *
135144 * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
136145 * `onDidRunWorkingCopyFileOperation` events to participate.
137146 */
138- move ( files : Required < SourceTargetPair > [ ] , overwrite ?: boolean ) : Promise < IFileStatWithMetadata [ ] > ;
147+ move ( files : Required < SourceTargetPair > [ ] , options ?: { overwrite ?: boolean } ) : Promise < IFileStatWithMetadata [ ] > ;
139148
140149 /**
141150 * Will copy working copies matching the provided resources and corresponding children
@@ -144,7 +153,7 @@ export interface IWorkingCopyFileService {
144153 * Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
145154 * `onDidRunWorkingCopyFileOperation` events to participate.
146155 */
147- copy ( files : Required < SourceTargetPair > [ ] , overwrite ?: boolean ) : Promise < IFileStatWithMetadata [ ] > ;
156+ copy ( files : Required < SourceTargetPair > [ ] , options ?: { overwrite ?: boolean } ) : Promise < IFileStatWithMetadata [ ] > ;
148157
149158 /**
150159 * Will delete working copies matching the provided resources and children
@@ -219,17 +228,49 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
219228 } ) ;
220229 }
221230
231+
222232 //#region File operations
223233
224- async move ( files : Required < SourceTargetPair > [ ] , overwrite ?: boolean ) : Promise < IFileStatWithMetadata [ ] > {
225- return this . doMoveOrCopy ( files , true , overwrite ) ;
234+ async create ( resource : URI , contents ?: VSBuffer , options ?: { overwrite ?: boolean } ) : Promise < void > {
235+
236+ // validate create operation before starting
237+ const validateCreate = await this . fileService . canCreateFile ( resource , options ) ;
238+ if ( validateCreate instanceof Error ) {
239+ throw validateCreate ;
240+ }
241+
242+ // file operation participant
243+ await this . runFileOperationParticipants ( [ { target : resource } ] , FileOperation . CREATE ) ;
244+
245+ // before events
246+ const event = { correlationId : this . correlationIds ++ , operation : FileOperation . CREATE , files : [ { target : resource } ] } ;
247+ await this . _onWillRunWorkingCopyFileOperation . fireAsync ( event , CancellationToken . None ) ;
248+
249+ // now actually create on disk
250+ try {
251+ await this . fileService . createFile ( resource , contents , { overwrite : options ?. overwrite } ) ;
252+ } catch ( error ) {
253+
254+ // error event
255+ await this . _onDidFailWorkingCopyFileOperation . fireAsync ( event , CancellationToken . None ) ;
256+
257+ throw error ;
258+ }
259+
260+ // after event
261+ await this . _onDidRunWorkingCopyFileOperation . fireAsync ( event , CancellationToken . None ) ;
262+ }
263+
264+ async move ( files : Required < SourceTargetPair > [ ] , options ?: { overwrite ?: boolean } ) : Promise < IFileStatWithMetadata [ ] > {
265+ return this . doMoveOrCopy ( files , true , options ) ;
226266 }
227267
228- async copy ( files : Required < SourceTargetPair > [ ] , overwrite ?: boolean ) : Promise < IFileStatWithMetadata [ ] > {
229- return this . doMoveOrCopy ( files , false , overwrite ) ;
268+ async copy ( files : Required < SourceTargetPair > [ ] , options ?: { overwrite ?: boolean } ) : Promise < IFileStatWithMetadata [ ] > {
269+ return this . doMoveOrCopy ( files , false , options ) ;
230270 }
231271
232- private async doMoveOrCopy ( files : Required < SourceTargetPair > [ ] , move : boolean , overwrite ?: boolean ) : Promise < IFileStatWithMetadata [ ] > {
272+ private async doMoveOrCopy ( files : Required < SourceTargetPair > [ ] , move : boolean , options ?: { overwrite ?: boolean } ) : Promise < IFileStatWithMetadata [ ] > {
273+ const overwrite = options ?. overwrite ;
233274 const stats : IFileStatWithMetadata [ ] = [ ] ;
234275
235276 // validate move/copy operation before starting
@@ -250,7 +291,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
250291 try {
251292 for ( const { source, target } of files ) {
252293
253- // If source and target are not equal, handle dirty working copies
294+ // if source and target are not equal, handle dirty working copies
254295 // depending on the operation:
255296 // - move: revert both source and target (if any)
256297 // - copy: revert target (if any)
@@ -298,15 +339,15 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
298339 const event = { correlationId : this . correlationIds ++ , operation : FileOperation . DELETE , files } ;
299340 await this . _onWillRunWorkingCopyFileOperation . fireAsync ( event , CancellationToken . None ) ;
300341
301- // Check for any existing dirty working copies for the resource
342+ // check for any existing dirty working copies for the resource
302343 // and do a soft revert before deleting to be able to close
303344 // any opened editor with these working copies
304345 for ( const resource of resources ) {
305346 const dirtyWorkingCopies = this . getDirty ( resource ) ;
306347 await Promise . all ( dirtyWorkingCopies . map ( dirtyWorkingCopy => dirtyWorkingCopy . revert ( { soft : true } ) ) ) ;
307348 }
308349
309- // Now actually delete from disk
350+ // now actually delete from disk
310351 try {
311352 for ( const resource of resources ) {
312353 await this . fileService . del ( resource , options ) ;
0 commit comments