From 642e60ce5f01816235b342d94939acec0086fa6a Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sun, 9 Dec 2018 19:27:04 -0600 Subject: [PATCH] Linux / OS X changes --- electron.js | 119 ++++++++++++++---------- helpers.js | 81 ++++++++-------- src/App.js | 6 +- src/constants.js | 6 ++ src/containers/MountItems/MountItems.js | 3 +- 5 files changed, 126 insertions(+), 89 deletions(-) diff --git a/electron.js b/electron.js index 4c5906f..1e84032 100644 --- a/electron.js +++ b/electron.js @@ -17,10 +17,15 @@ const AutoLaunch = require('auto-launch'); let mainContextWindow; let mainWindow; let mainWindowTray; -let mountedPIDs = []; +let mountedPIDs = {}; +let mountedLocations = []; let expectedUnmount = {}; let launchHidden = false; +function closeApplication() { + app.quit(); +} + function createWindow() { loadUiSettings(); @@ -50,7 +55,15 @@ function createWindow() { // Dereference the window object, usually you would store windows // in an array if your app supports multi windows, this is the time // when you should delete the corresponding element. - mainWindow = null + mainWindow = null; + + // Unmount all items + console.log(mountedLocations); + for (const i in mountedLocations) { + helpers.stopMountProcess(mountedPIDs[mountedLocations[i]], mountedLocations[i]); + } + mountedLocations = []; + mountedPIDs = {}; }); if ((os.platform() === 'win32') || (os.platform() === 'linux')) { @@ -103,7 +116,7 @@ function createWindow() { }, { label: 'Exit', click(item) { - app.quit(); + closeApplication(); } } ]); @@ -118,14 +131,14 @@ function createWindow() { mainWindowTray.setContextMenu(mainContextWindow) }) .catch(() => { - app.quit(); + closeApplication(); }); } } const instanceLock = app.requestSingleInstanceLock(); if (!instanceLock) { - app.quit() + closeApplication(); } else { app.on('second-instance', () => { if (mainWindow) { @@ -146,7 +159,7 @@ if (!instanceLock) { // On OS X it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== 'darwin') { - app.quit() + closeApplication(); } }); @@ -181,13 +194,15 @@ const saveUiSettings = () => { }; const standardIPCReply = (event, channel, data, error) => { - event.sender.send(channel, { - data: { - ...data, - Error: error, - Success: !error, - } - }); + if (mainWindow) { + event.sender.send(channel, { + data: { + ...data, + Error: error, + Success: !error, + } + }); + } }; ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => { @@ -237,11 +252,10 @@ ipcMain.on(Constants.IPC_Delete_File, (event, data) => { }); ipcMain.on(Constants.IPC_Detect_Mounts, (event, data) => { - let driveLetters = { - Hyperspace: [], - Sia: [], - SiaPrime: [], - }; + let driveLetters = {}; + for (const provider of Constants.PROVIDER_LIST) { + driveLetters[provider] = []; + } const grabDriveLetters = (hsLocation, siaLocation, siaPrimeLocation) => { for (let i = 'c'.charCodeAt(0); i <= 'z'.charCodeAt(0); i++) { @@ -503,30 +517,42 @@ ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => { ipcMain.on(Constants.IPC_Mount_Drive, (event, data) => { expectedUnmount[data.StorageType] = false; const dataDirectory = helpers.resolvePath(data.Directory); - const errorHandler = (pid, error) => { - mountedPIDs.splice(mountedPIDs.indexOf(pid), 1); - standardIPCReply(event, Constants.IPC_Unmount_Drive_Reply, { - Expected: expectedUnmount[data.StorageType], - Location: data.Location, - PID: -1, - StorageType: data.StorageType, - }, error || Error(data.StorageType + ' Unmounted')); - }; - helpers.executeMount(dataDirectory, data.Version, data.StorageType, data.Location, (error, pid) => { - errorHandler(pid, error); - }) - .then(pid => { - if (pid !== -1) { - mountedPIDs.push(pid); - } - standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, { - PID: pid, - StorageType: data.StorageType, - }); - }) - .catch(error => { - errorHandler(-1, error); - }); + + if (mountedLocations.indexOf(data.Location) !== -1) { + console.log(data.StorageType + ' already mounted: ' + data.Location); + } else { + mountedLocations.push(data.Location); + mountedPIDs[data.Location] = -1; + const errorHandler = (pid, error) => { + if (mountedLocations.indexOf(data.Location) !== -1) { + mountedLocations.splice(mountedLocations.indexOf(data.Location), 1); + delete mountedPIDs[data.Location]; + } + + standardIPCReply(event, Constants.IPC_Unmount_Drive_Reply, { + Expected: expectedUnmount[data.StorageType], + Location: data.Location, + PID: -1, + StorageType: data.StorageType, + }, error || Error(data.StorageType + ' Unmounted')); + }; + helpers + .executeMount(dataDirectory, data.Version, data.StorageType, data.Location, data.NoConsoleSupported, (error, pid) => { + errorHandler(pid, error); + }) + .then(pid => { + if (pid !== -1) { + mountedPIDs[data.Location] = pid; + } + standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, { + PID: pid, + StorageType: data.StorageType, + }); + }) + .catch(error => { + errorHandler(-1, error); + }); + } }); ipcMain.on(Constants.IPC_Save_State, (event, data) => { @@ -556,17 +582,14 @@ ipcMain.on(Constants.IPC_Set_Config_Values, (event, data) => { }); ipcMain.on(Constants.IPC_Shutdown, () => { - app.quit(); + closeApplication(); }); ipcMain.on(Constants.IPC_Unmount_Drive, (event, data) => { expectedUnmount[data.StorageType] = true; helpers - .stopProcessByPID(data.PID) - .then((pid)=> { - if (mountedPIDs.indexOf(pid) === -1) { - event.sender.send(Constants.IPC_Unmount_Drive_Reply); - } + .stopMountProcess(data.PID, data.Location) + .then(()=> { }) .catch((e) => { console.log(e); diff --git a/helpers.js b/helpers.js index 9c94bf8..665e853 100644 --- a/helpers.js +++ b/helpers.js @@ -4,6 +4,7 @@ const os = require('os'); const axios = require('axios'); const exec = require('child_process').exec; const spawn = require('child_process').spawn; +const Constants = require('./src/constants'); const tryParse = (j, def) => { try { @@ -37,23 +38,15 @@ module.exports.detectRepertoryMounts = (directory, version) => { }); process.on('exit', () => { - resolve(tryParse(result, { - Hyperspace: { + let defaultData = {}; + for (const provider of Constants.PROVIDER_LIST) { + defaultData[provider] = { Active: false, Location: '', PID: -1, - }, - Sia: { - Active: false, - Location: '', - PID: -1, - }, - SiaPrime: { - Active: false, - Location: '', - PID: -1, - }, - })); + }; + } + resolve(tryParse(result, defaultData)); }); process.unref(); }); @@ -163,29 +156,33 @@ module.exports.executeAsync = (command, args=[]) => { }); }; -module.exports.executeMount = (directory, version, storageType, location, exitCallback) => { +module.exports.executeMount = (directory, version, storageType, location, noConsoleSupported, exitCallback) => { return new Promise((resolve) => { const processOptions = { - detached: true, + detached: os.platform() === 'win32', shell: true, + stdio: 'ignore', }; const command = path.join(directory, version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory'); const args = []; - if (storageType.toLowerCase() === 'hyperspace') { - args.push('-hs'); - } else if (storageType.toLowerCase() === 'siaprime') { - args.push('-sp'); + if (Constants.PROVIDER_ARG[storageType.toLowerCase()].length > 0) { + args.push(Constants.PROVIDER_ARG[storageType.toLowerCase()]); } + if ((os.platform() === 'linux') || (os.platform() === 'darwin')) { args.push('-o'); args.push('big_writes'); + args.push('-f'); + if (noConsoleSupported) { + args.push('-nc'); + } } else if (os.platform() === 'win32') { args.push('-hidden'); } args.push(location); - const process = new spawn(command, args, processOptions); + let process = new spawn(command, args, processOptions); const pid = process.pid; const timeout = setTimeout(() => { @@ -196,11 +193,15 @@ module.exports.executeMount = (directory, version, storageType, location, exitCa clearTimeout(timeout); exitCallback(err, pid); }); + process.on('exit', (code) => { clearTimeout(timeout); exitCallback(code, pid); }); - process.unref(); + + if (os.platform() === 'win32') { + process.unref(); + } }); }; @@ -215,10 +216,8 @@ module.exports.getConfig = (directory, version, storageType) => { const command = path.join(directory, version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory'); const args = []; args.push('-dc'); - if (storageType.toLowerCase() === 'hyperspace') { - args.push('-hs'); - } else if (storageType.toLowerCase() === 'siaprime') { - args.push('-sp'); + if (Constants.PROVIDER_ARG[storageType.toLowerCase()].length > 0) { + args.push(Constants.PROVIDER_ARG[storageType.toLowerCase()]); } const process = new spawn(command, args, processOptions); @@ -263,10 +262,8 @@ module.exports.getConfigTemplate = (directory, version, storageType) => { const command = path.join(directory, version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory'); const args = []; args.push('-gt'); - if (storageType.toLowerCase() === 'hyperspace') { - args.push('-hs'); - } else if (storageType.toLowerCase() === 'siaprime') { - args.push('-sp'); + if (Constants.PROVIDER_ARG[storageType.toLowerCase()].length > 0) { + args.push(Constants.PROVIDER_ARG[storageType.toLowerCase()]); } const process = new spawn(command, args, processOptions); @@ -428,10 +425,8 @@ module.exports.setConfigValue = (name, value, directory, storageType, version) = args.push('-set'); args.push(name); args.push(value); - if (storageType.toLowerCase() === 'hyperspace') { - args.push('-hs'); - } else if (storageType.toLowerCase() === 'siaprime') { - args.push('-sp'); + if (Constants.PROVIDER_ARG[storageType.toLowerCase()].length > 0) { + args.push(Constants.PROVIDER_ARG[storageType.toLowerCase()]); } const process = new spawn(command, args, processOptions); @@ -448,23 +443,31 @@ module.exports.setConfigValue = (name, value, directory, storageType, version) = }); }; -module.exports.stopProcessByPID = pid => { +module.exports.stopMountProcess = (pid, location) => { return new Promise((resolve, reject) => { const processOptions = { detached: true, - shell: false, + shell: true, windowsHide: true, }; - const command = (os.platform() === 'win32') ? 'taskkill.exe' : 'kill'; + let procName = 'kill'; + if (location && location.length > 0) { + procName = 'fusermount'; + } + const command = (os.platform() === 'win32') ? 'taskkill.exe' : procName; const args = []; if (os.platform() === 'win32') { args.push('/PID'); } - args.push(pid); + if (procName === 'fusermount') { + args.push('-u'); + args.push(location); + } else { + args.push(pid); + } const process = new spawn(command, args, processOptions); - process.on('error', (err) => { reject(err); }); diff --git a/src/App.js b/src/App.js index ecd111c..9343c4a 100644 --- a/src/App.js +++ b/src/App.js @@ -588,7 +588,10 @@ class App extends Component { this.state.LocationsLookup[selectedVersion].config_support; const allowSiaPrime = this.state.LocationsLookup[selectedVersion] && - this.state.LocationsLookup[selectedVersion].siaprime_support; + this.state.LocationsLookup[selectedVersion].siaprime_support; + + const noConsoleSupported = this.state.LocationsLookup[selectedVersion] && + this.state.LocationsLookup[selectedVersion].no_console_supported; const showDependencies = missingDependencies && !this.state.DownloadActive; @@ -691,6 +694,7 @@ class App extends Component { { - if ((this.props.platform === 'win32') && arg && arg.data && !arg.data.Expected && arg.data.Location && this.props[arg.data.StorageType.toLowerCase()].AutoRestart) { + if (arg && arg.data && !arg.data.Expected && arg.data.Location && this.props[arg.data.StorageType.toLowerCase()].AutoRestart) { this.handleMountUnMount(arg.data.StorageType, true, arg.data.Location) } else { this.detectMounts();