import { App } from "obsidian" ; import ObsidianGit from "./main" ; import { BranchInfo , FileStatusResult , Status , TreeItem } from "./types" ; export abstract class GitManager { readonly plugin : ObsidianGit ; readonly app : App ; constructor ( plugin ) { this . plugin = plugin ; this . app = plugin . app ; } abstract status ( ) ; abstract commitAll ( message ? ) ; abstract commit ( message ? ) ; abstract stageAll ( ) ; abstract unstageAll ( ) ; abstract stage ( filepath ) ; abstract unstage ( filepath ) ; abstract discard ( filepath ) ; abstract pull ( ) ; abstract push ( ) ; abstract canPush ( ) ; abstract checkRequirements ( ) ; abstract branchInfo ( ) ; abstract checkout ( branch ) ; abstract init ( ) ; abstract clone ( url , dir ) ; abstract setConfig ( path , value ) ; abstract getConfig ( path ) ; abstract fetch ( remote ? ) ; abstract setRemote ( name , url ) ; abstract getRemotes ( ) ; abstract getRemoteBranches ( remote ) ; abstract removeRemote ( remoteName ) ; abstract updateUpstreamBranch ( remoteBranch ) ; abstract updateGitPath ( gitPath ) ; abstract getDiffString ( filePath ) ; getTreeStructure ( children , beginLength = 0 ) { let list = [ ] ; children = [ ... children ] ; while ( children . length > 0 ) { const first = children . first ( ) ; const restPath = first . path . substring ( beginLength ) ; if ( restPath . contains ( "/" ) ) { const title = restPath . substring ( 0 , restPath . indexOf ( "/" ) ) ; const childrenWithSameTitle = children . filter ( ( item ) => { return item . path . substring ( beginLength ) . startsWith ( title + "/" ) ; } ) ; childrenWithSameTitle . forEach ( ( item ) => children . remove ( item ) ) ; list . push ( { title : title , children : this . getTreeStructure ( childrenWithSameTitle , ( beginLength > 0 ? ( beginLength + title . length ) : title . length ) + 1 ) } ) ; } else { list . push ( { title : restPath , statusResult : first } ) ; children . remove ( first ) ; } } return list ; } async formatCommitMessage ( message ? ) { let template = message ?? this . plugin . settings . commitMessage ; let status ; if ( template . includes ( "{{numFiles}}" ) ) { status = await this . status ( ) ; let numFiles = status . staged . length ; template = template . replace ( "{{numFiles}}" , String ( numFiles ) ) ; } if ( template . includes ( "{{hostname}}" ) ) { const hostname = localStorage . getItem ( this . plugin . manifest . id + ":hostname" ) || "" ; template = template . replace ( "{{hostname}}" , hostname ) ; } if ( template . includes ( "{{files}}" ) ) { status = status ?? await this . status ( ) ; let changeset = { } ; status . staged . forEach ( ( value ) => { if ( value . index in changeset ) { changeset [ value . index ] . push ( value . path ) ; } else { changeset [ value . index ] = [ value . path ] ; } } ) ; let chunks = [ ] ; for ( let [ action , files ] of Object . entries ( changeset ) ) { chunks . push ( action + " " + files . join ( " " ) ) ; } let files = chunks . join ( ", " ) ; template = template . replace ( "{{files}}" , files ) ; } let moment = ( window as any ) . moment ; template = template . replace ( "{{date}}" , moment ( ) . format ( this . plugin . settings . commitDateFormat ) ) ; if ( this . plugin . settings . listChangedFilesInMessageBody ) { template = template + "\n\n" + "Affected files:" + "\n" + ( status ?? await this . status ( ) ) . staged . map ( ( e ) => e . path ) . join ( "\n" ) ; } return template ; } }