import { execSync } from 'child_process' ; import fs from 'fs-extra' ; import path from 'path' ; import { getRepoRootPath } from '../lib/config' ; import { ExitFailedError } from '../lib/errors' ; export type TBranchPRState = 'OPEN' | 'CLOSED' | 'MERGED' ; export type TBranchPRReviewDecision = 'APPROVED' | 'REVIEW_REQUIRED' | 'CHANGES_REQUESTED' ; export type TBranchPRInfo = { number : number ; base : string ; url ? : string ; title ? : string ; state ? : TBranchPRState ; reviewDecision ? : TBranchPRReviewDecision ; isDraft ? : boolean ; } ; export type TBranchPriorSubmitInfo = { title ? : string ; body ? : string ; } ; export type TMeta = { parentBranchName ? : string ; prevRef ? : string ; prInfo ? : TBranchPRInfo ; priorSubmitInfo ? : TBranchPriorSubmitInfo ; } ; export default class MetadataRef { _branchName : string ; constructor ( branchName ) { this . _branchName = branchName ; } private static branchMetadataDirPath ( ) { return path . join ( getRepoRootPath ( ) , `refs/branch-metadata/` ) ; } private static pathForBranchName ( branchName ) { return path . join ( MetadataRef . branchMetadataDirPath ( ) , branchName ) ; } static getMeta ( branchName ) { return new MetadataRef ( branchName ) . read ( ) ; } static updateOrCreate ( branchName , meta ) { const metaSha = execSync ( `git hash-object -w --stdin` , { input : JSON . stringify ( meta ) , } ) . toString ( ) ; execSync ( `git update-ref refs/branch-metadata/${ branchName } ${ metaSha }` , { stdio : 'ignore' , } ) ; } public getPath ( ) { return MetadataRef . pathForBranchName ( this . _branchName ) ; } public rename ( newBranchName ) { if ( ! fs . existsSync ( this . getPath ( ) ) ) { throw new ExitFailedError ( `No Graphite metadata ref found at ${ this . getPath ( ) }` ) ; } fs . moveSync ( path . join ( this . getPath ( ) ) , path . join ( path . dirname ( this . getPath ( ) ) , newBranchName ) ) ; this . _branchName = newBranchName ; } public read ( ) { try { const metaString = execSync ( `git cat-file -p refs/branch-metadata/${ this . _branchName } 2> /dev/null` ) . toString ( ) . trim ( ) ; if ( metaString . length == 0 ) { return undefined ; } const meta = JSON . parse ( metaString ) ; return meta ; } catch { return undefined ; } } public delete ( ) { fs . removeSync ( this . getPath ( ) ) ; } public static allMetadataRefs ( ) { if ( ! fs . existsSync ( MetadataRef . branchMetadataDirPath ( ) ) ) { return [ ] ; } return fs . readdirSync ( MetadataRef . branchMetadataDirPath ( ) ) . map ( ( dirent ) => new MetadataRef ( dirent ) ) ; } }