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