// ĠCopyright Ġ 2 0 0 0 - 2 0 1 9 ĠJetBrains Ġs . r . o . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ġthat Ġcan Ġbe Ġfound Ġin Ġthe ĠLICENSE Ġfile . Ċ package Ġgit 4 idea . index Ċ Ċ import Ġcom . intellij . openapi . diagnostic . Logger Ċ import Ġcom . intellij . openapi . util . text . StringUtil Ċ import Ġcom . intellij . openapi . vcs . FilePath Ċ import Ġcom . intellij . openapi . vcs . File Status Ċ import Ġcom . intellij . openapi . vcs . V cs Exception Ċ import Ġcom . intellij . openapi . vfs . V fs Util Core Ċ import Ġcom . intellij . openapi . vfs . Virtual File Ċ import Ġcom . intellij . util . Path Util Ċ import Ġcom . intellij . util . ui . UI Util Ċ import Ġgit 4 idea . commands . Git Ċ import Ġgit 4 idea . commands . Git Command Ċ import Ġgit 4 idea . commands . Git Line Handler Ċ import Ġgit 4 idea . config . Git Executable Manager Ċ import Ġgit 4 idea . config . Git Version Special ty Ċ import Ġgit 4 idea . i 1 8 n . Git Bundle Ċ import Ġorg . jetbrains . annotations . N ls Ċ import Ġjava . awt . Color Ċ Ċ const Ġval ĠN UL Ġ= Ġ"\ u 0 0 0 0 " Ċ private Ġval ĠLOG Ġ= ĠLogger . getInstance ("# git 4 idea . index . Git Index Status Util ") Ċ Ċ /* Ċ Ġ* Ġ` git Ġstatus ` Ġoutput Ġformat Ġ( por cel ain Ġversion Ġ 1 ): Ċ Ġ* Ċ Ġ* ĠXY ĠPATH Ċ Ġ* ĠXY ĠPATH \ u 0 0 0 0 OR IG _ PATH Ċ Ġ* Ċ Ġ* ĠX ĠĠĠĠĠĠĠĠĠ ĠY ĠĠĠĠ ĠMean ing Ċ Ġ* Ġ------------------------------------------------ - Ċ Ġ* Ġĉ ĠĠĠĠĠĠĠ Ġ[ AMD ] ĠĠ Ġnot Ġupdated Ċ Ġ* ĠM ĠĠĠĠĠĠĠ Ġ[ ĠMD ] ĠĠ Ġupdated Ġin Ġindex Ċ Ġ* ĠA ĠĠĠĠĠĠĠ Ġ[ ĠMD ] ĠĠ Ġadded Ġto Ġindex Ċ Ġ* ĠD ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdeleted Ġfrom Ġindex Ċ Ġ* ĠR ĠĠĠĠĠĠĠ Ġ[ ĠMD ] ĠĠ Ġrenamed Ġin Ġindex Ċ Ġ* ĠC ĠĠĠĠĠĠĠ Ġ[ ĠMD ] ĠĠ Ġcopied Ġin Ġindex Ċ Ġ* Ġ[ MAR C ] ĠĠĠĠĠĠĠĠĠĠ Ġindex Ġand Ġwork Ġtree Ġmatches Ċ Ġ* Ġ[ ĠM ARC ] ĠĠĠĠ ĠM ĠĠĠ Ġwork Ġtree Ġchanged Ġsince Ġindex Ċ Ġ* Ġ[ ĠM ARC ] ĠĠĠĠ ĠD ĠĠĠ Ġdeleted Ġin Ġwork Ġtree Ċ Ġ* Ġ[ ĠD ] ĠĠĠĠĠĠĠ ĠR ĠĠĠ Ġrenamed Ġin Ġwork Ġtree Ċ Ġ* Ġ[ ĠD ] ĠĠĠĠĠĠĠ ĠC ĠĠĠ Ġcopied Ġin Ġwork Ġtree Ċ Ġ* Ġ------------------------------------------------ - Ċ Ġ* ĠD ĠĠĠĠĠĠĠĠĠĠ ĠD ĠĠĠ Ġun merged , Ġboth Ġdeleted Ċ Ġ* ĠA ĠĠĠĠĠĠĠĠĠĠ ĠU ĠĠĠ Ġun merged , Ġadded Ġby Ġus Ċ Ġ* ĠU ĠĠĠĠĠĠĠĠĠĠ ĠD ĠĠĠ Ġun merged , Ġdeleted Ġby Ġthem Ċ Ġ* ĠU ĠĠĠĠĠĠĠĠĠĠ ĠA ĠĠĠ Ġun merged , Ġadded Ġby Ġthem Ċ Ġ* ĠD ĠĠĠĠĠĠĠĠĠĠ ĠU ĠĠĠ Ġun merged , Ġdeleted Ġby Ġus Ċ Ġ* ĠA ĠĠĠĠĠĠĠĠĠĠ ĠA ĠĠĠ Ġun merged , Ġboth Ġadded Ċ Ġ* ĠU ĠĠĠĠĠĠĠĠĠĠ ĠU ĠĠĠ Ġun merged , Ġboth Ġmodified Ċ Ġ* Ġ------------------------------------------------ - Ċ Ġ* Ġ? ĠĠĠĠĠĠĠĠĠĠ Ġ? ĠĠĠ Ġun tracked Ċ Ġ* Ġ! ĠĠĠĠĠĠĠĠĠĠ Ġ! ĠĠĠ Ġignored Ċ Ġ* Ġ------------------------------------------------ - Ċ Ġ*/ Ċ Ċ @ Throws ( V cs Exception :: class ) Ċ fun ĠgetFile Status ( root : ĠVirtual File , ĠfilePath : ĠFilePath , Ġexecutable : ĠString ): ĠGit File Status Ġ{ ĊĠ Ġval Ġh Ġ= ĠGit Line Handler ( null , ĠV fs Util Core . virtual To Io File ( root ), Ġexecutable , ĠGit Command . STATUS , Ġempty List ()) ĊĠ Ġh . set Sil ent ( true ) ĊĠ Ġh . add Parameters ("-- por cel ain ", Ġ"- z ", Ġ"-- no - re names ") ĊĠ Ġif Ġ( Git Version Special ty . STATUS _ SUPPORT S _ IG NO RED _ MODES . exists In ( Git Executable Manager . getInstance (). getVersion ( executable ))) Ġ{ ĊĠĠĠ Ġh . add Parameters ("-- ignored = matching ") ĊĠ Ġ} ĊĠ Ġelse Ġ{ ĊĠĠĠ Ġh . add Parameters ("-- ignored ") ĊĠ Ġ} ĊĠ Ġh . end Options () ĊĠ Ġh . add Relative Paths ( filePath ) ĊĊĠ Ġval Ġoutput : ĠString Ġ= ĠGit . getInstance (). run Command ( h ). getOutput OrThrow () ĊĠ Ġif Ġ( output . isNotBlank ()) Ġ{ ĊĠĠĠ Ġval Ġgit Status Output Ġ= Ġparse Git Status Output ( output ) ĊĠĠĠ Ġreturn Ġgit Status Output . first OrNull () Ġ?: ĠGit File Status . Blank ĊĠ Ġ} ĊĠĠĊĠ Ġval Ġrepository Path Ġ= Ġget FilePath ( root , ĠfilePath , Ġexecutable ) Ġ?: Ġreturn ĠGit File Status . Blank ĊĠ Ġreturn ĠGit File Status . Not Changed ( repository Path ) Ċ } Ċ Ċ @ Throws ( V cs Exception :: class ) Ċ fun Ġget FilePath ( root : ĠVirtual File , ĠfilePath : ĠFilePath , Ġexecutable : ĠString ): ĠString ? Ġ{ ĊĠ Ġval Ġhandler Ġ= ĠGit Line Handler ( null , ĠV fs Util Core . virtual To Io File ( root ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexecutable , ĠGit Command . LS _ FILES , Ġempty List ()) ĊĠ Ġhandler . add Parameters ("-- full - name ") ĊĠ Ġhandler . add Relative Paths ( filePath ) ĊĠ Ġhandler . set Sil ent ( true ) ĊĠ Ġreturn ĠGit . getInstance (). run Command ( handler ). getOutput OrThrow (). lines (). first OrNull () Ċ } Ċ Ċ @ Throws ( V cs Exception :: class ) Ċ fun Ġparse Git Status Output ( output : ĠString ): ĠList < Git File Status . Status Record > Ġ{ ĊĠ Ġval Ġresult Ġ= Ġmutable ListOf < Git File Status . Status Record >() ĊĊĠ Ġval Ġsplit Ġ= Ġoutput . split ( N UL ). to Typed Array () ĊĠ Ġfor Ġ( line Ġin Ġsplit ) Ġ{ ĊĠĠĠ Ġif Ġ( StringUtil . isEmpty Or Spaces ( line )) Ġcontinue ĊĠĠĠ Ġif Ġ( line . length Ġ< Ġ 4 Ġ|| Ġline [ 2 ] Ġ!= Ġ' Ġ') Ġ{ ĊĠĠĠĠĠ ĠLOG . error (" Could Ġnot Ġparse Ġstatus Ġline Ġ'$ line '") ĊĠĠĠĠĠ Ġcontinue Ġ// Ġignoring Ġbroken Ġlines Ġfor Ġnow ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġx Status Ġ= Ġline [ 0 ] ĊĠĠĠ Ġval Ġy Status Ġ= Ġline [ 1 ] ĊĠĠĠ Ġval Ġpath Part Ġ= Ġline . substring ( 3 ) Ġ// Ġskipping Ġthe Ġspace ĊĊĠĠĠ Ġresult . add ( Git File Status . Status Record ( x Status , Ġy Status , Ġpath Part )) ĊĠ Ġ} ĊĊĠ Ġreturn Ġresult ; Ċ } Ċ Ċ @ Throws ( V cs Exception :: class ) Ċ private Ġfun ĠgetFile Status ( status : ĠStatusCode ): ĠFile Status ? Ġ{ ĊĠ Ġreturn Ġwhen Ġ( status ) Ġ{ ĊĠĠĠ Ġ' Ġ' Ġ-> Ġnull ĊĠĠĠ Ġ' M ', Ġ' R ', Ġ' C ', Ġ' T ' Ġ-> ĠFile Status . MODI FIED ĊĠĠĠ Ġ' A ' Ġ-> ĠFile Status . AD DED ĊĠĠĠ Ġ' D ' Ġ-> ĠFile Status . DELETED ĊĠĠĠ Ġ' U ' Ġ-> ĠFile Status . MER GED _ WITH _ CONF LI CT S ĊĠĠĠ Ġ' !' Ġ-> ĠFile Status . IG NO RED ĊĠĠĠ Ġ' ?' Ġ-> ĠFile Status . UNKNOWN ĊĠĠĠ Ġelse Ġ-> Ġthrow ĠV cs Exception (" Unexpected Ġsymbol Ġas Ġstatus : Ġ$ status ") ĊĠ Ġ} Ċ } Ċ Ċ type alias ĠStatusCode Ġ= ĠChar Ċ Ċ sealed Ġclass ĠGit File Status Ġ{ ĊĠ Ġinternal Ġabstract Ġfun ĠgetFile Status (): ĠFile Status ĊĊĠ Ġobject ĠBl ank Ġ: ĠGit File Status () Ġ{ ĊĠĠĠ Ġoverride Ġfun ĠgetFile Status (): ĠFile Status Ġ= ĠFile Status . NOT _ CHANGED ĊĠ Ġ} ĊĊĠ Ġdata Ġclass ĠNot Changed ( val Ġpath : ĠString ) Ġ: ĠGit File Status () Ġ{ ĊĠĠĠ Ġoverride Ġfun ĠgetFile Status (): ĠFile Status Ġ= ĠFile Status . NOT _ CHANGED ĊĠ Ġ} ĊĊĠ Ġdata Ġclass ĠStatus Record ( val Ġindex : ĠStatusCode , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġwork Tree : ĠStatusCode , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpath : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġorig Path : ĠString ? Ġ= Ġnull ) Ġ: ĠGit File Status () Ġ{ ĊĠĠĠ Ġoverride Ġfun ĠgetFile Status (): ĠFile Status Ġ{ ĊĠĠĠĠĠ Ġif Ġ( is Conflict ed ()) Ġreturn ĠFile Status . MER GED _ WITH _ CONF LI CT S ĊĠĠĠĠĠ Ġreturn ĠgetFile Status ( index ) Ġ?: ĠgetFile Status ( work Tree ) Ġ?: ĠFile Status . NOT _ CHANGED ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinternal Ġfun Ġis Conflict ed (): ĠBoolean Ġ{ ĊĠĠĠĠĠ Ġreturn Ġ( index Ġ== Ġ' D ' Ġ&& Ġwork Tree Ġ== Ġ' D ') Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( index Ġ== Ġ' A ' Ġ&& Ġwork Tree Ġ== Ġ' A ') Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( index Ġ== Ġ' U ' Ġ|| Ġwork Tree Ġ== Ġ' U ') ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ fun ĠGit File Status . is Tracked (): ĠBoolean Ġ{ ĊĠ Ġreturn Ġwhen Ġ( this ) Ġ{ ĊĠĠĠ ĠGit File Status . Blank Ġ-> Ġfalse ĊĠĠĠ Ġis ĠGit File Status . Not Changed Ġ-> Ġtrue ĊĠĠĠ Ġis ĠGit File Status . Status Record Ġ-> Ġ! set Of (' ?', Ġ'! '). contains ( index ) ĊĠ Ġ} Ċ } Ċ Ċ val ĠGit File Status . repository Path : ĠString ? ĊĠ Ġget () Ġ= Ġwhen Ġ( this ) Ġ{ ĊĠĠĠ ĠGit File Status . Blank Ġ-> Ġnull ĊĠĠĠ Ġis ĠGit File Status . Not Changed Ġ-> Ġpath ĊĠĠĠ Ġis ĠGit File Status . Status Record Ġ-> Ġif Ġ(! is Tracked () Ġ|| Ġindex Ġ== Ġ' A ' Ġ|| Ġwork Tree Ġ== Ġ' A ') Ġnull Ġelse Ġorig Path Ġ?: Ġpath ĊĠ Ġ} Ċ Ċ val ĠGit File Status . color : ĠColor ? ĊĠ Ġget () Ġ= ĠgetFile Status (). color Ċ Ċ @ N ls Ċ fun ĠGit File Status . get Presentation (): ĠString Ġ{ ĊĠ Ġreturn Ġwhen Ġ( this ) Ġ{ ĊĠĠĠ ĠGit File Status . Blank , Ġis ĠGit File Status . Not Changed Ġ-> Ġ"" ĊĠĠĠ Ġis ĠGit File Status . Status Record Ġ-> Ġget Presentation () ĊĠ Ġ} Ċ } Ċ Ċ @ N ls Ċ private Ġfun ĠGit File Status . Status Record . get Presentation (): ĠString Ġ{ ĊĠ Ġval ĠfileName Ġ= ĠPath Util . get FileName ( path ) ĊĠ Ġif Ġ( index Ġ== Ġ' !' Ġ|| Ġwork Tree Ġ== Ġ' !' Ġ|| Ġindex Ġ== Ġ' ?' Ġ|| Ġwork Tree Ġ== Ġ'? ') Ġreturn Ġ"$ fileName : Ġ${ get Presentation ( index )}" ĊĠ Ġif Ġ( is Conflict ed ()) Ġ{ ĊĠĠĠ Ġval Ġstatus Ġ= Ġif Ġ( index Ġ== Ġwork Tree ) Ġ{ ĊĠĠĠĠĠ ĠGit Bundle . message (" git . status . un merged . both ", ĠgetFile Status ( if Ġ( index Ġ== Ġ' U ') Ġ' M ' Ġelse Ġindex ) !!. text . toLowerCase ()) ĊĠĠĠ Ġ} ĊĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠ Ġval Ġindex Presentation Ġ= Ġif Ġ( index Ġ== Ġ' U ') Ġ"" ĊĠĠĠĠĠ Ġelse ĠGit Bundle . message (" git . status . un merged . index ", Ġget Presentation ( index ). toLowerCase ()) ĊĠĠĠĠĠ Ġval Ġwork Tree Presentation Ġ= Ġif Ġ( work Tree Ġ== Ġ' U ') Ġ"" ĊĠĠĠĠĠ Ġelse ĠGit Bundle . message (" git . status . un merged . work . tree ", Ġget Presentation ( work Tree ). toLowerCase ()) ĊĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġindex Presentation . isBlank () Ġ-> Ġwork Tree Presentation ĊĠĠĠĠĠĠĠ Ġwork Tree Presentation . isBlank () Ġ-> Ġindex Presentation ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ"$ index Presentation , Ġ$ work Tree Presentation " ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġ"$ fileName : Ġ${ get Presentation (' U ')} Ġ($ status )" ĊĠ Ġ} ĊĠ Ġval Ġindex Presentation Ġ= Ġif Ġ( index Ġ== Ġ' Ġ') Ġ"" Ġelse ĠGit Bundle . message (" git . status . index ", Ġget Presentation ( index )) ĊĠ Ġval Ġwork Tree Presentation Ġ= Ġif Ġ( work Tree Ġ== Ġ' Ġ') Ġ"" Ġelse ĠGit Bundle . message (" git . status . work . tree ", Ġget Presentation ( work Tree )) ĊĠ Ġif Ġ( index Presentation . isBlank ()) Ġreturn Ġ"$ fileName : Ġ$ work Tree Presentation " ĊĠ Ġif Ġ( work Tree Presentation . isBlank ()) Ġreturn Ġ"$ fileName : Ġ$ index Presentation " ĊĠ Ġreturn Ġ"$ fileName :${ UI Util . BR }$ index Presentation ${ UI Util . BR }$ work Tree Presentation " Ċ } Ċ Ċ @ N ls Ċ private Ġfun Ġget Presentation ( status : ĠStatusCode ): ĠString Ġ{ ĊĠ Ġreturn Ġwhen Ġ( status ) Ġ{ ĊĠĠĠ Ġ' Ġ' Ġ-> ĠGit Bundle . message (" git . status . not . changed ") ĊĠĠĠ Ġ' R ' Ġ-> ĠGit Bundle . message (" git . status . re named ") ĊĠĠĠ Ġ' C ' Ġ-> ĠGit Bundle . message (" git . status . copied ") ĊĠĠĠ Ġ' T ' Ġ-> ĠGit Bundle . message (" git . status . type . changed ") ĊĠĠĠ Ġ' U ' Ġ-> ĠGit Bundle . message (" git . status . un merged ") ĊĠĠĠ Ġ' ?' Ġ-> ĠGit Bundle . message (" git . status . un tracked ") ĊĠĠĠ Ġelse Ġ-> ĠgetFile Status ( status ) !!. text ĊĠ Ġ} Ċ } Ċ