@@ -21,6 +21,7 @@ static const char * const builtin_remote_usage[] = {
21
21
22
22
#define GET_REF_STATES (1<<0)
23
23
#define GET_HEAD_NAMES (1<<1)
24
+ #define GET_PUSH_REF_STATES (1<<2)
24
25
25
26
static int verbose ;
26
27
@@ -220,7 +221,7 @@ static void read_branches(void)
220
221
221
222
struct ref_states {
222
223
struct remote * remote ;
223
- struct string_list new , stale , tracked , heads ;
224
+ struct string_list new , stale , tracked , heads , push ;
224
225
int queried ;
225
226
};
226
227
@@ -275,6 +276,112 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
275
276
return 0 ;
276
277
}
277
278
279
+ struct push_info {
280
+ char * dest ;
281
+ int forced ;
282
+ enum {
283
+ PUSH_STATUS_CREATE = 0 ,
284
+ PUSH_STATUS_DELETE ,
285
+ PUSH_STATUS_UPTODATE ,
286
+ PUSH_STATUS_FASTFORWARD ,
287
+ PUSH_STATUS_OUTOFDATE ,
288
+ PUSH_STATUS_NOTQUERIED ,
289
+ } status ;
290
+ };
291
+
292
+ static int get_push_ref_states (const struct ref * remote_refs ,
293
+ struct ref_states * states )
294
+ {
295
+ struct remote * remote = states -> remote ;
296
+ struct ref * ref , * local_refs , * push_map , * * push_tail ;
297
+ if (remote -> mirror )
298
+ return 0 ;
299
+
300
+ local_refs = get_local_heads ();
301
+ ref = push_map = copy_ref_list (remote_refs );
302
+ while (ref -> next )
303
+ ref = ref -> next ;
304
+ push_tail = & ref -> next ;
305
+
306
+ match_refs (local_refs , push_map , & push_tail , remote -> push_refspec_nr ,
307
+ remote -> push_refspec , MATCH_REFS_NONE );
308
+
309
+ states -> push .strdup_strings = 1 ;
310
+ for (ref = push_map ; ref ; ref = ref -> next ) {
311
+ struct string_list_item * item ;
312
+ struct push_info * info ;
313
+
314
+ if (!ref -> peer_ref )
315
+ continue ;
316
+ hashcpy (ref -> new_sha1 , ref -> peer_ref -> new_sha1 );
317
+
318
+ item = string_list_append (abbrev_branch (ref -> peer_ref -> name ),
319
+ & states -> push );
320
+ item -> util = xcalloc (sizeof (struct push_info ), 1 );
321
+ info = item -> util ;
322
+ info -> forced = ref -> force ;
323
+ info -> dest = xstrdup (abbrev_branch (ref -> name ));
324
+
325
+ if (is_null_sha1 (ref -> new_sha1 )) {
326
+ info -> status = PUSH_STATUS_DELETE ;
327
+ } else if (!hashcmp (ref -> old_sha1 , ref -> new_sha1 ))
328
+ info -> status = PUSH_STATUS_UPTODATE ;
329
+ else if (is_null_sha1 (ref -> old_sha1 ))
330
+ info -> status = PUSH_STATUS_CREATE ;
331
+ else if (has_sha1_file (ref -> old_sha1 ) &&
332
+ ref_newer (ref -> new_sha1 , ref -> old_sha1 ))
333
+ info -> status = PUSH_STATUS_FASTFORWARD ;
334
+ else
335
+ info -> status = PUSH_STATUS_OUTOFDATE ;
336
+ // ref->peer_ref = NULL; /* local ref which is freed below */
337
+ }
338
+ free_refs (local_refs );
339
+ free_refs (push_map );
340
+ return 0 ;
341
+ }
342
+
343
+ static int get_push_ref_states_noquery (struct ref_states * states )
344
+ {
345
+ int i ;
346
+ struct remote * remote = states -> remote ;
347
+ struct string_list_item * item ;
348
+ struct push_info * info ;
349
+
350
+ if (remote -> mirror )
351
+ return 0 ;
352
+
353
+ states -> push .strdup_strings = 1 ;
354
+ if (!remote -> push_refspec_nr ) {
355
+ item = string_list_append ("(matching)" , & states -> push );
356
+ info = item -> util = xcalloc (sizeof (struct push_info ), 1 );
357
+ info -> status = PUSH_STATUS_NOTQUERIED ;
358
+ info -> dest = xstrdup (item -> string );
359
+ }
360
+ for (i = 0 ; i < remote -> push_refspec_nr ; i ++ ) {
361
+ struct refspec * spec = remote -> push + i ;
362
+ char buf [PATH_MAX ];
363
+ if (spec -> matching )
364
+ item = string_list_append ("(matching)" , & states -> push );
365
+ else if (spec -> pattern ) {
366
+ snprintf (buf , (sizeof (buf )), "%s*" , spec -> src );
367
+ item = string_list_append (buf , & states -> push );
368
+ snprintf (buf , (sizeof (buf )), "%s*" , spec -> dst );
369
+ } else if (strlen (spec -> src ))
370
+ item = string_list_append (spec -> src , & states -> push );
371
+ else
372
+ item = string_list_append ("(delete)" , & states -> push );
373
+
374
+ info = item -> util = xcalloc (sizeof (struct push_info ), 1 );
375
+ info -> forced = spec -> force ;
376
+ info -> status = PUSH_STATUS_NOTQUERIED ;
377
+ if (spec -> pattern )
378
+ info -> dest = xstrdup (buf );
379
+ else
380
+ info -> dest = xstrdup (spec -> dst ? spec -> dst : item -> string );
381
+ }
382
+ return 0 ;
383
+ }
384
+
278
385
static int get_head_names (const struct ref * remote_refs , struct ref_states * states )
279
386
{
280
387
struct ref * ref , * matches ;
@@ -644,12 +751,20 @@ static int rm(int argc, const char **argv)
644
751
return result ;
645
752
}
646
753
754
+ void clear_push_info (void * util , const char * string )
755
+ {
756
+ struct push_info * info = util ;
757
+ free (info -> dest );
758
+ free (info );
759
+ }
760
+
647
761
static void free_remote_ref_states (struct ref_states * states )
648
762
{
649
763
string_list_clear (& states -> new , 0 );
650
764
string_list_clear (& states -> stale , 0 );
651
765
string_list_clear (& states -> tracked , 0 );
652
766
string_list_clear (& states -> heads , 0 );
767
+ string_list_clear_func (& states -> push , clear_push_info );
653
768
}
654
769
655
770
static int append_ref_to_tracked_list (const char * refname ,
@@ -693,9 +808,12 @@ static int get_remote_ref_states(const char *name,
693
808
get_ref_states (remote_refs , states );
694
809
if (query & GET_HEAD_NAMES )
695
810
get_head_names (remote_refs , states );
811
+ if (query & GET_PUSH_REF_STATES )
812
+ get_push_ref_states (remote_refs , states );
696
813
} else {
697
814
for_each_ref (append_ref_to_tracked_list , states );
698
815
sort_string_list (& states -> tracked );
816
+ get_push_ref_states_noquery (states );
699
817
}
700
818
701
819
return 0 ;
@@ -704,7 +822,7 @@ static int get_remote_ref_states(const char *name,
704
822
struct show_info {
705
823
struct string_list * list ;
706
824
struct ref_states * states ;
707
- int width ;
825
+ int width , width2 ;
708
826
int any_rebase ;
709
827
};
710
828
@@ -799,6 +917,58 @@ int show_local_info_item(struct string_list_item *item, void *cb_data)
799
917
return 0 ;
800
918
}
801
919
920
+ int add_push_to_show_info (struct string_list_item * push_item , void * cb_data )
921
+ {
922
+ struct show_info * show_info = cb_data ;
923
+ struct push_info * push_info = push_item -> util ;
924
+ struct string_list_item * item ;
925
+ int n ;
926
+ if ((n = strlen (push_item -> string )) > show_info -> width )
927
+ show_info -> width = n ;
928
+ if ((n = strlen (push_info -> dest )) > show_info -> width2 )
929
+ show_info -> width2 = n ;
930
+ item = string_list_append (push_item -> string , show_info -> list );
931
+ item -> util = push_item -> util ;
932
+ return 0 ;
933
+ }
934
+
935
+ int show_push_info_item (struct string_list_item * item , void * cb_data )
936
+ {
937
+ struct show_info * show_info = cb_data ;
938
+ struct push_info * push_info = item -> util ;
939
+ char * src = item -> string , * status = NULL ;
940
+
941
+ switch (push_info -> status ) {
942
+ case PUSH_STATUS_CREATE :
943
+ status = "create" ;
944
+ break ;
945
+ case PUSH_STATUS_DELETE :
946
+ status = "delete" ;
947
+ src = "(none)" ;
948
+ break ;
949
+ case PUSH_STATUS_UPTODATE :
950
+ status = "up to date" ;
951
+ break ;
952
+ case PUSH_STATUS_FASTFORWARD :
953
+ status = "fast forwardable" ;
954
+ break ;
955
+ case PUSH_STATUS_OUTOFDATE :
956
+ status = "local out of date" ;
957
+ break ;
958
+ case PUSH_STATUS_NOTQUERIED :
959
+ break ;
960
+ }
961
+ if (status )
962
+ printf (" %-*s %s to %-*s (%s)\n" , show_info -> width , src ,
963
+ push_info -> forced ? "forces" : "pushes" ,
964
+ show_info -> width2 , push_info -> dest , status );
965
+ else
966
+ printf (" %-*s %s to %s\n" , show_info -> width , src ,
967
+ push_info -> forced ? "forces" : "pushes" ,
968
+ push_info -> dest );
969
+ return 0 ;
970
+ }
971
+
802
972
static int show (int argc , const char * * argv )
803
973
{
804
974
int no_query = 0 , result = 0 , query_flag = 0 ;
@@ -817,7 +987,7 @@ static int show(int argc, const char **argv)
817
987
return show_all ();
818
988
819
989
if (!no_query )
820
- query_flag = (GET_REF_STATES | GET_HEAD_NAMES );
990
+ query_flag = (GET_REF_STATES | GET_HEAD_NAMES | GET_PUSH_REF_STATES );
821
991
822
992
memset (& states , 0 , sizeof (states ));
823
993
memset (& info , 0 , sizeof (info ));
@@ -867,19 +1037,18 @@ static int show(int argc, const char **argv)
867
1037
string_list_clear (info .list , 0 );
868
1038
869
1039
/* git push info */
870
- if (states .remote -> push_refspec_nr ) {
871
- printf (" Local branch%s pushed with 'git push'\n" ,
872
- states .remote -> push_refspec_nr > 1 ?
873
- "es" : "" );
874
- for (i = 0 ; i < states .remote -> push_refspec_nr ; i ++ ) {
875
- struct refspec * spec = states .remote -> push + i ;
876
- printf (" %s%s%s%s\n" ,
877
- spec -> force ? "+" : "" ,
878
- abbrev_branch (spec -> src ),
879
- spec -> dst ? ":" : "" ,
880
- spec -> dst ? abbrev_branch (spec -> dst ) : "" );
881
- }
882
- }
1040
+ if (states .remote -> mirror )
1041
+ printf (" Local refs will be mirrored by 'git push'\n" );
1042
+
1043
+ info .width = info .width2 = 0 ;
1044
+ for_each_string_list (add_push_to_show_info , & states .push , & info );
1045
+ sort_string_list (info .list );
1046
+ if (info .list -> nr )
1047
+ printf (" Local ref%s configured for 'git push'%s:\n" ,
1048
+ info .list -> nr > 1 ? "s" : "" ,
1049
+ no_query ? " (status not queried)" : "" );
1050
+ for_each_string_list (show_push_info_item , info .list , & info );
1051
+ string_list_clear (info .list , 0 );
883
1052
884
1053
free_remote_ref_states (& states );
885
1054
}
0 commit comments