21
22
#define GET_REF_STATES (1<<0)
23
#define GET_HEAD_NAMES (1<<1)
24
+#define GET_PUSH_REF_STATES (1<<2)
25
26
static int verbose;
27
221
222
struct ref_states {
223
struct remote *remote;
223
- struct string_list new, stale, tracked, heads;
224
+ struct string_list new, stale, tracked, heads, push;
225
int queried;
226
};
227
276
return 0;
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
+
385
static int get_head_names(const struct ref *remote_refs, struct ref_states *states)
386
{
387
struct ref *ref, *matches;
751
return result;
752
}
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
+
761
static void free_remote_ref_states(struct ref_states *states)
762
{
763
string_list_clear(&states->new, 0);
764
string_list_clear(&states->stale, 0);
765
string_list_clear(&states->tracked, 0);
766
string_list_clear(&states->heads, 0);
767
+ string_list_clear_func(&states->push, clear_push_info);
768
}
769
770
static int append_ref_to_tracked_list(const char *refname,
808
get_ref_states(remote_refs, states);
809
if (query & GET_HEAD_NAMES)
810
get_head_names(remote_refs, states);
811
+ if (query & GET_PUSH_REF_STATES)
812
+ get_push_ref_states(remote_refs, states);
813
} else {
814
for_each_ref(append_ref_to_tracked_list, states);
815
sort_string_list(&states->tracked);
816
+ get_push_ref_states_noquery(states);
817
}
818
819
return 0;
822
struct show_info {
823
struct string_list *list;
824
struct ref_states *states;
707
- int width;
825
+ int width, width2;
826
int any_rebase;
827
};
828
917
return 0;
918
}
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
+
972
static int show(int argc, const char **argv)
973
{
974
int no_query = 0, result = 0, query_flag = 0;
987
return show_all();
988
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);
991
992
memset(&states, 0, sizeof(states));
993
memset(&info, 0, sizeof(info));
1037
string_list_clear(info.list, 0);
1038
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);
1052
1053
free_remote_ref_states(&states);
1054
}