♻️ Refactor commands some more to make them simpler

This commit is contained in:
trickypr 2021-12-21 19:05:40 +11:00
parent f4982fc699
commit 7572f8527a
6 changed files with 79 additions and 219 deletions

View file

@ -7,7 +7,6 @@ import {
execute,
exportFile,
fixLineEndings,
importPatches,
init,
licenseCheck,
melonPackage,

View file

@ -6,7 +6,6 @@ export * from './download-artifacts'
export * from './execute'
export * from './export-file'
export * from './fix-le'
export * from './import-patches'
export * from './init'
export * from './license-check'
export * from './package'

View file

@ -37,29 +37,18 @@ function importMelonPatches(): ListrTaskGroup {
for (const brandingStyle of readdirSync(BRANDING_DIR).filter((file) =>
lstatSync(join(BRANDING_DIR, file)).isDirectory()
)) {
patches.push(new BrandingPatch(brandingStyle, false))
patches.push(new BrandingPatch(brandingStyle))
}
}
return patchMethod(
'melon',
patches,
async (patch, i) => await patch.applyWithStatus([i, patches.length])
)
return patchMethod('melon', patches, async (patch) => await patch.apply())
}
function importFolders(): ListrTaskGroup {
return patchMethod(
'folder',
manualPatches.map(
(patch, i) =>
new ManualPatch(
patch.name,
[i, manualPatches.length],
{},
patch.action,
patch.src
)
(patch) => new ManualPatch(patch.name, patch.action, patch.src)
),
async (patch) => await patch.apply()
)
@ -68,9 +57,8 @@ function importFolders(): ListrTaskGroup {
function importGitPatch(): ListrTaskGroup {
return patchMethod(
'git',
sync('**/*.patch').map(
(file, i, array) =>
new PatchFile(file, [i, array.length], {}, resolve(SRC_DIR, file))
sync('**/*.patch', { nodir: true, cwd: SRC_DIR }).map(
(file) => new PatchFile(file, resolve(SRC_DIR, file))
),
async (patch) => await patch.apply()
)

View file

@ -36,8 +36,8 @@ export class BrandingPatch extends PatchBase {
outputPath: string
configPath: string
constructor(name: string, minimal?: boolean) {
super(`Browser branding: ${name}`, [0, 0], { minimal })
constructor(name: string) {
super(`Browser branding: ${name}`)
this.name = name
this.outputPath = join(BRANDING_STORE, name)
@ -64,44 +64,25 @@ export class BrandingPatch extends PatchBase {
}
async apply(): Promise<void> {
this.start()
this.checkForFaults()
try {
log.debug('Checking branding files')
const brandingConfig = {
brandingGenericName: config.name,
brandingVendor: config.vendor,
this.checkForFaults()
const brandingConfig = {
brandingGenericName: config.name,
brandingVendor: config.vendor,
...defaultBrandsConfig,
...(config.brands[this.name] || {}),
}
log.debug(`Creating folder ${this.outputPath}`)
if (existsSync(this.outputPath))
rmdirSync(this.outputPath, { recursive: true })
mkdirSync(this.outputPath, { recursive: true })
log.debug('Setup images')
await this.setupImages()
log.debug(`Setup locales`)
this.setupLocales(brandingConfig)
log.debug(`Copying files from ${BRANDING_FF}`)
await this.copyMozillaFiles(brandingConfig)
this.done = true
} catch (e) {
this.error = e
this.done = false
...defaultBrandsConfig,
...(config.brands[this.name] || {}),
}
if (existsSync(this.outputPath))
rmdirSync(this.outputPath, { recursive: true })
mkdirSync(this.outputPath, { recursive: true })
await this.setupImages()
this.setupLocales(brandingConfig)
await this.copyMozillaFiles(brandingConfig)
}
private async copyMozillaFiles(brandingConfig: {
@ -159,16 +140,12 @@ export class BrandingPatch extends PatchBase {
}
private async setupImages() {
log.debug('Creating default*.png files')
for (const size of [16, 22, 24, 32, 48, 64, 128, 256]) {
await sharp(join(this.configPath, 'logo.png'))
.resize(size, size)
.toFile(join(this.outputPath, `default${size}.png`))
}
log.debug('Creating firefox*.ico')
await sharp(join(this.configPath, 'logo.png'))
.resize(512, 512)
.toFile(join(this.outputPath, 'firefox.ico'))
@ -176,8 +153,6 @@ export class BrandingPatch extends PatchBase {
.resize(64, 64)
.toFile(join(this.outputPath, 'firefox64.ico'))
log.debug('Creating content/about-logo*.png')
mkdirSync(join(this.outputPath, 'content'), { recursive: true })
await sharp(join(this.configPath, 'logo.png'))

View file

@ -1,80 +1,16 @@
import chalk from 'chalk'
import execa from 'execa'
import { existsSync, rmdirSync, rmSync, statSync } from 'fs'
import { resolve } from 'path'
import readline from 'readline'
import { log } from '..'
import { discard } from '../commands'
import { ENGINE_DIR, PATCH_ARGS } from '../constants'
import { copyManual } from '../utils'
export abstract class PatchBase {
public name: string
protected status: number[]
protected options: {
minimal?: boolean
noIgnore?: boolean
}
private _done = false
protected error: Error | unknown
constructor(
name: string,
status: number[],
options: {
minimal?: boolean
noIgnore?: boolean
} = {}
) {
constructor(name: string) {
this.name = name
this.status = status
this.options = options
}
protected get done(): boolean {
return this._done
}
protected set done(_: boolean) {
this._done = _
if (this.options.minimal) return
// Move to the start of the last line
readline.moveCursor(process.stdout, 0, -1)
readline.clearLine(process.stdout, 1)
// Print the status
log.info(
`${chalk.gray(`(${this.status[0]}/${this.status[1]})`)} Applying ${
this.name
}... ${chalk[this._done ? 'green' : 'red'].bold(
this._done ? 'Done ✔' : 'Error ❗'
)}`
)
// If there is an error present, it should be thrown
if (this.error) {
throw this.error
}
}
protected start(): void {
if (this.options.minimal) return
log.info(
`${chalk.gray(`(${this.status[0]}/${this.status[1]})`)} Applying ${
this.name
}...`
)
}
public applyWithStatus(status: [number, number]): Promise<void> {
this.status = status
return this.apply()
}
protected filesExist(files: string[]): boolean {
@ -89,17 +25,8 @@ export class ManualPatch extends PatchBase {
private src: string | string[]
constructor(
name: string,
status: number[],
options: {
minimal?: boolean
noIgnore?: boolean
} = {},
action: 'copy' | 'delete',
src: string | string[]
) {
super(name, status, options)
constructor(name: string, action: 'copy' | 'delete', src: string | string[]) {
super(name)
this.action = action
this.src = src
@ -126,48 +53,39 @@ export class ManualPatch extends PatchBase {
}
async apply(): Promise<void> {
this.start()
try {
switch (this.action) {
case 'copy':
if (typeof this.src === 'string') {
await copyManual(this.src, this.options.noIgnore)
} else if (Array.isArray(this.src)) {
for (const item of this.src) {
await copyManual(item, this.options.noIgnore)
}
} else {
throw new Error(
`'${this.src}' is not a valid source. Please provide a string or an array`
)
switch (this.action) {
case 'copy':
if (typeof this.src === 'string') {
await copyManual(this.src)
} else if (Array.isArray(this.src)) {
for (const item of this.src) {
await copyManual(item)
}
} else {
throw new Error(
`'${this.src}' is not a valid source. Please provide a string or an array`
)
}
break
break
case 'delete':
if (typeof this.src === 'string') {
this.delete(ENGINE_DIR, this.src)
} else if (Array.isArray(this.src)) {
for (const item of this.src) {
this.delete(ENGINE_DIR, item)
}
} else {
throw new Error(
`'${this.src}' is not a valid source. Please provide a string or an array`
)
case 'delete':
if (typeof this.src === 'string') {
this.delete(ENGINE_DIR, this.src)
} else if (Array.isArray(this.src)) {
for (const item of this.src) {
this.delete(ENGINE_DIR, item)
}
} else {
throw new Error(
`'${this.src}' is not a valid source. Please provide a string or an array`
)
}
break
break
default:
throw new Error(`Unknown manual patch action: ${this.action}`)
}
this.done = true
} catch (e) {
this.error = e
this.done = false
default:
throw new Error(`Unknown manual patch action: ${this.action}`)
}
}
}
@ -175,43 +93,29 @@ export class ManualPatch extends PatchBase {
export class PatchFile extends PatchBase {
private src: string
constructor(
name: string,
status: number[],
options: {
minimal?: boolean
noIgnore?: boolean
} = {},
src: string
) {
super(name, status, options)
constructor(name: string, src: string) {
super(name)
this.src = src
}
async apply(): Promise<void> {
this.start()
try {
try {
await execa('git', ['apply', '-R', ...PATCH_ARGS, this.src], {
cwd: ENGINE_DIR,
})
} catch (e) {
null
}
const { stdout, exitCode } = await execa(
'git',
['apply', ...PATCH_ARGS, this.src],
{ cwd: ENGINE_DIR }
)
if (exitCode != 0) throw stdout
this.done = true
} catch (e) {
this.error = e
this.done = false
await execa('git', ['apply', '-R', ...PATCH_ARGS, this.src], {
cwd: ENGINE_DIR,
})
} catch (_e) {
// If the patch has already been applied, we want to revert it. Because
// there is no good way to check this we are just going to catch and
// discard the error
null
}
const { stdout, exitCode } = await execa(
'git',
['apply', ...PATCH_ARGS, this.src],
{ cwd: ENGINE_DIR }
)
if (exitCode != 0) throw stdout
}
}

View file

@ -10,10 +10,7 @@ import { ENGINE_DIR, SRC_DIR } from '../constants'
const getChunked = (location: string) => location.replace(/\\/g, '/').split('/')
export const copyManual = async (
name: string,
noIgnore?: boolean
): Promise<void> => {
export const copyManual = async (name: string): Promise<void> => {
// If the file exists and is not a symlink, we want to replace it with a
// symlink to our file, so remove it
if (
@ -41,13 +38,11 @@ export const copyManual = async (
)
}
if (!noIgnore) {
const gitignore = readFileSync(resolve(ENGINE_DIR, '.gitignore'), 'utf-8')
const gitignore = readFileSync(resolve(ENGINE_DIR, '.gitignore'), 'utf-8')
if (!gitignore.includes(getChunked(name).join('/')))
appendToFileSync(
resolve(ENGINE_DIR, '.gitignore'),
`\n${getChunked(name).join('/')}`
)
}
if (!gitignore.includes(getChunked(name).join('/')))
appendToFileSync(
resolve(ENGINE_DIR, '.gitignore'),
`\n${getChunked(name).join('/')}`
)
}