@@ -9,11 +9,12 @@ use super::{utils::bytes2string, RepoPath};
99use crate :: {
1010 error:: { Error , Result } ,
1111 sync:: {
12- remotes:: get_default_remote_for_push_in_repo,
12+ gix_repo , remotes:: get_default_remote_for_push_in_repo,
1313 repository:: repo, utils:: get_head_repo, CommitId ,
1414 } ,
1515} ;
1616use git2:: { Branch , BranchType , Repository } ;
17+ use gix:: remote:: Direction ;
1718use scopetime:: scope_time;
1819use std:: collections:: HashSet ;
1920
@@ -123,76 +124,111 @@ pub fn get_branches_info(
123124) -> Result < Vec < BranchInfo > > {
124125 scope_time ! ( "get_branches_info" ) ;
125126
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+ } ) ;
127175
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 ( )
130189 } 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 ( ) )
141200 } )
142201 . 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) ;
160202
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 ( ) ;
162210
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) ,
168214 } ) ;
169215
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,
176228 } )
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,
192229 } )
193- } )
194- . filter_map ( Result :: ok)
195- . collect ( ) ;
230+ . collect ( )
231+ } ;
196232
197233 branches_for_display. sort_by ( |a, b| a. name . cmp ( & b. name ) ) ;
198234
0 commit comments