From dbad3b51a04659562b048c1bef42d23bdf9140ca Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 30 Aug 2019 09:04:47 +0200 Subject: [PATCH 01/47] Set header text implicitly --- src/html/index.pug | 2 +- src/html/scripts/main.pug | 1 - src/html/scripts/ui.pug | 8 -------- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/html/index.pug b/src/html/index.pug index 6c1a32f1..b9a58994 100644 --- a/src/html/index.pug +++ b/src/html/index.pug @@ -6,7 +6,7 @@ html body include scripts/root .header.is-over - h3#header-text.text-muted.installer UBports Installer + h3#header-text.text-muted.installer UBports Installer (#{global.packageInfo.version}) button#help.help-button.btn.btn-primary.is-over Report a bug button#donate.donate-button.btn.btn-primary.is-over Donate #particles-background.vertical-centered-box diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index 0f6fd9cd..05a42fce 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -195,7 +195,6 @@ script. // START utils.log.info("Welcome to the UBports Installer version " + global.packageInfo.version + "!"); - header.version_info.set(global.packageInfo.version); views.show("working", "particles"); footer.topText.set("UBports Installer is starting up").append("."); footer.underText.set("Starting adb service..."); diff --git a/src/html/scripts/ui.pug b/src/html/scripts/ui.pug index fd754a26..07098a16 100644 --- a/src/html/scripts/ui.pug +++ b/src/html/scripts/ui.pug @@ -101,14 +101,6 @@ script. remove: id => setText("user", id, "") } - const header = { - version_info: { - set: (text) => { - return $('#header-text').text('UBports Installer ('+text+')'); - } - } - } - const footer = { topText: { set: (text) => { From 4e92f2f8d28392f2d69aa8110d4ee90566df56e6 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 30 Aug 2019 09:58:03 +0200 Subject: [PATCH 02/47] Improve footer text handling --- src/html/index.pug | 13 ++++--------- src/html/scripts/main.pug | 26 ++++++++++++-------------- src/html/scripts/ui.pug | 8 +++++--- src/main.js | 4 ++-- 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/html/index.pug b/src/html/index.pug index b9a58994..88ec933b 100644 --- a/src/html/index.pug +++ b/src/html/index.pug @@ -24,15 +24,10 @@ html include views/working #progress.progress(hidden='hidden') footer.footer.is-over - #waitForDevice.container(hidden='hidden') - h3.text-muted.footer-top - | Waiting for a device - span#wait-dot - p.text-muted Connect the device to the computer with a USB cable. - #device.container - h3#device-name.text-muted.footer-top - | UBports Installer is starting up - p#device-under-text.text-muted Starting adb service... + .container + h3#footer-top.text-muted.footer-top UBports Installer is starting up + span#wait-dot(hidden='false') . + p#footer-bottom.text-muted Starting adb service // --- Modals --- include modals/install include modals/connection-lost diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index 05a42fce..155f3e30 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -24,7 +24,7 @@ script. installEvent.on("user:error", onErr); installEvent.on("bootstrap:flashing", () => { views.show("working", "particles"); - $("#device-under-text").text("Flashing recovery and boot images") + footer.underText.set("Flashing recovery and boot images") }); installEvent.on("system-image:start", () => { views.show("working", "particles"); @@ -88,8 +88,8 @@ script. views.show("reboot-" + i.button); $("[id=reboot-to-state]").text(i.state); $("#complex-reboot-instruction").text(i.instruction); - $("#device-name").text("Please reboot to "+i.state); - $("#device-under-text").text(i.instruction.split(".")[0]); + footer.topText.set("Please reboot to "+i.state); + footer.underText.set(i.instruction.split(".")[0]); }); installEvent.on("adb:rebooted", () => { $('#views-reboot-up').hide(); @@ -101,10 +101,10 @@ script. $('#views-reboot-down').hide(); }); installEvent.on("user:write:next", (text, current, total) => { - $("#device-under-text").text(text + " file " + current + " of " + total); + footer.underText.set(text + " file " + current + " of " + total); }); installEvent.on("user:write:start", (text, length) => { - $("#device-under-text").text(text+" file 1 of "+length); + footer.underText.set(text+" file 1 of "+length); }); installEvent.on("user:write:progress", (length) => { if(length >= 100) { @@ -117,13 +117,13 @@ script. remote.getCurrentWindow().close(); } else { views.show("done"); - $("#device-name").text("Done"); - $("#device-under-text").text("It is now safe to unplug the device."); + footer.topText.set("Done"); + footer.underText.set("It is now safe to unplug the device."); $("#progress").width("0%"); } }); installEvent.on("user:write:status", (status) => { - $("#device-name").text(status).append("."); + footer.topText.set(status, true) }); } @@ -131,8 +131,8 @@ script. utils.log.debug("mainEvent called") var installEvent; if(!output) { - $("#device-name").text("Device not supported"); - $("#device-under-text").text("The device " + device + " is not supported"); + footer.topText.set("Device not supported"); + footer.underText.set("The device " + device + " is not supported"); $("[id=your-device]").text(device) views.show("not-supported"); utils.log.warn("This device is not supported!") @@ -154,7 +154,7 @@ script. options.optionsValToUser(); modals.hide('select-device'); $("#btn-inst").show(); - $("#device-name").text(output.name); + footer.topText.set(output.name); if (isLegacyAndroid && !ubuntuCom) $("#legacy-android-note").show(); if (isLegacyAndroid) @@ -196,8 +196,6 @@ script. // START utils.log.info("Welcome to the UBports Installer version " + global.packageInfo.version + "!"); views.show("working", "particles"); - footer.topText.set("UBports Installer is starting up").append("."); - footer.underText.set("Starting adb service..."); devices.getDeviceSelects((out) => { if (out) { @@ -210,7 +208,7 @@ script. adb.start(false, false, (err) => { var waitEvent = devices.waitForDevice(mainEvent); if (!global.installProperties.device) { - footer.topText.set("Waiting for device").append("."); + footer.topText.set("Waiting for device", true) footer.underText.set("Please connect your device with a USB cable"); views.show("wait-for-device"); // Button to open device selector diff --git a/src/html/scripts/ui.pug b/src/html/scripts/ui.pug index 07098a16..31cdcd19 100644 --- a/src/html/scripts/ui.pug +++ b/src/html/scripts/ui.pug @@ -103,13 +103,15 @@ script. const footer = { topText: { - set: (text) => { - return $("#device-name").text(text) + set: (text, dots) => { + if (dots) $("#wait-dot").show() + else $("#wait-dot").hide() + return $("#footer-top").text(text) } }, underText: { set: (text) => { - return $("#device-under-text").text(text) + return $("#footer-bottom").text(text) } } } diff --git a/src/main.js b/src/main.js index 44d7643f..e4528c57 100755 --- a/src/main.js +++ b/src/main.js @@ -47,11 +47,11 @@ global.installProperties = { simulate: cli.simulate }; -ipcMain.on( "setInstallProperties", ( event, installProperties ) => { +ipcMain.on("setInstallProperties", ( event, installProperties ) => { global.installProperties = Object.assign(global.installProperties, installProperties); }); -ipcMain.on( "die", (exitCode) => { +ipcMain.on("die", (exitCode) => { process.exit(exitCode); }); From 241fef8d69af39c4dd5849155fcd47f98653aa63 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 26 Sep 2019 12:08:23 +0200 Subject: [PATCH 03/47] Move all logic to main and let renderer focus on the rendering --- src/adb.js | 68 ++---- src/devices.js | 387 ++++++++++++++++------------------- src/fastboot.js | 1 + src/html/modals/error.pug | 4 +- src/html/modals/oem-lock.pug | 2 + src/html/modals/options.pug | 6 +- src/html/scripts/main.pug | 372 ++++++++++++++++----------------- src/html/scripts/root.pug | 4 - src/html/scripts/ui.pug | 57 +++--- src/main.js | 193 ++++++++++++++++- src/system-image.js | 28 +-- src/utils.js | 38 ++-- 12 files changed, 616 insertions(+), 544 deletions(-) diff --git a/src/adb.js b/src/adb.js index a80b5704..5075c45d 100644 --- a/src/adb.js +++ b/src/adb.js @@ -12,16 +12,12 @@ const sys = require('util') const cp = require('child_process'); const path = require("path"); const fs = require("fs"); -const events = require("events") -const fEvent = require('forward-emitter'); const utils = require("./utils"); const exec = require('child_process').exec; // DEFAULT = 5037 const PORT = 5038 -class event extends events {} - // Since we need root anyway, why not start adb with root const start = (password, sudo, callback) => { // Make sure the server is not running @@ -140,10 +136,6 @@ var readUbuntuChannelINI = (callback) => { } var isBaseUbuntuCom = callback => { - if (global.installProperties.simulate) { - callback(global.installProperties.currentOs == "ubuntu"); - return; - } readUbuntuChannelINI(ini => { if (!ini) return callback(false); @@ -151,13 +143,7 @@ var isBaseUbuntuCom = callback => { }); } -var push = (file, dest, pushEvent) => { - if (global.installProperties.simulate) { - return setTimeout(() => { - pushEvent.emit("adbpush:progress", 50); - pushEvent.emit("adbpush:end"); - }, 50); - } +var push = (file, dest) => { var done; var hundredEmitted; var fileSize = fs.statSync(file)["size"]; @@ -170,22 +156,22 @@ var push = (file, dest, pushEvent) => { if (stderrShort.indexOf("I/O error") != -1) { utils.log.warn("connection to device lost"); // TODO: Only restart the event rather than the entire installation - pushEvent.emit("user:connection-lost", () => { location.reload(); }); + mainEvent.emit("user:connection-lost", () => { mainWindow.reload(); }); } else if (!err.killed && (err.code == 1)) { hasAdbAccess ((hasAccess) => { if (hasAccess) { - pushEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); + mainEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); } else { utils.log.warn("connection to device lost"); // TODO: Only restart the event rather than the entire installation - pushEvent.emit("user:connection-lost", () => { location.reload(); }); + mainEvent.emit("user:connection-lost", () => { mainWindow.reload(); }); } }); } else { - pushEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); + mainEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); } } - else pushEvent.emit("adbpush:end"); + else mainEvent.emit("adbpush:end"); }); var progress = () => { setTimeout(function () { @@ -193,7 +179,7 @@ var push = (file, dest, pushEvent) => { try { var currentSize = stat.split(" ")[1]; var percentage = Math.ceil((currentSize/fileSize)*100); - if(!isNaN(percentage) && !hundredEmitted) pushEvent.emit("adbpush:progress", percentage); + if(!isNaN(percentage) && !hundredEmitted) mainEvent.emit("adbpush:progress", percentage); if(percentage == 100) hundredEmitted = true; if(!done && (percentage < fileSize)) progress(); } catch (e) { } @@ -201,28 +187,26 @@ var push = (file, dest, pushEvent) => { }, 1000); } progress(); - return pushEvent; } -var pushMany = (files, pushManyEvent) => { +var pushMany = (files) => { var totalLength = files.length; if (files.length <= 0){ - pushManyEvent.emit("adbpush:error", "No files provided"); + mainEvent.emit("adbpush:error", "No files provided"); return false; } - pushManyEvent.emit("adbpush:start", files.length); - push(files[0].src, files[0].dest, pushManyEvent); - pushManyEvent.on("adbpush:end", () => { + mainEvent.emit("adbpush:start", files.length); + push(files[0].src, files[0].dest); + mainEvent.on("adbpush:end", () => { files.shift(); if (files.length <= 0){ - pushManyEvent.emit("adbpush:done"); + mainEvent.emit("adbpush:done"); return; } else { - pushManyEvent.emit("adbpush:next", totalLength-files.length+1, totalLength) - push(files[0].src, files[0].dest, pushManyEvent); + mainEvent.emit("adbpush:next", totalLength-files.length+1, totalLength) + push(files[0].src, files[0].dest); } }); - return pushManyEvent } var shell = (cmd, callback) => { @@ -234,13 +218,6 @@ var shell = (cmd, callback) => { } var waitForDevice = (callback) => { - if (global.installProperties.simulate) { - setTimeout(() => { - callback(true); - return new event(); - }, 1000); - } - var waitEvent = new event(); let timer = setInterval(() => { shell("echo 1", (r) => { if(r){ @@ -250,10 +227,9 @@ var waitForDevice = (callback) => { } }); }, 2000); - waitEvent.on("stop", () => { + mainEvent.on("stop", () => { clearInterval(timer); }); - return waitEvent; } var hasAdbAccess = (callback) => { @@ -263,10 +239,6 @@ var hasAdbAccess = (callback) => { } var reboot = (state, callback) => { - if (global.installProperties.simulate) { - callback(true); - return; - } utils.log.debug("reboot to "+state); utils.platformToolsExec("adb", ["-P", PORT, "reboot", state], (err, stdout, stderr) => { utils.log.debug("reboot to " + state + " done"); @@ -278,10 +250,6 @@ var reboot = (state, callback) => { } var format = (partition, callback) => { - if (global.installProperties.simulate) { - callback(true); - return; - } shell("cat /etc/recovery.fstab", (fstab_) => { if (!fstab_) { callback(false, "cannot find recovery.fstab"); @@ -314,10 +282,6 @@ var format = (partition, callback) => { } var wipeCache = (callback) => { - if (global.installProperties.simulate) { - callback(true); - return; - } // Try with format; format("cache", (err) => { if (!err){ diff --git a/src/devices.js b/src/devices.js index bc7cf64c..35626e66 100644 --- a/src/devices.js +++ b/src/devices.js @@ -16,11 +16,6 @@ const systemImage = require("./system-image"); const utils = require("./utils"); const os = require("os"); const path = require("path"); -const events = require("events") -const fEvent = require('forward-emitter'); -//const wildcard = require("wildcard"); - -class event extends events {} const devicesApi = new ubportsApi.Devices(); const downloadPath = utils.getUbuntuTouchDir(); @@ -36,10 +31,10 @@ var isLegacyAndroid = (device) => { case "frieza": case "turbo": case "arale": - console.log("This is a legacy android device") + utils.log.info("This is a legacy android device"); return true; default: - console.log("This is NOT a legacy android device") + utils.log.debug("This is NOT a legacy android device"); return false; } } @@ -60,12 +55,12 @@ var formatNotWorking = (nw) => { return nw.join(", ").replace("/\,(?=[^,]*$)", " and"); } -var instructReboot = (state, button, rebootEvent, callback) => { +var instructReboot = (state, button, callback) => { var rebooted = false; var manualReboot = () => { utils.log.info("Instructing manual reboot"); utils.log.info(button[state]["instruction"]); - rebootEvent.emit("user:reboot", { + global.mainEvent.emit("user:reboot", { button: button[state]["button"], instruction: button[state]["instruction"], state: state @@ -78,22 +73,22 @@ var instructReboot = (state, button, rebootEvent, callback) => { utils.log.warn("Adb failed to reboot!, " + out + " : " + eout); manualReboot(); } else { - rebootEvent.emit("adb:rebooted"); + global.mainEvent.emit("adb:rebooted"); } }); } else { manualReboot(); } if (state === "bootloader") { - requestPassword(rebootEvent, (pass) => { + requestPassword((pass) => { fastboot.waitForDevice(pass, (err, errM) => { if (err) { - rebootEvent.emit("Error", errM); + global.mainEvent.emit("Error", errM); return; } else { rebooted = true; - rebootEvent.emit("reboot:done"); - rebootEvent.emit("state:bootloader"); + global.mainEvent.emit("reboot:done"); + global.mainEvent.emit("state:bootloader"); callback(); return; } @@ -103,8 +98,8 @@ var instructReboot = (state, button, rebootEvent, callback) => { adb.waitForDevice(() => { rebooted = true; // We expect the device state to mach installState now - rebootEvent.emit("reboot:done"); - rebootEvent.emit("state:" + state); + global.mainEvent.emit("reboot:done"); + global.mainEvent.emit("state:" + state); callback(); return; }); @@ -113,7 +108,7 @@ var instructReboot = (state, button, rebootEvent, callback) => { setTimeout(() => { if (!rebooted) manualReboot() }, 15000); } -var requestPassword = (bootstrapEvent, callback) => { +var requestPassword = (callback) => { if (!utils.needRoot()) { callback(""); return; @@ -122,27 +117,27 @@ var requestPassword = (bootstrapEvent, callback) => { callback(password); return; } - bootstrapEvent.emit("user:password"); - bootstrapEvent.once("password", (p) => { + global.mainEvent.emit("user:password"); + global.mainEvent.once("password", (p) => { utils.checkPassword(p, (correct, err) => { if (correct) { password=p; callback(p); } else if (err.password) { - bootstrapEvent.emit("user:password:wrong"); - requestPassword(bootstrapEvent, callback); + global.mainEvent.emit("user:password:wrong"); + requestPassword(callback); } else { - bootstrapEvent.emit("error", err.message) + global.mainEvent.emit("error", err.message) } }); }); } -var instructOemUnlock = (unlockEvent, callback) => { - requestPassword(unlockEvent, (p) => { +var instructOemUnlock = (callback) => { + requestPassword((p) => { fastboot.oemUnlock(password, (err, errM) => { if (err) { - unlockEvent.emit("error", errM); + global.mainEvent.emit("error", errM); callback(true); } else { callback(false); @@ -151,32 +146,32 @@ var instructOemUnlock = (unlockEvent, callback) => { }) } -var handleBootstrapError = (err, errM, bootstrapEvent, backToFunction) => { +var handleBootstrapError = (err, errM, backToFunction) => { if (err.bootFailed) { utils.log.warn("fastboot boot failed, does the " + global.installProperties.device + " really support it?"); - bootstrapEvent.emit("bootstrap:done", false); // This will instruct a manual reboot + global.mainEvent.emit("bootstrap:done", false); // This will instruct a manual reboot } else if (err.password) { - bootstrapEvent.emit("user:password:wrong", backToFunction); + ipcRenderer.send("user:password:wrong", backToFunction); } else if (err.connectionLost) { utils.log.warn("connection to device lost"); - bootstrapEvent.emit("user:connection-lost", backToFunction); + global.mainEvent.emit("user:connection-lost", backToFunction); } else if (err.locked) { - bootstrapEvent.emit("user:oem-lock", backToFunction); + global.mainEvent.emit("user:oem-lock", backToFunction); } else if (err.lowPower) { - bootstrapEvent.emit("user:low-power"); + global.mainEvent.emit("user:low-power"); } else { - bootstrapEvent.emit("error", errM); + global.mainEvent.emit("error", errM); } } -var instructBootstrap = (bootstrap, images, bootstrapEvent) => { +var instructBootstrap = (bootstrap, images) => { //TODO check bootloader name/version/device var flash = (p) => { utils.log.info("Flashing images...") fastboot.flash(images, (err, errM) => { if (err) { - handleBootstrapError(err, errM, bootstrapEvent, () => { - instructBootstrap(bootstrap, images, bootstrapEvent); + handleBootstrapError(err, errM, () => { + instructBootstrap(bootstrap, images); }); } else { if (bootstrap) { // The device supports the "fastboot boot" command @@ -189,30 +184,30 @@ var instructBootstrap = (bootstrap, images, bootstrapEvent) => { }); // If we can't find it, report error! if (!recoveryImg) { - bootstrapEvent.emit("error", "Cant find recoveryImg to boot: "+images); + global.mainEvent.emit("error", "Cant find recoveryImg to boot: "+images); } else { fastboot.boot(recoveryImg, p, (err, errM) => { if (err) { - handleBootstrapError(err, errM, bootstrapEvent, () => { - instructBootstrap(bootstrap, images, bootstrapEvent); + handleBootstrapError(err, errM, () => { + instructBootstrap(bootstrap, images); }); } else { - bootstrapEvent.emit("bootstrap:done", bootstrap); + global.mainEvent.emit("bootstrap:done", bootstrap); } }); } } else { // The device needs to be rebooted manually - bootstrapEvent.emit("bootstrap:done", false); + global.mainEvent.emit("bootstrap:done", false); } } }, p); } - bootstrapEvent.emit("bootstrap:flashing") - bootstrapEvent.emit("user:write:status", "Flashing images") + global.mainEvent.emit("bootstrap:flashing") + global.mainEvent.emit("user:write:status", "Flashing images") if (!utils.needRoot()) { flash(false); } else { - requestPassword(bootstrapEvent, (p) => { + requestPassword((p) => { flash(p); }); } @@ -227,77 +222,75 @@ var addPathToImages = (images, device) => { return ret; } -var setEvents = (downloadEvent) => { - downloadEvent.on("download:done", () => { - utils.log.info("Download complete"); - downloadEvent.emit("user:write:progress", 0); - }); - downloadEvent.on("download:error", (r) => { - utils.log.error("Devices: Download error "+r); - }); - downloadEvent.on("error", (r) => { - downloadEvent.emit("user:error", r); - utils.log.error("Devices: Error: "+r); - }); - downloadEvent.on("download:checking", () => { - utils.log.info("Download checking file"); - }); - downloadEvent.on("download:startCheck", () => { - downloadEvent.emit("user:write:status", "Checking Ubuntu Touch files"); - utils.log.debug("Download startCheck"); - }); - downloadEvent.on("download:start", (total) => { - downloadEvent.nextTotal = total; - downloadEvent.nextCurrent = 1; - downloadEvent.nextBaseProgress = 0; - utils.log.info("Starting download of "+total+" files"); - downloadEvent.emit("user:write:status", "Downloading Ubuntu Touch"); - downloadEvent.emit("user:write:next", "Downloading", 1, total); - }); - downloadEvent.on("download:next", (current, total) => { - downloadEvent.nextCurrent = current; - downloadEvent.nextBaseProgress = Math.abs(Math.ceil((current-1)/total*100)); - utils.log.info(`Downloading file ${downloadEvent.nextCurrent}/${downloadEvent.nextTotal}`); - downloadEvent.emit("user:write:next", "Downloading", downloadEvent.nextCurrent, downloadEvent.nextTotal); - downloadEvent.emit("user:write:progress", downloadEvent.nextBaseProgress); - }); - downloadEvent.on("download:progress", (percent) => { - utils.log.debug(`Downloading file ${downloadEvent.nextCurrent} of ${downloadEvent.nextTotal}, ${Math.ceil(percent)}% complete`); - downloadEvent.emit("user:write:progress", Math.ceil(percent/downloadEvent.nextTotal+downloadEvent.nextBaseProgress)); - }); - downloadEvent.on("adbpush:done", () => { - utils.log.info("Done pushing files"); - utils.log.info("Rebooting to recovery to flash"); - downloadEvent.emit("system-image:done"); - downloadEvent.emit("user:write:status", "Rebooting to recovery to start the flashing process"); - downloadEvent.emit("user:write:progress", 0); - }); - downloadEvent.on("adbpush:error", (e) => { - downloadEvent.emit("error", "Adb push error: " + e) - utils.log.error("Devices: Adb push error: "+ e) - }); - downloadEvent.on("adbpush:progress", (percent) => { - if (percent != NaN && percent != 100) { - utils.log.debug(`Pushing file ${downloadEvent.nextCurrent} of ${downloadEvent.nextTotal}, ${Math.ceil(percent)}% complete`); - downloadEvent.emit("user:write:progress", Math.ceil(percent/downloadEvent.nextTotal+downloadEvent.nextBaseProgress)); - } - }); - downloadEvent.on("adbpush:next", (current, total) => { - downloadEvent.nextCurrent = current; - downloadEvent.nextBaseProgress = Math.abs(Math.ceil((current-1)/total*100)); - utils.log.info(`Pushing file ${downloadEvent.nextCurrent}/${downloadEvent.nextTotal}`); - downloadEvent.emit("user:write:next", "Pushing", downloadEvent.nextCurrent, downloadEvent.nextTotal); - downloadEvent.emit("user:write:progress", downloadEvent.nextBaseProgress); - }); - downloadEvent.on("adbpush:start", (total) => { - downloadEvent.nextTotal = total; - downloadEvent.nextCurrent = 1; - downloadEvent.nextBaseProgress = 0; - utils.log.info("Start pushing " + total + " files"); - downloadEvent.emit("user:write:status", "Pushing files to device"); - downloadEvent.emit("user:write:start", "Pushing", total); - }); -} +global.mainEvent.on("download:done", () => { + utils.log.info("Download complete"); + global.mainEvent.emit("user:write:progress", 0); +}); +global.mainEvent.on("download:error", (r) => { + utils.log.error("Devices: Download error "+r); +}); +global.mainEvent.on("error", (r) => { + global.mainEvent.emit("user:error", r); + utils.log.error("Devices: Error: "+r); +}); +global.mainEvent.on("download:checking", () => { + utils.log.info("Download checking file"); +}); +global.mainEvent.on("download:startCheck", () => { + global.mainEvent.emit("user:write:status", "Checking Ubuntu Touch files"); + utils.log.debug("Download startCheck"); +}); +global.mainEvent.on("download:start", (total) => { + global.mainEvent.nextTotal = total; + global.mainEvent.nextCurrent = 1; + global.mainEvent.nextBaseProgress = 0; + utils.log.info("Starting download of "+total+" files"); + global.mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); + global.mainEvent.emit("user:write:next", "Downloading", 1, total); +}); +global.mainEvent.on("download:next", (current, total) => { + global.mainEvent.nextCurrent = current; + global.mainEvent.nextBaseProgress = Math.abs(Math.ceil((current-1)/total*100)); + utils.log.info(`Downloading file ${global.mainEvent.nextCurrent}/${global.mainEvent.nextTotal}`); + global.mainEvent.emit("user:write:next", "Downloading", global.mainEvent.nextCurrent, global.mainEvent.nextTotal); + global.mainEvent.emit("user:write:progress", global.mainEvent.nextBaseProgress); +}); +global.mainEvent.on("download:progress", (percent) => { + utils.log.debug(`Downloading file ${global.mainEvent.nextCurrent} of ${global.mainEvent.nextTotal}, ${Math.ceil(percent)}% complete`); + global.mainEvent.emit("user:write:progress", Math.ceil(percent/global.mainEvent.nextTotal+global.mainEvent.nextBaseProgress)); +}); +global.mainEvent.on("adbpush:done", () => { + utils.log.info("Done pushing files"); + utils.log.info("Rebooting to recovery to flash"); + global.mainEvent.emit("system-image:done"); + global.mainEvent.emit("user:write:status", "Rebooting to recovery to start the flashing process"); + global.mainEvent.emit("user:write:progress", 0); +}); +global.mainEvent.on("adbpush:error", (e) => { + global.mainEvent.emit("error", "Adb push error: " + e) + utils.log.error("Devices: Adb push error: "+ e) +}); +global.mainEvent.on("adbpush:progress", (percent) => { + if (percent != NaN && percent != 100) { + utils.log.debug(`Pushing file ${global.mainEvent.nextCurrent} of ${global.mainEvent.nextTotal}, ${Math.ceil(percent)}% complete`); + global.mainEvent.emit("user:write:progress", Math.ceil(percent/global.mainEvent.nextTotal+global.mainEvent.nextBaseProgress)); + } +}); +global.mainEvent.on("adbpush:next", (current, total) => { + global.mainEvent.nextCurrent = current; + global.mainEvent.nextBaseProgress = Math.abs(Math.ceil((current-1)/total*100)); + utils.log.info(`Pushing file ${global.mainEvent.nextCurrent}/${global.mainEvent.nextTotal}`); + global.mainEvent.emit("user:write:next", "Pushing", global.mainEvent.nextCurrent, global.mainEvent.nextTotal); + global.mainEvent.emit("user:write:progress", global.mainEvent.nextBaseProgress); +}); +global.mainEvent.on("adbpush:start", (total) => { + global.mainEvent.nextTotal = total; + global.mainEvent.nextCurrent = 1; + global.mainEvent.nextBaseProgress = 0; + utils.log.info("Start pushing " + total + " files"); + global.mainEvent.emit("user:write:status", "Pushing files to device"); + global.mainEvent.emit("user:write:start", "Pushing", total); +}); var install = (options) => { // helper vars for progress events @@ -306,56 +299,52 @@ var install = (options) => { var nextBaseProgress; if (!options) return false; - const installEvent = new event(); utils.log.debug("install event started with options: " + JSON.stringify(options)) devicesApi.getInstallInstructs(options.device).then((instructs) => { - setEvents(installEvent); - installEvent.on("images:startDownload", () => { - installEvent.emit("user:write:status", "Downloading images"); - utils.downloadFiles(addPathToImages(instructs.images, options.device), installEvent); + global.mainEvent.on("images:startDownload", () => { + global.mainEvent.emit("user:write:status", "Downloading images"); + utils.downloadFiles(addPathToImages(instructs.images, options.device)); }); - installEvent.on("system-image:start", () => { + global.mainEvent.on("system-image:start", () => { systemImage.installLatestVersion({ device: options.device, channel: options.channel, - event: installEvent, wipe: options.wipe }); }); - installEvent.on("system-image:done", () => { - instructReboot("recovery", instructs.buttons, installEvent, () => { - installEvent.emit("user:write:done"); + global.mainEvent.on("system-image:done", () => { + instructReboot("recovery", instructs.buttons, () => { + global.mainEvent.emit("user:write:done"); }); }); - installEvent.on("bootstrap:done", (bootstrap) => { + global.mainEvent.on("bootstrap:done", (bootstrap) => { utils.log.info("bootstrap done: " + (bootstrap ? "rebooting automatically" : "rebooting manually")); if (!bootstrap){ - instructReboot("recovery", instructs.buttons, installEvent, () => { - installEvent.emit("system-image:start"); + instructReboot("recovery", instructs.buttons, () => { + global.mainEvent.emit("system-image:start"); }); } else { - installEvent.emit("user:write:status", "Waiting for device to enter recovery mode"); + global.mainEvent.emit("user:write:status", "Waiting for device to enter recovery mode"); adb.waitForDevice(() => { - installEvent.emit("system-image:start"); + global.mainEvent.emit("system-image:start"); }); } }); if (instructs.images.length > 0) { // If images are specified, flash them (bootstrapping) // We need to be in bootloader - instructReboot("bootloader", instructs.buttons, installEvent, () => { - installEvent.once("download:done", () => { - instructBootstrap(instructs.installSettings.bootstrap, addPathToImages(instructs.images, options.device), installEvent); + instructReboot("bootloader", instructs.buttons, () => { + global.mainEvent.once("download:done", () => { + instructBootstrap(instructs.installSettings.bootstrap, addPathToImages(instructs.images, options.device)); }); - installEvent.emit("images:startDownload"); + global.mainEvent.emit("images:startDownload"); }); } else { // If no images are specified, go straight to system-image // We need to be in recovery - instructReboot("recovery", instructs.buttons, installEvent, () => { - installEvent.emit("system-image:start"); + instructReboot("recovery", instructs.buttons, () => { + global.mainEvent.emit("system-image:start"); }); } - }); - return installEvent; + }).catch(utils.log.error); } var getChannelSelects = (device, callback) => { @@ -365,93 +354,71 @@ var getChannelSelects = (device, callback) => { } var channelsAppend = []; systemImage.getDeviceChannels(device).then((channels) => { - if (!global.installProperties.channel) { - devicesApi.getInstallInstructs(device).then((ret) => { - if (ret) { - channels.forEach((channel) => { - var _channel = channel.replace("ubports-touch/", ""); - // Ignore blacklisted channels - if (ret["systemServer"]["blacklist"].indexOf(channel) == -1 && - channel.indexOf("15.04") == -1) { - if (channel === ret["systemServer"]["selected"]) - channelsAppend.push(""); - else - channelsAppend.push(""); - } - }); - channelsAppend.push("") - callback(channelsAppend.join('')); - return; - } else { - callback(false); - return; - } - }); - } else { - if (channels.indexOf(global.installProperties.channel) != -1) { - setTimeout(callback([ - "" - ]), 50); + devicesApi.getInstallInstructs(device).then((ret) => { + if (ret) { + channels.forEach((channel) => { + var _channel = channel.replace("ubports-touch/", ""); + // Ignore blacklisted channels + if (ret["systemServer"]["blacklist"].indexOf(channel) == -1 && + channel.indexOf("15.04") == -1) { + if (channel === ret["systemServer"]["selected"]) + channelsAppend.push(""); + else + channelsAppend.push(""); + } + }); + channelsAppend.push("") + callback(channelsAppend.join('')); return; } else { callback(false); return; } - } - }); - // If the respose takes longer than half a second, get help - setTimeout(() => { - utils.log.debug("getChannelSelects timed out"); - callback(false); - return; - }, 500); + }).catch(utils.log.error); + }).catch(utils.log.error); } module.exports = { getDevice: devicesApi.getDevice, - waitForDevice: (callback) => { - var waitEvent; - if (!global.installProperties.device) { - waitEvent = adb.waitForDevice((deviceDetected) => { - if (deviceDetected) { - adb.getDeviceName((device) => { - adb.isBaseUbuntuCom((ubuntuCom) => { - waitEvent.emit("device:select:event", device, ubuntuCom, true); - return; - }); + waitForDevice: () => { + adb.waitForDevice((deviceDetected) => { + if (deviceDetected) { + adb.getDeviceName((device) => { + adb.isBaseUbuntuCom((ubuntuCom) => { + global.mainEvent.emit("device:select:event", device, ubuntuCom, true); + return; }); - } else { - waitEvent.emit("device:select:event", false); - return; - } - }); - } else { - waitEvent = new event(); - } - waitEvent.on("device:select", (device) => { - waitEvent.emit("stop"); + }); + } else { + global.mainEvent.emit("device:select:event", false); + return; + } + }); + global.mainEvent.once("device:select", (device) => { + global.mainEvent.emit("stop"); utils.log.info(device + " selected"); - waitEvent.emit("device:select:event", device, false, false); + global.mainEvent.emit("device:select:event", device, false, false); }); - waitEvent.once("device:select:event", (device, ubuntuCom, autoDetected) => { + global.mainEvent.once("device:select:event", (device, ubuntuCom, autoDetected) => { devicesApi.getDevice(device).then((apiData) => { - if (apiData) { - setTimeout(getChannelSelects(device, (channels) => { - if (channels) - callback(apiData, device, channels, ubuntuCom, autoDetected, isLegacyAndroid(device)); - ipcRenderer.send("setInstallProperties", { device: device }); + if (apiData) { + setTimeout(() => { + getChannelSelects(device, (channels) => { + if (channels) { + global.mainEvent.emit("device:select:data-ready", apiData, device, channels, ubuntuCom, autoDetected, isLegacyAndroid(device)); + } else { + global.mainEvent.emit("user:no-network"); + } + return; + }); + }, 50); + } else { + mainEvent.emit("user:device-unsupported", device); // If there is no response, the device is not supported + // ipcRenderer.send("setInstallProperties", { device: device }); return; - }), 50); - } else { - callback(false, device); // If there is no response, the device is not supported - ipcRenderer.send("setInstallProperties", { device: device }); - return; - } - }); + } + }).catch(utils.log.error); }); - return waitEvent; }, getNotWorking: getNotWorking, formatNotWorking: formatNotWorking, @@ -475,7 +442,7 @@ module.exports = { } else { callback(false); } - }); + }).catch(utils.log.error); }, instructOemUnlock: instructOemUnlock } diff --git a/src/fastboot.js b/src/fastboot.js index 58617d6d..750b1912 100644 --- a/src/fastboot.js +++ b/src/fastboot.js @@ -7,6 +7,7 @@ Author: Marius Gripsgard */ const path = require("path"); +var utils = global.utils; const lockedErrors = ["unlocked", "locked", "oem-lock", "lock"] diff --git a/src/html/modals/error.pug b/src/html/modals/error.pug index 7b06756a..eda4e203 100644 --- a/src/html/modals/error.pug +++ b/src/html/modals/error.pug @@ -17,6 +17,6 @@ p If you need help, you can join UBports' support channels on #[a(onclick="shell.openExternal('https://t.me/WelcomePlus')") telegram] or #[a(onclick="shell.openExternal('https://matrix.to/#/!KwdniMNeTmClpgHkND:matrix.org?via=matrix.org&via=ubports.chat&via=disroot.org')") matrix] or ask a question #[a(onclick="shell.openExternal('https://forums.ubports.com')") in the forum] or on #[a(onclick="shell.openExternal('https://askubuntu.com')") askubuntu]. As a last resort, we also have #[a(onclick="shell.openExternal('https://devices.ubuntu-touch.io')") manual installation instructions for every device], that you can follow if you want to install without using the UBports Installer. .modal-footer - button.btn.btn-default(type='button', hidden='hidden', data-dismiss='modal', onclick="location.reload(); utils.log.info('STARTING OVER')") Try again - button.btn.btn-default(type='button', hidden='hidden', data-dismiss='modal', onclick="utils.log.info('ERROR IGNORED')") Ignore + button.btn.btn-default(type='button', hidden='hidden', data-dismiss='modal', onclick="restartInstaller()") Try again + button.btn.btn-default(type='button', hidden='hidden', data-dismiss='modal', onclick="ignoreError()") Ignore button#btn-bugreport.btn.btn-primary(type='button') Report a bug diff --git a/src/html/modals/oem-lock.pug b/src/html/modals/oem-lock.pug index 310b3a97..f1a05cd9 100644 --- a/src/html/modals/oem-lock.pug +++ b/src/html/modals/oem-lock.pug @@ -12,6 +12,8 @@ | Removing the OEM-lock might void your devices warranty. If you want to be sure, please ask your manufacturer or vendor if they allow this. UBports is not responsible and won't replace devices in case of warranty loss. You are responsible for your own actions. p | Do you want to unlock your device now? + p + | You might see a confirmation dialog on your device next. .modal-footer button#btn-exit.btn.btn-default(type='button', data-dismiss='modal') Abort button#btn-unlock.btn.btn-primary(type='button') Unlock diff --git a/src/html/modals/options.pug b/src/html/modals/options.pug index 226d5e2c..26bb9b81 100644 --- a/src/html/modals/options.pug +++ b/src/html/modals/options.pug @@ -18,11 +18,11 @@ label input#options-wipe(type='checkbox') | Wipe storage - .col-xs-3 + //- .col-xs-3 label input#options-custom-tools(type='checkbox') | Custom tools - .col-xs-12 + //- .col-xs-12 p#options-custom-tools-snap-note(hidden='hidden') b NOTE: | Custom tools can not be specified for confined snaps. @@ -31,7 +31,7 @@ b NOTE: | If the wipe option is enabled all data stored on the device will be erased. b Please create an external backup of the data you want to keep! - .div#options-custom-tools-area(hidden='hidden') + //- .div#options-custom-tools-area(hidden='hidden') .form-group label.col-xs-3.control-label adb .col-xs-9 diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index 155f3e30..527184fd 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -1,10 +1,9 @@ script. // CATCH ANY ERRORS! var onErr = (err) => { - if (global.installProperties.cli) utils.die(err) - if(utils.getUpdateAvailable()) { + if(global.packageInfo.updateAvailable) { $("#not-latest-stable").show(); - if (utils.isSnap()) { + if (global.packageInfo.isSnap) { $("#snap-update-instructions-error").show(); } else { $("#generic-update-instructions-error").show(); @@ -19,214 +18,193 @@ script. onErr(err+" (MainRenderer:"+line+")"); } - - const setInstallEvents = (installEvent) => { - installEvent.on("user:error", onErr); - installEvent.on("bootstrap:flashing", () => { - views.show("working", "particles"); - footer.underText.set("Flashing recovery and boot images") - }); - installEvent.on("system-image:start", () => { - views.show("working", "particles"); - }); - installEvent.on("download:start", () => { - views.show("working", "download"); - }); - installEvent.on("adbpush:start", () => { - views.show("working", "push"); - }); - installEvent.on("adbpush:done", () => { - views.show("working", "particles"); - }); - installEvent.on("user:password", () => { - modals.show("password"); - $("#password-input").val(""); - $("#password-input").keypress((event) => { - if (event.which == '13') { - event.preventDefault(); - installEvent.emit("password", $("#password-input").val()); - modals.hide("password") - $('#password-wrong').hide(); - } - }); - $("#btn-password").click(() => { - installEvent.emit("password", $("#password-input").val()); + ipcRenderer.on("user:password", () => { + modals.show("password"); + $("#password-input").val(""); + $("#password-input").keypress((event) => { + if (event.which == '13') { + event.preventDefault(); + ipcRenderer.send("password", $("#password-input").val()); + modals.hide("password"); $('#password-wrong').hide(); - }); - }); - installEvent.on("user:connection-lost", (callback) => { - modals.show("connection-lost"); - $("#btn-reconnect").click(callback); - }); - installEvent.on("user:low-power", (callback) => { - modals.show("low-power"); - }); - installEvent.on("user:oem-lock", (callback) => { - modals.show('oem-lock'); - $("#btn-unlock").click(() => { - $("#btn-unlock").attr("disabled", true); - $("#btn-exit").attr("disabled", true); - $("#unlock-prog").removeClass("hidden"); - devices.instructOemUnlock(installEvent, (err) => { - $("#btn-unlock").attr("disabled", false); - $("#btn-exit").attr("disabled", false); - $("#unlock-prog").addClass("hidden"); - if (err) { - modals.hide('oem-lock'); - } else { - callback(callback); - modals.hide('oem-lock'); - } - }); - }); - }); - installEvent.on("user:password:wrong", () => { - installEvent.emit("user:password"); - $('#password-wrong').show(); - }); - installEvent.on("user:reboot", (i) => { - views.show("reboot-" + i.button); - $("[id=reboot-to-state]").text(i.state); - $("#complex-reboot-instruction").text(i.instruction); - footer.topText.set("Please reboot to "+i.state); - footer.underText.set(i.instruction.split(".")[0]); - }); - installEvent.on("adb:rebooted", () => { - $('#views-reboot-up').hide(); - $('#views-reboot-down').hide(); - }); - installEvent.on("reboot:done", () => { - views.show("working", "particles"); - $('#views-reboot-up').hide(); - $('#views-reboot-down').hide(); - }); - installEvent.on("user:write:next", (text, current, total) => { - footer.underText.set(text + " file " + current + " of " + total); - }); - installEvent.on("user:write:start", (text, length) => { - footer.underText.set(text+" file 1 of "+length); - }); - installEvent.on("user:write:progress", (length) => { - if(length >= 100) { - length=100; } - $("#progress").width(length.toString()+"%"); }); - installEvent.on("user:write:done", () => { - if (global.installProperties.cli) { - remote.getCurrentWindow().close(); - } else { - views.show("done"); - footer.topText.set("Done"); - footer.underText.set("It is now safe to unplug the device."); - $("#progress").width("0%"); - } - }); - installEvent.on("user:write:status", (status) => { - footer.topText.set(status, true) + $("#btn-password").click(() => { + ipcRenderer.send("password", $("#password-input").val()); + $('#password-wrong').hide(); }); + }); + + ipcRenderer.on("user:password:wrong", () => { + ipcRenderer.send("user:password"); + $('#password-wrong').show(); + }); + + ipcRenderer.on("user:error", (event, err) => { onErr(err); }); + + ipcRenderer.on("bootstrap:flashing", () => { + views.show("working", "particles"); + footer.underText.set("Flashing recovery and boot images") + }); + + ipcRenderer.on("system-image:start", () => { + views.show("working", "particles"); + }); + + ipcRenderer.on("download:start", () => { + views.show("working", "download"); + }); + + ipcRenderer.on("adbpush:start", () => { + views.show("working", "push"); + }); + + ipcRenderer.on("adbpush:done", () => { + views.show("working", "particles"); + }); + + ipcRenderer.on("user:connection-lost", (e, callback) => { + modals.show("connection-lost"); + $("#btn-reconnect").click(callback); + }); + + ipcRenderer.on("user:low-power", (callback) => { + modals.show("low-power"); + }); + + var ignoreError = () => { + ipcRenderer.send('error_ignored'); } - const mainEvent = (output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { - utils.log.debug("mainEvent called") - var installEvent; - if(!output) { - footer.topText.set("Device not supported"); - footer.underText.set("The device " + device + " is not supported"); - $("[id=your-device]").text(device) - views.show("not-supported"); - utils.log.warn("This device is not supported!") - $("#btn-inst").hide(); - } else { - if (global.installProperties.cli) { - utils.log.debug(output); - installEvent = devices.install({ - device: global.installProperties.device, - channel: global.installProperties.channel, - wipe: false // TODO --wipe option - }); - setInstallEvents(installEvent); - views.show("working", "particles"); - $("#progress").show(); - } else { - views.show("install"); - $("#options-channel").append(channels); - options.optionsValToUser(); - modals.hide('select-device'); - $("#btn-inst").show(); - footer.topText.set(output.name); - if (isLegacyAndroid && !ubuntuCom) - $("#legacy-android-note").show(); - if (isLegacyAndroid) - modals.show("legacy-android"); - if (autoDetected) - footer.underText.set("Are you ready for Ubuntu Touch on your " + output.name + "?"); - else - footer.underText.set("Please connect your " + output.name + " with a USB cable."); - $("#your-ubp-device").text(output.name+" ("+output.device+")") - $("#your-ubp-device").click(() => { - shell.openExternal("https://devices.ubuntu-touch.io/device/"+output.device); - }); - - views.show(ubuntuCom ? "switch" : "install"); - - $("#btn-inst").click(() => { - modals.show('install'); - if(options.get("custom-tools", true)) { - utils.setCustomPlatformTool("adb", options.get("custom-tools-adb")); - utils.setCustomPlatformTool("fastboot", options.get("custom-tools-fastboot")); - } - }); - - $("#btn-installModal").click(() => { - views.show("working", "particles"); - $("#progress").show(); - ipcRenderer.send("setInstallProperties", {device: output.device, channel: options.get("channel", true)}); - installEvent = devices.install({ - device: output.device, - channel: options.get("channel", true), - wipe: options.get("wipe", true) - }); - setInstallEvents(installEvent); - }); - } - } - }; + var restartInstaller = () => { + ipcRenderer.send('restart'); + } - // START - utils.log.info("Welcome to the UBports Installer version " + global.packageInfo.version + "!"); - views.show("working", "particles"); + ipcRenderer.on("user:oem-lock", (event) => { + modals.show('oem-lock'); + $("#btn-unlock").click(() => { + event.sender.send("user:oem-lock:ok"); + modals.hide('oem-lock'); + $("#btn-unlock").attr("disabled", true); + $("#btn-exit").attr("disabled", true); + $("#unlock-prog").removeClass("hidden"); + }); + }); + + ipcRenderer.on("user:reboot", (e, i) => { + views.show("reboot-" + i.button); + $("[id=reboot-to-state]").text(i.state); + $("#complex-reboot-instruction").text(i.instruction); + footer.topText.set("Please reboot to "+i.state); + footer.underText.set(i.instruction.split(".")[0]); + }); + + ipcRenderer.on("adb:rebooted", () => { + $('#views-reboot-up').hide(); + $('#views-reboot-down').hide(); + }); + + ipcRenderer.on("reboot:done", () => { + views.show("working", "particles"); + $('#views-reboot-up').hide(); + $('#views-reboot-down').hide(); + }); + + ipcRenderer.on("user:no-network", () => { + modals.show('no-network'); + }); + + ipcRenderer.on("user:write:next", (e, text, current, total) => { + footer.underText.set(text + " file " + current + " of " + total); + }); + + ipcRenderer.on("user:write:start", (e, text, length) => { + footer.underText.set(text+" file 1 of "+length); + }); + + ipcRenderer.on("user:write:progress", (e, length) => { + if(length >= 100) { + length=100; + } + $("#progress").width(length.toString()+"%"); + }); - devices.getDeviceSelects((out) => { - if (out) { - $("#device-select").append(out); + ipcRenderer.on("user:write:done", () => { + if (global.installProperties.cli) { + remote.getCurrentWindow().close(); } else { - modals.show('no-network'); + views.show("done"); + footer.topText.set("Done"); + footer.underText.set("It is now safe to unplug the device."); + $("#progress").width("0%"); } }); - adb.start(false, false, (err) => { - var waitEvent = devices.waitForDevice(mainEvent); - if (!global.installProperties.device) { - footer.topText.set("Waiting for device", true) - footer.underText.set("Please connect your device with a USB cable"); - views.show("wait-for-device"); - // Button to open device selector - $("#btn-modal-select-device").click(() => { - waitEvent.emit("stop"); - modals.show('select-device'); - }); - // Button to confirm device selection - $("#btn-select-device").click(() => { - var device = $("#device-select").find(":selected").attr("name"); - waitEvent.emit("device:select", device); - }); + ipcRenderer.on("user:write:status", (e, status) => { + footer.topText.set(status, true) + }); + + ipcRenderer.on("user:device-unsupported", (event, device) => { + footer.topText.set("Device not supported"); + footer.underText.set("The device " + device + " is not supported"); + $("[id=your-device]").text(device); + views.show("not-supported"); + $("#btn-inst").hide(); + }); + + ipcRenderer.on("device:select:data-ready", (event, output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { + views.show("install"); + $("#options-channel").append(channels); + options.optionsValToUser(); + modals.hide('select-device'); + $("#btn-inst").show(); + footer.topText.set(output.name); + if (isLegacyAndroid && !ubuntuCom) { + $("#legacy-android-note").show(); + modals.show("legacy-android"); + } + if (autoDetected) { + footer.underText.set("Are you ready for Ubuntu Touch on your " + output.name + "?"); } else { - setTimeout(waitEvent.emit('device:select', (global.installProperties.device)), 50); + footer.underText.set("Please connect your " + output.name + " with a USB cable."); } - waitEvent.on("user:error", onErr); - waitEvent.on("device:select", (device) => { - modals.hide('select-device'); + $("#your-ubp-device").text(output.name+" ("+output.device+")"); + $("#your-ubp-device").click(() => { + shell.openExternal("https://devices.ubuntu-touch.io/device/"+output.device); + }); + + views.show(ubuntuCom ? "switch" : "install"); + + $("#btn-installModal").click(() => { + views.show("working", "particles"); + $("#progress").show(); + ipcRenderer.send("user:device:select", { + device: output.device, + channel: options.get("channel", true), + wipe: options.get("wipe", true) + }); + }); + }); + + // START + views.show("working", "particles"); + + ipcRenderer.on("device:wait:data-ready", (event, deviceSelects) => { + $("#device-select").append(deviceSelects); + }); + + ipcRenderer.on("user:adb:ready", () => { + footer.topText.set("Waiting for device", true); + footer.underText.set("Please connect your device with a USB cable"); + views.show("wait-for-device"); + // Button to open device selector + $("#btn-modal-select-device").click(() => { + modals.show('select-device'); + }); + // Button to confirm device selection + $("#btn-select-device").click(() => { + var device = $("#device-select").find(":selected").attr("name"); + ipcRenderer.send("device:select", device); }); }); diff --git a/src/html/scripts/root.pug b/src/html/scripts/root.pug index 8c21469d..7b98db1a 100644 --- a/src/html/scripts/root.pug +++ b/src/html/scripts/root.pug @@ -2,10 +2,6 @@ script. require('jquery'); window.$ = window.jQuery = require('../../node_modules/jquery/dist/jquery.js'); const { shell } = require('electron'); - const devices = require('../devices.js'); - const systemImage = require("../system-image.js"); - const adb = require("../adb.js"); - const utils = require("../utils.js"); const remote = require('electron').remote; var ipcRenderer = require('electron').ipcRenderer; require('bootstrap'); diff --git a/src/html/scripts/ui.pug b/src/html/scripts/ui.pug index 31cdcd19..78cb2f59 100644 --- a/src/html/scripts/ui.pug +++ b/src/html/scripts/ui.pug @@ -173,22 +173,20 @@ script. switchHide("modal-install-body-wipe", "modal-install-body-no-wipe"); } }); - $("#options-custom-tools").change(() => { - if (getOptionVal("custom-tools", true)) { - $("#options-custom-tools-area").show(); - } else { - $("#options-custom-tools-area").hide(); - } - }); + // $("#options-custom-tools").change(() => { + // if (getOptionVal("custom-tools", true)) { + // $("#options-custom-tools-area").show(); + // } else { + // $("#options-custom-tools-area").hide(); + // } + // }); }, optionsValToUser: optionsValToUser } $("#btn-bugreport").click(() => { var title = $("#error-body").text(); - utils.createBugReport(title, (body) => { - shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title="+title+"&body="+body); - }); + ipcRenderer.send("createBugReport", title); }); $("#btn-exit").click(() => { @@ -197,9 +195,7 @@ script. }); $("#help").click(() => { - utils.createBugReport("user-requested error report", (body) => { - shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title=please describe the problem you are experiencing&body="+body); - }); + ipcRenderer.send("createBugReport", "user-requested bug-report"); }); $("#donate").click(() => { @@ -214,26 +210,29 @@ script. modals.show('developer-mode-info'); }); - if(utils.isSnap()) { - $("#options-custom-tools").prop("disabled", true); - $("#options-custom-tools-snap-note").show(); - } + $("#btn-inst").click(() => { + modals.show('install'); + // if(options.get("custom-tools", true)) { + // utils.setCustomPlatformTool("adb", options.get("custom-tools-adb")); + // utils.setCustomPlatformTool("fastboot", options.get("custom-tools-fastboot")); + // } + }); + + // if(global.packageInfo.isSnap) { + // $("#options-custom-tools").prop("disabled", true); + // $("#options-custom-tools-snap-note").show(); + // } if (process.platform === "win32" && !localStorage.getItem('neverAskForWindowsDrivers')) { modals.show('windows-drivers'); } - utils.getUpdateAvailable().then((updateAvailable) => { - if(updateAvailable) { - utils.log.warn("This is not the latest stable release!") - if (utils.isSnap()) { - $("#snap-update-instructions").show(); - $("#btn-update-installer").hide(); - } else { - $("#generic-update-instructions").show(); - } - modals.show('new-update'); + if(global.packageInfo.updateAvailable) { + if (global.packageInfo.isSnap) { + $("#snap-update-instructions").show(); + $("#btn-update-installer").hide(); } else { - utils.log.debug("Running latest stable version."); + $("#generic-update-instructions").show(); } - }); + modals.show('new-update'); + } diff --git a/src/main.js b/src/main.js index e4528c57..cdda6a2c 100755 --- a/src/main.js +++ b/src/main.js @@ -11,16 +11,28 @@ Author: Marius Gripsgard const cli = require("commander"); const electron = require('electron'); const electronPug = require('electron-pug'); + const app = electron.app; const BrowserWindow = electron.BrowserWindow; -var ipcMain = require('electron').ipcMain; +global.packageInfo = require('../package.json'); const path = require('path'); const url = require('url'); +const events = require("events"); +class event extends events {}; + const pug = new electronPug(); +const ipcMain = electron.ipcMain; let mainWindow; -global.packageInfo = require('../package.json'); +var mainEvent = new event(); +global.mainEvent = mainEvent; + +var utils = require('./utils.js'); +global.utils = utils; +var fastboot = require('./fastboot.js'); +var devices = require('./devices.js'); +var adb = require('./adb.js'); cli .name(global.packageInfo.name) @@ -47,20 +59,166 @@ global.installProperties = { simulate: cli.simulate }; -ipcMain.on("setInstallProperties", ( event, installProperties ) => { +global.packageInfo.isSnap = utils.isSnap(); +utils.getUpdateAvailable((updateAvailable) => { global.packageInfo.updateAvailable = updateAvailable; }); + +//============================================================================== +// RENDERER SIGNAL HANDLING +//============================================================================== + +ipcMain.on("user:device:select", (event, installProperties) => { global.installProperties = Object.assign(global.installProperties, installProperties); + devices.install(installProperties); +}); + +ipcMain.on("password", (e, password) => { + mainEvent.emit("password", password); }); ipcMain.on("die", (exitCode) => { process.exit(exitCode); }); -ipcMain.on("resetDeviceAndChannel", () => { +ipcMain.on("restart", () => { global.installProperties.device = undefined; global.installProperties.channel = undefined; + utils.log.debug("WINDOW RELOADED"); + mainWindow.reload(); +}); + +ipcMain.on("error_ignored", () => { + utils.log.debug("ERROR IGNORED"); +}); + +ipcMain.on("createBugReport", (title) => { + utils.createBugReport(title, (body) => { + shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title="+title+"&body="+body); + }); +}); + +ipcMain.on("device:select", (event, device) => { + mainEvent.emit("device:select", device); +}); + +//============================================================================== +// RENDERER COMMUNICATION +//============================================================================== + +mainEvent.on("user:password", () => { + mainWindow.webContents.send("user:password"); +}); + +mainEvent.on("user:password:wrong", () => { + mainWindow.webContents.send("user:password:wrong"); +}); + +mainEvent.on("user:error", (err) => { + mainWindow.webContents.send("user:error", err); +}); + +mainEvent.on("bootstrap:flashing", () => { + mainWindow.webContents.send("bootstrap:flashing"); +}); + +mainEvent.on("system-image:start", () => { + mainWindow.webContents.send("system-image:start"); +}); + +mainEvent.on("download:start", () => { + mainWindow.webContents.send("download:start"); +}); + +mainEvent.on("adbpush:done", () => { + mainWindow.webContents.send("adbpush:done"); +}); + +mainEvent.on("adbpush:start", () => { + mainWindow.webContents.send("adbpush:start"); +}); + +mainEvent.on("user:connection-lost", (callback) => { + mainWindow.webContents.send("user:connection-lost", callback); +}); + +mainEvent.on("user:low-power", () => { + mainWindow.webContents.send("user:low-power"); }); +mainEvent.on("user:oem-lock", (callback) => { + mainWindow.webContents.send("user:oem-lock"); + ipcMain.once("user:oem-lock:ok", () => { + devices.instructOemUnlock((err) => { + if (err) { + mainEvent.emit("user:error", err); + } else { + callback(true); + } + }); + }); +}); + +mainEvent.on("user:reboot", (i) => { + mainWindow.webContents.send("user:reboot", i); +}); + +mainEvent.on("adb:rebooted", () => { + mainWindow.webContents.send("adb:rebooted"); +}); + +mainEvent.on("reboot:done", () => { + mainWindow.webContents.send("reboot:done"); +}); + +mainEvent.on("user:write:next", (text, current, total) => { + mainWindow.webContents.send("user:write:next", text, current, total); +}); + +mainEvent.on("user:write:start", (text, length) => { + mainWindow.webContents.send("user:write:start", text, length); +}); + +mainEvent.on("user:write:progress", (length) => { + mainWindow.webContents.send("user:write:progress", length); +}); + +mainEvent.on("user:write:done", () => { + mainWindow.webContents.send("user:write:done"); + utils.log.info("All done! Your device will now reboot and complete the installation. Enjoy exploring Ubuntu Touch!"); +}); + +mainEvent.on("user:write:status", (status) => { + mainWindow.webContents.send("user:write:status", status); +}); + +mainEvent.on("user:adb:ready", () => { + mainWindow.webContents.send("user:adb:ready"); +}); + +mainEvent.on("user:device-unsupported", (device) => { + utils.log.warn("The device " + device + " is not supported!"); + mainWindow.webContents.send("user:device-unsupported", device); +}); + +mainEvent.on("device:select:data-ready", (output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { + mainWindow.webContents.send("device:select:data-ready", output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid); +}); + +mainEvent.once("device:wait:data-ready", (deviceSelects) => { + mainWindow.webContents.send("device:wait:data-ready", deviceSelects); +}); + +mainEvent.on("user:no-network", () => { + mainWindow.webContents.send("user:no-network"); +}); + +//============================================================================== +// CREATE WINDOW +//============================================================================== + function createWindow () { + utils.setLogLevel(global.installProperties.verbose ? "debug" : "info"); + utils.log.info("Welcome to the UBports Installer version " + global.packageInfo.version + "!"); + utils.log.info("This is " + (global.packageInfo.updateAvailable ? "not" : "") + " the latest stable version!"); mainWindow = new BrowserWindow({ width: cli.cli ? 0 : (cli.debug ? 1600 : 800), height: cli.cli ? 0 : 600, @@ -69,12 +227,23 @@ function createWindow () { title: "UBports Installer ("+global.packageInfo.version+")" }); + mainWindow.webContents.on("did-finish-load", () => { + adb.start(false, false, (err) => { + mainEvent.emit("user:adb:ready"); + devices.waitForDevice(); + }); + devices.getDeviceSelects((out) => { + mainEvent.emit("device:wait:data-ready", out) + }); + }); + mainWindow.loadURL(url.format({ pathname: path.join(__dirname, 'html/index.pug'), protocol: 'file:', slashes: true })); - mainWindow.setMenu(null); + + mainWindow.setMenu(null); // TODO set menu if (cli.debug) { mainWindow.webContents.openDevTools(); @@ -85,6 +254,10 @@ function createWindow () { }); } +//============================================================================== +// FUNCTIONAL EVENT HANDLING +//============================================================================== + app.on('ready', createWindow); app.on('uncaughtException', function (error) { @@ -92,10 +265,12 @@ app.on('uncaughtException', function (error) { }); app.on('window-all-closed', function () { - console.log("Good bye!"); - if (process.platform !== 'darwin') { - app.quit(); - } + utils.log.info("Good bye!"); + adb.stop(() => { + if (process.platform !== 'darwin') { + app.quit(); + } + }); }); app.on('activate', function () { diff --git a/src/system-image.js b/src/system-image.js index 85c80487..7be40bd4 100644 --- a/src/system-image.js +++ b/src/system-image.js @@ -12,12 +12,10 @@ const fs = require("fs"); const utils = require("./utils"); const adb = require("./adb"); const path = require("path"); -const events = require("events") const mkdirp = require('mkdirp'); const systemImageClient = require("system-image-node-module").Client; const systemImage = new systemImageClient({path: utils.getUbuntuTouchDir()}); -class event extends events {} const ubuntuCommandFile = "ubuntu_command"; const ubuntuPushDir = "/cache/recovery/" @@ -28,18 +26,13 @@ const getDeviceChannels = (device) => { var downloadLatestVersion = (options) => { utils.log.debug("downloadLatestVersion options: ", options); - var thisEvent; - if (!options.event) - thisEvent = new event(); - else - thisEvent = options.event; systemImage.getLatestVersion(options.device, options.channel).then((latest) => { var urls = systemImage.getFilesUrlsArray(latest) urls.push.apply(urls, systemImage.getGgpUrlsArray()); var files = systemImage.getFilePushArray(urls); - utils.downloadFiles(urls, thisEvent); + utils.downloadFiles(urls); utils.log.debug(urls); - thisEvent.once("download:done", () => { + mainEvent.once("download:done", () => { files.push({ src: systemImage.createInstallCommandsFile( systemImage.createInstallCommands( @@ -52,19 +45,18 @@ var downloadLatestVersion = (options) => { ), dest: ubuntuPushDir + ubuntuCommandFile }); - thisEvent.emit("download:pushReady", files); + mainEvent.emit("download:pushReady", files); }); }).catch(() => { - thisEvent.emit("error", "could not find latest version; " + "device: " + options.device + " channel: " + options.channel); + mainEvent.emit("error", "could not find latest version; " + "device: " + options.device + " channel: " + options.channel); }); - return thisEvent; } -var pushLatestVersion = (files, thisEvent, dontWipeCache) => { +var pushLatestVersion = (files, dontWipeCache) => { var doPush = () => { adb.shell("mount -a", () => { adb.shell("mkdir -p /cache/recovery", () => { - adb.pushMany(files, thisEvent); + adb.pushMany(files); }); }); } @@ -72,15 +64,13 @@ var pushLatestVersion = (files, thisEvent, dontWipeCache) => { doPush(); else adb.wipeCache(doPush); - return thisEvent; } var installLatestVersion = (options) => { - var downloadEvent = downloadLatestVersion(options); - downloadEvent.once("download:pushReady", (files) => { - pushLatestVersion(files, downloadEvent) + downloadLatestVersion(options); + mainEvent.once("download:pushReady", (files) => { + pushLatestVersion(files); }); - return downloadEvent; } module.exports = { diff --git a/src/utils.js b/src/utils.js index 43f2c601..8d3ae80d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -182,21 +182,20 @@ var checkPassword = (password, callback) => { } log.debug("checking password") exec(sudoCommand(password) + "echo correct", (err, output) => { - if(err){ + if (err) { if (err.message.includes("incorrect password")) { log.debug("incorrect password") callback(false, { password: true }); - } else{ - // Replace password with "" to make sure it wont get logged - // with password + } else { + // Replace password with "***" to make sure it wont get logged log.debug("unknown sudo error") callback(false, { message: err.message.replace(password, "***") }); } - }else { + } else { log.debug("correct password") if (output.includes("correct")) callback(true); @@ -291,7 +290,7 @@ const platformToolsExecAsar = (tool, callback) => { cb(err,e,r); }) }, - done: () => { console.log("done platform tools") } + done: () => {} }); return true; } @@ -433,36 +432,36 @@ urls format: } ] */ -var downloadFiles = (urls_, downloadEvent) => { +var downloadFiles = (urls_) => { var urls; var totalFiles; - downloadEvent.emit("download:startCheck"); + mainEvent.emit("download:startCheck"); var dl = () => { if (!fs.existsSync(urls[0].path)) { mkdirp.sync(urls[0].path); } progress(http(urls[0].url)) .on('progress', (state) => { - downloadEvent.emit("download:progress", state.percent*100); + mainEvent.emit("download:progress", state.percent*100); }) .on('error', (err) => { - if (err) downloadEvent.emit("download:error", err); + if (err) mainEvent.emit("download:error", err); }) .on('end', () => { fs.rename(path.join(urls[0].path, path.basename(urls[0].url + ".tmp")), path.join(urls[0].path, path.basename(urls[0].url)), () => { - downloadEvent.emit("download:checking"); + mainEvent.emit("download:checking"); checksumFile(urls[0], (check) => { if (check) { if (urls.length <= 1) { - downloadEvent.emit("download:done"); + mainEvent.emit("download:done"); } else { urls.shift(); - downloadEvent.emit("download:next", totalFiles-urls.length+1, totalFiles); + mainEvent.emit("download:next", totalFiles-urls.length+1, totalFiles); dl() } } else { - downloadEvent.emit("download:error", "Checksum mismatch on file " + path.basename(urls[0].url)); + mainEvent.emit("download:error", "Checksum mismatch on file " + path.basename(urls[0].url)); } }); }); @@ -471,15 +470,14 @@ var downloadFiles = (urls_, downloadEvent) => { } checkFiles(urls_, (ret) => { if (ret.length <= 0) { - downloadEvent.emit("download:done"); + mainEvent.emit("download:done"); } else { urls = ret; totalFiles = urls.length; - downloadEvent.emit("download:start", totalFiles); + mainEvent.emit("download:start", totalFiles); dl(); } - }) - return downloadEvent; + }); } const getRandomInt = (min, max) => { @@ -518,5 +516,7 @@ module.exports = { getRandomInt: getRandomInt, getVersion: getVersion, hidePassword: hidePassword, - die: die + die: die, + ipcRenderer: ipcRenderer, + setLogLevel: (level) => { winston.level = level; } } From 2a121f3f8eeaeb9a36af5cb8b364816c708aa1b9 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 26 Sep 2019 12:09:32 +0200 Subject: [PATCH 04/47] Bump version number --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index d6343016..9b5a1b5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ubports-installer", - "version": "0.2.7-beta", + "version": "0.3.0-beta", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 12a98e04..12244dc5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ubports-installer", - "version": "0.2.7-beta", + "version": "0.3.0-beta", "description": "The easy way to install Ubuntu Touch on UBports devices. A friendly cross-platform Installer for Ubuntu Touch. Just connect a supported device to your PC, follow the on-screen instructions and watch this awesome tool do all the rest.", "keywords": [ "Ubuntu", From c7e28f2b7124e23aefe0115058c062b354fa2a84 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 26 Sep 2019 12:49:27 +0200 Subject: [PATCH 05/47] Fix bug reports --- src/main.js | 10 ++++++---- src/utils.js | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main.js b/src/main.js index cdda6a2c..d945f652 100755 --- a/src/main.js +++ b/src/main.js @@ -90,13 +90,14 @@ ipcMain.on("error_ignored", () => { utils.log.debug("ERROR IGNORED"); }); -ipcMain.on("createBugReport", (title) => { - utils.createBugReport(title, (body) => { - shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title="+title+"&body="+body); +ipcMain.on("createBugReport", (event, title) => { + utils.createBugReport(title, global.installProperties, (body) => { + electron.shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title="+title+"&body="+body); }); }); ipcMain.on("device:select", (event, device) => { + global.installProperties.device = device; mainEvent.emit("device:select", device); }); @@ -200,6 +201,7 @@ mainEvent.on("user:device-unsupported", (device) => { }); mainEvent.on("device:select:data-ready", (output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { + global.installProperties.device = device; mainWindow.webContents.send("device:select:data-ready", output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid); }); @@ -218,7 +220,7 @@ mainEvent.on("user:no-network", () => { function createWindow () { utils.setLogLevel(global.installProperties.verbose ? "debug" : "info"); utils.log.info("Welcome to the UBports Installer version " + global.packageInfo.version + "!"); - utils.log.info("This is " + (global.packageInfo.updateAvailable ? "not" : "") + " the latest stable version!"); + utils.log.info("This is " + (global.packageInfo.updateAvailable ? "not " : "") + "the latest stable version!"); mainWindow = new BrowserWindow({ width: cli.cli ? 0 : (cli.debug ? 1600 : 800), height: cli.cli ? 0 : 600, diff --git a/src/utils.js b/src/utils.js index 8d3ae80d..04949147 100644 --- a/src/utils.js +++ b/src/utils.js @@ -53,7 +53,7 @@ var log = { debug: (l) => {winston.log("debug", l)} } -var createBugReport = (title, callback) => { +var createBugReport = (title, installProperties, callback) => { var options = { limit: 400, start: 0, @@ -84,9 +84,9 @@ var createBugReport = (title, callback) => { getos((e,gOs) => { callback("*Automatically generated error report* %0D%0A" + "UBports Installer Version: " + global.packageInfo.version + " %0D%0A" + - "Device: " + (global.installProperties.device ? global.installProperties.device : "Not detected") + "%0D%0A" + - "Channel: " + (global.installProperties.channel ? global.installProperties.channel : "Not yet set") + "%0D%0A" + - "Package: " + (isSnap() ? "snap" : (global.packageInfo.package || "source")) + "%0D%0A" + + "Device: " + (installProperties.device ? installProperties.device : "Not detected") + "%0D%0A" + + "Channel: " + (installProperties.channel ? installProperties.channel : "Not yet set") + "%0D%0A" + + "Package: " + (isSnap() ? "snap" : (packageInfo.package || "source")) + "%0D%0A" + "Operating System: " + getCleanOs() + " " + os.arch() + " %0D%0A" + "NodeJS version: " + process.version + " %0D%0A%0D%0A" + "Error log: https://paste.ubuntu.com/" + res.headers.location + " %0D%0A"); From 0ebe9e26c23e98a8a3c6d1e7376565e5565f36b4 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 26 Sep 2019 15:25:21 +0200 Subject: [PATCH 06/47] Properly clean event listeners when restarting --- src/adb.js | 21 +++++++++++++-------- src/devices.js | 24 +++++++++++++----------- src/html/modals/low-power.pug | 2 +- src/html/modals/no-network.pug | 2 +- src/html/views/done.pug | 2 +- src/main.js | 12 ++++++++---- src/utils.js | 4 ++-- 7 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/adb.js b/src/adb.js index 5075c45d..2ed5cb6c 100644 --- a/src/adb.js +++ b/src/adb.js @@ -156,7 +156,7 @@ var push = (file, dest) => { if (stderrShort.indexOf("I/O error") != -1) { utils.log.warn("connection to device lost"); // TODO: Only restart the event rather than the entire installation - mainEvent.emit("user:connection-lost", () => { mainWindow.reload(); }); + mainEvent.emit("user:connection-lost", () => { mainEvent.emit("restart"); }); } else if (!err.killed && (err.code == 1)) { hasAdbAccess ((hasAccess) => { if (hasAccess) { @@ -164,7 +164,7 @@ var push = (file, dest) => { } else { utils.log.warn("connection to device lost"); // TODO: Only restart the event rather than the entire installation - mainEvent.emit("user:connection-lost", () => { mainWindow.reload(); }); + mainEvent.emit("user:connection-lost", () => { mainEvent.emit("restart"); }); } }); } else { @@ -198,13 +198,18 @@ var pushMany = (files) => { mainEvent.emit("adbpush:start", files.length); push(files[0].src, files[0].dest); mainEvent.on("adbpush:end", () => { - files.shift(); - if (files.length <= 0){ - mainEvent.emit("adbpush:done"); - return; + if (files) { + files.shift(); + if (files.length <= 0){ + files = null; + mainEvent.emit("adbpush:done"); + return; + } else { + if (files) mainEvent.emit("adbpush:next", totalLength-files.length+1, totalLength) + push(files[0].src, files[0].dest); + } } else { - mainEvent.emit("adbpush:next", totalLength-files.length+1, totalLength) - push(files[0].src, files[0].dest); + return; } }); } diff --git a/src/devices.js b/src/devices.js index 35626e66..30aa37ea 100644 --- a/src/devices.js +++ b/src/devices.js @@ -259,14 +259,8 @@ global.mainEvent.on("download:progress", (percent) => { utils.log.debug(`Downloading file ${global.mainEvent.nextCurrent} of ${global.mainEvent.nextTotal}, ${Math.ceil(percent)}% complete`); global.mainEvent.emit("user:write:progress", Math.ceil(percent/global.mainEvent.nextTotal+global.mainEvent.nextBaseProgress)); }); -global.mainEvent.on("adbpush:done", () => { - utils.log.info("Done pushing files"); - utils.log.info("Rebooting to recovery to flash"); - global.mainEvent.emit("system-image:done"); - global.mainEvent.emit("user:write:status", "Rebooting to recovery to start the flashing process"); - global.mainEvent.emit("user:write:progress", 0); -}); global.mainEvent.on("adbpush:error", (e) => { + global.mainEvent.removeListener("adbpush:end", () => {}); global.mainEvent.emit("error", "Adb push error: " + e) utils.log.error("Devices: Adb push error: "+ e) }); @@ -301,23 +295,31 @@ var install = (options) => { return false; utils.log.debug("install event started with options: " + JSON.stringify(options)) devicesApi.getInstallInstructs(options.device).then((instructs) => { - global.mainEvent.on("images:startDownload", () => { + global.mainEvent.once("images:startDownload", () => { global.mainEvent.emit("user:write:status", "Downloading images"); utils.downloadFiles(addPathToImages(instructs.images, options.device)); }); - global.mainEvent.on("system-image:start", () => { + global.mainEvent.once("adbpush:done", () => { + global.mainEvent.removeListener("adbpush:end", () => {}); + utils.log.info("Done pushing files"); + utils.log.info("Rebooting to recovery to flash"); + global.mainEvent.emit("system-image:done"); + global.mainEvent.emit("user:write:status", "Rebooting to recovery to start the flashing process"); + global.mainEvent.emit("user:write:progress", 0); + }); + global.mainEvent.once("system-image:start", () => { systemImage.installLatestVersion({ device: options.device, channel: options.channel, wipe: options.wipe }); }); - global.mainEvent.on("system-image:done", () => { + global.mainEvent.once("system-image:done", () => { instructReboot("recovery", instructs.buttons, () => { global.mainEvent.emit("user:write:done"); }); }); - global.mainEvent.on("bootstrap:done", (bootstrap) => { + global.mainEvent.once("bootstrap:done", (bootstrap) => { utils.log.info("bootstrap done: " + (bootstrap ? "rebooting automatically" : "rebooting manually")); if (!bootstrap){ instructReboot("recovery", instructs.buttons, () => { diff --git a/src/html/modals/low-power.pug b/src/html/modals/low-power.pug index 3d247245..32fce5df 100644 --- a/src/html/modals/low-power.pug +++ b/src/html/modals/low-power.pug @@ -11,4 +11,4 @@ b | Please let your device charge for a while and try again. .modal-footer - button.btn.btn-default(type='button', data-dismiss='modal', onclick="location.reload()") Try again + button.btn.btn-default(type='button', data-dismiss='modal', onclick="ipcRenderer.send('restart');") Try again diff --git a/src/html/modals/no-network.pug b/src/html/modals/no-network.pug index e70ba2be..8baacf6b 100644 --- a/src/html/modals/no-network.pug +++ b/src/html/modals/no-network.pug @@ -9,4 +9,4 @@ p | The installer could not connect to UBports' servers to download the devices list. Are you connected to the internet? .modal-footer - button.btn.btn-default(type='button', data-dismiss='modal', onclick="location.reload()") Try again + button.btn.btn-default(type='button', data-dismiss='modal', onclick="ipcRenderer.send('restart');") Try again diff --git a/src/html/views/done.pug b/src/html/views/done.pug index f80e7929..5a8f50d2 100644 --- a/src/html/views/done.pug +++ b/src/html/views/done.pug @@ -14,4 +14,4 @@ button.btn.btn-primary(type='button', style='width: 49%; margin-bottom: 10px;', onclick="shell.openExternal('https://ubports.com/donate')") Donate p | Got more devices you want to flash? - button.btn.btn-info(type='button', style='width: 100%;', onclick="location.reload(); ipcRenderer.send('resetDeviceAndChannel')") Flash another device! + button.btn.btn-info(type='button', style='width: 100%;', onclick="ipcRenderer.send('restart');") Flash another device! diff --git a/src/main.js b/src/main.js index d945f652..084e13a2 100755 --- a/src/main.js +++ b/src/main.js @@ -80,10 +80,7 @@ ipcMain.on("die", (exitCode) => { }); ipcMain.on("restart", () => { - global.installProperties.device = undefined; - global.installProperties.channel = undefined; - utils.log.debug("WINDOW RELOADED"); - mainWindow.reload(); + mainEvent.emit("restart"); }); ipcMain.on("error_ignored", () => { @@ -145,6 +142,13 @@ mainEvent.on("user:low-power", () => { mainWindow.webContents.send("user:low-power"); }); +mainEvent.on("restart", () => { + global.installProperties.device = undefined; + global.installProperties.channel = undefined; + utils.log.debug("WINDOW RELOADED"); + mainWindow.reload(); +}); + mainEvent.on("user:oem-lock", (callback) => { mainWindow.webContents.send("user:oem-lock"); ipcMain.once("user:oem-lock:ok", () => { diff --git a/src/utils.js b/src/utils.js index 04949147..0248beb0 100644 --- a/src/utils.js +++ b/src/utils.js @@ -444,10 +444,10 @@ var downloadFiles = (urls_) => { .on('progress', (state) => { mainEvent.emit("download:progress", state.percent*100); }) - .on('error', (err) => { + .once('error', (err) => { if (err) mainEvent.emit("download:error", err); }) - .on('end', () => { + .once('end', () => { fs.rename(path.join(urls[0].path, path.basename(urls[0].url + ".tmp")), path.join(urls[0].path, path.basename(urls[0].url)), () => { mainEvent.emit("download:checking"); From 38b1f7a802fb76da8a012990bad726ffa502fa8a Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 26 Sep 2019 16:42:05 +0200 Subject: [PATCH 07/47] fix build --- build.js | 25 +- package-lock.json | 607 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 613 insertions(+), 20 deletions(-) diff --git a/build.js b/build.js index 8b74a8c2..201f90f2 100755 --- a/build.js +++ b/build.js @@ -12,10 +12,10 @@ Author: Marius Gripsgard const builder = require("electron-builder") const cli = require("commander"); -const utils = require("./src/utils"); const unzip = require("unzipper"); const path = require("path"); const fs = require("fs-extra"); +const download = require('download'); const events = require("events"); class event extends events {} const Platform = builder.Platform @@ -175,31 +175,16 @@ var build = () => { // Download platform tools if (cli.platformTools) { - const downloadEvent = new event(); - utils.downloadFiles(getAndroidPlatformTools(), downloadEvent); - downloadEvent.on("download:done", () => { + download(getAndroidPlatformTools()[0].url,getAndroidPlatformTools()[0].path).then(() => { + console.log('files downloaded!'); extractPlatformTools(getAndroidPlatformTools(), () => { console.log("Platform tools downloaded successfully!"); if (!cli.downloadOnly) build(); }); - }); - downloadEvent.on("download:error", (r) => { - console.log("Download error " + r); - process.exit(1); - }); - downloadEvent.on("error", (r) => { - console.log("Error: " + r); + }).catch(() => { + console.error("Failed to download files!") process.exit(1); }); - downloadEvent.on("download:start", (r) => { - console.log("Starting download of " + r + " files"); - }); - downloadEvent.on("download:next", (i) => { - console.log(`Downloading next file, ${i} left`); - }); - downloadEvent.on("download:progress", (i) => { - process.stdout.write(`Downloading file, ${Math.ceil(i.percent*100)}% complete\r`); - }); } else { build(); } diff --git a/package-lock.json b/package-lock.json index 9b5a1b5a..bc24fd9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -270,6 +270,23 @@ } } }, + "archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", + "dev": true, + "requires": { + "file-type": "^4.2.0" + }, + "dependencies": { + "file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", + "dev": true + } + } + }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", @@ -890,6 +907,18 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "dev": true, + "requires": { + "get-proxy": "^2.0.0", + "isurl": "^1.0.0-alpha5", + "tunnel-agent": "^0.6.0", + "url-to-options": "^1.0.1" + } + }, "center-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", @@ -1218,6 +1247,16 @@ } } }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "configstore": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", @@ -1243,6 +1282,15 @@ "babylon": "^6.18.0" } }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, "core-js": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", @@ -1415,6 +1463,22 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "decompress": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", + "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "dev": true, + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + } + }, "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", @@ -1424,6 +1488,114 @@ "mimic-response": "^1.0.0" } }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dev": true, + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "dependencies": { + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "dev": true + } + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dev": true, + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "dev": true + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dev": true, + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "dependencies": { + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "dev": true + } + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "dev": true, + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } + }, "decompress-zip": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.3.2.tgz", @@ -1545,6 +1717,135 @@ "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU=", "dev": true }, + "download": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", + "integrity": "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==", + "dev": true, + "requires": { + "archive-type": "^4.0.0", + "caw": "^2.0.1", + "content-disposition": "^0.5.2", + "decompress": "^4.2.0", + "ext-name": "^5.0.0", + "file-type": "^8.1.0", + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^8.3.1", + "make-dir": "^1.2.0", + "p-event": "^2.1.0", + "pify": "^3.0.0" + }, + "dependencies": { + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "dev": true + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "dev": true, + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + } + } + }, + "got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + } + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true, + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + } + } + }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -2210,6 +2511,25 @@ "pify": "^2.2.0" } }, + "ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dev": true, + "requires": { + "mime-db": "^1.28.0" + } + }, + "ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "dev": true, + "requires": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2303,6 +2623,29 @@ "escape-string-regexp": "^1.0.5" } }, + "file-type": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", + "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==", + "dev": true + }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", + "dev": true + }, + "filenamify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", + "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", + "dev": true, + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -2414,6 +2757,48 @@ "resolved": "https://registry.npmjs.org/forward-emitter/-/forward-emitter-0.1.1.tgz", "integrity": "sha1-Vu3QwIIlDtujNOC5Iv/SwBk53uE=" }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -2656,6 +3041,15 @@ } } }, + "get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "dev": true, + "requires": { + "npm-conf": "^1.1.0" + } + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -2767,6 +3161,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, "grapheme-splitter": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", @@ -2837,12 +3237,27 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true + }, "has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, "has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -2992,6 +3407,24 @@ } } }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "dev": true, + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + }, + "dependencies": { + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true + } + } + }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -3091,6 +3524,12 @@ "is-path-inside": "^1.0.0" } }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", + "dev": true + }, "is-npm": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", @@ -3103,6 +3542,12 @@ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, "is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", @@ -3112,6 +3557,12 @@ "path-is-inside": "^1.0.1" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -3125,6 +3576,12 @@ "has": "^1.0.1" } }, + "is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -3221,6 +3678,16 @@ } } }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, "jquery": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", @@ -4060,6 +4527,24 @@ "integrity": "sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ==", "dev": true }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "requires": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, "npm-install-package": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz", @@ -4297,6 +4782,15 @@ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, + "p-event": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", + "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", + "dev": true, + "requires": { + "p-timeout": "^2.0.1" + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -4327,6 +4821,15 @@ "p-limit": "^2.0.0" } }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -4535,6 +5038,12 @@ "asap": "~2.0.3" } }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -4686,6 +5195,17 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -5027,6 +5547,26 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "dev": true, + "requires": { + "commander": "~2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + } + } + }, "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", @@ -5115,6 +5655,24 @@ "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.14.0.tgz", "integrity": "sha512-9stIF1utB0ywNHNT7RgiXbdmen8QDCRsrTjw+G9TgKt1Yexjiv8TOWZ6WHsTPz57Yky3DIswZvEqX8fpuHNDtQ==" }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "dev": true, + "requires": { + "sort-keys": "^1.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5241,6 +5799,12 @@ "integrity": "sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng==", "dev": true }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -5276,6 +5840,15 @@ "is-utf8": "^0.2.0" } }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dev": true, + "requires": { + "is-natural-number": "^4.0.1" + } + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -5297,6 +5870,15 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "sumchecker": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-1.3.1.tgz", @@ -5610,6 +6192,15 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "truncate-utf8-bytes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", @@ -5792,6 +6383,16 @@ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "optional": true }, + "unbzip2-stream": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", + "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", + "dev": true, + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, "unique-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", @@ -5923,6 +6524,12 @@ "prepend-http": "^2.0.0" } }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true + }, "utf8-byte-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", diff --git a/package.json b/package.json index 12244dc5..08e1d057 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "electron-packager": "^12.2.0", "istanbul": "^0.4.5", "mocha": "^6.2.0", + "download": "^7.1.0", "sinon": "^1.17.7", "spectron": "^3.6.0", "unzipper": "^0.9.4" From be25fbed4afd3342133a4cbb441093d3b7eb26ac Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 27 Sep 2019 04:49:26 +0200 Subject: [PATCH 08/47] Ignore another connection-lost error, fixes #883 --- src/fastboot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fastboot.js b/src/fastboot.js index 750b1912..a76505d8 100644 --- a/src/fastboot.js +++ b/src/fastboot.js @@ -33,6 +33,7 @@ var handleError = (c, r, e, password, callback) => { } else if ( e.includes("FAILED (status read failed (No such device))") || e.includes("FAILED (command write failed (No such device))") || + e.includes("FAILED (command write failed (Success))") || e.includes("FAILED (data transfer failure (Broken pipe))") || e.includes("FAILED (data transfer failure (Protocol error))") ) { From 9146f62beb12021fa4b7952d9dd275a1e61098b0 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 27 Sep 2019 16:53:00 +0200 Subject: [PATCH 09/47] Download system-image files in parallel; improve guidance and progress bars --- package-lock.json | 213 ++++++++++---------------------------- package.json | 2 +- src/devices.js | 26 ++++- src/html/index.pug | 9 +- src/html/scripts/main.pug | 9 ++ src/html/scripts/ui.pug | 6 ++ src/main.js | 9 ++ src/system-image.js | 41 ++------ src/utils.js | 4 +- 9 files changed, 120 insertions(+), 199 deletions(-) diff --git a/package-lock.json b/package-lock.json index bc24fd9d..2b98ed80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -274,7 +274,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", - "dev": true, "requires": { "file-type": "^4.2.0" }, @@ -282,8 +281,7 @@ "file-type": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", - "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", - "dev": true + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=" } } }, @@ -565,8 +563,7 @@ "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -596,7 +593,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "dev": true, "requires": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" @@ -605,14 +601,12 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -627,7 +621,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -728,7 +721,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true, "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" @@ -738,7 +730,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, "requires": { "buffer-alloc-unsafe": "^1.1.0", "buffer-fill": "^1.0.0" @@ -747,20 +738,17 @@ "buffer-alloc-unsafe": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" }, "buffer-from": { "version": "1.1.1", @@ -911,7 +899,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", - "dev": true, "requires": { "get-proxy": "^2.0.0", "isurl": "^1.0.0-alpha5", @@ -1099,7 +1086,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "requires": { "mimic-response": "^1.0.0" } @@ -1251,7 +1237,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dev": true, "requires": { "ini": "^1.3.4", "proto-list": "~1.2.1" @@ -1286,7 +1271,6 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, "requires": { "safe-buffer": "5.1.2" } @@ -1460,14 +1444,12 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "decompress": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", - "dev": true, "requires": { "decompress-tar": "^4.0.0", "decompress-tarbz2": "^4.0.0", @@ -1483,7 +1465,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, "requires": { "mimic-response": "^1.0.0" } @@ -1492,7 +1473,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", - "dev": true, "requires": { "file-type": "^5.2.0", "is-stream": "^1.1.0", @@ -1502,8 +1482,7 @@ "file-type": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", - "dev": true + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" } } }, @@ -1511,7 +1490,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", - "dev": true, "requires": { "decompress-tar": "^4.1.0", "file-type": "^6.1.0", @@ -1523,8 +1501,7 @@ "file-type": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", - "dev": true + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" } } }, @@ -1532,7 +1509,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", - "dev": true, "requires": { "decompress-tar": "^4.1.1", "file-type": "^5.2.0", @@ -1542,8 +1518,7 @@ "file-type": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", - "dev": true + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" } } }, @@ -1551,7 +1526,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", - "dev": true, "requires": { "file-type": "^3.8.0", "get-stream": "^2.2.0", @@ -1563,7 +1537,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, "requires": { "pend": "~1.2.0" } @@ -1571,14 +1544,12 @@ "file-type": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", - "dev": true + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" }, "get-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", - "dev": true, "requires": { "object-assign": "^4.0.1", "pinkie-promise": "^2.0.0" @@ -1588,7 +1559,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, "requires": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -1721,7 +1691,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", "integrity": "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==", - "dev": true, "requires": { "archive-type": "^4.0.0", "caw": "^2.0.1", @@ -1740,14 +1709,12 @@ "@sindresorhus/is": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", - "dev": true + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", - "dev": true, "requires": { "clone-response": "1.0.2", "get-stream": "3.0.0", @@ -1761,8 +1728,7 @@ "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", - "dev": true + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" } } }, @@ -1770,7 +1736,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", - "dev": true, "requires": { "@sindresorhus/is": "^0.7.0", "cacheable-request": "^2.1.1", @@ -1794,14 +1759,12 @@ "http-cache-semantics": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" }, "keyv": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true, "requires": { "json-buffer": "3.0.0" } @@ -1810,7 +1773,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, "requires": { "prepend-http": "^2.0.0", "query-string": "^5.0.1", @@ -1820,20 +1782,17 @@ "p-cancelable": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", - "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", - "dev": true + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" }, "sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, "requires": { "is-plain-obj": "^1.0.0" } @@ -1841,8 +1800,7 @@ "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" } } }, @@ -1890,8 +1848,7 @@ "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, "ecc-jsbn": { "version": "0.1.2", @@ -2381,7 +2338,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -2515,7 +2471,6 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", - "dev": true, "requires": { "mime-db": "^1.28.0" } @@ -2524,7 +2479,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", - "dev": true, "requires": { "ext-list": "^2.0.0", "sort-keys-length": "^1.0.0" @@ -2626,20 +2580,17 @@ "file-type": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", - "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==", - "dev": true + "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==" }, "filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", - "dev": true + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=" }, "filenamify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", - "dev": true, "requires": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.0", @@ -2761,7 +2712,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" @@ -2770,14 +2720,12 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -2792,7 +2740,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -2802,8 +2749,7 @@ "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { "version": "2.1.2", @@ -3045,7 +2991,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", - "dev": true, "requires": { "npm-conf": "^1.1.0" } @@ -3059,8 +3004,7 @@ "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "getos": { "version": "3.1.1", @@ -3164,8 +3108,7 @@ "graceful-readlink": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, "grapheme-splitter": { "version": "1.0.4", @@ -3240,8 +3183,7 @@ "has-symbol-support-x": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "dev": true + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" }, "has-symbols": { "version": "1.0.0", @@ -3253,7 +3195,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, "requires": { "has-symbol-support-x": "^1.4.1" } @@ -3309,8 +3250,7 @@ "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, "import-lazy": { "version": "2.1.0", @@ -3411,7 +3351,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true, "requires": { "from2": "^2.1.1", "p-is-promise": "^1.1.0" @@ -3420,8 +3359,7 @@ "p-is-promise": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" } } }, @@ -3527,8 +3465,7 @@ "is-natural-number": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", - "dev": true + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" }, "is-npm": { "version": "3.0.0", @@ -3545,8 +3482,7 @@ "is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" }, "is-path-inside": { "version": "1.0.1", @@ -3560,8 +3496,7 @@ "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" }, "is-promise": { "version": "2.1.0", @@ -3579,14 +3514,12 @@ "is-retry-allowed": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", - "dev": true + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-symbol": { "version": "1.0.2", @@ -3682,7 +3615,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, "requires": { "has-to-string-tag-x": "^1.2.0", "is-object": "^1.0.1" @@ -3720,8 +3652,7 @@ "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" }, "json-schema": { "version": "0.2.3", @@ -3982,8 +3913,7 @@ "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" }, "lru-cache": { "version": "4.1.5", @@ -3999,7 +3929,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, "requires": { "pify": "^3.0.0" }, @@ -4007,8 +3936,7 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" } } }, @@ -4091,8 +4019,7 @@ "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" }, "minimatch": { "version": "3.0.4", @@ -4531,7 +4458,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", - "dev": true, "requires": { "config-chain": "^1.1.11", "pify": "^3.0.0" @@ -4540,8 +4466,7 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" } } }, @@ -4786,7 +4711,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", - "dev": true, "requires": { "p-timeout": "^2.0.1" } @@ -4794,8 +4718,7 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-is-promise": { "version": "2.1.0", @@ -4825,7 +4748,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true, "requires": { "p-finally": "^1.0.0" } @@ -4949,8 +4871,7 @@ "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" }, "performance-now": { "version": "2.1.0", @@ -4965,14 +4886,12 @@ "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { "pinkie": "^2.0.0" } @@ -5001,8 +4920,7 @@ "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, "pretty-bytes": { "version": "1.0.4", @@ -5017,8 +4935,7 @@ "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "progress-stream": { "version": "1.2.0", @@ -5041,8 +4958,7 @@ "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" }, "pseudomap": { "version": "1.0.2", @@ -5199,7 +5115,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, "requires": { "decode-uri-component": "^0.2.0", "object-assign": "^4.1.0", @@ -5439,7 +5354,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, "requires": { "lowercase-keys": "^1.0.0" } @@ -5551,7 +5465,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", - "dev": true, "requires": { "commander": "~2.8.1" }, @@ -5560,7 +5473,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "dev": true, "requires": { "graceful-readlink": ">= 1.0.0" } @@ -5659,7 +5571,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, "requires": { "is-plain-obj": "^1.0.0" } @@ -5668,7 +5579,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", - "dev": true, "requires": { "sort-keys": "^1.0.0" } @@ -5802,8 +5712,7 @@ "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, "string-width": { "version": "1.0.2", @@ -5844,7 +5753,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", - "dev": true, "requires": { "is-natural-number": "^4.0.1" } @@ -5874,7 +5782,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, "requires": { "escape-string-regexp": "^1.0.2" } @@ -5909,12 +5816,14 @@ } }, "system-image-node-module": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/system-image-node-module/-/system-image-node-module-1.0.7.tgz", - "integrity": "sha1-LAMxp0PtBfRMbwzhEcnTK+L8iik=", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/system-image-node-module/-/system-image-node-module-1.0.9.tgz", + "integrity": "sha512-4KAtlVaSwW0YvsO81eeDUjcO5fPH7GWDir0FQSda8+u+dftpH8YtQIRbJQ7228CI1k5pcDHLPn2JTWRFYWPkxw==", "requires": { "chai": "^4.1.2", + "checksum": "^0.1.1", "coveralls": "^3.0.0", + "download": "^7.1.0", "istanbul": "^0.4.5", "mkdirp": "^0.5.1", "mocha": "^4.0.1", @@ -6024,7 +5933,6 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, "requires": { "bl": "^1.0.0", "buffer-alloc": "^1.2.0", @@ -6038,14 +5946,12 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -6060,7 +5966,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -6068,8 +5973,7 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" } } }, @@ -6101,8 +6005,7 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "0.2.3", @@ -6125,8 +6028,7 @@ "to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", - "dev": true + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" }, "to-fast-properties": { "version": "1.0.3", @@ -6196,7 +6098,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", - "dev": true, "requires": { "escape-string-regexp": "^1.0.2" } @@ -6387,7 +6288,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", - "dev": true, "requires": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -6519,7 +6419,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, "requires": { "prepend-http": "^2.0.0" } @@ -6527,8 +6426,7 @@ "url-to-options": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", - "dev": true + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" }, "utf8-byte-length": { "version": "1.0.4", @@ -6560,8 +6458,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "3.3.2", diff --git a/package.json b/package.json index 08e1d057..f8f22929 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "mkdirp": "^0.5.1", "request": "^2.79.0", "request-progress": "^3.0.0", - "system-image-node-module": "^1.0.7", + "system-image-node-module": "^1.0.9", "ubports-api-node-module": "^1.0.2", "tmp": "0.0.31", "wildcard": "^1.1.2", diff --git a/src/devices.js b/src/devices.js index 30aa37ea..950ca024 100644 --- a/src/devices.js +++ b/src/devices.js @@ -244,21 +244,34 @@ global.mainEvent.on("download:start", (total) => { global.mainEvent.nextTotal = total; global.mainEvent.nextCurrent = 1; global.mainEvent.nextBaseProgress = 0; - utils.log.info("Starting download of "+total+" files"); global.mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); - global.mainEvent.emit("user:write:next", "Downloading", 1, total); + if (total) global.mainEvent.emit("user:write:next", "Downloading", 1, total); + else global.mainEvent.emit("user:write:under", "Downloading"); }); -global.mainEvent.on("download:next", (current, total) => { +global.mainEvent.on("download:next:hack", (current, total) => { global.mainEvent.nextCurrent = current; global.mainEvent.nextBaseProgress = Math.abs(Math.ceil((current-1)/total*100)); utils.log.info(`Downloading file ${global.mainEvent.nextCurrent}/${global.mainEvent.nextTotal}`); global.mainEvent.emit("user:write:next", "Downloading", global.mainEvent.nextCurrent, global.mainEvent.nextTotal); global.mainEvent.emit("user:write:progress", global.mainEvent.nextBaseProgress); }); -global.mainEvent.on("download:progress", (percent) => { +global.mainEvent.on("download:next", (current, total) => { + utils.log.info(`Downloading file ${current}/${total}`); + global.mainEvent.emit("user:write:next", "Downloading", current, total); +}); +// TODO remove this one in favor of download:progress +global.mainEvent.on("download:progress:hack", (percent) => { utils.log.debug(`Downloading file ${global.mainEvent.nextCurrent} of ${global.mainEvent.nextTotal}, ${Math.ceil(percent)}% complete`); global.mainEvent.emit("user:write:progress", Math.ceil(percent/global.mainEvent.nextTotal+global.mainEvent.nextBaseProgress)); }); +global.mainEvent.on("download:progress", (percent) => { + // utils.log.debug(`Downloading files: ${percent*100}% complete`); + global.mainEvent.emit("user:write:progress", percent*100); +}); +global.mainEvent.on("download:speed", (speed) => { + // utils.log.debug(`Downloading at ${speed}% MB/s`); + global.mainEvent.emit("user:write:speed", Math.round(speed*100)/100); +}); global.mainEvent.on("adbpush:error", (e) => { global.mainEvent.removeListener("adbpush:end", () => {}); global.mainEvent.emit("error", "Adb push error: " + e) @@ -305,6 +318,7 @@ var install = (options) => { utils.log.info("Rebooting to recovery to flash"); global.mainEvent.emit("system-image:done"); global.mainEvent.emit("user:write:status", "Rebooting to recovery to start the flashing process"); + global.mainEvent.emit("user:write:status", "All files pushed successfully!"); global.mainEvent.emit("user:write:progress", 0); }); global.mainEvent.once("system-image:start", () => { @@ -326,7 +340,8 @@ var install = (options) => { global.mainEvent.emit("system-image:start"); }); } else { - global.mainEvent.emit("user:write:status", "Waiting for device to enter recovery mode"); + global.mainEvent.emit("user:write:status", "Waiting for device to enter recovery mode", true); + global.mainEvent.emit("user:write:under", "Rebooting..."); adb.waitForDevice(() => { global.mainEvent.emit("system-image:start"); }); @@ -334,6 +349,7 @@ var install = (options) => { }); if (instructs.images.length > 0) { // If images are specified, flash them (bootstrapping) // We need to be in bootloader + global.mainEvent.emit("user:write:under", "Please connect your device with a USB cable"); instructReboot("bootloader", instructs.buttons, () => { global.mainEvent.once("download:done", () => { instructBootstrap(instructs.installSettings.bootstrap, addPathToImages(instructs.images, options.device)); diff --git a/src/html/index.pug b/src/html/index.pug index 88ec933b..52859ecf 100644 --- a/src/html/index.pug +++ b/src/html/index.pug @@ -25,9 +25,12 @@ html #progress.progress(hidden='hidden') footer.footer.is-over .container - h3#footer-top.text-muted.footer-top UBports Installer is starting up - span#wait-dot(hidden='false') . - p#footer-bottom.text-muted Starting adb service + h3(style="margin-top: 0").text-muted.footer-top + span#footer-top UBports Installer is starting up + span#wait-dot(hidden='false') + p + span#footer-bottom.text-muted Starting adb service + span#footer-speed.text-muted // --- Modals --- include modals/install include modals/connection-lost diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index 527184fd..af9b13dd 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -49,6 +49,7 @@ script. ipcRenderer.on("system-image:start", () => { views.show("working", "particles"); + footer.underText.set("Preparing system image"); }); ipcRenderer.on("download:start", () => { @@ -114,6 +115,10 @@ script. modals.show('no-network'); }); + ipcRenderer.on("user:write:speed", (e, speed) => { + footer.speedText.set(speed); + }); + ipcRenderer.on("user:write:next", (e, text, current, total) => { footer.underText.set(text + " file " + current + " of " + total); }); @@ -144,6 +149,10 @@ script. footer.topText.set(status, true) }); + ipcRenderer.on("user:write:under", (e, status) => { + footer.underText.set(status, true) + }); + ipcRenderer.on("user:device-unsupported", (event, device) => { footer.topText.set("Device not supported"); footer.underText.set("The device " + device + " is not supported"); diff --git a/src/html/scripts/ui.pug b/src/html/scripts/ui.pug index 78cb2f59..3bede503 100644 --- a/src/html/scripts/ui.pug +++ b/src/html/scripts/ui.pug @@ -113,6 +113,12 @@ script. set: (text) => { return $("#footer-bottom").text(text) } + }, + speedText: { + set: (text) => { + if (text) return $("#footer-speed").text(" at " + text + " MB/s"); + else return $("#footer-speed").text(""); + } } } diff --git a/src/main.js b/src/main.js index 084e13a2..3ffb1b1e 100755 --- a/src/main.js +++ b/src/main.js @@ -188,6 +188,7 @@ mainEvent.on("user:write:progress", (length) => { mainEvent.on("user:write:done", () => { mainWindow.webContents.send("user:write:done"); + mainWindow.webContents.send("user:write:speed"); utils.log.info("All done! Your device will now reboot and complete the installation. Enjoy exploring Ubuntu Touch!"); }); @@ -195,6 +196,14 @@ mainEvent.on("user:write:status", (status) => { mainWindow.webContents.send("user:write:status", status); }); +mainEvent.on("user:write:speed", (speed) => { + mainWindow.webContents.send("user:write:speed", speed); +}); + +mainEvent.on("user:write:under", (status) => { + mainWindow.webContents.send("user:write:under", status); +}); + mainEvent.on("user:adb:ready", () => { mainWindow.webContents.send("user:adb:ready"); }); diff --git a/src/system-image.js b/src/system-image.js index 7be40bd4..082acaf5 100644 --- a/src/system-image.js +++ b/src/system-image.js @@ -24,34 +24,6 @@ const getDeviceChannels = (device) => { return systemImage.getDeviceChannels(device); } -var downloadLatestVersion = (options) => { - utils.log.debug("downloadLatestVersion options: ", options); - systemImage.getLatestVersion(options.device, options.channel).then((latest) => { - var urls = systemImage.getFilesUrlsArray(latest) - urls.push.apply(urls, systemImage.getGgpUrlsArray()); - var files = systemImage.getFilePushArray(urls); - utils.downloadFiles(urls); - utils.log.debug(urls); - mainEvent.once("download:done", () => { - files.push({ - src: systemImage.createInstallCommandsFile( - systemImage.createInstallCommands( - latest.files, - options.installerCheck, - options.wipe, - options.enable - ), - options.device - ), - dest: ubuntuPushDir + ubuntuCommandFile - }); - mainEvent.emit("download:pushReady", files); - }); - }).catch(() => { - mainEvent.emit("error", "could not find latest version; " + "device: " + options.device + " channel: " + options.channel); - }); -} - var pushLatestVersion = (files, dontWipeCache) => { var doPush = () => { adb.shell("mount -a", () => { @@ -67,8 +39,17 @@ var pushLatestVersion = (files, dontWipeCache) => { } var installLatestVersion = (options) => { - downloadLatestVersion(options); - mainEvent.once("download:pushReady", (files) => { + mainEvent.once("download:progress", () => { + mainEvent.emit("download:start"); + }) + systemImage.downloadLatestVersion(options, (progress, speed) => { + mainEvent.emit("download:progress", progress); + mainEvent.emit("download:speed", speed); + }, (current, total) => { + if (current != total) mainEvent.emit("download:next", current+1, total); + }).then((files) => { + utils.log.debug(files) + mainEvent.emit("download:done"); pushLatestVersion(files); }); } diff --git a/src/utils.js b/src/utils.js index 0248beb0..fe0bac2d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -442,7 +442,7 @@ var downloadFiles = (urls_) => { } progress(http(urls[0].url)) .on('progress', (state) => { - mainEvent.emit("download:progress", state.percent*100); + mainEvent.emit("download:progress:hack", state.percent*100); }) .once('error', (err) => { if (err) mainEvent.emit("download:error", err); @@ -457,7 +457,7 @@ var downloadFiles = (urls_) => { mainEvent.emit("download:done"); } else { urls.shift(); - mainEvent.emit("download:next", totalFiles-urls.length+1, totalFiles); + mainEvent.emit("download:next:hack", totalFiles-urls.length+1, totalFiles); dl() } } else { From 8745e7ec73bc3be0cafaf17e46ec58b778e5c77c Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 27 Sep 2019 17:42:50 +0200 Subject: [PATCH 10/47] Add a note that the oem option in the settings is not always there, as suggested by #888. --- src/html/modals/developer-mode.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/html/modals/developer-mode.pug b/src/html/modals/developer-mode.pug index 1b333914..910c5f0f 100644 --- a/src/html/modals/developer-mode.pug +++ b/src/html/modals/developer-mode.pug @@ -47,7 +47,7 @@ li | Now go back to the Settings menu and find "developer settings" (sometimes called "developer options"), Tap that. li - | Enable the "OEM unlock" and "USB debugging" options. + | Enable "USB debugging", "ADB" or "Android Debug Bridge" option. If you see it, also enable the "allow OEM unlock" option, but that is not available on every device. .col-xs-6 img(src='../screens/android-dev-mode.gif', style='width: 100%') .modal-footer From 50ea94718940c100f0042bbde95cebea5e3b51c7 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 27 Sep 2019 17:56:40 +0200 Subject: [PATCH 11/47] Improve update detection --- src/html/scripts/ui.pug | 4 ++-- src/main.js | 7 ++++++- src/utils.js | 7 +++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/html/scripts/ui.pug b/src/html/scripts/ui.pug index 3bede503..5c3ffb24 100644 --- a/src/html/scripts/ui.pug +++ b/src/html/scripts/ui.pug @@ -233,7 +233,7 @@ script. modals.show('windows-drivers'); } - if(global.packageInfo.updateAvailable) { + ipcRenderer.on("user:update-available", () => { if (global.packageInfo.isSnap) { $("#snap-update-instructions").show(); $("#btn-update-installer").hide(); @@ -241,4 +241,4 @@ script. $("#generic-update-instructions").show(); } modals.show('new-update'); - } + }); diff --git a/src/main.js b/src/main.js index 3ffb1b1e..0ec68dfd 100755 --- a/src/main.js +++ b/src/main.js @@ -60,7 +60,6 @@ global.installProperties = { }; global.packageInfo.isSnap = utils.isSnap(); -utils.getUpdateAvailable((updateAvailable) => { global.packageInfo.updateAvailable = updateAvailable; }); //============================================================================== // RENDERER SIGNAL HANDLING @@ -250,6 +249,12 @@ function createWindow () { devices.getDeviceSelects((out) => { mainEvent.emit("device:wait:data-ready", out) }); + utils.getUpdateAvailable().then(() => { + utils.log.info("This is not the latest version! Please update: https://devices.ubuntu-touch.io/installer/" + global.packageInfo.package); + mainWindow.webContents.send("user:update-available"); + }).catch(() => { + utils.log.debug("This is the latest version.") + }); }); mainWindow.loadURL(url.format({ diff --git a/src/utils.js b/src/utils.js index fe0bac2d..37dc7f3a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -133,8 +133,11 @@ function getLatestInstallerVersion() { } function getUpdateAvailable() { - return getLatestInstallerVersion().then((latestVersion) => { - return latestVersion != global.packageInfo.version; + return new Promise((resolve, reject) => { + getLatestInstallerVersion().then((latestVersion) => { + if(latestVersion != global.packageInfo.version) resolve(); + else reject(); + }); }); } From 30bc221dde82db3c47d7cffbb0d62cbba005dffb Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 27 Sep 2019 18:05:11 +0200 Subject: [PATCH 12/47] Catch and ignore jenkins errors --- Jenkinsfile | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 44df8f9c..a46f3f4c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,20 +2,28 @@ pipeline { agent any stages { stage('Install') { - steps { - sh 'curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash' - sh 'chmod +x "$HOME/.nvm/nvm.sh"' - sh '$HOME/.nvm/nvm.sh install 8' - sh 'npm install' - sh 'npm prune' + try { + steps { + sh 'curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash' + sh 'chmod +x "$HOME/.nvm/nvm.sh"' + sh '$HOME/.nvm/nvm.sh install 8' + sh 'npm install' + sh 'npm prune' + } + } catch (e) { + echo e } } stage('Build') { - steps { - sh 'npm run dist:linux:deb' - sh 'npm run dist:linux:appimage' - sh 'npm run dist:linux:snap' - sh 'mv ./*.snap ./dist/.' + try { + steps { + sh 'npm run dist:linux:deb' + sh 'npm run dist:linux:appimage' + sh 'npm run dist:linux:snap' + sh 'mv ./*.snap ./dist/.' + } + } catch (e) { + echo e } } } From d658dafce492d70dce3c32a2a20a94ecaa974e4c Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 27 Sep 2019 18:07:26 +0200 Subject: [PATCH 13/47] Fix Jenkinsfile syntax --- Jenkinsfile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index a46f3f4c..0a43562b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,28 +2,28 @@ pipeline { agent any stages { stage('Install') { - try { - steps { + steps { + try { sh 'curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash' sh 'chmod +x "$HOME/.nvm/nvm.sh"' sh '$HOME/.nvm/nvm.sh install 8' sh 'npm install' sh 'npm prune' + } catch (e) { + echo e } - } catch (e) { - echo e } } stage('Build') { - try { - steps { + steps { + try { sh 'npm run dist:linux:deb' sh 'npm run dist:linux:appimage' sh 'npm run dist:linux:snap' sh 'mv ./*.snap ./dist/.' + } catch (e) { + echo e } - } catch (e) { - echo e } } } From e3253d4683f0371322eaa5ebd7bd4bfccbf5d5f7 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 27 Sep 2019 18:11:40 +0200 Subject: [PATCH 14/47] Jenkins: will it build? Stay tuned to find out! --- Jenkinsfile | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 0a43562b..88583ac5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -3,26 +3,30 @@ pipeline { stages { stage('Install') { steps { - try { - sh 'curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash' - sh 'chmod +x "$HOME/.nvm/nvm.sh"' - sh '$HOME/.nvm/nvm.sh install 8' - sh 'npm install' - sh 'npm prune' - } catch (e) { - echo e + script { + try { + sh 'curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash' + sh 'chmod +x "$HOME/.nvm/nvm.sh"' + sh '$HOME/.nvm/nvm.sh install 8' + sh 'npm install' + sh 'npm prune' + } catch (e) { + echo e + } } } } stage('Build') { steps { - try { - sh 'npm run dist:linux:deb' - sh 'npm run dist:linux:appimage' - sh 'npm run dist:linux:snap' - sh 'mv ./*.snap ./dist/.' - } catch (e) { - echo e + script { + try { + sh 'npm run dist:linux:deb' + sh 'npm run dist:linux:appimage' + sh 'npm run dist:linux:snap' + sh 'mv ./*.snap ./dist/.' + } catch (e) { + echo e + } } } } From a374a7146bb1f6dd712655ad3de3e9a230b75c91 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 27 Sep 2019 18:32:46 +0200 Subject: [PATCH 15/47] Remove getRandomInt function moved to SIC module --- src/utils.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/utils.js b/src/utils.js index 37dc7f3a..a392a2bd 100644 --- a/src/utils.js +++ b/src/utils.js @@ -483,12 +483,6 @@ var downloadFiles = (urls_) => { }); } -const getRandomInt = (min, max) => { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min)) + min; -} - const hidePassword = (output, pw) => { if (needRoot()) { return output.replace(pw.replace(/\'/g, "'\\''"), "***"); @@ -516,7 +510,6 @@ module.exports = { getUpdateAvailable: getUpdateAvailable, getPlatform: getPlatform, asarExec: asarExec, - getRandomInt: getRandomInt, getVersion: getVersion, hidePassword: hidePassword, die: die, From 8534e62fd085bd835cabae2d4ce894bc0dd136af Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 27 Sep 2019 20:59:58 +0200 Subject: [PATCH 16/47] Parallelize bootstrap downloads --- package-lock.json | 13 ---- package.json | 3 +- src/devices.js | 24 +++++-- src/utils.js | 158 ++++++++++++++++++++-------------------------- 4 files changed, 90 insertions(+), 108 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2b98ed80..0aef8103 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5316,14 +5316,6 @@ "uuid": "^3.3.2" } }, - "request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", - "requires": { - "throttleit": "^1.0.0" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5997,11 +5989,6 @@ "execa": "^0.7.0" } }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=" - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", diff --git a/package.json b/package.json index f8f22929..e1b5c8bc 100644 --- a/package.json +++ b/package.json @@ -41,13 +41,13 @@ "electron-packager": "^12.2.0", "istanbul": "^0.4.5", "mocha": "^6.2.0", - "download": "^7.1.0", "sinon": "^1.17.7", "spectron": "^3.6.0", "unzipper": "^0.9.4" }, "dependencies": { "bootstrap": "^3.3.7", + "download": "^7.1.0", "popper.js": "^1.14.3", "checksum": "^0.1.1", "command-exists": "^1.2.2", @@ -64,7 +64,6 @@ "jquery-i18next": "^1.2.0", "mkdirp": "^0.5.1", "request": "^2.79.0", - "request-progress": "^3.0.0", "system-image-node-module": "^1.0.9", "ubports-api-node-module": "^1.0.2", "tmp": "0.0.31", diff --git a/src/devices.js b/src/devices.js index 950ca024..02f7767b 100644 --- a/src/devices.js +++ b/src/devices.js @@ -213,6 +213,23 @@ var instructBootstrap = (bootstrap, images) => { } } +var downloadImages = (images, device) => { + utils.log.debug(addPathToImages(images, device)) + global.mainEvent.once("download:progress", () => { + global.mainEvent.emit("download:start"); + }) + utils.downloadFiles(images, (progress, speed) => { + global.mainEvent.emit("download:progress", progress); + global.mainEvent.emit("download:speed", speed); + }, (current, total) => { + if (current != total) global.mainEvent.emit("download:next", current+1, total); + }).then((files) => { + utils.log.debug(files) + global.mainEvent.emit("download:done"); + pushLatestVersion(files); + }); +} + var addPathToImages = (images, device) => { var ret = []; images.forEach((image) => { @@ -308,10 +325,6 @@ var install = (options) => { return false; utils.log.debug("install event started with options: " + JSON.stringify(options)) devicesApi.getInstallInstructs(options.device).then((instructs) => { - global.mainEvent.once("images:startDownload", () => { - global.mainEvent.emit("user:write:status", "Downloading images"); - utils.downloadFiles(addPathToImages(instructs.images, options.device)); - }); global.mainEvent.once("adbpush:done", () => { global.mainEvent.removeListener("adbpush:end", () => {}); utils.log.info("Done pushing files"); @@ -354,7 +367,8 @@ var install = (options) => { global.mainEvent.once("download:done", () => { instructBootstrap(instructs.installSettings.bootstrap, addPathToImages(instructs.images, options.device)); }); - global.mainEvent.emit("images:startDownload"); + global.mainEvent.emit("user:write:status", "Downloading images"); + downloadImages(instructs.images, options.device); }); } else { // If no images are specified, go straight to system-image // We need to be in recovery diff --git a/src/utils.js b/src/utils.js index a392a2bd..aa4dc98b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -7,7 +7,7 @@ Author: Marius Gripsgard */ const http = require("request"); -const progress = require("request-progress"); +const download = require("download"); const os = require("os"); const fs = require("fs-extra"); const path = require("path"); @@ -378,51 +378,28 @@ var ensureRoot = (m) => { process.exit(1); } -var checkFiles = (urls, callback) => { - var urls_ = []; - var next = () => { - if (urls.length <= 1) { - callback(urls_) +function checksumFile(file) { + return new Promise(function(resolve, reject) { + fs.access(path.join(file.path, path.basename(file.url)), (err) => { + if (err) { + reject(); + } else { + if (!file.checksum) { + // No checksum so return true; + resolve(); + return; } else { - urls.shift(); - check() + checksum.file(path.join(file.path, path.basename(file.url)), { + algorithm: "sha256" + }, function(err, sum) { + utils.log.debug("checked: " +path.basename(file.url), sum === file.checksum); + if (sum === file.checksum) resolve(); + else reject(); + }); } - } - var check = () => { - fs.access(path.join(urls[0].path, path.basename(urls[0].url)), (err) => { - if (err) { - log.debug("Not existing " + path.join(urls[0].path, path.basename(urls[0].url))); - urls_.push(urls[0]); - next(); - } else { - checksumFile(urls[0], (check) => { - if (check) { - log.debug(path.join(urls[0].path, path.basename(urls[0].url)) + " exists with the expected checksum, so the download will be skipped."); - next(); - } else { - log.debug("Checksum mismatch on " + path.join(urls[0].path, path.basename(urls[0].url)) + ". This file will be downloaded again."); - urls_.push(urls[0]); - next(); - } - }) - } - }) - } - check(); -} - -var checksumFile = (file, callback) => { - if (!file.checksum) { - // No checksum so return true; - callback(true); - return; - } - checksum.file(path.join(file.path, path.basename(file.url)), { - algorithm: "sha256" - }, function(err, sum) { - log.debug("checked: " +path.basename(file.url), sum === file.checksum); - callback(sum === file.checksum, sum); + } }); + }); } /* @@ -435,51 +412,58 @@ urls format: } ] */ -var downloadFiles = (urls_) => { - var urls; - var totalFiles; - mainEvent.emit("download:startCheck"); - var dl = () => { - if (!fs.existsSync(urls[0].path)) { - mkdirp.sync(urls[0].path); - } - progress(http(urls[0].url)) - .on('progress', (state) => { - mainEvent.emit("download:progress:hack", state.percent*100); - }) - .once('error', (err) => { - if (err) mainEvent.emit("download:error", err); - }) - .once('end', () => { - fs.rename(path.join(urls[0].path, path.basename(urls[0].url + ".tmp")), - path.join(urls[0].path, path.basename(urls[0].url)), () => { - mainEvent.emit("download:checking"); - checksumFile(urls[0], (check) => { - if (check) { - if (urls.length <= 1) { - mainEvent.emit("download:done"); - } else { - urls.shift(); - mainEvent.emit("download:next:hack", totalFiles-urls.length+1, totalFiles); - dl() - } - } else { - mainEvent.emit("download:error", "Checksum mismatch on file " + path.basename(urls[0].url)); - } +function downloadFiles(urls, progress, next) { + return new Promise(function(resolve, reject) { + var filesDownloaded = 0; + var overallSize = 0; + var overallDownloaded = 0; + var previousOverallDownloaded = 0; + var downloadProgress = 0; + var progressInterval = setInterval(() => { + downloadProgress = overallDownloaded/overallSize; + if (overallSize != 0) { + if (downloadProgress < 0.999) { + progress(downloadProgress, (overallDownloaded-previousOverallDownloaded)/1000000); + previousOverallDownloaded = overallDownloaded; + } else { + clearInterval(progressInterval); + progress(1, 0); + } + } + }, 1000); + Promise.all(urls.map((file) => { + return new Promise(function(resolve, reject) { + checksumFile(file).then(() => { + next(++filesDownloaded, urls.length); + resolve(); + return; + }).catch(() => { + download(file.url, file.path).on("response", (res) => { + var totalSize = eval(res.headers['content-length']); + overallSize += totalSize; + var downloaded = 0; + res.on('data', data => { + overallDownloaded += data.length; + }); + }).then(() => { + checksumFile(file).then(() => { + next(++filesDownloaded, urls.length); + resolve(); + return; + }).catch((err) => { + reject(err); + return; + }); + }); }); }); - }) - .pipe(fs.createWriteStream(path.join(urls[0].path, path.basename(urls[0].url + ".tmp")))); - } - checkFiles(urls_, (ret) => { - if (ret.length <= 0) { - mainEvent.emit("download:done"); - } else { - urls = ret; - totalFiles = urls.length; - mainEvent.emit("download:start", totalFiles); - dl(); - } + })).then(() => { + resolve(); + return; + }).catch((err) => { + reject(err); + return; + }); }); } @@ -494,8 +478,6 @@ const hidePassword = (output, pw) => { module.exports = { setCustomPlatformTool: setCustomPlatformTool, downloadFiles: downloadFiles, - checksumFile: checksumFile, - checkFiles: checkFiles, log: log, platformToolsExec: platformToolsExec, platformToolsExecAsar: platformToolsExecAsar, From 63aadf94cd0157dc57df480dc86ba2ecdc2d3df2 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Fri, 27 Sep 2019 21:31:02 +0200 Subject: [PATCH 17/47] Move to default ADB port --- src/adb.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adb.js b/src/adb.js index 2ed5cb6c..6ea8ef9a 100644 --- a/src/adb.js +++ b/src/adb.js @@ -16,7 +16,7 @@ const utils = require("./utils"); const exec = require('child_process').exec; // DEFAULT = 5037 -const PORT = 5038 +const PORT = 5037 // Since we need root anyway, why not start adb with root const start = (password, sudo, callback) => { From 697530d6ca64ed6ff9335de44f8ced73f3359679 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 00:58:49 +0200 Subject: [PATCH 18/47] Absolutely *awesome* progress bar improvement for adb push --- src/adb.js | 118 +++++++++++++++++++++++++------------------------ src/devices.js | 9 +--- 2 files changed, 63 insertions(+), 64 deletions(-) diff --git a/src/adb.js b/src/adb.js index 6ea8ef9a..6734fda6 100644 --- a/src/adb.js +++ b/src/adb.js @@ -144,74 +144,78 @@ var isBaseUbuntuCom = callback => { } var push = (file, dest) => { - var done; - var hundredEmitted; - var fileSize = fs.statSync(file)["size"]; - var guardedfile = process.platform == "darwin" ? file : '"' + file + '"'; // macos can't handle double quotes - utils.platformToolsExec("adb", ["-P", PORT, "push", guardedfile, dest], (err, stdout, stderr) => { - done=true; - if (err) { - var stdoutShort = stdout && stdout.length > 256 ? "[...]" + stdout.substr(-256, stdout.length) : stdout; - var stderrShort = stderr && stderr.length > 256 ? "[...]" + stderr.substr(-256, stderr.length) : stderr; - if (stderrShort.indexOf("I/O error") != -1) { - utils.log.warn("connection to device lost"); - // TODO: Only restart the event rather than the entire installation - mainEvent.emit("user:connection-lost", () => { mainEvent.emit("restart"); }); - } else if (!err.killed && (err.code == 1)) { - hasAdbAccess ((hasAccess) => { - if (hasAccess) { - mainEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); - } else { - utils.log.warn("connection to device lost"); - // TODO: Only restart the event rather than the entire installation - mainEvent.emit("user:connection-lost", () => { mainEvent.emit("restart"); }); - } - }); - } else { - mainEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); - } - } - else mainEvent.emit("adbpush:end"); - }); - var progress = () => { - setTimeout(function () { - shell("stat -t "+dest+"/"+path.basename(file), (stat) => { - try { - var currentSize = stat.split(" ")[1]; - var percentage = Math.ceil((currentSize/fileSize)*100); - if(!isNaN(percentage) && !hundredEmitted) mainEvent.emit("adbpush:progress", percentage); - if(percentage == 100) hundredEmitted = true; - if(!done && (percentage < fileSize)) progress(); - } catch (e) { } + return new Promise(function(resolve, reject) { + var done; + var hundredEmitted; + var fileSize = fs.statSync(file)["size"]; + var lastSize = 0; + var progressInterval = setInterval(() => { + shell("stat -t " + dest + "/" + path.basename(file), (stat) => { + mainEvent.emit("adbpush:progress:size", eval(stat.split(" ")[1])-lastSize); + lastSize = eval(stat.split(" ")[1]); }); }, 1000); - } - progress(); + var guardedfile = process.platform == "darwin" ? file : '"' + file + '"'; // macos can't handle double quotes + utils.platformToolsExec("adb", ["-P", PORT, "push", guardedfile, dest], (err, stdout, stderr) => { + done=true; + if (err) { + var stdoutShort = stdout && stdout.length > 256 ? "[...]" + stdout.substr(-256, stdout.length) : stdout; + var stderrShort = stderr && stderr.length > 256 ? "[...]" + stderr.substr(-256, stderr.length) : stderr; + if (stderrShort.indexOf("I/O error") != -1) { + utils.log.warn("connection to device lost"); + // TODO: Only restart the event rather than the entire installation + mainEvent.emit("user:connection-lost", () => { mainEvent.emit("restart"); }); + } else if (!err.killed && (err.code == 1)) { + hasAdbAccess ((hasAccess) => { + if (hasAccess) { + mainEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); + } else { + utils.log.warn("connection to device lost"); + // TODO: Only restart the event rather than the entire installation + mainEvent.emit("user:connection-lost", () => { mainEvent.emit("restart"); }); + } + }); + } else { + mainEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); + } + } + clearInterval(progressInterval); + resolve(); + }); + }); } var pushMany = (files) => { - var totalLength = files.length; if (files.length <= 0){ mainEvent.emit("adbpush:error", "No files provided"); return false; } + var totalSize = 0; + var downloadedSize = 0; + // Get total size for progress bar + files.forEach((file) => { + totalSize += fs.statSync(file.src)["size"]; + }); mainEvent.emit("adbpush:start", files.length); - push(files[0].src, files[0].dest); - mainEvent.on("adbpush:end", () => { - if (files) { - files.shift(); - if (files.length <= 0){ - files = null; - mainEvent.emit("adbpush:done"); - return; - } else { - if (files) mainEvent.emit("adbpush:next", totalLength-files.length+1, totalLength) - push(files[0].src, files[0].dest); - } - } else { - return; - } + mainEvent.once("adbpush:done", () => { + mainEvent.emit("adbpush:progress", 1); + }) + mainEvent.on("adbpush:progress:size", (s) => { + downloadedSize += s; + mainEvent.emit("adbpush:progress", downloadedSize/totalSize); }); + // Push it to the limit + function pushNext(i) { + mainEvent.emit("adbpush:next", i+1, files.length) + push(files[i].src, files[i].dest).then(() => { + if (i+1 < files.length) { + pushNext(i+1); + } else { + mainEvent.emit("adbpush:done"); + } + }); + } + pushNext(0); // Begin pushing } var shell = (cmd, callback) => { diff --git a/src/devices.js b/src/devices.js index 02f7767b..253fd669 100644 --- a/src/devices.js +++ b/src/devices.js @@ -226,7 +226,6 @@ var downloadImages = (images, device) => { }).then((files) => { utils.log.debug(files) global.mainEvent.emit("download:done"); - pushLatestVersion(files); }); } @@ -290,15 +289,12 @@ global.mainEvent.on("download:speed", (speed) => { global.mainEvent.emit("user:write:speed", Math.round(speed*100)/100); }); global.mainEvent.on("adbpush:error", (e) => { - global.mainEvent.removeListener("adbpush:end", () => {}); global.mainEvent.emit("error", "Adb push error: " + e) utils.log.error("Devices: Adb push error: "+ e) }); global.mainEvent.on("adbpush:progress", (percent) => { - if (percent != NaN && percent != 100) { - utils.log.debug(`Pushing file ${global.mainEvent.nextCurrent} of ${global.mainEvent.nextTotal}, ${Math.ceil(percent)}% complete`); - global.mainEvent.emit("user:write:progress", Math.ceil(percent/global.mainEvent.nextTotal+global.mainEvent.nextBaseProgress)); - } + utils.log.debug(`Pushing ${Math.ceil(percent*100)}% complete`); + global.mainEvent.emit("user:write:progress", percent*100); }); global.mainEvent.on("adbpush:next", (current, total) => { global.mainEvent.nextCurrent = current; @@ -326,7 +322,6 @@ var install = (options) => { utils.log.debug("install event started with options: " + JSON.stringify(options)) devicesApi.getInstallInstructs(options.device).then((instructs) => { global.mainEvent.once("adbpush:done", () => { - global.mainEvent.removeListener("adbpush:end", () => {}); utils.log.info("Done pushing files"); utils.log.info("Rebooting to recovery to flash"); global.mainEvent.emit("system-image:done"); From a854a0f7160f90c307bbc7f3cab726eb83c78290 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 10:24:53 +0200 Subject: [PATCH 19/47] Remove hack event listeners --- src/devices.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/devices.js b/src/devices.js index 253fd669..9db57123 100644 --- a/src/devices.js +++ b/src/devices.js @@ -264,22 +264,10 @@ global.mainEvent.on("download:start", (total) => { if (total) global.mainEvent.emit("user:write:next", "Downloading", 1, total); else global.mainEvent.emit("user:write:under", "Downloading"); }); -global.mainEvent.on("download:next:hack", (current, total) => { - global.mainEvent.nextCurrent = current; - global.mainEvent.nextBaseProgress = Math.abs(Math.ceil((current-1)/total*100)); - utils.log.info(`Downloading file ${global.mainEvent.nextCurrent}/${global.mainEvent.nextTotal}`); - global.mainEvent.emit("user:write:next", "Downloading", global.mainEvent.nextCurrent, global.mainEvent.nextTotal); - global.mainEvent.emit("user:write:progress", global.mainEvent.nextBaseProgress); -}); global.mainEvent.on("download:next", (current, total) => { utils.log.info(`Downloading file ${current}/${total}`); global.mainEvent.emit("user:write:next", "Downloading", current, total); }); -// TODO remove this one in favor of download:progress -global.mainEvent.on("download:progress:hack", (percent) => { - utils.log.debug(`Downloading file ${global.mainEvent.nextCurrent} of ${global.mainEvent.nextTotal}, ${Math.ceil(percent)}% complete`); - global.mainEvent.emit("user:write:progress", Math.ceil(percent/global.mainEvent.nextTotal+global.mainEvent.nextBaseProgress)); -}); global.mainEvent.on("download:progress", (percent) => { // utils.log.debug(`Downloading files: ${percent*100}% complete`); global.mainEvent.emit("user:write:progress", percent*100); From 0bdec565f264d21aa104c0a22372c47e60dac6e0 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 10:34:51 +0200 Subject: [PATCH 20/47] Remove adbpush:next event, since our overall progress method is far more user-friendly --- src/adb.js | 2 +- src/devices.js | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/adb.js b/src/adb.js index 6734fda6..c7aaae2f 100644 --- a/src/adb.js +++ b/src/adb.js @@ -206,7 +206,7 @@ var pushMany = (files) => { }); // Push it to the limit function pushNext(i) { - mainEvent.emit("adbpush:next", i+1, files.length) + utils.log.debug("Pushing file " + (i+1) + " of " + files.length); push(files[i].src, files[i].dest).then(() => { if (i+1 < files.length) { pushNext(i+1); diff --git a/src/devices.js b/src/devices.js index 9db57123..fd107bc1 100644 --- a/src/devices.js +++ b/src/devices.js @@ -257,9 +257,6 @@ global.mainEvent.on("download:startCheck", () => { utils.log.debug("Download startCheck"); }); global.mainEvent.on("download:start", (total) => { - global.mainEvent.nextTotal = total; - global.mainEvent.nextCurrent = 1; - global.mainEvent.nextBaseProgress = 0; global.mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); if (total) global.mainEvent.emit("user:write:next", "Downloading", 1, total); else global.mainEvent.emit("user:write:under", "Downloading"); @@ -284,13 +281,6 @@ global.mainEvent.on("adbpush:progress", (percent) => { utils.log.debug(`Pushing ${Math.ceil(percent*100)}% complete`); global.mainEvent.emit("user:write:progress", percent*100); }); -global.mainEvent.on("adbpush:next", (current, total) => { - global.mainEvent.nextCurrent = current; - global.mainEvent.nextBaseProgress = Math.abs(Math.ceil((current-1)/total*100)); - utils.log.info(`Pushing file ${global.mainEvent.nextCurrent}/${global.mainEvent.nextTotal}`); - global.mainEvent.emit("user:write:next", "Pushing", global.mainEvent.nextCurrent, global.mainEvent.nextTotal); - global.mainEvent.emit("user:write:progress", global.mainEvent.nextBaseProgress); -}); global.mainEvent.on("adbpush:start", (total) => { global.mainEvent.nextTotal = total; global.mainEvent.nextCurrent = 1; From c786e9553cfe10c8358cd4784d826de824a0b09a Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 10:39:12 +0200 Subject: [PATCH 21/47] Remove download:next event --- src/devices.js | 6 +----- src/system-image.js | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/devices.js b/src/devices.js index fd107bc1..73f79d53 100644 --- a/src/devices.js +++ b/src/devices.js @@ -222,7 +222,7 @@ var downloadImages = (images, device) => { global.mainEvent.emit("download:progress", progress); global.mainEvent.emit("download:speed", speed); }, (current, total) => { - if (current != total) global.mainEvent.emit("download:next", current+1, total); + if (current != total) utils.log.debug("Downloading bootstrap image " + (current+1) + " of " + total); }).then((files) => { utils.log.debug(files) global.mainEvent.emit("download:done"); @@ -261,10 +261,6 @@ global.mainEvent.on("download:start", (total) => { if (total) global.mainEvent.emit("user:write:next", "Downloading", 1, total); else global.mainEvent.emit("user:write:under", "Downloading"); }); -global.mainEvent.on("download:next", (current, total) => { - utils.log.info(`Downloading file ${current}/${total}`); - global.mainEvent.emit("user:write:next", "Downloading", current, total); -}); global.mainEvent.on("download:progress", (percent) => { // utils.log.debug(`Downloading files: ${percent*100}% complete`); global.mainEvent.emit("user:write:progress", percent*100); diff --git a/src/system-image.js b/src/system-image.js index 082acaf5..8d6b7bf7 100644 --- a/src/system-image.js +++ b/src/system-image.js @@ -46,7 +46,7 @@ var installLatestVersion = (options) => { mainEvent.emit("download:progress", progress); mainEvent.emit("download:speed", speed); }, (current, total) => { - if (current != total) mainEvent.emit("download:next", current+1, total); + if (current != total) utils.log.debug("Downloading system-image file " + (current+1) + " of " + total); }).then((files) => { utils.log.debug(files) mainEvent.emit("download:done"); From 2bdb55522dc3a380122a5cb10ee2f4b4b3221e85 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 10:52:22 +0200 Subject: [PATCH 22/47] Remove user:write:next event --- src/devices.js | 3 +-- src/html/scripts/main.pug | 4 ---- src/main.js | 4 ---- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/devices.js b/src/devices.js index 73f79d53..21f6d2a3 100644 --- a/src/devices.js +++ b/src/devices.js @@ -258,8 +258,7 @@ global.mainEvent.on("download:startCheck", () => { }); global.mainEvent.on("download:start", (total) => { global.mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); - if (total) global.mainEvent.emit("user:write:next", "Downloading", 1, total); - else global.mainEvent.emit("user:write:under", "Downloading"); + global.mainEvent.emit("user:write:under", "Downloading"); }); global.mainEvent.on("download:progress", (percent) => { // utils.log.debug(`Downloading files: ${percent*100}% complete`); diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index af9b13dd..fb9ab209 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -119,10 +119,6 @@ script. footer.speedText.set(speed); }); - ipcRenderer.on("user:write:next", (e, text, current, total) => { - footer.underText.set(text + " file " + current + " of " + total); - }); - ipcRenderer.on("user:write:start", (e, text, length) => { footer.underText.set(text+" file 1 of "+length); }); diff --git a/src/main.js b/src/main.js index 0ec68dfd..be0df51a 100755 --- a/src/main.js +++ b/src/main.js @@ -173,10 +173,6 @@ mainEvent.on("reboot:done", () => { mainWindow.webContents.send("reboot:done"); }); -mainEvent.on("user:write:next", (text, current, total) => { - mainWindow.webContents.send("user:write:next", text, current, total); -}); - mainEvent.on("user:write:start", (text, length) => { mainWindow.webContents.send("user:write:start", text, length); }); From 51f3ea0bba75403ba61e869f64e5b24a2e3c1d63 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 11:00:00 +0200 Subject: [PATCH 23/47] Remove unused code --- src/devices.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/devices.js b/src/devices.js index 21f6d2a3..57a42b0e 100644 --- a/src/devices.js +++ b/src/devices.js @@ -261,11 +261,9 @@ global.mainEvent.on("download:start", (total) => { global.mainEvent.emit("user:write:under", "Downloading"); }); global.mainEvent.on("download:progress", (percent) => { - // utils.log.debug(`Downloading files: ${percent*100}% complete`); global.mainEvent.emit("user:write:progress", percent*100); }); global.mainEvent.on("download:speed", (speed) => { - // utils.log.debug(`Downloading at ${speed}% MB/s`); global.mainEvent.emit("user:write:speed", Math.round(speed*100)/100); }); global.mainEvent.on("adbpush:error", (e) => { @@ -277,19 +275,12 @@ global.mainEvent.on("adbpush:progress", (percent) => { global.mainEvent.emit("user:write:progress", percent*100); }); global.mainEvent.on("adbpush:start", (total) => { - global.mainEvent.nextTotal = total; - global.mainEvent.nextCurrent = 1; - global.mainEvent.nextBaseProgress = 0; utils.log.info("Start pushing " + total + " files"); global.mainEvent.emit("user:write:status", "Pushing files to device"); global.mainEvent.emit("user:write:start", "Pushing", total); }); var install = (options) => { - // helper vars for progress events - var nextCurrent; - var nextTotal; - var nextBaseProgress; if (!options) return false; utils.log.debug("install event started with options: " + JSON.stringify(options)) From 3a67bfda73a731f0b85046141f033aa5d9742076 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 12:13:35 +0200 Subject: [PATCH 24/47] Move error handling to function --- src/adb.js | 66 ++++++++++++++++++++++++++++---------------------- src/devices.js | 31 ++++++++---------------- src/utils.js | 7 ++++++ 3 files changed, 54 insertions(+), 50 deletions(-) diff --git a/src/adb.js b/src/adb.js index c7aaae2f..7b852760 100644 --- a/src/adb.js +++ b/src/adb.js @@ -168,7 +168,7 @@ var push = (file, dest) => { } else if (!err.killed && (err.code == 1)) { hasAdbAccess ((hasAccess) => { if (hasAccess) { - mainEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); + utils.errorToUser(err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort, "ADB push"); } else { utils.log.warn("connection to device lost"); // TODO: Only restart the event rather than the entire installation @@ -176,7 +176,7 @@ var push = (file, dest) => { } }); } else { - mainEvent.emit("adbpush:error", err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort); + utils.errorToUser(err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort, "ADB push"); } } clearInterval(progressInterval); @@ -186,36 +186,44 @@ var push = (file, dest) => { } var pushMany = (files) => { - if (files.length <= 0){ - mainEvent.emit("adbpush:error", "No files provided"); - return false; - } - var totalSize = 0; - var downloadedSize = 0; - // Get total size for progress bar - files.forEach((file) => { - totalSize += fs.statSync(file.src)["size"]; - }); - mainEvent.emit("adbpush:start", files.length); - mainEvent.once("adbpush:done", () => { - mainEvent.emit("adbpush:progress", 1); - }) - mainEvent.on("adbpush:progress:size", (s) => { - downloadedSize += s; - mainEvent.emit("adbpush:progress", downloadedSize/totalSize); - }); - // Push it to the limit - function pushNext(i) { - utils.log.debug("Pushing file " + (i+1) + " of " + files.length); - push(files[i].src, files[i].dest).then(() => { - if (i+1 < files.length) { - pushNext(i+1); - } else { - mainEvent.emit("adbpush:done"); + try { + if (files.length <= 0){ + utils.errorToUser("No files provided", "ADB push"); + return false; + } + var totalSize = 0; + var downloadedSize = 0; + // Get total size for progress bar + files.forEach((file) => { + try { + totalSize += fs.statSync(file.src)["size"]; + } catch (e) { + throw "Can't read system-image files: " + e } }); + mainEvent.emit("adbpush:start", files.length); + mainEvent.once("adbpush:done", () => { + mainEvent.emit("adbpush:progress", 1); + }) + mainEvent.on("adbpush:progress:size", (s) => { + downloadedSize += s; + mainEvent.emit("adbpush:progress", downloadedSize/totalSize); + }); + // Push it to the limit + function pushNext(i) { + utils.log.debug("Pushing file " + (i+1) + " of " + files.length); + push(files[i].src, files[i].dest).then(() => { + if (i+1 < files.length) { + pushNext(i+1); + } else { + mainEvent.emit("adbpush:done"); + } + }); + } + pushNext(0); // Begin pushing + } catch (e) { + utils.errorToUser(e, "ADB PushMany") } - pushNext(0); // Begin pushing } var shell = (cmd, callback) => { diff --git a/src/devices.js b/src/devices.js index 57a42b0e..6673d07d 100644 --- a/src/devices.js +++ b/src/devices.js @@ -83,7 +83,7 @@ var instructReboot = (state, button, callback) => { requestPassword((pass) => { fastboot.waitForDevice(pass, (err, errM) => { if (err) { - global.mainEvent.emit("Error", errM); + utils.errorToUser(errM, "fastboot.waitForDevice"); return; } else { rebooted = true; @@ -127,7 +127,7 @@ var requestPassword = (callback) => { global.mainEvent.emit("user:password:wrong"); requestPassword(callback); } else { - global.mainEvent.emit("error", err.message) + utils.errorToUser(err.message, "Password"); } }); }); @@ -137,7 +137,7 @@ var instructOemUnlock = (callback) => { requestPassword((p) => { fastboot.oemUnlock(password, (err, errM) => { if (err) { - global.mainEvent.emit("error", errM); + utils.errorToUser(errM, "OEM unlock"); callback(true); } else { callback(false); @@ -160,7 +160,7 @@ var handleBootstrapError = (err, errM, backToFunction) => { } else if (err.lowPower) { global.mainEvent.emit("user:low-power"); } else { - global.mainEvent.emit("error", errM); + utils.errorToUser(errM, "Bootstrap"); } } @@ -184,7 +184,7 @@ var instructBootstrap = (bootstrap, images) => { }); // If we can't find it, report error! if (!recoveryImg) { - global.mainEvent.emit("error", "Cant find recoveryImg to boot: "+images); + utils.errorToUser("Cant find recoveryImg to boot: "+images, "fastboot.boot"); } else { fastboot.boot(recoveryImg, p, (err, errM) => { if (err) { @@ -242,13 +242,6 @@ global.mainEvent.on("download:done", () => { utils.log.info("Download complete"); global.mainEvent.emit("user:write:progress", 0); }); -global.mainEvent.on("download:error", (r) => { - utils.log.error("Devices: Download error "+r); -}); -global.mainEvent.on("error", (r) => { - global.mainEvent.emit("user:error", r); - utils.log.error("Devices: Error: "+r); -}); global.mainEvent.on("download:checking", () => { utils.log.info("Download checking file"); }); @@ -266,10 +259,6 @@ global.mainEvent.on("download:progress", (percent) => { global.mainEvent.on("download:speed", (speed) => { global.mainEvent.emit("user:write:speed", Math.round(speed*100)/100); }); -global.mainEvent.on("adbpush:error", (e) => { - global.mainEvent.emit("error", "Adb push error: " + e) - utils.log.error("Devices: Adb push error: "+ e) -}); global.mainEvent.on("adbpush:progress", (percent) => { utils.log.debug(`Pushing ${Math.ceil(percent*100)}% complete`); global.mainEvent.emit("user:write:progress", percent*100); @@ -335,7 +324,7 @@ var install = (options) => { global.mainEvent.emit("system-image:start"); }); } - }).catch(utils.log.error); + }).catch((e) => { utils.errorToUser(e, "Install"); }); } var getChannelSelects = (device, callback) => { @@ -365,8 +354,8 @@ var getChannelSelects = (device, callback) => { callback(false); return; } - }).catch(utils.log.error); - }).catch(utils.log.error); + }).catch(((e) => { utils.errorToUser(e, "Devices API"); })); + }).catch((e) => { utils.errorToUser(e, "SystemImage API"); }); } module.exports = { @@ -408,7 +397,7 @@ module.exports = { // ipcRenderer.send("setInstallProperties", { device: device }); return; } - }).catch(utils.log.error); + }).catch(((e) => { utils.errorToUser(e, "Device Select"); })); }); }, getNotWorking: getNotWorking, @@ -433,7 +422,7 @@ module.exports = { } else { callback(false); } - }).catch(utils.log.error); + }).catch(((e) => { utils.errorToUser(e, "getDeviceSelects"); })); }, instructOemUnlock: instructOemUnlock } diff --git a/src/utils.js b/src/utils.js index aa4dc98b..dceb25a1 100644 --- a/src/utils.js +++ b/src/utils.js @@ -475,7 +475,14 @@ const hidePassword = (output, pw) => { } } +function errorToUser(error, errorLocation) { + var errorString = "Error: " + (errorLocation ? errorLocation : "Unknown") + ": " + error; + utils.log.error(errorString); + global.mainEvent.emit("user:error", errorString); +} + module.exports = { + errorToUser: errorToUser, setCustomPlatformTool: setCustomPlatformTool, downloadFiles: downloadFiles, log: log, From 13eb365f1de0bda4d0249db80794c3913c0e7580 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 12:42:01 +0200 Subject: [PATCH 25/47] Fix bug that caused device-selects-list to be empty after restarting --- src/html/scripts/main.pug | 2 +- src/main.js | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index fb9ab209..90b6821c 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -194,7 +194,7 @@ script. // START views.show("working", "particles"); - ipcRenderer.on("device:wait:data-ready", (event, deviceSelects) => { + ipcRenderer.on("device:wait:device-selects-ready", (event, deviceSelects) => { $("#device-select").append(deviceSelects); }); diff --git a/src/main.js b/src/main.js index be0df51a..3c277bc7 100755 --- a/src/main.js +++ b/src/main.js @@ -213,10 +213,6 @@ mainEvent.on("device:select:data-ready", (output, device, channels, ubuntuCom, a mainWindow.webContents.send("device:select:data-ready", output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid); }); -mainEvent.once("device:wait:data-ready", (deviceSelects) => { - mainWindow.webContents.send("device:wait:data-ready", deviceSelects); -}); - mainEvent.on("user:no-network", () => { mainWindow.webContents.send("user:no-network"); }); @@ -237,16 +233,21 @@ function createWindow () { title: "UBports Installer ("+global.packageInfo.version+")" }); + // Tasks we need for every start mainWindow.webContents.on("did-finish-load", () => { adb.start(false, false, (err) => { mainEvent.emit("user:adb:ready"); devices.waitForDevice(); }); devices.getDeviceSelects((out) => { - mainEvent.emit("device:wait:data-ready", out) + mainWindow.webContents.send("device:wait:device-selects-ready", out) }); + }); + + // Task we need only on the first start + mainWindow.webContents.once("did-finish-load", () => { utils.getUpdateAvailable().then(() => { - utils.log.info("This is not the latest version! Please update: https://devices.ubuntu-touch.io/installer/" + global.packageInfo.package); + utils.log.info("This is not the latest version of the UBports Installer! Please update: https://devices.ubuntu-touch.io/installer/" + global.packageInfo.package); mainWindow.webContents.send("user:update-available"); }).catch(() => { utils.log.debug("This is the latest version.") From e6f0555b45746b8516877154302fce717afdcd39 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 13:15:29 +0200 Subject: [PATCH 26/47] Remove download:start and adbpush:start events --- src/adb.js | 2 +- src/devices.js | 15 ++++----------- src/html/scripts/main.pug | 12 ++---------- src/main.js | 16 ++++------------ src/system-image.js | 4 +++- 5 files changed, 14 insertions(+), 35 deletions(-) diff --git a/src/adb.js b/src/adb.js index 7b852760..2f89ff00 100644 --- a/src/adb.js +++ b/src/adb.js @@ -201,7 +201,7 @@ var pushMany = (files) => { throw "Can't read system-image files: " + e } }); - mainEvent.emit("adbpush:start", files.length); + mainEvent.emit("user:write:working", "push"); mainEvent.once("adbpush:done", () => { mainEvent.emit("adbpush:progress", 1); }) diff --git a/src/devices.js b/src/devices.js index 6673d07d..e90806dd 100644 --- a/src/devices.js +++ b/src/devices.js @@ -214,9 +214,11 @@ var instructBootstrap = (bootstrap, images) => { } var downloadImages = (images, device) => { - utils.log.debug(addPathToImages(images, device)) + utils.log.debug(addPathToImages(images, device)); global.mainEvent.once("download:progress", () => { - global.mainEvent.emit("download:start"); + global.mainEvent.emit("user:write:working", "download"); + global.mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); + global.mainEvent.emit("user:write:under", "Downloading"); }) utils.downloadFiles(images, (progress, speed) => { global.mainEvent.emit("download:progress", progress); @@ -249,10 +251,6 @@ global.mainEvent.on("download:startCheck", () => { global.mainEvent.emit("user:write:status", "Checking Ubuntu Touch files"); utils.log.debug("Download startCheck"); }); -global.mainEvent.on("download:start", (total) => { - global.mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); - global.mainEvent.emit("user:write:under", "Downloading"); -}); global.mainEvent.on("download:progress", (percent) => { global.mainEvent.emit("user:write:progress", percent*100); }); @@ -263,11 +261,6 @@ global.mainEvent.on("adbpush:progress", (percent) => { utils.log.debug(`Pushing ${Math.ceil(percent*100)}% complete`); global.mainEvent.emit("user:write:progress", percent*100); }); -global.mainEvent.on("adbpush:start", (total) => { - utils.log.info("Start pushing " + total + " files"); - global.mainEvent.emit("user:write:status", "Pushing files to device"); - global.mainEvent.emit("user:write:start", "Pushing", total); -}); var install = (options) => { if (!options) diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index 90b6821c..83d121de 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -52,12 +52,8 @@ script. footer.underText.set("Preparing system image"); }); - ipcRenderer.on("download:start", () => { - views.show("working", "download"); - }); - - ipcRenderer.on("adbpush:start", () => { - views.show("working", "push"); + ipcRenderer.on("user:write:working", (e, animation) => { + views.show("working", animation); }); ipcRenderer.on("adbpush:done", () => { @@ -119,10 +115,6 @@ script. footer.speedText.set(speed); }); - ipcRenderer.on("user:write:start", (e, text, length) => { - footer.underText.set(text+" file 1 of "+length); - }); - ipcRenderer.on("user:write:progress", (e, length) => { if(length >= 100) { length=100; diff --git a/src/main.js b/src/main.js index 3c277bc7..39672cbb 100755 --- a/src/main.js +++ b/src/main.js @@ -121,18 +121,10 @@ mainEvent.on("system-image:start", () => { mainWindow.webContents.send("system-image:start"); }); -mainEvent.on("download:start", () => { - mainWindow.webContents.send("download:start"); -}); - mainEvent.on("adbpush:done", () => { mainWindow.webContents.send("adbpush:done"); }); -mainEvent.on("adbpush:start", () => { - mainWindow.webContents.send("adbpush:start"); -}); - mainEvent.on("user:connection-lost", (callback) => { mainWindow.webContents.send("user:connection-lost", callback); }); @@ -173,10 +165,6 @@ mainEvent.on("reboot:done", () => { mainWindow.webContents.send("reboot:done"); }); -mainEvent.on("user:write:start", (text, length) => { - mainWindow.webContents.send("user:write:start", text, length); -}); - mainEvent.on("user:write:progress", (length) => { mainWindow.webContents.send("user:write:progress", length); }); @@ -187,6 +175,10 @@ mainEvent.on("user:write:done", () => { utils.log.info("All done! Your device will now reboot and complete the installation. Enjoy exploring Ubuntu Touch!"); }); +mainEvent.on("user:write:working", (animation) => { + mainWindow.webContents.send("user:write:working", animation); +}); + mainEvent.on("user:write:status", (status) => { mainWindow.webContents.send("user:write:status", status); }); diff --git a/src/system-image.js b/src/system-image.js index 8d6b7bf7..af066615 100644 --- a/src/system-image.js +++ b/src/system-image.js @@ -40,7 +40,9 @@ var pushLatestVersion = (files, dontWipeCache) => { var installLatestVersion = (options) => { mainEvent.once("download:progress", () => { - mainEvent.emit("download:start"); + mainEvent.emit("user:write:working", "download"); + mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); + mainEvent.emit("user:write:under", "Downloading"); }) systemImage.downloadLatestVersion(options, (progress, speed) => { mainEvent.emit("download:progress", progress); From 970032369d88c2887017652202eb78c5be9e6b80 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 13:28:12 +0200 Subject: [PATCH 27/47] Remove unused download:startCheck event --- src/devices.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/devices.js b/src/devices.js index e90806dd..c103fc78 100644 --- a/src/devices.js +++ b/src/devices.js @@ -247,10 +247,6 @@ global.mainEvent.on("download:done", () => { global.mainEvent.on("download:checking", () => { utils.log.info("Download checking file"); }); -global.mainEvent.on("download:startCheck", () => { - global.mainEvent.emit("user:write:status", "Checking Ubuntu Touch files"); - utils.log.debug("Download startCheck"); -}); global.mainEvent.on("download:progress", (percent) => { global.mainEvent.emit("user:write:progress", percent*100); }); From be97bf74623d2be7c6191e5c8d46c84016bd0119 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 13:28:57 +0200 Subject: [PATCH 28/47] Remove system-image:start event --- src/devices.js | 25 +++++++++++++++---------- src/html/scripts/main.pug | 5 ----- src/main.js | 4 ---- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/devices.js b/src/devices.js index c103fc78..cd2ed77c 100644 --- a/src/devices.js +++ b/src/devices.js @@ -271,13 +271,6 @@ var install = (options) => { global.mainEvent.emit("user:write:status", "All files pushed successfully!"); global.mainEvent.emit("user:write:progress", 0); }); - global.mainEvent.once("system-image:start", () => { - systemImage.installLatestVersion({ - device: options.device, - channel: options.channel, - wipe: options.wipe - }); - }); global.mainEvent.once("system-image:done", () => { instructReboot("recovery", instructs.buttons, () => { global.mainEvent.emit("user:write:done"); @@ -287,13 +280,21 @@ var install = (options) => { utils.log.info("bootstrap done: " + (bootstrap ? "rebooting automatically" : "rebooting manually")); if (!bootstrap){ instructReboot("recovery", instructs.buttons, () => { - global.mainEvent.emit("system-image:start"); + systemImage.installLatestVersion({ + device: options.device, + channel: options.channel, + wipe: options.wipe + }); }); } else { global.mainEvent.emit("user:write:status", "Waiting for device to enter recovery mode", true); global.mainEvent.emit("user:write:under", "Rebooting..."); adb.waitForDevice(() => { - global.mainEvent.emit("system-image:start"); + systemImage.installLatestVersion({ + device: options.device, + channel: options.channel, + wipe: options.wipe + }); }); } }); @@ -310,7 +311,11 @@ var install = (options) => { } else { // If no images are specified, go straight to system-image // We need to be in recovery instructReboot("recovery", instructs.buttons, () => { - global.mainEvent.emit("system-image:start"); + systemImage.installLatestVersion({ + device: options.device, + channel: options.channel, + wipe: options.wipe + }); }); } }).catch((e) => { utils.errorToUser(e, "Install"); }); diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index 83d121de..b51c587b 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -47,11 +47,6 @@ script. footer.underText.set("Flashing recovery and boot images") }); - ipcRenderer.on("system-image:start", () => { - views.show("working", "particles"); - footer.underText.set("Preparing system image"); - }); - ipcRenderer.on("user:write:working", (e, animation) => { views.show("working", animation); }); diff --git a/src/main.js b/src/main.js index 39672cbb..37f45767 100755 --- a/src/main.js +++ b/src/main.js @@ -117,10 +117,6 @@ mainEvent.on("bootstrap:flashing", () => { mainWindow.webContents.send("bootstrap:flashing"); }); -mainEvent.on("system-image:start", () => { - mainWindow.webContents.send("system-image:start"); -}); - mainEvent.on("adbpush:done", () => { mainWindow.webContents.send("adbpush:done"); }); From 85847e6ed1583e75d3f09e378cbd2a3280672340 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 13:29:27 +0200 Subject: [PATCH 29/47] Make sure dots are shown on startup --- src/html/index.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/html/index.pug b/src/html/index.pug index 52859ecf..21b195f2 100644 --- a/src/html/index.pug +++ b/src/html/index.pug @@ -27,7 +27,7 @@ html .container h3(style="margin-top: 0").text-muted.footer-top span#footer-top UBports Installer is starting up - span#wait-dot(hidden='false') + span#wait-dot p span#footer-bottom.text-muted Starting adb service span#footer-speed.text-muted From 027c1e831fdc3e08e4245162585b25fe03e6ee0d Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 15:24:17 +0200 Subject: [PATCH 30/47] Improve user guidance --- src/adb.js | 7 +++--- src/devices.js | 45 ++++++++++++++------------------- src/html/scripts/main.pug | 13 +--------- src/main.js | 53 ++++++++++++++++++--------------------- src/system-image.js | 18 +++++++------ 5 files changed, 59 insertions(+), 77 deletions(-) diff --git a/src/adb.js b/src/adb.js index 2f89ff00..c5145fb2 100644 --- a/src/adb.js +++ b/src/adb.js @@ -186,6 +186,9 @@ var push = (file, dest) => { } var pushMany = (files) => { + mainEvent.emit("user:write:working", "push"); + mainEvent.emit("user:write:status", "Pushing files"); + mainEvent.emit("user:write:under", "Almost finished! Are you excited yet?"); try { if (files.length <= 0){ utils.errorToUser("No files provided", "ADB push"); @@ -201,10 +204,6 @@ var pushMany = (files) => { throw "Can't read system-image files: " + e } }); - mainEvent.emit("user:write:working", "push"); - mainEvent.once("adbpush:done", () => { - mainEvent.emit("adbpush:progress", 1); - }) mainEvent.on("adbpush:progress:size", (s) => { downloadedSize += s; mainEvent.emit("adbpush:progress", downloadedSize/totalSize); diff --git a/src/devices.js b/src/devices.js index cd2ed77c..70ba1a6b 100644 --- a/src/devices.js +++ b/src/devices.js @@ -56,6 +56,9 @@ var formatNotWorking = (nw) => { } var instructReboot = (state, button, callback) => { + global.mainEvent.emit("user:write:working", "particles"); + global.mainEvent.emit("user:write:status", "Rebooting to " + state); + global.mainEvent.emit("user:write:under", "Waiting for device to enter " + state + " mode"); var rebooted = false; var manualReboot = () => { utils.log.info("Instructing manual reboot"); @@ -99,7 +102,6 @@ var instructReboot = (state, button, callback) => { rebooted = true; // We expect the device state to mach installState now global.mainEvent.emit("reboot:done"); - global.mainEvent.emit("state:" + state); callback(); return; }); @@ -202,8 +204,10 @@ var instructBootstrap = (bootstrap, images) => { } }, p); } - global.mainEvent.emit("bootstrap:flashing") - global.mainEvent.emit("user:write:status", "Flashing images") + global.mainEvent.emit("user:write:working", "particles"); + global.mainEvent.emit("user:write:status", "Flashing images"); + global.mainEvent.emit("user:write:under", "Flashing recovery and boot images"); + global.mainEvent.emit("user:write:progress", 0); if (!utils.needRoot()) { flash(false); } else { @@ -215,11 +219,9 @@ var instructBootstrap = (bootstrap, images) => { var downloadImages = (images, device) => { utils.log.debug(addPathToImages(images, device)); - global.mainEvent.once("download:progress", () => { - global.mainEvent.emit("user:write:working", "download"); - global.mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); - global.mainEvent.emit("user:write:under", "Downloading"); - }) + global.mainEvent.emit("user:write:working", "download"); + global.mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); + global.mainEvent.emit("user:write:under", "Downloading"); utils.downloadFiles(images, (progress, speed) => { global.mainEvent.emit("download:progress", progress); global.mainEvent.emit("download:speed", speed); @@ -227,7 +229,10 @@ var downloadImages = (images, device) => { if (current != total) utils.log.debug("Downloading bootstrap image " + (current+1) + " of " + total); }).then((files) => { utils.log.debug(files) - global.mainEvent.emit("download:done"); + // Wait for one second until the progress event stops firing + setTimeout(() => { + global.mainEvent.emit("download:done"); + }, 1000); }); } @@ -240,13 +245,6 @@ var addPathToImages = (images, device) => { return ret; } -global.mainEvent.on("download:done", () => { - utils.log.info("Download complete"); - global.mainEvent.emit("user:write:progress", 0); -}); -global.mainEvent.on("download:checking", () => { - utils.log.info("Download checking file"); -}); global.mainEvent.on("download:progress", (percent) => { global.mainEvent.emit("user:write:progress", percent*100); }); @@ -254,7 +252,6 @@ global.mainEvent.on("download:speed", (speed) => { global.mainEvent.emit("user:write:speed", Math.round(speed*100)/100); }); global.mainEvent.on("adbpush:progress", (percent) => { - utils.log.debug(`Pushing ${Math.ceil(percent*100)}% complete`); global.mainEvent.emit("user:write:progress", percent*100); }); @@ -266,12 +263,8 @@ var install = (options) => { global.mainEvent.once("adbpush:done", () => { utils.log.info("Done pushing files"); utils.log.info("Rebooting to recovery to flash"); - global.mainEvent.emit("system-image:done"); - global.mainEvent.emit("user:write:status", "Rebooting to recovery to start the flashing process"); - global.mainEvent.emit("user:write:status", "All files pushed successfully!"); global.mainEvent.emit("user:write:progress", 0); - }); - global.mainEvent.once("system-image:done", () => { + global.mainEvent.emit("user:write:working", "particles"); instructReboot("recovery", instructs.buttons, () => { global.mainEvent.emit("user:write:done"); }); @@ -287,8 +280,8 @@ var install = (options) => { }); }); } else { - global.mainEvent.emit("user:write:status", "Waiting for device to enter recovery mode", true); - global.mainEvent.emit("user:write:under", "Rebooting..."); + global.mainEvent.emit("user:write:status", "Rebooting to recovery"); + global.mainEvent.emit("user:write:under", "Waiting for device to enter recovery mode"); adb.waitForDevice(() => { systemImage.installLatestVersion({ device: options.device, @@ -300,12 +293,12 @@ var install = (options) => { }); if (instructs.images.length > 0) { // If images are specified, flash them (bootstrapping) // We need to be in bootloader - global.mainEvent.emit("user:write:under", "Please connect your device with a USB cable"); + global.mainEvent.emit("user:write:status", "Waiting for device to enter bootloader mode"); + global.mainEvent.emit("user:write:under", "Fastboot is scanning for devices"); instructReboot("bootloader", instructs.buttons, () => { global.mainEvent.once("download:done", () => { instructBootstrap(instructs.installSettings.bootstrap, addPathToImages(instructs.images, options.device)); }); - global.mainEvent.emit("user:write:status", "Downloading images"); downloadImages(instructs.images, options.device); }); } else { // If no images are specified, go straight to system-image diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index b51c587b..3192c4aa 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -42,19 +42,10 @@ script. ipcRenderer.on("user:error", (event, err) => { onErr(err); }); - ipcRenderer.on("bootstrap:flashing", () => { - views.show("working", "particles"); - footer.underText.set("Flashing recovery and boot images") - }); - ipcRenderer.on("user:write:working", (e, animation) => { views.show("working", animation); }); - ipcRenderer.on("adbpush:done", () => { - views.show("working", "particles"); - }); - ipcRenderer.on("user:connection-lost", (e, callback) => { modals.show("connection-lost"); $("#btn-reconnect").click(callback); @@ -87,8 +78,6 @@ script. views.show("reboot-" + i.button); $("[id=reboot-to-state]").text(i.state); $("#complex-reboot-instruction").text(i.instruction); - footer.topText.set("Please reboot to "+i.state); - footer.underText.set(i.instruction.split(".")[0]); }); ipcRenderer.on("adb:rebooted", () => { @@ -122,7 +111,7 @@ script. remote.getCurrentWindow().close(); } else { views.show("done"); - footer.topText.set("Done"); + footer.topText.set("Installation complete!"); footer.underText.set("It is now safe to unplug the device."); $("#progress").width("0%"); } diff --git a/src/main.js b/src/main.js index 37f45767..dcb037de 100755 --- a/src/main.js +++ b/src/main.js @@ -94,7 +94,7 @@ ipcMain.on("createBugReport", (event, title) => { ipcMain.on("device:select", (event, device) => { global.installProperties.device = device; - mainEvent.emit("device:select", device); + if (mainWindow) mainEvent.emit("device:select", device); }); //============================================================================== @@ -102,31 +102,28 @@ ipcMain.on("device:select", (event, device) => { //============================================================================== mainEvent.on("user:password", () => { - mainWindow.webContents.send("user:password"); + if (mainWindow) mainWindow.webContents.send("user:password"); }); mainEvent.on("user:password:wrong", () => { - mainWindow.webContents.send("user:password:wrong"); + if (mainWindow) mainWindow.webContents.send("user:password:wrong"); }); mainEvent.on("user:error", (err) => { - mainWindow.webContents.send("user:error", err); -}); - -mainEvent.on("bootstrap:flashing", () => { - mainWindow.webContents.send("bootstrap:flashing"); -}); - -mainEvent.on("adbpush:done", () => { - mainWindow.webContents.send("adbpush:done"); + try { + mainWindow.webContents.send("user:error", err); + } catch (e) { + utils.log.error(e); + process.exit(1); + } }); mainEvent.on("user:connection-lost", (callback) => { - mainWindow.webContents.send("user:connection-lost", callback); + if (mainWindow) mainWindow.webContents.send("user:connection-lost", callback); }); mainEvent.on("user:low-power", () => { - mainWindow.webContents.send("user:low-power"); + if (mainWindow) mainWindow.webContents.send("user:low-power"); }); mainEvent.on("restart", () => { @@ -150,59 +147,59 @@ mainEvent.on("user:oem-lock", (callback) => { }); mainEvent.on("user:reboot", (i) => { - mainWindow.webContents.send("user:reboot", i); + if (mainWindow) mainWindow.webContents.send("user:reboot", i); }); mainEvent.on("adb:rebooted", () => { - mainWindow.webContents.send("adb:rebooted"); + if (mainWindow) mainWindow.webContents.send("adb:rebooted"); }); mainEvent.on("reboot:done", () => { - mainWindow.webContents.send("reboot:done"); + if (mainWindow) mainWindow.webContents.send("reboot:done"); }); mainEvent.on("user:write:progress", (length) => { - mainWindow.webContents.send("user:write:progress", length); + if (mainWindow) mainWindow.webContents.send("user:write:progress", length); }); mainEvent.on("user:write:done", () => { - mainWindow.webContents.send("user:write:done"); - mainWindow.webContents.send("user:write:speed"); + if (mainWindow) mainWindow.webContents.send("user:write:done"); + if (mainWindow) mainWindow.webContents.send("user:write:speed"); utils.log.info("All done! Your device will now reboot and complete the installation. Enjoy exploring Ubuntu Touch!"); }); mainEvent.on("user:write:working", (animation) => { - mainWindow.webContents.send("user:write:working", animation); + if (mainWindow) mainWindow.webContents.send("user:write:working", animation); }); mainEvent.on("user:write:status", (status) => { - mainWindow.webContents.send("user:write:status", status); + if (mainWindow) mainWindow.webContents.send("user:write:status", status); }); mainEvent.on("user:write:speed", (speed) => { - mainWindow.webContents.send("user:write:speed", speed); + if (mainWindow) mainWindow.webContents.send("user:write:speed", speed); }); mainEvent.on("user:write:under", (status) => { - mainWindow.webContents.send("user:write:under", status); + if (mainWindow) mainWindow.webContents.send("user:write:under", status); }); mainEvent.on("user:adb:ready", () => { - mainWindow.webContents.send("user:adb:ready"); + if (mainWindow) mainWindow.webContents.send("user:adb:ready"); }); mainEvent.on("user:device-unsupported", (device) => { utils.log.warn("The device " + device + " is not supported!"); - mainWindow.webContents.send("user:device-unsupported", device); + if (mainWindow) mainWindow.webContents.send("user:device-unsupported", device); }); mainEvent.on("device:select:data-ready", (output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { global.installProperties.device = device; - mainWindow.webContents.send("device:select:data-ready", output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid); + if (mainWindow) mainWindow.webContents.send("device:select:data-ready", output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid); }); mainEvent.on("user:no-network", () => { - mainWindow.webContents.send("user:no-network"); + if (mainWindow) mainWindow.webContents.send("user:no-network"); }); //============================================================================== diff --git a/src/system-image.js b/src/system-image.js index af066615..6949bb62 100644 --- a/src/system-image.js +++ b/src/system-image.js @@ -39,11 +39,9 @@ var pushLatestVersion = (files, dontWipeCache) => { } var installLatestVersion = (options) => { - mainEvent.once("download:progress", () => { - mainEvent.emit("user:write:working", "download"); - mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); - mainEvent.emit("user:write:under", "Downloading"); - }) + mainEvent.emit("user:write:working", "download"); + mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); + mainEvent.emit("user:write:under", "Downloading"); systemImage.downloadLatestVersion(options, (progress, speed) => { mainEvent.emit("download:progress", progress); mainEvent.emit("download:speed", speed); @@ -51,8 +49,14 @@ var installLatestVersion = (options) => { if (current != total) utils.log.debug("Downloading system-image file " + (current+1) + " of " + total); }).then((files) => { utils.log.debug(files) - mainEvent.emit("download:done"); - pushLatestVersion(files); + mainEvent.emit("user:write:working", "particles"); + mainEvent.emit("user:write:status", "Download Complete"); + mainEvent.emit("user:write:under", "Checking downloaded files"); + // Wait for one second until the progress event stops firing + setTimeout(() => { + mainEvent.emit("download:done"); + pushLatestVersion(files); + }, 1000); }); } From e76f9cbdc18fe106e4a7a3eeccb810a9081d7d06 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 28 Sep 2019 16:14:22 +0200 Subject: [PATCH 31/47] Add comments to main.js and clean up --- src/devices.js | 2 +- src/html/scripts/main.pug | 7 ------ src/main.js | 47 ++++++++++++++++++++++++--------------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/devices.js b/src/devices.js index 70ba1a6b..c2c60acf 100644 --- a/src/devices.js +++ b/src/devices.js @@ -76,7 +76,7 @@ var instructReboot = (state, button, callback) => { utils.log.warn("Adb failed to reboot!, " + out + " : " + eout); manualReboot(); } else { - global.mainEvent.emit("adb:rebooted"); + global.mainEvent.emit("reboot:done"); } }); } else { diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index 3192c4aa..abcaa5b0 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -80,13 +80,7 @@ script. $("#complex-reboot-instruction").text(i.instruction); }); - ipcRenderer.on("adb:rebooted", () => { - $('#views-reboot-up').hide(); - $('#views-reboot-down').hide(); - }); - ipcRenderer.on("reboot:done", () => { - views.show("working", "particles"); $('#views-reboot-up').hide(); $('#views-reboot-down').hide(); }); @@ -167,7 +161,6 @@ script. }); }); - // START views.show("working", "particles"); ipcRenderer.on("device:wait:device-selects-ready", (event, deviceSelects) => { diff --git a/src/main.js b/src/main.js index dcb037de..54addb82 100755 --- a/src/main.js +++ b/src/main.js @@ -65,50 +65,60 @@ global.packageInfo.isSnap = utils.isSnap(); // RENDERER SIGNAL HANDLING //============================================================================== +// Device selected ipcMain.on("user:device:select", (event, installProperties) => { global.installProperties = Object.assign(global.installProperties, installProperties); devices.install(installProperties); }); +// Password submitted by user ipcMain.on("password", (e, password) => { mainEvent.emit("password", password); }); +// Exit process with optional non-zero exit code ipcMain.on("die", (exitCode) => { process.exit(exitCode); }); +// Restart the installer ipcMain.on("restart", () => { mainEvent.emit("restart"); }); +// The user ignored an error ipcMain.on("error_ignored", () => { utils.log.debug("ERROR IGNORED"); }); +// Submit a bug-report ipcMain.on("createBugReport", (event, title) => { utils.createBugReport(title, global.installProperties, (body) => { electron.shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title="+title+"&body="+body); }); }); +// The user selected a device ipcMain.on("device:select", (event, device) => { global.installProperties.device = device; - if (mainWindow) mainEvent.emit("device:select", device); + mainEvent.emit("device:select", device); }); //============================================================================== // RENDERER COMMUNICATION //============================================================================== +// Prompt the user for the password mainEvent.on("user:password", () => { if (mainWindow) mainWindow.webContents.send("user:password"); }); +// The user entered a wrong password, prompt again mainEvent.on("user:password:wrong", () => { if (mainWindow) mainWindow.webContents.send("user:password:wrong"); }); +// Open the bugreporting tool mainEvent.on("user:error", (err) => { try { mainWindow.webContents.send("user:error", err); @@ -118,14 +128,17 @@ mainEvent.on("user:error", (err) => { } }); +// Connection to the device was lost mainEvent.on("user:connection-lost", (callback) => { if (mainWindow) mainWindow.webContents.send("user:connection-lost", callback); }); +// The device battery is too low to install mainEvent.on("user:low-power", () => { if (mainWindow) mainWindow.webContents.send("user:low-power"); }); +// Restart the installer mainEvent.on("restart", () => { global.installProperties.device = undefined; global.installProperties.channel = undefined; @@ -133,6 +146,7 @@ mainEvent.on("restart", () => { mainWindow.reload(); }); +// The device's bootloader is locked, prompt the user to unlock it mainEvent.on("user:oem-lock", (callback) => { mainWindow.webContents.send("user:oem-lock"); ipcMain.once("user:oem-lock:ok", () => { @@ -146,58 +160,61 @@ mainEvent.on("user:oem-lock", (callback) => { }); }); +// Prompt the user to reboot mainEvent.on("user:reboot", (i) => { if (mainWindow) mainWindow.webContents.send("user:reboot", i); }); -mainEvent.on("adb:rebooted", () => { - if (mainWindow) mainWindow.webContents.send("adb:rebooted"); -}); - +// Reboot complete, hide the reboot prompt mainEvent.on("reboot:done", () => { if (mainWindow) mainWindow.webContents.send("reboot:done"); }); +// Control the progress bar mainEvent.on("user:write:progress", (length) => { if (mainWindow) mainWindow.webContents.send("user:write:progress", length); }); +// Installation successfull mainEvent.on("user:write:done", () => { if (mainWindow) mainWindow.webContents.send("user:write:done"); if (mainWindow) mainWindow.webContents.send("user:write:speed"); utils.log.info("All done! Your device will now reboot and complete the installation. Enjoy exploring Ubuntu Touch!"); }); +// Show working animation mainEvent.on("user:write:working", (animation) => { if (mainWindow) mainWindow.webContents.send("user:write:working", animation); }); +// Set the top text in the footer mainEvent.on("user:write:status", (status) => { if (mainWindow) mainWindow.webContents.send("user:write:status", status); }); +// Set the speed part of the footer mainEvent.on("user:write:speed", (speed) => { if (mainWindow) mainWindow.webContents.send("user:write:speed", speed); }); +// Set the lower text in the footer mainEvent.on("user:write:under", (status) => { if (mainWindow) mainWindow.webContents.send("user:write:under", status); }); -mainEvent.on("user:adb:ready", () => { - if (mainWindow) mainWindow.webContents.send("user:adb:ready"); -}); - +// Device is unsupported mainEvent.on("user:device-unsupported", (device) => { utils.log.warn("The device " + device + " is not supported!"); if (mainWindow) mainWindow.webContents.send("user:device-unsupported", device); }); +// Set the install configuration data mainEvent.on("device:select:data-ready", (output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { global.installProperties.device = device; if (mainWindow) mainWindow.webContents.send("device:select:data-ready", output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid); }); +// No internet connection mainEvent.on("user:no-network", () => { if (mainWindow) mainWindow.webContents.send("user:no-network"); }); @@ -221,7 +238,7 @@ function createWindow () { // Tasks we need for every start mainWindow.webContents.on("did-finish-load", () => { adb.start(false, false, (err) => { - mainEvent.emit("user:adb:ready"); + mainWindow.webContents.send("user:adb:ready"); devices.waitForDevice(); }); devices.getDeviceSelects((out) => { @@ -232,7 +249,7 @@ function createWindow () { // Task we need only on the first start mainWindow.webContents.once("did-finish-load", () => { utils.getUpdateAvailable().then(() => { - utils.log.info("This is not the latest version of the UBports Installer! Please update: https://devices.ubuntu-touch.io/installer/" + global.packageInfo.package); + utils.log.info("This is not the latest version of the UBports Installer! Please update: https://devices.ubuntu-touch.io/installer/" + (global.packageInfo.package ? global.packageInfo.package : "")); mainWindow.webContents.send("user:update-available"); }).catch(() => { utils.log.debug("This is the latest version.") @@ -247,9 +264,7 @@ function createWindow () { mainWindow.setMenu(null); // TODO set menu - if (cli.debug) { - mainWindow.webContents.openDevTools(); - } + if (cli.debug) mainWindow.webContents.openDevTools(); mainWindow.on('closed', function () { mainWindow = null; @@ -262,10 +277,6 @@ function createWindow () { app.on('ready', createWindow); -app.on('uncaughtException', function (error) { - console.log("CRAP!"); -}); - app.on('window-all-closed', function () { utils.log.info("Good bye!"); adb.stop(() => { From aa505efc1b869639d6977a45b46745eaad5f2f9c Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 00:08:26 +0200 Subject: [PATCH 32/47] Initial implementation of adb and fastboot modules --- package-lock.json | 1039 +++++++++++++++++++++++++++++++++---- package.json | 1 + src/adb.js | 329 ------------ src/devices.js | 275 +++------- src/fastboot.js | 239 --------- src/html/scripts/main.pug | 3 +- src/main.js | 38 +- src/system-image.js | 40 +- 8 files changed, 1062 insertions(+), 902 deletions(-) delete mode 100644 src/adb.js delete mode 100644 src/fastboot.js diff --git a/package-lock.json b/package-lock.json index 0aef8103..6ecd52d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,131 @@ "integrity": "sha512-AsnBZN3a8/JcNt+KPkGGODaA4c7l3W5+WpeKgGSbstSLxqWtTXqd1ieJGBQ8IFCtRg8DmmKUcSkIkUc0A4p3YA==", "dev": true }, + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.2.tgz", + "integrity": "sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ==", + "requires": { + "@babel/types": "^7.6.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.2.tgz", + "integrity": "sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==" + }, + "@babel/template": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", + "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0" + } + }, + "@babel/traverse": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.2.tgz", + "integrity": "sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.6.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.6.2", + "@babel/types": "^7.6.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@babel/types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + } + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -204,7 +329,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -270,6 +394,14 @@ } } }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "requires": { + "default-require-extensions": "^2.0.0" + } + }, "archive-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", @@ -407,6 +539,11 @@ } } }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -867,6 +1004,33 @@ } } }, + "caching-transform": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "requires": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, "camelcase": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", @@ -973,7 +1137,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -983,14 +1146,12 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -1100,7 +1261,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -1108,8 +1268,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { "version": "1.0.3", @@ -1134,6 +1293,11 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, "compare-version": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", @@ -1275,6 +1439,14 @@ "safe-buffer": "5.1.2" } }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, "core-js": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", @@ -1305,6 +1477,34 @@ } } }, + "cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "requires": { + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, "crc": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", @@ -1606,6 +1806,21 @@ "integrity": "sha512-VIPwiMJqJ13ZQfaCsIFnp5Me9tnjURiaIFxfz7EH0Ci0dTSQpZtSLrqOicXqEd/z2r+z+Klk9GzmnRsgpgbOsQ==", "dev": true }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "requires": { + "strip-bom": "^3.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + } + } + }, "defer-to-connect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.0.2.tgz", @@ -2331,8 +2546,7 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "end-of-stream": { "version": "1.4.1", @@ -2352,7 +2566,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "requires": { "is-arrayish": "^0.2.1" } @@ -2390,6 +2603,11 @@ "is-symbol": "^1.0.2" } }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" + }, "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", @@ -2597,6 +2815,32 @@ "trim-repeated": "^1.0.0" } }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -2671,6 +2915,26 @@ } } }, + "foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + } + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -2859,8 +3123,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-func-name": { "version": "2.0.0", @@ -3043,6 +3306,11 @@ "ini": "^1.3.4" } }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, "globule": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", @@ -3122,9 +3390,9 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" }, "handlebars": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", - "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.0.tgz", + "integrity": "sha512-xkRtOt3/3DzTKMOt3xahj2M/EqNhY988T+imYSlMgs5fVhLN2fmKVVj0LtEGmb+3UUYV5Qmm1052Mm3dIQxOvw==", "requires": { "neo-async": "^2.6.0", "optimist": "^0.6.1", @@ -3205,6 +3473,14 @@ "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "dev": true }, + "hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "requires": { + "is-stream": "^1.0.1" + } + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -3219,8 +3495,7 @@ "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" }, "http-cache-semantics": { "version": "4.0.3", @@ -3261,8 +3536,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "2.1.0", @@ -3378,8 +3652,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-buffer": { "version": "1.1.6", @@ -3611,6 +3884,128 @@ } } }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==" + }, + "istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "istanbul-reports": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "requires": { + "handlebars": "^4.1.2" + } + }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", @@ -3635,6 +4030,11 @@ "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -3649,11 +4049,21 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -3852,7 +4262,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -3861,8 +4270,7 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" } } }, @@ -3871,6 +4279,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=" + }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -3919,7 +4332,6 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -3992,6 +4404,14 @@ } } }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "requires": { + "source-map": "^0.6.1" + } + }, "mime": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", @@ -4348,6 +4768,11 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" }, + "nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==" + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4431,7 +4856,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -4529,40 +4953,164 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "nyc": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", + "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "requires": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" }, "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } } }, "object.entries": { @@ -4640,6 +5188,11 @@ } } }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, "os-locale": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", @@ -4730,7 +5283,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -4739,7 +5291,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -4755,8 +5306,18 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "package-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", + "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } }, "package-json": { "version": "6.4.0", @@ -4896,6 +5457,24 @@ "pinkie": "^2.0.0" } }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + } + } + }, "plist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", @@ -4955,6 +5534,171 @@ "asap": "~2.0.3" } }, + "promise-android-tools": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-android-tools/-/promise-android-tools-1.0.1.tgz", + "integrity": "sha512-l0TawmYm3ucXtvRT7GZzMxgCkj/yOPyBnG2vaZA5Xq/Xx7W60l5NTMEwZYjAbqCjtnEMV/WhBlX7TJoQlRWzMQ==", + "requires": { + "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", + "coveralls": "^3.0.0", + "mocha": "^4.0.1", + "nyc": "^14.1.1", + "sinon": "^7.5.0", + "sinon-chai": "^3.3.0" + }, + "dependencies": { + "@sinonjs/formatio": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", + "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "requires": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "requires": { + "check-error": "^1.0.2" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "lolex": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==" + }, + "mocha": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + } + }, + "nise": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz", + "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==", + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^4.1.0", + "path-to-regexp": "^1.7.0" + } + }, + "sinon": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", + "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.3", + "diff": "^3.5.0", + "lolex": "^4.2.0", + "nise": "^1.5.2", + "supports-color": "^5.5.0" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "sinon-chai": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.3.0.tgz", + "integrity": "sha512-r2JhDY7gbbmh5z3Q62pNbrjxZdOAjpsqW/8yxAZRSqLZqowmfGZPGUZPFf3UX36NLis0cv8VEM5IJh9HgkSOAA==" + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -4963,8 +5707,7 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "psl": { "version": "1.1.33", @@ -5269,6 +6012,14 @@ "rc": "^1.2.8" } }, + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "requires": { + "es6-error": "^4.0.1" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -5319,14 +6070,12 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { "version": "1.11.1", @@ -5336,6 +6085,11 @@ "path-parse": "^1.0.6" } }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -5378,7 +6132,6 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, "requires": { "glob": "^7.1.3" }, @@ -5387,7 +6140,6 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5474,8 +6226,7 @@ "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" }, "semver-diff": { "version": "2.1.0", @@ -5489,8 +6240,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "setimmediate": { "version": "1.0.5", @@ -5516,8 +6266,7 @@ "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "single-line-log": { "version": "1.1.2", @@ -5609,11 +6358,23 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, + "spawn-wrap": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", + "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", + "requires": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -5622,14 +6383,12 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -5638,8 +6397,7 @@ "spdx-license-ids": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", - "dev": true + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==" }, "spectron": { "version": "3.8.0", @@ -5989,6 +6747,97 @@ "execa": "^0.7.0" } }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + } + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -6456,7 +7305,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -6577,8 +7425,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "wide-align": { "version": "1.1.3", @@ -6679,7 +7526,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, "requires": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -6689,20 +7535,17 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -6713,7 +7556,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -6729,7 +7571,6 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, "requires": { "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", @@ -6766,14 +7607,12 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { "version": "3.10.0", @@ -6790,7 +7629,6 @@ "version": "13.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -6799,8 +7637,7 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" } } }, diff --git a/package.json b/package.json index e1b5c8bc..f7d85a4a 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "jquery": "^3.1.1", "jquery-i18next": "^1.2.0", "mkdirp": "^0.5.1", + "promise-android-tools": "^1.0.1", "request": "^2.79.0", "system-image-node-module": "^1.0.9", "ubports-api-node-module": "^1.0.2", diff --git a/src/adb.js b/src/adb.js deleted file mode 100644 index c5145fb2..00000000 --- a/src/adb.js +++ /dev/null @@ -1,329 +0,0 @@ -"use strict"; - -/* - -Adb wrapper, part of ubports-installer - -Author: Marius Gripsgard - -*/ - -const sys = require('util') -const cp = require('child_process'); -const path = require("path"); -const fs = require("fs"); -const utils = require("./utils"); -const exec = require('child_process').exec; - -// DEFAULT = 5037 -const PORT = 5037 - -// Since we need root anyway, why not start adb with root -const start = (password, sudo, callback) => { - // Make sure the server is not running - stop(err => { - var cmd=""; - if (utils.needRoot() && sudo) - cmd += utils.sudoCommand(password); - cmd += "adb -P " + PORT + " start-server"; - // HACK: Authorize Fairphone 2 vendor ID if necessary - if (utils.isSnap()) - exec("echo 0x2ae5 > ~/.android/adb_usb.ini"); - utils.platformToolsExecAsar("adb", (platformToolsExecAsar) => { - platformToolsExecAsar.exec(cmd, (c, r, e) => { - if (r.includes("incorrect password")) - callback({ - password: true - }); - else - callback(); - platformToolsExecAsar.done(); - }); - }); - }); -} - -const stop = (callback) => { - utils.log.debug("Killing all running adb servers...") - utils.platformToolsExec("adb", ["kill-server"], (err, stdout, stderr) => { - utils.platformToolsExec("adb", ["-P", PORT, "kill-server"], (err, stdout, stderr) => { - // console.log(stdout) - if (err !== null) callback(false); - else callback(); - }); - }); -} - -// TODO: remove lazy override alias, this should be handled by the server -// NOT localy. -const lazyOverrideAlias = (func, arg, callback) => { - var alias = { - "A0001": "bacon", - "a0001": "bacon", - "find7op": "bacon", - "nexus5": "hammerhead", - "fairphone2": "FP2", - "PRO5": "turbo", - "mx4": "arale", - "Aquaris_E45": "krillin", - "Aquaris_E5": "vegetahd", - "Aquaris_M10HD": "cooler", - "Aquaris_M10FHD": "frieza" - } - func(device => { - if (device in alias) - callback(alias[device]); - else - callback(device); - }, arg) -} - -var getDeviceNameFromPropFile = (callback) => { - shell("cat default.prop", (output) => { - output=output.split("\n"); - var ret; - output.forEach((prop) => { - if (prop.includes("ro.product.device") && prop !== undefined && !ret){ - ret = prop.split("=")[1]; - } - }); - callback(ret.replace(/\W/g, "")); - }); -} - -var _getDeviceName = (callback, method) => { - if (!method) method = "device"; - shell("getprop ro.product."+method, (stdout) => { - if (!stdout) { - utils.log.debug("getprop: error"); - callback(false); - return; - } else if (stdout.includes("getprop: not found")){ - utils.log.debug("getprop: not found") - getDeviceNameFromPropFile(callback); - return; - } - utils.log.debug("getprop: "+stdout.replace(/\W/g, "")) - callback(stdout.replace(/\W/g, "")); - }); -} - -var getDeviceName = (callback, method) => { - lazyOverrideAlias(_getDeviceName, method, callback) -} - -var isUbuntuDevice = (callback) => { - shell("cat /etc/system-image/channel.ini", (output) => { - callback(output ? true : false); - }); -} - -var readUbuntuChannelINI = (callback) => { - shell("cat /etc/system-image/channel.ini", (output) => { - if (!output) - return callback(false); - if (!output.startsWith("[service]")) - return callback(false); - var ret = {}; - output.split("\n").forEach(line => { - if (!line.includes(": ")) - return; - var split = line.replace("\r", "").split(": "); - ret[split[0]] = split[1]; - }); - callback(ret); - }) -} - -var isBaseUbuntuCom = callback => { - readUbuntuChannelINI(ini => { - if (!ini) - return callback(false); - callback(ini.base.includes("system-image.ubuntu.com")) - }); -} - -var push = (file, dest) => { - return new Promise(function(resolve, reject) { - var done; - var hundredEmitted; - var fileSize = fs.statSync(file)["size"]; - var lastSize = 0; - var progressInterval = setInterval(() => { - shell("stat -t " + dest + "/" + path.basename(file), (stat) => { - mainEvent.emit("adbpush:progress:size", eval(stat.split(" ")[1])-lastSize); - lastSize = eval(stat.split(" ")[1]); - }); - }, 1000); - var guardedfile = process.platform == "darwin" ? file : '"' + file + '"'; // macos can't handle double quotes - utils.platformToolsExec("adb", ["-P", PORT, "push", guardedfile, dest], (err, stdout, stderr) => { - done=true; - if (err) { - var stdoutShort = stdout && stdout.length > 256 ? "[...]" + stdout.substr(-256, stdout.length) : stdout; - var stderrShort = stderr && stderr.length > 256 ? "[...]" + stderr.substr(-256, stderr.length) : stderr; - if (stderrShort.indexOf("I/O error") != -1) { - utils.log.warn("connection to device lost"); - // TODO: Only restart the event rather than the entire installation - mainEvent.emit("user:connection-lost", () => { mainEvent.emit("restart"); }); - } else if (!err.killed && (err.code == 1)) { - hasAdbAccess ((hasAccess) => { - if (hasAccess) { - utils.errorToUser(err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort, "ADB push"); - } else { - utils.log.warn("connection to device lost"); - // TODO: Only restart the event rather than the entire installation - mainEvent.emit("user:connection-lost", () => { mainEvent.emit("restart"); }); - } - }); - } else { - utils.errorToUser(err + ", stdout: " + stdoutShort + ", stderr: " + stderrShort, "ADB push"); - } - } - clearInterval(progressInterval); - resolve(); - }); - }); -} - -var pushMany = (files) => { - mainEvent.emit("user:write:working", "push"); - mainEvent.emit("user:write:status", "Pushing files"); - mainEvent.emit("user:write:under", "Almost finished! Are you excited yet?"); - try { - if (files.length <= 0){ - utils.errorToUser("No files provided", "ADB push"); - return false; - } - var totalSize = 0; - var downloadedSize = 0; - // Get total size for progress bar - files.forEach((file) => { - try { - totalSize += fs.statSync(file.src)["size"]; - } catch (e) { - throw "Can't read system-image files: " + e - } - }); - mainEvent.on("adbpush:progress:size", (s) => { - downloadedSize += s; - mainEvent.emit("adbpush:progress", downloadedSize/totalSize); - }); - // Push it to the limit - function pushNext(i) { - utils.log.debug("Pushing file " + (i+1) + " of " + files.length); - push(files[i].src, files[i].dest).then(() => { - if (i+1 < files.length) { - pushNext(i+1); - } else { - mainEvent.emit("adbpush:done"); - } - }); - } - pushNext(0); // Begin pushing - } catch (e) { - utils.errorToUser(e, "ADB PushMany") - } -} - -var shell = (cmd, callback) => { - if (!cmd.startsWith("stat")) utils.log.debug("adb shell: "+cmd); - utils.platformToolsExec("adb", ["-P", PORT, "shell", cmd], (err, stdout, stderr) => { - if (err) callback(false); - else callback(stdout); - }); -} - -var waitForDevice = (callback) => { - let timer = setInterval(() => { - shell("echo 1", (r) => { - if(r){ - clearInterval(timer); - callback(true); - return; - } - }); - }, 2000); - mainEvent.on("stop", () => { - clearInterval(timer); - }); -} - -var hasAdbAccess = (callback) => { - shell("echo 1", (r) => { - callback(r); - }) -} - -var reboot = (state, callback) => { - utils.log.debug("reboot to "+state); - utils.platformToolsExec("adb", ["-P", PORT, "reboot", state], (err, stdout, stderr) => { - utils.log.debug("reboot to " + state + " done"); - if (stdout.includes("failed")) callback(true, stdout, stderr); - else if (stderr.includes("failed")) callback(true, stdout, stderr); - else if (err !== null) callback(true, stdout, stderr); - else callback(false); - }); -} - -var format = (partition, callback) => { - shell("cat /etc/recovery.fstab", (fstab_) => { - if (!fstab_) { - callback(false, "cannot find recovery.fstab"); - return; - } - var fstab = fstab_.split("\n"); - var block; - fstab.forEach((fs) => { - if (!fs.includes(partition) || block) - return; - block = fs.split(" ")[0]; - if (!block.startsWith("/dev")) - block=false; - }) - if (!block) { - callback(false, "cannot find partition: "+partition); - return; - } - shell("umount /"+partition, () => { - shell("make_ext4fs " + block, (ret) => { - shell("mount /"+partition, () => { - if (ret) - callback(false, "failed to wipe "+partition) - else - callback(true); - }) - }); - }) - }) -} - -var wipeCache = (callback) => { - // Try with format; - format("cache", (err) => { - if (!err){ - callback(true); - return; - } - - // If format failed, just rm the contents of cache; - shell("rm -rf /cache/*", callback); - }) -} - -module.exports = { - waitForDevice: waitForDevice, - shell: shell, - getDeviceName: getDeviceName, - push: push, - pushMany: pushMany, - hasAdbAccess: hasAdbAccess, - reboot: reboot, - getDeviceNameFromPropFile: getDeviceNameFromPropFile, - isUbuntuDevice: isUbuntuDevice, - readUbuntuChannelINI: readUbuntuChannelINI, - format: format, - wipeCache: wipeCache, - isBaseUbuntuCom, isBaseUbuntuCom, - start: start, - stop: stop -} diff --git a/src/devices.js b/src/devices.js index c2c60acf..66be66b4 100644 --- a/src/devices.js +++ b/src/devices.js @@ -10,8 +10,6 @@ Author: Marius Gripsgard const http = require("request"); const ubportsApi = require("ubports-api-node-module"); -const adb = require("./adb"); -const fastboot = require("./fastboot"); const systemImage = require("./system-image"); const utils = require("./utils"); const os = require("os"); @@ -39,27 +37,10 @@ var isLegacyAndroid = (device) => { } } -var getNotWorking = (ww) => { - if (!ww) return false; - var notWorking = []; - var whatsWorking = JSON.parse(ww); - for (var i in whatsWorking) { - if (whatsWorking[i] == 1) notWorking.push(i); - } - if (whatsWorking.length == 0) return false; - else return notWorking; -} - -var formatNotWorking = (nw) => { - if (!nw) return false; - return nw.join(", ").replace("/\,(?=[^,]*$)", " and"); -} - var instructReboot = (state, button, callback) => { global.mainEvent.emit("user:write:working", "particles"); global.mainEvent.emit("user:write:status", "Rebooting to " + state); global.mainEvent.emit("user:write:under", "Waiting for device to enter " + state + " mode"); - var rebooted = false; var manualReboot = () => { utils.log.info("Instructing manual reboot"); utils.log.info(button[state]["instruction"]); @@ -69,45 +50,44 @@ var instructReboot = (state, button, callback) => { state: state }); } - adb.hasAdbAccess((hasAccess) => { + var rebootTimeout = setTimeout(() => { manualReboot(); }, 15000); + adb.hasAccess().then((hasAccess) => { if (hasAccess) { - adb.reboot(state, (err, out, eout) => { - if (err) { - utils.log.warn("Adb failed to reboot!, " + out + " : " + eout); - manualReboot(); - } else { - global.mainEvent.emit("reboot:done"); - } + adb.reboot(state).then(() => { + clearTimeout(rebootTimeout); + global.mainEvent.emit("reboot:done"); + }).catch((err) => { + utils.log.warn("Adb failed to reboot!, " + err); + clearTimeout(rebootTimeout); + manualReboot(); }); } else { + clearTimeout(rebootTimeout); manualReboot(); } if (state === "bootloader") { - requestPassword((pass) => { - fastboot.waitForDevice(pass, (err, errM) => { - if (err) { - utils.errorToUser(errM, "fastboot.waitForDevice"); - return; - } else { - rebooted = true; - global.mainEvent.emit("reboot:done"); - global.mainEvent.emit("state:bootloader"); - callback(); - return; - } - }); + fastboot.waitForDevice().then((err, errM) => { + if (err) { + utils.errorToUser(errM, "fastboot.waitForDevice"); + return; + } else { + clearTimeout(rebootTimeout); + global.mainEvent.emit("reboot:done"); + callback(); + return; + } }); } else { - adb.waitForDevice(() => { - rebooted = true; - // We expect the device state to mach installState now + adb.waitForDevice().then(() => { + clearTimeout(rebootTimeout); global.mainEvent.emit("reboot:done"); callback(); return; }); } + }).catch((error) => { + utils.errorToUser(error, "Wait for device") }); - setTimeout(() => { if (!rebooted) manualReboot() }, 15000); } var requestPassword = (callback) => { @@ -135,92 +115,10 @@ var requestPassword = (callback) => { }); } -var instructOemUnlock = (callback) => { - requestPassword((p) => { - fastboot.oemUnlock(password, (err, errM) => { - if (err) { - utils.errorToUser(errM, "OEM unlock"); - callback(true); - } else { - callback(false); - } - }); - }) -} - -var handleBootstrapError = (err, errM, backToFunction) => { - if (err.bootFailed) { - utils.log.warn("fastboot boot failed, does the " + global.installProperties.device + " really support it?"); - global.mainEvent.emit("bootstrap:done", false); // This will instruct a manual reboot - } else if (err.password) { - ipcRenderer.send("user:password:wrong", backToFunction); - } else if (err.connectionLost) { - utils.log.warn("connection to device lost"); - global.mainEvent.emit("user:connection-lost", backToFunction); - } else if (err.locked) { - global.mainEvent.emit("user:oem-lock", backToFunction); - } else if (err.lowPower) { - global.mainEvent.emit("user:low-power"); - } else { - utils.errorToUser(errM, "Bootstrap"); - } -} - -var instructBootstrap = (bootstrap, images) => { - //TODO check bootloader name/version/device - var flash = (p) => { - utils.log.info("Flashing images...") - fastboot.flash(images, (err, errM) => { - if (err) { - handleBootstrapError(err, errM, () => { - instructBootstrap(bootstrap, images); - }); - } else { - if (bootstrap) { // The device supports the "fastboot boot" command - utils.log.info("Booting into recovery image..."); - // find recovery image - var recoveryImg; - images.forEach((image) => { - if (image.type === "recovery") - recoveryImg = image; - }); - // If we can't find it, report error! - if (!recoveryImg) { - utils.errorToUser("Cant find recoveryImg to boot: "+images, "fastboot.boot"); - } else { - fastboot.boot(recoveryImg, p, (err, errM) => { - if (err) { - handleBootstrapError(err, errM, () => { - instructBootstrap(bootstrap, images); - }); - } else { - global.mainEvent.emit("bootstrap:done", bootstrap); - } - }); - } - } else { // The device needs to be rebooted manually - global.mainEvent.emit("bootstrap:done", false); - } - } - }, p); - } - global.mainEvent.emit("user:write:working", "particles"); - global.mainEvent.emit("user:write:status", "Flashing images"); - global.mainEvent.emit("user:write:under", "Flashing recovery and boot images"); - global.mainEvent.emit("user:write:progress", 0); - if (!utils.needRoot()) { - flash(false); - } else { - requestPassword((p) => { - flash(p); - }); - } -} - var downloadImages = (images, device) => { utils.log.debug(addPathToImages(images, device)); global.mainEvent.emit("user:write:working", "download"); - global.mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); + global.mainEvent.emit("user:write:status", "Downloading Firmware"); global.mainEvent.emit("user:write:under", "Downloading"); utils.downloadFiles(images, (progress, speed) => { global.mainEvent.emit("download:progress", progress); @@ -236,10 +134,12 @@ var downloadImages = (images, device) => { }); } -var addPathToImages = (images, device) => { +function addPathToImages(images, device) { var ret = []; images.forEach((image) => { + image["partition"] = image.type; image["path"] = path.join(downloadPath, "images", device); + image["file"] = path.join(downloadPath, "images", device, image.type + "-" + device + ".img"); ret.push(image); }); return ret; @@ -251,14 +151,10 @@ global.mainEvent.on("download:progress", (percent) => { global.mainEvent.on("download:speed", (speed) => { global.mainEvent.emit("user:write:speed", Math.round(speed*100)/100); }); -global.mainEvent.on("adbpush:progress", (percent) => { - global.mainEvent.emit("user:write:progress", percent*100); -}); var install = (options) => { if (!options) return false; - utils.log.debug("install event started with options: " + JSON.stringify(options)) devicesApi.getInstallInstructs(options.device).then((instructs) => { global.mainEvent.once("adbpush:done", () => { utils.log.info("Done pushing files"); @@ -271,7 +167,7 @@ var install = (options) => { }); global.mainEvent.once("bootstrap:done", (bootstrap) => { utils.log.info("bootstrap done: " + (bootstrap ? "rebooting automatically" : "rebooting manually")); - if (!bootstrap){ + if (!bootstrap) { instructReboot("recovery", instructs.buttons, () => { systemImage.installLatestVersion({ device: options.device, @@ -282,13 +178,13 @@ var install = (options) => { } else { global.mainEvent.emit("user:write:status", "Rebooting to recovery"); global.mainEvent.emit("user:write:under", "Waiting for device to enter recovery mode"); - adb.waitForDevice(() => { + adb.waitForDevice().then(() => { systemImage.installLatestVersion({ device: options.device, channel: options.channel, wipe: options.wipe }); - }); + }).catch((error) => { utils.errorToUser(error, "Wait for device"); }); } }); if (instructs.images.length > 0) { // If images are specified, flash them (bootstrapping) @@ -297,7 +193,27 @@ var install = (options) => { global.mainEvent.emit("user:write:under", "Fastboot is scanning for devices"); instructReboot("bootloader", instructs.buttons, () => { global.mainEvent.once("download:done", () => { - instructBootstrap(instructs.installSettings.bootstrap, addPathToImages(instructs.images, options.device)); + global.mainEvent.emit("user:write:working", "particles"); + global.mainEvent.emit("user:write:status", "Flashing images"); + global.mainEvent.emit("user:write:under", "Flashing recovery and boot images"); + global.mainEvent.emit("user:write:progress", 0); + fastboot.erase("cache").then(() => { + fastboot.flashArray(addPathToImages(instructs.images, options.device)).then(() => { + if (instructs.bootstrap) { // Device should support the fastboot boot command + var recoveryImg; + instructs.images.forEach((image) => { + if (image.type == "recovery") recoveryImg = image.file; + }); + fastboot.boot(recoveryImg).then(() => { + global.mainEvent.emit("bootstrap:done", true); + }).catch(() => { + global.mainEvent.emit("bootstrap:done", false); + }); + } else { + global.mainEvent.emit("bootstrap:done", false); + } + }).catch((error) => { utils.errorToUser(error, "bootstrap"); }); + }).catch(((e) => { utils.errorToUser(e, "Fastboot: Erase cache"); })); }); downloadImages(instructs.images, options.device); }); @@ -314,53 +230,21 @@ var install = (options) => { }).catch((e) => { utils.errorToUser(e, "Install"); }); } -var getChannelSelects = (device, callback) => { - if (!device) { - callback (false); - return; - } - var channelsAppend = []; - systemImage.getDeviceChannels(device).then((channels) => { - devicesApi.getInstallInstructs(device).then((ret) => { - if (ret) { - channels.forEach((channel) => { - var _channel = channel.replace("ubports-touch/", ""); - // Ignore blacklisted channels - if (ret["systemServer"]["blacklist"].indexOf(channel) == -1 && - channel.indexOf("15.04") == -1) { - if (channel === ret["systemServer"]["selected"]) - channelsAppend.push(""); - else - channelsAppend.push(""); - } - }); - channelsAppend.push("") - callback(channelsAppend.join('')); - return; - } else { - callback(false); - return; - } - }).catch(((e) => { utils.errorToUser(e, "Devices API"); })); - }).catch((e) => { utils.errorToUser(e, "SystemImage API"); }); -} - module.exports = { getDevice: devicesApi.getDevice, waitForDevice: () => { - adb.waitForDevice((deviceDetected) => { - if (deviceDetected) { - adb.getDeviceName((device) => { - adb.isBaseUbuntuCom((ubuntuCom) => { - global.mainEvent.emit("device:select:event", device, ubuntuCom, true); - return; - }); + adb.waitForDevice().then(() => { + adb.getDeviceName().then((device) => { + adb.getOs().then((operatingSystem) => { + global.mainEvent.emit("device:select:event", device, (operatingSystem=="ubuntutouch"), true); + return; + }).catch((error) => { + utils.errorToUser(error, "Wait for device") }); - } else { - global.mainEvent.emit("device:select:event", false); - return; - } - }); + }).catch((error) => { + utils.errorToUser(error, "get device name"); + }); + }).catch(e => utils.log.debug("no device detected: " + e)); global.mainEvent.once("device:select", (device) => { global.mainEvent.emit("stop"); utils.log.info(device + " selected"); @@ -369,16 +253,24 @@ module.exports = { global.mainEvent.once("device:select:event", (device, ubuntuCom, autoDetected) => { devicesApi.getDevice(device).then((apiData) => { if (apiData) { - setTimeout(() => { - getChannelSelects(device, (channels) => { - if (channels) { - global.mainEvent.emit("device:select:data-ready", apiData, device, channels, ubuntuCom, autoDetected, isLegacyAndroid(device)); - } else { - global.mainEvent.emit("user:no-network"); - } - return; - }); - }, 50); + systemImage.getDeviceChannels(device).then((channels) => { + var channelsAppend = []; + devicesApi.getInstallInstructs(device).then((ret) => { + channels.forEach((channel) => { + var _channel = channel.replace("ubports-touch/", ""); + // Ignore blacklisted channels + if (ret["systemServer"]["blacklist"].indexOf(channel) == -1 && + channel.indexOf("15.04") == -1) { + if (channel === ret["systemServer"]["selected"]) + channelsAppend.push(""); + else + channelsAppend.push(""); + } + }); + channelsAppend.push("") + global.mainEvent.emit("device:select:data-ready", apiData, device, channelsAppend.join(''), ubuntuCom, autoDetected); + }).catch(((e) => { utils.log.error(e); global.mainEvent.emit("user:no-network"); })); + }).catch((e) => { utils.log.error(e); global.mainEvent.emit("user:no-network"); }); } else { mainEvent.emit("user:device-unsupported", device); // If there is no response, the device is not supported // ipcRenderer.send("setInstallProperties", { device: device }); @@ -387,8 +279,6 @@ module.exports = { }).catch(((e) => { utils.errorToUser(e, "Device Select"); })); }); }, - getNotWorking: getNotWorking, - formatNotWorking: formatNotWorking, install: install, getDeviceSelects: (callback) => { devicesApi.getDevices().then((devices) => { @@ -410,6 +300,5 @@ module.exports = { callback(false); } }).catch(((e) => { utils.errorToUser(e, "getDeviceSelects"); })); - }, - instructOemUnlock: instructOemUnlock + } } diff --git a/src/fastboot.js b/src/fastboot.js deleted file mode 100644 index a76505d8..00000000 --- a/src/fastboot.js +++ /dev/null @@ -1,239 +0,0 @@ -/* - -Fastboot wrapper, part of ubports-installer - -Author: Marius Gripsgard - -*/ - -const path = require("path"); -var utils = global.utils; - -const lockedErrors = ["unlocked", "locked", "oem-lock", "lock"] - -var isLocked = (message) => { - var locked = false; - lockedErrors.forEach((l) => { - if (message.includes(l)){ - locked = true; - return true; - } - }) - return locked; -} - -var handleError = (c, r, e, password, callback) => { - if (c) { - if (c.message.includes("incorrect password")) { - callback({ password: true }); - } else if (isLocked(c.message)) { - callback({ locked: true }); - } else if (e.includes("booting...") && e.includes("FAILED (remote failure)")) { - callback({ bootFailed: true }); - } else if ( - e.includes("FAILED (status read failed (No such device))") || - e.includes("FAILED (command write failed (No such device))") || - e.includes("FAILED (command write failed (Success))") || - e.includes("FAILED (data transfer failure (Broken pipe))") || - e.includes("FAILED (data transfer failure (Protocol error))") - ) { - callback({ connectionLost: true }); - } else if (e.includes("FAILED (remote: low power, need battery charging.)")) { - callback({ lowPower: true }); - } else { - callback(true, "Fastboot: Unknown error: " + utils.hidePassword(r,password) + " " + utils.hidePassword(e,password)); - } - } else { - callback(c, r, e); - } -} - -/* - -args; string, function - -*/ -var waitForDevice = (password, callback) => { - utils.log.info("fastboot: wait for device"); - if (global.installProperties.simulate) { - callback(false); - return; - } - var cmd = ""; - if (utils.needRoot()) - cmd += utils.sudoCommand(password); - cmd += "fastboot" + " devices"; - var stop; - utils.log.debug("Executing: " + utils.hidePassword(cmd, password)); - utils.platformToolsExecAsar("fastboot", (asarExec) => { - var repeat = () => { - asarExec.exec(cmd, (err, r, e) => { - if (r) { - if (r.includes("incorrect password")) - callback(true, { - password: true - }); - else if (r.includes("fastboot")) { - callback(false); - asarExec.done(); - } else { - // Unknown error; - utils.log.error("Fastboot: Unknown error: " + utils.hidePassword(r,password) + " " + utils.hidePassword(e,password)); - callback(true, "Fastboot: Unknown error: " + utils.hidePassword(r,password) + " " + utils.hidePassword(e,password)); - } - return; - } else { - if (e) { - utils.log.error("Fastboot: Unknown error: " + utils.hidePassword(r,password) + " " + utils.hidePassword(e,password)); - callback(true, "Fastboot: Unknown error: " + utils.hidePassword(r,password) + " " + utils.hidePassword(e,password)); - } - setTimeout(() => { - if (!stop) repeat(); - else asarExec.done(); - }, 5000) - } - }) - } - repeat(); - }); - return { - stop: () => { - stop = true; - } - }; -} - -// Due to limitations with sudo we combind the sudo.exec to one call to prevent -// seperate password prompts -/* - -args; array(object), string, function - -image object format -[ - { - path: string, | path of file - url: string, | url to extract filename - type: string | partition to flash - } -] - -*/ -var flash = (images, callback, password) => { - if (global.installProperties.simulate) { - callback(false); - return; - } - utils.log.debug("fastboot: flash; " + JSON.stringify(images)); - var cmd = ""; - images.forEach((image, l) => { - if (utils.needRoot()) - cmd += utils.sudoCommand(password); - cmd += "fastboot" + " flash " + image.type + " \"" + path.join(image.path, path.basename(image.url)) + "\""; - if (l !== images.length - 1) - cmd += " && " - }); - utils.platformToolsExecAsar("fastboot", (asarExec) => { - asarExec.exec(cmd, (c, r, e) => { - handleError(c, r, e, password, callback); - asarExec.done(); - }) - }); -} - -/* - -args; array(object), string, function - -image object format -[ - { - path: string, | path of file - url: string | url to extract filename - } -] - -*/ -var boot = (image, password, callback) => { - if (global.installProperties.simulate) { - callback(false); - return; - } - var cmd=""; - if (utils.needRoot()) - cmd += utils.sudoCommand(password); - cmd += "fastboot" + " boot \"" + path.join(image.path, path.basename(image.url)) + "\""; - utils.platformToolsExecAsar("fastboot", (asarExec) => { - asarExec.exec(cmd, (c, r, e) => { - handleError(c, r, e, password, callback); - asarExec.done(); - }) - }); -} -/* - -args; array, string, function - -*/ -var format = (partitions, password, callback) => { - if (global.installProperties.simulate) { - callback(false); - return; - } - var cmd=""; - partitions.forEach((partition, l) => { - if (utils.needRoot()) - cmd += utils.sudoCommand(password); - cmd += "fastboot" + " format " + partition; - if (l !== partitions.length - 1) - cmd += " && " - }); - utils.platformToolsExecAsar("fastboot", (asarExec) => { - asarExec.exec(cmd, (c, r, e) => { - handleError(c, r, e, password, callback); - asarExec.done(); - }) - }); -} - -/* - -args; array, string, function - -*/ -var oem = (command, password, callback) => { - if (global.installProperties.simulate) { - callback(false); - return; - } - var cmd=""; - if (utils.needRoot()) - cmd += utils.sudoCommand(password); - cmd += "fastboot" + " oem " + command; - utils.platformToolsExecAsar("fastboot", (asarExec) => { - asarExec.exec(cmd, (c, r, e) => { - setTimeout(() => { - handleError(c, r, e, password, callback); - asarExec.done(); - }, 100); - }) - }); -} - -/* - -args; string, function - -*/ -var oemUnlock = (password, callback) => { - oem("unlock", password, callback); -} - -module.exports = { - flash: flash, - waitForDevice: waitForDevice, - boot: boot, - format: format, - oem: oem, - oemUnlock: oemUnlock -} diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index abcaa5b0..2cb482af 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -128,6 +128,7 @@ script. }); ipcRenderer.on("device:select:data-ready", (event, output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { + console.log("yep") views.show("install"); $("#options-channel").append(channels); options.optionsValToUser(); @@ -148,8 +149,6 @@ script. shell.openExternal("https://devices.ubuntu-touch.io/device/"+output.device); }); - views.show(ubuntuCom ? "switch" : "install"); - $("#btn-installModal").click(() => { views.show("working", "particles"); $("#progress").show(); diff --git a/src/main.js b/src/main.js index 54addb82..5009791e 100755 --- a/src/main.js +++ b/src/main.js @@ -16,6 +16,9 @@ const app = electron.app; const BrowserWindow = electron.BrowserWindow; global.packageInfo = require('../package.json'); +const Adb = require('../../android-tools/src/module.js').Adb; +const Fastboot = require('../../android-tools/src/module.js').Fastboot; + const path = require('path'); const url = require('url'); const events = require("events"); @@ -25,14 +28,16 @@ const pug = new electronPug(); const ipcMain = electron.ipcMain; let mainWindow; -var mainEvent = new event(); +const mainEvent = new event(); global.mainEvent = mainEvent; -var utils = require('./utils.js'); +const utils = require('./utils.js'); global.utils = utils; -var fastboot = require('./fastboot.js'); -var devices = require('./devices.js'); -var adb = require('./adb.js'); +const devices = require('./devices.js'); +const adb = new Adb(); +global.adb = adb; +const fastboot = new Fastboot(); +global.fastboot = fastboot; cli .name(global.packageInfo.name) @@ -121,7 +126,8 @@ mainEvent.on("user:password:wrong", () => { // Open the bugreporting tool mainEvent.on("user:error", (err) => { try { - mainWindow.webContents.send("user:error", err); + if (mainWindow) mainWindow.webContents.send("user:error", err); + else utils.die(err); } catch (e) { utils.log.error(e); process.exit(1); @@ -150,12 +156,10 @@ mainEvent.on("restart", () => { mainEvent.on("user:oem-lock", (callback) => { mainWindow.webContents.send("user:oem-lock"); ipcMain.once("user:oem-lock:ok", () => { - devices.instructOemUnlock((err) => { - if (err) { - mainEvent.emit("user:error", err); - } else { - callback(true); - } + fastboot.oemUnlock().then(() => { + callback(true); + }).catch((err) => { + mainEvent.emit("user:error", err); }); }); }); @@ -237,7 +241,7 @@ function createWindow () { // Tasks we need for every start mainWindow.webContents.on("did-finish-load", () => { - adb.start(false, false, (err) => { + adb.startServer().then(() => { mainWindow.webContents.send("user:adb:ready"); devices.waitForDevice(); }); @@ -279,7 +283,7 @@ app.on('ready', createWindow); app.on('window-all-closed', function () { utils.log.info("Good bye!"); - adb.stop(() => { + adb.killServer().then(() => { if (process.platform !== 'darwin') { app.quit(); } @@ -291,3 +295,9 @@ app.on('activate', function () { createWindow(); } }); + +process.on('unhandledRejection', (r) => { + utils.log.error(r); + if (mainWindow) utils.errorToUser(r); + else utils.die(r); +}); diff --git a/src/system-image.js b/src/system-image.js index 6949bb62..58cf5aa7 100644 --- a/src/system-image.js +++ b/src/system-image.js @@ -10,7 +10,6 @@ Author: Marius Gripsgard const fs = require("fs"); const utils = require("./utils"); -const adb = require("./adb"); const path = require("path"); const mkdirp = require('mkdirp'); const systemImageClient = require("system-image-node-module").Client; @@ -24,20 +23,6 @@ const getDeviceChannels = (device) => { return systemImage.getDeviceChannels(device); } -var pushLatestVersion = (files, dontWipeCache) => { - var doPush = () => { - adb.shell("mount -a", () => { - adb.shell("mkdir -p /cache/recovery", () => { - adb.pushMany(files); - }); - }); - } - if (dontWipeCache) - doPush(); - else - adb.wipeCache(doPush); -} - var installLatestVersion = (options) => { mainEvent.emit("user:write:working", "download"); mainEvent.emit("user:write:status", "Downloading Ubuntu Touch"); @@ -48,15 +33,22 @@ var installLatestVersion = (options) => { }, (current, total) => { if (current != total) utils.log.debug("Downloading system-image file " + (current+1) + " of " + total); }).then((files) => { - utils.log.debug(files) - mainEvent.emit("user:write:working", "particles"); - mainEvent.emit("user:write:status", "Download Complete"); - mainEvent.emit("user:write:under", "Checking downloaded files"); - // Wait for one second until the progress event stops firing - setTimeout(() => { - mainEvent.emit("download:done"); - pushLatestVersion(files); - }, 1000); + mainEvent.emit("download:done"); + mainEvent.emit("user:write:progress", 0); + mainEvent.emit("user:write:working", "push"); + mainEvent.emit("user:write:status", "Sending"); + mainEvent.emit("user:write:under", "Sending files to the device"); + adb.wipeCache().then(() => { + adb.shell("mount -a").then(() => { + adb.shell("mkdir -p /cache/recovery").then(() => { + adb.pushArray(files, (progress) => { + global.mainEvent.emit("user:write:progress", progress*100); + }).then(() => { + global.mainEvent.emit("adbpush:done"); + }).catch(e => utils.errorToUser("Push failed: Failed push: " + e)); + }).catch(e => utils.errorToUser("Push failed: Failed to create target dir: " + e)); + }).catch(e => utils.errorToUser("Push failed: Failed to mount: " + e)); + }).catch(e => utils.errorToUser("Push failed: Failed wipe cache: " + e)); }); } From 3110d0f2023ff759034760ae99838a439e50b0e8 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 10:58:27 +0200 Subject: [PATCH 33/47] Download platform tools in setup-dev.sh --- build.js | 8 ++++++-- setup-dev.sh | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/build.js b/build.js index 201f90f2..baf25a7b 100755 --- a/build.js +++ b/build.js @@ -142,8 +142,12 @@ switch (cli.package) { case "": break; default: - console.log("Building " + cli.package + " is not configured!"); - process.exit(1); + if (!cli.downloadOnly) { + console.log("Building " + cli.package + " is not configured!"); + process.exit(1); + } else { + break; + } } var build = () => { diff --git a/setup-dev.sh b/setup-dev.sh index 6b517e29..5d79080e 100755 --- a/setup-dev.sh +++ b/setup-dev.sh @@ -19,4 +19,7 @@ sudo apt install $packages echo "Setting up node modules..." npm install +echo "Downloading platform tools" +node build.js --download-only --os=linux + echo "Done!" From 321db32397ec725650daa632645f78e6ca9dffb5 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 10:59:00 +0200 Subject: [PATCH 34/47] die gracefully --- src/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index dceb25a1..c017f728 100644 --- a/src/utils.js +++ b/src/utils.js @@ -170,7 +170,7 @@ winston.add(winston.transports.File, { var die = (e) => { log.error(e); - ipcRenderer.send("die", 1); + process.exit(-1) } var sudoCommand = (password) => { From 9750ba0afbf7f4b1a9d02d9cc69fccdc701407ec Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 10:59:27 +0200 Subject: [PATCH 35/47] Fix copyright notice in package metadata --- buildconfig-generic.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildconfig-generic.json b/buildconfig-generic.json index 6cd44d8a..90323d2c 100644 --- a/buildconfig-generic.json +++ b/buildconfig-generic.json @@ -1,7 +1,7 @@ { "appId": "com.ubports.installer", "productName": "ubports-installer", - "copyright": "Copyright © year UBports Foundation", + "copyright": "Copyright © 2017-2019 UBports Foundation", "publish": [], "files": [ "src/**/*", From 463555a61144b8dfb5df814ea956dd07c21e6265 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 11:41:33 +0200 Subject: [PATCH 36/47] Copy executables from asar package --- src/main.js | 23 +++++++++++++++++++---- src/utils.js | 16 +++++++++++++++- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/main.js b/src/main.js index 5009791e..06d471c3 100755 --- a/src/main.js +++ b/src/main.js @@ -16,9 +16,10 @@ const app = electron.app; const BrowserWindow = electron.BrowserWindow; global.packageInfo = require('../package.json'); -const Adb = require('../../android-tools/src/module.js').Adb; -const Fastboot = require('../../android-tools/src/module.js').Fastboot; +const Adb = require('promise-android-tools').Adb; +const Fastboot = require('promise-android-tools').Fastboot; +const exec = require('child_process').exec; const path = require('path'); const url = require('url'); const events = require("events"); @@ -34,9 +35,21 @@ global.mainEvent = mainEvent; const utils = require('./utils.js'); global.utils = utils; const devices = require('./devices.js'); -const adb = new Adb(); +var adb = new Adb({ + exec: (args, callback) => { exec( + [(path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'adb'))].concat(args).join(" "), + {options: {maxBuffer: 1024*1024*2}}, + callback + ); } +}); global.adb = adb; -const fastboot = new Fastboot(); +var fastboot = new Fastboot({ + exec: (args, callback) => { exec( + [(path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'fastboot'))].concat(args).join(" "), + {options: {maxBuffer: 1024*1024*2}}, + callback + ); } +}); global.fastboot = fastboot; cli @@ -66,6 +79,8 @@ global.installProperties = { global.packageInfo.isSnap = utils.isSnap(); +utils.exportExecutablesFromPackage(); + //============================================================================== // RENDERER SIGNAL HANDLING //============================================================================== diff --git a/src/utils.js b/src/utils.js index c017f728..fd409b90 100644 --- a/src/utils.js +++ b/src/utils.js @@ -156,7 +156,7 @@ var getUbuntuTouchDir = () => { default: throw Error("Unknown platform " + process.platform); } - return path.join(osCacheDir, "ubports") + return path.join(osCacheDir, "ubports"); } if (!fs.existsSync(getUbuntuTouchDir())) { @@ -208,6 +208,19 @@ var checkPassword = (password, callback) => { }); } +function exportExecutablesFromPackage() { + fs.copy( + (path.join(path.dirname(__dirname), 'platform-tools', 'linux', 'adb')), + (path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'adb')), + () => {fs.chmodSync((path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'adb')), 0o755);} + ); + fs.copy( + (path.join(path.dirname(__dirname), 'platform-tools', 'linux', 'fastboot')), + (path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'fastboot')), + () => {fs.chmodSync((path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'fastboot')), 0o755);} + ); +} + // WORKAROUND: since we are using asar packages to compress into one package we cannot use // child_process.exec since it spans a shell and shell wont be able to access the files // inside the asar package. @@ -483,6 +496,7 @@ function errorToUser(error, errorLocation) { module.exports = { errorToUser: errorToUser, + exportExecutablesFromPackage: exportExecutablesFromPackage, setCustomPlatformTool: setCustomPlatformTool, downloadFiles: downloadFiles, log: log, From e39bd6deebd0a834798a21e26d301dd4bce249e3 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 12:33:40 +0200 Subject: [PATCH 37/47] Streamline platform tool detection and remove dead code --- src/utils.js | 285 +++++++++++++-------------------------------------- 1 file changed, 71 insertions(+), 214 deletions(-) diff --git a/src/utils.js b/src/utils.js index fd409b90..c5a1e736 100644 --- a/src/utils.js +++ b/src/utils.js @@ -25,24 +25,12 @@ var ipcRenderer = require('electron').ipcRenderer; global.installProperties = remote ? remote.getGlobal('installProperties') : undefined; global.packageInfo = remote ? remote.getGlobal('packageInfo') : require('../package.json'); -var customTools = { - adb: undefined, - fastboot: undefined -} - const platforms = { "linux": "linux", "darwin": "mac", "win32": "win" } -var platformNativeToolsLogged; -var platformFallbackToolsLogged; - -var getVersion = () => { - return global.packageInfo.version; -} - if (global.installProperties) winston.level = global.installProperties.verbose ? 'debug' : 'info'; @@ -162,6 +150,7 @@ var getUbuntuTouchDir = () => { if (!fs.existsSync(getUbuntuTouchDir())) { mkdirp.sync(getUbuntuTouchDir()); } + winston.add(winston.transports.File, { filename: path.join(getUbuntuTouchDir(), 'ubports-installer.log'), level: 'debug', // Print debug logs to the file @@ -178,153 +167,48 @@ var sudoCommand = (password) => { } var checkPassword = (password, callback) => { - if (!needRoot()) { - log.debug("no root needed") + if (!needRoot()) { + log.debug("no root needed"); + callback(true); + return; + } + log.debug("checking password"); + exec(sudoCommand(password) + "echo correct", (err, output) => { + if (err) { + if (err.message.includes("incorrect password")) { + log.debug("incorrect password"); + callback(false, { + password: true + }); + } else { + // Replace password with "***" to make sure it wont get logged + log.debug("unknown sudo error"); + callback(false, { + message: err.message.replace(password, "***") + }); + } + } else { + log.debug("correct password") + if (output.includes("correct")) callback(true); - return; + else + callback(false); } - log.debug("checking password") - exec(sudoCommand(password) + "echo correct", (err, output) => { - if (err) { - if (err.message.includes("incorrect password")) { - log.debug("incorrect password") - callback(false, { - password: true - }); - } else { - // Replace password with "***" to make sure it wont get logged - log.debug("unknown sudo error") - callback(false, { - message: err.message.replace(password, "***") - }); - } - } else { - log.debug("correct password") - if (output.includes("correct")) - callback(true); - else - callback(false); - } - }); + }); } +// WORKAROUND: the chile spawned by child_process.exec can not access files inside the asar package function exportExecutablesFromPackage() { - fs.copy( - (path.join(path.dirname(__dirname), 'platform-tools', 'linux', 'adb')), - (path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'adb')), - () => {fs.chmodSync((path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'adb')), 0o755);} - ); - fs.copy( - (path.join(path.dirname(__dirname), 'platform-tools', 'linux', 'fastboot')), - (path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'fastboot')), - () => {fs.chmodSync((path.join(utils.getUbuntuTouchDir(), 'platform-tools', 'fastboot')), 0o755);} - ); -} - -// WORKAROUND: since we are using asar packages to compress into one package we cannot use -// child_process.exec since it spans a shell and shell wont be able to access the files -// inside the asar package. -var asarExec = (file, callback) => { - tmp.dir((err, tmpDir, cleanup) => { - if (err) callback(true); - fs.copy(file, path.join(tmpDir, path.basename(file)), (err) => { - fs.chmodSync(path.join(tmpDir, path.basename(file)), 0o755); - if(err) die(err); - callback({ - exec: (cmd, cb) => { - let name = file.split('/').pop(); - cmd = cmd.replace(new RegExp(name, 'g'), path.join(tmpDir, path.basename(file))); - exec(cmd, (err, e,r) => { - // log.debug(cmd) // CAREFUL! THIS MIGHT LOG PASSWORDS! - cb(err,e,r); - }) - }, - done: () => { - fs.removeSync(tmpDir); - } - }); - }); + getFallbackPlatformTools().forEach((tool) => { + fs.copy(tool.package, tool.cache, () => { + fs.chmodSync(tool.cache, 0o755); }); -} - -const logPlatformNativeToolsOnce = () => { - if (!platformNativeToolsLogged) { - log.debug("Using native platform tools!"); - platformNativeToolsLogged=true; - } -} - -const logPlatformFallbackToolsOnce = () => { - if (!platformFallbackToolsLogged) { - log.debug("Using fallback platform tools!"); - platformFallbackToolsLogged=true; - } -} - -const callbackHook = (callback) => { - return (a,b,c) => { - // log.debug(a,b,c); - callback(a,b,c) - } -} - -const platformToolsExec = (tool, arg, callback) => { - var tools = getPlatformTools(); - - // First check for native tools - if (tools[tool] && !global.installProperties.forceFallback) { - logPlatformNativeToolsOnce(); - var cmd = tools[tool] + " " + arg.join(" "); - // log.debug(cmd) // CAREFUL! THIS MIGHT LOG PASSWORDS! - cp.exec(cmd, {maxBuffer: 2000*1024}, callbackHook(callback)); - return true; - } - - // Try using fallback tools - if (tools.fallback[tool]) { - logPlatformFallbackToolsOnce(); - // log.debug(tools.fallback[tool] + " " + arg.join(" ")) // CAREFUL! THIS MIGHT LOG PASSWORDS! - cp.execFile(tools.fallback[tool], arg, {maxBuffer: 2000*1024}, callbackHook(callback)); - return true; - } - log.error("NO PLATFORM TOOL USED!"); - callback(true, false); - return false; -} - -const platformToolsExecAsar = (tool, callback) => { - var tools = getPlatformTools(); - - // First check for native - if (tools[tool] && !global.installProperties.forceFallback) { - logPlatformNativeToolsOnce(); - callback({ - exec: (cmd, cb) => { - var _cmd = cmd.replace(tool, tools[tool]); - exec(_cmd, (err, e,r) => { - // log.debug(_cmd) // CAREFUL! THIS MIGHT LOG PASSWORDS! - cb(err,e,r); - }) - }, - done: () => {} - }); - return true; - } - - // Use fallback tools if there are no native tools installed - if (tools.fallback[tool]) { - logPlatformFallbackToolsOnce(); - asarExec(tools.fallback[tool], callback); - return true; - } - log.error("NO PLATFORM TOOL USED!"); - callback(true, false); - return false; + }); } var maybeEXE = (platform, tool) => { - if(platform === "win32") tool+=".exe"; - return tool; + if(platform === "win32") tool+=".exe"; + return tool; } var getPlatform = () => { @@ -333,40 +217,21 @@ var getPlatform = () => { return platforms[thisPlatform]; } -// Check if we have native platform tools -const setCustomPlatformTool = (tool, executable) => { - log.info(tool + " has been set to " + executable) - customTools[tool] = executable; -} - -// Check if we have native platform tools -const getPlatformTools = () => { - var p = getNativePlatformTools(); - p["fallback"] = getFallbackPlatformTools(); - return p; -} - -const getNativePlatformTools = () => { - var ret = {}; - if (customTools["adb"]) - ret["adb"] = customTools["adb"]; - else if (commandExistsSync("adb")) - ret["adb"] = "adb"; - if (customTools["fastboot"]) - ret["fastboot"] = customTools["fastboot"]; - else if (commandExistsSync("fastboot")) - ret["fastboot"] = "fastboot"; - return ret; -} - -const getFallbackPlatformTools = () => { - var thisPlatform = os.platform(); - if(!platforms[thisPlatform]) die("Unsupported platform"); - var platformToolsPath = path.join(__dirname, "/../platform-tools/", platforms[thisPlatform]); - return { - fastboot: path.join(platformToolsPath, maybeEXE(thisPlatform, "fastboot")), - adb: path.join(platformToolsPath, maybeEXE(thisPlatform, "adb")) +function getFallbackPlatformTools() { + var thisPlatform = os.platform(); + if(!platforms[thisPlatform]) die("Unsupported platform"); + var toolInPackage = path.join(__dirname, "/../platform-tools/", platforms[thisPlatform]); + var toolInCache = path.join(utils.getUbuntuTouchDir(), 'platform-tools'); + return [ + { + package: path.join(toolInPackage, maybeEXE(thisPlatform, "fastboot")), + cache: path.join(toolInCache, maybeEXE(thisPlatform, "fastboot")) + }, + { + package: path.join(toolInPackage, maybeEXE(thisPlatform, "adb")), + cache: path.join(toolInCache, maybeEXE(thisPlatform, "adb")) } + ] } var isSnap = () => { @@ -374,14 +239,13 @@ var isSnap = () => { } var needRoot = () => { - if ( - (os.platform() === "win32") || - isSnap() || - !commandExistsSync("sudo") || - global.installProperties.noRoot || - global.installProperties.simulate - ) return false; - else return !process.env.SUDO_UID + if ( + (os.platform() === "win32") || + isSnap() || + !commandExistsSync("sudo") || + global.installProperties.noRoot + ) return false; + else return !process.env.SUDO_UID } var ensureRoot = (m) => { @@ -495,27 +359,20 @@ function errorToUser(error, errorLocation) { } module.exports = { - errorToUser: errorToUser, - exportExecutablesFromPackage: exportExecutablesFromPackage, - setCustomPlatformTool: setCustomPlatformTool, - downloadFiles: downloadFiles, - log: log, - platformToolsExec: platformToolsExec, - platformToolsExecAsar: platformToolsExecAsar, - ensureRoot: ensureRoot, - isSnap: isSnap, - getPlatformTools: getPlatformTools, - getUbuntuTouchDir: getUbuntuTouchDir, - needRoot: needRoot, - sudoCommand: sudoCommand, - checkPassword: checkPassword, - createBugReport: createBugReport, - getUpdateAvailable: getUpdateAvailable, - getPlatform: getPlatform, - asarExec: asarExec, - getVersion: getVersion, - hidePassword: hidePassword, - die: die, - ipcRenderer: ipcRenderer, - setLogLevel: (level) => { winston.level = level; } + errorToUser: errorToUser, + exportExecutablesFromPackage: exportExecutablesFromPackage, + downloadFiles: downloadFiles, + log: log, + ensureRoot: ensureRoot, + isSnap: isSnap, + getUbuntuTouchDir: getUbuntuTouchDir, + needRoot: needRoot, + sudoCommand: sudoCommand, + checkPassword: checkPassword, + createBugReport: createBugReport, + getUpdateAvailable: getUpdateAvailable, + hidePassword: hidePassword, + die: die, + ipcRenderer: ipcRenderer, + setLogLevel: (level) => { winston.level = level; } } From 7285e5de1883e2d9e4b901de4f43895602c55584 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 18:31:49 +0200 Subject: [PATCH 38/47] Minor code quality improvements --- src/devices.js | 25 -------------- src/utils.js | 88 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/src/devices.js b/src/devices.js index 66be66b4..0747ae25 100644 --- a/src/devices.js +++ b/src/devices.js @@ -90,31 +90,6 @@ var instructReboot = (state, button, callback) => { }); } -var requestPassword = (callback) => { - if (!utils.needRoot()) { - callback(""); - return; - } - if (password) { - callback(password); - return; - } - global.mainEvent.emit("user:password"); - global.mainEvent.once("password", (p) => { - utils.checkPassword(p, (correct, err) => { - if (correct) { - password=p; - callback(p); - } else if (err.password) { - global.mainEvent.emit("user:password:wrong"); - requestPassword(callback); - } else { - utils.errorToUser(err.message, "Password"); - } - }); - }); -} - var downloadImages = (images, device) => { utils.log.debug(addPathToImages(images, device)); global.mainEvent.emit("user:write:working", "download"); diff --git a/src/utils.js b/src/utils.js index c5a1e736..de043680 100644 --- a/src/utils.js +++ b/src/utils.js @@ -41,7 +41,7 @@ var log = { debug: (l) => {winston.log("debug", l)} } -var createBugReport = (title, installProperties, callback) => { +function createBugReport(title, installProperties, callback) { var options = { limit: 400, start: 0, @@ -84,7 +84,7 @@ var createBugReport = (title, installProperties, callback) => { }); } -var getCleanOs = () => { +function getCleanOs() { try { return getos((e,gOs) => { if(gOs.os == "linux") @@ -129,26 +129,26 @@ function getUpdateAvailable() { }); } -var getUbuntuTouchDir = () => { - var osCacheDir; - switch (process.platform) { - case "linux": - osCacheDir = path.join(process.env.HOME, '.cache'); - break; - case "darwin": - osCacheDir = path.join(process.env.HOME, 'Library/Caches'); - break; - case "win32": - osCacheDir = process.env.APPDATA; - break; - default: - throw Error("Unknown platform " + process.platform); - } - return path.join(osCacheDir, "ubports"); +function getUbuntuTouchDir() { + var osCacheDir; + switch (process.platform) { + case "linux": + osCacheDir = path.join(process.env.HOME, '.cache'); + break; + case "darwin": + osCacheDir = path.join(process.env.HOME, 'Library/Caches'); + break; + case "win32": + osCacheDir = process.env.APPDATA; + break; + default: + throw Error("Unknown platform " + process.platform); + } + return path.join(osCacheDir, "ubports"); } if (!fs.existsSync(getUbuntuTouchDir())) { - mkdirp.sync(getUbuntuTouchDir()); + mkdirp.sync(getUbuntuTouchDir()); } winston.add(winston.transports.File, { @@ -157,16 +157,41 @@ winston.add(winston.transports.File, { options: { flags: 'w' } // Clear log before writing to it }); -var die = (e) => { - log.error(e); - process.exit(-1) +function die(e) { + log.error(e); + process.exit(-1); +} + +function requestPassword(callback) { + if (!needRoot()) { + callback(""); + return; + } + if (password) { + callback(password); + return; + } + global.mainEvent.emit("user:password"); + global.mainEvent.once("password", (p) => { + checkPassword(p, (correct, err) => { + if (correct) { + password=p; + callback(p); + } else if (err.password) { + global.mainEvent.emit("user:password:wrong"); + requestPassword(callback); + } else { + errorToUser(err.message, "Password"); + } + }); + }); } -var sudoCommand = (password) => { - return isSnap() ? "" : "echo '" + password.replace(/\'/g, "'\\''") + "' | sudo -S "; +function sudoCommand(password) { + return isSnap() ? "" : "echo '" + password.replace(/\'/g, "'\\''") + "' | sudo -S "; } -var checkPassword = (password, callback) => { +function checkPassword(password, callback) { if (!needRoot()) { log.debug("no root needed"); callback(true); @@ -206,12 +231,12 @@ function exportExecutablesFromPackage() { }); } -var maybeEXE = (platform, tool) => { +function maybeEXE(platform, tool) { if(platform === "win32") tool+=".exe"; return tool; } -var getPlatform = () => { +function getPlatform() { var thisPlatform = os.platform(); if(!platforms[thisPlatform]) die("Unsuported platform"); return platforms[thisPlatform]; @@ -234,11 +259,11 @@ function getFallbackPlatformTools() { ] } -var isSnap = () => { +function isSnap() { return process.env.SNAP_NAME } -var needRoot = () => { +function needRoot() { if ( (os.platform() === "win32") || isSnap() || @@ -248,7 +273,7 @@ var needRoot = () => { else return !process.env.SUDO_UID } -var ensureRoot = (m) => { +function ensureRoot(m) { if(process.env.SUDO_UID) return; log.error(m) @@ -344,7 +369,7 @@ function downloadFiles(urls, progress, next) { }); } -const hidePassword = (output, pw) => { +function hidePassword(output, pw) { if (needRoot()) { return output.replace(pw.replace(/\'/g, "'\\''"), "***"); } else { @@ -372,6 +397,7 @@ module.exports = { createBugReport: createBugReport, getUpdateAvailable: getUpdateAvailable, hidePassword: hidePassword, + requestPassword: requestPassword, die: die, ipcRenderer: ipcRenderer, setLogLevel: (level) => { winston.level = level; } From 7e3efd4e557816cbff8123d76aabdfc395d0fe69 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 18:50:06 +0200 Subject: [PATCH 39/47] Do not prompt for password --- package.json | 1 - src/devices.js | 2 - src/html/index.pug | 1 - src/html/modals/password.pug | 20 -------- src/html/scripts/main.pug | 23 --------- src/main.js | 17 ------- src/utils.js | 92 ------------------------------------ 7 files changed, 156 deletions(-) delete mode 100644 src/html/modals/password.pug diff --git a/package.json b/package.json index f7d85a4a..c230437d 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "commander": "^2.9.0", "electron-open-link-in-browser": "^1.0.2", "electron-pug": "^1.5.1", - "electron-sudo": "^3.0.13", "executable": "^4.1.0", "forward-emitter": "^0.1.1", "fs-extra": "^2.0.0", diff --git a/src/devices.js b/src/devices.js index 0747ae25..ed6d32ce 100644 --- a/src/devices.js +++ b/src/devices.js @@ -18,8 +18,6 @@ const path = require("path"); const devicesApi = new ubportsApi.Devices(); const downloadPath = utils.getUbuntuTouchDir(); -var password; - // HACK: This should be handled by the server, not locally var isLegacyAndroid = (device) => { switch (device) { diff --git a/src/html/index.pug b/src/html/index.pug index 21b195f2..652ccf70 100644 --- a/src/html/index.pug +++ b/src/html/index.pug @@ -35,7 +35,6 @@ html include modals/install include modals/connection-lost include modals/error - include modals/password include modals/oem-lock include modals/legacy-android include modals/low-power diff --git a/src/html/modals/password.pug b/src/html/modals/password.pug deleted file mode 100644 index 2d7e48ee..00000000 --- a/src/html/modals/password.pug +++ /dev/null @@ -1,20 +0,0 @@ -#password-modal.modal.fade(tabindex='-1', data-backdrop='static', data-keyboard='false', role='dialog') - .modal-dialog(role='document') - .modal-content - .modal-header - button.close(type='button', data-dismiss='modal', aria-label='Close') - span(aria-hidden='true') × - h4#myModalLabel.modal-title Administrator password needed to continue - .modal-body - p - | In order to flash the bootimages on your device, your administrator password is needed. This is the same one you use to install software on this computer. - #password-wrong.alert.alert-danger(role='alert', hidden='hidden') - | Access denied, please try again. Are you sure you have entered the correct password? - hr - form.form-horizontal - .form-group - label.col-xs-3.control-label Password - .col-xs-9 - input#password-input.form-control(type='password') - .modal-footer - button#btn-password.btn.btn-primary(type='button', data-dismiss='modal') OK diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index 2cb482af..ec73936f 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -11,35 +11,12 @@ script. } $("#error-body").text(err); $("#error-modal").modal("show"); - $("#password-modal").modal("hide"); } window.onerror = (err, url, line) => { onErr(err+" (MainRenderer:"+line+")"); } - ipcRenderer.on("user:password", () => { - modals.show("password"); - $("#password-input").val(""); - $("#password-input").keypress((event) => { - if (event.which == '13') { - event.preventDefault(); - ipcRenderer.send("password", $("#password-input").val()); - modals.hide("password"); - $('#password-wrong').hide(); - } - }); - $("#btn-password").click(() => { - ipcRenderer.send("password", $("#password-input").val()); - $('#password-wrong').hide(); - }); - }); - - ipcRenderer.on("user:password:wrong", () => { - ipcRenderer.send("user:password"); - $('#password-wrong').show(); - }); - ipcRenderer.on("user:error", (event, err) => { onErr(err); }); ipcRenderer.on("user:write:working", (e, animation) => { diff --git a/src/main.js b/src/main.js index 06d471c3..49a4bf53 100755 --- a/src/main.js +++ b/src/main.js @@ -60,7 +60,6 @@ cli .option('-c, --channel ', '[experimental] Override the recommended release-channel for the device') .option('-C, --cli', "[experimental] Run without GUI", undefined, 'false') .option('-F, --force-fallback', "Use the android-tools packaged with the UBports Installer", undefined, 'false') - .option('-n, --no-root', "Do not ask for the password and run fastboot without elevated privilleges", undefined, 'false') .option('-v, --verbose', "Enable verbose logging", undefined, 'false') .option('-D, --debug', "Enable debugging tools and verbose logging", undefined, 'false') .option('-s, --simulate', "[experimental] Run through every step except actually installing", undefined, 'false') @@ -71,7 +70,6 @@ global.installProperties = { channel: cli.channel, cli: cli.cli, forceFallback: cli.forceFallback, - noRoot: !cli.root, verbose: (cli.verbose || cli.debug), debug: cli.debug, simulate: cli.simulate @@ -91,11 +89,6 @@ ipcMain.on("user:device:select", (event, installProperties) => { devices.install(installProperties); }); -// Password submitted by user -ipcMain.on("password", (e, password) => { - mainEvent.emit("password", password); -}); - // Exit process with optional non-zero exit code ipcMain.on("die", (exitCode) => { process.exit(exitCode); @@ -128,16 +121,6 @@ ipcMain.on("device:select", (event, device) => { // RENDERER COMMUNICATION //============================================================================== -// Prompt the user for the password -mainEvent.on("user:password", () => { - if (mainWindow) mainWindow.webContents.send("user:password"); -}); - -// The user entered a wrong password, prompt again -mainEvent.on("user:password:wrong", () => { - if (mainWindow) mainWindow.webContents.send("user:password:wrong"); -}); - // Open the bugreporting tool mainEvent.on("user:error", (err) => { try { diff --git a/src/utils.js b/src/utils.js index de043680..d5300a5b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -16,7 +16,6 @@ const mkdirp = require('mkdirp'); const tmp = require('tmp'); const exec = require('child_process').exec; const cp = require('child_process'); -const sudo = require('electron-sudo'); const winston = require('winston'); const getos = require('getos'); const commandExistsSync = require('command-exists').sync; @@ -162,66 +161,6 @@ function die(e) { process.exit(-1); } -function requestPassword(callback) { - if (!needRoot()) { - callback(""); - return; - } - if (password) { - callback(password); - return; - } - global.mainEvent.emit("user:password"); - global.mainEvent.once("password", (p) => { - checkPassword(p, (correct, err) => { - if (correct) { - password=p; - callback(p); - } else if (err.password) { - global.mainEvent.emit("user:password:wrong"); - requestPassword(callback); - } else { - errorToUser(err.message, "Password"); - } - }); - }); -} - -function sudoCommand(password) { - return isSnap() ? "" : "echo '" + password.replace(/\'/g, "'\\''") + "' | sudo -S "; -} - -function checkPassword(password, callback) { - if (!needRoot()) { - log.debug("no root needed"); - callback(true); - return; - } - log.debug("checking password"); - exec(sudoCommand(password) + "echo correct", (err, output) => { - if (err) { - if (err.message.includes("incorrect password")) { - log.debug("incorrect password"); - callback(false, { - password: true - }); - } else { - // Replace password with "***" to make sure it wont get logged - log.debug("unknown sudo error"); - callback(false, { - message: err.message.replace(password, "***") - }); - } - } else { - log.debug("correct password") - if (output.includes("correct")) - callback(true); - else - callback(false); - } - }); -} - // WORKAROUND: the chile spawned by child_process.exec can not access files inside the asar package function exportExecutablesFromPackage() { getFallbackPlatformTools().forEach((tool) => { @@ -263,23 +202,6 @@ function isSnap() { return process.env.SNAP_NAME } -function needRoot() { - if ( - (os.platform() === "win32") || - isSnap() || - !commandExistsSync("sudo") || - global.installProperties.noRoot - ) return false; - else return !process.env.SUDO_UID -} - -function ensureRoot(m) { - if(process.env.SUDO_UID) - return; - log.error(m) - process.exit(1); -} - function checksumFile(file) { return new Promise(function(resolve, reject) { fs.access(path.join(file.path, path.basename(file.url)), (err) => { @@ -369,14 +291,6 @@ function downloadFiles(urls, progress, next) { }); } -function hidePassword(output, pw) { - if (needRoot()) { - return output.replace(pw.replace(/\'/g, "'\\''"), "***"); - } else { - return output; - } -} - function errorToUser(error, errorLocation) { var errorString = "Error: " + (errorLocation ? errorLocation : "Unknown") + ": " + error; utils.log.error(errorString); @@ -388,16 +302,10 @@ module.exports = { exportExecutablesFromPackage: exportExecutablesFromPackage, downloadFiles: downloadFiles, log: log, - ensureRoot: ensureRoot, isSnap: isSnap, getUbuntuTouchDir: getUbuntuTouchDir, - needRoot: needRoot, - sudoCommand: sudoCommand, - checkPassword: checkPassword, createBugReport: createBugReport, getUpdateAvailable: getUpdateAvailable, - hidePassword: hidePassword, - requestPassword: requestPassword, die: die, ipcRenderer: ipcRenderer, setLogLevel: (level) => { winston.level = level; } From 4b7a64f55f7b1c237df6a97a0f2be5c0d2b751d4 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 18:54:31 +0200 Subject: [PATCH 40/47] Clean up cli options --- src/main.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main.js b/src/main.js index 49a4bf53..f9246e4e 100755 --- a/src/main.js +++ b/src/main.js @@ -59,20 +59,16 @@ cli .option('-d, --device ', '[experimental] Override detected device-id (codename)') .option('-c, --channel ', '[experimental] Override the recommended release-channel for the device') .option('-C, --cli', "[experimental] Run without GUI", undefined, 'false') - .option('-F, --force-fallback', "Use the android-tools packaged with the UBports Installer", undefined, 'false') .option('-v, --verbose', "Enable verbose logging", undefined, 'false') .option('-D, --debug', "Enable debugging tools and verbose logging", undefined, 'false') - .option('-s, --simulate', "[experimental] Run through every step except actually installing", undefined, 'false') .parse(process.argv); global.installProperties = { device: cli.device, channel: cli.channel, cli: cli.cli, - forceFallback: cli.forceFallback, verbose: (cli.verbose || cli.debug), - debug: cli.debug, - simulate: cli.simulate + debug: cli.debug }; global.packageInfo.isSnap = utils.isSnap(); From 6f0714a1dba3176750f5c9a53df68568ca89171e Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 19:15:51 +0200 Subject: [PATCH 41/47] Dependency cleanup --- package-lock.json | 1580 +------------------------------------------ package.json | 14 - src/devices.js | 1 - src/system-image.js | 6 - src/utils.js | 9 +- 5 files changed, 3 insertions(+), 1607 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6ecd52d7..9e92fe72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -307,18 +307,6 @@ } } }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -417,128 +405,6 @@ } } }, - "archiver": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", - "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", - "dev": true, - "requires": { - "archiver-utils": "^1.3.0", - "async": "^2.0.0", - "buffer-crc32": "^0.2.1", - "glob": "^7.0.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0", - "tar-stream": "^1.5.0", - "zip-stream": "^1.2.0" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "archiver-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", - "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", - "dev": true, - "requires": { - "glob": "^7.0.0", - "graceful-fs": "^4.1.0", - "lazystream": "^1.0.0", - "lodash": "^4.8.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -645,12 +511,6 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, "author-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz", @@ -1079,51 +939,6 @@ "lazy-cache": "^1.0.3" } }, - "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true, - "requires": { - "assertion-error": "^1.0.1", - "deep-eql": "^0.1.3", - "type-detect": "^1.0.0" - }, - "dependencies": { - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "requires": { - "type-detect": "0.1.1" - }, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, - "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", - "dev": true - } - } - }, - "chai-as-promised": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-6.0.0.tgz", - "integrity": "sha1-GgKkM6byTa+sY7nJb6FoTbGqjaY=", - "dev": true, - "requires": { - "check-error": "^1.0.2" - } - }, "chainsaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", @@ -1166,12 +981,6 @@ "is-regex": "^1.0.3" } }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -1211,21 +1020,6 @@ "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", "dev": true }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", @@ -1283,11 +1077,6 @@ "delayed-stream": "~1.0.0" } }, - "command-exists": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz", - "integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==" - }, "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", @@ -1304,50 +1093,6 @@ "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", "dev": true }, - "compress-commons": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", - "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", - "dev": true, - "requires": { - "buffer-crc32": "^0.2.1", - "crc32-stream": "^2.0.0", - "normalize-path": "^2.0.0", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1505,57 +1250,6 @@ } } }, - "crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "dev": true, - "requires": { - "buffer": "^5.1.0" - } - }, - "crc32-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", - "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", - "dev": true, - "requires": { - "crc": "^3.4.4", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -1573,33 +1267,6 @@ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, - "css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - } - }, - "css-parse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", - "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", - "dev": true, - "requires": { - "css": "^2.0.0" - } - }, - "css-value": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", - "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", - "dev": true - }, "cuint": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", @@ -1800,12 +1467,6 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, - "deepmerge": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.0.1.tgz", - "integrity": "sha512-VIPwiMJqJ13ZQfaCsIFnp5Me9tnjURiaIFxfz7EH0Ci0dTSQpZtSLrqOicXqEd/z2r+z+Klk9GzmnRsgpgbOsQ==", - "dev": true - }, "default-require-extensions": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", @@ -1827,34 +1488,11 @@ "integrity": "sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw==", "dev": true }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, - "dev-null": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", - "integrity": "sha1-WiBc48Ky73e2I41roXnrdMag6Bg=", - "dev": true - }, "diff": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", @@ -2185,87 +1823,6 @@ } } }, - "electron-chromedriver": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-1.8.0.tgz", - "integrity": "sha512-m1f3nle5MaGp94bcDTtMZZMMOgPO54+TXoPBlTbBSUjfINR5SJ46yQXLfuE79/qsFfJKslZB1UzWURDDFIRmpQ==", - "dev": true, - "requires": { - "electron-download": "^4.1.0", - "extract-zip": "^1.6.5" - }, - "dependencies": { - "electron-download": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.1.tgz", - "integrity": "sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg==", - "dev": true, - "requires": { - "debug": "^3.0.0", - "env-paths": "^1.0.0", - "fs-extra": "^4.0.1", - "minimist": "^1.2.0", - "nugget": "^2.0.1", - "path-exists": "^3.0.0", - "rc": "^1.2.1", - "semver": "^5.4.1", - "sumchecker": "^2.0.2" - } - }, - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "sumchecker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", - "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", - "dev": true, - "requires": { - "debug": "^2.2.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - } - } - }, "electron-download": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz", @@ -2538,11 +2095,6 @@ "pug": "^2.0.3" } }, - "electron-sudo": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/electron-sudo/-/electron-sudo-3.0.13.tgz", - "integrity": "sha1-TIUM3C878PPlQ7j9IcvWVka9V+o=" - }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -2570,39 +2122,6 @@ "is-arrayish": "^0.2.1" } }, - "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } - } - }, - "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -2677,14 +2196,6 @@ "strip-eof": "^1.0.0" } }, - "executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "requires": { - "pify": "^2.2.0" - } - }, "ext-list": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", @@ -2707,28 +2218,6 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - }, - "dependencies": { - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - } - } - }, "extract-zip": { "version": "1.6.7", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", @@ -2786,15 +2275,6 @@ "pend": "~1.2.0" } }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, "file-type": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", @@ -2851,23 +2331,6 @@ "pinkie-promise": "^2.0.0" } }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", - "dev": true - } - } - }, "flora-colossus": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/flora-colossus/-/flora-colossus-1.0.1.tgz", @@ -2950,28 +2413,6 @@ "mime-types": "^2.1.12" } }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true, - "requires": { - "samsam": "~1.1" - }, - "dependencies": { - "samsam": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.3.tgz", - "integrity": "sha1-n1CHQZtNCR8jJXHn+lLpCw9VJiE=", - "dev": true - } - } - }, - "forward-emitter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/forward-emitter/-/forward-emitter-0.1.1.tgz", - "integrity": "sha1-Vu3QwIIlDtujNOC5Iv/SwBk53uE=" - }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -3111,15 +2552,6 @@ } } }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "requires": { - "globule": "^1.0.0" - } - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3311,33 +2743,6 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, - "globule": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", - "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", - "dev": true, - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -3378,12 +2783,6 @@ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -3453,12 +2852,6 @@ "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, "has-to-string-tag-x": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", @@ -3566,61 +2959,6 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, "into-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", @@ -3643,12 +2981,6 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -3659,12 +2991,6 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true - }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -3674,12 +3000,6 @@ "ci-info": "^2.0.0" } }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, "is-electron-renderer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-electron-renderer/-/is-electron-renderer-2.0.1.tgz", @@ -3719,12 +3039,6 @@ "number-is-nan": "^1.0.0" } }, - "is-generator-function": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", - "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", - "dev": true - }, "is-installed-globally": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", @@ -3794,15 +3108,6 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, - "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.0" - } - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -4175,47 +3480,6 @@ "integrity": "sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q==", "dev": true }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -4294,15 +3558,6 @@ "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, "lolex": { "version": "2.7.5", "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", @@ -4494,275 +3749,11 @@ } } }, - "mocha": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", - "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.2.2", - "yargs-parser": "13.0.0", - "yargs-unparser": "1.5.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - } - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - } - }, - "yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, "neo-async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", @@ -4807,16 +3798,6 @@ } } }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, "nodeify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/nodeify/-/nodeify-1.0.1.tgz", @@ -4863,15 +3844,6 @@ "validate-npm-package-license": "^3.0.1" } }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, "normalize-url": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.3.0.tgz", @@ -4894,12 +3866,6 @@ } } }, - "npm-install-package": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz", - "integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=", - "dev": true - }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -5093,48 +4059,6 @@ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } - } - }, - "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5143,23 +4067,6 @@ "wrappy": "1" } }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - } - } - }, "optimist": { "version": "0.3.7", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", @@ -5246,7 +4153,8 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true }, "p-cancelable": { "version": "1.1.0", @@ -5864,12 +4772,6 @@ "strict-uri-encode": "^1.0.0" } }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -6020,12 +4922,6 @@ "es6-error": "^4.0.1" } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -6090,12 +4986,6 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -6104,22 +4994,6 @@ "lowercase-keys": "^1.0.0" } }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "rgb2hex": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.9.tgz", - "integrity": "sha512-32iuQzhOjyT+cv9aAFRBJ19JgHwzQwbjUhH3Fj2sWW2EEGAW8fpFrDFP5ndoKDxJaLO06x1hE3kyuIFrUQtybQ==", - "dev": true - }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -6151,30 +5025,6 @@ } } }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "requires": { - "rx-lite": "*" - } - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -6277,32 +5127,6 @@ "string-width": "^1.0.1" } }, - "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true, - "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": ">=0.10.3 <1" - }, - "dependencies": { - "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", - "dev": true - }, - "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", - "dev": true - } - } - }, "sinon-chai": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.14.0.tgz", @@ -6329,19 +5153,6 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "source-map-support": { "version": "0.5.12", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", @@ -6352,12 +5163,6 @@ "source-map": "^0.6.0" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, "spawn-wrap": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", @@ -6399,34 +5204,12 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==" }, - "spectron": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/spectron/-/spectron-3.8.0.tgz", - "integrity": "sha512-fQ7gFp6UuEaONjXFLifLeIUI022pOsm3b+NFAm696r2umUkSZ9IbnEgHwrvBX+pJ3QUDyCEs5bPHUieYU7FvaQ==", - "dev": true, - "requires": { - "dev-null": "^0.1.1", - "electron-chromedriver": "~1.8.0", - "request": "^2.81.0", - "split": "^1.0.0", - "webdriverio": "^4.8.0" - } - }, "speedometer": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", "dev": true }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -6853,14 +5636,6 @@ "xtend": "~2.1.1" } }, - "tmp": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", - "requires": { - "os-tmpdir": "~1.0.1" - } - }, "to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", @@ -7227,30 +6002,6 @@ "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -7270,27 +6021,6 @@ "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", "dev": true }, - "util": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", - "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "object.entries": "^1.1.0", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7325,95 +6055,6 @@ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" }, - "wdio-dot-reporter": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/wdio-dot-reporter/-/wdio-dot-reporter-0.0.10.tgz", - "integrity": "sha512-A0TCk2JdZEn3M1DSG9YYbNRcGdx/YRw19lTiRpgwzH4qqWkO/oRDZRmi3Snn4L2j54KKTfPalBhlOtc8fojVgg==", - "dev": true - }, - "webdriverio": { - "version": "4.14.4", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-4.14.4.tgz", - "integrity": "sha512-Knp2vzuzP5c5ybgLu+zTwy/l1Gh0bRP4zAr8NWcrStbuomm9Krn9oRF0rZucT6AyORpXinETzmeowFwIoo7mNA==", - "dev": true, - "requires": { - "archiver": "~2.1.0", - "babel-runtime": "^6.26.0", - "css-parse": "^2.0.0", - "css-value": "~0.0.1", - "deepmerge": "~2.0.1", - "ejs": "~2.5.6", - "gaze": "~1.1.2", - "glob": "~7.1.1", - "grapheme-splitter": "^1.0.2", - "inquirer": "~3.3.0", - "json-stringify-safe": "~5.0.1", - "mkdirp": "~0.5.1", - "npm-install-package": "~2.1.0", - "optimist": "~0.6.1", - "q": "~1.5.0", - "request": "^2.83.0", - "rgb2hex": "^0.1.9", - "safe-buffer": "~5.1.1", - "supports-color": "~5.0.0", - "url": "~0.11.0", - "wdio-dot-reporter": "~0.0.8", - "wgxpath": "~1.0.0" - }, - "dependencies": { - "ejs": { - "version": "2.5.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.9.tgz", - "integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==", - "dev": true - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "supports-color": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.0.1.tgz", - "integrity": "sha512-7FQGOlSQ+AQxBNXJpVDj8efTA/FtyB5wcNE1omXXJ0cq6jm1jjDwuROlYDbnzHqdNPqliWFhcioCWSyav+xBnA==", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } - } - } - }, - "wgxpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-1.0.0.tgz", - "integrity": "sha1-7vikudVYzEla06mit1FZfs2a9pA=", - "dev": true - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -7427,15 +6068,6 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "widest-line": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", @@ -7478,11 +6110,6 @@ } } }, - "wildcard": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", - "integrity": "sha1-pwIEUwhNjNLv5wup02liY94XEKU=" - }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -7641,165 +6268,6 @@ } } }, - "yargs-unparser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", - "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.11", - "yargs": "^12.0.5" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, "yauzl": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", @@ -7808,50 +6276,6 @@ "requires": { "fd-slicer": "~1.0.1" } - }, - "zip-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", - "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", - "dev": true, - "requires": { - "archiver-utils": "^1.3.0", - "compress-commons": "^1.2.0", - "lodash": "^4.8.0", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } } } } diff --git a/package.json b/package.json index c230437d..f4946bbd 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ "main": "src/main.js", "bin": "./src/main.js", "scripts": { - "test-unit": "NODE_ENV=test mocha 'tests/unit-tests/*.js'", "start": "electron .", "dist:mac": "node ./build.js -o 'mac' -p 'dmg'", "dist:win": "node ./build.js -o \"win\" -p \"exe\"", @@ -33,16 +32,9 @@ "dist:linux:snap": "snapcraft cleanbuild" }, "devDependencies": { - "ajv": "^6.10.2", - "chai": "^3.5.0", - "chai-as-promised": "^6.0.0", "electron": "^1.8.8", "electron-builder": "^20.36.2", "electron-packager": "^12.2.0", - "istanbul": "^0.4.5", - "mocha": "^6.2.0", - "sinon": "^1.17.7", - "spectron": "^3.6.0", "unzipper": "^0.9.4" }, "dependencies": { @@ -50,15 +42,11 @@ "download": "^7.1.0", "popper.js": "^1.14.3", "checksum": "^0.1.1", - "command-exists": "^1.2.2", "commander": "^2.9.0", "electron-open-link-in-browser": "^1.0.2", "electron-pug": "^1.5.1", - "executable": "^4.1.0", - "forward-emitter": "^0.1.1", "fs-extra": "^2.0.0", "getos": "^3.0.1", - "ini": "^1.3.4", "jquery": "^3.1.1", "jquery-i18next": "^1.2.0", "mkdirp": "^0.5.1", @@ -66,8 +54,6 @@ "request": "^2.79.0", "system-image-node-module": "^1.0.9", "ubports-api-node-module": "^1.0.2", - "tmp": "0.0.31", - "wildcard": "^1.1.2", "winston": "^2.3.1" } } diff --git a/src/devices.js b/src/devices.js index ed6d32ce..8990a1c7 100644 --- a/src/devices.js +++ b/src/devices.js @@ -246,7 +246,6 @@ module.exports = { }).catch((e) => { utils.log.error(e); global.mainEvent.emit("user:no-network"); }); } else { mainEvent.emit("user:device-unsupported", device); // If there is no response, the device is not supported - // ipcRenderer.send("setInstallProperties", { device: device }); return; } }).catch(((e) => { utils.errorToUser(e, "Device Select"); })); diff --git a/src/system-image.js b/src/system-image.js index 58cf5aa7..e0685798 100644 --- a/src/system-image.js +++ b/src/system-image.js @@ -8,17 +8,11 @@ Author: Marius Gripsgard */ -const fs = require("fs"); const utils = require("./utils"); -const path = require("path"); -const mkdirp = require('mkdirp'); const systemImageClient = require("system-image-node-module").Client; const systemImage = new systemImageClient({path: utils.getUbuntuTouchDir()}); -const ubuntuCommandFile = "ubuntu_command"; -const ubuntuPushDir = "/cache/recovery/" - const getDeviceChannels = (device) => { return systemImage.getDeviceChannels(device); } diff --git a/src/utils.js b/src/utils.js index d5300a5b..65e0a404 100644 --- a/src/utils.js +++ b/src/utils.js @@ -13,16 +13,10 @@ const fs = require("fs-extra"); const path = require("path"); const checksum = require('checksum'); const mkdirp = require('mkdirp'); -const tmp = require('tmp'); -const exec = require('child_process').exec; const cp = require('child_process'); const winston = require('winston'); const getos = require('getos'); -const commandExistsSync = require('command-exists').sync; -const remote = require('electron').remote; -var ipcRenderer = require('electron').ipcRenderer; -global.installProperties = remote ? remote.getGlobal('installProperties') : undefined; -global.packageInfo = remote ? remote.getGlobal('packageInfo') : require('../package.json'); +global.packageInfo = require('../package.json'); const platforms = { "linux": "linux", @@ -307,6 +301,5 @@ module.exports = { createBugReport: createBugReport, getUpdateAvailable: getUpdateAvailable, die: die, - ipcRenderer: ipcRenderer, setLogLevel: (level) => { winston.level = level; } } From 0e3f92bf8a770893e8cd2f707f53fb6a34687543 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 23:02:46 +0200 Subject: [PATCH 42/47] Update adb and fastboot lib --- package-lock.json | 296 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 150 insertions(+), 148 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9e92fe72..89169279 100644 --- a/package-lock.json +++ b/package-lock.json @@ -939,6 +939,27 @@ "lazy-cache": "^1.0.3" } }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "requires": { + "check-error": "^1.0.2" + } + }, "chainsaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", @@ -3749,6 +3770,61 @@ } } }, + "mocha": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -4443,9 +4519,9 @@ } }, "promise-android-tools": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-android-tools/-/promise-android-tools-1.0.1.tgz", - "integrity": "sha512-l0TawmYm3ucXtvRT7GZzMxgCkj/yOPyBnG2vaZA5Xq/Xx7W60l5NTMEwZYjAbqCjtnEMV/WhBlX7TJoQlRWzMQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promise-android-tools/-/promise-android-tools-1.0.2.tgz", + "integrity": "sha512-14jRUvTB7BvCuLp+XE7VNKJtmbQ4a2hbbkpb+WwfI7wIWdkBDbfb1cWbeZjbqMaA6bTW+AfJLLrAzHJGfwp0Jg==", "requires": { "chai": "^4.1.2", "chai-as-promised": "^7.1.1", @@ -4456,154 +4532,10 @@ "sinon-chai": "^3.3.0" }, "dependencies": { - "@sinonjs/formatio": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", - "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } - }, - "@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "requires": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" - } - }, - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", - "requires": { - "check-error": "^1.0.2" - } - }, - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "lolex": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", - "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==" - }, - "mocha": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.11.0", - "debug": "3.1.0", - "diff": "3.3.1", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.3", - "he": "1.1.1", - "mkdirp": "0.5.1", - "supports-color": "4.4.0" - } - }, - "nise": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz", - "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==", - "requires": { - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^4.1.0", - "path-to-regexp": "^1.7.0" - } - }, - "sinon": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", - "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", - "requires": { - "@sinonjs/commons": "^1.4.0", - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/samsam": "^3.3.3", - "diff": "^3.5.0", - "lolex": "^4.2.0", - "nise": "^1.5.2", - "supports-color": "^5.5.0" - }, - "dependencies": { - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "sinon-chai": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.3.0.tgz", "integrity": "sha512-r2JhDY7gbbmh5z3Q62pNbrjxZdOAjpsqW/8yxAZRSqLZqowmfGZPGUZPFf3UX36NLis0cv8VEM5IJh9HgkSOAA==" - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "requires": { - "has-flag": "^2.0.0" - } } } }, @@ -5127,6 +5059,76 @@ "string-width": "^1.0.1" } }, + "sinon": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", + "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.3", + "diff": "^3.5.0", + "lolex": "^4.2.0", + "nise": "^1.5.2", + "supports-color": "^5.5.0" + }, + "dependencies": { + "@sinonjs/formatio": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", + "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "requires": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "lolex": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==" + }, + "nise": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz", + "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==", + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^4.1.0", + "path-to-regexp": "^1.7.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "sinon-chai": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.14.0.tgz", diff --git a/package.json b/package.json index f4946bbd..5dfe145e 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "jquery": "^3.1.1", "jquery-i18next": "^1.2.0", "mkdirp": "^0.5.1", - "promise-android-tools": "^1.0.1", + "promise-android-tools": "^1.0.2", "request": "^2.79.0", "system-image-node-module": "^1.0.9", "ubports-api-node-module": "^1.0.2", From a0958ca9696a17f85e3c7c098a1a462997c5411e Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Thu, 3 Oct 2019 23:17:00 +0200 Subject: [PATCH 43/47] Bump version --- package-lock.json | 2 +- package.json | 2 +- src/html/scripts/main.pug | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 89169279..e4672a98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ubports-installer", - "version": "0.3.0-beta", + "version": "0.3.1-beta", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5dfe145e..29c4b7de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ubports-installer", - "version": "0.3.0-beta", + "version": "0.3.1-beta", "description": "The easy way to install Ubuntu Touch on UBports devices. A friendly cross-platform Installer for Ubuntu Touch. Just connect a supported device to your PC, follow the on-screen instructions and watch this awesome tool do all the rest.", "keywords": [ "Ubuntu", diff --git a/src/html/scripts/main.pug b/src/html/scripts/main.pug index ec73936f..13ba5f05 100644 --- a/src/html/scripts/main.pug +++ b/src/html/scripts/main.pug @@ -105,7 +105,6 @@ script. }); ipcRenderer.on("device:select:data-ready", (event, output, device, channels, ubuntuCom, autoDetected, isLegacyAndroid) => { - console.log("yep") views.show("install"); $("#options-channel").append(channels); options.optionsValToUser(); From 4f17eb08babbda1518342a6d93a1efd7c536e1b4 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 5 Oct 2019 14:41:27 +0200 Subject: [PATCH 44/47] Fix a few typos --- src/html/modals/error.pug | 2 +- src/html/modals/install.pug | 2 +- src/html/modals/oem-lock.pug | 2 +- src/html/modals/windows-drivers.pug | 2 +- src/html/views/done.pug | 2 +- src/html/views/not-supported.pug | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/html/modals/error.pug b/src/html/modals/error.pug index eda4e203..352651f5 100644 --- a/src/html/modals/error.pug +++ b/src/html/modals/error.pug @@ -8,7 +8,7 @@ .modal-body p The Installation stopped due to a problem. You can choose to ignore this, or re-start the installation process. p If this continues to happen, please check if you are affected by #[a(onclick="shell.openExternal('https://github.com/ubports/ubports-installer/issues')") a known bug]. - p If your problem is not yet known, klick the button below to report a new bug. + p If your problem is not yet known, click the button below to report a new bug. pre#error-body. \n p#not-latest-stable(hidden='hidden') You are not using the latest stable version of the UBports Installer. diff --git a/src/html/modals/install.pug b/src/html/modals/install.pug index 16dd89fe..8759a5ee 100644 --- a/src/html/modals/install.pug +++ b/src/html/modals/install.pug @@ -10,7 +10,7 @@ .modal-install-body-no-wipe p b NOTE - | : Installing may in rare cases lead to data loss + | : Installing may in rare cases lead to data loss. p b NOTE ANDROID | : Please note you won't be able to access your Android data and/or apps in Ubuntu Touch. diff --git a/src/html/modals/oem-lock.pug b/src/html/modals/oem-lock.pug index f1a05cd9..fa8765ea 100644 --- a/src/html/modals/oem-lock.pug +++ b/src/html/modals/oem-lock.pug @@ -9,7 +9,7 @@ p | Your device is oem locked, that means installation of third party operating systems like Ubuntu Touch is disabled. b - | Removing the OEM-lock might void your devices warranty. If you want to be sure, please ask your manufacturer or vendor if they allow this. UBports is not responsible and won't replace devices in case of warranty loss. You are responsible for your own actions. + | Removing the OEM-lock might void your device's warranty. If you want to be sure, please ask your manufacturer or vendor if they allow this. UBports is not responsible and won't replace devices in case of warranty loss. You are responsible for your own actions. p | Do you want to unlock your device now? p diff --git a/src/html/modals/windows-drivers.pug b/src/html/modals/windows-drivers.pug index 771de5db..11596f60 100644 --- a/src/html/modals/windows-drivers.pug +++ b/src/html/modals/windows-drivers.pug @@ -10,7 +10,7 @@ | You need to install the #[a(onclick="shell.openExternal('https://adb.clockworkmod.com/')") Universal ADB driver] and re-start the program to continue with the installation. | If you have already installed adb drivers, you can dismiss this message and simply continue with the installation. br - | If installer still does not detect you device, you might want to try installing #[a(onclick="shell.openExternal('https://developer.android.com/studio/releases/')") Android Studio] from Google. After that, you can specify custom adb and fastboot tools in the options in the next step. + | If installer still does not detect your device, you might want to try installing #[a(onclick="shell.openExternal('https://developer.android.com/studio/releases/')") Android Studio] from Google. After that, you can specify custom adb and fastboot tools in the options in the next step. br | Please note that the UBports Installer is still somewhat unstable on Windows. If the installation does not work on this machine and you have access to a Linux computer, you might want to try your luck there. br diff --git a/src/html/views/done.pug b/src/html/views/done.pug index 5a8f50d2..813bbeaf 100644 --- a/src/html/views/done.pug +++ b/src/html/views/done.pug @@ -7,7 +7,7 @@ p | The installation process from the computer is done. The device will now perform the remaining steps which should take less than five minutes. After the installation, the device will reboot and you can begin to explore Ubuntu Touch. p - | Found something you don't like? #[a(onclick="shell.openExternal('https://github.com/ubports/ubports-touch')") tell us], or help us change it! + | Found something you don't like? #[a(onclick="shell.openExternal('https://github.com/ubports/ubports-touch')") Tell us], or help us change it! p | Development of Ubuntu Touch is driven by the #[a(onclick="shell.openExternal('https://ubports.com')") UBports Community]. Donate now to allow us to continue our mission! button.btn.btn-default(type='button', style='width: 49%; margin-bottom: 10px; margin-right: 5px', onclick="shell.openExternal('https://ubports.com/get-involved')") Get involved diff --git a/src/html/views/not-supported.pug b/src/html/views/not-supported.pug index 85cde80f..7ca068da 100644 --- a/src/html/views/not-supported.pug +++ b/src/html/views/not-supported.pug @@ -17,5 +17,5 @@ hr h4(style='font-weight: bold;') You want to try to install anyway? p - | You can try selecting your device manualy, but please only do so if you're sure that your exact model is actually supported! You might also want to #[a(onclick="shell.openExternal('http://devices.ubuntu-touch.io')") file a bug]. + | You can try selecting your device manually, but please only do so if you're sure that your exact model is actually supported! You might also want to #[a(onclick="shell.openExternal('http://devices.ubuntu-touch.io')") file a bug]. button#btn-modal-select-device-unsupported.btn.btn-default(type='button', style='width: 100%;') Select device manually From 02a4d51876c5d0702d6a6fb51700ef167bc28041 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 5 Oct 2019 15:50:08 +0200 Subject: [PATCH 45/47] Fix image paths, resolves #904, resolves #903. --- src/devices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices.js b/src/devices.js index 8990a1c7..a1da1b1f 100644 --- a/src/devices.js +++ b/src/devices.js @@ -112,7 +112,7 @@ function addPathToImages(images, device) { images.forEach((image) => { image["partition"] = image.type; image["path"] = path.join(downloadPath, "images", device); - image["file"] = path.join(downloadPath, "images", device, image.type + "-" + device + ".img"); + image["file"] = path.join(downloadPath, "images", device, path.basename(image.url)); ret.push(image); }); return ret; From 14f98209fc4084f2436d7202d8b17d1b4b9cccb5 Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 5 Oct 2019 15:52:51 +0200 Subject: [PATCH 46/47] Add license headers to js files --- src/devices.js | 21 +++++++++++++++------ src/main.js | 21 +++++++++++++++------ src/system-image.js | 21 +++++++++++++++------ src/utils.js | 21 +++++++++++++++------ 4 files changed, 60 insertions(+), 24 deletions(-) diff --git a/src/devices.js b/src/devices.js index a1da1b1f..6f8b7e3d 100644 --- a/src/devices.js +++ b/src/devices.js @@ -1,12 +1,21 @@ "use strict"; /* - -This file is a part of ubports-installer - -Author: Marius Gripsgard - -*/ + * Copyright (C) 2017-2019 UBports Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ const http = require("request"); const ubportsApi = require("ubports-api-node-module"); diff --git a/src/main.js b/src/main.js index f9246e4e..c6f3aca6 100755 --- a/src/main.js +++ b/src/main.js @@ -1,12 +1,21 @@ "use strict"; /* - -This file is a part of ubports-installer - -Author: Marius Gripsgard - -*/ + * Copyright (C) 2017-2019 UBports Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ const cli = require("commander"); const electron = require('electron'); diff --git a/src/system-image.js b/src/system-image.js index e0685798..b51fc791 100644 --- a/src/system-image.js +++ b/src/system-image.js @@ -1,12 +1,21 @@ "use strict"; /* - -This file is a part of ubports-installer - -Author: Marius Gripsgard - -*/ + * Copyright (C) 2017-2019 UBports Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ const utils = require("./utils"); const systemImageClient = require("system-image-node-module").Client; diff --git a/src/utils.js b/src/utils.js index 65e0a404..a7be29b3 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,10 +1,19 @@ /* - -This file is a part of ubports-installer - -Author: Marius Gripsgard - -*/ + * Copyright (C) 2017-2019 UBports Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ const http = require("request"); const download = require("download"); From a4644ce92a24f7685f0ad544b34f8e91680963be Mon Sep 17 00:00:00 2001 From: Jan Sprinz Date: Sat, 5 Oct 2019 15:53:46 +0200 Subject: [PATCH 47/47] Bump version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index e4672a98..5208f11c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ubports-installer", - "version": "0.3.1-beta", + "version": "0.3.2-beta", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 29c4b7de..d6947a76 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ubports-installer", - "version": "0.3.1-beta", + "version": "0.3.2-beta", "description": "The easy way to install Ubuntu Touch on UBports devices. A friendly cross-platform Installer for Ubuntu Touch. Just connect a supported device to your PC, follow the on-screen instructions and watch this awesome tool do all the rest.", "keywords": [ "Ubuntu",