Merge branch 'filesystem_events' of https://github.com/ethereum/remix-project into flattentree

pull/5370/head
filip mertens 11 months ago
commit da262590c3
  1. 15
      apps/remix-ide/src/app/files/fileManager.ts
  2. 101
      apps/remixdesktop/src/plugins/fsPlugin.ts
  3. 2
      libs/remix-ui/run-tab/src/lib/actions/events.ts
  4. 4
      libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx
  5. 1
      libs/remix-ui/workspace/src/lib/actions/events.ts
  6. 1
      libs/remix-ui/workspace/src/lib/actions/index.ts
  7. 1
      libs/remix-ui/workspace/src/lib/reducers/workspace.ts

@ -5,7 +5,6 @@ import JSZip from 'jszip'
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json'
import {Registry} from '@remix-project/remix-lib'
import { EventEmitter } from 'events'
import { fileChangedToastMsg, recursivePasteToastMsg, storageFullMessage } from '@remix-ui/helper'
import helper from '../../lib/helper.js'
import { RemixAppManager } from '../../remixAppManager'
@ -42,7 +41,6 @@ const createError = (err) => {
class FileManager extends Plugin {
mode: string
openedFiles: any
events: EventEmitter
editor: any
_components: any
appManager: RemixAppManager
@ -56,7 +54,6 @@ class FileManager extends Plugin {
super(profile)
this.mode = 'browser'
this.openedFiles = {} // list all opened files
this.events = new EventEmitter()
this.editor = editor
this._components = {}
this._components.registry = Registry.getInstance()
@ -565,7 +562,6 @@ class FileManager extends Plugin {
}
// TODO: Only keep `this.emit` (issue#2210)
this.emit('fileRenamed', oldName, newName, isFolder)
this.events.emit('fileRenamed', oldName, newName, isFolder)
}
currentFileProvider() {
@ -583,7 +579,6 @@ class FileManager extends Plugin {
async closeAllFiles() {
// TODO: Only keep `this.emit` (issue#2210)
this.emit('filesAllClosed')
this.events.emit('filesAllClosed')
for (const file in this.openedFiles) {
await this.closeFile(file)
}
@ -595,11 +590,9 @@ class FileManager extends Plugin {
this._deps.config.set('currentFile', '')
// TODO: Only keep `this.emit` (issue#2210)
this.emit('noFileSelected')
this.events.emit('noFileSelected')
}
// TODO: Only keep `this.emit` (issue#2210)
this.emit('fileClosed', name)
this.events.emit('fileClosed', name)
}
currentPath() {
@ -703,8 +696,9 @@ class FileManager extends Plugin {
delete this.openedFiles[path]
// TODO: Only keep `this.emit` (issue#2210)
this.emit('fileRemoved', path)
this.events.emit('fileRemoved', path)
this.openFile(this._deps.config.get('currentFile'))
if (path === this._deps.config.get('currentFile')) {
this.openFile(this._deps.config.get('currentFile'))
}
}
async unselectCurrentFile() {
@ -712,13 +706,11 @@ class FileManager extends Plugin {
this._deps.config.set('currentFile', '')
// TODO: Only keep `this.emit` (issue#2210)
this.emit('noFileSelected')
this.events.emit('noFileSelected')
}
async openFile(file?: string) {
if (!file) {
this.emit('noFileSelected')
this.events.emit('noFileSelected')
} else {
file = this.normalize(file)
const resolved = this.getPathFromUrl(file)
@ -752,7 +744,6 @@ class FileManager extends Plugin {
}
// TODO: Only keep `this.emit` (issue#2210)
this.emit('currentFileChanged', file)
this.events.emit('currentFileChanged', file)
return true
}
}

@ -90,7 +90,7 @@ const clientProfile: Profile = {
}
class FSPluginClient extends ElectronBasePluginClient {
watcher: chokidar.FSWatcher
watchers: Record<string, chokidar.FSWatcher> = {}
workingDir: string = ''
trackDownStreamUpdate: Record<string, string> = {}
@ -148,13 +148,10 @@ class FSPluginClient extends ElectronBasePluginClient {
}
async rmdir(path: string): Promise<void> {
if (this.watcher) await this.watcher.close()
await fs.rm(this.fixPath(path), {
recursive: true,
})
this.emit('change', 'unlinkDir', path)
await this.watch()
}
async unlink(path: string): Promise<void> {
@ -203,59 +200,89 @@ class FSPluginClient extends ElectronBasePluginClient {
}
async watch(): Promise<void> {
if (this.watcher) this.watcher.close()
try{
this.watcher = chokidar
.watch(this.workingDir, {
this.on('filePanel' as any, 'expandPathChanged', async (paths: string[]) => {
for (let path of paths) {
if (!this.watchers[path]) {
path = this.fixPath(path)
this.watchers[path] = await this.watcherInit(path)
console.log('added watcher', path)
}
}
paths = paths.map(path => this.fixPath(path))
for (const watcher in this.watchers) {
if (watcher === this.workingDir) continue
if (!paths.includes(watcher)) {
this.watchers[watcher].close()
delete this.watchers[watcher]
console.log('removed watcher', watcher)
}
}
})
this.watchers[this.workingDir] = await this.watcherInit(this.workingDir) // root
console.log('added root watcher', this.workingDir)
} catch(e){
console.log('error watching', e)
}
}
private async watcherInit (path: string) {
const watcher = chokidar
.watch(path, {
ignorePermissionErrors: true,
ignoreInitial: true,
ignored: [
'**/.git/index.lock', // this file is created and unlinked all the time when git is running on Windows
],
depth: 20
depth: 1
})
.on('all', async (eventName, path, stats) => {
let pathWithoutPrefix = path.replace(this.workingDir, '')
pathWithoutPrefix = convertPathToPosix(pathWithoutPrefix)
if (pathWithoutPrefix.startsWith('/')) pathWithoutPrefix = pathWithoutPrefix.slice(1)
if (eventName === 'change') {
// remove workingDir from path
const newContent = await fs.readFile(path, 'utf-8')
const currentContent = this.trackDownStreamUpdate[pathWithoutPrefix]
if (currentContent !== newContent) {
try {
this.emit('change', eventName, pathWithoutPrefix)
} catch (e) {
console.log('error emitting change', e)
}
}
} else {
try {
this.emit('change', eventName, pathWithoutPrefix)
} catch (e) {
console.log('error emitting change', e)
}
}
this.watcherExec(eventName, path)
})
.on('error', error => {
this.watcher.close()
watcher.close()
if(error.message.includes('ENOSPC')) {
this.emit('error', 'ENOSPC')
}
console.log(`Watcher error: ${error}`)
})
}catch(e){
console.log('error watching', e)
return watcher
}
private async watcherExec (eventName: string, path: string) {
let pathWithoutPrefix = path.replace(this.workingDir, '')
pathWithoutPrefix = convertPathToPosix(pathWithoutPrefix)
if (pathWithoutPrefix.startsWith('/')) pathWithoutPrefix = pathWithoutPrefix.slice(1)
if (eventName === 'change') {
// remove workingDir from path
const newContent = await fs.readFile(path, 'utf-8')
const currentContent = this.trackDownStreamUpdate[pathWithoutPrefix]
if (currentContent !== newContent) {
try {
console.log('emitting', eventName, pathWithoutPrefix)
this.emit('change', eventName, pathWithoutPrefix)
} catch (e) {
console.log('error emitting change', e)
}
}
} else {
try {
console.log('emitting', eventName, pathWithoutPrefix)
this.emit('change', eventName, pathWithoutPrefix)
} catch (e) {
console.log('error emitting change', e)
}
}
}
async closeWatch(): Promise<void> {
if (this.watcher) this.watcher.close()
for (const watcher in this.watchers) {
this.watchers[watcher].close()
}
}
async updateRecentFolders(path: string): Promise<void> {

@ -104,7 +104,7 @@ export const setupEvents = (plugin: RunTab, dispatch: React.Dispatch<any>) => {
}
})
plugin.fileManager.events.on('currentFileChanged', (currentFile: string) => {
plugin.on('fileManager', 'currentFileChanged', (currentFile: string) => {
if (/.(.abi)$/.exec(currentFile)) {
dispatch(setLoadType('abi'))
} else if (/.(.sol)$/.exec(currentFile) ||

@ -175,10 +175,10 @@ export const SolidityUnitTesting = (props: Record<string, any>) => {
return tmp ? tmp[1] : version
}
testTab.fileManager.events.on('noFileSelected', async () => {
testTab.on('fileManager', 'noFileSelected', async () => {
await updateForNewCurrent()
})
testTab.fileManager.events.on('currentFileChanged', async (file: string) => {
testTab.on('fileManager', 'currentFileChanged', async (file: string) => {
await updateForNewCurrent(file)
})
testTab.on('solidity', 'compilerLoaded', async (version: string, license: string) => {

@ -220,6 +220,7 @@ const fileRemoved = async (removePath: string) => {
const fileRenamed = async (oldPath: string) => {
const provider = plugin.fileManager.currentFileProvider()
const path = extractParentFromKey(oldPath) || ROOT_PATH
const promise: Promise<FileTree> = new Promise((resolve) => {
provider.resolveDirectory(path, (error, fileTree: FileTree) => {
if (error) console.error(error)

@ -378,6 +378,7 @@ export const handleClickFile = async (path: string, type: 'file' | 'folder' | 'g
}
export const handleExpandPath = (paths: string[]) => {
plugin.emit('expandPathChanged', paths)
dispatch(setExpandPath(paths))
}

@ -331,7 +331,6 @@ export const browserReducer = (state = browserInitialState, action: Actions) =>
case 'FILE_ADDED_SUCCESS': {
const payload = action.payload
return {
...state,
browser: {

Loading…
Cancel
Save