Git fork
at reftables-rust 844 lines 24 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2#define DISABLE_SIGN_COMPARE_WARNINGS 3 4#include "builtin.h" 5#include "config.h" 6#include "environment.h" 7#include "gettext.h" 8#include "hash.h" 9#include "hex.h" 10#include "refs.h" 11#include "object-name.h" 12#include "parse-options.h" 13#include "quote.h" 14 15static const char * const git_update_ref_usage[] = { 16 N_("git update-ref [<options>] -d <refname> [<old-oid>]"), 17 N_("git update-ref [<options>] <refname> <new-oid> [<old-oid>]"), 18 N_("git update-ref [<options>] --stdin [-z] [--batch-updates]"), 19 NULL 20}; 21 22static char line_termination = '\n'; 23static unsigned int update_flags; 24static unsigned int default_flags; 25static unsigned create_reflog_flag; 26static const char *msg; 27 28/* 29 * Parse one whitespace- or NUL-terminated, possibly C-quoted argument 30 * and append the result to arg. Return a pointer to the terminator. 31 * Die if there is an error in how the argument is C-quoted. This 32 * function is only used if not -z. 33 */ 34static const char *parse_arg(const char *next, struct strbuf *arg) 35{ 36 if (*next == '"') { 37 const char *orig = next; 38 39 if (unquote_c_style(arg, next, &next)) 40 die("badly quoted argument: %s", orig); 41 if (*next && !isspace(*next)) 42 die("unexpected character after quoted argument: %s", orig); 43 } else { 44 while (*next && !isspace(*next)) 45 strbuf_addch(arg, *next++); 46 } 47 48 return next; 49} 50 51/* 52 * Parse the reference name immediately after "command SP". If not 53 * -z, then handle C-quoting. Return a pointer to a newly allocated 54 * string containing the name of the reference, or NULL if there was 55 * an error. Update *next to point at the character that terminates 56 * the argument. Die if C-quoting is malformed or the reference name 57 * is invalid. 58 */ 59static char *parse_refname(const char **next) 60{ 61 struct strbuf ref = STRBUF_INIT; 62 63 if (line_termination) { 64 /* Without -z, use the next argument */ 65 *next = parse_arg(*next, &ref); 66 } else { 67 /* With -z, use everything up to the next NUL */ 68 strbuf_addstr(&ref, *next); 69 *next += ref.len; 70 } 71 72 if (!ref.len) { 73 strbuf_release(&ref); 74 return NULL; 75 } 76 77 if (check_refname_format(ref.buf, REFNAME_ALLOW_ONELEVEL)) 78 die("invalid ref format: %s", ref.buf); 79 80 return strbuf_detach(&ref, NULL); 81} 82 83/* 84 * Wrapper around parse_refname which skips the next delimiter. 85 */ 86static char *parse_next_refname(const char **next) 87{ 88 if (line_termination) { 89 /* Without -z, consume SP and use next argument */ 90 if (!**next || **next == line_termination) 91 return NULL; 92 if (**next != ' ') 93 die("expected SP but got: %s", *next); 94 } else { 95 /* With -z, read the next NUL-terminated line */ 96 if (**next) 97 return NULL; 98 } 99 /* Skip the delimiter */ 100 (*next)++; 101 102 return parse_refname(next); 103} 104 105/* 106 * Wrapper around parse_arg which skips the next delimiter. 107 */ 108static char *parse_next_arg(const char **next) 109{ 110 struct strbuf arg = STRBUF_INIT; 111 112 if (line_termination) { 113 /* Without -z, consume SP and use next argument */ 114 if (!**next || **next == line_termination) 115 return NULL; 116 if (**next != ' ') 117 die("expected SP but got: %s", *next); 118 } else { 119 /* With -z, read the next NUL-terminated line */ 120 if (**next) 121 return NULL; 122 } 123 /* Skip the delimiter */ 124 (*next)++; 125 126 if (line_termination) { 127 /* Without -z, use the next argument */ 128 *next = parse_arg(*next, &arg); 129 } else { 130 /* With -z, use everything up to the next NUL */ 131 strbuf_addstr(&arg, *next); 132 *next += arg.len; 133 } 134 135 if (arg.len) 136 return strbuf_detach(&arg, NULL); 137 138 strbuf_release(&arg); 139 return NULL; 140} 141 142/* 143 * The value being parsed is <old-oid> (as opposed to <new-oid>; the 144 * difference affects which error messages are generated): 145 */ 146#define PARSE_SHA1_OLD 0x01 147 148/* 149 * For backwards compatibility, accept an empty string for update's 150 * <new-oid> in binary mode to be equivalent to specifying zeros. 151 */ 152#define PARSE_SHA1_ALLOW_EMPTY 0x02 153 154/* 155 * Parse an argument separator followed by the next argument, if any. 156 * If there is an argument, convert it to a SHA-1, write it to sha1, 157 * set *next to point at the character terminating the argument, and 158 * return 0. If there is no argument at all (not even the empty 159 * string), return 1 and leave *next unchanged. If the value is 160 * provided but cannot be converted to a SHA-1, die. flags can 161 * include PARSE_SHA1_OLD and/or PARSE_SHA1_ALLOW_EMPTY. 162 */ 163static int parse_next_oid(const char **next, const char *end, 164 struct object_id *oid, 165 const char *command, const char *refname, 166 int flags) 167{ 168 struct strbuf arg = STRBUF_INIT; 169 int ret = 0; 170 171 if (*next == end) 172 goto eof; 173 174 if (line_termination) { 175 /* Without -z, consume SP and use next argument */ 176 if (!**next || **next == line_termination) 177 return 1; 178 if (**next != ' ') 179 die("%s %s: expected SP but got: %s", 180 command, refname, *next); 181 (*next)++; 182 *next = parse_arg(*next, &arg); 183 if (arg.len) { 184 if (repo_get_oid_with_flags(the_repository, arg.buf, oid, 185 GET_OID_SKIP_AMBIGUITY_CHECK)) 186 goto invalid; 187 } else { 188 /* Without -z, an empty value means all zeros: */ 189 oidclr(oid, the_repository->hash_algo); 190 } 191 } else { 192 /* With -z, read the next NUL-terminated line */ 193 if (**next) 194 die("%s %s: expected NUL but got: %s", 195 command, refname, *next); 196 (*next)++; 197 if (*next == end) 198 goto eof; 199 strbuf_addstr(&arg, *next); 200 *next += arg.len; 201 202 if (arg.len) { 203 if (repo_get_oid_with_flags(the_repository, arg.buf, oid, 204 GET_OID_SKIP_AMBIGUITY_CHECK)) 205 goto invalid; 206 } else if (flags & PARSE_SHA1_ALLOW_EMPTY) { 207 /* With -z, treat an empty value as all zeros: */ 208 warning("%s %s: missing <new-oid>, treating as zero", 209 command, refname); 210 oidclr(oid, the_repository->hash_algo); 211 } else { 212 /* 213 * With -z, an empty non-required value means 214 * unspecified: 215 */ 216 ret = 1; 217 } 218 } 219 220 strbuf_release(&arg); 221 222 return ret; 223 224 invalid: 225 die(flags & PARSE_SHA1_OLD ? 226 "%s %s: invalid <old-oid>: %s" : 227 "%s %s: invalid <new-oid>: %s", 228 command, refname, arg.buf); 229 230 eof: 231 die(flags & PARSE_SHA1_OLD ? 232 "%s %s: unexpected end of input when reading <old-oid>" : 233 "%s %s: unexpected end of input when reading <new-oid>", 234 command, refname); 235} 236 237 238/* 239 * The following five parse_cmd_*() functions parse the corresponding 240 * command. In each case, next points at the character following the 241 * command name and the following space. They each return a pointer 242 * to the character terminating the command, and die with an 243 * explanatory message if there are any parsing problems. All of 244 * these functions handle either text or binary format input, 245 * depending on how line_termination is set. 246 */ 247 248static void parse_cmd_update(struct ref_transaction *transaction, 249 const char *next, const char *end) 250{ 251 struct strbuf err = STRBUF_INIT; 252 char *refname; 253 struct object_id new_oid, old_oid; 254 int have_old; 255 256 refname = parse_refname(&next); 257 if (!refname) 258 die("update: missing <ref>"); 259 260 if (parse_next_oid(&next, end, &new_oid, "update", refname, 261 PARSE_SHA1_ALLOW_EMPTY)) 262 die("update %s: missing <new-oid>", refname); 263 264 have_old = !parse_next_oid(&next, end, &old_oid, "update", refname, 265 PARSE_SHA1_OLD); 266 267 if (*next != line_termination) 268 die("update %s: extra input: %s", refname, next); 269 270 if (ref_transaction_update(transaction, refname, 271 &new_oid, have_old ? &old_oid : NULL, 272 NULL, NULL, 273 update_flags | create_reflog_flag, 274 msg, &err)) 275 die("%s", err.buf); 276 277 update_flags = default_flags; 278 free(refname); 279 strbuf_release(&err); 280} 281 282static void parse_cmd_symref_update(struct ref_transaction *transaction, 283 const char *next, const char *end UNUSED) 284{ 285 char *refname, *new_target, *old_arg; 286 char *old_target = NULL; 287 struct strbuf err = STRBUF_INIT; 288 struct object_id old_oid; 289 int have_old_oid = 0; 290 291 refname = parse_refname(&next); 292 if (!refname) 293 die("symref-update: missing <ref>"); 294 295 new_target = parse_next_refname(&next); 296 if (!new_target) 297 die("symref-update %s: missing <new-target>", refname); 298 299 old_arg = parse_next_arg(&next); 300 if (old_arg) { 301 old_target = parse_next_arg(&next); 302 if (!old_target) 303 die("symref-update %s: expected old value", refname); 304 305 if (!strcmp(old_arg, "oid")) { 306 if (repo_get_oid_with_flags(the_repository, old_target, &old_oid, 307 GET_OID_SKIP_AMBIGUITY_CHECK)) 308 die("symref-update %s: invalid oid: %s", refname, old_target); 309 310 have_old_oid = 1; 311 } else if (!strcmp(old_arg, "ref")) { 312 if (check_refname_format(old_target, REFNAME_ALLOW_ONELEVEL)) 313 die("symref-update %s: invalid ref: %s", refname, old_target); 314 } else { 315 die("symref-update %s: invalid arg '%s' for old value", refname, old_arg); 316 } 317 } 318 319 if (*next != line_termination) 320 die("symref-update %s: extra input: %s", refname, next); 321 322 if (ref_transaction_update(transaction, refname, NULL, 323 have_old_oid ? &old_oid : NULL, 324 new_target, 325 have_old_oid ? NULL : old_target, 326 update_flags | create_reflog_flag, 327 msg, &err)) 328 die("%s", err.buf); 329 330 update_flags = default_flags; 331 free(refname); 332 free(old_arg); 333 free(old_target); 334 free(new_target); 335 strbuf_release(&err); 336} 337 338static void parse_cmd_create(struct ref_transaction *transaction, 339 const char *next, const char *end) 340{ 341 struct strbuf err = STRBUF_INIT; 342 char *refname; 343 struct object_id new_oid; 344 345 refname = parse_refname(&next); 346 if (!refname) 347 die("create: missing <ref>"); 348 349 if (parse_next_oid(&next, end, &new_oid, "create", refname, 0)) 350 die("create %s: missing <new-oid>", refname); 351 352 if (is_null_oid(&new_oid)) 353 die("create %s: zero <new-oid>", refname); 354 355 if (*next != line_termination) 356 die("create %s: extra input: %s", refname, next); 357 358 if (ref_transaction_create(transaction, refname, &new_oid, NULL, 359 update_flags | create_reflog_flag, 360 msg, &err)) 361 die("%s", err.buf); 362 363 update_flags = default_flags; 364 free(refname); 365 strbuf_release(&err); 366} 367 368 369static void parse_cmd_symref_create(struct ref_transaction *transaction, 370 const char *next, const char *end UNUSED) 371{ 372 struct strbuf err = STRBUF_INIT; 373 char *refname, *new_target; 374 375 refname = parse_refname(&next); 376 if (!refname) 377 die("symref-create: missing <ref>"); 378 379 new_target = parse_next_refname(&next); 380 if (!new_target) 381 die("symref-create %s: missing <new-target>", refname); 382 383 if (*next != line_termination) 384 die("symref-create %s: extra input: %s", refname, next); 385 386 if (ref_transaction_create(transaction, refname, NULL, new_target, 387 update_flags | create_reflog_flag, 388 msg, &err)) 389 die("%s", err.buf); 390 391 update_flags = default_flags; 392 free(refname); 393 free(new_target); 394 strbuf_release(&err); 395} 396 397static void parse_cmd_delete(struct ref_transaction *transaction, 398 const char *next, const char *end) 399{ 400 struct strbuf err = STRBUF_INIT; 401 char *refname; 402 struct object_id old_oid; 403 int have_old; 404 405 refname = parse_refname(&next); 406 if (!refname) 407 die("delete: missing <ref>"); 408 409 if (parse_next_oid(&next, end, &old_oid, "delete", refname, 410 PARSE_SHA1_OLD)) { 411 have_old = 0; 412 } else { 413 if (is_null_oid(&old_oid)) 414 die("delete %s: zero <old-oid>", refname); 415 have_old = 1; 416 } 417 418 if (*next != line_termination) 419 die("delete %s: extra input: %s", refname, next); 420 421 if (ref_transaction_delete(transaction, refname, 422 have_old ? &old_oid : NULL, 423 NULL, update_flags, msg, &err)) 424 die("%s", err.buf); 425 426 update_flags = default_flags; 427 free(refname); 428 strbuf_release(&err); 429} 430 431 432static void parse_cmd_symref_delete(struct ref_transaction *transaction, 433 const char *next, const char *end UNUSED) 434{ 435 struct strbuf err = STRBUF_INIT; 436 char *refname, *old_target; 437 438 if (!(update_flags & REF_NO_DEREF)) 439 die("symref-delete: cannot operate with deref mode"); 440 441 refname = parse_refname(&next); 442 if (!refname) 443 die("symref-delete: missing <ref>"); 444 445 old_target = parse_next_refname(&next); 446 447 if (*next != line_termination) 448 die("symref-delete %s: extra input: %s", refname, next); 449 450 if (ref_transaction_delete(transaction, refname, NULL, 451 old_target, update_flags, msg, &err)) 452 die("%s", err.buf); 453 454 update_flags = default_flags; 455 free(refname); 456 free(old_target); 457 strbuf_release(&err); 458} 459 460 461static void parse_cmd_verify(struct ref_transaction *transaction, 462 const char *next, const char *end) 463{ 464 struct strbuf err = STRBUF_INIT; 465 char *refname; 466 struct object_id old_oid; 467 468 refname = parse_refname(&next); 469 if (!refname) 470 die("verify: missing <ref>"); 471 472 if (parse_next_oid(&next, end, &old_oid, "verify", refname, 473 PARSE_SHA1_OLD)) 474 oidclr(&old_oid, the_repository->hash_algo); 475 476 if (*next != line_termination) 477 die("verify %s: extra input: %s", refname, next); 478 479 if (ref_transaction_verify(transaction, refname, &old_oid, 480 NULL, update_flags, &err)) 481 die("%s", err.buf); 482 483 update_flags = default_flags; 484 free(refname); 485 strbuf_release(&err); 486} 487 488static void parse_cmd_symref_verify(struct ref_transaction *transaction, 489 const char *next, const char *end UNUSED) 490{ 491 struct strbuf err = STRBUF_INIT; 492 struct object_id old_oid; 493 char *refname, *old_target; 494 495 if (!(update_flags & REF_NO_DEREF)) 496 die("symref-verify: cannot operate with deref mode"); 497 498 refname = parse_refname(&next); 499 if (!refname) 500 die("symref-verify: missing <ref>"); 501 502 /* 503 * old_ref is optional, if not provided, we need to ensure that the 504 * ref doesn't exist. 505 */ 506 old_target = parse_next_refname(&next); 507 if (!old_target) 508 oidcpy(&old_oid, null_oid(the_hash_algo)); 509 510 if (*next != line_termination) 511 die("symref-verify %s: extra input: %s", refname, next); 512 513 if (ref_transaction_verify(transaction, refname, 514 old_target ? NULL : &old_oid, 515 old_target, update_flags, &err)) 516 die("%s", err.buf); 517 518 update_flags = default_flags; 519 free(refname); 520 free(old_target); 521 strbuf_release(&err); 522} 523 524static void report_ok(const char *command) 525{ 526 fprintf(stdout, "%s: ok\n", command); 527 fflush(stdout); 528} 529 530static void parse_cmd_option(struct ref_transaction *transaction UNUSED, 531 const char *next, const char *end UNUSED) 532{ 533 const char *rest; 534 if (skip_prefix(next, "no-deref", &rest) && *rest == line_termination) 535 update_flags |= REF_NO_DEREF; 536 else 537 die("option unknown: %s", next); 538} 539 540static void parse_cmd_start(struct ref_transaction *transaction UNUSED, 541 const char *next, const char *end UNUSED) 542{ 543 if (*next != line_termination) 544 die("start: extra input: %s", next); 545 report_ok("start"); 546} 547 548static void parse_cmd_prepare(struct ref_transaction *transaction, 549 const char *next, const char *end UNUSED) 550{ 551 struct strbuf error = STRBUF_INIT; 552 if (*next != line_termination) 553 die("prepare: extra input: %s", next); 554 if (ref_transaction_prepare(transaction, &error)) 555 die("prepare: %s", error.buf); 556 report_ok("prepare"); 557} 558 559static void parse_cmd_abort(struct ref_transaction *transaction, 560 const char *next, const char *end UNUSED) 561{ 562 struct strbuf error = STRBUF_INIT; 563 if (*next != line_termination) 564 die("abort: extra input: %s", next); 565 if (ref_transaction_abort(transaction, &error)) 566 die("abort: %s", error.buf); 567 report_ok("abort"); 568} 569 570static void print_rejected_refs(const char *refname, 571 const struct object_id *old_oid, 572 const struct object_id *new_oid, 573 const char *old_target, 574 const char *new_target, 575 enum ref_transaction_error err, 576 void *cb_data UNUSED) 577{ 578 struct strbuf sb = STRBUF_INIT; 579 const char *reason = ref_transaction_error_msg(err); 580 581 strbuf_addf(&sb, "rejected %s %s %s %s\n", refname, 582 new_oid ? oid_to_hex(new_oid) : new_target, 583 old_oid ? oid_to_hex(old_oid) : old_target, 584 reason); 585 586 fwrite(sb.buf, sb.len, 1, stdout); 587 strbuf_release(&sb); 588} 589 590static void parse_cmd_commit(struct ref_transaction *transaction, 591 const char *next, const char *end UNUSED) 592{ 593 struct strbuf error = STRBUF_INIT; 594 if (*next != line_termination) 595 die("commit: extra input: %s", next); 596 if (ref_transaction_commit(transaction, &error)) 597 die("commit: %s", error.buf); 598 599 ref_transaction_for_each_rejected_update(transaction, 600 print_rejected_refs, NULL); 601 602 report_ok("commit"); 603 ref_transaction_free(transaction); 604} 605 606enum update_refs_state { 607 /* Non-transactional state open for updates. */ 608 UPDATE_REFS_OPEN, 609 /* A transaction has been started. */ 610 UPDATE_REFS_STARTED, 611 /* References are locked and ready for commit */ 612 UPDATE_REFS_PREPARED, 613 /* Transaction has been committed or closed. */ 614 UPDATE_REFS_CLOSED, 615}; 616 617static const struct parse_cmd { 618 const char *prefix; 619 void (*fn)(struct ref_transaction *, const char *, const char *); 620 unsigned args; 621 enum update_refs_state state; 622} command[] = { 623 { "update", parse_cmd_update, 3, UPDATE_REFS_OPEN }, 624 { "create", parse_cmd_create, 2, UPDATE_REFS_OPEN }, 625 { "delete", parse_cmd_delete, 2, UPDATE_REFS_OPEN }, 626 { "verify", parse_cmd_verify, 2, UPDATE_REFS_OPEN }, 627 { "symref-update", parse_cmd_symref_update, 4, UPDATE_REFS_OPEN }, 628 { "symref-create", parse_cmd_symref_create, 2, UPDATE_REFS_OPEN }, 629 { "symref-delete", parse_cmd_symref_delete, 2, UPDATE_REFS_OPEN }, 630 { "symref-verify", parse_cmd_symref_verify, 2, UPDATE_REFS_OPEN }, 631 { "option", parse_cmd_option, 1, UPDATE_REFS_OPEN }, 632 { "start", parse_cmd_start, 0, UPDATE_REFS_STARTED }, 633 { "prepare", parse_cmd_prepare, 0, UPDATE_REFS_PREPARED }, 634 { "abort", parse_cmd_abort, 0, UPDATE_REFS_CLOSED }, 635 { "commit", parse_cmd_commit, 0, UPDATE_REFS_CLOSED }, 636}; 637 638static void update_refs_stdin(unsigned int flags) 639{ 640 struct strbuf input = STRBUF_INIT, err = STRBUF_INIT; 641 enum update_refs_state state = UPDATE_REFS_OPEN; 642 struct ref_transaction *transaction; 643 int i, j; 644 645 transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), 646 flags, &err); 647 if (!transaction) 648 die("%s", err.buf); 649 650 /* Read each line dispatch its command */ 651 while (!strbuf_getwholeline(&input, stdin, line_termination)) { 652 const struct parse_cmd *cmd = NULL; 653 654 if (*input.buf == line_termination) 655 die("empty command in input"); 656 else if (isspace(*input.buf)) 657 die("whitespace before command: %s", input.buf); 658 659 for (i = 0; i < ARRAY_SIZE(command); i++) { 660 const char *prefix = command[i].prefix; 661 char c; 662 663 if (!starts_with(input.buf, prefix)) 664 continue; 665 666 /* 667 * If the command has arguments, verify that it's 668 * followed by a space. Otherwise, it shall be followed 669 * by a line terminator. 670 */ 671 c = command[i].args ? ' ' : line_termination; 672 if (input.buf[strlen(prefix)] != c) 673 continue; 674 675 cmd = &command[i]; 676 break; 677 } 678 if (!cmd) 679 die("unknown command: %s", input.buf); 680 681 /* 682 * Read additional arguments if NUL-terminated. Do not raise an 683 * error in case there is an early EOF to let the command 684 * handle missing arguments with a proper error message. 685 */ 686 for (j = 1; line_termination == '\0' && j < cmd->args; j++) 687 if (strbuf_appendwholeline(&input, stdin, line_termination)) 688 break; 689 690 switch (state) { 691 case UPDATE_REFS_OPEN: 692 case UPDATE_REFS_STARTED: 693 if (state == UPDATE_REFS_STARTED && cmd->state == UPDATE_REFS_STARTED) 694 die("cannot restart ongoing transaction"); 695 /* Do not downgrade a transaction to a non-transaction. */ 696 if (cmd->state >= state) 697 state = cmd->state; 698 break; 699 case UPDATE_REFS_PREPARED: 700 if (cmd->state != UPDATE_REFS_CLOSED) 701 die("prepared transactions can only be closed"); 702 state = cmd->state; 703 break; 704 case UPDATE_REFS_CLOSED: 705 if (cmd->state != UPDATE_REFS_STARTED) 706 die("transaction is closed"); 707 708 /* 709 * Open a new transaction if we're currently closed and 710 * get a "start". 711 */ 712 state = cmd->state; 713 transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), 714 flags, &err); 715 if (!transaction) 716 die("%s", err.buf); 717 718 break; 719 } 720 721 cmd->fn(transaction, input.buf + strlen(cmd->prefix) + !!cmd->args, 722 input.buf + input.len); 723 } 724 725 switch (state) { 726 case UPDATE_REFS_OPEN: 727 /* Commit by default if no transaction was requested. */ 728 if (ref_transaction_commit(transaction, &err)) 729 die("%s", err.buf); 730 ref_transaction_for_each_rejected_update(transaction, 731 print_rejected_refs, NULL); 732 ref_transaction_free(transaction); 733 break; 734 case UPDATE_REFS_STARTED: 735 case UPDATE_REFS_PREPARED: 736 /* If using a transaction, we want to abort it. */ 737 if (ref_transaction_abort(transaction, &err)) 738 die("%s", err.buf); 739 break; 740 case UPDATE_REFS_CLOSED: 741 /* Otherwise no need to do anything, the transaction was closed already. */ 742 break; 743 } 744 745 strbuf_release(&err); 746 strbuf_release(&input); 747} 748 749int cmd_update_ref(int argc, 750 const char **argv, 751 const char *prefix, 752 struct repository *repo UNUSED) 753{ 754 const char *refname, *oldval; 755 struct object_id oid, oldoid; 756 int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0; 757 int create_reflog = 0; 758 unsigned int flags = 0; 759 760 struct option options[] = { 761 OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")), 762 OPT_BOOL('d', NULL, &delete, N_("delete the reference")), 763 OPT_BOOL( 0 , "no-deref", &no_deref, 764 N_("update <refname> not the one it points to")), 765 OPT_BOOL('z', NULL, &end_null, N_("stdin has NUL-terminated arguments")), 766 OPT_BOOL( 0 , "stdin", &read_stdin, N_("read updates from stdin")), 767 OPT_BOOL( 0 , "create-reflog", &create_reflog, N_("create a reflog")), 768 OPT_BIT('0', "batch-updates", &flags, N_("batch reference updates"), 769 REF_TRANSACTION_ALLOW_FAILURE), 770 OPT_END(), 771 }; 772 773 repo_config(the_repository, git_default_config, NULL); 774 argc = parse_options(argc, argv, prefix, options, git_update_ref_usage, 775 0); 776 if (msg && !*msg) 777 die("Refusing to perform update with empty message."); 778 779 create_reflog_flag = create_reflog ? REF_FORCE_CREATE_REFLOG : 0; 780 781 if (no_deref) { 782 default_flags = REF_NO_DEREF; 783 update_flags = default_flags; 784 } 785 786 if (read_stdin) { 787 if (delete || argc > 0) 788 usage_with_options(git_update_ref_usage, options); 789 if (end_null) 790 line_termination = '\0'; 791 update_refs_stdin(flags); 792 return 0; 793 } else if (flags & REF_TRANSACTION_ALLOW_FAILURE) { 794 die("--batch-updates can only be used with --stdin"); 795 } 796 797 if (end_null) 798 usage_with_options(git_update_ref_usage, options); 799 800 if (delete) { 801 if (argc < 1 || argc > 2) 802 usage_with_options(git_update_ref_usage, options); 803 refname = argv[0]; 804 oldval = argv[1]; 805 } else { 806 const char *value; 807 if (argc < 2 || argc > 3) 808 usage_with_options(git_update_ref_usage, options); 809 refname = argv[0]; 810 value = argv[1]; 811 oldval = argv[2]; 812 if (repo_get_oid_with_flags(the_repository, value, &oid, 813 GET_OID_SKIP_AMBIGUITY_CHECK)) 814 die("%s: not a valid SHA1", value); 815 } 816 817 if (oldval) { 818 if (!*oldval) 819 /* 820 * The empty string implies that the reference 821 * must not already exist: 822 */ 823 oidclr(&oldoid, the_repository->hash_algo); 824 else if (repo_get_oid_with_flags(the_repository, oldval, &oldoid, 825 GET_OID_SKIP_AMBIGUITY_CHECK)) 826 die("%s: not a valid old SHA1", oldval); 827 } 828 829 if (delete) 830 /* 831 * For purposes of backwards compatibility, we treat 832 * NULL_SHA1 as "don't care" here: 833 */ 834 return refs_delete_ref(get_main_ref_store(the_repository), 835 msg, refname, 836 (oldval && !is_null_oid(&oldoid)) ? &oldoid : NULL, 837 default_flags); 838 else 839 return refs_update_ref(get_main_ref_store(the_repository), 840 msg, refname, &oid, 841 oldval ? &oldoid : NULL, 842 default_flags | create_reflog_flag, 843 UPDATE_REFS_DIE_ON_ERR); 844}