diff --git a/CHANGELOG.md b/CHANGELOG.md index 6574817..291320b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * CentOS 8 support * Support remote send and receive timeouts * Support WinFSP mount manager +* Fix `spawn()` failure on Windows when paths contain spaces ## 1.1.2 * Style changes diff --git a/README.md b/README.md index 5e91f0a..590091d 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,10 @@ Repertory allows you to mount Sia and/or ScPrime blockchain storage solutions vi * ScPrime >=1.4.1.2 ## Downloads -* **Repertory UI v1.1.3 Linux 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.3_linux_x86_64.AppImage) +* **Repertory UI v1.1.2 Linux 64-bit** [](https://pixeldrain.com/u/5i1mA1gb) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.2_linux_x86_64.AppImage) * NOTE: Linux distributions require `fuse` and `libfuse` to be installed. -* **Repertory UI v1.1.3 OS X 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.3_mac.dmg) -* **Repertory UI v1.1.3 Windows 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.3_win.exe) +* **Repertory UI v1.1.2 OS X 64-bit** [](https://pixeldrain.com/u/jEWmNDRX) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.2_mac.dmg) +* **Repertory UI v1.1.3 Windows 64-bit** [](https://pixeldrain.com/u/xyfCGfcM) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.3_win.exe) ## Supported Platforms * OS X 64-bit diff --git a/src/helpers.js b/src/helpers.js index 697993a..d0a5ae0 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -8,12 +8,15 @@ const spawn = require('child_process').spawn; const Constants = require('./constants'); const RandomString = require('randomstring'); -const _executeProcess = (command, args=[]) => { +const _executeProcess = (command, working, args=[]) => { return new Promise((resolve, reject) => { - const processOptions = { + let processOptions = { detached: true, shell: false, }; + if (working) { + processOptions.cwd = working; + } const process = new spawn(command, args, processOptions); const pid = process.pid; @@ -30,12 +33,16 @@ const _executeProcess = (command, args=[]) => { }); }; -const _execProcessGetOutput = (cmd, args) => { +const _execProcessGetOutput = (cmd, working, args) => { return new Promise((resolve, reject) => { - const proc = spawn(cmd, args, { + let processOptions = { env: process.env, stdio: ['ignore', 'pipe', 'pipe'] - }); + }; + if (working) { + processOptions.cwd = working; + } + const proc = spawn(cmd, args, processOptions); let output; proc.stdout.on('data', data => { @@ -74,7 +81,10 @@ const _getDefaultRepertoryArgs = (provider, remote) => { }; const _getRepertoryExec = version => { - return path.join(_getDataDirectory(), version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory'); + return { + cmd: (os.platform() === 'win32') ? 'repertory.exe' : 'repertory', + working: path.join(_getDataDirectory(), version), + }; }; const _resolvePath = str => { @@ -97,17 +107,17 @@ const _tryParse = (j, def) => { module.exports.checkDaemonVersion = (version, provider) => { return new Promise((resolve, reject) => { + const repertoryExec = _getRepertoryExec(version); const processOptions = { + cwd: repertoryExec.working, detached: true, shell: false, windowsHide: true, }; - const command = _getRepertoryExec(version); const args = _getDefaultRepertoryArgs(provider, false); args.push('-cv'); - - const process = new spawn(command, args, processOptions); + const process = new spawn(repertoryExec.cmd, args, processOptions); process.on('error', err => { reject(err); @@ -159,17 +169,18 @@ module.exports.detectRepertoryMounts = (version, providerList) => { resolve(mountState); } else { const provider = providerList[index]; + const repertoryExec = _getRepertoryExec(version); const processOptions = { + cwd: repertoryExec.working, detached: true, shell: false, windowsHide: true, }; - const command = _getRepertoryExec(version); const args = _getDefaultRepertoryArgs(provider, !Constants.PROVIDER_LIST.includes(provider)); args.push('-status'); - const process = new spawn(command, args, processOptions); + const process = new spawn(repertoryExec.cmd, args, processOptions); let result = ''; process.on('error', (err) => { @@ -277,15 +288,20 @@ module.exports.executeAndWait = (command, ignoreResult) => { module.exports.executeAsync = (command, args=[]) => { return new Promise((resolve, reject) => { const launchProcess = (count, timeout) => { - const processOptions = { + const cmd = path.basename(command); + const working = cmd.length === command.length ? null : command.substr(0, command.length - cmd.length); + let processOptions = { detached: true, shell: false, }; + if (working) { + processOptions.cwd = working; + } - const process = new spawn(command, args, processOptions); + const process = new spawn(cmd, args, processOptions); const pid = process.pid; - process.on('error', (err) => { + process.on('error', err => { if (++count === 5) { reject(err, pid); } else { @@ -345,13 +361,14 @@ module.exports.executeScript = script => { module.exports.executeMount = (version, provider, remote, location, noConsoleSupported, exitCallback) => { return new Promise((resolve) => { + const repertoryExec = _getRepertoryExec(version); const processOptions = { + cwd: repertoryExec.working, detached: false, shell: os.platform() !== 'darwin', stdio: 'ignore', }; - const command = _getRepertoryExec(version); const args = _getDefaultRepertoryArgs(provider, remote); if ((os.platform() === 'linux') || (os.platform() === 'darwin')) { @@ -366,7 +383,7 @@ module.exports.executeMount = (version, provider, remote, location, noConsoleSup } args.push(location); - let process = new spawn(command, args, processOptions); + let process = new spawn(repertoryExec.cmd, args, processOptions); const pid = process.pid; const timeout = setTimeout(() => { @@ -387,17 +404,18 @@ module.exports.executeMount = (version, provider, remote, location, noConsoleSup module.exports.getConfig = (version, provider, remote) => { return new Promise((resolve, reject) => { + const repertoryExec = _getRepertoryExec(version); const processOptions = { + cwd: repertoryExec.working, detached: true, shell: false, windowsHide: true, }; - const command = _getRepertoryExec(version); const args = _getDefaultRepertoryArgs(provider, remote); args.push('-dc'); - const process = new spawn(command, args, processOptions); + const process = new spawn(repertoryExec.cmd, args, processOptions); let result = ''; process.on('error', (err) => { @@ -430,17 +448,18 @@ module.exports.getConfig = (version, provider, remote) => { module.exports.getConfigTemplate = (version, provider, remote) => { return new Promise((resolve, reject) => { + const repertoryExec = _getRepertoryExec(version); const processOptions = { + cwd: repertoryExec.working, detached: true, shell: false, windowsHide: true, }; - const command = _getRepertoryExec(version); const args = _getDefaultRepertoryArgs(provider, remote); args.push('-gt'); - const process = new spawn(command, args, processOptions); + const process = new spawn(repertoryExec.cmd, args, processOptions); let result = ''; process.on('error', (err) => { @@ -579,7 +598,7 @@ module.exports.performWindowsUninstall = names => { } else { const cmd = path.join(process.env.windir, 'system32', 'reg.exe'); const args = ["QUERY", "HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"]; - _execProcessGetOutput(cmd, args) + _execProcessGetOutput(cmd, null, args) .then(lines => { const parseLine = index => { if (index < lines.length) { @@ -591,13 +610,13 @@ module.exports.performWindowsUninstall = names => { args2.push('DisplayName'); args2.push('/t'); args2.push('REG_SZ'); - _execProcessGetOutput(cmd, args2) + _execProcessGetOutput(cmd, null, args2) .then(lines => { const value = lines[2].trim().substr(args2[3].length).trim().substr(6).trim(); if (names.includes(value)) { const items = line.split('\\'); const productCode = items[items.length - 1]; - _executeProcess('msiexec.exe', ['/x', productCode, '/norestart']) + _executeProcess('msiexec.exe', null,['/x', productCode, '/norestart']) .then(code => { if ((code === 0) || (code === 3010) || (code === 1641)) { resolve(true); @@ -651,19 +670,20 @@ module.exports.resolvePath = _resolvePath; module.exports.setConfigValue = (name, value, provider, remote, version) => { return new Promise((resolve, reject) => { + const repertoryExec = _getRepertoryExec(version); const processOptions = { + cwd: repertoryExec.working, detached: true, shell: false, windowsHide: true, }; - const command = _getRepertoryExec(version); const args = _getDefaultRepertoryArgs(provider, remote); args.push('-set'); args.push(name); args.push(value); - const process = new spawn(command, args, processOptions); + const process = new spawn(repertoryExec.cmd, args, processOptions); process.on('error', (err) => { reject(err); @@ -679,17 +699,18 @@ module.exports.setConfigValue = (name, value, provider, remote, version) => { module.exports.stopMountProcess = (version, provider, remote) => { return new Promise((resolve, reject) => { + const repertoryExec = _getRepertoryExec(version); const processOptions = { + cwd: repertoryExec.working, detached: os.platform() === 'darwin', shell: os.platform() !== 'darwin', windowsHide: true, }; - const command = _getRepertoryExec(version); const args = _getDefaultRepertoryArgs(provider, remote); args.push('-unmount'); - const process = new spawn(command, args, processOptions); + const process = new spawn(repertoryExec.cmd, args, processOptions); const pid = process.pid; process.on('error', (err) => { reject(err); @@ -708,24 +729,25 @@ module.exports.stopMountProcess = (version, provider, remote) => { }; module.exports.stopMountProcessSync = (version, provider, remote) => { + const repertoryExec = _getRepertoryExec(version); const processOptions = { + cwd: repertoryExec.working, detached: true, shell: os.platform() !== 'darwin', windowsHide: true, }; - const command = _getRepertoryExec(version); const args = _getDefaultRepertoryArgs(provider, remote); args.push('-unmount'); - const process = new spawn(command, args, processOptions); + const process = new spawn(repertoryExec.cmd, args, processOptions); process.unref(); }; module.exports.testRepertoryBinary = version => { return new Promise((resolve, reject) => { - const command = _getRepertoryExec(version); - _executeProcess(command, ['-dc']) + const repertoryExec = _getRepertoryExec(version); + _executeProcess(repertoryExec.cmd, repertoryExec.working, ['-dc']) .then(code => { if (code === 0) { resolve(); @@ -809,4 +831,4 @@ module.exports.verifySignature = (file, signatureFile, publicKeyFile) => { reject(Error('Platform not supported: ' + os.platform())) } }); -}; \ No newline at end of file +};