@@ -11,39 +11,55 @@ extension GitClient {
1111 /// Get branches
1212 /// - Returns: Array of branches
1313 func getBranches( ) async throws -> [ GitBranch ] {
14- let command = " branch --format \" %(refname:short)|%(refname)|%(upstream:short) \" -a "
14+ let command = " branch --format \" %(refname:short)|%(refname)|%(upstream:short) %(upstream:track) \" -a "
1515
1616 return try await run ( command)
1717 . components ( separatedBy: " \n " )
1818 . filter { $0 != " " && !$0. contains ( " HEAD " ) }
1919 . compactMap { line in
20- let components = line. components ( separatedBy: " | " )
21- let name = components [ 0 ]
22- let upstream = components [ safe: 2 ]
20+ guard let branchPart = line. components ( separatedBy: " " ) . first else { return nil }
21+ let branchComponents = branchPart. components ( separatedBy: " | " )
22+ let name = branchComponents [ 0 ]
23+ let upstream = branchComponents [ safe: 2 ]
24+
25+ let trackInfoString = line
26+ . dropFirst ( branchPart. count)
27+ . trimmingCharacters ( in: . whitespacesWithoutNewlines)
28+ let trackInfo = parseBranchTrackInfo ( from: trackInfoString)
2329
2430 return . init(
2531 name: name,
26- longName: components [ safe: 1 ] ?? name,
27- upstream: upstream? . isEmpty == true ? nil : upstream
32+ longName: branchComponents [ safe: 1 ] ?? name,
33+ upstream: upstream? . isEmpty == true ? nil : upstream,
34+ ahead: trackInfo. ahead,
35+ behind: trackInfo. behind
2836 )
2937 }
3038 }
3139
3240 /// Get current branch
3341 func getCurrentBranch( ) async throws -> GitBranch ? {
3442 let branchName = try await run ( " branch --show-current " ) . trimmingCharacters ( in: . whitespacesAndNewlines)
35- let components = try await run (
36- " for-each-ref --format= \" %(refname)|%(upstream:short) \" refs/heads/ \( branchName) "
43+ let output = try await run (
44+ " for-each-ref --format= \" %(refname)|%(upstream:short) %(upstream:track) \" refs/heads/ \( branchName) "
3745 )
3846 . trimmingCharacters ( in: . whitespacesAndNewlines)
39- . components ( separatedBy: " | " )
4047
41- let upstream = components [ safe: 1 ]
48+ guard let branchPart = output. components ( separatedBy: " " ) . first else { return nil }
49+ let branchComponents = branchPart. components ( separatedBy: " | " )
50+ let upstream = branchComponents [ safe: 1 ]
51+
52+ let trackInfoString = output
53+ . dropFirst ( branchPart. count)
54+ . trimmingCharacters ( in: . whitespacesWithoutNewlines)
55+ let trackInfo = parseBranchTrackInfo ( from: trackInfoString)
4256
4357 return . init(
4458 name: branchName,
45- longName: components [ 0 ] ,
46- upstream: upstream? . isEmpty == true ? nil : upstream
59+ longName: branchComponents [ 0 ] ,
60+ upstream: upstream? . isEmpty == true ? nil : upstream,
61+ ahead: trackInfo. ahead,
62+ behind: trackInfo. behind
4763 )
4864 }
4965
@@ -100,4 +116,35 @@ extension GitClient {
100116 }
101117 }
102118 }
119+
120+ private func parseBranchTrackInfo( from infoString: String ) -> ( ahead: Int , behind: Int ) {
121+ let pattern = " \\ [ahead ( \\ d+)(?:, behind ( \\ d+))? \\ ]| \\ [behind ( \\ d+) \\ ] "
122+ // Create a regular expression object
123+ guard let regex = try ? NSRegularExpression ( pattern: pattern, options: [ ] ) else {
124+ fatalError ( " Invalid regular expression pattern " )
125+ }
126+ var ahead = 0
127+ var behind = 0
128+ // Match the input string with the regular expression
129+ if let match = regex. firstMatch (
130+ in: infoString,
131+ options: [ ] ,
132+ range: NSRange ( location: 0 , length: infoString. utf16. count)
133+ ) {
134+ // Extract the captured groups
135+ if let aheadRange = Range ( match. range ( at: 1 ) , in: infoString) ,
136+ let aheadValue = Int ( infoString [ aheadRange] ) {
137+ ahead = aheadValue
138+ }
139+ if let behindRange = Range ( match. range ( at: 2 ) , in: infoString) ,
140+ let behindValue = Int ( infoString [ behindRange] ) {
141+ behind = behindValue
142+ }
143+ if let behindRange = Range ( match. range ( at: 3 ) , in: infoString) ,
144+ let behindValue = Int ( infoString [ behindRange] ) {
145+ behind = behindValue
146+ }
147+ }
148+ return ( ahead, behind)
149+ }
103150}
0 commit comments