builtin-receive-pack.con commit t3600: Use test prerequisite tags (56e78bf)
   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 const char *head_name;
  31
  32static char capabilities[] = " report-status delete-refs ";
  33static int capabilities_sent;
  34
  35static enum deny_action parse_deny_action(const char *var, const char *value)
  36{
  37        if (value) {
  38                if (!strcasecmp(value, "ignore"))
  39                        return DENY_IGNORE;
  40                if (!strcasecmp(value, "warn"))
  41                        return DENY_WARN;
  42                if (!strcasecmp(value, "refuse"))
  43                        return DENY_REFUSE;
  44        }
  45        if (git_config_bool(var, value))
  46                return DENY_REFUSE;
  47        return DENY_IGNORE;
  48}
  49
  50static int receive_pack_config(const char *var, const char *value, void *cb)
  51{
  52        if (strcmp(var, "receive.denydeletes") == 0) {
  53                deny_deletes = git_config_bool(var, value);
  54                return 0;
  55        }
  56
  57        if (strcmp(var, "receive.denynonfastforwards") == 0) {
  58                deny_non_fast_forwards = git_config_bool(var, value);
  59                return 0;
  60        }
  61
  62        if (strcmp(var, "receive.unpacklimit") == 0) {
  63                receive_unpack_limit = git_config_int(var, value);
  64                return 0;
  65        }
  66
  67        if (strcmp(var, "transfer.unpacklimit") == 0) {
  68                transfer_unpack_limit = git_config_int(var, value);
  69                return 0;
  70        }
  71
  72        if (strcmp(var, "receive.fsckobjects") == 0) {
  73                receive_fsck_objects = git_config_bool(var, value);
  74                return 0;
  75        }
  76
  77        if (!strcmp(var, "receive.denycurrentbranch")) {
  78                deny_current_branch = parse_deny_action(var, value);
  79                return 0;
  80        }
  81
  82        if (strcmp(var, "receive.denydeletecurrent") == 0) {
  83                deny_delete_current = parse_deny_action(var, value);
  84                return 0;
  85        }
  86
  87        return git_default_config(var, value, cb);
  88}
  89
  90static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
  91{
  92        if (capabilities_sent)
  93                packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
  94        else
  95                packet_write(1, "%s %s%c%s\n",
  96                             sha1_to_hex(sha1), path, 0, capabilities);
  97        capabilities_sent = 1;
  98        return 0;
  99}
 100
 101static void write_head_info(void)
 102{
 103        for_each_ref(show_ref, NULL);
 104        if (!capabilities_sent)
 105                show_ref("capabilities^{}", null_sha1, 0, NULL);
 106
 107}
 108
 109struct command {
 110        struct command *next;
 111        const char *error_string;
 112        unsigned char old_sha1[20];
 113        unsigned char new_sha1[20];
 114        char ref_name[FLEX_ARRAY]; /* more */
 115};
 116
 117static struct command *commands;
 118
 119static const char pre_receive_hook[] = "hooks/pre-receive";
 120static const char post_receive_hook[] = "hooks/post-receive";
 121
 122static int hook_status(int code, const char *hook_name)
 123{
 124        switch (code) {
 125        case 0:
 126                return 0;
 127        case -ERR_RUN_COMMAND_FORK:
 128                return error("hook fork failed");
 129        case -ERR_RUN_COMMAND_EXEC:
 130                return error("hook execute failed");
 131        case -ERR_RUN_COMMAND_PIPE:
 132                return error("hook pipe failed");
 133        case -ERR_RUN_COMMAND_WAITPID:
 134                return error("waitpid failed");
 135        case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
 136                return error("waitpid is confused");
 137        case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
 138                return error("%s died of signal", hook_name);
 139        case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
 140                return error("%s died strangely", hook_name);
 141        default:
 142                error("%s exited with error code %d", hook_name, -code);
 143                return -code;
 144        }
 145}
 146
 147static int run_receive_hook(const char *hook_name)
 148{
 149        static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
 150        struct command *cmd;
 151        struct child_process proc;
 152        const char *argv[2];
 153        int have_input = 0, code;
 154
 155        for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
 156                if (!cmd->error_string)
 157                        have_input = 1;
 158        }
 159
 160        if (!have_input || access(hook_name, X_OK) < 0)
 161                return 0;
 162
 163        argv[0] = hook_name;
 164        argv[1] = NULL;
 165
 166        memset(&proc, 0, sizeof(proc));
 167        proc.argv = argv;
 168        proc.in = -1;
 169        proc.stdout_to_stderr = 1;
 170
 171        code = start_command(&proc);
 172        if (code)
 173                return hook_status(code, hook_name);
 174        for (cmd = commands; cmd; cmd = cmd->next) {
 175                if (!cmd->error_string) {
 176                        size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
 177                                sha1_to_hex(cmd->old_sha1),
 178                                sha1_to_hex(cmd->new_sha1),
 179                                cmd->ref_name);
 180                        if (write_in_full(proc.in, buf, n) != n)
 181                                break;
 182                }
 183        }
 184        close(proc.in);
 185        return hook_status(finish_command(&proc), hook_name);
 186}
 187
 188static int run_update_hook(struct command *cmd)
 189{
 190        static const char update_hook[] = "hooks/update";
 191        struct child_process proc;
 192        const char *argv[5];
 193
 194        if (access(update_hook, X_OK) < 0)
 195                return 0;
 196
 197        argv[0] = update_hook;
 198        argv[1] = cmd->ref_name;
 199        argv[2] = sha1_to_hex(cmd->old_sha1);
 200        argv[3] = sha1_to_hex(cmd->new_sha1);
 201        argv[4] = NULL;
 202
 203        memset(&proc, 0, sizeof(proc));
 204        proc.argv = argv;
 205        proc.no_stdin = 1;
 206        proc.stdout_to_stderr = 1;
 207
 208        return hook_status(run_command(&proc), 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;
 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        run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
 421                | RUN_COMMAND_STDOUT_TO_STDERR);
 422}
 423
 424static void execute_commands(const char *unpacker_error)
 425{
 426        struct command *cmd = commands;
 427        unsigned char sha1[20];
 428
 429        if (unpacker_error) {
 430                while (cmd) {
 431                        cmd->error_string = "n/a (unpacker error)";
 432                        cmd = cmd->next;
 433                }
 434                return;
 435        }
 436
 437        if (run_receive_hook(pre_receive_hook)) {
 438                while (cmd) {
 439                        cmd->error_string = "pre-receive hook declined";
 440                        cmd = cmd->next;
 441                }
 442                return;
 443        }
 444
 445        head_name = resolve_ref("HEAD", sha1, 0, NULL);
 446
 447        while (cmd) {
 448                cmd->error_string = update(cmd);
 449                cmd = cmd->next;
 450        }
 451}
 452
 453static void read_head_info(void)
 454{
 455        struct command **p = &commands;
 456        for (;;) {
 457                static char line[1000];
 458                unsigned char old_sha1[20], new_sha1[20];
 459                struct command *cmd;
 460                char *refname;
 461                int len, reflen;
 462
 463                len = packet_read_line(0, line, sizeof(line));
 464                if (!len)
 465                        break;
 466                if (line[len-1] == '\n')
 467                        line[--len] = 0;
 468                if (len < 83 ||
 469                    line[40] != ' ' ||
 470                    line[81] != ' ' ||
 471                    get_sha1_hex(line, old_sha1) ||
 472                    get_sha1_hex(line + 41, new_sha1))
 473                        die("protocol error: expected old/new/ref, got '%s'",
 474                            line);
 475
 476                refname = line + 82;
 477                reflen = strlen(refname);
 478                if (reflen + 82 < len) {
 479                        if (strstr(refname + reflen + 1, "report-status"))
 480                                report_status = 1;
 481                }
 482                cmd = xmalloc(sizeof(struct command) + len - 80);
 483                hashcpy(cmd->old_sha1, old_sha1);
 484                hashcpy(cmd->new_sha1, new_sha1);
 485                memcpy(cmd->ref_name, line + 82, len - 81);
 486                cmd->error_string = NULL;
 487                cmd->next = NULL;
 488                *p = cmd;
 489                p = &cmd->next;
 490        }
 491}
 492
 493static const char *parse_pack_header(struct pack_header *hdr)
 494{
 495        switch (read_pack_header(0, hdr)) {
 496        case PH_ERROR_EOF:
 497                return "eof before pack header was fully read";
 498
 499        case PH_ERROR_PACK_SIGNATURE:
 500                return "protocol error (pack signature mismatch detected)";
 501
 502        case PH_ERROR_PROTOCOL:
 503                return "protocol error (pack version unsupported)";
 504
 505        default:
 506                return "unknown error in parse_pack_header";
 507
 508        case 0:
 509                return NULL;
 510        }
 511}
 512
 513static const char *pack_lockfile;
 514
 515static const char *unpack(void)
 516{
 517        struct pack_header hdr;
 518        const char *hdr_err;
 519        char hdr_arg[38];
 520
 521        hdr_err = parse_pack_header(&hdr);
 522        if (hdr_err)
 523                return hdr_err;
 524        snprintf(hdr_arg, sizeof(hdr_arg),
 525                        "--pack_header=%"PRIu32",%"PRIu32,
 526                        ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
 527
 528        if (ntohl(hdr.hdr_entries) < unpack_limit) {
 529                int code, i = 0;
 530                const char *unpacker[4];
 531                unpacker[i++] = "unpack-objects";
 532                if (receive_fsck_objects)
 533                        unpacker[i++] = "--strict";
 534                unpacker[i++] = hdr_arg;
 535                unpacker[i++] = NULL;
 536                code = run_command_v_opt(unpacker, RUN_GIT_CMD);
 537                switch (code) {
 538                case 0:
 539                        return NULL;
 540                case -ERR_RUN_COMMAND_FORK:
 541                        return "unpack fork failed";
 542                case -ERR_RUN_COMMAND_EXEC:
 543                        return "unpack execute failed";
 544                case -ERR_RUN_COMMAND_WAITPID:
 545                        return "waitpid failed";
 546                case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
 547                        return "waitpid is confused";
 548                case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
 549                        return "unpacker died of signal";
 550                case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
 551                        return "unpacker died strangely";
 552                default:
 553                        return "unpacker exited with error code";
 554                }
 555        } else {
 556                const char *keeper[7];
 557                int s, status, i = 0;
 558                char keep_arg[256];
 559                struct child_process ip;
 560
 561                s = sprintf(keep_arg, "--keep=receive-pack %"PRIuMAX" on ", (uintmax_t) getpid());
 562                if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
 563                        strcpy(keep_arg + s, "localhost");
 564
 565                keeper[i++] = "index-pack";
 566                keeper[i++] = "--stdin";
 567                if (receive_fsck_objects)
 568                        keeper[i++] = "--strict";
 569                keeper[i++] = "--fix-thin";
 570                keeper[i++] = hdr_arg;
 571                keeper[i++] = keep_arg;
 572                keeper[i++] = NULL;
 573                memset(&ip, 0, sizeof(ip));
 574                ip.argv = keeper;
 575                ip.out = -1;
 576                ip.git_cmd = 1;
 577                if (start_command(&ip))
 578                        return "index-pack fork failed";
 579                pack_lockfile = index_pack_lockfile(ip.out);
 580                close(ip.out);
 581                status = finish_command(&ip);
 582                if (!status) {
 583                        reprepare_packed_git();
 584                        return NULL;
 585                }
 586                return "index-pack abnormal exit";
 587        }
 588}
 589
 590static void report(const char *unpack_status)
 591{
 592        struct command *cmd;
 593        packet_write(1, "unpack %s\n",
 594                     unpack_status ? unpack_status : "ok");
 595        for (cmd = commands; cmd; cmd = cmd->next) {
 596                if (!cmd->error_string)
 597                        packet_write(1, "ok %s\n",
 598                                     cmd->ref_name);
 599                else
 600                        packet_write(1, "ng %s %s\n",
 601                                     cmd->ref_name, cmd->error_string);
 602        }
 603        packet_flush(1);
 604}
 605
 606static int delete_only(struct command *cmd)
 607{
 608        while (cmd) {
 609                if (!is_null_sha1(cmd->new_sha1))
 610                        return 0;
 611                cmd = cmd->next;
 612        }
 613        return 1;
 614}
 615
 616static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
 617{
 618        char *other;
 619        size_t len;
 620        struct remote *remote;
 621        struct transport *transport;
 622        const struct ref *extra;
 623
 624        e->name[-1] = '\0';
 625        other = xstrdup(make_absolute_path(e->base));
 626        e->name[-1] = '/';
 627        len = strlen(other);
 628
 629        while (other[len-1] == '/')
 630                other[--len] = '\0';
 631        if (len < 8 || memcmp(other + len - 8, "/objects", 8))
 632                return 0;
 633        /* Is this a git repository with refs? */
 634        memcpy(other + len - 8, "/refs", 6);
 635        if (!is_directory(other))
 636                return 0;
 637        other[len - 8] = '\0';
 638        remote = remote_get(other);
 639        transport = transport_get(remote, other);
 640        for (extra = transport_get_remote_refs(transport);
 641             extra;
 642             extra = extra->next) {
 643                add_extra_ref(".have", extra->old_sha1, 0);
 644        }
 645        transport_disconnect(transport);
 646        free(other);
 647        return 0;
 648}
 649
 650static void add_alternate_refs(void)
 651{
 652        foreach_alt_odb(add_refs_from_alternate, NULL);
 653}
 654
 655int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 656{
 657        int i;
 658        char *dir = NULL;
 659
 660        argv++;
 661        for (i = 1; i < argc; i++) {
 662                const char *arg = *argv++;
 663
 664                if (*arg == '-') {
 665                        /* Do flag handling here */
 666                        usage(receive_pack_usage);
 667                }
 668                if (dir)
 669                        usage(receive_pack_usage);
 670                dir = xstrdup(arg);
 671        }
 672        if (!dir)
 673                usage(receive_pack_usage);
 674
 675        setup_path();
 676
 677        if (!enter_repo(dir, 0))
 678                die("'%s' does not appear to be a git repository", dir);
 679
 680        if (is_repository_shallow())
 681                die("attempt to push into a shallow repository");
 682
 683        git_config(receive_pack_config, NULL);
 684
 685        if (0 <= transfer_unpack_limit)
 686                unpack_limit = transfer_unpack_limit;
 687        else if (0 <= receive_unpack_limit)
 688                unpack_limit = receive_unpack_limit;
 689
 690        add_alternate_refs();
 691        write_head_info();
 692        clear_extra_refs();
 693
 694        /* EOF */
 695        packet_flush(1);
 696
 697        read_head_info();
 698        if (commands) {
 699                const char *unpack_status = NULL;
 700
 701                if (!delete_only(commands))
 702                        unpack_status = unpack();
 703                execute_commands(unpack_status);
 704                if (pack_lockfile)
 705                        unlink(pack_lockfile);
 706                if (report_status)
 707                        report(unpack_status);
 708                run_receive_hook(post_receive_hook);
 709                run_update_post_hook(commands);
 710        }
 711        return 0;
 712}