]> git.ipfire.org Git - thirdparty/git.git/blame - builtin/push.c
cmd_push: set "atomic" bit directly
[thirdparty/git.git] / builtin / push.c
CommitLineData
755225de
LT
1/*
2 * "git push"
3 */
4#include "cache.h"
5#include "refs.h"
6#include "run-command.h"
7#include "builtin.h"
5751f490 8#include "remote.h"
9b288516 9#include "transport.h"
378c4832 10#include "parse-options.h"
d2b17b32 11#include "submodule.h"
755225de 12
378c4832 13static const char * const push_usage[] = {
78dafaa5 14 N_("git push [<options>] [<repository> [<refspec>...]]"),
378c4832
DB
15 NULL,
16};
755225de 17
f7c815c3 18static int thin = 1;
f517f1f2 19static int deleterefs;
d23842fd 20static const char *receivepack;
8afd8dc0 21static int verbosity;
01fdc21f 22static int progress = -1;
755225de 23
28f5d176
JH
24static struct push_cas_option cas;
25
96f1e58f
DR
26static const char **refspec;
27static int refspec_nr;
8a883b02 28static int refspec_alloc;
755225de
LT
29
30static void add_refspec(const char *ref)
31{
8a883b02
JH
32 refspec_nr++;
33 ALLOC_GROW(refspec, refspec_nr, refspec_alloc);
34 refspec[refspec_nr-1] = ref;
755225de
LT
35}
36
ca02465b
JH
37static const char *map_refspec(const char *ref,
38 struct remote *remote, struct ref *local_refs)
755225de 39{
ca02465b
JH
40 struct ref *matched = NULL;
41
42 /* Does "ref" uniquely name our ref? */
43 if (count_refspec_match(ref, local_refs, &matched) != 1)
44 return ref;
45
46 if (remote->push) {
47 struct refspec query;
48 memset(&query, 0, sizeof(struct refspec));
49 query.src = matched->name;
50 if (!query_refspecs(remote->push, remote->push_refspec_nr, &query) &&
51 query.dst) {
52 struct strbuf buf = STRBUF_INIT;
53 strbuf_addf(&buf, "%s%s:%s",
54 query.force ? "+" : "",
55 query.src, query.dst);
56 return strbuf_detach(&buf, NULL);
57 }
58 }
59
fc9261ca 60 if (push_default == PUSH_DEFAULT_UPSTREAM &&
e3f11859 61 starts_with(matched->name, "refs/heads/")) {
fc9261ca
JH
62 struct branch *branch = branch_get(matched->name + 11);
63 if (branch->merge_nr == 1 && branch->merge[0]->src) {
64 struct strbuf buf = STRBUF_INIT;
65 strbuf_addf(&buf, "%s:%s",
66 ref, branch->merge[0]->src);
67 return strbuf_detach(&buf, NULL);
68 }
69 }
70
ca02465b
JH
71 return ref;
72}
73
74static void set_refspecs(const char **refs, int nr, const char *repo)
75{
76 struct remote *remote = NULL;
77 struct ref *local_refs = NULL;
8558fd9e 78 int i;
ca02465b 79
8558fd9e
DB
80 for (i = 0; i < nr; i++) {
81 const char *ref = refs[i];
82 if (!strcmp("tag", ref)) {
50d829c1 83 struct strbuf tagref = STRBUF_INIT;
8558fd9e 84 if (nr <= ++i)
8352d29e 85 die(_("tag shorthand without <tag>"));
50d829c1
JH
86 ref = refs[i];
87 if (deleterefs)
88 strbuf_addf(&tagref, ":refs/tags/%s", ref);
89 else
90 strbuf_addf(&tagref, "refs/tags/%s", ref);
91 ref = strbuf_detach(&tagref, NULL);
92 } else if (deleterefs) {
93 struct strbuf delref = STRBUF_INIT;
94 if (strchr(ref, ':'))
95 die(_("--delete only accepts plain target ref names"));
96 strbuf_addf(&delref, ":%s", ref);
97 ref = strbuf_detach(&delref, NULL);
ca02465b
JH
98 } else if (!strchr(ref, ':')) {
99 if (!remote) {
100 /* lazily grab remote and local_refs */
101 remote = remote_get(repo);
102 local_refs = get_local_heads();
f517f1f2 103 }
ca02465b 104 ref = map_refspec(ref, remote, local_refs);
50d829c1 105 }
8558fd9e 106 add_refspec(ref);
755225de 107 }
755225de
LT
108}
109
135dadef
JH
110static int push_url_of_remote(struct remote *remote, const char ***url_p)
111{
112 if (remote->pushurl_nr) {
113 *url_p = remote->pushurl;
114 return remote->pushurl_nr;
115 }
116 *url_p = remote->url;
117 return remote->url_nr;
118}
119
b55e6775
MM
120static NORETURN int die_push_simple(struct branch *branch, struct remote *remote) {
121 /*
122 * There's no point in using shorten_unambiguous_ref here,
123 * as the ambiguity would be on the remote side, not what
124 * we have locally. Plus, this is supposed to be the simple
125 * mode. If the user is doing something crazy like setting
126 * upstream to a non-branch, we should probably be showing
127 * them the big ugly fully qualified ref.
128 */
129 const char *advice_maybe = "";
cf4fff57
JK
130 const char *short_upstream = branch->merge[0]->src;
131
132 skip_prefix(short_upstream, "refs/heads/", &short_upstream);
b55e6775 133
b55e6775 134 /*
98e023de 135 * Don't show advice for people who explicitly set
b55e6775
MM
136 * push.default.
137 */
138 if (push_default == PUSH_DEFAULT_UNSPECIFIED)
139 advice_maybe = _("\n"
140 "To choose either option permanently, "
141 "see push.default in 'git help config'.");
142 die(_("The upstream branch of your current branch does not match\n"
143 "the name of your current branch. To push to the upstream branch\n"
144 "on the remote, use\n"
145 "\n"
146 " git push %s HEAD:%s\n"
147 "\n"
148 "To push to the branch of the same name on the remote, use\n"
149 "\n"
150 " git push %s %s\n"
151 "%s"),
152 remote->name, short_upstream,
153 remote->name, branch->name, advice_maybe);
154}
155
35ee69c0
RR
156static const char message_detached_head_die[] =
157 N_("You are not currently on a branch.\n"
158 "To push the history leading to the current (detached HEAD)\n"
159 "state now, use\n"
160 "\n"
161 " git push %s HEAD:<name-of-remote-branch>\n");
162
ed2b1829 163static void setup_push_upstream(struct remote *remote, struct branch *branch,
00a6fa07 164 int triangular, int simple)
52153747
FAG
165{
166 struct strbuf refspec = STRBUF_INIT;
ed2b1829 167
52153747 168 if (!branch)
35ee69c0 169 die(_(message_detached_head_die), remote->name);
135dadef 170 if (!branch->merge_nr || !branch->merge || !branch->remote_name)
6c80cd29 171 die(_("The current branch %s has no upstream branch.\n"
ec8460bd
MM
172 "To push the current branch and set the remote as upstream, use\n"
173 "\n"
6c80cd29 174 " git push --set-upstream %s %s\n"),
ec8460bd
MM
175 branch->name,
176 remote->name,
52153747
FAG
177 branch->name);
178 if (branch->merge_nr != 1)
6c80cd29 179 die(_("The current branch %s has multiple upstream branches, "
8352d29e 180 "refusing to push."), branch->name);
ed2b1829 181 if (triangular)
135dadef
JH
182 die(_("You are pushing to remote '%s', which is not the upstream of\n"
183 "your current branch '%s', without telling me what to push\n"
184 "to update which remote branch."),
185 remote->name, branch->name);
ed2b1829 186
00a6fa07 187 if (simple) {
ed2b1829
RR
188 /* Additional safety */
189 if (strcmp(branch->refname, branch->merge[0]->src))
190 die_push_simple(branch, remote);
191 }
135dadef 192
52153747
FAG
193 strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
194 add_refspec(refspec.buf);
195}
196
ed2b1829
RR
197static void setup_push_current(struct remote *remote, struct branch *branch)
198{
199 if (!branch)
200 die(_(message_detached_head_die), remote->name);
201 add_refspec(branch->name);
202}
203
f2c2c901 204static char warn_unspecified_push_default_msg[] =
b2ed944a 205N_("push.default is unset; its implicit value has changed in\n"
f2c2c901 206 "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
b2ed944a 207 "and maintain the traditional behavior, use:\n"
f2c2c901
MM
208 "\n"
209 " git config --global push.default matching\n"
210 "\n"
211 "To squelch this message and adopt the new behavior now, use:\n"
212 "\n"
213 " git config --global push.default simple\n"
214 "\n"
c13a5fe4
GJ
215 "When push.default is set to 'matching', git will push local branches\n"
216 "to the remote branches that already exist with the same name.\n"
217 "\n"
11037ee7 218 "Since Git 2.0, Git defaults to the more conservative 'simple'\n"
c13a5fe4
GJ
219 "behavior, which only pushes the current branch to the corresponding\n"
220 "remote branch that 'git pull' uses to update the current branch.\n"
221 "\n"
f2c2c901
MM
222 "See 'git help config' and search for 'push.default' for further information.\n"
223 "(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode\n"
224 "'current' instead of 'simple' if you sometimes use older versions of Git)");
225
226static void warn_unspecified_push_default_configuration(void)
227{
228 static int warn_once;
229
230 if (warn_once++)
231 return;
232 warning("%s\n", _(warn_unspecified_push_default_msg));
233}
234
ed2b1829
RR
235static int is_workflow_triangular(struct remote *remote)
236{
237 struct remote *fetch_remote = remote_get(NULL);
238 return (fetch_remote && fetch_remote != remote);
239}
240
ec8460bd 241static void setup_default_push_refspecs(struct remote *remote)
52153747 242{
ed2b1829
RR
243 struct branch *branch = branch_get(NULL);
244 int triangular = is_workflow_triangular(remote);
7b2ecd81 245
52153747 246 switch (push_default) {
bba0fd22 247 default:
52153747
FAG
248 case PUSH_DEFAULT_MATCHING:
249 add_refspec(":");
250 break;
251
b2ed944a
JH
252 case PUSH_DEFAULT_UNSPECIFIED:
253 warn_unspecified_push_default_configuration();
254 /* fallthru */
255
b55e6775 256 case PUSH_DEFAULT_SIMPLE:
ed2b1829
RR
257 if (triangular)
258 setup_push_current(remote, branch);
259 else
00a6fa07 260 setup_push_upstream(remote, branch, triangular, 1);
b55e6775
MM
261 break;
262
53c40311 263 case PUSH_DEFAULT_UPSTREAM:
00a6fa07 264 setup_push_upstream(remote, branch, triangular, 0);
52153747
FAG
265 break;
266
267 case PUSH_DEFAULT_CURRENT:
ed2b1829 268 setup_push_current(remote, branch);
52153747
FAG
269 break;
270
271 case PUSH_DEFAULT_NOTHING:
8352d29e
ÆAB
272 die(_("You didn't specify any refspecs to push, and "
273 "push.default is \"nothing\"."));
52153747
FAG
274 break;
275 }
276}
277
f25950f3
CT
278static const char message_advice_pull_before_push[] =
279 N_("Updates were rejected because the tip of your current branch is behind\n"
fc6c4e96
JK
280 "its remote counterpart. Integrate the remote changes (e.g.\n"
281 "'git pull ...') before pushing again.\n"
f25950f3
CT
282 "See the 'Note about fast-forwards' in 'git push --help' for details.");
283
f25950f3
CT
284static const char message_advice_checkout_pull_push[] =
285 N_("Updates were rejected because a pushed branch tip is behind its remote\n"
fc6c4e96
JK
286 "counterpart. Check out this branch and integrate the remote changes\n"
287 "(e.g. 'git pull ...') before pushing again.\n"
f25950f3
CT
288 "See the 'Note about fast-forwards' in 'git push --help' for details.");
289
75e5c0dc
JH
290static const char message_advice_ref_fetch_first[] =
291 N_("Updates were rejected because the remote contains work that you do\n"
292 "not have locally. This is usually caused by another repository pushing\n"
fc6c4e96
JK
293 "to the same ref. You may want to first integrate the remote changes\n"
294 "(e.g., 'git pull ...') before pushing again.\n"
75e5c0dc
JH
295 "See the 'Note about fast-forwards' in 'git push --help' for details.");
296
b24e6047 297static const char message_advice_ref_already_exists[] =
b4cf8db2 298 N_("Updates were rejected because the tag already exists in the remote.");
b24e6047 299
75e5c0dc
JH
300static const char message_advice_ref_needs_force[] =
301 N_("You cannot update a remote ref that points at a non-commit object,\n"
302 "or update a remote ref to make it point at a non-commit object,\n"
303 "without using the '--force' option.\n");
b24e6047 304
f25950f3
CT
305static void advise_pull_before_push(void)
306{
1184564e 307 if (!advice_push_non_ff_current || !advice_push_update_rejected)
f25950f3
CT
308 return;
309 advise(_(message_advice_pull_before_push));
310}
311
f25950f3
CT
312static void advise_checkout_pull_push(void)
313{
1184564e 314 if (!advice_push_non_ff_matching || !advice_push_update_rejected)
f25950f3
CT
315 return;
316 advise(_(message_advice_checkout_pull_push));
317}
318
b24e6047
CR
319static void advise_ref_already_exists(void)
320{
b4505682
CR
321 if (!advice_push_already_exists || !advice_push_update_rejected)
322 return;
b24e6047
CR
323 advise(_(message_advice_ref_already_exists));
324}
325
75e5c0dc
JH
326static void advise_ref_fetch_first(void)
327{
328 if (!advice_push_fetch_first || !advice_push_update_rejected)
329 return;
330 advise(_(message_advice_ref_fetch_first));
331}
332
333static void advise_ref_needs_force(void)
334{
335 if (!advice_push_needs_force || !advice_push_update_rejected)
336 return;
337 advise(_(message_advice_ref_needs_force));
338}
339
fb0cc87e
DB
340static int push_with_options(struct transport *transport, int flags)
341{
342 int err;
10643d4e 343 unsigned int reject_reasons;
8afd8dc0 344
78381069 345 transport_set_verbosity(transport, verbosity, progress);
8afd8dc0 346
fb0cc87e
DB
347 if (receivepack)
348 transport_set_option(transport,
349 TRANS_OPT_RECEIVEPACK, receivepack);
f7c815c3 350 transport_set_option(transport, TRANS_OPT_THIN, thin ? "yes" : NULL);
fb0cc87e 351
91048a95
JH
352 if (!is_empty_cas(&cas)) {
353 if (!transport->smart_options)
354 die("underlying transport does not support --%s option",
355 CAS_OPT_NAME);
356 transport->smart_options->cas = &cas;
357 }
358
8afd8dc0 359 if (verbosity > 0)
8352d29e 360 fprintf(stderr, _("Pushing to %s\n"), transport->url);
fb0cc87e 361 err = transport_push(transport, refspec_nr, refspec, flags,
10643d4e 362 &reject_reasons);
53970b92 363 if (err != 0)
8352d29e 364 error(_("failed to push some refs to '%s'"), transport->url);
53970b92 365
fb0cc87e 366 err |= transport_disconnect(transport);
fb0cc87e
DB
367 if (!err)
368 return 0;
369
10643d4e 370 if (reject_reasons & REJECT_NON_FF_HEAD) {
f25950f3 371 advise_pull_before_push();
10643d4e 372 } else if (reject_reasons & REJECT_NON_FF_OTHER) {
b2ed944a 373 advise_checkout_pull_push();
b24e6047
CR
374 } else if (reject_reasons & REJECT_ALREADY_EXISTS) {
375 advise_ref_already_exists();
75e5c0dc
JH
376 } else if (reject_reasons & REJECT_FETCH_FIRST) {
377 advise_ref_fetch_first();
378 } else if (reject_reasons & REJECT_NEEDS_FORCE) {
379 advise_ref_needs_force();
fb0cc87e
DB
380 }
381
382 return 1;
383}
384
9b288516 385static int do_push(const char *repo, int flags)
755225de 386{
5751f490 387 int i, errs;
f24f715e 388 struct remote *remote = pushremote_get(repo);
20346234
MG
389 const char **url;
390 int url_nr;
755225de 391
fa685bdf
DB
392 if (!remote) {
393 if (repo)
8352d29e 394 die(_("bad repository '%s'"), repo);
6c80cd29 395 die(_("No configured push destination.\n"
a3f5e7a3
MM
396 "Either specify the URL from the command-line or configure a remote repository using\n"
397 "\n"
398 " git remote add <name> <url>\n"
399 "\n"
400 "and then push using the remote name\n"
401 "\n"
6c80cd29 402 " git push <name>\n"));
fa685bdf 403 }
755225de 404
84bb2dfd
PB
405 if (remote->mirror)
406 flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
407
b259f09b
MZ
408 if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
409 if (!strcmp(*refspec, "refs/tags/*"))
8352d29e
ÆAB
410 return error(_("--all and --tags are incompatible"));
411 return error(_("--all can't be combined with refspecs"));
b259f09b
MZ
412 }
413
414 if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
415 if (!strcmp(*refspec, "refs/tags/*"))
8352d29e
ÆAB
416 return error(_("--mirror and --tags are incompatible"));
417 return error(_("--mirror can't be combined with refspecs"));
b259f09b 418 }
84bb2dfd
PB
419
420 if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
421 (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
8352d29e 422 return error(_("--all and --mirror are incompatible"));
84bb2dfd
PB
423 }
424
52153747
FAG
425 if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
426 if (remote->push_refspec_nr) {
427 refspec = remote->push_refspec;
428 refspec_nr = remote->push_refspec_nr;
429 } else if (!(flags & TRANSPORT_PUSH_MIRROR))
ec8460bd 430 setup_default_push_refspecs(remote);
5751f490 431 }
fd1d1b05 432 errs = 0;
135dadef 433 url_nr = push_url_of_remote(remote, &url);
fb0cc87e
DB
434 if (url_nr) {
435 for (i = 0; i < url_nr; i++) {
436 struct transport *transport =
437 transport_get(remote, url[i]);
438 if (push_with_options(transport, flags))
439 errs++;
07436e43 440 }
fb0cc87e
DB
441 } else {
442 struct transport *transport =
443 transport_get(remote, NULL);
444
445 if (push_with_options(transport, flags))
446 errs++;
755225de 447 }
fd1d1b05 448 return !!errs;
755225de
LT
449}
450
d2b17b32
FG
451static int option_parse_recurse_submodules(const struct option *opt,
452 const char *arg, int unset)
453{
454 int *flags = opt->value;
eb21c732
HV
455
456 if (*flags & (TRANSPORT_RECURSE_SUBMODULES_CHECK |
457 TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND))
458 die("%s can only be used once.", opt->long_name);
459
d2b17b32
FG
460 if (arg) {
461 if (!strcmp(arg, "check"))
462 *flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
eb21c732
HV
463 else if (!strcmp(arg, "on-demand"))
464 *flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND;
d2b17b32
FG
465 else
466 die("bad %s argument: %s", opt->long_name, arg);
467 } else
eb21c732
HV
468 die("option %s needs an argument (check|on-demand)",
469 opt->long_name);
d2b17b32
FG
470
471 return 0;
472}
473
b9459019
MG
474static int git_push_config(const char *k, const char *v, void *cb)
475{
b9459019
MG
476 int status;
477
478 status = git_gpg_config(k, v, NULL);
479 if (status)
480 return status;
06038cd7 481 return git_default_config(k, v, NULL);
b9459019
MG
482}
483
a633fca0 484int cmd_push(int argc, const char **argv, const char *prefix)
755225de 485{
9b288516 486 int flags = 0;
378c4832 487 int tags = 0;
84bb2dfd 488 int rc;
5751f490 489 const char *repo = NULL; /* default repository */
378c4832 490 struct option options[] = {
8afd8dc0 491 OPT__VERBOSITY(&verbosity),
78dafaa5
NTND
492 OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
493 OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
494 OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
c29c1b40 495 (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
d5d09d47
SB
496 OPT_BOOL( 0, "delete", &deleterefs, N_("delete refs")),
497 OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
78dafaa5
NTND
498 OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
499 OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
500 OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
28f5d176
JH
501 { OPTION_CALLBACK,
502 0, CAS_OPT_NAME, &cas, N_("refname>:<expect"),
503 N_("require old value of ref to be at this value"),
504 PARSE_OPT_OPTARG, parseopt_push_cas_option },
eedc4be5 505 { OPTION_CALLBACK, 0, "recurse-submodules", &flags, "check|on-demand",
f63cf8c9 506 N_("control recursive pushing of submodules"),
d2b17b32 507 PARSE_OPT_OPTARG, option_parse_recurse_submodules },
d5d09d47 508 OPT_BOOL( 0 , "thin", &thin, N_("use thin pack")),
78dafaa5
NTND
509 OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
510 OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")),
511 OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"),
e9fcd1e2 512 TRANSPORT_PUSH_SET_UPSTREAM),
78dafaa5
NTND
513 OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
514 OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"),
6ddba5e2 515 TRANSPORT_PUSH_PRUNE),
ec55559f 516 OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK),
c2aba155
JH
517 OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"),
518 TRANSPORT_PUSH_FOLLOW_TAGS),
a85b377d 519 OPT_BIT(0, "signed", &flags, N_("GPG sign the push"), TRANSPORT_PUSH_CERT),
d16c33b4 520 OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
378c4832
DB
521 OPT_END()
522 };
755225de 523
bbc30f99 524 packet_trace_identity("push");
b9459019 525 git_config(git_push_config, NULL);
37782920 526 argc = parse_options(argc, argv, prefix, options, push_usage, 0);
378c4832 527
f517f1f2 528 if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
8352d29e 529 die(_("--delete is incompatible with --all, --mirror and --tags"));
f517f1f2 530 if (deleterefs && argc < 2)
8352d29e 531 die(_("--delete doesn't make sense without any refs"));
f517f1f2 532
378c4832
DB
533 if (tags)
534 add_refspec("refs/tags/*");
378c4832
DB
535
536 if (argc > 0) {
537 repo = argv[0];
ca02465b 538 set_refspecs(argv + 1, argc - 1, repo);
755225de 539 }
8558fd9e 540
84bb2dfd
PB
541 rc = do_push(repo, flags);
542 if (rc == -1)
94c89ba6 543 usage_with_options(push_usage, options);
84bb2dfd
PB
544 else
545 return rc;
755225de 546}