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