Unverified Commit 9c2633d6 authored by yann300's avatar yann300 Committed by GitHub

Merge pull request #1070 from ethereum/fixFileExist

Fix file exist (from fileProvider)
parents 4864d9cb 04797e15
...@@ -30,11 +30,11 @@ while [ ! -f "$SAUCECONNECT_READYFILE" ]; do ...@@ -30,11 +30,11 @@ while [ ! -f "$SAUCECONNECT_READYFILE" ]; do
sleep .5 sleep .5
done done
# npm run nightwatch_remote_chrome || TEST_EXITCODE=1 npm run nightwatch_remote_chrome || TEST_EXITCODE=1
# npm run nightwatch_remote_firefox || TEST_EXITCODE=1 npm run nightwatch_remote_firefox || TEST_EXITCODE=1
# npm run nightwatch_remote_safari || TEST_EXITCODE=1 npm run nightwatch_remote_safari || TEST_EXITCODE=1
# npm run nightwatch_remote_ie || TEST_EXITCODE=1 # npm run nightwatch_remote_ie || TEST_EXITCODE=1
npm run nightwatch_remote_parallel || TEST_EXITCODE=1 # npm run nightwatch_remote_parallel || TEST_EXITCODE=1
node ci/sauceDisconnect.js "$SAUCECONNECT_USERNAME" "$SAUCECONNECT_ACCESSKEY" "$SAUCECONNECT_JOBIDENTIFIER" node ci/sauceDisconnect.js "$SAUCECONNECT_USERNAME" "$SAUCECONNECT_ACCESSKEY" "$SAUCECONNECT_JOBIDENTIFIER"
......
import "./contract.sol";
contract Assets { contract Assets {
uint[] proposals;
function add(uint8 _numProposals) { function add(uint8 _numProposals) {
proposals.length = _numProposals; proposals.length = _numProposals;
} }
......
contract gmbh { contract gmbh {
uint[] proposals;
function register(uint8 _numProposals) { function register(uint8 _numProposals) {
proposals.length = _numProposals; proposals.length = _numProposals;
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
var $ = require('jquery') var $ = require('jquery')
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
var yo = require('yo-yo') var yo = require('yo-yo')
var async = require('async')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager var EventManager = remixLib.EventManager
...@@ -214,9 +215,16 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -214,9 +215,16 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// ----------------- Compiler ----------------- // ----------------- Compiler -----------------
var compiler = new Compiler((url, cb) => { var compiler = new Compiler((url, cb) => {
var provider = fileManager.fileProviderOf(url) var provider = fileManager.fileProviderOf(url)
if (provider && provider.exists(url)) { if (provider) {
provider.exists(url, (error, exist) => {
if (error) return cb(error)
if (exist) {
return provider.get(url, cb) return provider.get(url, cb)
} else {
return cb('Unable to import "' + url + '": File not found')
} }
})
} else {
handleImports.import(url, handleImports.import(url,
(loadingMsg) => { (loadingMsg) => {
$('#output').append($('<div/>').append($('<pre/>').text(loadingMsg))) $('#output').append($('<div/>').append($('<pre/>').text(loadingMsg)))
...@@ -229,6 +237,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -229,6 +237,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
cb(error) cb(error)
} }
}) })
}
}) })
var offsetToLineColumnConverter = new OffsetToLineColumnConverter(compiler.event) var offsetToLineColumnConverter = new OffsetToLineColumnConverter(compiler.event)
...@@ -386,14 +395,26 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -386,14 +395,26 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
this._components.contextView = new ContextView({ this._components.contextView = new ContextView({
contextualListener: this._components.contextualListener, contextualListener: this._components.contextualListener,
jumpTo: (position) => { jumpTo: (position) => {
function jumpToLine (lineColumn) {
if (lineColumn.start && lineColumn.start.line && lineColumn.start.column) {
editor.gotoLine(lineColumn.start.line, lineColumn.end.column + 1)
}
}
if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) { if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) {
var lineColumn = offsetToLineColumnConverter.offsetToLineColumn(position, position.file, compiler.lastCompilationResult) var lineColumn = offsetToLineColumnConverter.offsetToLineColumn(position, position.file, compiler.lastCompilationResult)
var filename = compiler.getSourceName(position.file) var filename = compiler.getSourceName(position.file)
if (filename !== config.get('currentFile') && (filesProviders['browser'].exists(filename) || filesProviders['localhost'].exists(filename))) { // TODO: refactor with rendererAPI.errorClick
if (filename !== config.get('currentFile')) {
var provider = fileManager.fileProviderOf(filename)
if (provider) {
provider.exists(filename, (error, exist) => {
if (error) return console.log(error)
fileManager.switchFile(filename) fileManager.switchFile(filename)
jumpToLine(lineColumn)
})
} }
if (lineColumn.start && lineColumn.start.line && lineColumn.start.column) { } else {
editor.gotoLine(lineColumn.start.line, lineColumn.end.column + 1) jumpToLine(lineColumn)
} }
} }
} }
...@@ -443,15 +464,21 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -443,15 +464,21 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
function loadFiles (filesSet, fileProvider) { function loadFiles (filesSet, fileProvider) {
if (!fileProvider) fileProvider = 'browser' if (!fileProvider) fileProvider = 'browser'
for (var f in filesSet) { async.each(Object.keys(filesSet), (file, callback) => {
var name = helper.createNonClashingName(f, filesProviders[fileProvider]) helper.createNonClashingName(file, filesProviders[fileProvider],
if (helper.checkSpecialChars(name)) { (error, name) => {
if (error) {
modalDialogCustom.alert('Unexpected error loading the file ' + error)
} else if (helper.checkSpecialChars(name)) {
modalDialogCustom.alert('Special characters are not allowed') modalDialogCustom.alert('Special characters are not allowed')
return } else {
} filesProviders[fileProvider].set(name, filesSet[file].content)
filesProviders[fileProvider].set(name, filesSet[f].content)
} }
fileManager.switchFile() callback()
})
}, (error) => {
if (!error) fileManager.switchFile()
})
} }
// Replace early callback with instant response // Replace early callback with instant response
...@@ -541,12 +568,21 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -541,12 +568,21 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
} }
}, },
errorClick: (errFile, errLine, errCol) => { errorClick: (errFile, errLine, errCol) => {
if (errFile !== config.get('currentFile') && (filesProviders['browser'].exists(errFile) || filesProviders['localhost'].exists(errFile))) { if (errFile !== config.get('currentFile')) {
// TODO: refactor with this._components.contextView.jumpTo
var provider = fileManager.fileProviderOf(errFile)
if (provider) {
provider.exists(errFile, (error, exist) => {
if (error) return console.log(error)
fileManager.switchFile(errFile) fileManager.switchFile(errFile)
editor.gotoLine(errLine, errCol)
})
} }
} else {
editor.gotoLine(errLine, errCol) editor.gotoLine(errLine, errCol)
} }
} }
}
var renderer = new Renderer(rendererAPI) var renderer = new Renderer(rendererAPI)
// ----------------- StaticAnalysis ----------------- // ----------------- StaticAnalysis -----------------
......
...@@ -21,10 +21,10 @@ class BasicReadOnlyExplorer { ...@@ -21,10 +21,10 @@ class BasicReadOnlyExplorer {
this.files = {} this.files = {}
} }
exists (path) { exists (path, cb) {
if (!this.files) return false if (!this.files) return cb(null, false)
var unprefixedPath = this.removePrefix(path) var unprefixedPath = this.removePrefix(path)
return this.files[unprefixedPath] !== undefined cb(null, this.files[unprefixedPath] !== undefined)
} }
get (path, cb) { get (path, cb) {
......
...@@ -8,7 +8,11 @@ function Files (storage) { ...@@ -8,7 +8,11 @@ function Files (storage) {
var readonly = {} var readonly = {}
this.type = 'browser' this.type = 'browser'
this.exists = function (path) { this.exists = function (path, cb) {
cb(null, this._exists(path))
}
this._exists = function (path) {
var unprefixedpath = this.removePrefix(path) var unprefixedpath = this.removePrefix(path)
// NOTE: ignore the config file // NOTE: ignore the config file
if (path === '.remix.config') return false if (path === '.remix.config') return false
...@@ -75,7 +79,7 @@ function Files (storage) { ...@@ -75,7 +79,7 @@ function Files (storage) {
this.remove = function (path) { this.remove = function (path) {
var unprefixedpath = this.removePrefix(path) var unprefixedpath = this.removePrefix(path)
if (!this.exists(unprefixedpath)) { if (!this._exists(unprefixedpath)) {
return false return false
} }
...@@ -133,7 +137,7 @@ function Files (storage) { ...@@ -133,7 +137,7 @@ function Files (storage) {
} }
// rename .browser-solidity.json to .remix.config // rename .browser-solidity.json to .remix.config
if (this.exists('.browser-solidity.json')) { if (this._exists('.browser-solidity.json')) {
this.rename('.browser-solidity.json', '.remix.config') this.rename('.browser-solidity.json', '.remix.config')
} }
} }
......
...@@ -221,16 +221,21 @@ function fileExplorer (appAPI, files) { ...@@ -221,16 +221,21 @@ function fileExplorer (appAPI, files) {
} else if (helper.checkSpecialChars(label.innerText)) { } else if (helper.checkSpecialChars(label.innerText)) {
modalDialogCustom.alert('Special characters are not allowed') modalDialogCustom.alert('Special characters are not allowed')
label.innerText = textUnderEdit label.innerText = textUnderEdit
} else if (!files.exists(newPath)) { } else {
files.exists(newPath, (error, exist) => {
if (error) return modalDialogCustom.alert('Unexpected error while renaming: ' + error)
if (!exist) {
files.rename(label.dataset.path, newPath, isFolder) files.rename(label.dataset.path, newPath, isFolder)
} else { } else {
modalDialogCustom.alert('File already exists.') modalDialogCustom.alert('File already exists.')
label.innerText = textUnderEdit label.innerText = textUnderEdit
} }
})
}
} }
if (event.which === 13) event.preventDefault() if (event.which === 13) event.preventDefault()
if (event.type === 'blur' || event.which === 13 && label.getAttribute('contenteditable')) { if ((event.type === 'blur' || event.which === 13) && label.getAttribute('contenteditable')) {
var isFolder = label.className.indexOf('folder') !== -1 var isFolder = label.className.indexOf('folder') !== -1
var save = textUnderEdit !== label.innerText var save = textUnderEdit !== label.innerText
if (save) { if (save) {
......
...@@ -65,13 +65,11 @@ module.exports = class SharedFolder { ...@@ -65,13 +65,11 @@ module.exports = class SharedFolder {
// //
// this.remixd.exists(path, (error, isValid) => {}) // this.remixd.exists(path, (error, isValid) => {})
exists (path) { exists (path, cb) {
// @TODO: add new remixd.exists() method var unprefixedpath = this.removePrefix(path)
// we remove the this.files = null at the beggining this._remixd.call('sharedfolder', 'exists', {path: unprefixedpath}, (error, result) => {
// modify the exists() (cause it is using the this.files) to use remixd cb(error, result)
// yes for the exists I think you might need another remixd function })
if (!this.files) return false
return this.files[path] !== undefined
} }
get (path, cb) { get (path, cb) {
......
...@@ -169,18 +169,21 @@ function filepanel (appAPI, filesProvider) { ...@@ -169,18 +169,21 @@ function filepanel (appAPI, filesProvider) {
} }
var success = files.set(name, event.target.result) var success = files.set(name, event.target.result)
if (!success) modalDialogCustom.alert('Failed to create file ' + name) if (!success) modalDialogCustom.alert('Failed to create file ' + name)
else self.events.trigger('focus', [name]) else self.event.trigger('focus', [name])
} }
fileReader.readAsText(file) fileReader.readAsText(file)
} }
var name = files.type + '/' + file.name var name = files.type + '/' + file.name
if (!files.exists(name)) { files.exists(name, (error, exist) => {
if (error) console.log(error)
if (!exist) {
loadFile() loadFile()
} else { } else {
modalDialogCustom.confirm(null, `The file ${name} already exists! Would you like to overwrite it?`, () => { loadFile() }) modalDialogCustom.confirm(null, `The file ${name} already exists! Would you like to overwrite it?`, () => { loadFile() })
} }
}) })
})
} }
// ----------------- resizeable ui --------------- // ----------------- resizeable ui ---------------
...@@ -221,13 +224,15 @@ function filepanel (appAPI, filesProvider) { ...@@ -221,13 +224,15 @@ function filepanel (appAPI, filesProvider) {
function createNewFile () { function createNewFile () {
modalDialogCustom.prompt(null, 'File Name', 'Untitled.sol', (input) => { modalDialogCustom.prompt(null, 'File Name', 'Untitled.sol', (input) => {
var newName = filesProvider['browser'].type + '/' + helper.createNonClashingName(input, filesProvider['browser']) helper.createNonClashingName(input, filesProvider['browser'], (error, newName) => {
if (error) return modalDialogCustom.alert('Failed to create file ' + newName + ' ' + error)
if (!filesProvider['browser'].set(newName, '')) { if (!filesProvider['browser'].set(newName, '')) {
modalDialogCustom.alert('Failed to create file ' + newName) modalDialogCustom.alert('Failed to create file ' + newName)
} else { } else {
appAPI.switchFile(newName) appAPI.switchFile(filesProvider['browser'].type + '/' + newName)
} }
}) })
})
} }
/** /**
......
...@@ -161,12 +161,14 @@ function makeRecorder (events, appAPI, appEvents) { ...@@ -161,12 +161,14 @@ function makeRecorder (events, appAPI, appEvents) {
var fileProvider = appAPI.fileProviderOf(path) var fileProvider = appAPI.fileProviderOf(path)
if (fileProvider) { if (fileProvider) {
var newFile = path + input var newFile = path + input
newFile = helper.createNonClashingName(newFile, fileProvider, '.json') helper.createNonClashingName(newFile, fileProvider, (error, newFile) => {
if (error) return modalDialogCustom.alert('Failed to create file. ' + newFile + ' ' + error)
if (!fileProvider.set(newFile, txJSON)) { if (!fileProvider.set(newFile, txJSON)) {
modalDialogCustom.alert('Failed to create file ' + newFile) modalDialogCustom.alert('Failed to create file ' + newFile)
} else { } else {
appAPI.switchFile(newFile) appAPI.switchFile(newFile)
} }
})
} }
}) })
} }
......
...@@ -45,7 +45,7 @@ module.exports = (event, items) => { ...@@ -45,7 +45,7 @@ module.exports = (event, items) => {
event.preventDefault() event.preventDefault()
function hide (event, force) { function hide (event, force) {
if (force || (event.target !== container)) { if (container && container.parentElement && (force || (event.target !== container))) {
container.parentElement.removeChild(container) container.parentElement.removeChild(container)
} }
window.removeEventListener('click', hide) window.removeEventListener('click', hide)
......
var async = require('async')
module.exports = { module.exports = {
shortenAddress: function (address, etherBalance) { shortenAddress: function (address, etherBalance) {
var len = address.length var len = address.length
...@@ -9,7 +11,7 @@ module.exports = { ...@@ -9,7 +11,7 @@ module.exports = {
var len = data.length var len = data.length
return data.slice(0, 5) + '...' + data.slice(len - 5, len) return data.slice(0, 5) + '...' + data.slice(len - 5, len)
}, },
createNonClashingName (name, fileProvider) { createNonClashingName (name, fileProvider, cb) {
var counter = '' var counter = ''
var ext = 'sol' var ext = 'sol'
var reg = /(.*)\.([^.]+)/g var reg = /(.*)\.([^.]+)/g
...@@ -18,10 +20,22 @@ module.exports = { ...@@ -18,10 +20,22 @@ module.exports = {
name = split[1] name = split[1]
ext = split[2] ext = split[2]
} }
while (fileProvider.exists(name + counter + '.' + ext)) { var exist = true
counter = (counter | 0) + 1 async.whilst(
() => { return exist },
(callback) => {
fileProvider.exists(name + counter + '.' + ext, (error, currentExist) => {
if (error) {
callback(error)
} else {
exist = currentExist
if (exist) counter = (counter | 0) + 1
callback()
} }
return name + counter + '.' + ext })
},
(error) => { cb(error, name + counter + '.' + ext) }
)
}, },
checkSpecialChars (name) { checkSpecialChars (name) {
return name.match(/[/:*?"<>\\'|]/) != null return name.match(/[/:*?"<>\\'|]/) != null
......
...@@ -3,9 +3,33 @@ var contractHelper = require('../helpers/contracts') ...@@ -3,9 +3,33 @@ var contractHelper = require('../helpers/contracts')
var init = require('../helpers/init') var init = require('../helpers/init')
var sauce = require('./sauce') var sauce = require('./sauce')
var assetsTestContract = `import "./contract.sol";
contract Assets {
uint[] proposals;
function add(uint8 _numProposals) {
proposals.length = _numProposals;
}
}
`
var gmbhTestContract = `
contract gmbh {
uint[] proposals;
function register(uint8 _numProposals) {
proposals.length = _numProposals;
}
}
`
var sources = [ var sources = [
{ {
'localhost/folder1/contract2.sol': {content: 'contract test2 { function get () returns (uint) { return 11; }}'} 'localhost/folder1/contract2.sol': {content: 'contract test2 { function get () returns (uint) { return 11; }}'}
},
{
'localhost/src/gmbh/company.sol': {content: assetsTestContract}
},
{
'localhost/src/gmbh/company.sol': {content: assetsTestContract},
'localhost/src/gmbh/contract.sol': {content: gmbhTestContract}
} }
] ]
...@@ -92,6 +116,9 @@ function runTests (browser, testData) { ...@@ -92,6 +116,9 @@ function runTests (browser, testData) {
done() done()
}) })
}) })
.perform(function (done) {
testImportFromRemixd(browser, () => { done() })
})
.perform(function () { .perform(function () {
browser.click('[data-path="localhost"]') // collapse and expand browser.click('[data-path="localhost"]') // collapse and expand
.waitForElementNotVisible('[data-path="localhost/folder1"]') .waitForElementNotVisible('[data-path="localhost/folder1"]')
...@@ -107,3 +134,19 @@ function runTests (browser, testData) { ...@@ -107,3 +134,19 @@ function runTests (browser, testData) {
.end() .end()
}) })
} }
function testImportFromRemixd (browser, callback) {
browser
.waitForElementVisible('[data-path="localhost/src"]', 100000)
.click('[data-path="localhost/src"]')
.waitForElementVisible('[data-path="localhost/src/gmbh"]', 100000)
.click('[data-path="localhost/src/gmbh"]')
.waitForElementVisible('[data-path="localhost/src/gmbh/company.sol"]', 100000)
.click('[data-path="localhost/src/gmbh/company.sol"]')
.pause(1000)
.perform(() => {
contractHelper.verifyContract(browser, ['Assets', 'gmbh'], function () {
callback()
})
})
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment