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