1- using System ;
1+ using System ;
22using System . Collections . Generic ;
33
44using Avalonia ;
@@ -62,7 +62,7 @@ public class Dot
6262 public List < Link > Links { get ; } = [ ] ;
6363 public List < Dot > Dots { get ; } = [ ] ;
6464
65- public static CommitGraph Parse ( List < Commit > commits , bool firstParentOnlyEnabled )
65+ public static CommitGraph Parse ( List < Commit > commits , bool firstParentOnlyEnabled , bool alwaysShowCurrentHeadOnLeft )
6666 {
6767 const double unitWidth = 12 ;
6868 const double halfWidth = 6 ;
@@ -75,6 +75,24 @@ public static CommitGraph Parse(List<Commit> commits, bool firstParentOnlyEnable
7575 var offsetY = - halfHeight ;
7676 var colorPicker = new ColorPicker ( ) ;
7777
78+ var headPathSHAs = new HashSet < string > ( ) ;
79+ if ( alwaysShowCurrentHeadOnLeft )
80+ {
81+ var head = commits . Find ( x => x . IsCurrentHead ) ;
82+ if ( head != null )
83+ {
84+ headPathSHAs . Add ( head . SHA ) ;
85+
86+ // Forward (newer commits leading to HEAD)
87+ for ( int i = commits . IndexOf ( head ) - 1 ; i >= 0 ; i -- )
88+ {
89+ if ( commits [ i ] . Parents . Count > 0 && headPathSHAs . Contains ( commits [ i ] . Parents [ 0 ] ) )
90+ headPathSHAs . Add ( commits [ i ] . SHA ) ;
91+ }
92+ }
93+ }
94+
95+ PathHelper headPath = null ;
7896 foreach ( var commit in commits )
7997 {
8098 PathHelper major = null ;
@@ -83,9 +101,26 @@ public static CommitGraph Parse(List<Commit> commits, bool firstParentOnlyEnable
83101 // Update current y offset
84102 offsetY += unitHeight ;
85103
86- // Find first curves that links to this commit and marks others that links to this commit ended.
104+ // 1. Move HEAD path to the front of unsolved list (index 0)
105+ if ( alwaysShowCurrentHeadOnLeft && headPath != null && unsolved . Contains ( headPath ) )
106+ {
107+ unsolved . Remove ( headPath ) ;
108+ unsolved . Insert ( 0 , headPath ) ;
109+ }
110+
111+ // 2. Reserve leftmost column (offsetX) for HEAD path if not yet found
87112 var offsetX = 4 - halfWidth ;
88- var maxOffsetOld = unsolved . Count > 0 ? unsolved [ ^ 1 ] . LastX : offsetX + unitWidth ;
113+ if ( alwaysShowCurrentHeadOnLeft && headPath == null )
114+ offsetX += unitWidth ;
115+
116+ // 3. Keep track of max offsetX used in previous rows for margin calculation
117+ var maxOffsetOld = 0.0 ;
118+ foreach ( var l in unsolved )
119+ maxOffsetOld = Math . Max ( maxOffsetOld , l . LastX ) ;
120+ if ( unsolved . Count == 0 )
121+ maxOffsetOld = offsetX + unitWidth ;
122+
123+ // 4. Process existing paths
89124 foreach ( var l in unsolved )
90125 {
91126 if ( l . Next . Equals ( commit . SHA , StringComparison . Ordinal ) )
@@ -129,14 +164,24 @@ public static CommitGraph Parse(List<Commit> commits, bool firstParentOnlyEnable
129164 }
130165 ended . Clear ( ) ;
131166
132- // If no path found, create new curve for branch head
133- // Otherwise, create new curve for new merged commit
167+ // 5. Create new curve for branch tip or new merged commit
134168 if ( major == null )
135169 {
136- offsetX += unitWidth ;
137-
138- if ( commit . Parents . Count > 0 )
170+ // If this is the start of the HEAD lineage, place it in the reserved column (index 0)
171+ if ( alwaysShowCurrentHeadOnLeft && headPath == null && headPathSHAs . Contains ( commit . SHA ) )
139172 {
173+ if ( commit . Parents . Count > 0 )
174+ {
175+ var headX = 4 - halfWidth + unitWidth ;
176+ major = new PathHelper ( commit . Parents [ 0 ] , isMerged , colorPicker . Next ( ) , new Point ( headX , offsetY ) ) ;
177+ headPath = major ;
178+ unsolved . Insert ( 0 , major ) ;
179+ temp . Paths . Add ( major . Path ) ;
180+ }
181+ }
182+ else if ( commit . Parents . Count > 0 )
183+ {
184+ offsetX += unitWidth ;
140185 major = new PathHelper ( commit . Parents [ 0 ] , isMerged , colorPicker . Next ( ) , new Point ( offsetX , offsetY ) ) ;
141186 unsolved . Add ( major ) ;
142187 temp . Paths . Add ( major . Path ) ;
0 commit comments