115 lines
3.3 KiB
TypeScript
115 lines
3.3 KiB
TypeScript
"use strict";
|
|
import * as git from "simple-git/promise"
|
|
import * as gyt from "git-describe"
|
|
import { promises as fs, mkdirSync } from "fs"
|
|
import * as rimraf from "rimraf"
|
|
import * as path from "path"
|
|
import * as Logger from 'log4js'
|
|
Logger.configure({
|
|
appenders:
|
|
{
|
|
"admin/gitupdater": { type: 'stdout' },
|
|
//app: { type: 'file', filename: 'application.log' }
|
|
},
|
|
categories:
|
|
{
|
|
default: { appenders: [ 'admin/gitupdater' ], level: 'debug' }
|
|
}
|
|
})
|
|
const logger = Logger.getLogger("admin/gitupdater")
|
|
|
|
|
|
|
|
const rmrf = (path:string, options = {}) => {
|
|
return new Promise((acc, _) => rimraf(path, options, acc))
|
|
}
|
|
|
|
export type RepoFolderStatus = {
|
|
exists: boolean
|
|
empty: boolean
|
|
isRepo: boolean
|
|
currentTag?: string
|
|
tags?: string[]
|
|
latestTag?: string
|
|
remote?: string
|
|
}
|
|
|
|
export class GitUpdater{
|
|
private repo: git.SimpleGit
|
|
constructor(private readonly folderPath:string){
|
|
}
|
|
|
|
async getStatus():Promise<RepoFolderStatus>{
|
|
try {
|
|
await fs.access(this.folderPath);
|
|
}
|
|
catch (e) {
|
|
return { exists: false, empty: true, isRepo: false };
|
|
}
|
|
|
|
const files = await fs.readdir(this.folderPath)
|
|
const empty:boolean = files.length === 0
|
|
|
|
try{
|
|
await fs.access(this.folderPath+"/.git");
|
|
}catch(e2){
|
|
return { exists: true, empty: empty, isRepo: false };
|
|
}
|
|
|
|
if(!this.repo){
|
|
this.repo = git(this.folderPath)
|
|
}
|
|
|
|
|
|
await this.repo.fetch("origin", "master", {
|
|
"--tags": null
|
|
});
|
|
const remoteInfo = await this.repo.getRemotes(/* verbose for full url */true)
|
|
let remoteURL
|
|
if(remoteInfo.length != 0){
|
|
const filtered = remoteInfo.find(i => i.name === "origin")
|
|
remoteURL = filtered?filtered.refs.fetch:"origin unknown"
|
|
}
|
|
const remoteTags = await this.repo.tags();
|
|
const desc = await gyt.gitDescribe(this.folderPath, { match: "*" });
|
|
return {
|
|
exists: true,
|
|
empty: empty,
|
|
isRepo: true,
|
|
currentTag: !desc.tag?null:desc.tag,
|
|
tags: !remoteTags.all?[]:remoteTags.all,
|
|
latestTag: remoteTags.latest,
|
|
remote: remoteURL
|
|
};
|
|
}
|
|
|
|
async cloneRepo(from:string, force:boolean = false):Promise<RepoFolderStatus> {
|
|
if(force){
|
|
await rmrf(this.folderPath)
|
|
await fs.mkdir(this.folderPath)
|
|
}
|
|
const status = await this.getStatus()
|
|
if(!status.exists){
|
|
await fs.mkdir(this.folderPath)
|
|
}
|
|
if(!status.empty){
|
|
logger.error("The folder "+this.folderPath+" is not empty. Not cloning! Pass the force parameter to override this check")
|
|
logger.error(status)
|
|
return status
|
|
}
|
|
|
|
await git().clone(from, path.resolve(this.folderPath));
|
|
return await this.getStatus();
|
|
}
|
|
|
|
async checkoutTag(tag:string):Promise<RepoFolderStatus> {
|
|
const status = await this.getStatus()
|
|
if(!status.exists || !status.tags || status.tags.length === 0){
|
|
logger.error("Unable to check out tag", tag, status)
|
|
return status
|
|
}
|
|
await this.repo.checkout(tag);
|
|
return await this.getStatus();
|
|
}
|
|
}
|