@@ -11,39 +11,55 @@ extension GitClient {
11
11
/// Get branches
12
12
/// - Returns: Array of branches
13
13
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 "
15
15
16
16
return try await run ( command)
17
17
. components ( separatedBy: " \n " )
18
18
. filter { $0 != " " && !$0. contains ( " HEAD " ) }
19
19
. 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)
23
29
24
30
return . init(
25
31
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
28
36
)
29
37
}
30
38
}
31
39
32
40
/// Get current branch
33
41
func getCurrentBranch( ) async throws -> GitBranch ? {
34
42
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) "
37
45
)
38
46
. trimmingCharacters ( in: . whitespacesAndNewlines)
39
- . components ( separatedBy: " | " )
40
47
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)
42
56
43
57
return . init(
44
58
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
47
63
)
48
64
}
49
65
@@ -100,4 +116,35 @@ extension GitClient {
100
116
}
101
117
}
102
118
}
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
+ }
103
150
}
0 commit comments