Some need changes and fixed the updater
This commit is contained in:
parent
4ded40e7ba
commit
d0687a26ba
16
main.ts
16
main.ts
@ -4,12 +4,28 @@ import * as rhelper from "./modules/shared/require";
|
||||
console.log("Native module path: %s", rhelper.native_module_path());
|
||||
|
||||
import * as crash_handler from "./modules/crash_handler";
|
||||
import * as child_process from "child_process";
|
||||
import {app} from "electron";
|
||||
|
||||
const is_electron_run = process.argv[0].endsWith("electron") || process.argv[0].endsWith("electron.exe");
|
||||
const process_arguments = is_electron_run ? process.argv.slice(2) : process.argv.slice(1);
|
||||
if(process_arguments.length > 0 && process_arguments[0] === "crash-handler") {
|
||||
/* crash handler callback */
|
||||
crash_handler.handle_crash_callback(process_arguments.slice(1));
|
||||
} else if(process_arguments.length > 0 && process_arguments[0] === "dtest") {
|
||||
console.log("Executing installer");
|
||||
try {
|
||||
let pipe = child_process.spawn("\"C:\\Program Files (x86)\\TeaSpeak\\update-installer.exe\"", [], {
|
||||
detached: true,
|
||||
shell: true,
|
||||
cwd: "C:\\Program Files (x86)\\TeaSpeak",
|
||||
stdio: "ignore"
|
||||
});
|
||||
} catch(error) {
|
||||
console.dir(error);
|
||||
}
|
||||
|
||||
setTimeout(() => app.exit(0), 2000);
|
||||
} else {
|
||||
if(process_arguments.length > 0 && process_arguments[0] == "--main-crash-handler")
|
||||
crash_handler.initialize_handler("main", is_electron_run);
|
||||
|
@ -118,31 +118,27 @@ export async function newest_version(current_version: Version, channel?: string)
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export async function extract_updater(update_file: string) {
|
||||
/**
|
||||
* @param update_file The input file from where the update will get installed
|
||||
* @return The target executable file
|
||||
*/
|
||||
export async function extract_updater(update_file: string) : Promise<string> {
|
||||
if(!fs.existsSync(update_file)) throw "Missing update file!";
|
||||
|
||||
|
||||
let parent_path = app.getAppPath();
|
||||
if(parent_path.endsWith(".asar")) {
|
||||
parent_path = path.join(parent_path, "..", "..");
|
||||
parent_path = fs.realpathSync(parent_path);
|
||||
}
|
||||
|
||||
let post_path;
|
||||
if(os.platform() == "linux")
|
||||
post_path = parent_path + "/update-installer";
|
||||
else
|
||||
post_path = parent_path + "/update-installer.exe";
|
||||
let update_installer = app.getPath('temp') + "/teaclient-update-installer-" + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
||||
if(os.platform() == "win32")
|
||||
update_installer += ".exe";
|
||||
|
||||
const source = fs.createReadStream(update_file);
|
||||
const extract = tar.extract();
|
||||
await new Promise(resolve => {
|
||||
await new Promise((resolve, reject) => {
|
||||
let updater_found = false;
|
||||
source.on('end', () => {
|
||||
if(!updater_found) {
|
||||
console.error("Failed to extract the updater (Updater hasn't been found!)");
|
||||
resolve(); //FIXME use reject!
|
||||
reject("Updater hasn't been found in bundle");
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
@ -151,13 +147,16 @@ export async function extract_updater(update_file: string) {
|
||||
console.log("Got entry " + header.name);
|
||||
|
||||
if(header.name == "./update-installer" || header.name == "./update-installer.exe") {
|
||||
console.log("Found updater! (" + header.size + ")");
|
||||
console.log("Extracting to %s", post_path);
|
||||
const s = fs.createWriteStream(post_path);
|
||||
console.log("Found updater! (" + header.size + " bytes)");
|
||||
console.log("Extracting to %s", update_installer);
|
||||
const s = fs.createWriteStream(update_installer);
|
||||
stream.pipe(s).on('finish', event => {
|
||||
console.log("Updater extracted and written!");
|
||||
updater_found = true;
|
||||
resolve();
|
||||
}).on('error', event => {
|
||||
console.error("Failed write update file: %o", event);
|
||||
reject("failed to write file")
|
||||
});
|
||||
} else {
|
||||
stream.resume(); //Drain the stream
|
||||
@ -167,6 +166,8 @@ export async function extract_updater(update_file: string) {
|
||||
|
||||
source.pipe(extract);
|
||||
});
|
||||
|
||||
return update_installer;
|
||||
}
|
||||
|
||||
export async function update_updater() : Promise<void> {
|
||||
@ -466,6 +467,7 @@ export async function execute_update(update_file: string, restart_callback: (cal
|
||||
console.log("Using update file: %s", update_file);
|
||||
|
||||
const temp_directory = path.join(app.getPath("temp"), "teaclient_update_" + Math.random().toString(36).substring(7));
|
||||
let updater_executable;
|
||||
{
|
||||
console.log("Preparing update source directory at %s", temp_directory);
|
||||
try {
|
||||
@ -486,8 +488,9 @@ export async function execute_update(update_file: string, restart_callback: (cal
|
||||
if(header.type == "directory") {
|
||||
await fs.mkdirp(target_file);
|
||||
} else if(header.type == "file") {
|
||||
const target_finfo = path.parse(target_file);
|
||||
{
|
||||
const directory = path.parse(target_file).dir;
|
||||
const directory = target_finfo.dir;
|
||||
console.debug("Testing for directory: %s", directory);
|
||||
if(!(await util.promisify(ofs.exists)(directory)) || !(await util.promisify(ofs.stat)(directory)).isDirectory()) {
|
||||
console.log("Creating directory %s", directory);
|
||||
@ -506,6 +509,12 @@ export async function execute_update(update_file: string, restart_callback: (cal
|
||||
.on('error', reject)
|
||||
.on('finish', resolve);
|
||||
});
|
||||
|
||||
if(target_finfo.name === "update-installer" || target_finfo.name === "update-installer.exe") {
|
||||
updater_executable = target_file;
|
||||
console.log("Found update installer: %s", target_file);
|
||||
}
|
||||
|
||||
return; /* success */
|
||||
} catch(error) {
|
||||
console.error("Failed to extract update file %s: %o", header.name, error);
|
||||
@ -534,6 +543,10 @@ export async function execute_update(update_file: string, restart_callback: (cal
|
||||
throw "update unpacking failed";
|
||||
}
|
||||
}
|
||||
|
||||
if(typeof(updater_executable) !== "string" || !(await fs.pathExists(updater_executable)))
|
||||
throw "missing update installer executable within update package";
|
||||
|
||||
/* the "new" environment should now be available at 'temp_directory' */
|
||||
console.log("Update unpacked successfully. Building update extractor file.");
|
||||
|
||||
@ -555,22 +568,14 @@ export async function execute_update(update_file: string, restart_callback: (cal
|
||||
throw "failed to write update install config file";
|
||||
}
|
||||
|
||||
const update_installer = path.join(application_path, "update-installer" + (os.platform() === "win32" ? ".exe" : ""));
|
||||
if(!(await fs.pathExists(update_installer))) {
|
||||
console.error("Missing update installer! Supposed to be at %s", update_installer);
|
||||
throw "Missing update installer!";
|
||||
} else {
|
||||
console.log("Using update installer located at %s", update_installer);
|
||||
}
|
||||
|
||||
if(os.platform() == "linux") {
|
||||
console.log("Executing update install on linux");
|
||||
|
||||
//We have to unpack it later
|
||||
const rest_callback = () => {
|
||||
console.log("Executing command %s with args %o", update_installer, [log_file, config_file]);
|
||||
console.log("Executing command %s with args %o", updater_executable, [log_file, config_file]);
|
||||
try {
|
||||
let result = child_process.spawnSync(update_installer, [log_file, config_file]);
|
||||
let result = child_process.spawnSync(updater_executable, [log_file, config_file]);
|
||||
if(result.status != 0) {
|
||||
console.error("Failed to execute update installer! Return code: %d", result.status);
|
||||
dialog.showMessageBox({
|
||||
@ -621,13 +626,21 @@ export async function execute_update(update_file: string, restart_callback: (cal
|
||||
|
||||
//We have to unpack it later
|
||||
const rest_callback = () => {
|
||||
let pipe = child_process.spawn(update_installer, [log_file, config_file], {
|
||||
detached: true,
|
||||
cwd: application_path,
|
||||
stdio: 'ignore',
|
||||
});
|
||||
pipe.unref();
|
||||
app.quit();
|
||||
console.log("Executing command %s with args %o", updater_executable, [log_file, config_file]);
|
||||
|
||||
try {
|
||||
const pipe = child_process.spawn(updater_executable, [log_file, config_file], {
|
||||
detached: true,
|
||||
shell: true,
|
||||
cwd: path.dirname(app.getAppPath()),
|
||||
stdio: "ignore"
|
||||
});
|
||||
pipe.unref();
|
||||
app.quit();
|
||||
} catch(error) {
|
||||
console.dir(error);
|
||||
electron.dialog.showErrorBox("Failed to finalize update", "Failed to finalize update.\nInvoking the update-installer.exe failed.\nLookup the console for more details.");
|
||||
}
|
||||
};
|
||||
restart_callback(rest_callback);
|
||||
}
|
||||
|
21
modules/core/instance_handler.ts
Normal file
21
modules/core/instance_handler.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import * as electron from "electron";
|
||||
import * as main_window from "./main_window";
|
||||
|
||||
export function handle_second_instance_call(argv: string[], work_dir: string) {
|
||||
const original_args = argv.slice(1).filter(e => !e.startsWith("--original-process-start-time=") && e != "--allow-file-access-from-files");
|
||||
console.log("Second instance: %o", original_args);
|
||||
|
||||
if(!main_window.main_window) {
|
||||
console.warn("Ignoring second instance call because we haven't yet started");
|
||||
return;
|
||||
}
|
||||
main_window.main_window.focus();
|
||||
|
||||
{
|
||||
const connect_url = argv.find(e => e.startsWith("teaclient://"));
|
||||
if(connect_url) {
|
||||
console.log("Received connect url: %s", connect_url);
|
||||
main_window.main_window.webContents.send('connect', connect_url);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// Quit when all windows are closed.
|
||||
import * as electron from "electron";
|
||||
import * as app_updater from "./app-updater";
|
||||
import * as instance_handler from "./instance_handler";
|
||||
|
||||
import { app } from "electron";
|
||||
import MessageBoxOptions = electron.MessageBoxOptions;
|
||||
@ -35,8 +36,6 @@ async function execute_app() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(process_args.has_value("update-execute")) {
|
||||
console.log("Executing update " + process_args.value("update-execute"));
|
||||
await app_updater.execute_update(process_args.value("update-execute"), callback => {
|
||||
@ -153,6 +152,12 @@ async function execute_app() {
|
||||
}
|
||||
}
|
||||
|
||||
/* register client a teaclient:// handler */
|
||||
if(app.getAppPath().endsWith(".asar")) {
|
||||
if(!app.setAsDefaultProtocolClient("teaclient", app.getPath("exe")))
|
||||
console.error("Failed to setup default teaclient protocol handler");
|
||||
}
|
||||
|
||||
try {
|
||||
{
|
||||
const version = await app_updater.current_version();
|
||||
@ -176,32 +181,26 @@ async function execute_app() {
|
||||
|
||||
function main() {
|
||||
process.on('uncaughtException', err => {
|
||||
console.error(err, 'Uncaught Exception thrown');
|
||||
console.error('Uncaught Exception thrown:');
|
||||
console.dir(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
/*
|
||||
if(false) {
|
||||
SegfaultHandler = require('segfault-handler');
|
||||
|
||||
SegfaultHandler.registerHandler("crash.log"); // With no argument, SegfaultHandler will generate a generic log file name
|
||||
}
|
||||
|
||||
const SegfaultHandler = require('segfault-handler');
|
||||
SegfaultHandler.registerHandler("crash.log"); // With no argument, SegfaultHandler will generate a generic log file name
|
||||
*/
|
||||
if(app) { //We're executed!
|
||||
parse_arguments();
|
||||
if(process_args.has_value(Arguments.DISABLE_HARDWARE_ACCELERATION))
|
||||
app.disableHardwareAcceleration();
|
||||
|
||||
if(process_args.has_value(Arguments.DUMMY_CRASH_MAIN))
|
||||
crash_handler.handler.crash();
|
||||
|
||||
if(!process_args.has_value(Arguments.DEBUG) && !process_args.has_value(Arguments.NO_SINGLE_INSTANCE)) {
|
||||
if(!app.requestSingleInstanceLock()) {
|
||||
console.log("Another instance is already running. Closing this instance");
|
||||
app.exit(0);
|
||||
}
|
||||
|
||||
app.on('second-instance', (event, argv, workingDirectory) => instance_handler.handle_second_instance_call(argv, workingDirectory));
|
||||
}
|
||||
app.on('ready', execute_app);
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ function spawn_main_window(entry_point: string) {
|
||||
});
|
||||
|
||||
main_window.on('closed', () => {
|
||||
app.releaseSingleInstanceLock();
|
||||
require("./url-preview").close();
|
||||
main_window = null;
|
||||
prevent_instant_close = false;
|
||||
|
9
modules/renderer/app_backend.ts
Normal file
9
modules/renderer/app_backend.ts
Normal file
@ -0,0 +1,9 @@
|
||||
window["require_setup"](module);
|
||||
|
||||
import * as electron from "electron";
|
||||
const remote = electron.remote;
|
||||
|
||||
electron.ipcRenderer.on('connect', (event, url) => {
|
||||
console.log(tr("Received connect event to %s"), url);
|
||||
console.error(tr("Dropping connect event (Currently not supported)"));
|
||||
});
|
@ -200,6 +200,13 @@ const load_modules = async () => {
|
||||
console.dir(error);
|
||||
throw error;
|
||||
}
|
||||
try {
|
||||
require("./app_backend");
|
||||
} catch(error) {
|
||||
console.error("Failed to load renderer app backend");
|
||||
console.dir(error);
|
||||
throw error;
|
||||
}
|
||||
try {
|
||||
const helper = require("./icon-helper");
|
||||
await helper.initialize();
|
||||
|
@ -40,7 +40,7 @@ export function parse_arguments() {
|
||||
const minimist: <T> (args, opts) => T = require("./minimist") as any;
|
||||
let args = minimist<Arguments>(is_electron_run ? process.argv.slice(2) : process.argv.slice(1), {
|
||||
boolean: true,
|
||||
stopEarly: true
|
||||
"--": true
|
||||
}) as Arguments;
|
||||
args.has_flag = (...keys) => {
|
||||
for(const key of [].concat(...Array.of(...keys).map(e => Array.isArray(e) ? Array.of(...e) : [e])))
|
||||
|
@ -57,7 +57,7 @@ namespace minimist {
|
||||
const parse = (args: string[], options: minimist.Opts) => {
|
||||
options = options || {};
|
||||
|
||||
var flags = { bools : {}, strings : {}, unknownFn: null, allBools: false };
|
||||
let flags = { bools : {}, strings : {}, unknownFn: null, allBools: false };
|
||||
|
||||
if (typeof options['unknown'] === 'function') {
|
||||
flags.unknownFn = options['unknown'];
|
||||
@ -71,7 +71,7 @@ const parse = (args: string[], options: minimist.Opts) => {
|
||||
});
|
||||
}
|
||||
|
||||
var aliases = {};
|
||||
let aliases = {};
|
||||
Object.keys(options.alias || {}).forEach(function (key) {
|
||||
aliases[key] = [].concat(options.alias[key]);
|
||||
aliases[key].forEach(function (x) {
|
||||
@ -88,14 +88,14 @@ const parse = (args: string[], options: minimist.Opts) => {
|
||||
}
|
||||
});
|
||||
|
||||
var defaults = options['default'] || {};
|
||||
let defaults = options['default'] || {};
|
||||
|
||||
var argv = { _ : [] };
|
||||
let argv = { _ : [] };
|
||||
Object.keys(flags.bools).forEach(function (key) {
|
||||
setArg(key, defaults[key] === undefined ? false : defaults[key]);
|
||||
});
|
||||
|
||||
var notFlags = [];
|
||||
let notFlags = [];
|
||||
|
||||
if (args.indexOf('--') !== -1) {
|
||||
notFlags = args.slice(args.indexOf('--')+1);
|
||||
@ -147,16 +147,16 @@ const parse = (args: string[], options: minimist.Opts) => {
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
var arg = args[i];
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
let arg = args[i];
|
||||
|
||||
if (/^--.+=/.test(arg)) {
|
||||
// Using [\s\S] instead of . because js doesn't support the
|
||||
// 'dotall' regex modifier. See:
|
||||
// http://stackoverflow.com/a/1068308/13216
|
||||
var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
|
||||
var key = m[1];
|
||||
var value: any = m[2];
|
||||
let m = arg.match(/^--([^=]+)=([\s\S]*)$/);
|
||||
let key = m[1];
|
||||
let value: any = m[2];
|
||||
if (flags.bools[key]) {
|
||||
value = value !== 'false';
|
||||
}
|
||||
@ -169,8 +169,8 @@ const parse = (args: string[], options: minimist.Opts) => {
|
||||
}
|
||||
*/
|
||||
else if (/^--.+/.test(arg)) {
|
||||
var key = arg.match(/^--(.+)/)[1];
|
||||
var next = args[i + 1];
|
||||
let key = arg.match(/^--(.+)/)[1];
|
||||
let next = args[i + 1];
|
||||
if (next !== undefined && !/^-/.test(next)
|
||||
&& !flags.bools[key]
|
||||
&& !flags.allBools
|
||||
@ -187,11 +187,11 @@ const parse = (args: string[], options: minimist.Opts) => {
|
||||
}
|
||||
}
|
||||
else if (/^-[^-]+/.test(arg)) {
|
||||
var letters = arg.slice(1,-1).split('');
|
||||
let letters = arg.slice(1,-1).split('');
|
||||
|
||||
var broken = false;
|
||||
for (var j = 0; j < letters.length; j++) {
|
||||
var next = arg.slice(j+2);
|
||||
let broken = false;
|
||||
for (let j = 0; j < letters.length; j++) {
|
||||
let next = arg.slice(j+2);
|
||||
|
||||
if (next === '-') {
|
||||
setArg(letters[j], next, arg)
|
||||
@ -221,7 +221,7 @@ const parse = (args: string[], options: minimist.Opts) => {
|
||||
}
|
||||
}
|
||||
|
||||
var key = arg.slice(-1)[0];
|
||||
let key = arg.slice(-1)[0];
|
||||
if (!broken && key !== '-') {
|
||||
if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
|
||||
&& !flags.bools[key]
|
||||
@ -262,7 +262,7 @@ const parse = (args: string[], options: minimist.Opts) => {
|
||||
});
|
||||
|
||||
if (options['--']) {
|
||||
argv['--'] = new Array();
|
||||
argv['--'] = [];
|
||||
notFlags.forEach(function(key) {
|
||||
argv['--'].push(key);
|
||||
});
|
||||
@ -277,12 +277,12 @@ const parse = (args: string[], options: minimist.Opts) => {
|
||||
};
|
||||
|
||||
function hasKey (obj, keys) {
|
||||
var o = obj;
|
||||
let o = obj;
|
||||
keys.slice(0,-1).forEach(function (key) {
|
||||
o = (o[key] || {});
|
||||
});
|
||||
|
||||
var key = keys[keys.length - 1];
|
||||
let key = keys[keys.length - 1];
|
||||
return key in o;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
"start-d1": "electron . --disable-hardware-acceleration --debug -t --gdb -su http://clientapi.teaspeak.dev/ --updater-ui-loader_type=0",
|
||||
"start-n": "electron . -t --disable-hardware-acceleration --no-single-instance -u=https://clientapi.teaspeak.de/ -d --updater-ui-loader_type=0",
|
||||
"start-01": "electron . --updater-channel=test -u=http://dev.clientapi.teaspeak.de/ -d --updater-ui-loader_type=0 --updater-local-version=1.0.1",
|
||||
"dtest": "electron . dtest",
|
||||
"compile-sass": "sass --update .:.",
|
||||
"compile-tsc": "tsc",
|
||||
"build-linux-64": "node installer/build.js linux",
|
||||
|
Loading…
Reference in New Issue
Block a user