Select Git revision
gitMission.ts
gitMission.ts 4.48 KiB
import { exec as execCallback } from 'child_process';
import simpleGit, { SimpleGit, SimpleGitOptions } from 'simple-git';
import { GITEA_PATH_IC } from './config';
import { log as customizableLog, error as customizableError } from '../recorder/utils/log';
import { promisify } from 'util';
import ApiService from './api.service';
import UserMission from './mission/model/userMission';
const exec = promisify(execCallback);
const defaultRemote = 'origin';
type Branch = 'master' | 'live';
export default class GitMission {
private static _instance: GitMission;
public static get instance(): GitMission {
if (!GitMission._instance) {
GitMission._instance = new GitMission();
}
return GitMission._instance;
}
private prefix = 'DEADLOCK-RECORDER';
private git: SimpleGit;
private constructor() {
const options: Partial<SimpleGitOptions> = {
baseDir: GITEA_PATH_IC,
binary: 'git',
maxConcurrentProcesses: 2,
};
this.git = simpleGit(options);
}
log(message: any, ...args: any[]) {
customizableLog(this.prefix, message, ...args);
}
error(message: any, ...args: any[]) {
customizableError(this.prefix, message, ...args);
}
async setupSshAgent() {
try {
const gitea = await ApiService.instance.getGiteaPublicProperties();
await exec(`ssh-add /tmp/.ssh/id_rsa`);
await exec(`eval "$(ssh-agent -s)" && ssh-keyscan -p ${gitea.sshPort} -H ${gitea.sshHost} >> ~/.ssh/known_hosts`);
} catch (err) {
this.log(err);
if (err instanceof Error) {
if (err) {
this.error(err.message);
throw err;
}
} else {
this.log(`Unhandled error: ${err}`);
throw err;
}
}
}
async forgetSshKeys() {
await exec(`ssh-add -d /tmp/.ssh/id_rsa`);
}
async getAuthor(): Promise<string> {
return (await UserMission.instance.getGiteaUser()).username;
}
async init() {
try {
await this.setupSshAgent();
await this.git.init();
const remote = await this.readRemote();
if (remote === defaultRemote) {
return Promise.resolve(this);
}
const giteaUser = await UserMission.instance.getGiteaUser();
await this.git.addRemote(defaultRemote, await this.getRemotePath());
await this.git.addConfig('user.email', await UserMission.instance.getEmail(), false, 'local');
await this.git.addConfig(
'user.name',
`${giteaUser.details.lastName} ${giteaUser.details.firstName}`,
false,
'local',
);
await this.git.addConfig('core.excludesFile', `user-git-${giteaUser.username}/\n`, true, 'local');
return Promise.resolve(this);
} catch (e) {
this.error(e);
return Promise.reject(e);
}
}
private async getRemotePath() {
const giteaConfig = await ApiService.instance.getGiteaPublicProperties();
return `ssh://git@${giteaConfig.sshHost}:${giteaConfig.sshPort}/${
(await UserMission.instance.getGiteaUser()).username
}/${UserMission.instance.missionId}`;
}
async readRemote() {
try {
return ((await this.git.remote([])) || '').replace(/(\r\n|\n|\r)/gm, '');
} catch (e) {
this.error(e);
}
return '';
}
fetch() {
return this.git.fetch(defaultRemote);
}
pull(branch: Branch = 'master') {
return this.git.pull(defaultRemote, branch, { '--rebase': 'true' });
}
addAll() {
return this.git.add('.');
}
commit(message: string, options: string[] = []) {
return this.git.commit(message, options);
}
push() {
return this.git.push(defaultRemote);
}
createLocalBranch(branch: Branch = 'master') {
return this.git.checkout(['-b', branch]);
}
createRemoteBranch(branch: Branch = 'master') {
return this.git.push(['-u', defaultRemote, branch]);
}
setUpstream(branch: Branch = 'master') {
return this.git.branch(['-u', defaultRemote, branch]);
}
createBranch(branch: Branch = 'master') {
const createBranchLocally = this.createLocalBranch(branch);
const createRemoteBranch = this.createRemoteBranch(branch);
return Promise.all([createBranchLocally, createRemoteBranch]);
}
checkout(branch: Branch = 'master') {
return this.git.checkout(branch);
}
merge(options?: string[]) {
return this.git.merge(options ?? []);
}
async isRemoteRepoExist() {
try {
const remotes = await this.git.listRemote();
return remotes.length !== 0;
} catch {
// error, Gitea throws Gitea: Unauthorized when not found
return false;
}
}
}