@@ -382,8 +382,73 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
382382 ) ;
383383 }
384384
385- public rename ( oldUri : vscode . Uri , newUri : vscode . Uri , options : { overwrite : boolean } ) : void | Thenable < void > {
386- throw new Error ( "Move / rename is not supported on server" ) ;
385+ public async rename ( oldUri : vscode . Uri , newUri : vscode . Uri , options : { overwrite : boolean } ) : Promise < void > {
386+ if ( ! oldUri . path . includes ( "." ) ) {
387+ throw vscode . FileSystemError . NoPermissions ( "Cannot rename a package/folder" ) ;
388+ }
389+ if ( oldUri . path . split ( "." ) . pop ( ) . toLowerCase ( ) != newUri . path . split ( "." ) . pop ( ) . toLowerCase ( ) ) {
390+ throw vscode . FileSystemError . NoPermissions ( "Cannot change a file's extension during rename" ) ;
391+ }
392+ if ( vscode . workspace . getWorkspaceFolder ( oldUri ) != vscode . workspace . getWorkspaceFolder ( newUri ) ) {
393+ throw vscode . FileSystemError . NoPermissions ( "Cannot rename a file across workspace folders" ) ;
394+ }
395+ // Check if the destination exists
396+ let newFileStat : vscode . FileStat ;
397+ try {
398+ newFileStat = await vscode . workspace . fs . stat ( newUri ) ;
399+ if ( ! options . overwrite ) {
400+ // If it does and we can't overwrite it, throw an error
401+ throw vscode . FileSystemError . FileExists ( newUri ) ;
402+ }
403+ } catch ( error ) {
404+ if ( error instanceof vscode . FileSystemError && error . code == "FileExists" ) {
405+ // Re-throw the FileExists error
406+ throw error ;
407+ }
408+ }
409+ // Get the name of the new file
410+ const newParams = new URLSearchParams ( newUri . query ) ;
411+ const newCsp = newParams . has ( "csp" ) && [ "" , "1" ] . includes ( newParams . get ( "csp" ) ) ;
412+ const newFileName = newCsp ? newUri . path : newUri . path . slice ( 1 ) . replace ( / \/ / g, "." ) ;
413+ // Generate content for the new file
414+ const newContent = generateFileContent ( newFileName , Buffer . from ( await vscode . workspace . fs . readFile ( oldUri ) ) ) ;
415+ if ( newFileStat ) {
416+ // We're overwriting an existing file so prompt the user to check it out
417+ await fireOtherStudioAction ( OtherStudioAction . AttemptedEdit , newUri ) ;
418+ }
419+ // Write the new file
420+ // This is going to attempt the write regardless of the user's response to the check out prompt
421+ const api = new AtelierAPI ( oldUri ) ;
422+ await api
423+ . putDoc (
424+ newFileName ,
425+ {
426+ ...newContent ,
427+ mtime : Date . now ( ) ,
428+ } ,
429+ true
430+ )
431+ . catch ( ( error ) => {
432+ // Throw all failures
433+ if ( error . errorText && error . errorText !== "" ) {
434+ throw vscode . FileSystemError . Unavailable ( error . errorText ) ;
435+ }
436+ throw vscode . FileSystemError . Unavailable ( error . message ) ;
437+ } )
438+ . then ( ( response ) => {
439+ // New file has been written
440+ if ( newFileStat != undefined && response && response . result . ext && response . result . ext [ 0 ] ) {
441+ // We created a file
442+ fireOtherStudioAction ( OtherStudioAction . CreatedNewDocument , newUri , response . result . ext [ 0 ] ) ;
443+ fireOtherStudioAction ( OtherStudioAction . FirstTimeDocumentSave , newUri , response . result . ext [ 1 ] ) ;
444+ }
445+ // Sanity check that we find it there, then make client side update things
446+ this . _lookupAsFile ( newUri ) . then ( ( ) => {
447+ this . _fireSoon ( { type : vscode . FileChangeType . Changed , uri : newUri } ) ;
448+ } ) ;
449+ } ) ;
450+ // Delete the old file
451+ await vscode . workspace . fs . delete ( oldUri ) ;
387452 }
388453
389454 public watch ( uri : vscode . Uri ) : vscode . Disposable {
0 commit comments