builtin-receive-pack.con commit Fix export_marks() error handling. (96d69b5)
   1#include "cache.h"
   2#include "pack.h"
   3#include "refs.h"
   4#include "pkt-line.h"
   5#include "run-command.h"
   6#include "exec_cmd.h"
   7#include "commit.h"
   8#include "object.h"
   9#include "remote.h"
  10#include "transport.h"
  11
  12static const char receive_pack_usage[] = "git receive-pack <git-dir>";
  13
  14enum deny_action {
  15        DENY_UNCONFIGURED,
  16        DENY_IGNORE,
  17        DENY_WARN,
  18        DENY_REFUSE,
  19};
  20
  21static int deny_deletes;
  22static int deny_non_fast_forwards;
  23static enum deny_action deny_current_branch = DENY_UNCONFIGURED;
  24static enum deny_action deny_delete_current = DENY_UNCONFIGURED;
  25static int receive_fsck_objects;
  26static int receive_unpack_limit = -1;
  27static int transfer_unpack_limit = -1;
  28static int unpack_limit = 100;
  29static int report_status;
  30static int prefer_ofs_delta = 1;
  31static const char *head_name;
  32static char *capabilities_to_send;
  33
  34static enum deny_action parse_deny_action(const char *var, const char *value)
  35{
  36        if (value) {
  37                if (!strcasecmp(value, "ignore"))
  38                        return DENY_IGNORE;
  39                if (!strcasecmp(value, "warn"))
  40                        return DENY_WARN;
  41                if (!strcasecmp(value, "refuse"))
  42                        return DENY_REFUSE;
  43        }
  44        if (git_config_bool(var, value))
  45                return DENY_REFUSE;
  46        return DENY_IGNORE;
  47}
  48
  49static int receive_pack_config(const char *var, const char *value, void *cb)
  50{
  51        if (strcmp(var, "receive.denydeletes") == 0) {
  52                deny_deletes = git_config_bool(var, value);
  53                return 0;
  54        }
  55
  56        if (strcmp(var, "receive.denynonfastforwards") == 0) {
  57                deny_non_fast_forwards = git_config_bool(var, value);
  58                return 0;
  59        }
  60
  61        if (strcmp(var, "receive.unpacklimit") == 0) {
  62                receive_unpack_limit = git_config_int(var, value);
  63                return 0;
  64        }
  65
  66        if (strcmp(var, "transfer.unpacklimit") == 0) {
  67                transfer_unpack_limit = git_config_int(var, value);
  68                return 0;
  69        }
  70
  71        if (strcmp(var, "receive.fsckobjects") == 0) {
  72                receive_fsck_objects = git_config_bool(var, value);
  73                return 0;
  74        }
  75
  76        if (!strcmp(var, "receive.denycurrentbranch")) {
  77                deny_current_branch = parse_deny_action(var, value);
  78                return 0;
  79        }
  80
  81        if (strcmp(var, "receive.denydeletecurrent") == 0) {
  82                deny_delete_current = parse_deny_action(var, value);
  83                return 0;
  84        }
  85
  86        if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
  87                prefer_ofs_delta = git_config_bool(var, value);
  88                return 0;
  89        }
  90
  91        return git_default_config(var, value, cb);
  92}
  93
  94static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
  95{
  96        if (!capabilities_to_send)
  97                packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
  98        else
  99                packet_write(1, "%s %s%c%s\n",
 100                             sha1_to_hex(sha1), path, 0, capabilities_to_send);
 101        capabilities_to_send = NULL;
 102        return 0;
 103}
 104
 105static void write_head_info(void)
 106{
 107        for_each_ref(show_ref, NULL);
 108        if (capabilities_to_send)
 109                show_ref("capabilities^{}", null_sha1, 0, NULL);
 110
 111}
 112
 113struct command {
 114        struct command *next;
 115        const char *error_string;
 116        unsigned char old_sha1[20];
 117        unsigned char new_sha1[20];
 118        char ref_name[FLEX_ARRAY]; /* more */
 119};
 120
 121static struct command *commands;
 122
 123static const char pre_receive_hook[] = "hooks/pre-receive";
 124static const char post_receive_hook[] = "hooks/post-receive";
 125
 126static int hook_status(int code, const char *hook_name)
 127{
 128        switch (code) {
 129        case 0:
 130                return 0;
 131        case -ERR_RUN_COMMAND_FORK:
 132                return error("hook fork failed");
 133        case -ERR_RUN_COMMAND_EXEC:
 134                return error("hook execute failed");
 135        case -ERR_RUN_COMMAND_PIPE:
 136                return error("hook pipe failed");
 137        case -ERR_RUN_COMMAND_WAITPID:
 138                return error("waitpid failed");
 139        case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
 140                return error("waitpid is confused");
 141        case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
 142                return error("%s died of signal", hook_name);
 143        case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
 144                return error("%s died strangely", hook_name);
 145        default:
 146                error("%s exited with error code %d", hook_name, -code);
 147                return -code;
 148        }
 149}
 150
 151static int run_receive_hook(const char *hook_name)
 152{
 153        static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
 154        struct command *cmd;
 155        struct child_process proc;
 156        const char *argv[2];
 157        int have_input = 0, code;
 158
 159        for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
 160                if (!cmd->error_string)
 161                        have_input = 1;
 162        }
 163
 164        if (!have_input || access(hook_name, X_OK) < 0)
 165                return 0;
 166
 167        argv[0] = hook_name;
 168        argv[1] = NULL;
 169
 170        memset(&proc, 0, sizeof(proc));
 171        proc.argv = argv;
 172        proc.in = -1;
 173        proc.stdout_to_stderr = 1;
 174
 175        code = start_command(&proc);
 176        if (code)
 177                return hook_status(code, hook_name);
 178        for (cmd = commands; cmd; cmd = cmd->next) {
 179                if (!cmd->error_string) {
 180                        size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
 181                                sha1_to_hex(cmd->old_sha1),
 182                                sha1_to_hex(cmd->new_sha1),
 183                                cmd->ref_name);
 184                        if (write_in_full(proc.in, buf, n) != n)
 185                                break;
 186                }
 187        }
 188        close(proc.in);
 189        return hook_status(finish_command(&proc), hook_name);
 190}
 191
 192static int run_update_hook(struct command *cmd)
 193{
 194        static const char update_hook[] = "hooks/update";
 195        struct child_process proc;
 196        const char *argv[5];
 197
 198        if (access(update_hook, X_OK) < 0)
 199                return 0;
 200
 201        argv[0] = update_hook;
 202        argv[1] = cmd->ref_name;
 203        argv[2] = sha1_to_hex(cmd->old_sha1);
 204        argv[3] = sha1_to_hex(cmd->new_sha1);
 205        argv[4] = NULL;
 206
 207        memset(&proc, 0, sizeof(proc));
 208        proc.argv = argv;
 209        proc.no_stdin = 1;
 210        proc.stdout_to_stderr = 1;
 211
 212        return hook_status(run_command(&proc), update_hook);
 213}
 214
 215static int is_ref_checked_out(const char *ref)
 216{
 217        if (is_bare_repository())
 218                return 0;
 219
 220        if (!head_name)
 221                return 0;
 222        return !strcmp(head_name, ref);
 223}
 224
 225static char *warn_unconfigured_deny_msg[] = {
 226        "Updating the currently checked out branch may cause confusion,",
 227        "as the index and work tree do not reflect changes that are in HEAD.",
 228        "As a result, you may see the changes you just pushed into it",
 229        "reverted when you run 'git diff' over there, and you may want",
 230        "to run 'git reset --hard' before starting to work to recover.",
 231        "",
 232        "You can set 'receive.denyCurrentBranch' configuration variable to",
 233        "'refuse' in the remote repository to forbid pushing into its",
 234        "current branch."
 235        "",
 236        "To allow pushing into the current branch, you can set it to 'ignore';",
 237        "but this is not recommended unless you arranged to update its work",
 238        "tree to match what you pushed in some other way.",
 239        "",
 240        "To squelch this message, you can set it to 'warn'.",
 241        "",
 242        "Note that the default will change in a future version of git",
 243        "to refuse updating the current branch unless you have the",
 244        "configuration variable set to either 'ignore' or 'warn'."
 245};
 246
 247static void warn_unconfigured_deny(void)
 248{
 249        int i;
 250        for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++)
 251                warning("%s", warn_unconfigured_deny_msg[i]);
 252}
 253
 254static char *warn_unconfigured_deny_delete_current_msg[] = {
 255        "Deleting the current branch can cause confusion by making the next",
 256        "'git clone' not check out any file.",
 257        "",
 258        "You can set 'receive.denyDeleteCurrent' configuration variable to",
 259        "'refuse' in the remote repository to disallow deleting the current",
 260        "branch.",
 261        "",
 262        "You can set it to 'ignore' to allow such a delete without a warning.",
 263        "",
 264        "To make this warning message less loud, you can set it to 'warn'.",
 265        "",
 266        "Note that the default will change in a future version of git",
 267        "to refuse deleting the current branch unless you have the",
 268        "configuration variable set to either 'ignore' or 'warn'."
 269};
 270
 271static void warn_unconfigured_deny_delete_current(void)
 272{
 273        int i;
 274        for (i = 0;
 275             i < ARRAY_SIZE(warn_unconfigured_deny_delete_current_msg);
 276             i++)
 277                warning("%s", warn_unconfigured_deny_delete_current_msg[i]);
 278}
 279
 280static const char *update(struct command *cmd)
 281{
 282        const char *name = cmd->ref_name;
 283        unsigned char *old_sha1 = cmd->old_sha1;
 284        unsigned char *new_sha1 = cmd->new_sha1;
 285        struct ref_lock *lock;
 286
 287        /* only refs/... are allowed */
 288        if (prefixcmp(name, "refs/") || check_ref_format(name + 5)) {
 289                error("refusing to create funny ref '%s' remotely", name);
 290                return "funny refname";
 291        }
 292
 293        if (is_ref_checked_out(name)) {
 294                switch (deny_current_branch) {
 295                case DENY_IGNORE:
 296                        break;
 297                case DENY_UNCONFIGURED:
 298                case DENY_WARN:
 299                        warning("updating the current branch");
 300                        if (deny_current_branch == DENY_UNCONFIGURED)
 301                                warn_unconfigured_deny();
 302                        break;
 303                case DENY_REFUSE:
 304                        error("refusing to update checked out branch: %s", name);
 305                        return "branch is currently checked out";
 306                }
 307        }
 308
 309        if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
 310                error("unpack should have generated %s, "
 311                      "but I can't find it!", sha1_to_hex(new_sha1));
 312                return "bad pack";
 313        }
 314
 315        if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
 316                if (deny_deletes && !prefixcmp(name, "refs/heads/")) {
 317                        error("denying ref deletion for %s", name);
 318                        return "deletion prohibited";
 319                }
 320
 321                if (!strcmp(name, head_name)) {
 322                        switch (deny_delete_current) {
 323                        case DENY_IGNORE:
 324                                break;
 325                        case DENY_WARN:
 326                        case DENY_UNCONFIGURED:
 327                                if (deny_delete_current == DENY_UNCONFIGURED)
 328                                        warn_unconfigured_deny_delete_current();
 329                                warning("deleting the current branch");
 330                                break;
 331                        case DENY_REFUSE:
 332                                error("refusing to delete the current branch: %s", name);
 333                                return "deletion of the current branch prohibited";
 334                        }
 335                }
 336        }
 337
 338        if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
 339            !is_null_sha1(old_sha1) &&
 340            !prefixcmp(name, "refs/heads/")) {
 341                struct object *old_object, *new_object;
 342                struct commit *old_commit, *new_commit;
 343                struct commit_list *bases, *ent;
 344
 345                old_object = parse_object(old_sha1);
 346                new_object = parse_object(new_sha1);
 347
 348                if (!old_object || !new_object ||
 349                    old_object->type != OBJ_COMMIT ||
 350                    new_object->type != OBJ_COMMIT) {
 351                        error("bad sha1 objects for %s", name);
 352                        return "bad ref";
 353                }
 354                old_commit = (struct commit *)old_object;
 355                new_commit = (struct commit *)new_object;
 356                bases = get_merge_bases(old_commit, new_commit, 1);
 357                for (ent = bases; ent; ent = ent->next)
 358                        if (!hashcmp(old_sha1, ent->item->object.sha1))
 359                                break;
 360                free_commit_list(bases);
 361                if (!ent) {
 362                        error("denying non-fast forward %s"
 363                              " (you should pull first)", name);
 364                        return "non-fast forward";
 365                }
 366        }
 367        if (run_update_hook(cmd)) {
 368                error("hook declined to update %s", name);
 369                return "hook declined";
 370        }
 371
 372        if (is_null_sha1(new_sha1)) {
 373                if (!parse_object(old_sha1)) {
 374                        warning ("Allowing deletion of corrupt ref.");
 375                        old_sha1 = NULL;
 376                }
 377                if (delete_ref(name, old_sha1, 0)) {
 378                        error("failed to delete %s", name);
 379                        return "failed to delete";
 380                }
 381                return NULL; /* good */
 382        }
 383        else {
 384                lock = lock_any_ref_for_update(name, old_sha1, 0);
 385                if (!lock) {
 386                        error("failed to lock %s", name);
 387                        return "failed to lock";
 388                }
 389                if (write_ref_sha1(lock, new_sha1, "push")) {
 390                        return "failed to write"; /* error() already called */
 391                }
 392                return NULL; /* good */
 393        }
 394}
 395
 396static char update_post_hook[] = "hooks/post-update";
 397
 398static void run_update_post_hook(struct command *cmd)
 399{
 400        struct command *cmd_p;
 401        int argc;
 402        const char **argv;
 403
 404        for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
 405                if (cmd_p->error_string)
 406                        continue;
 407                argc++;
 408        }
 409        if (!argc || access(update_post_hook, X_OK) < 0)
 410                return;
 411        argv = xmalloc(sizeof(*argv) * (2 + argc));
 412        argv[0] = update_post_hook;
 413
 414        for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
 415                char *p;
 416                if (cmd_p->error_string)
 417                        continue;
 418                p = xmalloc(strlen(cmd_p->ref_name) + 1);
 419                strcpy(p, cmd_p->ref_name);
 420                argv[argc] = p;
 421                argc++;
 422        }
 423        argv[argc] = NULL;
 424        run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
 425                | RUN_COMMAND_STDOUT_TO_STDERR);
 426}
 427
 428static void execute_commands(const char *unpacker_error)
 429{
 430        struct command *cmd = commands;
 431        unsigned char sha1[20];
 432
 433        if (unpacker_error) {
 434                while (cmd) {
 435                        cmd->error_string = "n/a (unpacker error)";
 436                        cmd = cmd->next;
 437                }
 438                return;
 439        }
 440
 441        if (run_receive_hook(pre_receive_hook)) {
 442                while (cmd) {
 443                        cmd->error_string = "pre-receive hook declined";
 444                        cmd = cmd->next;
 445                }
 446                return;
 447        }
 448
 449        head_name = resolve_ref("HEAD", sha1, 0, NULL);
 450
 451        while (cmd) {
 452                cmd->error_string = update(cmd);
 453                cmd = cmd->next;
 454        }
 455}
 456
 457static void read_head_info(void)
 458{
 459        struct command **p = &commands;
 460        for (;;) {
 461                static char line[1000];
 462                unsigned char old_sha1[20], new_sha1[20];
 463                struct command *cmd;
 464                char *refname;
 465                int len, reflen;
 466
 467                len = packet_read_line(0, line, sizeof(line));
 468                if (!len)
 469                        break;
 470                if (line[len-1] == '\n')
 471                        line[--len] = 0;
 472                if (len < 83 ||
 473                    line[40] != ' ' ||
 474                    line[81] != ' ' ||
 475                    get_sha1_hex(line, old_sha1) ||
 476                    get_sha1_hex(line + 41, new_sha1))
 477                        die("protocol error: expected old/new/ref, got '%s'",
 478                            line);
 479
 480                refname = line + 82;
 481                reflen = strlen(refname);
 482                if (reflen + 82 < len) {
 483                        if (strstr(refname + reflen + 1, "report-status"))
 484                                report_status = 1;
 485                }
 486                cmd = xmalloc(sizeof(struct command) + len - 80);
 487                hashcpy(cmd->old_sha1, old_sha1);
 488                hashcpy(cmd->new_sha1, new_sha1);
 489                memcpy(cmd->ref_name, line + 82, len - 81);
 490                cmd->error_string = NULL;
 491                cmd->next = NULL;
 492                *p = cmd;
 493                p = &cmd->next;
 494        }
 495}
 496
 497static const char *parse_pack_header(struct pack_header *hdr)
 498{
 499        switch (read_pack_header(0, hdr)) {
 500        case PH_ERROR_EOF:
 501                return "eof before pack header was fully read";
 502
 503        case PH_ERROR_PACK_SIGNATURE:
 504                return "protocol error (pack signature mismatch detected)";
 505
 506        case PH_ERROR_PROTOCOL:
 507                return "protocol error (pack version unsupported)";
 508
 509        default:
 510                return "unknown error in parse_pack_header";
 511
 512        case 0:
 513                return NULL;
 514        }
 515}
 516
 517static const char *pack_lockfile;
 518
 519static const char *unpack(void)
 520{
 521        struct pack_header hdr;
 522        const char *hdr_err;
 523        char hdr_arg[38];
 524
 525        hdr_err = parse_pack_header(&hdr);
 526        if (hdr_err)
 527                return hdr_err;
 528        snprintf(hdr_arg, sizeof(hdr_arg),
 529                        "--pack_header=%"PRIu32",%"PRIu32,
 530                        ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
 531
 532        if (ntohl(hdr.hdr_entries) < unpack_limit) {
 533                int code, i = 0;
 534                const char *unpacker[4];
 535                unpacker[i++] = "unpack-objects";
 536                if (receive_fsck_objects)
 537                        unpacker[i++] = "--strict";
 538                unpacker[i++] = hdr_arg;
 539                unpacker[i++] = NULL;
 540                code = run_command_v_opt(unpacker, RUN_GIT_CMD);
 541                switch (code) {
 542                case 0:
 543                        return NULL;
 544                case -ERR_RUN_COMMAND_FORK:
 545                        return "unpack fork failed";
 546                case -ERR_RUN_COMMAND_EXEC:
 547                        return "unpack execute failed";
 548                case -ERR_RUN_COMMAND_WAITPID:
 549                        return "waitpid failed";
 550                case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
 551                        return "waitpid is confused";
 552                case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
 553                        return "unpacker died of signal";
 554                case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
 555                        return "unpacker died strangely";
 556                default:
 557                        return "unpacker exited with error code";
 558                }
 559        } else {
 560                const char *keeper[7];
 561                int s, status, i = 0;
 562                char keep_arg[256];
 563                struct child_process ip;
 564
 565                s = sprintf(keep_arg, "--keep=receive-pack %"PRIuMAX" on ", (uintmax_t) getpid());
 566                if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
 567                        strcpy(keep_arg + s, "localhost");
 568
 569                keeper[i++] = "index-pack";
 570                keeper[i++] = "--stdin";
 571                if (receive_fsck_objects)
 572                        keeper[i++] = "--strict";
 573                keeper[i++] = "--fix-thin";
 574                keeper[i++] = hdr_arg;
 575                keeper[i++] = keep_arg;
 576                keeper[i++] = NULL;
 577                memset(&ip, 0, sizeof(ip));
 578                ip.argv = keeper;
 579                ip.out = -1;
 580                ip.git_cmd = 1;
 581                if (start_command(&ip))
 582                        return "index-pack fork failed";
 583                pack_lockfile = index_pack_lockfile(ip.out);
 584                close(ip.out);
 585                status = finish_command(&ip);
 586                if (!status) {
 587                        reprepare_packed_git();
 588                        return NULL;
 589                }
 590                return "index-pack abnormal exit";
 591        }
 592}
 593
 594static void report(const char *unpack_status)
 595{
 596        struct command *cmd;
 597        packet_write(1, "unpack %s\n",
 598                     unpack_status ? unpack_status : "ok");
 599        for (cmd = commands; cmd; cmd = cmd->next) {
 600                if (!cmd->error_string)
 601                        packet_write(1, "ok %s\n",
 602                                     cmd->ref_name);
 603                else
 604                        packet_write(1, "ng %s %s\n",
 605                                     cmd->ref_name, cmd->error_string);
 606        }
 607        packet_flush(1);
 608}
 609
 610static int delete_only(struct command *cmd)
 611{
 612        while (cmd) {
 613                if (!is_null_sha1(cmd->new_sha1))
 614                        return 0;
 615                cmd = cmd->next;
 616        }
 617        return 1;
 618}
 619
 620static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
 621{
 622        char *other;
 623        size_t len;
 624        struct remote *remote;
 625        struct transport *transport;
 626        const struct ref *extra;
 627
 628        e->name[-1] = '\0';
 629        other = xstrdup(make_absolute_path(e->base));
 630        e->name[-1] = '/';
 631        len = strlen(other);
 632
 633        while (other[len-1] == '/')
 634                other[--len] = '\0';
 635        if (len < 8 || memcmp(other + len - 8, "/objects", 8))
 636                return 0;
 637        /* Is this a git repository with refs? */
 638        memcpy(other + len - 8, "/refs", 6);
 639        if (!is_directory(other))
 640                return 0;
 641        other[len - 8] = '\0';
 642        remote = remote_get(other);
 643        transport = transport_get(remote, other);
 644        for (extra = transport_get_remote_refs(transport);
 645             extra;
 646             extra = extra->next) {
 647                add_extra_ref(".have", extra->old_sha1, 0);
 648        }
 649        transport_disconnect(transport);
 650        free(other);
 651        return 0;
 652}
 653
 654static void add_alternate_refs(void)
 655{
 656        foreach_alt_odb(add_refs_from_alternate, NULL);
 657}
 658
 659int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 660{
 661        int i;
 662        char *dir = NULL;
 663
 664        argv++;
 665        for (i = 1; i < argc; i++) {
 666                const char *arg = *argv++;
 667
 668                if (*arg == '-') {
 669                        /* Do flag handling here */
 670                        usage(receive_pack_usage);
 671                }
 672                if (dir)
 673                        usage(receive_pack_usage);
 674                dir = xstrdup(arg);
 675        }
 676        if (!dir)
 677                usage(receive_pack_usage);
 678
 679        setup_path();
 680
 681        if (!enter_repo(dir, 0))
 682                die("'%s' does not appear to be a git repository", dir);
 683
 684        if (is_repository_shallow())
 685                die("attempt to push into a shallow repository");
 686
 687        git_config(receive_pack_config, NULL);
 688
 689        if (0 <= transfer_unpack_limit)
 690                unpack_limit = transfer_unpack_limit;
 691        else if (0 <= receive_unpack_limit)
 692                unpack_limit = receive_unpack_limit;
 693
 694        capabilities_to_send = (prefer_ofs_delta) ?
 695                " report-status delete-refs ofs-delta " :
 696                " report-status delete-refs ";
 697
 698        add_alternate_refs();
 699        write_head_info();
 700        clear_extra_refs();
 701
 702        /* EOF */
 703        packet_flush(1);
 704
 705        read_head_info();
 706        if (commands) {
 707                const char *unpack_status = NULL;
 708
 709                if (!delete_only(commands))
 710                        unpack_status = unpack();
 711                execute_commands(unpack_status);
 712                if (pack_lockfile)
 713                        unlink_or_warn(pack_lockfile);
 714                if (report_status)
 715                        report(unpack_status);
 716                run_receive_hook(post_receive_hook);
 717                run_update_post_hook(commands);
 718        }
 719        return 0;
 720}