"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{ 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 { 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 { 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(); } }