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