1/*
2 * "git push"
3 */
4#include "cache.h"
5#include "config.h"
6#include "refs.h"
7#include "run-command.h"
8#include "builtin.h"
9#include "remote.h"
10#include "transport.h"
11#include "parse-options.h"
12#include "submodule.h"
13#include "submodule-config.h"
14#include "send-pack.h"
15#include "color.h"
16
17static const char * const push_usage[] = {
18 N_("git push [<options>] [<repository> [<refspec>...]]"),
19 NULL,
20};
21
22static int push_use_color = -1;
23static char push_colors[][COLOR_MAXLEN] = {
24 GIT_COLOR_RESET,
25 GIT_COLOR_RED, /* ERROR */
26};
27
28enum color_push {
29 PUSH_COLOR_RESET = 0,
30 PUSH_COLOR_ERROR = 1
31};
32
33static int parse_push_color_slot(const char *slot)
34{
35 if (!strcasecmp(slot, "reset"))
36 return PUSH_COLOR_RESET;
37 if (!strcasecmp(slot, "error"))
38 return PUSH_COLOR_ERROR;
39 return -1;
40}
41
42static const char *push_get_color(enum color_push ix)
43{
44 if (want_color_stderr(push_use_color))
45 return push_colors[ix];
46 return "";
47}
48
49static int thin = 1;
50static int deleterefs;
51static const char *receivepack;
52static int verbosity;
53static int progress = -1;
54static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
55static enum transport_family family;
56
57static struct push_cas_option cas;
58
59static const char **refspec;
60static int refspec_nr;
61static int refspec_alloc;
62
63static struct string_list push_options_config = STRING_LIST_INIT_DUP;
64
65static void add_refspec(const char *ref)
66{
67 refspec_nr++;
68 ALLOC_GROW(refspec, refspec_nr, refspec_alloc);
69 refspec[refspec_nr-1] = ref;
70}
71
72static const char *map_refspec(const char *ref,
73 struct remote *remote, struct ref *local_refs)
74{
75 struct ref *matched = NULL;
76
77 /* Does "ref" uniquely name our ref? */
78 if (count_refspec_match(ref, local_refs, &matched) != 1)
79 return ref;
80
81 if (remote->push) {
82 struct refspec query;
83 memset(&query, 0, sizeof(struct refspec));
84 query.src = matched->name;
85 if (!query_refspecs(remote->push, remote->push_refspec_nr, &query) &&
86 query.dst) {
87 struct strbuf buf = STRBUF_INIT;
88 strbuf_addf(&buf, "%s%s:%s",
89 query.force ? "+" : "",
90 query.src, query.dst);
91 return strbuf_detach(&buf, NULL);
92 }
93 }
94
95 if (push_default == PUSH_DEFAULT_UPSTREAM &&
96 starts_with(matched->name, "refs/heads/")) {
97 struct branch *branch = branch_get(matched->name + 11);
98 if (branch->merge_nr == 1 && branch->merge[0]->src) {
99 struct strbuf buf = STRBUF_INIT;
100 strbuf_addf(&buf, "%s:%s",
101 ref, branch->merge[0]->src);
102 return strbuf_detach(&buf, NULL);
103 }
104 }
105
106 return ref;
107}
108
109static void set_refspecs(const char **refs, int nr, const char *repo)
110{
111 struct remote *remote = NULL;
112 struct ref *local_refs = NULL;
113 int i;
114
115 for (i = 0; i < nr; i++) {
116 const char *ref = refs[i];
117 if (!strcmp("tag", ref)) {
118 struct strbuf tagref = STRBUF_INIT;
119 if (nr <= ++i)
120 die(_("tag shorthand without <tag>"));
121 ref = refs[i];
122 if (deleterefs)
123 strbuf_addf(&tagref, ":refs/tags/%s", ref);
124 else
125 strbuf_addf(&tagref, "refs/tags/%s", ref);
126 ref = strbuf_detach(&tagref, NULL);
127 } else if (deleterefs) {
128 struct strbuf delref = STRBUF_INIT;
129 if (strchr(ref, ':'))
130 die(_("--delete only accepts plain target ref names"));
131 strbuf_addf(&delref, ":%s", ref);
132 ref = strbuf_detach(&delref, NULL);
133 } else if (!strchr(ref, ':')) {
134 if (!remote) {
135 /* lazily grab remote and local_refs */
136 remote = remote_get(repo);
137 local_refs = get_local_heads();
138 }
139 ref = map_refspec(ref, remote, local_refs);
140 }
141 add_refspec(ref);
142 }
143}
144
145static int push_url_of_remote(struct remote *remote, const char ***url_p)
146{
147 if (remote->pushurl_nr) {
148 *url_p = remote->pushurl;
149 return remote->pushurl_nr;
150 }
151 *url_p = remote->url;
152 return remote->url_nr;
153}
154
155static NORETURN int die_push_simple(struct branch *branch, struct remote *remote) {
156 /*
157 * There's no point in using shorten_unambiguous_ref here,
158 * as the ambiguity would be on the remote side, not what
159 * we have locally. Plus, this is supposed to be the simple
160 * mode. If the user is doing something crazy like setting
161 * upstream to a non-branch, we should probably be showing
162 * them the big ugly fully qualified ref.
163 */
164 const char *advice_maybe = "";
165 const char *short_upstream = branch->merge[0]->src;
166
167 skip_prefix(short_upstream, "refs/heads/", &short_upstream);
168
169 /*
170 * Don't show advice for people who explicitly set
171 * push.default.
172 */
173 if (push_default == PUSH_DEFAULT_UNSPECIFIED)
174 advice_maybe = _("\n"
175 "To choose either option permanently, "
176 "see push.default in 'git help config'.");
177 die(_("The upstream branch of your current branch does not match\n"
178 "the name of your current branch. To push to the upstream branch\n"
179 "on the remote, use\n"
180 "\n"
181 " git push %s HEAD:%s\n"
182 "\n"
183 "To push to the branch of the same name on the remote, use\n"
184 "\n"
185 " git push %s %s\n"
186 "%s"),
187 remote->name, short_upstream,
188 remote->name, branch->name, advice_maybe);
189}
190
191static const char message_detached_head_die[] =
192 N_("You are not currently on a branch.\n"
193 "To push the history leading to the current (detached HEAD)\n"
194 "state now, use\n"
195 "\n"
196 " git push %s HEAD:<name-of-remote-branch>\n");
197
198static void setup_push_upstream(struct remote *remote, struct branch *branch,
199 int triangular, int simple)
200{
201 struct strbuf refspec = STRBUF_INIT;
202
203 if (!branch)
204 die(_(message_detached_head_die), remote->name);
205 if (!branch->merge_nr || !branch->merge || !branch->remote_name)
206 die(_("The current branch %s has no upstream branch.\n"
207 "To push the current branch and set the remote as upstream, use\n"
208 "\n"
209 " git push --set-upstream %s %s\n"),
210 branch->name,
211 remote->name,
212 branch->name);
213 if (branch->merge_nr != 1)
214 die(_("The current branch %s has multiple upstream branches, "
215 "refusing to push."), branch->name);
216 if (triangular)
217 die(_("You are pushing to remote '%s', which is not the upstream of\n"
218 "your current branch '%s', without telling me what to push\n"
219 "to update which remote branch."),
220 remote->name, branch->name);
221
222 if (simple) {
223 /* Additional safety */
224 if (strcmp(branch->refname, branch->merge[0]->src))
225 die_push_simple(branch, remote);
226 }
227
228 strbuf_addf(&refspec, "%s:%s", branch->refname, branch->merge[0]->src);
229 add_refspec(refspec.buf);
230}
231
232static void setup_push_current(struct remote *remote, struct branch *branch)
233{
234 struct strbuf refspec = STRBUF_INIT;
235
236 if (!branch)
237 die(_(message_detached_head_die), remote->name);
238 strbuf_addf(&refspec, "%s:%s", branch->refname, branch->refname);
239 add_refspec(refspec.buf);
240}
241
242static int is_workflow_triangular(struct remote *remote)
243{
244 struct remote *fetch_remote = remote_get(NULL);
245 return (fetch_remote && fetch_remote != remote);
246}
247
248static void setup_default_push_refspecs(struct remote *remote)
249{
250 struct branch *branch = branch_get(NULL);
251 int triangular = is_workflow_triangular(remote);
252
253 switch (push_default) {
254 default:
255 case PUSH_DEFAULT_MATCHING:
256 add_refspec(":");
257 break;
258
259 case PUSH_DEFAULT_UNSPECIFIED:
260 case PUSH_DEFAULT_SIMPLE:
261 if (triangular)
262 setup_push_current(remote, branch);
263 else
264 setup_push_upstream(remote, branch, triangular, 1);
265 break;
266
267 case PUSH_DEFAULT_UPSTREAM:
268 setup_push_upstream(remote, branch, triangular, 0);
269 break;
270
271 case PUSH_DEFAULT_CURRENT:
272 setup_push_current(remote, branch);
273 break;
274
275 case PUSH_DEFAULT_NOTHING:
276 die(_("You didn't specify any refspecs to push, and "
277 "push.default is \"nothing\"."));
278 break;
279 }
280}
281
282static const char message_advice_pull_before_push[] =
283 N_("Updates were rejected because the tip of your current branch is behind\n"
284 "its remote counterpart. Integrate the remote changes (e.g.\n"
285 "'git pull ...') before pushing again.\n"
286 "See the 'Note about fast-forwards' in 'git push --help' for details.");
287
288static const char message_advice_checkout_pull_push[] =
289 N_("Updates were rejected because a pushed branch tip is behind its remote\n"
290 "counterpart. Check out this branch and integrate the remote changes\n"
291 "(e.g. 'git pull ...') before pushing again.\n"
292 "See the 'Note about fast-forwards' in 'git push --help' for details.");
293
294static const char message_advice_ref_fetch_first[] =
295 N_("Updates were rejected because the remote contains work that you do\n"
296 "not have locally. This is usually caused by another repository pushing\n"
297 "to the same ref. You may want to first integrate the remote changes\n"
298 "(e.g., 'git pull ...') before pushing again.\n"
299 "See the 'Note about fast-forwards' in 'git push --help' for details.");
300
301static const char message_advice_ref_already_exists[] =
302 N_("Updates were rejected because the tag already exists in the remote.");
303
304static const char message_advice_ref_needs_force[] =
305 N_("You cannot update a remote ref that points at a non-commit object,\n"
306 "or update a remote ref to make it point at a non-commit object,\n"
307 "without using the '--force' option.\n");
308
309static void advise_pull_before_push(void)
310{
311 if (!advice_push_non_ff_current || !advice_push_update_rejected)
312 return;
313 advise(_(message_advice_pull_before_push));
314}
315
316static void advise_checkout_pull_push(void)
317{
318 if (!advice_push_non_ff_matching || !advice_push_update_rejected)
319 return;
320 advise(_(message_advice_checkout_pull_push));
321}
322
323static void advise_ref_already_exists(void)
324{
325 if (!advice_push_already_exists || !advice_push_update_rejected)
326 return;
327 advise(_(message_advice_ref_already_exists));
328}
329
330static void advise_ref_fetch_first(void)
331{
332 if (!advice_push_fetch_first || !advice_push_update_rejected)
333 return;
334 advise(_(message_advice_ref_fetch_first));
335}
336
337static void advise_ref_needs_force(void)
338{
339 if (!advice_push_needs_force || !advice_push_update_rejected)
340 return;
341 advise(_(message_advice_ref_needs_force));
342}
343
344static int push_with_options(struct transport *transport, int flags)
345{
346 int err;
347 unsigned int reject_reasons;
348
349 transport_set_verbosity(transport, verbosity, progress);
350 transport->family = family;
351
352 if (receivepack)
353 transport_set_option(transport,
354 TRANS_OPT_RECEIVEPACK, receivepack);
355 transport_set_option(transport, TRANS_OPT_THIN, thin ? "yes" : NULL);
356
357 if (!is_empty_cas(&cas)) {
358 if (!transport->smart_options)
359 die("underlying transport does not support --%s option",
360 CAS_OPT_NAME);
361 transport->smart_options->cas = &cas;
362 }
363
364 if (verbosity > 0)
365 fprintf(stderr, _("Pushing to %s\n"), transport->url);
366 err = transport_push(transport, refspec_nr, refspec, flags,
367 &reject_reasons);
368 if (err != 0) {
369 fprintf(stderr, "%s", push_get_color(PUSH_COLOR_ERROR));
370 error(_("failed to push some refs to '%s'"), transport->url);
371 fprintf(stderr, "%s", push_get_color(PUSH_COLOR_RESET));
372 }
373
374 err |= transport_disconnect(transport);
375 if (!err)
376 return 0;
377
378 if (reject_reasons & REJECT_NON_FF_HEAD) {
379 advise_pull_before_push();
380 } else if (reject_reasons & REJECT_NON_FF_OTHER) {
381 advise_checkout_pull_push();
382 } else if (reject_reasons & REJECT_ALREADY_EXISTS) {
383 advise_ref_already_exists();
384 } else if (reject_reasons & REJECT_FETCH_FIRST) {
385 advise_ref_fetch_first();
386 } else if (reject_reasons & REJECT_NEEDS_FORCE) {
387 advise_ref_needs_force();
388 }
389
390 return 1;
391}
392
393static int do_push(const char *repo, int flags,
394 const struct string_list *push_options)
395{
396 int i, errs;
397 struct remote *remote = pushremote_get(repo);
398 const char **url;
399 int url_nr;
400
401 if (!remote) {
402 if (repo)
403 die(_("bad repository '%s'"), repo);
404 die(_("No configured push destination.\n"
405 "Either specify the URL from the command-line or configure a remote repository using\n"
406 "\n"
407 " git remote add <name> <url>\n"
408 "\n"
409 "and then push using the remote name\n"
410 "\n"
411 " git push <name>\n"));
412 }
413
414 if (remote->mirror)
415 flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
416
417 if (push_options->nr)
418 flags |= TRANSPORT_PUSH_OPTIONS;
419
420 if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
421 if (!strcmp(*refspec, "refs/tags/*"))
422 return error(_("--all and --tags are incompatible"));
423 return error(_("--all can't be combined with refspecs"));
424 }
425
426 if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
427 if (!strcmp(*refspec, "refs/tags/*"))
428 return error(_("--mirror and --tags are incompatible"));
429 return error(_("--mirror can't be combined with refspecs"));
430 }
431
432 if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
433 (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
434 return error(_("--all and --mirror are incompatible"));
435 }
436
437 if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
438 if (remote->push_refspec_nr) {
439 refspec = remote->push_refspec;
440 refspec_nr = remote->push_refspec_nr;
441 } else if (!(flags & TRANSPORT_PUSH_MIRROR))
442 setup_default_push_refspecs(remote);
443 }
444 errs = 0;
445 url_nr = push_url_of_remote(remote, &url);
446 if (url_nr) {
447 for (i = 0; i < url_nr; i++) {
448 struct transport *transport =
449 transport_get(remote, url[i]);
450 if (flags & TRANSPORT_PUSH_OPTIONS)
451 transport->push_options = push_options;
452 if (push_with_options(transport, flags))
453 errs++;
454 }
455 } else {
456 struct transport *transport =
457 transport_get(remote, NULL);
458 if (flags & TRANSPORT_PUSH_OPTIONS)
459 transport->push_options = push_options;
460 if (push_with_options(transport, flags))
461 errs++;
462 }
463 return !!errs;
464}
465
466static int option_parse_recurse_submodules(const struct option *opt,
467 const char *arg, int unset)
468{
469 int *recurse_submodules = opt->value;
470
471 if (unset)
472 *recurse_submodules = RECURSE_SUBMODULES_OFF;
473 else if (arg)
474 *recurse_submodules = parse_push_recurse_submodules_arg(opt->long_name, arg);
475 else
476 die("%s missing parameter", opt->long_name);
477
478 return 0;
479}
480
481static void set_push_cert_flags(int *flags, int v)
482{
483 switch (v) {
484 case SEND_PACK_PUSH_CERT_NEVER:
485 *flags &= ~(TRANSPORT_PUSH_CERT_ALWAYS | TRANSPORT_PUSH_CERT_IF_ASKED);
486 break;
487 case SEND_PACK_PUSH_CERT_ALWAYS:
488 *flags |= TRANSPORT_PUSH_CERT_ALWAYS;
489 *flags &= ~TRANSPORT_PUSH_CERT_IF_ASKED;
490 break;
491 case SEND_PACK_PUSH_CERT_IF_ASKED:
492 *flags |= TRANSPORT_PUSH_CERT_IF_ASKED;
493 *flags &= ~TRANSPORT_PUSH_CERT_ALWAYS;
494 break;
495 }
496}
497
498
499static int git_push_config(const char *k, const char *v, void *cb)
500{
501 const char *slot_name;
502 int *flags = cb;
503 int status;
504
505 status = git_gpg_config(k, v, NULL);
506 if (status)
507 return status;
508
509 if (!strcmp(k, "push.followtags")) {
510 if (git_config_bool(k, v))
511 *flags |= TRANSPORT_PUSH_FOLLOW_TAGS;
512 else
513 *flags &= ~TRANSPORT_PUSH_FOLLOW_TAGS;
514 return 0;
515 } else if (!strcmp(k, "push.gpgsign")) {
516 const char *value;
517 if (!git_config_get_value("push.gpgsign", &value)) {
518 switch (git_parse_maybe_bool(value)) {
519 case 0:
520 set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_NEVER);
521 break;
522 case 1:
523 set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_ALWAYS);
524 break;
525 default:
526 if (value && !strcasecmp(value, "if-asked"))
527 set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_IF_ASKED);
528 else
529 return error("Invalid value for '%s'", k);
530 }
531 }
532 } else if (!strcmp(k, "push.recursesubmodules")) {
533 const char *value;
534 if (!git_config_get_value("push.recursesubmodules", &value))
535 recurse_submodules = parse_push_recurse_submodules_arg(k, value);
536 } else if (!strcmp(k, "submodule.recurse")) {
537 int val = git_config_bool(k, v) ?
538 RECURSE_SUBMODULES_ON_DEMAND : RECURSE_SUBMODULES_OFF;
539 recurse_submodules = val;
540 } else if (!strcmp(k, "push.pushoption")) {
541 if (!v)
542 return config_error_nonbool(k);
543 else
544 if (!*v)
545 string_list_clear(&push_options_config, 0);
546 else
547 string_list_append(&push_options_config, v);
548 return 0;
549 } else if (!strcmp(k, "color.push")) {
550 push_use_color = git_config_colorbool(k, v);
551 return 0;
552 } else if (skip_prefix(k, "color.push.", &slot_name)) {
553 int slot = parse_push_color_slot(slot_name);
554 if (slot < 0)
555 return 0;
556 if (!v)
557 return config_error_nonbool(k);
558 return color_parse(v, push_colors[slot]);
559 }
560
561 return git_default_config(k, v, NULL);
562}
563
564int cmd_push(int argc, const char **argv, const char *prefix)
565{
566 int flags = 0;
567 int tags = 0;
568 int push_cert = -1;
569 int rc;
570 const char *repo = NULL; /* default repository */
571 struct string_list push_options_cmdline = STRING_LIST_INIT_DUP;
572 struct string_list *push_options;
573 const struct string_list_item *item;
574
575 struct option options[] = {
576 OPT__VERBOSITY(&verbosity),
577 OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
578 OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
579 OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
580 (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
581 OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")),
582 OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
583 OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
584 OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
585 OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
586 { OPTION_CALLBACK,
587 0, CAS_OPT_NAME, &cas, N_("refname>:<expect"),
588 N_("require old value of ref to be at this value"),
589 PARSE_OPT_OPTARG, parseopt_push_cas_option },
590 { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, "check|on-demand|no",
591 N_("control recursive pushing of submodules"),
592 PARSE_OPT_OPTARG, option_parse_recurse_submodules },
593 OPT_BOOL_F( 0 , "thin", &thin, N_("use thin pack"), PARSE_OPT_NOCOMPLETE),
594 OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
595 OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")),
596 OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"),
597 TRANSPORT_PUSH_SET_UPSTREAM),
598 OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
599 OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"),
600 TRANSPORT_PUSH_PRUNE),
601 OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK),
602 OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"),
603 TRANSPORT_PUSH_FOLLOW_TAGS),
604 { OPTION_CALLBACK,
605 0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
606 PARSE_OPT_OPTARG, option_parse_push_signed },
607 OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
608 OPT_STRING_LIST('o', "push-option", &push_options_cmdline, N_("server-specific"), N_("option to transmit")),
609 OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
610 TRANSPORT_FAMILY_IPV4),
611 OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
612 TRANSPORT_FAMILY_IPV6),
613 OPT_END()
614 };
615
616 packet_trace_identity("push");
617 git_config(git_push_config, &flags);
618 argc = parse_options(argc, argv, prefix, options, push_usage, 0);
619 push_options = (push_options_cmdline.nr
620 ? &push_options_cmdline
621 : &push_options_config);
622 set_push_cert_flags(&flags, push_cert);
623
624 if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
625 die(_("--delete is incompatible with --all, --mirror and --tags"));
626 if (deleterefs && argc < 2)
627 die(_("--delete doesn't make sense without any refs"));
628
629 if (recurse_submodules == RECURSE_SUBMODULES_CHECK)
630 flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
631 else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
632 flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND;
633 else if (recurse_submodules == RECURSE_SUBMODULES_ONLY)
634 flags |= TRANSPORT_RECURSE_SUBMODULES_ONLY;
635
636 if (tags)
637 add_refspec("refs/tags/*");
638
639 if (argc > 0) {
640 repo = argv[0];
641 set_refspecs(argv + 1, argc - 1, repo);
642 }
643
644 for_each_string_list_item(item, push_options)
645 if (strchr(item->string, '\n'))
646 die(_("push options must not have new line characters"));
647
648 rc = do_push(repo, flags, push_options);
649 string_list_clear(&push_options_cmdline, 0);
650 string_list_clear(&push_options_config, 0);
651 if (rc == -1)
652 usage_with_options(push_usage, options);
653 else
654 return rc;
655}