Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/remix-ide/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// get the file list from the parent iframe
loadFileFromParent(fileManager)

migrateToWorkspace(fileManager)
migrateToWorkspace(fileManager, filePanel)

if (params.embed) framingService.embed()
}
29 changes: 15 additions & 14 deletions apps/remix-ide/src/app/files/fileManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ class FileManager extends Plugin {
this.mode = mode
}

limitPluginScope (path) {
return path.replace(/^\/browser\//, '').replace(/^browser\//, '') // forbids plugin to access the root filesystem
}

/**
* Emit error if path doesn't exist
* @param {string} path path of the file/directory
Expand Down Expand Up @@ -110,6 +114,7 @@ class FileManager extends Plugin {
* @returns {boolean} true if the path exists
*/
exists (path) {
path = this.limitPluginScope(path)
const provider = this.fileProviderOf(path)
const result = provider.exists(path, (err, result) => {
if (err) return false
Expand Down Expand Up @@ -149,6 +154,7 @@ class FileManager extends Plugin {
* @returns {void}
*/
async open (path) {
path = this.limitPluginScope(path)
await this._handleExists(path, `Cannot open file ${path}`)
await this._handleIsFile(path, `Cannot open file ${path}`)
return this.openFile(path)
Expand All @@ -161,6 +167,7 @@ class FileManager extends Plugin {
* @returns {void}
*/
async writeFile (path, data) {
path = this.limitPluginScope(path)
if (await this.exists(path)) {
await this._handleIsFile(path, `Cannot write file ${path}`)
return await this.setFileContent(path, data)
Expand All @@ -177,6 +184,7 @@ class FileManager extends Plugin {
* @returns {string} content of the file
*/
async readFile (path) {
path = this.limitPluginScope(path)
await this._handleExists(path, `Cannot read file ${path}`)
await this._handleIsFile(path, `Cannot read file ${path}`)
return this.getFileContent(path)
Expand All @@ -189,6 +197,8 @@ class FileManager extends Plugin {
* @returns {void}
*/
async copyFile (src, dest) {
src = this.limitPluginScope(src)
dest = this.limitPluginScope(dest)
await this._handleExists(src, `Cannot copy from ${src}`)
await this._handleIsFile(src, `Cannot copy from ${src}`)
await this._handleIsFile(dest, `Cannot paste content into ${dest}`)
Expand All @@ -204,6 +214,8 @@ class FileManager extends Plugin {
* @returns {void}
*/
async rename (oldPath, newPath) {
oldPath = this.limitPluginScope(oldPath)
newPath = this.limitPluginScope(newPath)
await this._handleExists(oldPath, `Cannot rename ${oldPath}`)
const isFile = await this.isFile(oldPath)
const newPathExists = await this.exists(newPath)
Expand All @@ -230,6 +242,7 @@ class FileManager extends Plugin {
* @returns {void}
*/
async mkdir (path) {
path = this.limitPluginScope(path)
if (await this.exists(path)) {
throw createError({ code: 'EEXIST', message: `Cannot create directory ${path}` })
}
Expand All @@ -244,6 +257,7 @@ class FileManager extends Plugin {
* @returns {string[]} list of the file/directory name in this directory
*/
async readdir (path) {
path = this.limitPluginScope(path)
await this._handleExists(path)
await this._handleIsDir(path)

Expand All @@ -263,6 +277,7 @@ class FileManager extends Plugin {
* @returns {void}
*/
async remove (path) {
path = this.limitPluginScope(path)
await this._handleExists(path, `Cannot remove file or directory ${path}`)
const provider = this.fileProviderOf(path)

Expand Down Expand Up @@ -585,20 +600,6 @@ class FileManager extends Plugin {
if (callback) callback(error)
})
}

async createWorkspace (name) {
const workspaceProvider = this._deps.filesProviders.workspace
const workspacePath = 'browser/' + workspaceProvider.workspacesPath + '/' + name
const workspaceRootPath = 'browser/' + workspaceProvider.workspacesPath
if (!this.exists(workspaceRootPath)) await this.mkdir(workspaceRootPath)
if (!this.exists(workspacePath)) await this.mkdir(workspacePath)
}

async workspaceExists (name) {
const workspaceProvider = this._deps.filesProviders.workspace
const workspacePath = 'browser/' + workspaceProvider.workspacesPath + '/' + name
return this.exists(workspacePath)
}
}

module.exports = FileManager
4 changes: 3 additions & 1 deletion apps/remix-ide/src/app/files/fileProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ class FileProvider {
exists (path, cb) {
// todo check the type (directory/file) as well #2386
// currently it is not possible to have a file and folder with same path
return cb(null, this._exists(path))
const ret = this._exists(path)
if (cb) cb(null, ret)
return ret
}

_exists (path) {
Expand Down
30 changes: 23 additions & 7 deletions apps/remix-ide/src/app/panels/file-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,20 +131,19 @@ module.exports = class Filepanel extends ViewPlugin {
async initWorkspace () {
const queryParams = new QueryParams()
const gistHandler = new GistHandler()
const workspacesPath = this._deps.fileProviders.workspace.workspacesPath
const params = queryParams.get()
// get the file from gist
const loadedFromGist = gistHandler.loadFromGist(params, this._deps.fileManager)

if (loadedFromGist) return
if (params.code) {
try {
await this._deps.fileManager.createWorkspace('code-sample')
await this.processCreateWorkspace('code-sample')
this._deps.fileProviders.workspace.setWorkspace('code-sample')
var hash = ethutil.bufferToHex(ethutil.keccak(params.code))
const fileName = 'contract-' + hash.replace('0x', '').substring(0, 10) + '.sol'
const path = 'browser/' + workspacesPath + '/code-sample/' + fileName
await this._deps.fileManager.writeFile(path, atob(params.code))
const path = fileName
await this._deps.fileProviders.workspace.set(path, atob(params.code))
this.initialWorkspace = 'code-sample'
await this._deps.fileManager.openFile(fileName)
} catch (e) {
Expand All @@ -170,13 +169,30 @@ module.exports = class Filepanel extends ViewPlugin {
return await this.request.uploadFile()
}

async processCreateWorkspace (name) {
const workspaceProvider = this._deps.fileProviders.workspace
const browserProvider = this._deps.fileProviders.browser
const workspacePath = 'browser/' + workspaceProvider.workspacesPath + '/' + name
const workspaceRootPath = 'browser/' + workspaceProvider.workspacesPath
if (!browserProvider.exists(workspaceRootPath)) browserProvider.createDir(workspaceRootPath)
if (!browserProvider.exists(workspacePath)) browserProvider.createDir(workspacePath)
}

async workspaceExists (name) {
const workspaceProvider = this._deps.fileProviders.workspace
const browserProvider = this._deps.fileProviders.browser
const workspacePath = 'browser/' + workspaceProvider.workspacesPath + '/' + name
return browserProvider.exists(workspacePath)
}

async createWorkspace (workspaceName) {
if (await this._deps.fileManager.workspaceExists(workspaceName)) throw new Error('workspace already exists')
if (await this.workspaceExists(workspaceName)) throw new Error('workspace already exists')
const browserProvider = this._deps.fileProviders.browser
const workspacesPath = this._deps.fileProviders.workspace.workspacesPath
await this._deps.fileManager.createWorkspace(workspaceName)
await this.processCreateWorkspace(workspaceName)
for (const file in examples) {
try {
await this._deps.fileManager.writeFile('browser/' + workspacesPath + '/' + workspaceName + '/' + examples[file].name, examples[file].content)
await browserProvider.set('browser/' + workspacesPath + '/' + workspaceName + '/' + examples[file].name, examples[file].content)
} catch (error) {
console.error(error)
}
Expand Down
15 changes: 8 additions & 7 deletions apps/remix-ide/src/migrateFileSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default (fileProvider) => {
fileStorageBrowserFS.set(flag, 'done')
}

export async function migrateToWorkspace (fileManager) {
export async function migrateToWorkspace (fileManager, filePanel) {
const browserProvider = fileManager.getProvider('browser')
const workspaceProvider = fileManager.getProvider('workspace')
const flag = 'status'
Expand All @@ -31,19 +31,20 @@ export async function migrateToWorkspace (fileManager) {
console.log(files)
const workspaceName = 'default_workspace'
const workspacePath = joinPath('browser', workspaceProvider.workspacesPath, workspaceName)
await fileManager.createWorkspace(workspaceName)
await populateWorkspace(workspacePath, files, fileManager)
await filePanel.createWorkspace(workspaceName)
filePanel.getWorkspaces() // refresh list
await populateWorkspace(workspacePath, files, browserProvider)
fileStorageBrowserWorkspace.set(flag, 'done')
}

const populateWorkspace = async (workspace, json, fileManager) => {
const populateWorkspace = async (workspace, json, browserProvider) => {
for (const item in json) {
const isFolder = json[item].content === undefined
if (isFolder) {
await fileManager.mkdir(joinPath(workspace, item))
await populateWorkspace(workspace, json[item].children, fileManager)
browserProvider.createDir(joinPath(workspace, item))
await populateWorkspace(workspace, json[item].children, browserProvider)
} else {
await fileManager.writeFile(joinPath(workspace, item), json[item].content)
await browserProvider.set(joinPath(workspace, item), json[item].content)
}
}
}
14 changes: 8 additions & 6 deletions libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,7 @@ export const Workspace = (props: WorkspaceProps) => {
useEffect(() => {
const getWorkspaces = async () => {
if (props.workspaces && Array.isArray(props.workspaces)) {
if (props.initialWorkspace) {
props.workspace.setWorkspace(props.initialWorkspace)
setState(prevState => {
return { ...prevState, workspaces: props.workspaces, currentWorkspace: props.initialWorkspace }
})
} else if (props.workspaces.length > 0 && state.currentWorkspace === NO_WORKSPACE) {
if (props.workspaces.length > 0 && state.currentWorkspace === NO_WORKSPACE) {
props.workspace.setWorkspace(props.workspaces[0])
setState(prevState => {
return { ...prevState, workspaces: props.workspaces, currentWorkspace: props.workspaces[0] }
Expand All @@ -91,6 +86,13 @@ export const Workspace = (props: WorkspaceProps) => {
props.localhost.event.register('disconnected', (event) => {
remixdExplorer.hide()
})

if (props.initialWorkspace) {
props.workspace.setWorkspace(props.initialWorkspace)
setState(prevState => {
return { ...prevState, currentWorkspace: props.initialWorkspace }
})
}
}, [])

const [state, setState] = useState({
Expand Down