diff --git a/.prettierrc.json b/.prettierrc.json index 5769097..a8f118f 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,7 +1,7 @@ { - "tabWidth": 2, - "useTabs": false, - "semi": false, - "singleQuote": true, - "trailingComma": "es5" + "tabWidth": 2, + "useTabs": false, + "semi": false, + "singleQuote": true, + "trailingComma": "es5" } diff --git a/README.md b/README.md index c186a2d..6f05359 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # melon + 🍉 Build Firefox-based browsers with ease diff --git a/package.json b/package.json index 32feb95..1c564d7 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build": "tsc" + "build": "tsc", + "format": "prettier . -w" }, "repository": { "type": "git", diff --git a/src/cmds.ts b/src/cmds.ts index 6809a31..0aef256 100644 --- a/src/cmds.ts +++ b/src/cmds.ts @@ -1,161 +1,148 @@ import { - bootstrap, - build, - discard, - download, - downloadArtifacts, - execute, - exportFile, - exportPatches, - fixLineEndings, - importPatches, - init, - licenseCheck, - melonPackage, - reset, - run, - setBranch, - status, - test -} from "./commands"; -import { Cmd } from "./types"; + bootstrap, + build, + discard, + download, + downloadArtifacts, + execute, + exportFile, + exportPatches, + fixLineEndings, + importPatches, + init, + licenseCheck, + melonPackage, + reset, + run, + setBranch, + status, + test, +} from './commands' +import { Cmd } from './types' export const commands: Cmd[] = [ - { - cmd: "bootstrap", - description: "Bootstrap Dot Browser.", - controller: bootstrap + { + cmd: 'bootstrap', + description: 'Bootstrap Dot Browser.', + controller: bootstrap, + }, + { + cmd: 'build [os]', + aliases: ['b'], + description: + 'Build Dot Browser. Specify the OS param for cross-platform builds.', + options: [ + { + arg: '--a, --arch ', + description: 'Specify architecture for build', + }, + ], + controller: build, + }, + { + cmd: 'discard ', + description: 'Discard a files changes.', + options: [ + { + arg: '--keep, --keep-patch', + description: 'Keep the patch file instead of removing it', + }, + ], + controller: discard, + }, + { + cmd: 'download [ffVersion]', + description: 'Download Firefox.', + controller: download, + }, + { + cmd: 'download-artifacts', + description: 'Download Windows artifacts from GitHub.', + flags: { + platforms: ['win32'], }, - { - cmd: "build [os]", - aliases: ["b"], - description: - "Build Dot Browser. Specify the OS param for cross-platform builds.", - options: [ - { - arg: "--a, --arch ", - description: - "Specify architecture for build" - } - ], - controller: build - }, - { - cmd: "discard ", - description: "Discard a files changes.", - options: [ - { - arg: "--keep, --keep-patch", - description: - "Keep the patch file instead of removing it" - } - ], - controller: discard - }, - { - cmd: "download [ffVersion]", - description: "Download Firefox.", - controller: download - }, - { - cmd: "download-artifacts", - description: - "Download Windows artifacts from GitHub.", - flags: { - platforms: ["win32"] - }, - controller: downloadArtifacts - }, - { - cmd: "execute", - description: - "Execute a command inside the engine directory.", - controller: execute - }, - { - cmd: "export-file ", - description: "Export a changed file as a patch.", - controller: exportFile - }, - { - cmd: "export", - aliases: ["export-patches"], - description: - "Export the changed files as patches.", - controller: exportPatches - }, - { - cmd: "lfify", - aliases: ["fix-le"], - description: - "Convert CRLF line endings to Unix LF line endings.", - controller: fixLineEndings - }, - { - cmd: "import [type]", - aliases: ["import-patches", "i"], - description: "Import patches into the browser.", - options: [ - { - arg: "-m, --minimal", - description: - "Import patches in minimal mode" - }, - { - arg: "--noignore", - description: - "Bypass .gitignore. You shouldn't really use this." - } - ], - controller: importPatches - }, - { - cmd: "init ", - aliases: ["initialise", "initialize"], - description: "Initialise the Firefox directory.", - controller: init - }, - { - cmd: "license-check", - aliases: ["lc"], - description: - "Check the src directory for the absence of MPL-2.0 header.", - controller: licenseCheck - }, - { - cmd: "package", - aliases: ["pack"], - description: - "Package the browser for distribution.", - controller: melonPackage - }, - { - cmd: "reset", - description: - "Reset the source directory to stock Firefox.", - controller: reset - }, - { - cmd: "run [chrome]", - aliases: ["r", "open"], - description: "Run the browser.", - controller: run - }, - { - cmd: "set-branch ", - description: "Change the default branch.", - controller: setBranch - }, - { - cmd: "status", - description: - "Status and files changed for src directory.", - controller: status - }, - { - cmd: "test", - description: - "Run the test suite for Dot Browser.", - controller: test - } -]; + controller: downloadArtifacts, + }, + { + cmd: 'execute', + description: 'Execute a command inside the engine directory.', + controller: execute, + }, + { + cmd: 'export-file ', + description: 'Export a changed file as a patch.', + controller: exportFile, + }, + { + cmd: 'export', + aliases: ['export-patches'], + description: 'Export the changed files as patches.', + controller: exportPatches, + }, + { + cmd: 'lfify', + aliases: ['fix-le'], + description: 'Convert CRLF line endings to Unix LF line endings.', + controller: fixLineEndings, + }, + { + cmd: 'import [type]', + aliases: ['import-patches', 'i'], + description: 'Import patches into the browser.', + options: [ + { + arg: '-m, --minimal', + description: 'Import patches in minimal mode', + }, + { + arg: '--noignore', + description: "Bypass .gitignore. You shouldn't really use this.", + }, + ], + controller: importPatches, + }, + { + cmd: 'init ', + aliases: ['initialise', 'initialize'], + description: 'Initialise the Firefox directory.', + controller: init, + }, + { + cmd: 'license-check', + aliases: ['lc'], + description: 'Check the src directory for the absence of MPL-2.0 header.', + controller: licenseCheck, + }, + { + cmd: 'package', + aliases: ['pack'], + description: 'Package the browser for distribution.', + controller: melonPackage, + }, + { + cmd: 'reset', + description: 'Reset the source directory to stock Firefox.', + controller: reset, + }, + { + cmd: 'run [chrome]', + aliases: ['r', 'open'], + description: 'Run the browser.', + controller: run, + }, + { + cmd: 'set-branch ', + description: 'Change the default branch.', + controller: setBranch, + }, + { + cmd: 'status', + description: 'Status and files changed for src directory.', + controller: status, + }, + { + cmd: 'test', + description: 'Run the test suite for Dot Browser.', + controller: test, + }, +] diff --git a/src/commands/bootstrap.ts b/src/commands/bootstrap.ts index ef946c7..bb68457 100644 --- a/src/commands/bootstrap.ts +++ b/src/commands/bootstrap.ts @@ -1,89 +1,81 @@ /// -import distro from "linus"; -import { bin_name } from ".."; -import { log } from "../"; -import { ENGINE_DIR } from "../constants"; -import { dispatch } from "../utils"; -import { pacmanInstall } from "./bootstrap/arch"; +import distro from 'linus' +import { bin_name } from '..' +import { log } from '../' +import { ENGINE_DIR } from '../constants' +import { dispatch } from '../utils' +import { pacmanInstall } from './bootstrap/arch' export const bootstrap = async () => { - if (process.platform == "win32") - log.error( - `You do not need to bootstrap on Windows. As long as you ran |${bin_name} download-artifacts| everything should work fine.` - ); + if (process.platform == 'win32') + log.error( + `You do not need to bootstrap on Windows. As long as you ran |${bin_name} download-artifacts| everything should work fine.` + ) - log.info(`Bootstrapping Dot Browser for Desktop...`); + log.info(`Bootstrapping Dot Browser for Desktop...`) - const args = ["--application-choice", "browser"]; + const args = ['--application-choice', 'browser'] - if (process.platform === "linux") { - linuxBootstrap(); - } else { - console.info( - `Custom bootstrapping doesn't work on ${process.platform}. Consider contributing to improve support` - ); + if (process.platform === 'linux') { + linuxBootstrap() + } else { + console.info( + `Custom bootstrapping doesn't work on ${process.platform}. Consider contributing to improve support` + ) - console.info( - `Passing through to |mach bootstrap|` - ); + console.info(`Passing through to |mach bootstrap|`) - await dispatch( - `./mach`, - ["bootstrap", ...args], - ENGINE_DIR - ); - } -}; + await dispatch(`./mach`, ['bootstrap', ...args], ENGINE_DIR) + } +} function getDistro(): Promise { - return new Promise((resolve, reject) => { - distro.name((err: Error, name: string) => { - if (name) resolve(name); - else { - reject( - err || "Failed to get linux distro" - ); - } - }); - }); + return new Promise((resolve, reject) => { + distro.name((err: Error, name: string) => { + if (name) resolve(name) + else { + reject(err || 'Failed to get linux distro') + } + }) + }) } async function linuxBootstrap() { - const distro = await getDistro(); + const distro = await getDistro() - switch (distro) { - // Both arch and manjaro use the same package repo and the same package manager - case "ManjaroLinux": - case "ArchLinux": - console.log( - await pacmanInstall( - // Shared packages - "base-devel", - "nodejs", - "unzip", - "zip", + switch (distro) { + // Both arch and manjaro use the same package repo and the same package manager + case 'ManjaroLinux': + case 'ArchLinux': + console.log( + await pacmanInstall( + // Shared packages + 'base-devel', + 'nodejs', + 'unzip', + 'zip', - // Needed for desktop apps - "alsa-lib", - "dbus-glib", - "gtk3", - "libevent", - "libvpx", - "libxt", - "mime-types", - "nasm", - "startup-notification", - "gst-plugins-base-libs", - "libpulse", - "xorg-server-xvfb", - "gst-libav", - "gst-plugins-good" - ) - ); - break; + // Needed for desktop apps + 'alsa-lib', + 'dbus-glib', + 'gtk3', + 'libevent', + 'libvpx', + 'libxt', + 'mime-types', + 'nasm', + 'startup-notification', + 'gst-plugins-base-libs', + 'libpulse', + 'xorg-server-xvfb', + 'gst-libav', + 'gst-plugins-good' + ) + ) + break - default: - log.error(`Unimplemented distro '${distro}'`); - } + default: + log.error(`Unimplemented distro '${distro}'`) + } } diff --git a/src/commands/bootstrap/arch.ts b/src/commands/bootstrap/arch.ts index ee991dc..e2192ce 100644 --- a/src/commands/bootstrap/arch.ts +++ b/src/commands/bootstrap/arch.ts @@ -1,14 +1,6 @@ -import execa from "execa"; +import execa from 'execa' -export async function pacmanInstall( - ...packages: string[] -): Promise { - return ( - await execa("sudo", [ - "pacman", - "--noconfirm", - "-S", - ...packages - ]) - ).stdout; +export async function pacmanInstall(...packages: string[]): Promise { + return (await execa('sudo', ['pacman', '--noconfirm', '-S', ...packages])) + .stdout } diff --git a/src/commands/build.ts b/src/commands/build.ts index 3fdf0dd..90f2593 100644 --- a/src/commands/build.ts +++ b/src/commands/build.ts @@ -1,187 +1,129 @@ -import execa from "execa"; +import execa from 'execa' +import { existsSync, readFileSync, writeFileSync } from 'fs' +import { join, resolve } from 'path' +import { bin_name, log } from '..' import { - existsSync, - readFileSync, - writeFileSync -} from "fs"; -import { join, resolve } from "path"; -import { bin_name, log } from ".."; -import { - ARCHITECTURE, - BUILD_TARGETS, - CONFIGS_DIR, - ENGINE_DIR -} from "../constants"; -import { dispatch } from "../utils"; + ARCHITECTURE, + BUILD_TARGETS, + CONFIGS_DIR, + ENGINE_DIR, +} from '../constants' +import { dispatch } from '../utils' const platform: any = { - win32: "windows", - darwin: "macos", - linux: "linux" -}; - -const applyConfig = async (os: string, arch: string) => { - log.info("Applying mozconfig..."); - - let commonConfig = readFileSync( - resolve(CONFIGS_DIR, "common", "mozconfig"), - "utf-8" - ); - - const changesetPrefix = commonConfig - .split("\n") - .find((ln) => - ln.startsWith("export MOZ_SOURCE_CHANGESET=") - ); - - const changeset = changesetPrefix?.replace( - /export MOZ_SOURCE_CHANGESET=/, - "" - ); - - const { stdout: gitSha } = await execa("git", [ - "rev-parse", - "HEAD" - ]); - - console.log(changeset, gitSha); - - if (changeset) - commonConfig = commonConfig.replace( - changeset, - gitSha - ); - - writeFileSync( - resolve(CONFIGS_DIR, "common", "mozconfig"), - commonConfig - ); - - const osConfig = readFileSync( - resolve( - CONFIGS_DIR, - os, - arch === "i686" - ? "mozconfig-i686" - : "mozconfig" - ), - "utf-8" - ); - - // Allow a custom config to be placed in /mozconfig. This will not be committed - // to origin - const customConfig = existsSync( - join(process.cwd(), "mozconfig") - ) - ? readFileSync( - join(process.cwd(), "mozconfig") - ).toString() - : ""; - - const mergedConfig = `# This file is automatically generated. You should only modify this if you know what you are doing!\n\n${commonConfig}\n\n${osConfig}\n\n${customConfig}`; - - writeFileSync( - resolve(ENGINE_DIR, "mozconfig"), - mergedConfig - ); - - log.info(`Config for this \`${os}\` build:`); - - mergedConfig.split("\n").map((ln) => { - if ( - ln.startsWith("mk") || - ln.startsWith("ac") || - ln.startsWith("export") - ) - log.info( - `\t${ln - .replace(/mk_add_options /, "") - .replace(/ac_add_options /, "") - .replace(/export /, "")}` - ); - }); -}; - -const genericBuild = async (os: string, tier: string) => { - log.info(`Building for "${os}"...`); - - log.warning( - `If you get any dependency errors, try running |${bin_name} bootstrap|.` - ); - - await dispatch( - `./mach`, - ["build"].concat(tier ? [tier] : []), - ENGINE_DIR - ); -}; - -const parseDate = (d: number) => { - d = d / 1000; - var h = Math.floor(d / 3600); - var m = Math.floor((d % 3600) / 60); - var s = Math.floor((d % 3600) % 60); - - var hDisplay = - h > 0 - ? h + (h == 1 ? " hour, " : " hours, ") - : ""; - var mDisplay = - m > 0 - ? m + (m == 1 ? " minute, " : " minutes, ") - : ""; - var sDisplay = - s > 0 - ? s + (s == 1 ? " second" : " seconds") - : ""; - return hDisplay + mDisplay + sDisplay; -}; - -const success = (date: number) => { - // mach handles the success messages - console.log(); - log.info( - `Total build time: ${parseDate( - Date.now() - date - )}.` - ); -}; - -interface Options { - arch: string; + win32: 'windows', + darwin: 'macos', + linux: 'linux', } -export const build = async ( - tier: string, - options: Options -) => { - let d = Date.now(); +const applyConfig = async (os: string, arch: string) => { + log.info('Applying mozconfig...') - // Host build + let commonConfig = readFileSync( + resolve(CONFIGS_DIR, 'common', 'mozconfig'), + 'utf-8' + ) - const prettyHost = platform[process.platform as any]; + const changesetPrefix = commonConfig + .split('\n') + .find((ln) => ln.startsWith('export MOZ_SOURCE_CHANGESET=')) - if (BUILD_TARGETS.includes(prettyHost)) { - let arch = "64bit"; + const changeset = changesetPrefix?.replace(/export MOZ_SOURCE_CHANGESET=/, '') - if (options.arch) { - if (!ARCHITECTURE.includes(options.arch)) - return log.error( - `We do not support "${ - options.arch - }" build right now.\nWe only currently support ${JSON.stringify( - ARCHITECTURE - )}.` - ); - else arch = options.arch; - } + const { stdout: gitSha } = await execa('git', ['rev-parse', 'HEAD']) - applyConfig(prettyHost, options.arch); + console.log(changeset, gitSha) - setTimeout(async () => { - await genericBuild(prettyHost, tier).then( - (_) => success(d) - ); - }, 2500); + if (changeset) commonConfig = commonConfig.replace(changeset, gitSha) + + writeFileSync(resolve(CONFIGS_DIR, 'common', 'mozconfig'), commonConfig) + + const osConfig = readFileSync( + resolve(CONFIGS_DIR, os, arch === 'i686' ? 'mozconfig-i686' : 'mozconfig'), + 'utf-8' + ) + + // Allow a custom config to be placed in /mozconfig. This will not be committed + // to origin + const customConfig = existsSync(join(process.cwd(), 'mozconfig')) + ? readFileSync(join(process.cwd(), 'mozconfig')).toString() + : '' + + const mergedConfig = `# This file is automatically generated. You should only modify this if you know what you are doing!\n\n${commonConfig}\n\n${osConfig}\n\n${customConfig}` + + writeFileSync(resolve(ENGINE_DIR, 'mozconfig'), mergedConfig) + + log.info(`Config for this \`${os}\` build:`) + + mergedConfig.split('\n').map((ln) => { + if (ln.startsWith('mk') || ln.startsWith('ac') || ln.startsWith('export')) + log.info( + `\t${ln + .replace(/mk_add_options /, '') + .replace(/ac_add_options /, '') + .replace(/export /, '')}` + ) + }) +} + +const genericBuild = async (os: string, tier: string) => { + log.info(`Building for "${os}"...`) + + log.warning( + `If you get any dependency errors, try running |${bin_name} bootstrap|.` + ) + + await dispatch(`./mach`, ['build'].concat(tier ? [tier] : []), ENGINE_DIR) +} + +const parseDate = (d: number) => { + d = d / 1000 + var h = Math.floor(d / 3600) + var m = Math.floor((d % 3600) / 60) + var s = Math.floor((d % 3600) % 60) + + var hDisplay = h > 0 ? h + (h == 1 ? ' hour, ' : ' hours, ') : '' + var mDisplay = m > 0 ? m + (m == 1 ? ' minute, ' : ' minutes, ') : '' + var sDisplay = s > 0 ? s + (s == 1 ? ' second' : ' seconds') : '' + return hDisplay + mDisplay + sDisplay +} + +const success = (date: number) => { + // mach handles the success messages + console.log() + log.info(`Total build time: ${parseDate(Date.now() - date)}.`) +} + +interface Options { + arch: string +} + +export const build = async (tier: string, options: Options) => { + let d = Date.now() + + // Host build + + const prettyHost = platform[process.platform as any] + + if (BUILD_TARGETS.includes(prettyHost)) { + let arch = '64bit' + + if (options.arch) { + if (!ARCHITECTURE.includes(options.arch)) + return log.error( + `We do not support "${ + options.arch + }" build right now.\nWe only currently support ${JSON.stringify( + ARCHITECTURE + )}.` + ) + else arch = options.arch } -}; + + applyConfig(prettyHost, options.arch) + + setTimeout(async () => { + await genericBuild(prettyHost, tier).then((_) => success(d)) + }, 2500) + } +} diff --git a/src/commands/discard.ts b/src/commands/discard.ts index 6471668..9cb2466 100644 --- a/src/commands/discard.ts +++ b/src/commands/discard.ts @@ -1,71 +1,61 @@ -import execa from "execa"; -import { existsSync, statSync } from "fs"; -import { resolve } from "path"; -import rimraf from "rimraf"; -import { log } from ".."; -import { ENGINE_DIR, PATCHES_DIR } from "../constants"; +import execa from 'execa' +import { existsSync, statSync } from 'fs' +import { resolve } from 'path' +import rimraf from 'rimraf' +import { log } from '..' +import { ENGINE_DIR, PATCHES_DIR } from '../constants' interface Options { - keep?: boolean; - fromRemote?: string; + keep?: boolean + fromRemote?: string } const remotes = { - ff: (file: string, version: string) => - `https://hg.mozilla.org/experimental/firefox-unified-stage/raw-file/FIREFOX_${version - .replace(" ", "_") - .replace(".", "_")}_RELEASE/${file}`, - dot: (file: string, ref: string) => - `https://raw.githubusercontent.com/dothq/browser-desktop/${ref}/${file}` -}; + ff: (file: string, version: string) => + `https://hg.mozilla.org/experimental/firefox-unified-stage/raw-file/FIREFOX_${version + .replace(' ', '_') + .replace('.', '_')}_RELEASE/${file}`, + dot: (file: string, ref: string) => + `https://raw.githubusercontent.com/dothq/browser-desktop/${ref}/${file}`, +} -export const discard = async ( - file: string, - options: Options -) => { - log.info(`Discarding ${file}...`); +export const discard = async (file: string, options: Options) => { + log.info(`Discarding ${file}...`) - if (!statSync(file).isFile()) - throw new Error("Target must be a file."); + if (!statSync(file).isFile()) throw new Error('Target must be a file.') - // @todo add remote discard - if (options.fromRemote) { - if ( - options.fromRemote == "ff" || - options.fromRemote == "firefox" - ) { - } else if (options.fromRemote == "dot") { - } else { - throw new Error( - "Unrecognised remote type. Expected `ff` or `dot`." - ); - } + // @todo add remote discard + if (options.fromRemote) { + if (options.fromRemote == 'ff' || options.fromRemote == 'firefox') { + } else if (options.fromRemote == 'dot') { } else { - if (!existsSync(resolve(ENGINE_DIR, file))) - throw new Error( - `File ${file} could not be found in src directory. Check the path for any mistakes and try again.` - ); - - const patchFile = resolve( - PATCHES_DIR, - file.replace(/\//g, "-").replace(/\./g, "-") + - ".patch" - ); - - if (!existsSync(patchFile)) - throw new Error( - `File ${file} does have an associated patch in the patches directory.` - ); - - const { stdout, exitCode } = await execa( - "git", - ["apply", "-R", "-p", "1", patchFile], - { cwd: ENGINE_DIR } - ); - - if (exitCode == 0) { - log.success(`Discarded changes to ${file}.`); - if (!options.keep) rimraf.sync(patchFile); - } else throw new Error(stdout); + throw new Error('Unrecognised remote type. Expected `ff` or `dot`.') } -}; + } else { + if (!existsSync(resolve(ENGINE_DIR, file))) + throw new Error( + `File ${file} could not be found in src directory. Check the path for any mistakes and try again.` + ) + + const patchFile = resolve( + PATCHES_DIR, + file.replace(/\//g, '-').replace(/\./g, '-') + '.patch' + ) + + if (!existsSync(patchFile)) + throw new Error( + `File ${file} does have an associated patch in the patches directory.` + ) + + const { stdout, exitCode } = await execa( + 'git', + ['apply', '-R', '-p', '1', patchFile], + { cwd: ENGINE_DIR } + ) + + if (exitCode == 0) { + log.success(`Discarded changes to ${file}.`) + if (!options.keep) rimraf.sync(patchFile) + } else throw new Error(stdout) + } +} diff --git a/src/commands/download-artifacts.ts b/src/commands/download-artifacts.ts index 66dea58..b9d3d37 100644 --- a/src/commands/download-artifacts.ts +++ b/src/commands/download-artifacts.ts @@ -1,81 +1,61 @@ -import axios from "axios"; -import execa from "execa"; -import fs from "fs"; -import { homedir } from "os"; -import { posix, resolve, sep } from "path"; -import { log } from ".."; +import axios from 'axios' +import execa from 'execa' +import fs from 'fs' +import { homedir } from 'os' +import { posix, resolve, sep } from 'path' +import { log } from '..' export const downloadArtifacts = async () => { - if (process.platform !== "win32") - return log.error( - "This is not a Windows machine, will not download artifacts." - ); - if (process.env.MOZILLABUILD) - return log.error( - "Run this command in Git Bash, it does not work in Mozilla Build." - ); + if (process.platform !== 'win32') + return log.error( + 'This is not a Windows machine, will not download artifacts.' + ) + if (process.env.MOZILLABUILD) + return log.error( + 'Run this command in Git Bash, it does not work in Mozilla Build.' + ) - const filename = "mozbuild.tar.bz2"; - const url = `https://github.com/dothq/windows-artifacts/releases/latest/download/mozbuild.tar.bz2`; - let home = homedir().split(sep).join(posix.sep); + const filename = 'mozbuild.tar.bz2' + const url = `https://github.com/dothq/windows-artifacts/releases/latest/download/mozbuild.tar.bz2` + let home = homedir().split(sep).join(posix.sep) - if (process.platform == "win32") { - home = - "/" + - home - .replace(/\:/, "") - .replace(/\\/g, "/") - .toLowerCase(); + if (process.platform == 'win32') { + home = '/' + home.replace(/\:/, '').replace(/\\/g, '/').toLowerCase() + } + + log.info(`Downloading Windows artifacts...`) + + const { data, headers } = await axios.get(url, { + responseType: 'stream', + }) + + const length = headers['content-length'] + + const writer = fs.createWriteStream(resolve(process.cwd(), filename)) + + let receivedBytes = 0 + + data.on('data', (chunk: any) => { + receivedBytes += chunk.length + + let rand = Math.floor(Math.random() * 1000 + 1) + + if (rand > 999.5) { + let percentCompleted = parseInt( + Math.round((receivedBytes * 100) / length).toFixed(0) + ) + if (percentCompleted % 2 == 0 || percentCompleted >= 100) return + log.info(`\t${filename}\t${percentCompleted}%...`) } + }) - log.info(`Downloading Windows artifacts...`); + data.pipe(writer) - const { data, headers } = await axios.get(url, { - responseType: "stream" - }); + data.on('end', async () => { + log.info('Unpacking mozbuild...') - const length = headers["content-length"]; + await execa('tar', ['-xvf', filename, '-C', home]) - const writer = fs.createWriteStream( - resolve(process.cwd(), filename) - ); - - let receivedBytes = 0; - - data.on("data", (chunk: any) => { - receivedBytes += chunk.length; - - let rand = Math.floor(Math.random() * 1000 + 1); - - if (rand > 999.5) { - let percentCompleted = parseInt( - Math.round( - (receivedBytes * 100) / length - ).toFixed(0) - ); - if ( - percentCompleted % 2 == 0 || - percentCompleted >= 100 - ) - return; - log.info( - `\t${filename}\t${percentCompleted}%...` - ); - } - }); - - data.pipe(writer); - - data.on("end", async () => { - log.info("Unpacking mozbuild..."); - - await execa("tar", [ - "-xvf", - filename, - "-C", - home - ]); - - log.info("Done extracting mozbuild artifacts."); - }); -}; + log.info('Done extracting mozbuild artifacts.') + }) +} diff --git a/src/commands/download.ts b/src/commands/download.ts index 3f8a5ff..79a3db7 100644 --- a/src/commands/download.ts +++ b/src/commands/download.ts @@ -1,269 +1,223 @@ -import axios from "axios"; -import chalk from "chalk"; -import execa from "execa"; -import fs, { - existsSync, - rmdirSync, - writeFileSync -} from "fs"; -import { ensureDirSync, removeSync } from "fs-extra"; -import ora from "ora"; -import { homedir } from "os"; -import { posix, resolve, sep } from "path"; -import { bin_name, log } from ".."; -import { ENGINE_DIR } from "../constants"; -import { getLatestFF, writeMetadata } from "../utils"; -import { downloadArtifacts } from "./download-artifacts"; +import axios from 'axios' +import chalk from 'chalk' +import execa from 'execa' +import fs, { existsSync, rmdirSync, writeFileSync } from 'fs' +import { ensureDirSync, removeSync } from 'fs-extra' +import ora from 'ora' +import { homedir } from 'os' +import { posix, resolve, sep } from 'path' +import { bin_name, log } from '..' +import { ENGINE_DIR } from '../constants' +import { getLatestFF, writeMetadata } from '../utils' +import { downloadArtifacts } from './download-artifacts' -const pjson = require("../../package.json"); +const pjson = require('../../package.json') -let initProgressText = "Initialising..."; +let initProgressText = 'Initialising...' let initProgress: any = ora({ - text: `Initialising...`, - prefixText: chalk.blueBright.bold("00:00:00"), - spinner: { - frames: [""] - }, - indent: 0 -}); + text: `Initialising...`, + prefixText: chalk.blueBright.bold('00:00:00'), + spinner: { + frames: [''], + }, + indent: 0, +}) const onData = (data: any) => { - const d = data.toString(); + const d = data.toString() - d.split("\n").forEach((line: any) => { - if (line.trim().length !== 0) { - let t = line.split(" "); - t.shift(); - initProgressText = t.join(" "); - } - }); -}; + d.split('\n').forEach((line: any) => { + if (line.trim().length !== 0) { + let t = line.split(' ') + t.shift() + initProgressText = t.join(' ') + } + }) +} const unpack = async (name: string, version: string) => { - let cwd = process.cwd().split(sep).join(posix.sep); + let cwd = process.cwd().split(sep).join(posix.sep) - if (process.platform == "win32") { - cwd = "./"; + if (process.platform == 'win32') { + cwd = './' + } + + initProgress.start() + + setInterval(() => { + if (initProgress) { + initProgress.text = initProgressText + initProgress.prefixText = chalk.blueBright.bold(log.getDiff()) } + }, 100) - initProgress.start(); + initProgressText = `Unpacking Firefox...` - setInterval(() => { - if (initProgress) { - initProgress.text = initProgressText; - initProgress.prefixText = - chalk.blueBright.bold(log.getDiff()); - } - }, 100); + try { + rmdirSync(ENGINE_DIR) + } catch (e) {} + ensureDirSync(ENGINE_DIR) - initProgressText = `Unpacking Firefox...`; + let tarProc = execa('tar', [ + '--transform', + 's,firefox-89.0,engine,', + `--show-transformed`, + '-xf', + resolve(cwd, '.dotbuild', 'engines', name), + ]) - try { - rmdirSync(ENGINE_DIR); - } catch (e) {} - ensureDirSync(ENGINE_DIR); + ;(tarProc.stdout as any).on('data', onData) + ;(tarProc.stdout as any).on('error', onData) - let tarProc = execa("tar", [ - "--transform", - "s,firefox-89.0,engine,", - `--show-transformed`, - "-xf", - resolve(cwd, ".dotbuild", "engines", name) - ]); + tarProc.on('exit', () => { + if (process.env.CI_SKIP_INIT) return log.info('Skipping initialisation.') - (tarProc.stdout as any).on("data", onData); - (tarProc.stdout as any).on("error", onData); + const initProc = execa(`./${bin_name}`, ['init', 'engine']) - tarProc.on("exit", () => { - if (process.env.CI_SKIP_INIT) - return log.info("Skipping initialisation."); + ;(initProc.stdout as any).on('data', onData) + ;(initProc.stdout as any).on('error', onData) - const initProc = execa(`./${bin_name}`, [ - "init", - "engine" - ]); + initProc.on('exit', async () => { + initProgressText = '' + initProgress.stop() + initProgress = null - (initProc.stdout as any).on("data", onData); - (initProc.stdout as any).on("error", onData); + await new Promise((resolve) => setTimeout(resolve, 5000)) - initProc.on("exit", async () => { - initProgressText = ""; - initProgress.stop(); - initProgress = null; + log.success( + `You should be ready to make changes to Dot Browser.\n\n\t You should import the patches next, run |${bin_name} import|.\n\t To begin building Dot, run |${bin_name} build|.` + ) + console.log() - await new Promise((resolve) => - setTimeout(resolve, 5000) - ); + pjson.versions['firefox-display'] = version + pjson.versions['firefox'] = version.split('b')[0] - log.success( - `You should be ready to make changes to Dot Browser.\n\n\t You should import the patches next, run |${bin_name} import|.\n\t To begin building Dot, run |${bin_name} build|.` - ); - console.log(); + writeFileSync( + resolve(process.cwd(), 'package.json'), + JSON.stringify(pjson, null, 4) + ) - pjson.versions["firefox-display"] = version; - pjson.versions["firefox"] = - version.split("b")[0]; + await writeMetadata() - writeFileSync( - resolve(process.cwd(), "package.json"), - JSON.stringify(pjson, null, 4) - ); + removeSync(resolve(cwd, '.dotbuild', 'engines', name)) - await writeMetadata(); + process.exit(0) + }) + }) +} - removeSync( - resolve(cwd, ".dotbuild", "engines", name) - ); - - process.exit(0); - }); - }); -}; - -export const download = async ( - firefoxVersion?: string -) => { - if (firefoxVersion) - log.warning( - `A custom Firefox version is being used. Some features of Dot may not work as expected.` - ); - - if (!firefoxVersion) { - firefoxVersion = - pjson.versions["firefox-display"]; - } - - let version = await getLatestFF(); - - if (firefoxVersion) { - version = firefoxVersion; - } - - const base = `https://archive.mozilla.org/pub/firefox/releases/${version}/source/`; - const filename = `firefox-${version}.source.tar.xz`; - - const url = `${base}${filename}`; - - log.info(`Locating Firefox release ${version}...`); - - ensureDirSync( - resolve(process.cwd(), `.dotbuild`, `engines`) - ); - - if ( - existsSync( - resolve( - process.cwd(), - `.dotbuild`, - `engines`, - `firefox-${version.split("b")[0]}` - ) - ) - ) { - log.error( - `Cannot download version ${ - version.split("b")[0] - } as it already exists at "${resolve( - process.cwd(), - `firefox-${version.split("b")[0]}` - )}"` - ); - } - - if (version == firefoxVersion) - log.info( - `Version is frozen at ${firefoxVersion}!` - ); - if (version.includes("b")) - log.warning( - "Version includes non-numeric characters. This is probably a beta." - ); - - if ( - fs.existsSync( - resolve( - process.cwd(), - `.dotbuild`, - `engines`, - "firefox", - version.split("b")[0] - ) - ) || - fs.existsSync( - resolve( - process.cwd(), - "firefox", - "firefox-" + version.split("b")[0] - ) - ) +export const download = async (firefoxVersion?: string) => { + if (firefoxVersion) + log.warning( + `A custom Firefox version is being used. Some features of Dot may not work as expected.` ) - log.error( - `Workspace with version "${ - version.split("b")[0] - }" already exists.\nRemove that workspace and run |${bin_name} download ${version}| again.` - ); - log.info(`Downloading Firefox release ${version}...`); + if (!firefoxVersion) { + firefoxVersion = pjson.versions['firefox-display'] + } - const { data, headers } = await axios.get(url, { - responseType: "stream" - }); + let version = await getLatestFF() - const length = headers["content-length"]; + if (firefoxVersion) { + version = firefoxVersion + } - const writer = fs.createWriteStream( - resolve( - process.cwd(), - `.dotbuild`, - `engines`, - filename - ) - ); + const base = `https://archive.mozilla.org/pub/firefox/releases/${version}/source/` + const filename = `firefox-${version}.source.tar.xz` - let receivedBytes = 0; + const url = `${base}${filename}` - data.on("data", (chunk: any) => { - receivedBytes += chunk.length; + log.info(`Locating Firefox release ${version}...`) - let rand = Math.floor(Math.random() * 1000 + 1); + ensureDirSync(resolve(process.cwd(), `.dotbuild`, `engines`)) - if (rand > 999.5) { - let percentCompleted = parseInt( - Math.round( - (receivedBytes * 100) / length - ).toFixed(0) - ); - if ( - percentCompleted % 2 == 0 || - percentCompleted >= 100 - ) - return; - log.info( - `\t${filename}\t${percentCompleted}%...` - ); - } - }); + if ( + existsSync( + resolve( + process.cwd(), + `.dotbuild`, + `engines`, + `firefox-${version.split('b')[0]}` + ) + ) + ) { + log.error( + `Cannot download version ${ + version.split('b')[0] + } as it already exists at "${resolve( + process.cwd(), + `firefox-${version.split('b')[0]}` + )}"` + ) + } - data.pipe(writer); + if (version == firefoxVersion) + log.info(`Version is frozen at ${firefoxVersion}!`) + if (version.includes('b')) + log.warning( + 'Version includes non-numeric characters. This is probably a beta.' + ) - data.on("end", async () => { - await unpack(filename, version); + if ( + fs.existsSync( + resolve( + process.cwd(), + `.dotbuild`, + `engines`, + 'firefox', + version.split('b')[0] + ) + ) || + fs.existsSync( + resolve(process.cwd(), 'firefox', 'firefox-' + version.split('b')[0]) + ) + ) + log.error( + `Workspace with version "${ + version.split('b')[0] + }" already exists.\nRemove that workspace and run |${bin_name} download ${version}| again.` + ) - if (process.platform === "win32") { - if ( - existsSync( - resolve(homedir(), ".mozbuild") - ) - ) { - log.info( - "Mozbuild directory already exists, not redownloading" - ); - } else { - log.info( - "Mozbuild not found, downloading artifacts." - ); - await downloadArtifacts(); - } - } - }); -}; + log.info(`Downloading Firefox release ${version}...`) + + const { data, headers } = await axios.get(url, { + responseType: 'stream', + }) + + const length = headers['content-length'] + + const writer = fs.createWriteStream( + resolve(process.cwd(), `.dotbuild`, `engines`, filename) + ) + + let receivedBytes = 0 + + data.on('data', (chunk: any) => { + receivedBytes += chunk.length + + let rand = Math.floor(Math.random() * 1000 + 1) + + if (rand > 999.5) { + let percentCompleted = parseInt( + Math.round((receivedBytes * 100) / length).toFixed(0) + ) + if (percentCompleted % 2 == 0 || percentCompleted >= 100) return + log.info(`\t${filename}\t${percentCompleted}%...`) + } + }) + + data.pipe(writer) + + data.on('end', async () => { + await unpack(filename, version) + + if (process.platform === 'win32') { + if (existsSync(resolve(homedir(), '.mozbuild'))) { + log.info('Mozbuild directory already exists, not redownloading') + } else { + log.info('Mozbuild not found, downloading artifacts.') + await downloadArtifacts() + } + } + }) +} diff --git a/src/commands/execute.ts b/src/commands/execute.ts index 978ed1e..5eda596 100644 --- a/src/commands/execute.ts +++ b/src/commands/execute.ts @@ -1,26 +1,24 @@ -import { existsSync } from "fs"; -import { log } from ".."; -import { ENGINE_DIR } from "../constants"; -import { dispatch } from "../utils"; +import { existsSync } from 'fs' +import { log } from '..' +import { ENGINE_DIR } from '../constants' +import { dispatch } from '../utils' export const execute = async (_: any, cmd: any[]) => { - if (existsSync(ENGINE_DIR)) { - if (!cmd || cmd.length == 0) - log.error( - "You need to specify a command to run." - ); + if (existsSync(ENGINE_DIR)) { + if (!cmd || cmd.length == 0) + log.error('You need to specify a command to run.') - const bin = cmd[0]; - const args = cmd; - args.shift(); + const bin = cmd[0] + const args = cmd + args.shift() - log.info( - `Executing \`${bin}${ - args.length !== 0 ? ` ` : `` - }${args.join(" ")}\` in \`src\`...` - ); - dispatch(bin, args, ENGINE_DIR, true); - } else { - log.error(`Unable to locate src directory.`); - } -}; + log.info( + `Executing \`${bin}${args.length !== 0 ? ` ` : ``}${args.join( + ' ' + )}\` in \`src\`...` + ) + dispatch(bin, args, ENGINE_DIR, true) + } else { + log.error(`Unable to locate src directory.`) + } +} diff --git a/src/commands/export-file.ts b/src/commands/export-file.ts index 2e285f5..f4e8fdf 100644 --- a/src/commands/export-file.ts +++ b/src/commands/export-file.ts @@ -1,64 +1,56 @@ -import execa from "execa"; -import { existsSync, writeFileSync } from "fs"; -import { ensureDirSync } from "fs-extra"; -import { resolve } from "path"; -import { log } from ".."; -import { ENGINE_DIR, SRC_DIR } from "../constants"; -import { delay } from "../utils"; +import execa from 'execa' +import { existsSync, writeFileSync } from 'fs' +import { ensureDirSync } from 'fs-extra' +import { resolve } from 'path' +import { log } from '..' +import { ENGINE_DIR, SRC_DIR } from '../constants' +import { delay } from '../utils' export const exportFile = async (file: string) => { - log.info(`Exporting ${file}...`); + log.info(`Exporting ${file}...`) - if (!existsSync(resolve(ENGINE_DIR, file))) - throw new Error( - `File ${file} could not be found in engine directory. Check the path for any mistakes and try again.` - ); + if (!existsSync(resolve(ENGINE_DIR, file))) + throw new Error( + `File ${file} could not be found in engine directory. Check the path for any mistakes and try again.` + ) - const proc = await execa( - "git", - [ - "diff", - "--src-prefix=a/", - "--dst-prefix=b/", - "--full-index", - resolve(ENGINE_DIR, file) - ], - { - cwd: ENGINE_DIR, - stripFinalNewline: false - } - ); - const name = - file - .split("/") - [ - file.replace(/\./g, "-").split("/") - .length - 1 - ].replace(/\./g, "-") + ".patch"; - - const patchPath = file - .replace(/\./g, "-") - .split("/") - .slice(0, -1); - - ensureDirSync(resolve(SRC_DIR, ...patchPath)); - - if (proc.stdout.length >= 8000) { - log.warning(""); - log.warning( - `Exported patch is over 8000 characters. This patch may become hard to manage in the future.` - ); - log.warning( - `We recommend trying to decrease your patch size by making minimal edits to the source.` - ); - log.warning(""); - await delay(2000); + const proc = await execa( + 'git', + [ + 'diff', + '--src-prefix=a/', + '--dst-prefix=b/', + '--full-index', + resolve(ENGINE_DIR, file), + ], + { + cwd: ENGINE_DIR, + stripFinalNewline: false, } + ) + const name = + file + .split('/') + [file.replace(/\./g, '-').split('/').length - 1].replace(/\./g, '-') + + '.patch' - writeFileSync( - resolve(SRC_DIR, ...patchPath, name), - proc.stdout - ); - log.info(`Wrote "${name}" to patches directory.`); - console.log(); -}; + const patchPath = file.replace(/\./g, '-').split('/').slice(0, -1) + + ensureDirSync(resolve(SRC_DIR, ...patchPath)) + + if (proc.stdout.length >= 8000) { + log.warning('') + log.warning( + `Exported patch is over 8000 characters. This patch may become hard to manage in the future.` + ) + log.warning( + `We recommend trying to decrease your patch size by making minimal edits to the source.` + ) + log.warning('') + await delay(2000) + } + + writeFileSync(resolve(SRC_DIR, ...patchPath, name), proc.stdout) + log.info(`Wrote "${name}" to patches directory.`) + console.log() +} diff --git a/src/commands/export-patches.ts b/src/commands/export-patches.ts index a3646e0..0ec7246 100644 --- a/src/commands/export-patches.ts +++ b/src/commands/export-patches.ts @@ -1,218 +1,163 @@ -import execa from "execa"; +import execa from 'execa' import { - appendFileSync, - createWriteStream, - existsSync, - mkdirSync, - rmdirSync, - writeFileSync -} from "fs"; -import { copySync, ensureDirSync } from "fs-extra"; -import { resolve } from "path"; -import { log } from ".."; -import { - COMMON_DIR, - ENGINE_DIR, - PATCHES_DIR -} from "../constants"; -import manualPatches from "../manual-patches"; + appendFileSync, + createWriteStream, + existsSync, + mkdirSync, + rmdirSync, + writeFileSync, +} from 'fs' +import { copySync, ensureDirSync } from 'fs-extra' +import { resolve } from 'path' +import { log } from '..' +import { COMMON_DIR, ENGINE_DIR, PATCHES_DIR } from '../constants' +import manualPatches from '../manual-patches' const flags: { - [key: string]: string; + [key: string]: string } = { - D: "delete", - M: "modify", - A: "add" -}; + D: 'delete', + M: 'modify', + A: 'add', +} const getFiles = async (flags: string, cwd: string) => { - let { stdout: ignored } = await execa( - "git", - [ - "ls-files", - `-${flags.toLowerCase()}`, - "-i", - "-o", - "--exclude-standard" - ], - { cwd } - ); + let { stdout: ignored } = await execa( + 'git', + ['ls-files', `-${flags.toLowerCase()}`, '-i', '-o', '--exclude-standard'], + { cwd } + ) - let { stdout: fls } = await execa( - "git", - [ - "diff", - `--diff-filter=${flags}`, - "--name-only", - "--ignore-space-at-eol" - ], - { cwd } - ); + let { stdout: fls } = await execa( + 'git', + ['diff', `--diff-filter=${flags}`, '--name-only', '--ignore-space-at-eol'], + { cwd } + ) - const files = fls.split("\n").filter((i: any) => { - return !( - ignored.split("\n").includes(i) || - i == ".gitignore" - ); - }); // this filters out the manual patches + const files = fls.split('\n').filter((i: any) => { + return !(ignored.split('\n').includes(i) || i == '.gitignore') + }) // this filters out the manual patches - log.info( - `Ignoring ${ignored.split("\n").length} files...` - ); + log.info(`Ignoring ${ignored.split('\n').length} files...`) - const fileNames: any = files.map((f: any) => { - if (f.length !== 0) { - return ( - f - .replace(/\//g, "-") - .replace(/\./g, "-") + ".patch" - ); - } - }); + const fileNames: any = files.map((f: any) => { + if (f.length !== 0) { + return f.replace(/\//g, '-').replace(/\./g, '-') + '.patch' + } + }) - return { files, fileNames }; -}; + return { files, fileNames } +} -const exportModified = async ( - patchesDir: string, - cwd: string -) => { - const { files, fileNames } = await getFiles("M", cwd); +const exportModified = async (patchesDir: string, cwd: string) => { + const { files, fileNames } = await getFiles('M', cwd) - var filesWritten = 0; + var filesWritten = 0 - await Promise.all( - files.map(async (file: any, i: any) => { - if (file) { - try { - const proc = execa( - "git", - [ - "diff", - "--src-prefix=a/", - "--dst-prefix=b/", - "--full-index", - file - ], - { - cwd, - stripFinalNewline: false - } - ); - const name = fileNames[i]; - - proc.stdout?.pipe( - createWriteStream( - resolve(patchesDir, name) - ) - ); - - appendFileSync( - resolve(PATCHES_DIR, ".index"), - `${name} - ${file}\n` - ); - - ++filesWritten; - } catch (e) { - log.error(e); - return; - } + await Promise.all( + files.map(async (file: any, i: any) => { + if (file) { + try { + const proc = execa( + 'git', + [ + 'diff', + '--src-prefix=a/', + '--dst-prefix=b/', + '--full-index', + file, + ], + { + cwd, + stripFinalNewline: false, } - }) - ); + ) + const name = fileNames[i] - log.info( - `Wrote ${filesWritten} to patches directory.` - ); -}; + proc.stdout?.pipe(createWriteStream(resolve(patchesDir, name))) -const exportFlag = async ( - flag: string, - cwd: string, - actions: any[] -) => { - const { files } = await getFiles(flag, cwd); + appendFileSync(resolve(PATCHES_DIR, '.index'), `${name} - ${file}\n`) - actions.push({ - action: flags[flag], - target: files - }); + ++filesWritten + } catch (e) { + log.error(e) + return + } + } + }) + ) - return actions; -}; + log.info(`Wrote ${filesWritten} to patches directory.`) +} + +const exportFlag = async (flag: string, cwd: string, actions: any[]) => { + const { files } = await getFiles(flag, cwd) + + actions.push({ + action: flags[flag], + target: files, + }) + + return actions +} const exportManual = async (cwd: string) => { - return new Promise(async (resol) => { - manualPatches.forEach((patch) => { - if (patch.action == "copy") { - if (typeof patch.src == "string") { - const inSrc = resolve(cwd, patch.src); - const outsideSrc = resolve( - COMMON_DIR, - patch.src - ); + return new Promise(async (resol) => { + manualPatches.forEach((patch) => { + if (patch.action == 'copy') { + if (typeof patch.src == 'string') { + const inSrc = resolve(cwd, patch.src) + const outsideSrc = resolve(COMMON_DIR, patch.src) - if (!existsSync(inSrc)) - return log.error( - `Cannot find "${patch.src}" from manual patches.` - ); - if (!existsSync(outsideSrc)) - ensureDirSync(outsideSrc); // make sure target dir exists before copying + if (!existsSync(inSrc)) + return log.error(`Cannot find "${patch.src}" from manual patches.`) + if (!existsSync(outsideSrc)) ensureDirSync(outsideSrc) // make sure target dir exists before copying - copySync(inSrc, outsideSrc); - } else if (Array.isArray(patch.src)) { - patch.src.forEach((p) => { - const inSrc = resolve(cwd, p); - const outsideSrc = resolve( - COMMON_DIR, - p - ); + copySync(inSrc, outsideSrc) + } else if (Array.isArray(patch.src)) { + patch.src.forEach((p) => { + const inSrc = resolve(cwd, p) + const outsideSrc = resolve(COMMON_DIR, p) - if (!existsSync(inSrc)) - return log.error( - `Cannot find "${p}" from manual patches.` - ); - if (!existsSync(outsideSrc)) - ensureDirSync(outsideSrc); // make sure target dir exists before copying + if (!existsSync(inSrc)) + return log.error(`Cannot find "${p}" from manual patches.`) + if (!existsSync(outsideSrc)) ensureDirSync(outsideSrc) // make sure target dir exists before copying - copySync(inSrc, outsideSrc); - }); - } - } - }); - }); -}; + copySync(inSrc, outsideSrc) + }) + } + } + }) + }) +} export const exportPatches = async () => { - throw new Error( - "export-patches has been deprecated in favour of export-file. This change has been made to limit the amount of active patches we have in the tree." - ); + throw new Error( + 'export-patches has been deprecated in favour of export-file. This change has been made to limit the amount of active patches we have in the tree.' + ) - let actions: any[] = []; + let actions: any[] = [] - log.info(`Wiping patches directory...`); - console.log(); - // TODO: Replace this with fs.rmSync(path, { recursive: true }) when node 12 is deprecated - // This function has been depriciated, however its replacement was only available - // from v14.14.0 onwards (https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fs_fs_rmsync_path_options) - rmdirSync(PATCHES_DIR, { recursive: true }); - mkdirSync(PATCHES_DIR); - writeFileSync(resolve(PATCHES_DIR, ".index"), ""); + log.info(`Wiping patches directory...`) + console.log() + // TODO: Replace this with fs.rmSync(path, { recursive: true }) when node 12 is deprecated + // This function has been depriciated, however its replacement was only available + // from v14.14.0 onwards (https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fs_fs_rmsync_path_options) + rmdirSync(PATCHES_DIR, { recursive: true }) + mkdirSync(PATCHES_DIR) + writeFileSync(resolve(PATCHES_DIR, '.index'), '') - log.info("Exporting modified files..."); - await exportModified(PATCHES_DIR, ENGINE_DIR); - console.log(); + log.info('Exporting modified files...') + await exportModified(PATCHES_DIR, ENGINE_DIR) + console.log() - log.info("Exporting deleted files..."); - await exportFlag("D", ENGINE_DIR, actions); - console.log(); + log.info('Exporting deleted files...') + await exportFlag('D', ENGINE_DIR, actions) + console.log() - log.info("Exporting manual patches..."); - await exportManual(ENGINE_DIR); - console.log(); + log.info('Exporting manual patches...') + await exportManual(ENGINE_DIR) + console.log() - copySync( - resolve(ENGINE_DIR, "dot"), - resolve(process.cwd(), "browser") - ); -}; + copySync(resolve(ENGINE_DIR, 'dot'), resolve(process.cwd(), 'browser')) +} diff --git a/src/commands/fix-le.ts b/src/commands/fix-le.ts index a1c6187..39797e3 100644 --- a/src/commands/fix-le.ts +++ b/src/commands/fix-le.ts @@ -1,49 +1,28 @@ -import { - existsSync, - readdirSync, - readFileSync -} from "fs-extra"; -import { resolve } from "path"; -import { log } from ".."; -import { ENGINE_DIR, PATCHES_DIR } from "../constants"; -import { dispatch } from "../utils"; +import { existsSync, readdirSync, readFileSync } from 'fs-extra' +import { resolve } from 'path' +import { log } from '..' +import { ENGINE_DIR, PATCHES_DIR } from '../constants' +import { dispatch } from '../utils' export const fixLineEndings = async () => { - let patches = readdirSync(PATCHES_DIR); + let patches = readdirSync(PATCHES_DIR) - patches = patches.filter((p) => p !== ".index"); + patches = patches.filter((p) => p !== '.index') - await Promise.all( - patches.map(async (patch) => { - const patchContents = readFileSync( - resolve(PATCHES_DIR, patch), - "utf-8" - ); - const originalPath = patchContents - .split("diff --git a/")[1] - .split(" b/")[0]; + await Promise.all( + patches.map(async (patch) => { + const patchContents = readFileSync(resolve(PATCHES_DIR, patch), 'utf-8') + const originalPath = patchContents + .split('diff --git a/')[1] + .split(' b/')[0] - if ( - existsSync( - resolve(ENGINE_DIR, originalPath) - ) - ) { - dispatch( - "dos2unix", - [originalPath], - ENGINE_DIR - ).then(async (_) => { - await dispatch( - "dos2unix", - [patch], - PATCHES_DIR - ); - }); - } else { - log.warning( - `Skipping ${patch} as it no longer exists in tree...` - ); - } + if (existsSync(resolve(ENGINE_DIR, originalPath))) { + dispatch('dos2unix', [originalPath], ENGINE_DIR).then(async (_) => { + await dispatch('dos2unix', [patch], PATCHES_DIR) }) - ); -}; + } else { + log.warning(`Skipping ${patch} as it no longer exists in tree...`) + } + }) + ) +} diff --git a/src/commands/import-patches.ts b/src/commands/import-patches.ts index 0584cdb..d6d4bdc 100644 --- a/src/commands/import-patches.ts +++ b/src/commands/import-patches.ts @@ -1,141 +1,115 @@ -import { sync } from "glob"; -import { bin_name, log } from ".."; -import { SRC_DIR } from "../constants"; -import Patch from "../controllers/patch"; -import manualPatches from "../manual-patches"; -import { delay, dispatch } from "../utils"; +import { sync } from 'glob' +import { bin_name, log } from '..' +import { SRC_DIR } from '../constants' +import Patch from '../controllers/patch' +import manualPatches from '../manual-patches' +import { delay, dispatch } from '../utils' const { - versions: { dot } -} = require("../../package.json"); + versions: { dot }, +} = require('../../package.json') -const importManual = async ( - minimal?: boolean, - noIgnore?: boolean -) => { - log.info( - `Applying ${manualPatches.length} manual patches...` - ); +const importManual = async (minimal?: boolean, noIgnore?: boolean) => { + log.info(`Applying ${manualPatches.length} manual patches...`) - if (!minimal) console.log(); + if (!minimal) console.log() - await delay(500); + await delay(500) - return new Promise(async (res, rej) => { - var total = 0; + return new Promise(async (res, rej) => { + var total = 0 - var i = 0; + var i = 0 - for await (let { - name, - action, - src, - markers, - indent - } of manualPatches) { - ++i; + for await (let { name, action, src, markers, indent } of manualPatches) { + ++i - const p = new Patch({ - name, - action, - src, - type: "manual", - status: [i, manualPatches.length], - markers, - indent, - options: { - minimal, - noIgnore - } - }); + const p = new Patch({ + name, + action, + src, + type: 'manual', + status: [i, manualPatches.length], + markers, + indent, + options: { + minimal, + noIgnore, + }, + }) - await delay(100); + await delay(100) - await p.apply(); - } - - log.success( - `Successfully imported ${manualPatches.length} manual patches!` - ); - console.log(); - - await delay(1000); - - res(total); - }); -}; - -const importPatchFiles = async ( - minimal?: boolean, - noIgnore?: boolean -) => { - let patches = sync("**/*.patch", { - nodir: true, - cwd: SRC_DIR - }); - - patches = patches - .filter((p) => p !== ".index") - .filter((p) => !p.includes("node_modules")); - - log.info(`Applying ${patches.length} patch files...`); - - if (!minimal) console.log(); - - await delay(500); - - var i = 0; - - for await (const patch of patches) { - ++i; - - const p = new Patch({ - name: patch, - type: "file", - status: [i, patches.length], - options: { - minimal, - noIgnore - } - }); - - await delay(100); - - await p.apply(); + await p.apply() } - console.log(); - await dispatch( - `./${bin_name}`, - ["doctor", "patches"], - process.cwd(), - true, - true - ); + log.success(`Successfully imported ${manualPatches.length} manual patches!`) + console.log() - log.success( - `Successfully imported ${patches.length} patch files!` - ); -}; + await delay(1000) -interface Args { - minimal?: boolean; - noignore?: boolean; + res(total) + }) } -export const importPatches = async ( - type: string, - args: Args -) => { - if (type) { - if (type == "manual") - await importManual(args.minimal); - else if (type == "file") - await importPatchFiles(args.minimal); - } else { - await importManual(args.minimal, args.noignore); - await importPatchFiles( - args.minimal, - args.noignore - ); - } -}; +const importPatchFiles = async (minimal?: boolean, noIgnore?: boolean) => { + let patches = sync('**/*.patch', { + nodir: true, + cwd: SRC_DIR, + }) + + patches = patches + .filter((p) => p !== '.index') + .filter((p) => !p.includes('node_modules')) + + log.info(`Applying ${patches.length} patch files...`) + + if (!minimal) console.log() + + await delay(500) + + var i = 0 + + for await (const patch of patches) { + ++i + + const p = new Patch({ + name: patch, + type: 'file', + status: [i, patches.length], + options: { + minimal, + noIgnore, + }, + }) + + await delay(100) + + await p.apply() + } + + console.log() + await dispatch( + `./${bin_name}`, + ['doctor', 'patches'], + process.cwd(), + true, + true + ) + + log.success(`Successfully imported ${patches.length} patch files!`) +} + +interface Args { + minimal?: boolean + noignore?: boolean +} + +export const importPatches = async (type: string, args: Args) => { + if (type) { + if (type == 'manual') await importManual(args.minimal) + else if (type == 'file') await importPatchFiles(args.minimal) + } else { + await importManual(args.minimal, args.noignore) + await importPatchFiles(args.minimal, args.noignore) + } +} diff --git a/src/commands/index.ts b/src/commands/index.ts index 5695b16..c975fdd 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -1,18 +1,18 @@ -export * from "./bootstrap"; -export * from "./build"; -export * from "./discard"; -export * from "./download"; -export * from "./download-artifacts"; -export * from "./execute"; -export * from "./export-file"; -export * from "./export-patches"; -export * from "./fix-le"; -export * from "./import-patches"; -export * from "./init"; -export * from "./license-check"; -export * from "./package"; -export * from "./reset"; -export * from "./run"; -export * from "./set-branch"; -export * from "./status"; -export * from "./test"; +export * from './bootstrap' +export * from './build' +export * from './discard' +export * from './download' +export * from './download-artifacts' +export * from './execute' +export * from './export-file' +export * from './export-patches' +export * from './fix-le' +export * from './import-patches' +export * from './init' +export * from './license-check' +export * from './package' +export * from './reset' +export * from './run' +export * from './set-branch' +export * from './status' +export * from './test' diff --git a/src/commands/init.ts b/src/commands/init.ts index 98fa409..e464ca7 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -1,68 +1,53 @@ -import { Command } from "commander"; -import { existsSync, readFileSync } from "fs"; -import { resolve } from "path"; -import { bin_name, log } from ".."; -import { dispatch } from "../utils"; +import { Command } from 'commander' +import { existsSync, readFileSync } from 'fs' +import { resolve } from 'path' +import { bin_name, log } from '..' +import { dispatch } from '../utils' export const init = async (directory: Command) => { - if (process.platform == "win32") { - // Because Windows cannot handle paths correctly, we're just calling a script as the workaround. - log.info( - "Successfully downloaded browser source. Please run |./windows-init.sh| to finish up." - ); - process.exit(0); - } + if (process.platform == 'win32') { + // Because Windows cannot handle paths correctly, we're just calling a script as the workaround. + log.info( + 'Successfully downloaded browser source. Please run |./windows-init.sh| to finish up.' + ) + process.exit(0) + } - const cwd = process.cwd(); + const cwd = process.cwd() - const dir = resolve( - cwd as string, - directory.toString() - ); + const dir = resolve(cwd as string, directory.toString()) - if (!existsSync(dir)) { - log.error( - `Directory "${directory}" not found.\nCheck the directory exists and run |${bin_name} init| again.` - ); - } + if (!existsSync(dir)) { + log.error( + `Directory "${directory}" not found.\nCheck the directory exists and run |${bin_name} init| again.` + ) + } - let version = readFileSync( - resolve( - cwd, - directory.toString(), - "browser", - "config", - "version_display.txt" - ), - "utf-8" - ); + let version = readFileSync( + resolve( + cwd, + directory.toString(), + 'browser', + 'config', + 'version_display.txt' + ), + 'utf-8' + ) - if (!version) - log.error( - `Directory "${directory}" not found.\nCheck the directory exists and run |${bin_name} init| again.` - ); + if (!version) + log.error( + `Directory "${directory}" not found.\nCheck the directory exists and run |${bin_name} init| again.` + ) - version = version.trim().replace(/\\n/g, ""); + version = version.trim().replace(/\\n/g, '') - await dispatch("git", ["init"], dir as string); - await dispatch( - "git", - ["checkout", "--orphan", version], - dir as string - ); - await dispatch( - "git", - ["add", "-v", "-f", "."], - dir as string - ); - await dispatch( - "git", - ["commit", "-am", `"Firefox ${version}"`], - dir as string - ); - await dispatch( - "git", - ["checkout", "-b", "dot"], - dir as string - ); -}; + await dispatch('git', ['init'], dir as string) + await dispatch('git', ['checkout', '--orphan', version], dir as string) + await dispatch('git', ['add', '-v', '-f', '.'], dir as string) + await dispatch( + 'git', + ['commit', '-am', `"Firefox ${version}"`], + dir as string + ) + await dispatch('git', ['checkout', '-b', 'dot'], dir as string) +} diff --git a/src/commands/license-check.ts b/src/commands/license-check.ts index 0e64d08..a135d8b 100644 --- a/src/commands/license-check.ts +++ b/src/commands/license-check.ts @@ -1,92 +1,69 @@ -import chalk from "chalk"; -import { readdirSync, readFileSync } from "fs-extra"; -import { resolve } from "path"; -import { log } from ".."; -import { ENGINE_DIR, PATCHES_DIR } from "../constants"; +import chalk from 'chalk' +import { readdirSync, readFileSync } from 'fs-extra' +import { resolve } from 'path' +import { log } from '..' +import { ENGINE_DIR, PATCHES_DIR } from '../constants' -const ignoredExt = [".json", ".bundle.js"]; +const ignoredExt = ['.json', '.bundle.js'] export const licenseCheck = async () => { - log.info("Checking project..."); + log.info('Checking project...') - let patches = readdirSync(PATCHES_DIR).map((p) => p); + let patches = readdirSync(PATCHES_DIR).map((p) => p) - patches = patches.filter((p) => p !== ".index"); + patches = patches.filter((p) => p !== '.index') - const originalPaths = patches.map((p) => { - const data = readFileSync( - resolve(PATCHES_DIR, p), - "utf-8" - ); + const originalPaths = patches.map((p) => { + const data = readFileSync(resolve(PATCHES_DIR, p), 'utf-8') - return data - .split("diff --git a/")[1] - .split(" b/")[0]; - }); + return data.split('diff --git a/')[1].split(' b/')[0] + }) - let passed: string[] = []; - let failed: string[] = []; - let ignored: string[] = []; + let passed: string[] = [] + let failed: string[] = [] + let ignored: string[] = [] - originalPaths.forEach((p) => { - const data = readFileSync( - resolve(ENGINE_DIR, p), - "utf-8" - ); - const headerRegion = data - .split("\n") - .slice(0, 32) - .join(" "); + originalPaths.forEach((p) => { + const data = readFileSync(resolve(ENGINE_DIR, p), 'utf-8') + const headerRegion = data.split('\n').slice(0, 32).join(' ') - const passes = - headerRegion.includes( - "http://mozilla.org/MPL/2.0" - ) && - headerRegion.includes( - "This Source Code Form" - ) && - headerRegion.includes("copy of the MPL"); + const passes = + headerRegion.includes('http://mozilla.org/MPL/2.0') && + headerRegion.includes('This Source Code Form') && + headerRegion.includes('copy of the MPL') - const isIgnored = ignoredExt.find((i) => - p.endsWith(i) - ) - ? true - : false; - isIgnored && ignored.push(p); + const isIgnored = ignoredExt.find((i) => p.endsWith(i)) ? true : false + isIgnored && ignored.push(p) - if (!isIgnored) { - if (passes) passed.push(p); - else if (!passes) failed.push(p); - } - }); + if (!isIgnored) { + if (passes) passed.push(p) + else if (!passes) failed.push(p) + } + }) - let maxPassed = 5; - let i = 0; + let maxPassed = 5 + let i = 0 - for (const p of passed) { - log.info( - `${p}... ${chalk.green("✔ Pass - MPL-2.0")}` - ); + for (const p of passed) { + log.info(`${p}... ${chalk.green('✔ Pass - MPL-2.0')}`) - if (i >= maxPassed) { - log.info( - `${chalk.gray.italic( - `${ - passed.length - maxPassed - } other files...` - )} ${chalk.green("✔ Pass - MPL-2.0")}` - ); - break; - } - - ++i; + if (i >= maxPassed) { + log.info( + `${chalk.gray.italic( + `${passed.length - maxPassed} other files...` + )} ${chalk.green('✔ Pass - MPL-2.0')}` + ) + break } - failed.forEach((p, i) => { - log.info(`${p}... ${chalk.red("❗ Failed")}`); - }); + ++i + } - ignored.forEach((p, i) => { - log.info(`${p}... ${chalk.gray("➖ Ignored")}`); - }); -}; + failed.forEach((p, i) => { + log.info(`${p}... ${chalk.red('❗ Failed')}`) + }) + + ignored.forEach((p, i) => { + log.info(`${p}... ${chalk.gray('➖ Ignored')}`) + }) +} diff --git a/src/commands/linus.d.ts b/src/commands/linus.d.ts index eb507c9..1af5b14 100644 --- a/src/commands/linus.d.ts +++ b/src/commands/linus.d.ts @@ -1,5 +1,3 @@ -declare module "linus" { - export function name( - callback: (error: Error, name: string) => void - ): void; +declare module 'linus' { + export function name(callback: (error: Error, name: string) => void): void } diff --git a/src/commands/package.ts b/src/commands/package.ts index 5136c38..3ea4852 100644 --- a/src/commands/package.ts +++ b/src/commands/package.ts @@ -1,35 +1,27 @@ -import execa from "execa"; -import { existsSync } from "fs"; -import { resolve } from "path"; -import { bin_name, log } from ".."; -import { ENGINE_DIR } from "../constants"; +import execa from 'execa' +import { existsSync } from 'fs' +import { resolve } from 'path' +import { bin_name, log } from '..' +import { ENGINE_DIR } from '../constants' export const melonPackage = async () => { - if (existsSync(ENGINE_DIR)) { - const artifactPath = resolve(ENGINE_DIR, "mach"); + if (existsSync(ENGINE_DIR)) { + const artifactPath = resolve(ENGINE_DIR, 'mach') - if (existsSync(artifactPath)) { - const args = ["package"]; + if (existsSync(artifactPath)) { + const args = ['package'] - log.info( - `Packaging \`dot\` with args ${JSON.stringify( - args.slice(1, 0) - )}...` - ); + log.info( + `Packaging \`dot\` with args ${JSON.stringify(args.slice(1, 0))}...` + ) - execa(artifactPath, args).stdout?.pipe( - process.stdout - ); - } else { - log.error( - `Cannot binary with name \`mach\` in ${resolve( - ENGINE_DIR - )}` - ); - } + execa(artifactPath, args).stdout?.pipe(process.stdout) } else { - log.error( - `Unable to locate any source directories.\nRun |${bin_name} download| to generate the source directory.` - ); + log.error(`Cannot binary with name \`mach\` in ${resolve(ENGINE_DIR)}`) } -}; + } else { + log.error( + `Unable to locate any source directories.\nRun |${bin_name} download| to generate the source directory.` + ) + } +} diff --git a/src/commands/reset.ts b/src/commands/reset.ts index f727d43..81755c2 100644 --- a/src/commands/reset.ts +++ b/src/commands/reset.ts @@ -1,171 +1,93 @@ -import execa from "execa"; -import { existsSync } from "fs-extra"; -import { resolve } from "path"; -import { confirm } from "promptly"; -import rimraf from "rimraf"; -import { bin_name, log } from ".."; -import { ENGINE_DIR } from "../constants"; -import { IPatch } from "../interfaces/patch"; -import manualPatches from "../manual-patches"; +import execa from 'execa' +import { existsSync } from 'fs-extra' +import { resolve } from 'path' +import { confirm } from 'promptly' +import rimraf from 'rimraf' +import { bin_name, log } from '..' +import { ENGINE_DIR } from '../constants' +import { IPatch } from '../interfaces/patch' +import manualPatches from '../manual-patches' export const reset = async () => { - try { - log.warning( - "This will clear all your unexported changes in the `src` directory!" - ); - log.warning( - `You can export your changes by running |${bin_name} export|.` - ); - confirm(`Are you sure you want to continue?`, { - default: "false" - }) - .then(async (answer) => { - if (answer) { - await execa( - "git", - ["checkout", "."], - { cwd: ENGINE_DIR } - ); + try { + log.warning( + 'This will clear all your unexported changes in the `src` directory!' + ) + log.warning(`You can export your changes by running |${bin_name} export|.`) + confirm(`Are you sure you want to continue?`, { + default: 'false', + }) + .then(async (answer) => { + if (answer) { + await execa('git', ['checkout', '.'], { cwd: ENGINE_DIR }) - manualPatches.forEach( - async (patch: IPatch) => { - const { src, action } = patch; + manualPatches.forEach(async (patch: IPatch) => { + const { src, action } = patch - if (action == "copy") { - if ( - typeof src == "string" - ) { - const path = resolve( - ENGINE_DIR, - src - ); + if (action == 'copy') { + if (typeof src == 'string') { + const path = resolve(ENGINE_DIR, src) - if ( - path !== - ENGINE_DIR - ) { - log.info( - `Deleting ${src}...` - ); + if (path !== ENGINE_DIR) { + log.info(`Deleting ${src}...`) - if ( - existsSync( - path - ) - ) - rimraf.sync( - path - ); - } - } else if ( - Array.isArray(src) - ) { - src.forEach((i) => { - const path = - resolve( - ENGINE_DIR, - i - ); - - if ( - path !== - ENGINE_DIR - ) { - log.info( - `Deleting ${i}...` - ); - - if ( - existsSync( - path - ) - ) - rimraf.sync( - path - ); - } - }); - } - } else { - log.warning( - "Resetting does not work on manual patches that have a `delete` action, skipping..." - ); - } - } - ); - - let leftovers = new Set(); - - const { stdout: origFiles } = - await execa( - "git", - [ - "clean", - "-e", - "'!*.orig'", - "--dry-run" - ], - { cwd: ENGINE_DIR } - ); - - const { stdout: rejFiles } = - await execa( - "git", - [ - "clean", - "-e", - "'!*.rej'", - "--dry-run" - ], - { cwd: ENGINE_DIR } - ); - - origFiles - .split("\n") - .map((f) => - leftovers.add( - f.replace( - /Would remove /, - "" - ) - ) - ); - rejFiles - .split("\n") - .map((f) => - leftovers.add( - f.replace( - /Would remove /, - "" - ) - ) - ); - - Array.from(leftovers).forEach( - (f: any) => { - const path = resolve( - ENGINE_DIR, - f - ); - - if (path !== ENGINE_DIR) { - log.info( - `Deleting ${f}...` - ); - - rimraf.sync( - resolve(ENGINE_DIR, f) - ); - } - } - ); - - log.success("Reset successfully."); - log.info( - "Next time you build, it may need to recompile parts of the program because the cache was invalidated." - ); + if (existsSync(path)) rimraf.sync(path) } - }) - .catch((e) => e); - } catch (e) {} -}; + } else if (Array.isArray(src)) { + src.forEach((i) => { + const path = resolve(ENGINE_DIR, i) + + if (path !== ENGINE_DIR) { + log.info(`Deleting ${i}...`) + + if (existsSync(path)) rimraf.sync(path) + } + }) + } + } else { + log.warning( + 'Resetting does not work on manual patches that have a `delete` action, skipping...' + ) + } + }) + + let leftovers = new Set() + + const { stdout: origFiles } = await execa( + 'git', + ['clean', '-e', "'!*.orig'", '--dry-run'], + { cwd: ENGINE_DIR } + ) + + const { stdout: rejFiles } = await execa( + 'git', + ['clean', '-e', "'!*.rej'", '--dry-run'], + { cwd: ENGINE_DIR } + ) + + origFiles + .split('\n') + .map((f) => leftovers.add(f.replace(/Would remove /, ''))) + rejFiles + .split('\n') + .map((f) => leftovers.add(f.replace(/Would remove /, ''))) + + Array.from(leftovers).forEach((f: any) => { + const path = resolve(ENGINE_DIR, f) + + if (path !== ENGINE_DIR) { + log.info(`Deleting ${f}...`) + + rimraf.sync(resolve(ENGINE_DIR, f)) + } + }) + + log.success('Reset successfully.') + log.info( + 'Next time you build, it may need to recompile parts of the program because the cache was invalidated.' + ) + } + }) + .catch((e) => e) + } catch (e) {} +} diff --git a/src/commands/run.ts b/src/commands/run.ts index 6335106..ebe87e4 100644 --- a/src/commands/run.ts +++ b/src/commands/run.ts @@ -1,36 +1,32 @@ -import { existsSync, readdirSync } from "fs"; -import { resolve } from "path"; -import { bin_name, log } from ".."; -import { ENGINE_DIR } from "../constants"; -import { dispatch } from "../utils"; +import { existsSync, readdirSync } from 'fs' +import { resolve } from 'path' +import { bin_name, log } from '..' +import { ENGINE_DIR } from '../constants' +import { dispatch } from '../utils' export const run = async (chrome?: string) => { - const dirs = readdirSync(ENGINE_DIR); - const objDirname: any = dirs.find((dir) => { - return dir.startsWith("obj-"); - }); + const dirs = readdirSync(ENGINE_DIR) + const objDirname: any = dirs.find((dir) => { + return dir.startsWith('obj-') + }) - if (!objDirname) { - throw new Error( - "Dot Browser needs to be built before you can do this." - ); - } + if (!objDirname) { + throw new Error('Dot Browser needs to be built before you can do this.') + } - const objDir = resolve(ENGINE_DIR, objDirname); + const objDir = resolve(ENGINE_DIR, objDirname) - if (existsSync(objDir)) { - dispatch( - "./mach", - ["run"].concat( - chrome ? ["-chrome", chrome] : [] - ), - ENGINE_DIR, - true, - true - ); - } else { - log.error( - `Unable to locate any built binaries.\nRun |${bin_name} build| to initiate a build.` - ); - } -}; + if (existsSync(objDir)) { + dispatch( + './mach', + ['run'].concat(chrome ? ['-chrome', chrome] : []), + ENGINE_DIR, + true, + true + ) + } else { + log.error( + `Unable to locate any built binaries.\nRun |${bin_name} build| to initiate a build.` + ) + } +} diff --git a/src/commands/set-branch.ts b/src/commands/set-branch.ts index a0301e8..e31c607 100644 --- a/src/commands/set-branch.ts +++ b/src/commands/set-branch.ts @@ -1,62 +1,29 @@ -import execa from "execa"; -import { - existsSync, - readFileSync, - writeFileSync -} from "fs-extra"; -import { resolve } from "path"; -import { log } from ".."; +import execa from 'execa' +import { existsSync, readFileSync, writeFileSync } from 'fs-extra' +import { resolve } from 'path' +import { log } from '..' export const setBranch = async (branch: string) => { - if ( - !existsSync( - resolve( - process.cwd(), - ".dotbuild", - "metadata" - ) - ) - ) { - return log.error( - "Cannot find metadata, aborting..." - ); - } + if (!existsSync(resolve(process.cwd(), '.dotbuild', 'metadata'))) { + return log.error('Cannot find metadata, aborting...') + } - const metadata = JSON.parse( - readFileSync( - resolve( - process.cwd(), - ".dotbuild", - "metadata" - ), - "utf-8" - ) - ); + const metadata = JSON.parse( + readFileSync(resolve(process.cwd(), '.dotbuild', 'metadata'), 'utf-8') + ) - try { - await execa("git", [ - "rev-parse", - "--verify", - branch - ]); + try { + await execa('git', ['rev-parse', '--verify', branch]) - metadata.branch = branch; + metadata.branch = branch - writeFileSync( - resolve( - process.cwd(), - ".dotbuild", - "metadata" - ), - JSON.stringify(metadata) - ); + writeFileSync( + resolve(process.cwd(), '.dotbuild', 'metadata'), + JSON.stringify(metadata) + ) - log.success( - `Default branch is at \`${branch}\`.` - ); - } catch (e) { - return log.error( - `Branch with name \`${branch}\` does not exist.` - ); - } -}; + log.success(`Default branch is at \`${branch}\`.`) + } catch (e) { + return log.error(`Branch with name \`${branch}\` does not exist.`) + } +} diff --git a/src/commands/status.ts b/src/commands/status.ts index 114c0db..c075df4 100644 --- a/src/commands/status.ts +++ b/src/commands/status.ts @@ -1,12 +1,12 @@ -import { existsSync } from "fs"; -import { log } from ".."; -import { ENGINE_DIR } from "../constants"; -import { dispatch } from "../utils"; +import { existsSync } from 'fs' +import { log } from '..' +import { ENGINE_DIR } from '../constants' +import { dispatch } from '../utils' export const status = async () => { - if (existsSync(ENGINE_DIR)) { - dispatch("git", ["status"], ENGINE_DIR, true); - } else { - log.error(`Unable to locate src directory.`); - } -}; + if (existsSync(ENGINE_DIR)) { + dispatch('git', ['status'], ENGINE_DIR, true) + } else { + log.error(`Unable to locate src directory.`) + } +} diff --git a/src/commands/test.ts b/src/commands/test.ts index 132e820..f8134bf 100644 --- a/src/commands/test.ts +++ b/src/commands/test.ts @@ -1,10 +1,6 @@ -import { resolve } from "path"; -import { dispatch } from "../utils"; +import { resolve } from 'path' +import { dispatch } from '../utils' export const test = async () => { - dispatch( - "yarn", - ["test"], - resolve(process.cwd(), "src", "dot") - ); -}; + dispatch('yarn', ['test'], resolve(process.cwd(), 'src', 'dot')) +} diff --git a/src/constants/index.ts b/src/constants/index.ts index ce8a452..d0f5d59 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,51 +1,31 @@ -import execa from "execa"; -import { resolve } from "path"; +import execa from 'execa' +import { resolve } from 'path' -export const BUILD_TARGETS = [ - "linux", - "windows", - "macos" -]; +export const BUILD_TARGETS = ['linux', 'windows', 'macos'] -export const ARCHITECTURE = ["i686", "x86_64"]; +export const ARCHITECTURE = ['i686', 'x86_64'] export const PATCH_ARGS = [ - "--ignore-space-change", - "--ignore-whitespace", - "--verbose" -]; + '--ignore-space-change', + '--ignore-whitespace', + '--verbose', +] -export const ENGINE_DIR = resolve( - process.cwd(), - "engine" -); -export const SRC_DIR = resolve(process.cwd(), "src"); -export const PATCHES_DIR = resolve( - process.cwd(), - "patches" -); -export const COMMON_DIR = resolve( - process.cwd(), - "common" -); -export const CONFIGS_DIR = resolve( - process.cwd(), - "configs" -); +export const ENGINE_DIR = resolve(process.cwd(), 'engine') +export const SRC_DIR = resolve(process.cwd(), 'src') +export const PATCHES_DIR = resolve(process.cwd(), 'patches') +export const COMMON_DIR = resolve(process.cwd(), 'common') +export const CONFIGS_DIR = resolve(process.cwd(), 'configs') -export let CONFIG_GUESS: any = null; +export let CONFIG_GUESS: any = null try { - CONFIG_GUESS = execa.commandSync( - "./build/autoconf/config.guess", - { cwd: ENGINE_DIR } - ).stdout; + CONFIG_GUESS = execa.commandSync('./build/autoconf/config.guess', { + cwd: ENGINE_DIR, + }).stdout } catch (e) {} -export const OBJ_DIR = resolve( - ENGINE_DIR, - `obj-${CONFIG_GUESS}` -); +export const OBJ_DIR = resolve(ENGINE_DIR, `obj-${CONFIG_GUESS}`) export const FTL_STRING_LINE_REGEX = - /(([a-zA-Z0-9\-]*|\.[a-z\-]*) =(.*|\.)|\[[a-zA-Z0-9]*\].*(\n\s?\s?})?|\*\[[a-zA-Z0-9]*\] .*(\n\s?\s?})?)/gm; + /(([a-zA-Z0-9\-]*|\.[a-z\-]*) =(.*|\.)|\[[a-zA-Z0-9]*\].*(\n\s?\s?})?|\*\[[a-zA-Z0-9]*\] .*(\n\s?\s?})?)/gm diff --git a/src/controllers/patch.ts b/src/controllers/patch.ts index 9c8f58c..43f57af 100644 --- a/src/controllers/patch.ts +++ b/src/controllers/patch.ts @@ -1,267 +1,188 @@ -import chalk from "chalk"; -import execa from "execa"; -import { - existsSync, - rmdirSync, - rmSync, - statSync -} from "fs-extra"; -import { resolve } from "path"; -import readline from "readline"; -import { log } from ".."; -import { - ENGINE_DIR, - PATCH_ARGS, - SRC_DIR -} from "../constants"; -import { copyManual } from "../utils"; +import chalk from 'chalk' +import execa from 'execa' +import { existsSync, rmdirSync, rmSync, statSync } from 'fs-extra' +import { resolve } from 'path' +import readline from 'readline' +import { log } from '..' +import { ENGINE_DIR, PATCH_ARGS, SRC_DIR } from '../constants' +import { copyManual } from '../utils' class Patch { - public name: string; - public action: string; - public src: string | string[]; - public type: "file" | "manual"; - public status: number[]; - public markers?: { - [key: string]: [string, string]; - }; - public indent?: number; - public options: { - minimal?: boolean; - noIgnore?: boolean; - }; - private _done: boolean = false; + public name: string + public action: string + public src: string | string[] + public type: 'file' | 'manual' + public status: number[] + public markers?: { + [key: string]: [string, string] + } + public indent?: number + public options: { + minimal?: boolean + noIgnore?: boolean + } + private _done: boolean = false - private error: Error | unknown; + private error: Error | unknown - private async applyAsManual() { - return new Promise(async (res, rej) => { - try { - switch (this.action) { - case "copy": - if (typeof this.src == "string") { - copyManual( - this.src, - this.options.noIgnore - ); - } - - if (Array.isArray(this.src)) { - this.src.forEach((i) => { - copyManual( - i, - this.options.noIgnore - ); - }); - } - - break; - case "delete": - if (typeof this.src == "string") { - if ( - !existsSync( - resolve( - ENGINE_DIR, - this.src - ) - ) - ) - return log.error( - `We were unable to delete the file or directory \`${this.src}\` as it doesn't exist in the src directory.` - ); - - if ( - statSync( - resolve( - ENGINE_DIR, - this.src - ) - ).isDirectory() - ) { - rmdirSync( - resolve( - ENGINE_DIR, - this.src - ) - ); - } else { - rmSync( - resolve( - ENGINE_DIR, - this.src - ) - ); - } - } - - if (Array.isArray(this.src)) { - this.src.forEach((i) => { - if ( - !existsSync( - resolve( - ENGINE_DIR, - i - ) - ) - ) - return log.error( - `We were unable to delete the file or directory \`${i}\` as it doesn't exist in the src directory.` - ); - - if ( - statSync( - resolve( - ENGINE_DIR, - i - ) - ).isDirectory() - ) { - rmdirSync( - resolve( - ENGINE_DIR, - i - ) - ); - } else { - rmSync( - resolve( - ENGINE_DIR, - i - ), - { force: true } - ); - } - }); - } - - break; - } - - res(true); - } catch (e) { - rej(e); + private async applyAsManual() { + return new Promise(async (res, rej) => { + try { + switch (this.action) { + case 'copy': + if (typeof this.src == 'string') { + copyManual(this.src, this.options.noIgnore) } - }); - } - private async applyAsPatch() { - return new Promise(async (res, rej) => { - try { - try { - await execa( - "git", - [ - "apply", - "-R", - ...PATCH_ARGS, - this.src as any - ], - { cwd: ENGINE_DIR } - ); - } catch (e) { - null; - } - - const { stdout, exitCode } = await execa( - "git", - [ - "apply", - ...PATCH_ARGS, - this.src as any - ], - { cwd: ENGINE_DIR } - ); - - if (exitCode == 0) res(true); - else throw stdout; - } catch (e) { - rej(e); + if (Array.isArray(this.src)) { + this.src.forEach((i) => { + copyManual(i, this.options.noIgnore) + }) } - }); - } - public async apply() { - if (!this.options.minimal) { - log.info( - `${chalk.gray( - `(${this.status[0]}/${this.status[1]})` - )} Applying ${this.name}...` - ); + break + case 'delete': + if (typeof this.src == 'string') { + if (!existsSync(resolve(ENGINE_DIR, this.src))) + return log.error( + `We were unable to delete the file or directory \`${this.src}\` as it doesn't exist in the src directory.` + ) + + if (statSync(resolve(ENGINE_DIR, this.src)).isDirectory()) { + rmdirSync(resolve(ENGINE_DIR, this.src)) + } else { + rmSync(resolve(ENGINE_DIR, this.src)) + } + } + + if (Array.isArray(this.src)) { + this.src.forEach((i) => { + if (!existsSync(resolve(ENGINE_DIR, i))) + return log.error( + `We were unable to delete the file or directory \`${i}\` as it doesn't exist in the src directory.` + ) + + if (statSync(resolve(ENGINE_DIR, i)).isDirectory()) { + rmdirSync(resolve(ENGINE_DIR, i)) + } else { + rmSync(resolve(ENGINE_DIR, i), { force: true }) + } + }) + } + + break } + res(true) + } catch (e) { + rej(e) + } + }) + } + + private async applyAsPatch() { + return new Promise(async (res, rej) => { + try { try { - if (this.type == "manual") - await this.applyAsManual(); - if (this.type == "file") - await this.applyAsPatch(); - - this.done = true; + await execa('git', ['apply', '-R', ...PATCH_ARGS, this.src as any], { + cwd: ENGINE_DIR, + }) } catch (e) { - this.error = e; - this.done = false; - } - } - - public get done() { - return this._done; - } - - public set done(_: any) { - this._done = _; - - if (!this.options.minimal) { - readline.moveCursor(process.stdout, 0, -1); - readline.clearLine(process.stdout, 1); - - log.info( - `${chalk.gray( - `(${this.status[0]}/${this.status[1]})` - )} Applying ${this.name}... ${chalk[ - this._done ? "green" : "red" - ].bold( - this._done ? "Done ✔" : "Error ❗" - )}` - ); + null } - if (this.error) { - throw this.error; - } + const { stdout, exitCode } = await execa( + 'git', + ['apply', ...PATCH_ARGS, this.src as any], + { cwd: ENGINE_DIR } + ) + + if (exitCode == 0) res(true) + else throw stdout + } catch (e) { + rej(e) + } + }) + } + + public async apply() { + if (!this.options.minimal) { + log.info( + `${chalk.gray(`(${this.status[0]}/${this.status[1]})`)} Applying ${ + this.name + }...` + ) } - constructor({ - name, - action, - src, - type, - status, - markers, - indent, - options - }: { - name: string; - action?: string; - src?: string | string[]; - type: "file" | "manual"; - status: number[]; - markers?: { - [key: string]: [string, string]; - }; - indent?: number; - options: { - minimal?: boolean; - noIgnore?: boolean; - }; - }) { - this.name = name; - this.action = action || ""; - this.src = src || resolve(SRC_DIR, name); - this.type = type; - this.status = status; - this.markers = markers; - this.indent = indent; - this.options = options; + try { + if (this.type == 'manual') await this.applyAsManual() + if (this.type == 'file') await this.applyAsPatch() + + this.done = true + } catch (e) { + this.error = e + this.done = false } + } + + public get done() { + return this._done + } + + public set done(_: any) { + this._done = _ + + if (!this.options.minimal) { + readline.moveCursor(process.stdout, 0, -1) + readline.clearLine(process.stdout, 1) + + log.info( + `${chalk.gray(`(${this.status[0]}/${this.status[1]})`)} Applying ${ + this.name + }... ${chalk[this._done ? 'green' : 'red'].bold( + this._done ? 'Done ✔' : 'Error ❗' + )}` + ) + } + + if (this.error) { + throw this.error + } + } + + constructor({ + name, + action, + src, + type, + status, + markers, + indent, + options, + }: { + name: string + action?: string + src?: string | string[] + type: 'file' | 'manual' + status: number[] + markers?: { + [key: string]: [string, string] + } + indent?: number + options: { + minimal?: boolean + noIgnore?: boolean + } + }) { + this.name = name + this.action = action || '' + this.src = src || resolve(SRC_DIR, name) + this.type = type + this.status = status + this.markers = markers + this.indent = indent + this.options = options + } } -export default Patch; +export default Patch diff --git a/src/index.ts b/src/index.ts index cfbced7..2a6d1c8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,108 +1,85 @@ -import chalk from "chalk"; -import commander, { Command } from "commander"; -import { existsSync, readFileSync } from "fs"; -import { resolve } from "path"; -import { commands } from "./cmds"; -import { ENGINE_DIR } from "./constants"; -import Log from "./log"; -import { shaCheck } from "./middleware/sha-check"; -import { updateCheck } from "./middleware/update-check"; -import { errorHandler } from "./utils"; +import chalk from 'chalk' +import commander, { Command } from 'commander' +import { existsSync, readFileSync } from 'fs' +import { resolve } from 'path' +import { commands } from './cmds' +import { ENGINE_DIR } from './constants' +import Log from './log' +import { shaCheck } from './middleware/sha-check' +import { updateCheck } from './middleware/update-check' +import { errorHandler } from './utils' -const program = new Command(); +const program = new Command() -export let log = new Log(); +export let log = new Log() -program - .storeOptionsAsProperties(false) - .passCommandToAction(false); +program.storeOptionsAsProperties(false).passCommandToAction(false) -const { dot, firefox, melon } = - require("../package.json").versions; +const { dot, firefox, melon } = require('../package.json').versions -let reportedFFVersion; +let reportedFFVersion -if ( - existsSync( - resolve( - ENGINE_DIR, - "browser", - "config", - "version.txt" - ) - ) -) { - const version = readFileSync( - resolve( - ENGINE_DIR, - "browser", - "config", - "version.txt" - ), - "utf-8" - ).replace(/\n/g, ""); +if (existsSync(resolve(ENGINE_DIR, 'browser', 'config', 'version.txt'))) { + const version = readFileSync( + resolve(ENGINE_DIR, 'browser', 'config', 'version.txt'), + 'utf-8' + ).replace(/\n/g, '') - if (version !== firefox) reportedFFVersion = version; + if (version !== firefox) reportedFFVersion = version } -export const bin_name = "melon"; +export const bin_name = 'melon' program.version(` -\t${chalk.bold("Dot Browser")} ${dot} -\t${chalk.bold("Firefox")} ${firefox} ${ - reportedFFVersion - ? `(being reported as ${reportedFFVersion})` - : `` +\t${chalk.bold('Dot Browser')} ${dot} +\t${chalk.bold('Firefox')} ${firefox} ${ + reportedFFVersion ? `(being reported as ${reportedFFVersion})` : `` } -\t${chalk.bold("Melon")} ${melon} +\t${chalk.bold('Melon')} ${melon} ${ - reportedFFVersion - ? `Mismatch detected between expected Firefox version and the actual version. + reportedFFVersion + ? `Mismatch detected between expected Firefox version and the actual version. You may have downloaded the source code using a different version and then switched to another branch.` - : `` + : `` } -`); -program.name(bin_name); +`) +program.name(bin_name) commands.forEach((command) => { - if (command.flags) { - if ( - command.flags.platforms && - !command.flags.platforms.includes( - process.platform - ) - ) { - return; - } + if (command.flags) { + if ( + command.flags.platforms && + !command.flags.platforms.includes(process.platform) + ) { + return } + } - const _cmd = commander.command(command.cmd); + const _cmd = commander.command(command.cmd) - _cmd.description(command.description); + _cmd.description(command.description) - command?.aliases?.forEach((alias) => { - _cmd.alias(alias); - }); + command?.aliases?.forEach((alias) => { + _cmd.alias(alias) + }) - command?.options?.forEach((opt) => { - _cmd.option(opt.arg, opt.description); - }); + command?.options?.forEach((opt) => { + _cmd.option(opt.arg, opt.description) + }) - _cmd.action(async (...args: any) => { - await shaCheck(command.cmd); - await updateCheck(); + _cmd.action(async (...args: any) => { + await shaCheck(command.cmd) + await updateCheck() - command.controller(...args); - }); + command.controller(...args) + }) - program.addCommand(_cmd); -}); + program.addCommand(_cmd) +}) -process.on("uncaughtException", errorHandler); -process.on("unhandledException", (err) => - errorHandler(err, true) -); +process.on('uncaughtException', errorHandler) +process.on('unhandledException', (err) => errorHandler(err, true)) -program.parse(process.argv); +program.parse(process.argv) diff --git a/src/interfaces/patch.ts b/src/interfaces/patch.ts index b527f82..cf75c46 100644 --- a/src/interfaces/patch.ts +++ b/src/interfaces/patch.ts @@ -1,9 +1,9 @@ export interface IPatch { - name: string; - action: string; - src: string | string[]; - markers?: { - [key: string]: [string, string]; - }; - indent?: number; + name: string + action: string + src: string | string[] + markers?: { + [key: string]: [string, string] + } + indent?: number } diff --git a/src/log.ts b/src/log.ts index 5a5a646..776dd29 100644 --- a/src/log.ts +++ b/src/log.ts @@ -1,70 +1,51 @@ -import chalk from "chalk"; +import chalk from 'chalk' class Log { - private startTime: number; + private startTime: number - constructor() { - const d = new Date(); + constructor() { + const d = new Date() - this.startTime = d.getTime(); + this.startTime = d.getTime() + } + + getDiff() { + const d = new Date() + + const currentTime = d.getTime() + + const elapsedTime = currentTime - this.startTime + + var secs = Math.floor((elapsedTime / 1000) % 60) + var mins = Math.floor((elapsedTime / (60 * 1000)) % 60) + var hours = Math.floor((elapsedTime / (60 * 60 * 1000)) % 24) + + const format = (r: number) => { + return r.toString().length == 1 ? '0' + r : r } - getDiff() { - const d = new Date(); + return `${format(hours)}:${format(mins)}:${format(secs)}` + } - const currentTime = d.getTime(); + info(...args: any[]) { + console.info(chalk.blueBright.bold(this.getDiff()), ...args) + } - const elapsedTime = currentTime - this.startTime; + warning(...args: any[]) { + console.info(chalk.yellowBright.bold(' WARNING'), ...args) + } - var secs = Math.floor((elapsedTime / 1000) % 60); - var mins = Math.floor( - (elapsedTime / (60 * 1000)) % 60 - ); - var hours = Math.floor( - (elapsedTime / (60 * 60 * 1000)) % 24 - ); + hardWarning(...args: any[]) { + console.info('', chalk.bgRed.bold('WARNING'), ...args) + } - const format = (r: number) => { - return r.toString().length == 1 ? "0" + r : r; - }; + success(...args: any[]) { + console.log(`\n${chalk.greenBright.bold('SUCCESS')}`, ...args) + } - return `${format(hours)}:${format(mins)}:${format( - secs - )}`; - } - - info(...args: any[]) { - console.info( - chalk.blueBright.bold(this.getDiff()), - ...args - ); - } - - warning(...args: any[]) { - console.info( - chalk.yellowBright.bold(" WARNING"), - ...args - ); - } - - hardWarning(...args: any[]) { - console.info( - "", - chalk.bgRed.bold("WARNING"), - ...args - ); - } - - success(...args: any[]) { - console.log( - `\n${chalk.greenBright.bold("SUCCESS")}`, - ...args - ); - } - - error(...args: any[]) { - throw new Error(...args); - } + error(...args: any[]) { + throw new Error(...args) + } } -export default Log; +export default Log diff --git a/src/manual-patches.ts b/src/manual-patches.ts index 81fb9e7..bcb2332 100644 --- a/src/manual-patches.ts +++ b/src/manual-patches.ts @@ -1,32 +1,26 @@ -import { sync } from "glob"; -import { SRC_DIR } from "./constants"; -import { IPatch } from "./interfaces/patch"; +import { sync } from 'glob' +import { SRC_DIR } from './constants' +import { IPatch } from './interfaces/patch' -let files = sync("**/*", { - nodir: true, - cwd: SRC_DIR +let files = sync('**/*', { + nodir: true, + cwd: SRC_DIR, }).filter( - (f) => - !( - f.endsWith(".patch") || - f.split("/").includes("node_modules") - ) -); + (f) => !(f.endsWith('.patch') || f.split('/').includes('node_modules')) +) -const manualPatches: IPatch[] = []; +const manualPatches: IPatch[] = [] files.map((i) => { - const group = i.split("/")[0]; + const group = i.split('/')[0] - if (!manualPatches.find((m) => m.name == group)) { - manualPatches.push({ - name: group, - action: "copy", - src: files.filter( - (f) => f.split("/")[0] == group - ) - }); - } -}); + if (!manualPatches.find((m) => m.name == group)) { + manualPatches.push({ + name: group, + action: 'copy', + src: files.filter((f) => f.split('/')[0] == group), + }) + } +}) -export default manualPatches; +export default manualPatches diff --git a/src/middleware/sha-check.ts b/src/middleware/sha-check.ts index 6f9b500..e7e7ebc 100644 --- a/src/middleware/sha-check.ts +++ b/src/middleware/sha-check.ts @@ -1,53 +1,34 @@ -import execa from "execa"; -import { existsSync, readFileSync } from "fs-extra"; -import { resolve } from "path"; -import { bin_name, log } from ".."; +import execa from 'execa' +import { existsSync, readFileSync } from 'fs-extra' +import { resolve } from 'path' +import { bin_name, log } from '..' -const blacklistedCommands = [ - "reset", - "init", - "set-branch" -]; +const blacklistedCommands = ['reset', 'init', 'set-branch'] export const shaCheck = async (command: string) => { - if ( - blacklistedCommands.filter((c) => - command.startsWith(c) - ).length !== 0 || - !existsSync( - resolve( - process.cwd(), - ".dotbuild", - "metadata" - ) - ) - ) - return; + if ( + blacklistedCommands.filter((c) => command.startsWith(c)).length !== 0 || + !existsSync(resolve(process.cwd(), '.dotbuild', 'metadata')) + ) + return - const metadata = JSON.parse( - readFileSync( - resolve( - process.cwd(), - ".dotbuild", - "metadata" - ), - "utf-8" - ) - ); + const metadata = JSON.parse( + readFileSync(resolve(process.cwd(), '.dotbuild', 'metadata'), 'utf-8') + ) - const { stdout: currentBranch } = await execa("git", [ - "branch", - "--show-current" - ]); + const { stdout: currentBranch } = await execa('git', [ + 'branch', + '--show-current', + ]) - if (metadata && metadata.branch) { - if (metadata.branch !== currentBranch) { - log.warning(`The current branch \`${currentBranch}\` differs from the original branch \`${metadata.branch}\`. + if (metadata && metadata.branch) { + if (metadata.branch !== currentBranch) { + log.warning(`The current branch \`${currentBranch}\` differs from the original branch \`${metadata.branch}\`. \t If you are changing the Firefox version, you will need to reset the tree \t with |${bin_name} reset --hard| and then |${bin_name} download|. -\t Or you can change the default branch by typing |${bin_name} set-branch |.`); - } +\t Or you can change the default branch by typing |${bin_name} set-branch |.`) } -}; + } +} diff --git a/src/middleware/update-check.ts b/src/middleware/update-check.ts index 6a64069..37a1e36 100644 --- a/src/middleware/update-check.ts +++ b/src/middleware/update-check.ts @@ -1,31 +1,24 @@ -import axios from "axios"; -import { log } from "../"; +import axios from 'axios' +import { log } from '../' -const pjson = require("../../package.json"); +const pjson = require('../../package.json') export const updateCheck = async () => { - const firefoxVersion = - pjson.versions["firefox-display"]; + const firefoxVersion = pjson.versions['firefox-display'] - try { - const { data } = await axios.get( - `https://product-details.mozilla.org/1.0/firefox_history_major_releases.json`, - { timeout: 1000 } - ); + try { + const { data } = await axios.get( + `https://product-details.mozilla.org/1.0/firefox_history_major_releases.json`, + { timeout: 1000 } + ) - if (data) { - let version = - Object.keys(data)[ - Object.keys(data).length - 1 - ]; + if (data) { + let version = Object.keys(data)[Object.keys(data).length - 1] - if ( - firefoxVersion && - version !== firefoxVersion - ) - log.warning( - `Latest version of Firefox (${version}) does not match frozen version (${firefoxVersion}).` - ); - } - } catch (e) {} -}; + if (firefoxVersion && version !== firefoxVersion) + log.warning( + `Latest version of Firefox (${version}) does not match frozen version (${firefoxVersion}).` + ) + } + } catch (e) {} +} diff --git a/src/types.d.ts b/src/types.d.ts index 897e458..fbafef5 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,19 +1,19 @@ export interface Cmd { - cmd: string; - description: string; + cmd: string + description: string - controller: (...args: any) => void; + controller: (...args: any) => void - options?: CmdOption[]; - aliases?: string[]; - flags?: { - platforms?: CmdFlagPlatform[]; - }; + options?: CmdOption[] + aliases?: string[] + flags?: { + platforms?: CmdFlagPlatform[] + } } export interface CmdOption { - arg: string; - description: string; + arg: string + description: string } -export type CmdFlagPlatform = NodeJS.Platform; +export type CmdFlagPlatform = NodeJS.Platform diff --git a/src/utils/delay.ts b/src/utils/delay.ts index 92ae0bb..6ce370a 100644 --- a/src/utils/delay.ts +++ b/src/utils/delay.ts @@ -1,5 +1,5 @@ export const delay = (delay: number) => { - return new Promise((resolve) => { - setTimeout(() => resolve(true), delay); - }); -}; + return new Promise((resolve) => { + setTimeout(() => resolve(true), delay) + }) +} diff --git a/src/utils/dispatch.ts b/src/utils/dispatch.ts index 779d310..6993c3f 100644 --- a/src/utils/dispatch.ts +++ b/src/utils/dispatch.ts @@ -1,49 +1,42 @@ -import execa from "execa"; -import { log } from ".."; +import execa from 'execa' +import { log } from '..' const handle = (data: any, killOnError?: boolean) => { - const d = data.toString(); + const d = data.toString() - d.split("\n").forEach((line: any) => { - if (line.length !== 0) - log.info( - line.replace(/\s\d{1,5}:\d\d\.\d\d /g, "") - ); - }); + d.split('\n').forEach((line: any) => { + if (line.length !== 0) log.info(line.replace(/\s\d{1,5}:\d\d\.\d\d /g, '')) + }) - if (killOnError) { - log.error("Command failed. See error above."); - process.exit(1); - } -}; + if (killOnError) { + log.error('Command failed. See error above.') + process.exit(1) + } +} export const dispatch = ( - cmd: string, - args?: any[], - cwd?: string, - noLog?: boolean, - killOnError?: boolean + cmd: string, + args?: any[], + cwd?: string, + noLog?: boolean, + killOnError?: boolean ) => { - return new Promise((resolve, reject) => { - process.env.MACH_USE_SYSTEM_PYTHON = "true"; + return new Promise((resolve, reject) => { + process.env.MACH_USE_SYSTEM_PYTHON = 'true' - const proc = execa(cmd, args, { - cwd: cwd ? cwd : process.cwd(), - env: process.env - }); + const proc = execa(cmd, args, { + cwd: cwd ? cwd : process.cwd(), + env: process.env, + }) - proc.stdout?.on("data", (d) => handle(d)); - proc.stderr?.on("data", (d) => handle(d)); + proc.stdout?.on('data', (d) => handle(d)) + proc.stderr?.on('data', (d) => handle(d)) - proc.stdout?.on("error", (d) => - handle(d, killOnError) - ); - proc.stderr?.on("error", (d) => - handle(d, killOnError) - ); + proc.stdout?.on('error', (d) => handle(d, killOnError)) + proc.stderr?.on('error', (d) => handle(d, killOnError)) - proc.on("exit", () => { - resolve(true); - }); - }); -}; + proc.on('exit', () => { + resolve(true) + }) + }) +} diff --git a/src/utils/error-handler.ts b/src/utils/error-handler.ts index cac30c8..f1bf9d1 100644 --- a/src/utils/error-handler.ts +++ b/src/utils/error-handler.ts @@ -1,45 +1,39 @@ -import chalk from "chalk"; -import { readFileSync } from "fs-extra"; -import { resolve } from "path"; -import { log } from ".."; +import chalk from 'chalk' +import { readFileSync } from 'fs-extra' +import { resolve } from 'path' +import { log } from '..' -export const errorHandler = ( - err: Error, - isUnhandledRej: boolean -) => { - let cc = readFileSync( - resolve(process.cwd(), ".dotbuild", "command"), - "utf-8" - ); - cc = cc.replace(/(\r\n|\n|\r)/gm, ""); +export const errorHandler = (err: Error, isUnhandledRej: boolean) => { + let cc = readFileSync(resolve(process.cwd(), '.dotbuild', 'command'), 'utf-8') + cc = cc.replace(/(\r\n|\n|\r)/gm, '') + console.log( + `\n ${chalk.redBright.bold( + 'ERROR' + )} An error occurred while running command ["${cc + .split(' ') + .join('", "')}"]:` + ) + console.log( + `\n\t`, + isUnhandledRej + ? err.toString().replace(/\n/g, '\n\t ') + : err.message.replace(/\n/g, '\n\t ') + ) + if (err.stack || isUnhandledRej) { + const stack: any = err.stack?.split('\n') + stack.shift() + stack.shift() console.log( - `\n ${chalk.redBright.bold( - "ERROR" - )} An error occurred while running command ["${cc - .split(" ") - .join('", "')}"]:` - ); - console.log( - `\n\t`, - isUnhandledRej - ? err.toString().replace(/\n/g, "\n\t ") - : err.message.replace(/\n/g, "\n\t ") - ); - if (err.stack || isUnhandledRej) { - const stack: any = err.stack?.split("\n"); - stack.shift(); - stack.shift(); - console.log( - `\t`, - stack - .join("\n") - .replace(/(\r\n|\n|\r)/gm, "") - .replace(/ at /g, "\n\t • ") - ); - } + `\t`, + stack + .join('\n') + .replace(/(\r\n|\n|\r)/gm, '') + .replace(/ at /g, '\n\t • ') + ) + } - console.log(); - log.info("Exiting due to error."); - process.exit(1); -}; + console.log() + log.info('Exiting due to error.') + process.exit(1) +} diff --git a/src/utils/import.ts b/src/utils/import.ts index 8c40439..86638bb 100644 --- a/src/utils/import.ts +++ b/src/utils/import.ts @@ -1,66 +1,46 @@ import { - appendFileSync, - ensureSymlink, - lstatSync, - readFileSync -} from "fs-extra"; -import { resolve } from "path"; -import rimraf from "rimraf"; -import { ENGINE_DIR, SRC_DIR } from "../constants"; + appendFileSync, + ensureSymlink, + lstatSync, + readFileSync, +} from 'fs-extra' +import { resolve } from 'path' +import rimraf from 'rimraf' +import { ENGINE_DIR, SRC_DIR } from '../constants' const getChunked = (location: string) => { - return location.replace(/\\/g, "/").split("/"); -}; + return location.replace(/\\/g, '/').split('/') +} -export const copyManual = ( - name: string, - noIgnore?: boolean -) => { +export const copyManual = (name: string, noIgnore?: boolean) => { + try { try { - try { - if ( - !lstatSync( - resolve( - ENGINE_DIR, - ...getChunked(name) - ) - ).isSymbolicLink() - ) { - rimraf.sync( - resolve( - ENGINE_DIR, - ...getChunked(name) - ) - ); - } - } catch (e) {} + if ( + !lstatSync(resolve(ENGINE_DIR, ...getChunked(name))).isSymbolicLink() + ) { + rimraf.sync(resolve(ENGINE_DIR, ...getChunked(name))) + } + } catch (e) {} - ensureSymlink( - resolve(SRC_DIR, ...getChunked(name)), - resolve(ENGINE_DIR, ...getChunked(name)) - ); + ensureSymlink( + resolve(SRC_DIR, ...getChunked(name)), + resolve(ENGINE_DIR, ...getChunked(name)) + ) - if (!noIgnore) { - const gitignore = readFileSync( - resolve(ENGINE_DIR, ".gitignore"), - "utf-8" - ); + if (!noIgnore) { + const gitignore = readFileSync(resolve(ENGINE_DIR, '.gitignore'), 'utf-8') - if ( - !gitignore.includes( - getChunked(name).join("/") - ) - ) - appendFileSync( - resolve(ENGINE_DIR, ".gitignore"), - `\n${getChunked(name).join("/")}` - ); - } - - return; - } catch (e) { - console.log(e); - process.exit(0); - // return e; + if (!gitignore.includes(getChunked(name).join('/'))) + appendFileSync( + resolve(ENGINE_DIR, '.gitignore'), + `\n${getChunked(name).join('/')}` + ) } -}; + + return + } catch (e) { + console.log(e) + process.exit(0) + // return e; + } +} diff --git a/src/utils/index.ts b/src/utils/index.ts index e9f2a5c..a864f5e 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,6 +1,6 @@ -export * from "./delay"; -export * from "./dispatch"; -export * from "./error-handler"; -export * from "./import"; -export * from "./version"; -export * from "./write-metadata"; +export * from './delay' +export * from './dispatch' +export * from './error-handler' +export * from './import' +export * from './version' +export * from './write-metadata' diff --git a/src/utils/version.ts b/src/utils/version.ts index ed22ec1..1c89fcc 100644 --- a/src/utils/version.ts +++ b/src/utils/version.ts @@ -1,11 +1,9 @@ -import axios from "axios"; +import axios from 'axios' export const getLatestFF = async () => { - const { data } = await axios.get( - `https://product-details.mozilla.org/1.0/firefox_history_major_releases.json` - ); + const { data } = await axios.get( + `https://product-details.mozilla.org/1.0/firefox_history_major_releases.json` + ) - return Object.keys(data)[ - Object.keys(data).length - 1 - ]; -}; + return Object.keys(data)[Object.keys(data).length - 1] +} diff --git a/src/utils/write-metadata.ts b/src/utils/write-metadata.ts index 5c5c51c..7c34af4 100644 --- a/src/utils/write-metadata.ts +++ b/src/utils/write-metadata.ts @@ -1,26 +1,20 @@ -import execa from "execa"; -import { writeFileSync } from "fs-extra"; -import { resolve } from "path"; +import execa from 'execa' +import { writeFileSync } from 'fs-extra' +import { resolve } from 'path' -const pjson = require("../../package.json"); +const pjson = require('../../package.json') export const writeMetadata = async () => { - const { stdout: sha } = await execa("git", [ - "rev-parse", - "HEAD" - ]); - const { stdout: branch } = await execa("git", [ - "branch", - "--show-current" - ]); + const { stdout: sha } = await execa('git', ['rev-parse', 'HEAD']) + const { stdout: branch } = await execa('git', ['branch', '--show-current']) - writeFileSync( - resolve(process.cwd(), ".dotbuild", "metadata"), - JSON.stringify({ - sha, - branch, - birth: Date.now(), - versions: pjson.versions - }) - ); -}; + writeFileSync( + resolve(process.cwd(), '.dotbuild', 'metadata'), + JSON.stringify({ + sha, + branch, + birth: Date.now(), + versions: pjson.versions, + }) + ) +} diff --git a/tsconfig.json b/tsconfig.json index e41e17f..460394a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,69 +1,64 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "es2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, - "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, - // "lib": [], /* Specify library files to be included in the compilation. */ - // "allowJs": true, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - // "declaration": true, /* Generates corresponding '.d.ts' file. */ - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./dist" /* Redirect output structure to the directory. */, - // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - /* Strict Type-Checking Options */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */, - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - /* Advanced Options */ - "skipLibCheck": true /* Skip type checking of declaration files. */, - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ - }, - "exclude": [ - "node_modules/**/*", - "firefox-*/**/*", - "gecko", - "engine/**/*" - ] + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./dist" /* Redirect output structure to the directory. */, + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */, + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "exclude": ["node_modules/**/*", "firefox-*/**/*", "gecko", "engine/**/*"] }