Linux / OS X changes

This commit is contained in:
Scott E. Graves
2018-12-09 19:27:04 -06:00
parent e95477f421
commit 642e60ce5f
5 changed files with 126 additions and 89 deletions

View File

@@ -17,10 +17,15 @@ const AutoLaunch = require('auto-launch');
let mainContextWindow; let mainContextWindow;
let mainWindow; let mainWindow;
let mainWindowTray; let mainWindowTray;
let mountedPIDs = []; let mountedPIDs = {};
let mountedLocations = [];
let expectedUnmount = {}; let expectedUnmount = {};
let launchHidden = false; let launchHidden = false;
function closeApplication() {
app.quit();
}
function createWindow() { function createWindow() {
loadUiSettings(); loadUiSettings();
@@ -50,7 +55,15 @@ function createWindow() {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // 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')) { if ((os.platform() === 'win32') || (os.platform() === 'linux')) {
@@ -103,7 +116,7 @@ function createWindow() {
}, },
{ {
label: 'Exit', click(item) { label: 'Exit', click(item) {
app.quit(); closeApplication();
} }
} }
]); ]);
@@ -118,14 +131,14 @@ function createWindow() {
mainWindowTray.setContextMenu(mainContextWindow) mainWindowTray.setContextMenu(mainContextWindow)
}) })
.catch(() => { .catch(() => {
app.quit(); closeApplication();
}); });
} }
} }
const instanceLock = app.requestSingleInstanceLock(); const instanceLock = app.requestSingleInstanceLock();
if (!instanceLock) { if (!instanceLock) {
app.quit() closeApplication();
} else { } else {
app.on('second-instance', () => { app.on('second-instance', () => {
if (mainWindow) { if (mainWindow) {
@@ -146,7 +159,7 @@ if (!instanceLock) {
// On OS X it is common for applications and their menu bar // On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit() closeApplication();
} }
}); });
@@ -181,13 +194,15 @@ const saveUiSettings = () => {
}; };
const standardIPCReply = (event, channel, data, error) => { const standardIPCReply = (event, channel, data, error) => {
event.sender.send(channel, { if (mainWindow) {
data: { event.sender.send(channel, {
...data, data: {
Error: error, ...data,
Success: !error, Error: error,
} Success: !error,
}); }
});
}
}; };
ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => { 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) => { ipcMain.on(Constants.IPC_Detect_Mounts, (event, data) => {
let driveLetters = { let driveLetters = {};
Hyperspace: [], for (const provider of Constants.PROVIDER_LIST) {
Sia: [], driveLetters[provider] = [];
SiaPrime: [], }
};
const grabDriveLetters = (hsLocation, siaLocation, siaPrimeLocation) => { const grabDriveLetters = (hsLocation, siaLocation, siaPrimeLocation) => {
for (let i = 'c'.charCodeAt(0); i <= 'z'.charCodeAt(0); i++) { 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) => { ipcMain.on(Constants.IPC_Mount_Drive, (event, data) => {
expectedUnmount[data.StorageType] = false; expectedUnmount[data.StorageType] = false;
const dataDirectory = helpers.resolvePath(data.Directory); const dataDirectory = helpers.resolvePath(data.Directory);
const errorHandler = (pid, error) => {
mountedPIDs.splice(mountedPIDs.indexOf(pid), 1); if (mountedLocations.indexOf(data.Location) !== -1) {
standardIPCReply(event, Constants.IPC_Unmount_Drive_Reply, { console.log(data.StorageType + ' already mounted: ' + data.Location);
Expected: expectedUnmount[data.StorageType], } else {
Location: data.Location, mountedLocations.push(data.Location);
PID: -1, mountedPIDs[data.Location] = -1;
StorageType: data.StorageType, const errorHandler = (pid, error) => {
}, error || Error(data.StorageType + ' Unmounted')); if (mountedLocations.indexOf(data.Location) !== -1) {
}; mountedLocations.splice(mountedLocations.indexOf(data.Location), 1);
helpers.executeMount(dataDirectory, data.Version, data.StorageType, data.Location, (error, pid) => { delete mountedPIDs[data.Location];
errorHandler(pid, error); }
})
.then(pid => { standardIPCReply(event, Constants.IPC_Unmount_Drive_Reply, {
if (pid !== -1) { Expected: expectedUnmount[data.StorageType],
mountedPIDs.push(pid); Location: data.Location,
} PID: -1,
standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, { StorageType: data.StorageType,
PID: pid, }, error || Error(data.StorageType + ' Unmounted'));
StorageType: data.StorageType, };
}); helpers
}) .executeMount(dataDirectory, data.Version, data.StorageType, data.Location, data.NoConsoleSupported, (error, pid) => {
.catch(error => { errorHandler(pid, error);
errorHandler(-1, 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) => { 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, () => { ipcMain.on(Constants.IPC_Shutdown, () => {
app.quit(); closeApplication();
}); });
ipcMain.on(Constants.IPC_Unmount_Drive, (event, data) => { ipcMain.on(Constants.IPC_Unmount_Drive, (event, data) => {
expectedUnmount[data.StorageType] = true; expectedUnmount[data.StorageType] = true;
helpers helpers
.stopProcessByPID(data.PID) .stopMountProcess(data.PID, data.Location)
.then((pid)=> { .then(()=> {
if (mountedPIDs.indexOf(pid) === -1) {
event.sender.send(Constants.IPC_Unmount_Drive_Reply);
}
}) })
.catch((e) => { .catch((e) => {
console.log(e); console.log(e);

View File

@@ -4,6 +4,7 @@ const os = require('os');
const axios = require('axios'); const axios = require('axios');
const exec = require('child_process').exec; const exec = require('child_process').exec;
const spawn = require('child_process').spawn; const spawn = require('child_process').spawn;
const Constants = require('./src/constants');
const tryParse = (j, def) => { const tryParse = (j, def) => {
try { try {
@@ -37,23 +38,15 @@ module.exports.detectRepertoryMounts = (directory, version) => {
}); });
process.on('exit', () => { process.on('exit', () => {
resolve(tryParse(result, { let defaultData = {};
Hyperspace: { for (const provider of Constants.PROVIDER_LIST) {
defaultData[provider] = {
Active: false, Active: false,
Location: '', Location: '',
PID: -1, PID: -1,
}, };
Sia: { }
Active: false, resolve(tryParse(result, defaultData));
Location: '',
PID: -1,
},
SiaPrime: {
Active: false,
Location: '',
PID: -1,
},
}));
}); });
process.unref(); 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) => { return new Promise((resolve) => {
const processOptions = { const processOptions = {
detached: true, detached: os.platform() === 'win32',
shell: true, shell: true,
stdio: 'ignore',
}; };
const command = path.join(directory, version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory'); const command = path.join(directory, version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory');
const args = []; const args = [];
if (storageType.toLowerCase() === 'hyperspace') { if (Constants.PROVIDER_ARG[storageType.toLowerCase()].length > 0) {
args.push('-hs'); args.push(Constants.PROVIDER_ARG[storageType.toLowerCase()]);
} else if (storageType.toLowerCase() === 'siaprime') {
args.push('-sp');
} }
if ((os.platform() === 'linux') || (os.platform() === 'darwin')) { if ((os.platform() === 'linux') || (os.platform() === 'darwin')) {
args.push('-o'); args.push('-o');
args.push('big_writes'); args.push('big_writes');
args.push('-f');
if (noConsoleSupported) {
args.push('-nc');
}
} else if (os.platform() === 'win32') { } else if (os.platform() === 'win32') {
args.push('-hidden'); args.push('-hidden');
} }
args.push(location); args.push(location);
const process = new spawn(command, args, processOptions); let process = new spawn(command, args, processOptions);
const pid = process.pid; const pid = process.pid;
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
@@ -196,11 +193,15 @@ module.exports.executeMount = (directory, version, storageType, location, exitCa
clearTimeout(timeout); clearTimeout(timeout);
exitCallback(err, pid); exitCallback(err, pid);
}); });
process.on('exit', (code) => { process.on('exit', (code) => {
clearTimeout(timeout); clearTimeout(timeout);
exitCallback(code, pid); 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 command = path.join(directory, version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory');
const args = []; const args = [];
args.push('-dc'); args.push('-dc');
if (storageType.toLowerCase() === 'hyperspace') { if (Constants.PROVIDER_ARG[storageType.toLowerCase()].length > 0) {
args.push('-hs'); args.push(Constants.PROVIDER_ARG[storageType.toLowerCase()]);
} else if (storageType.toLowerCase() === 'siaprime') {
args.push('-sp');
} }
const process = new spawn(command, args, processOptions); 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 command = path.join(directory, version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory');
const args = []; const args = [];
args.push('-gt'); args.push('-gt');
if (storageType.toLowerCase() === 'hyperspace') { if (Constants.PROVIDER_ARG[storageType.toLowerCase()].length > 0) {
args.push('-hs'); args.push(Constants.PROVIDER_ARG[storageType.toLowerCase()]);
} else if (storageType.toLowerCase() === 'siaprime') {
args.push('-sp');
} }
const process = new spawn(command, args, processOptions); const process = new spawn(command, args, processOptions);
@@ -428,10 +425,8 @@ module.exports.setConfigValue = (name, value, directory, storageType, version) =
args.push('-set'); args.push('-set');
args.push(name); args.push(name);
args.push(value); args.push(value);
if (storageType.toLowerCase() === 'hyperspace') { if (Constants.PROVIDER_ARG[storageType.toLowerCase()].length > 0) {
args.push('-hs'); args.push(Constants.PROVIDER_ARG[storageType.toLowerCase()]);
} else if (storageType.toLowerCase() === 'siaprime') {
args.push('-sp');
} }
const process = new spawn(command, args, processOptions); 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) => { return new Promise((resolve, reject) => {
const processOptions = { const processOptions = {
detached: true, detached: true,
shell: false, shell: true,
windowsHide: 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 = []; const args = [];
if (os.platform() === 'win32') { if (os.platform() === 'win32') {
args.push('/PID'); 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); const process = new spawn(command, args, processOptions);
process.on('error', (err) => { process.on('error', (err) => {
reject(err); reject(err);
}); });

View File

@@ -588,7 +588,10 @@ class App extends Component {
this.state.LocationsLookup[selectedVersion].config_support; this.state.LocationsLookup[selectedVersion].config_support;
const allowSiaPrime = this.state.LocationsLookup[selectedVersion] && 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 && const showDependencies = missingDependencies &&
!this.state.DownloadActive; !this.state.DownloadActive;
@@ -691,6 +694,7 @@ class App extends Component {
<MountItems {...providerProps} <MountItems {...providerProps}
allowConfig={allowConfig} allowConfig={allowConfig}
allowSiaPrime={allowSiaPrime} allowSiaPrime={allowSiaPrime}
noConsoleSupported={noConsoleSupported}
autoMountChanged={this.handleAutoMountChanged} autoMountChanged={this.handleAutoMountChanged}
autoMountProcessed={this.notifyAutoMountProcessed} autoMountProcessed={this.notifyAutoMountProcessed}
autoRestartChanged={this.handleAutoRestartChanged} autoRestartChanged={this.handleAutoRestartChanged}

View File

@@ -15,6 +15,12 @@ exports.PROVIDER_LIST = [
'SiaPrime' 'SiaPrime'
]; ];
exports.PROVIDER_ARG = {
hyperspace: '-hs',
sia: '',
siaprime: '-sp'
};
exports.IPC_Check_Dependency_Installed = 'check_dependency_installed'; exports.IPC_Check_Dependency_Installed = 'check_dependency_installed';
exports.IPC_Check_Dependency_Installed_Reply = 'check_dependency_installed'; exports.IPC_Check_Dependency_Installed_Reply = 'check_dependency_installed';

View File

@@ -74,6 +74,7 @@ class MountItems extends Component {
ipcRenderer.send(Constants.IPC_Mount_Drive, { ipcRenderer.send(Constants.IPC_Mount_Drive, {
Directory: this.props.directory, Directory: this.props.directory,
Location: location, Location: location,
NoConsoleSupported: this.props.noConsoleSupported,
StorageType: storageType, StorageType: storageType,
Version: this.props.version, Version: this.props.version,
}); });
@@ -145,7 +146,7 @@ class MountItems extends Component {
}; };
onUnmountDriveReply = (event, arg) => { onUnmountDriveReply = (event, arg) => {
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) this.handleMountUnMount(arg.data.StorageType, true, arg.data.Location)
} else { } else {
this.detectMounts(); this.detectMounts();