This commit is contained in:
Laura Liberda 2021-02-01 11:44:18 +01:00
parent c7ca3c9816
commit 0538691173
6 changed files with 834 additions and 17 deletions

6
bin/run Normal file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env node
require('../build/src/index')
.run()
.then(require('@oclif/command/flush'))
.catch(require('@oclif/errors/handle'));

View file

@ -17,6 +17,21 @@
"lint:prettier": "yarn prettier --check src",
"lint:prettier:fix": "yarn prettier --check --write src"
},
"bin": {
"copycat": "./bin/run"
},
"files": [
"/bin",
"/build/src",
"/oclif.manifest.json"
],
"oclif": {
"commands": "./src/cli",
"bin": "copycat",
"plugins": [
"@oclif/plugin-help"
]
},
"husky": {
"hooks": {
"pre-commit": "yarn lint:fix"
@ -24,6 +39,9 @@
},
"dependencies": {
"@iarna/toml": "^2.2.5",
"@oclif/command": "^1.8.0",
"@oclif/config": "^1.17.0",
"@oclif/plugin-help": "^3.2.1",
"appdata-path": "^1.0.0",
"fs-extra": "^9.0.1",
"got": "^11.5.1",
@ -35,6 +53,7 @@
"@graphql-codegen/introspection": "1.17.6",
"@graphql-codegen/typescript": "1.17.6",
"@graphql-codegen/typescript-resolvers": "1.17.6",
"@oclif/dev-cli": "^1.26.0",
"@types/fs-extra": "^9.0.1",
"@types/iarna__toml": "^2.0.0",
"@types/js-yaml": "^3.12.5",

39
src/cli/replicate.ts Normal file
View file

@ -0,0 +1,39 @@
import { Command, flags } from '@oclif/command';
import assert from 'assert';
import Copycat from '../copycat';
import { ENTITY_TYPE } from '../types';
import { parsePath } from '../utils';
export default class Replicate extends Command {
static description = 'Replicate issues/MRs between repositories';
static flags = {
help: flags.help({ char: 'h' }),
source: flags.string({ char: 's', required: true }),
dest: flags.string({ char: 'd', required: true }),
};
static args = [];
async run() {
const { flags } = this.parse(Replicate);
const sourcePath = parsePath(flags.source);
const destPath = parsePath(flags.dest);
assert(sourcePath.entity === ENTITY_TYPE.ISSUE, 'Only issues are supported now');
const cc = new Copycat();
await cc.initialize();
const sourceVendor = cc.vendorManagers.find((v) => v.vendor.domain === sourcePath.domain);
assert(sourceVendor, 'Source vendor not found in config');
const destVendor = cc.vendorManagers.find((v) => v.vendor.domain === destPath.domain);
assert(destVendor, 'Destination vendor not found in config');
const sourceRepo = await sourceVendor.getRepo(sourcePath.path);
const destRepo = await destVendor.getRepo(destPath.path);
const sourceEntity = await sourceRepo.getIssue(sourcePath.entityID);
const replicatedEntity = await destRepo.replicateIssue(sourceEntity);
console.log(replicatedEntity);
}
}

11
src/index.ts Executable file
View file

@ -0,0 +1,11 @@
#!/usr/bin/env ts-node
import { run } from '@oclif/command';
if (process.argv[1] === __filename) {
(run() as Promise<any>)
.then(require('@oclif/command/flush'))
.catch(require('@oclif/errors/handle'));
}
export { run };

View file

@ -9,7 +9,7 @@
import { readFileSync, writeFileSync } from 'fs-extra';
import toml from '@iarna/toml';
import appdataPath from 'appdata-path';
import { CopycatConfig, CopycatProfile } from './types';
import { CopycatConfig, ENTITY_TYPE } from './types';
export const DEFAULT_CONFIG: CopycatConfig = {
vendorConfigs: [],
@ -33,3 +33,48 @@ export const setConfig = (config: CopycatConfig) =>
writeFileSync(getConfigPath(), toml.stringify({ ...DEFAULT_CONFIG, ...config } as any), {
encoding: 'utf-8',
});
export type Path =
| {
domain: string;
path: string;
entity: ENTITY_TYPE;
entityID: string;
}
| {
domain: string;
path: string;
entity: null;
entityID: null;
};
export const parsePath = (path: string): Path => {
let mobj = /^https?:\/\/([^/]+)\/([a-zA-Z\d-]+\/(?:[a-zA-Z\d-]+\/)*?[a-zA-Z\d-]+)(?:\/-)?(?:\/(issues|pulls?|merge_requests)(?:\/(\d+))?\/?)(?:\?[^#]+)?(?:#.+)?$/.exec(
path,
);
if (mobj) {
return {
domain: mobj[1],
path: mobj[2],
entity: {
issues: ENTITY_TYPE.ISSUE,
merge_requests: ENTITY_TYPE.MERGE_REQUEST,
pull: ENTITY_TYPE.MERGE_REQUEST,
pulls: ENTITY_TYPE.MERGE_REQUEST,
}[mobj[3] as 'issues' | 'merge_requests' | 'pull' | 'pulls'],
entityID: mobj[4],
};
}
mobj = /^https?:\/\/([^/]+)\/([a-zA-Z\d-]+\/(?:[a-zA-Z\d-]+\/)*?[a-zA-Z\d-]+)(?:\?[^#]+)?(?:#.+)?$/.exec(
path,
);
if (mobj) {
return {
domain: mobj[1],
path: mobj[2],
entity: null,
entityID: null,
};
}
throw new Error('Path could not be parsed');
};

729
yarn.lock

File diff suppressed because it is too large Load diff