@@ -5,6 +5,8 @@ pub mod merge_ff;
5
5
pub mod merge_rebase;
6
6
pub mod rename;
7
7
8
+ use std:: collections:: HashSet ;
9
+
8
10
use super :: {
9
11
remotes:: get_default_remote_in_repo, utils:: bytes2string,
10
12
} ;
@@ -55,13 +57,20 @@ pub struct LocalBranch {
55
57
pub remote : Option < String > ,
56
58
}
57
59
60
+ ///
61
+ #[ derive( Debug ) ]
62
+ pub struct RemoteBranch {
63
+ ///
64
+ pub has_tracking : bool ,
65
+ }
66
+
58
67
///
59
68
#[ derive( Debug ) ]
60
69
pub enum BranchDetails {
61
70
///
62
71
Local ( LocalBranch ) ,
63
72
///
64
- Remote ,
73
+ Remote ( RemoteBranch ) ,
65
74
}
66
75
67
76
///
@@ -107,13 +116,26 @@ pub fn get_branches_info(
107
116
) -> Result < Vec < BranchInfo > > {
108
117
scope_time ! ( "get_branches_info" ) ;
109
118
110
- let filter = if local {
111
- BranchType :: Local
119
+ let repo = utils:: repo ( repo_path) ?;
120
+
121
+ let ( filter, remotes_with_tracking) = if local {
122
+ ( BranchType :: Local , HashSet :: default ( ) )
112
123
} else {
113
- BranchType :: Remote
124
+ let remotes: HashSet < _ > = repo
125
+ . branches ( Some ( BranchType :: Local ) ) ?
126
+ . filter_map ( |b| {
127
+ let branch = b. ok ( ) ?. 0 ;
128
+ let upstream = branch. upstream ( ) ;
129
+ upstream
130
+ . ok ( ) ?
131
+ . name_bytes ( )
132
+ . ok ( )
133
+ . map ( ToOwned :: to_owned)
134
+ } )
135
+ . collect ( ) ;
136
+ ( BranchType :: Remote , remotes)
114
137
} ;
115
138
116
- let repo = utils:: repo ( repo_path) ?;
117
139
let mut branches_for_display: Vec < BranchInfo > = repo
118
140
. branches ( Some ( filter) ) ?
119
141
. map ( |b| {
@@ -129,18 +151,23 @@ pub fn get_branches_info(
129
151
. and_then ( git2:: Buf :: as_str)
130
152
. map ( String :: from) ;
131
153
154
+ let name_bytes = branch. name_bytes ( ) ?;
155
+
132
156
let details = if local {
133
157
BranchDetails :: Local ( LocalBranch {
134
158
is_head : branch. is_head ( ) ,
135
159
has_upstream : upstream. is_ok ( ) ,
136
160
remote,
137
161
} )
138
162
} else {
139
- BranchDetails :: Remote
163
+ BranchDetails :: Remote ( RemoteBranch {
164
+ has_tracking : remotes_with_tracking
165
+ . contains ( name_bytes) ,
166
+ } )
140
167
} ;
141
168
142
169
Ok ( BranchInfo {
143
- name : bytes2string ( branch . name_bytes ( ) ? ) ?,
170
+ name : bytes2string ( name_bytes) ?,
144
171
reference,
145
172
top_commit_message : bytes2string (
146
173
top_commit. summary_bytes ( ) . unwrap_or_default ( ) ,
@@ -668,6 +695,17 @@ mod test_remote_branches {
668
695
repo_clone, repo_init_bare, write_commit_file,
669
696
} ;
670
697
698
+ impl BranchInfo {
699
+ /// returns details about remote branch or None
700
+ const fn remote_details ( & self ) -> Option < & RemoteBranch > {
701
+ if let BranchDetails :: Remote ( details) = & self . details {
702
+ Some ( details)
703
+ } else {
704
+ None
705
+ }
706
+ }
707
+ }
708
+
671
709
#[ test]
672
710
fn test_remote_branches ( ) {
673
711
let ( r1_dir, _repo) = repo_init_bare ( ) . unwrap ( ) ;
@@ -756,4 +794,49 @@ mod test_remote_branches {
756
794
757
795
assert_eq ! ( & get_branch_name( clone2_dir) . unwrap( ) , "foo" ) ;
758
796
}
797
+
798
+ #[ test]
799
+ fn test_has_tracking ( ) {
800
+ let ( r1_dir, _repo) = repo_init_bare ( ) . unwrap ( ) ;
801
+
802
+ let ( clone1_dir, clone1) =
803
+ repo_clone ( r1_dir. path ( ) . to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
804
+ let clone1_dir = clone1_dir. path ( ) . to_str ( ) . unwrap ( ) ;
805
+
806
+ // clone1
807
+
808
+ write_commit_file ( & clone1, "test.txt" , "test" , "commit1" ) ;
809
+ push (
810
+ clone1_dir, "origin" , "master" , false , false , None , None ,
811
+ )
812
+ . unwrap ( ) ;
813
+ create_branch ( clone1_dir, "foo" ) . unwrap ( ) ;
814
+ write_commit_file ( & clone1, "test.txt" , "test2" , "commit2" ) ;
815
+ push ( clone1_dir, "origin" , "foo" , false , false , None , None )
816
+ . unwrap ( ) ;
817
+
818
+ let branches_1 =
819
+ get_branches_info ( clone1_dir, false ) . unwrap ( ) ;
820
+
821
+ assert ! ( branches_1[ 0 ] . remote_details( ) . unwrap( ) . has_tracking) ;
822
+ assert ! ( branches_1[ 1 ] . remote_details( ) . unwrap( ) . has_tracking) ;
823
+
824
+ // clone2
825
+
826
+ let ( clone2_dir, _clone2) =
827
+ repo_clone ( r1_dir. path ( ) . to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
828
+
829
+ let clone2_dir = clone2_dir. path ( ) . to_str ( ) . unwrap ( ) ;
830
+
831
+ let branches_2 =
832
+ get_branches_info ( clone2_dir, false ) . unwrap ( ) ;
833
+
834
+ assert ! (
835
+ !branches_2[ 0 ] . remote_details( ) . unwrap( ) . has_tracking
836
+ ) ;
837
+ assert ! (
838
+ !branches_2[ 1 ] . remote_details( ) . unwrap( ) . has_tracking
839
+ ) ;
840
+ assert ! ( branches_2[ 2 ] . remote_details( ) . unwrap( ) . has_tracking) ;
841
+ }
759
842
}
0 commit comments