@@ -9,11 +9,12 @@ use super::{utils::bytes2string, RepoPath};
9
9
use crate :: {
10
10
error:: { Error , Result } ,
11
11
sync:: {
12
- remotes:: get_default_remote_for_push_in_repo,
12
+ gix_repo , remotes:: get_default_remote_for_push_in_repo,
13
13
repository:: repo, utils:: get_head_repo, CommitId ,
14
14
} ,
15
15
} ;
16
16
use git2:: { Branch , BranchType , Repository } ;
17
+ use gix:: remote:: Direction ;
17
18
use scopetime:: scope_time;
18
19
use std:: collections:: HashSet ;
19
20
@@ -123,76 +124,111 @@ pub fn get_branches_info(
123
124
) -> Result < Vec < BranchInfo > > {
124
125
scope_time ! ( "get_branches_info" ) ;
125
126
126
- let repo = repo ( repo_path) ?;
127
+ let gix_repo = gix_repo ( repo_path) ?;
128
+ let platform = gix_repo. references ( ) ?;
129
+ let head_name = gix_repo. head_name ( ) . ok ( ) . flatten ( ) ;
130
+
131
+ let mut branches_for_display: Vec < _ > = if local {
132
+ platform
133
+ . local_branches ( ) ?
134
+ . flatten ( )
135
+ . filter_map ( |mut branch| {
136
+ let branch_name = branch. name ( ) ;
137
+ let name = branch_name. shorten ( ) . to_string ( ) ;
138
+ let reference = branch_name. to_owned ( ) . to_string ( ) ;
139
+ // TODO:
140
+ // Verify that this is sufficiently similar to `git2`’s `is_head` by looking at the
141
+ // implementation of `git_branch_is_head`.
142
+ let is_head =
143
+ head_name. as_ref ( ) . is_some_and ( |head_name| {
144
+ head_name. as_ref ( ) == branch_name
145
+ } ) ;
146
+
147
+ let top_commit = branch. peel_to_commit ( ) . ok ( ) ?;
148
+ let upstream = branch. remote_tracking_ref_name (
149
+ // TODO:
150
+ // Is that correct?
151
+ Direction :: Fetch ,
152
+ ) ;
153
+
154
+ let upstream_branch = match upstream {
155
+ Some ( Ok ( reference) ) => Some ( UpstreamBranch {
156
+ reference : reference. into_owned ( ) . to_string ( ) ,
157
+ } ) ,
158
+ _ => None ,
159
+ } ;
160
+
161
+ let remote = branch
162
+ . remote_name (
163
+ // TODO:
164
+ // Is that correct?
165
+ Direction :: Fetch ,
166
+ )
167
+ . map ( |name| name. as_bstr ( ) . to_string ( ) ) ;
168
+
169
+ let details = BranchDetails :: Local ( LocalBranch {
170
+ is_head,
171
+ has_upstream : upstream_branch. is_some ( ) ,
172
+ upstream : upstream_branch,
173
+ remote,
174
+ } ) ;
127
175
128
- let ( filter, remotes_with_tracking) = if local {
129
- ( BranchType :: Local , HashSet :: default ( ) )
176
+ Some ( BranchInfo {
177
+ name,
178
+ reference,
179
+ top_commit_message : top_commit
180
+ . message ( )
181
+ . ok ( ) ?
182
+ . title
183
+ . to_string ( ) ,
184
+ top_commit : top_commit. into ( ) ,
185
+ details,
186
+ } )
187
+ } )
188
+ . collect ( )
130
189
} else {
131
- let remotes : HashSet < _ > = repo
132
- . branches ( Some ( BranchType :: Local ) ) ?
133
- . filter_map ( |b| {
134
- let branch = b . ok ( ) ? . 0 ;
135
- let upstream = branch. upstream ( ) ;
136
- upstream
137
- . ok ( ) ?
138
- . name_bytes ( )
139
- . ok ( )
140
- . map ( ToOwned :: to_owned )
190
+ let remotes_with_tracking : HashSet < _ > = platform
191
+ . local_branches ( ) ?
192
+ . flatten ( )
193
+ . filter_map ( |branch| {
194
+ let upstream = branch. remote_tracking_ref_name (
195
+ // TODO:
196
+ // Is that correct ?
197
+ Direction :: Fetch ,
198
+ ) ? ;
199
+ Some ( upstream . ok ( ) ? . into_owned ( ) )
141
200
} )
142
201
. collect ( ) ;
143
- ( BranchType :: Remote , remotes)
144
- } ;
145
-
146
- let mut branches_for_display: Vec < BranchInfo > = repo
147
- . branches ( Some ( filter) ) ?
148
- . map ( |b| {
149
- let branch = b?. 0 ;
150
- let top_commit = branch. get ( ) . peel_to_commit ( ) ?;
151
- let reference = bytes2string ( branch. get ( ) . name_bytes ( ) ) ?;
152
- let upstream = branch. upstream ( ) ;
153
-
154
- let remote = repo
155
- . branch_upstream_remote ( & reference)
156
- . ok ( )
157
- . as_ref ( )
158
- . and_then ( git2:: Buf :: as_str)
159
- . map ( String :: from) ;
160
202
161
- let name_bytes = branch. name_bytes ( ) ?;
203
+ platform
204
+ . remote_branches ( ) ?
205
+ . flatten ( )
206
+ . filter_map ( |mut branch| {
207
+ let branch_name = branch. name ( ) ;
208
+ let name = branch_name. shorten ( ) . to_string ( ) ;
209
+ let reference = branch_name. to_owned ( ) . to_string ( ) ;
162
210
163
- let upstream_branch =
164
- upstream. ok ( ) . and_then ( |upstream| {
165
- bytes2string ( upstream. get ( ) . name_bytes ( ) )
166
- . ok ( )
167
- . map ( |reference| UpstreamBranch { reference } )
211
+ let details = BranchDetails :: Remote ( RemoteBranch {
212
+ has_tracking : remotes_with_tracking
213
+ . contains ( branch_name) ,
168
214
} ) ;
169
215
170
- let details = if local {
171
- BranchDetails :: Local ( LocalBranch {
172
- is_head : branch. is_head ( ) ,
173
- has_upstream : upstream_branch. is_some ( ) ,
174
- upstream : upstream_branch,
175
- remote,
216
+ let top_commit = branch. peel_to_commit ( ) . ok ( ) ?;
217
+
218
+ Some ( BranchInfo {
219
+ name,
220
+ reference,
221
+ top_commit_message : top_commit
222
+ . message ( )
223
+ . ok ( ) ?
224
+ . title
225
+ . to_string ( ) ,
226
+ top_commit : top_commit. into ( ) ,
227
+ details,
176
228
} )
177
- } else {
178
- BranchDetails :: Remote ( RemoteBranch {
179
- has_tracking : remotes_with_tracking
180
- . contains ( name_bytes) ,
181
- } )
182
- } ;
183
-
184
- Ok ( BranchInfo {
185
- name : bytes2string ( name_bytes) ?,
186
- reference,
187
- top_commit_message : bytes2string (
188
- top_commit. summary_bytes ( ) . unwrap_or_default ( ) ,
189
- ) ?,
190
- top_commit : top_commit. id ( ) . into ( ) ,
191
- details,
192
229
} )
193
- } )
194
- . filter_map ( Result :: ok)
195
- . collect ( ) ;
230
+ . collect ( )
231
+ } ;
196
232
197
233
branches_for_display. sort_by ( |a, b| a. name . cmp ( & b. name ) ) ;
198
234
0 commit comments