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