FileSystemWorkspaceBinding.js 9.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. export default class FileSystemWorkspaceBinding{constructor(isolatedFileSystemManager,workspace){this._isolatedFileSystemManager=isolatedFileSystemManager;this._workspace=workspace;this._eventListeners=[this._isolatedFileSystemManager.addEventListener(Persistence.IsolatedFileSystemManager.Events.FileSystemAdded,this._onFileSystemAdded,this),this._isolatedFileSystemManager.addEventListener(Persistence.IsolatedFileSystemManager.Events.FileSystemRemoved,this._onFileSystemRemoved,this),this._isolatedFileSystemManager.addEventListener(Persistence.IsolatedFileSystemManager.Events.FileSystemFilesChanged,this._fileSystemFilesChanged,this)];this._boundFileSystems=new Map();this._isolatedFileSystemManager.waitForFileSystems().then(this._onFileSystemsLoaded.bind(this));}
  2. static projectId(fileSystemPath){return fileSystemPath;}
  3. static relativePath(uiSourceCode){const baseURL=(uiSourceCode.project())._fileSystemBaseURL;return uiSourceCode.url().substring(baseURL.length).split('/');}
  4. static tooltipForUISourceCode(uiSourceCode){const fileSystem=(uiSourceCode.project())._fileSystem;return fileSystem.tooltipForURL(uiSourceCode.url());}
  5. static fileSystemType(project){const fileSystem=(project)._fileSystem;return fileSystem.type();}
  6. static fileSystemSupportsAutomapping(project){const fileSystem=(project)._fileSystem;return fileSystem.supportsAutomapping();}
  7. static completeURL(project,relativePath){const fsProject=(project);return fsProject._fileSystemBaseURL+relativePath;}
  8. static fileSystemPath(projectId){return projectId;}
  9. fileSystemManager(){return this._isolatedFileSystemManager;}
  10. _onFileSystemsLoaded(fileSystems){for(const fileSystem of fileSystems){this._addFileSystem(fileSystem);}}
  11. _onFileSystemAdded(event){const fileSystem=(event.data);this._addFileSystem(fileSystem);}
  12. _addFileSystem(fileSystem){const boundFileSystem=new FileSystem(this,fileSystem,this._workspace);this._boundFileSystems.set(fileSystem.path(),boundFileSystem);}
  13. _onFileSystemRemoved(event){const fileSystem=(event.data);const boundFileSystem=this._boundFileSystems.get(fileSystem.path());boundFileSystem.dispose();this._boundFileSystems.remove(fileSystem.path());}
  14. _fileSystemFilesChanged(event){const paths=(event.data);for(const fileSystemPath of paths.changed.keysArray()){const fileSystem=this._boundFileSystems.get(fileSystemPath);if(!fileSystem){continue;}
  15. paths.changed.get(fileSystemPath).forEach(path=>fileSystem._fileChanged(path));}
  16. for(const fileSystemPath of paths.added.keysArray()){const fileSystem=this._boundFileSystems.get(fileSystemPath);if(!fileSystem){continue;}
  17. paths.added.get(fileSystemPath).forEach(path=>fileSystem._fileChanged(path));}
  18. for(const fileSystemPath of paths.removed.keysArray()){const fileSystem=this._boundFileSystems.get(fileSystemPath);if(!fileSystem){continue;}
  19. paths.removed.get(fileSystemPath).forEach(path=>fileSystem.removeUISourceCode(path));}}
  20. dispose(){Common.EventTarget.removeEventListeners(this._eventListeners);for(const fileSystem of this._boundFileSystems.values()){fileSystem.dispose();this._boundFileSystems.remove(fileSystem._fileSystem.path());}}}
  21. export class FileSystem extends Workspace.ProjectStore{constructor(fileSystemWorkspaceBinding,isolatedFileSystem,workspace){const fileSystemPath=isolatedFileSystem.path();const id=FileSystemWorkspaceBinding.projectId(fileSystemPath);console.assert(!workspace.project(id));const displayName=fileSystemPath.substr(fileSystemPath.lastIndexOf('/')+1);super(workspace,id,Workspace.projectTypes.FileSystem,displayName);this._fileSystem=isolatedFileSystem;this._fileSystemBaseURL=this._fileSystem.path()+'/';this._fileSystemParentURL=this._fileSystemBaseURL.substr(0,fileSystemPath.lastIndexOf('/')+1);this._fileSystemWorkspaceBinding=fileSystemWorkspaceBinding;this._fileSystemPath=fileSystemPath;this._creatingFilesGuard=new Set();workspace.addProject(this);this.populate();}
  22. fileSystemPath(){return this._fileSystemPath;}
  23. mimeType(uiSourceCode){return this._fileSystem.mimeFromPath(uiSourceCode.url());}
  24. initialGitFolders(){return this._fileSystem.initialGitFolders().map(folder=>this._fileSystemPath+'/'+folder);}
  25. _filePathForUISourceCode(uiSourceCode){return uiSourceCode.url().substring(this._fileSystemPath.length);}
  26. isServiceProject(){return false;}
  27. requestMetadata(uiSourceCode){if(uiSourceCode[_metadata]){return uiSourceCode[_metadata];}
  28. const relativePath=this._filePathForUISourceCode(uiSourceCode);const promise=this._fileSystem.getMetadata(relativePath).then(onMetadata);uiSourceCode[_metadata]=promise;return promise;function onMetadata(metadata){if(!metadata){return null;}
  29. return new Workspace.UISourceCodeMetadata(metadata.modificationTime,metadata.size);}}
  30. requestFileBlob(uiSourceCode){return this._fileSystem.requestFileBlob(this._filePathForUISourceCode(uiSourceCode));}
  31. requestFileContent(uiSourceCode){const filePath=this._filePathForUISourceCode(uiSourceCode);return this._fileSystem.requestFileContent(filePath);}
  32. canSetFileContent(){return true;}
  33. async setFileContent(uiSourceCode,newContent,isBase64){const filePath=this._filePathForUISourceCode(uiSourceCode);await this._fileSystem.setFileContent(filePath,newContent,isBase64);}
  34. fullDisplayName(uiSourceCode){const baseURL=(uiSourceCode.project())._fileSystemParentURL;return uiSourceCode.url().substring(baseURL.length);}
  35. canRename(){return true;}
  36. rename(uiSourceCode,newName,callback){if(newName===uiSourceCode.name()){callback(true,uiSourceCode.name(),uiSourceCode.url(),uiSourceCode.contentType());return;}
  37. let filePath=this._filePathForUISourceCode(uiSourceCode);this._fileSystem.renameFile(filePath,newName,innerCallback.bind(this));function innerCallback(success,newName){if(!success||!newName){callback(false,newName);return;}
  38. console.assert(newName);const slash=filePath.lastIndexOf('/');const parentPath=filePath.substring(0,slash);filePath=parentPath+'/'+newName;filePath=filePath.substr(1);const newURL=this._fileSystemBaseURL+filePath;const newContentType=this._fileSystem.contentType(newName);this.renameUISourceCode(uiSourceCode,newName);callback(true,newName,newURL,newContentType);}}
  39. async searchInFileContent(uiSourceCode,query,caseSensitive,isRegex){const filePath=this._filePathForUISourceCode(uiSourceCode);const{content}=await this._fileSystem.requestFileContent(filePath);if(content){return Common.ContentProvider.performSearchInContent(content,query,caseSensitive,isRegex);}
  40. return[];}
  41. async findFilesMatchingSearchRequest(searchConfig,filesMathingFileQuery,progress){let result=filesMathingFileQuery;const queriesToRun=searchConfig.queries().slice();if(!queriesToRun.length){queriesToRun.push('');}
  42. progress.setTotalWork(queriesToRun.length);for(const query of queriesToRun){const files=await this._fileSystem.searchInPath(searchConfig.isRegex()?'':query,progress);result=result.intersectOrdered(files.sort(),String.naturalOrderComparator);progress.worked(1);}
  43. progress.done();return result;}
  44. indexContent(progress){this._fileSystem.indexContent(progress);}
  45. populate(){const chunkSize=1000;const filePaths=this._fileSystem.initialFilePaths();reportFileChunk.call(this,0);function reportFileChunk(from){const to=Math.min(from+chunkSize,filePaths.length);for(let i=from;i<to;++i){this._addFile(filePaths[i]);}
  46. if(to<filePaths.length){setTimeout(reportFileChunk.bind(this,to),100);}}}
  47. excludeFolder(url){let relativeFolder=url.substring(this._fileSystemBaseURL.length);if(!relativeFolder.startsWith('/')){relativeFolder='/'+relativeFolder;}
  48. if(!relativeFolder.endsWith('/')){relativeFolder+='/';}
  49. this._fileSystem.addExcludedFolder(relativeFolder);const uiSourceCodes=this.uiSourceCodes().slice();for(let i=0;i<uiSourceCodes.length;++i){const uiSourceCode=uiSourceCodes[i];if(uiSourceCode.url().startsWith(url)){this.removeUISourceCode(uiSourceCode.url());}}}
  50. canExcludeFolder(path){return this._fileSystem.canExcludeFolder(path);}
  51. canCreateFile(){return true;}
  52. async createFile(path,name,content,isBase64){const guardFileName=this._fileSystemPath+path+(!path.endsWith('/')?'/':'')+name;this._creatingFilesGuard.add(guardFileName);const filePath=await this._fileSystem.createFile(path,name);if(!filePath){return null;}
  53. const uiSourceCode=this._addFile(filePath);uiSourceCode.setContent(content,!!isBase64);this._creatingFilesGuard.delete(guardFileName);return uiSourceCode;}
  54. deleteFile(uiSourceCode){const relativePath=this._filePathForUISourceCode(uiSourceCode);this._fileSystem.deleteFile(relativePath).then(success=>{if(success){this.removeUISourceCode(uiSourceCode.url());}});}
  55. remove(){this._fileSystemWorkspaceBinding._isolatedFileSystemManager.removeFileSystem(this._fileSystem);}
  56. _addFile(filePath){const contentType=this._fileSystem.contentType(filePath);const uiSourceCode=this.createUISourceCode(this._fileSystemBaseURL+filePath,contentType);this.addUISourceCode(uiSourceCode);return uiSourceCode;}
  57. _fileChanged(path){if(this._creatingFilesGuard.has(path)){return;}
  58. const uiSourceCode=this.uiSourceCodeForURL(path);if(!uiSourceCode){const contentType=this._fileSystem.contentType(path);this.addUISourceCode(this.createUISourceCode(path,contentType));return;}
  59. uiSourceCode[_metadata]=null;uiSourceCode.checkContentUpdated();}
  60. tooltipForURL(url){return this._fileSystem.tooltipForURL(url);}
  61. dispose(){this.removeProject();}}
  62. const _metadata=Symbol('FileSystemWorkspaceBinding.Metadata');self.Persistence=self.Persistence||{};Persistence=Persistence||{};Persistence.FileSystemWorkspaceBinding=FileSystemWorkspaceBinding;Persistence.FileSystemWorkspaceBinding.FileSystem=FileSystem;