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