Applied Linting

This commit is contained in:
Christopher Allford 2022-03-16 23:05:50 -07:00
parent 57ab538668
commit 831a895db3
3 changed files with 95 additions and 56 deletions

View File

@ -1,9 +1,3 @@
/**
* Internal dependencies
*/
import { MONOREPO_ROOT } from '../../const';
import { access, exec } from '../../node-async';
/**
* External dependencies
*/
@ -11,6 +5,12 @@ import { CliUx, Command, Flags } from '@oclif/core';
import { join } from 'path';
import { tmpdir } from 'os';
/**
* Internal dependencies
*/
import { MONOREPO_ROOT } from '../../const';
import { access, exec } from '../../node-async';
export default class Merge extends Command {
static description =
'Merges another repository into this one with history.';
@ -30,12 +30,11 @@ export default class Merge extends Command {
];
static flags = {
branch: Flags.string(
{
description: 'The destination branch we want to merge into the monorepo.',
default: 'main'
}
)
branch: Flags.string( {
description:
'The destination branch we want to merge into the monorepo.',
default: 'main',
} ),
};
/**
@ -47,27 +46,41 @@ export default class Merge extends Command {
await this.checkDependencies();
await this.validateArgs( args.source, args.destination );
let confirmation = await CliUx.ux.confirm( 'WARNING: This command will DESTROY the history of your current branch. Are you sure you want to proceed? (y/n)' );
let confirmation = await CliUx.ux.confirm(
'WARNING: This command will DESTROY the history of your current branch. Are you sure you want to proceed? (y/n)'
);
if ( ! confirmation ) {
this.exit( 0 );
}
const repositoryPath = await this.cloneRepository( args.source );
await this.alterRepositoryHistory( args.source, repositoryPath, args.destination );
await this.alterRepositoryHistory(
args.source,
repositoryPath,
args.destination
);
confirmation = await CliUx.ux.confirm( 'Are you ready to merge ' + args.source + ' from ' + repositoryPath + '? (y/n)' );
confirmation = await CliUx.ux.confirm(
'Are you ready to merge ' +
args.source +
' from ' +
repositoryPath +
'? (y/n)'
);
if ( ! confirmation ) {
// Remove the repository we've cloned.
try {
await exec( 'rm -rf ' + repositoryPath );
} catch {}
this.exit( 0 );
}
await this.mergeRepository( args.source, repositoryPath, flags.branch );
this.log( 'Successfully merged ' + args.source + ' into ' + args.destination );
this.log(
'Successfully merged ' + args.source + ' into ' + args.destination
);
}
/**
@ -89,38 +102,43 @@ export default class Merge extends Command {
/**
* Validates all of the arguments to make sure they're compatible with the command.
*
*
* @param {string} source The GitHub repository we are merging.
* @param {string} destination The local path we're merging into.
*/
private async validateArgs( source: string, destination: string ): Promise< void > {
private async validateArgs(
source: string,
destination: string
): Promise< void > {
// We only support pulling from GitHub so the format needs to match that.
if ( ! source.match( /^[a-zA-Z0-9\-_]+\/[a-zA-Z0-9\-_]+$/ ) ) {
this.error(
'The "source" argument must be in "organization/repository" format'
);
}
// We can't merge into a directory that already exists.
let exists = false;
try {
await access( join( MONOREPO_ROOT, destination ) );
exists = true;
} catch (err: any) {
} catch ( err: any ) {
exists = false;
}
if ( exists ) {
this.error('The "destination" argument points to a directory that already exists');
this.error(
'The "destination" argument points to a directory that already exists'
);
}
}
/**
* Clones a repository from GitHub into a temporary directory and returns the path.
*
*
* @param {string} source The GitHub repository we want to clone.
*/
private async cloneRepository(source: string): Promise< string > {
private async cloneRepository( source: string ): Promise< string > {
// Show progress for the cloning.
const gitPath = 'https://github.com/' + source;
CliUx.ux.action.start( 'Cloning from ' + gitPath );
@ -140,16 +158,24 @@ export default class Merge extends Command {
/**
* Alters the commit history so that it appears as if it always existed within the monorepo.
*
*
* @param {string} source The GitHub repository we are merging.
* @param {string} cloneDir The directory we've cloned the repository into.
* @param {string} destination The monorepo directory we want to move the files into.
*/
private async alterRepositoryHistory( source: string, cloneDir: string, destination: string ): Promise< void > {
private async alterRepositoryHistory(
source: string,
cloneDir: string,
destination: string
): Promise< void > {
const filterCommand = [
'git-filter-repo',
'--to-subdirectory-filter \'' + destination + '\'',
'--message-callback=\'return re.sub(b"\\(#(\\d+)\\)", b"(https://github.com/' + source + '/pull/\\\\1)", re.sub(b"(?<!\\()(#\\d+)(?!\\))", b"' + source + '\\\\1", message))\''
"--to-subdirectory-filter '" + destination + "'",
'--message-callback=\'return re.sub(b"\\(#(\\d+)\\)", b"(https://github.com/' +
source +
'/pull/\\\\1)", re.sub(b"(?<!\\()(#\\d+)(?!\\))", b"' +
source +
'\\\\1", message))\'',
].join( ' ' );
CliUx.ux.action.start( 'Altering repository history' );
@ -165,12 +191,16 @@ export default class Merge extends Command {
/**
* Merges the cloned repository into the current one.
*
*
* @param {string} source The GitHub repository we are merging.
* @param {string} cloneDir The directory we've cloned the repository into.
* @param {string} branchToMerge The branch we want to merge from.
*/
private async mergeRepository( source: string, cloneDir: string, branchToMerge: string ): Promise< void > {
private async mergeRepository(
source: string,
cloneDir: string,
branchToMerge: string
): Promise< void > {
CliUx.ux.action.start( 'Merging repositories' );
// We need the cloned repository as a remote in order to merge it.
@ -185,9 +215,14 @@ export default class Merge extends Command {
} catch {
this.error( 'Failed to fetch clone repository' );
}
try {
await exec( 'git merge --allow-unrelated-histories ' + source + '/' + branchToMerge );
await exec(
'git merge --allow-unrelated-histories ' +
source +
'/' +
branchToMerge
);
} catch {
this.error( 'Failed to merge the repositories' );
}

View File

@ -1,3 +1,6 @@
/**
* External dependencies
*/
import { dirname } from 'path';
// Escape from ./tools/monorepo-merge/src

View File

@ -6,40 +6,41 @@ import { exec as nodeExec, ExecOptions } from 'child_process';
/**
* A promise wrapper for Node's `fs.access` function.
*
*
* @param {string} path The path to access.
* @param {number} [mode] The access mode.
*/
export async function access( path: PathLike, mode?: number ): Promise< void > {
return new Promise(
( resolve, reject ) => {
nodeAccess(path, mode, ( err ) => {
if ( err ) {
reject( err );
return;
}
return new Promise( ( resolve, reject ) => {
nodeAccess( path, mode, ( err ) => {
if ( err ) {
reject( err );
return;
}
resolve();
} );
}
);
resolve();
} );
} );
}
/**
* A promise wrapper for Node's `child_process.exec` function.
*
*
* @param {string} command The command to execute.
* @param {ExecOptions} [options] The options for the command.
*/
export async function exec( command: string, options?: ExecOptions ): Promise< string | Buffer > {
return new Promise( (resolve, reject ) => {
nodeExec( command, options, ( err, stdout, stderr ) => {
if ( err ) {
reject( stderr );
return;
}
export async function exec(
command: string,
options?: ExecOptions
): Promise< string | Buffer > {
return new Promise( ( resolve, reject ) => {
nodeExec( command, options, ( err, stdout, stderr ) => {
if ( err ) {
reject( stderr );
return;
}
resolve( stdout );
} );
} );
resolve( stdout );
} );
} );
}