file import log = require ( "electron-log" ) ; import fs = require ( "fs" ) ; import GitUrlParse = require ( "git-url-parse" ) ; import path = require ( "path" ) ; import simpleGit , { ResetMode , SimpleGit } from "simple-git" ; import { User } from "./../../common/Objects/User" ; /**
 * This class is responsible for managing a local copy of a
 * GitHub repository.
 * It provides the following functionality:
 *
 *      Updating a local copy: This will clone or reset+pull the repo
 *
 *      Pushing: This will add/commit/push to the repo.
 *
 * Note that the current user must have write access to the repo you're
 * trying to manage!
 */ export class GitRepoManager { public repoURL : string ; public HTTPSRepoURL : string ; public workingDir : string ; public repoName : string ; public ownerName : string ; public repoDir : string ; public user : User ; public branch : string ; public defaultBranch : string ; constructor param { string } repoURL param { string } branch param { string } user param { string } workingDir constructor ( repoURL , branch , defaultBranch , user , workingDir ) { this . repoURL = repoURL ; this . user = user ; this . branch = branch ; this . defaultBranch = defaultBranch ; if ( this . branch !== this . defaultBranch ) { if ( ( this . branch === "master" || this . branch === "main" ) && ( this . defaultBranch === "master" || this . defaultBranch === "main" ) ) { this . branch = this . defaultBranch ; } } this . workingDir = workingDir ; const parsedURL = GitUrlParse ( this . repoURL ) ; this . repoName = parsedURL . name ; this . ownerName = parsedURL . owner ; this . repoDir = path . join ( this . workingDir , this . repoName ) ; this . HTTPSRepoURL = this . makeGitHTTPSUrl ( ) ; this . createFoldersIfNeeded ( this . workingDir ) ; } returns public async updateLocalCopy ( ) { const result = await this . hasRepo ( ) ; if ( result ) { log . info ( "Local copy detected, pulling changes" ) ; const git = simpleGit ( this . repoDir ) ; try { await git . checkout ( this . defaultBranch ) ; } catch ( error ) { log . error ( `Failed to checkout default branch. Error msg: ${ error }` ) ; throw error ; } try { await git . reset ( ResetMode . HARD ) ; } catch ( error ) { log . error ( `Failed to reset local copy of the repo. Error msg: ${ error }` ) ; throw error ; } try { await git . pull ( ) ; log . info ( "pull successful" ) ; } catch ( error ) { log . error ( `Failed to pull. Error msg: ${ error }` ) ; throw error ; } try { await git . checkout ( this . branch ) ; } catch ( error ) { try { await git . checkoutBranch ( this . branch , this . defaultBranch ) ; } catch ( error ) { log . error ( `Failed to checkout new branch of the repo. Error msg: ${ error }` ) ; throw error ; } } } else { log . info ( "No local copy detected - Cloning" ) ; let git = simpleGit ( this . workingDir ) ; try { await git . clone ( this . HTTPSRepoURL ) ; log . info ( `Cloning success of repo located at ${ this . repoDir }` ) ; } catch ( error ) { log . error ( `Failed to clone ${ this . repoURL }, error messag: ${ error }` ) ; throw error ; } git = simpleGit ( this . repoDir ) ; try { await git . checkout ( this . branch ) ; log . info ( "Checkout Success" ) ; } catch ( error ) { try { await git . checkoutBranch ( this . branch , this . defaultBranch ) ; } catch ( error ) { log . error ( `Failed to checkout new branch of the repo. Error msg: ${ error }` ) ; throw error ; } } } } param { string } fileContent param { string } fileName param { string } subDir public saveStringToFile ( fileContent , fileName , subDir = "" ) { const outFolderPath = this . repoDir + "/" + subDir ; const outFilePath = outFolderPath + "/" + fileName ; this . createFoldersIfNeeded ( outFolderPath ) ; fs . writeFileSync ( outFilePath , fileContent ) ; } param commitMessage returns public async pushChanges ( commitMessage ) { try { const git = simpleGit ( this . repoDir ) ; await git . add ( "./*" ) ; await git . commit ( commitMessage ) ; await git . push ( this . HTTPSRepoURL , this . branch ) ; } catch ( error ) { log . error ( `Failed to push changes. ${ error }` ) ; throw error ; } } returns private makeGitHTTPSUrl ( ) { return `https://${ this . user . userName }:${ this . user . token }@github.com/${ this . ownerName }/${ this . repoName }.git` ; } returns private async hasRepo ( ) { if ( ! fs . existsSync ( this . repoDir ) ) { log . warn ( `"${ this . repoDir }" does not contain a repository` ) ; return false ; } else { const git = simpleGit ( this . repoDir ) ; const result = await git . checkIsRepo ( ) ; if ( result ) { log . info ( `"${ this . repoDir }" is a repository"` ) ; } else { log . info ( `"${ this . repoDir }" does not contain a repository` ) ; } return result ; } } param { string } filepath private createFoldersIfNeeded ( filepath ) { if ( ! fs . existsSync ( filepath ) ) { fs . mkdirSync ( filepath , { recursive : true } ) ; } } }