@@ -149,6 +149,7 @@ static int add(int argc, const char **argv)
149
149
struct branch_info {
150
150
char * remote_name ;
151
151
struct string_list merge ;
152
+ int rebase ;
152
153
};
153
154
154
155
static struct string_list branch_list ;
@@ -165,10 +166,11 @@ static const char *abbrev_ref(const char *name, const char *prefix)
165
166
static int config_read_branches (const char * key , const char * value , void * cb )
166
167
{
167
168
if (!prefixcmp (key , "branch." )) {
169
+ const char * orig_key = key ;
168
170
char * name ;
169
171
struct string_list_item * item ;
170
172
struct branch_info * info ;
171
- enum { REMOTE , MERGE } type ;
173
+ enum { REMOTE , MERGE , REBASE } type ;
172
174
173
175
key += 7 ;
174
176
if (!postfixcmp (key , ".remote" )) {
@@ -177,6 +179,9 @@ static int config_read_branches(const char *key, const char *value, void *cb)
177
179
} else if (!postfixcmp (key , ".merge" )) {
178
180
name = xstrndup (key , strlen (key ) - 6 );
179
181
type = MERGE ;
182
+ } else if (!postfixcmp (key , ".rebase" )) {
183
+ name = xstrndup (key , strlen (key ) - 7 );
184
+ type = REBASE ;
180
185
} else
181
186
return 0 ;
182
187
@@ -187,9 +192,9 @@ static int config_read_branches(const char *key, const char *value, void *cb)
187
192
info = item -> util ;
188
193
if (type == REMOTE ) {
189
194
if (info -> remote_name )
190
- warning ("more than one branch. %s" , key );
195
+ warning ("more than one %s" , orig_key );
191
196
info -> remote_name = xstrdup (value );
192
- } else {
197
+ } else if ( type == MERGE ) {
193
198
char * space = strchr (value , ' ' );
194
199
value = abbrev_branch (value );
195
200
while (space ) {
@@ -200,7 +205,8 @@ static int config_read_branches(const char *key, const char *value, void *cb)
200
205
space = strchr (value , ' ' );
201
206
}
202
207
string_list_append (xstrdup (value ), & info -> merge );
203
- }
208
+ } else
209
+ info -> rebase = git_config_bool (orig_key , value );
204
210
}
205
211
return 0 ;
206
212
}
@@ -215,6 +221,7 @@ static void read_branches(void)
215
221
struct ref_states {
216
222
struct remote * remote ;
217
223
struct string_list new , stale , tracked , heads ;
224
+ int queried ;
218
225
};
219
226
220
227
static int handle_one_branch (const char * refname ,
@@ -637,20 +644,6 @@ static int rm(int argc, const char **argv)
637
644
return result ;
638
645
}
639
646
640
- static void show_list (const char * title , struct string_list * list ,
641
- const char * extra_arg )
642
- {
643
- int i ;
644
-
645
- if (!list -> nr )
646
- return ;
647
-
648
- printf (title , list -> nr > 1 ? "es" : "" , extra_arg );
649
- printf ("\n" );
650
- for (i = 0 ; i < list -> nr ; i ++ )
651
- printf (" %s\n" , list -> items [i ].string );
652
- }
653
-
654
647
static void free_remote_ref_states (struct ref_states * states )
655
648
{
656
649
string_list_clear (& states -> new , 0 );
@@ -695,6 +688,7 @@ static int get_remote_ref_states(const char *name,
695
688
remote_refs = transport_get_remote_refs (transport );
696
689
transport_disconnect (transport );
697
690
691
+ states -> queried = 1 ;
698
692
if (query & GET_REF_STATES )
699
693
get_ref_states (remote_refs , states );
700
694
if (query & GET_HEAD_NAMES )
@@ -707,6 +701,104 @@ static int get_remote_ref_states(const char *name,
707
701
return 0 ;
708
702
}
709
703
704
+ struct show_info {
705
+ struct string_list * list ;
706
+ struct ref_states * states ;
707
+ int width ;
708
+ int any_rebase ;
709
+ };
710
+
711
+ int add_remote_to_show_info (struct string_list_item * item , void * cb_data )
712
+ {
713
+ struct show_info * info = cb_data ;
714
+ int n = strlen (item -> string );
715
+ if (n > info -> width )
716
+ info -> width = n ;
717
+ string_list_insert (item -> string , info -> list );
718
+ return 0 ;
719
+ }
720
+
721
+ int show_remote_info_item (struct string_list_item * item , void * cb_data )
722
+ {
723
+ struct show_info * info = cb_data ;
724
+ struct ref_states * states = info -> states ;
725
+ const char * name = item -> string ;
726
+
727
+ if (states -> queried ) {
728
+ const char * fmt = "%s" ;
729
+ const char * arg = "" ;
730
+ if (string_list_has_string (& states -> new , name )) {
731
+ fmt = " new (next fetch will store in remotes/%s)" ;
732
+ arg = states -> remote -> name ;
733
+ } else if (string_list_has_string (& states -> tracked , name ))
734
+ arg = " tracked" ;
735
+ else if (string_list_has_string (& states -> stale , name ))
736
+ arg = " stale (use 'git remote prune' to remove)" ;
737
+ else
738
+ arg = " ???" ;
739
+ printf (" %-*s" , info -> width , name );
740
+ printf (fmt , arg );
741
+ printf ("\n" );
742
+ } else
743
+ printf (" %s\n" , name );
744
+
745
+ return 0 ;
746
+ }
747
+
748
+ int add_local_to_show_info (struct string_list_item * branch_item , void * cb_data )
749
+ {
750
+ struct show_info * show_info = cb_data ;
751
+ struct ref_states * states = show_info -> states ;
752
+ struct branch_info * branch_info = branch_item -> util ;
753
+ struct string_list_item * item ;
754
+ int n ;
755
+
756
+ if (!branch_info -> merge .nr || !branch_info -> remote_name ||
757
+ strcmp (states -> remote -> name , branch_info -> remote_name ))
758
+ return 0 ;
759
+ if ((n = strlen (branch_item -> string )) > show_info -> width )
760
+ show_info -> width = n ;
761
+ if (branch_info -> rebase )
762
+ show_info -> any_rebase = 1 ;
763
+
764
+ item = string_list_insert (branch_item -> string , show_info -> list );
765
+ item -> util = branch_info ;
766
+
767
+ return 0 ;
768
+ }
769
+
770
+ int show_local_info_item (struct string_list_item * item , void * cb_data )
771
+ {
772
+ struct show_info * show_info = cb_data ;
773
+ struct branch_info * branch_info = item -> util ;
774
+ struct string_list * merge = & branch_info -> merge ;
775
+ const char * also ;
776
+ int i ;
777
+
778
+ if (branch_info -> rebase && branch_info -> merge .nr > 1 ) {
779
+ error ("invalid branch.%s.merge; cannot rebase onto > 1 branch" ,
780
+ item -> string );
781
+ return 0 ;
782
+ }
783
+
784
+ printf (" %-*s " , show_info -> width , item -> string );
785
+ if (branch_info -> rebase ) {
786
+ printf ("rebases onto remote %s\n" , merge -> items [0 ].string );
787
+ return 0 ;
788
+ } else if (show_info -> any_rebase ) {
789
+ printf (" merges with remote %s\n" , merge -> items [0 ].string );
790
+ also = " and with remote" ;
791
+ } else {
792
+ printf ("merges with remote %s\n" , merge -> items [0 ].string );
793
+ also = " and with remote" ;
794
+ }
795
+ for (i = 1 ; i < merge -> nr ; i ++ )
796
+ printf (" %-*s %s %s\n" , show_info -> width , "" , also ,
797
+ merge -> items [i ].string );
798
+
799
+ return 0 ;
800
+ }
801
+
710
802
static int show (int argc , const char * * argv )
711
803
{
712
804
int no_query = 0 , result = 0 , query_flag = 0 ;
@@ -716,6 +808,8 @@ static int show(int argc, const char **argv)
716
808
OPT_END ()
717
809
};
718
810
struct ref_states states ;
811
+ struct string_list info_list = { NULL , 0 , 0 , 0 };
812
+ struct show_info info ;
719
813
720
814
argc = parse_options (argc , argv , options , builtin_remote_usage , 0 );
721
815
@@ -726,6 +820,9 @@ static int show(int argc, const char **argv)
726
820
query_flag = (GET_REF_STATES | GET_HEAD_NAMES );
727
821
728
822
memset (& states , 0 , sizeof (states ));
823
+ memset (& info , 0 , sizeof (info ));
824
+ info .states = & states ;
825
+ info .list = & info_list ;
729
826
for (; argc ; argc -- , argv ++ ) {
730
827
int i ;
731
828
@@ -747,32 +844,29 @@ static int show(int argc, const char **argv)
747
844
printf (" %s\n" , states .heads .items [i ].string );
748
845
}
749
846
750
- for (i = 0 ; i < branch_list .nr ; i ++ ) {
751
- struct string_list_item * branch = branch_list .items + i ;
752
- struct branch_info * info = branch -> util ;
753
- int j ;
754
-
755
- if (!info -> merge .nr || strcmp (* argv , info -> remote_name ))
756
- continue ;
757
- printf (" Remote branch%s merged with 'git pull' "
758
- "while on branch %s\n " ,
759
- info -> merge .nr > 1 ? "es" : "" ,
760
- branch -> string );
761
- for (j = 0 ; j < info -> merge .nr ; j ++ )
762
- printf (" %s" , info -> merge .items [j ].string );
763
- printf ("\n" );
764
- }
765
-
766
- if (!no_query ) {
767
- show_list (" New remote branch%s (next fetch "
768
- "will store in remotes/%s)" ,
769
- & states .new , states .remote -> name );
770
- show_list (" Stale tracking branch%s (use 'git remote "
771
- "prune')" , & states .stale , "" );
772
- }
773
-
774
- show_list (" Tracked remote branch%s" , & states .tracked , "" );
775
-
847
+ /* remote branch info */
848
+ info .width = 0 ;
849
+ for_each_string_list (add_remote_to_show_info , & states .new , & info );
850
+ for_each_string_list (add_remote_to_show_info , & states .tracked , & info );
851
+ for_each_string_list (add_remote_to_show_info , & states .stale , & info );
852
+ if (info .list -> nr )
853
+ printf (" Remote branch%s:%s\n" ,
854
+ info .list -> nr > 1 ? "es" : "" ,
855
+ no_query ? " (status not queried)" : "" );
856
+ for_each_string_list (show_remote_info_item , info .list , & info );
857
+ string_list_clear (info .list , 0 );
858
+
859
+ /* git pull info */
860
+ info .width = 0 ;
861
+ info .any_rebase = 0 ;
862
+ for_each_string_list (add_local_to_show_info , & branch_list , & info );
863
+ if (info .list -> nr )
864
+ printf (" Local branch%s configured for 'git pull':\n" ,
865
+ info .list -> nr > 1 ? "es" : "" );
866
+ for_each_string_list (show_local_info_item , info .list , & info );
867
+ string_list_clear (info .list , 0 );
868
+
869
+ /* git push info */
776
870
if (states .remote -> push_refspec_nr ) {
777
871
printf (" Local branch%s pushed with 'git push'\n" ,
778
872
states .remote -> push_refspec_nr > 1 ?
0 commit comments