builtin-receive-pack.con commit Add support for "import" helper command (e65e91e)
   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 int auto_update_server_info;
  32static int auto_gc = 1;
  33static const char *head_name;
  34static char *capabilities_to_send;
  35
  36static enum deny_action parse_deny_action(const char *var, const char *value)
  37{
  38        if (value) {
  39                if (!strcasecmp(value, "ignore"))
  40                        return DENY_IGNORE;
  41                if (!strcasecmp(value, "warn"))
  42                        return DENY_WARN;
  43                if (!strcasecmp(value, "refuse"))
  44                        return DENY_REFUSE;
  45        }
  46        if (git_config_bool(var, value))
  47                return DENY_REFUSE;
  48        return DENY_IGNORE;
  49}
  50
  51static int receive_pack_config(const char *var, const char *value, void *cb)
  52{
  53        if (strcmp(var, "receive.denydeletes") == 0) {
  54                deny_deletes = git_config_bool(var, value);
  55                return 0;
  56        }
  57
  58        if (strcmp(var, "receive.denynonfastforwards") == 0) {
  59                deny_non_fast_forwards = git_config_bool(var, value);
  60                return 0;
  61        }
  62
  63        if (strcmp(var, "receive.unpacklimit") == 0) {
  64                receive_unpack_limit = git_config_int(var, value);
  65                return 0;
  66        }
  67
  68        if (strcmp(var, "transfer.unpacklimit") == 0) {
  69                transfer_unpack_limit = git_config_int(var, value);
  70                return 0;
  71        }
  72
  73        if (strcmp(var, "receive.fsckobjects") == 0) {
  74                receive_fsck_objects = git_config_bool(var, value);
  75                return 0;
  76        }
  77
  78        if (!strcmp(var, "receive.denycurrentbranch")) {
  79                deny_current_branch = parse_deny_action(var, value);
  80                return 0;
  81        }
  82
  83        if (strcmp(var, "receive.denydeletecurrent") == 0) {
  84                deny_delete_current = parse_deny_action(var, value);
  85                return 0;
  86        }
  87
  88        if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
  89                prefer_ofs_delta = git_config_bool(var, value);
  90                return 0;
  91        }
  92
  93        if (strcmp(var, "receive.updateserverinfo") == 0) {
  94                auto_update_server_info = git_config_bool(var, value);
  95                return 0;
  96        }
  97
  98        if (strcmp(var, "receive.autogc") == 0) {
  99                auto_gc = git_config_bool(var, value);
 100                return 0;
 101        }
 102
 103        return git_default_config(var, value, cb);
 104}
 105
 106static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 107{
 108        if (!capabilities_to_send)
 109                packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
 110        else
 111                packet_write(1, "%s %s%c%s\n",
 112                             sha1_to_hex(sha1), path, 0, capabilities_to_send);
 113        capabilities_to_send = NULL;
 114        return 0;
 115}
 116
 117static void write_head_info(void)
 118{
 119        for_each_ref(show_ref, NULL);
 120        if (capabilities_to_send)
 121                show_ref("capabilities^{}", null_sha1, 0, NULL);
 122
 123}
 124
 125struct command {
 126        struct command *next;
 127        const char *error_string;
 128        unsigned char old_sha1[20];
 129        unsigned char new_sha1[20];
 130        char ref_name[FLEX_ARRAY]; /* more */
 131};
 132
 133static struct command *commands;
 134
 135static const char pre_receive_hook[] = "hooks/pre-receive";
 136static const char post_receive_hook[] = "hooks/post-receive";
 137
 138static int run_receive_hook(const char *hook_name)
 139{
 140        static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
 141        struct command *cmd;
 142        struct child_process proc;
 143        const char *argv[2];
 144        int have_input = 0, code;
 145
 146        for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
 147                if (!cmd->error_string)
 148                        have_input = 1;
 149        }
 150
 151        if (!have_input || access(hook_name, X_OK) < 0)
 152                return 0;
 153
 154        argv[0] = hook_name;
 155        argv[1] = NULL;
 156
 157        memset(&proc, 0, sizeof(proc));
 158        proc.argv = argv;
 159        proc.in = -1;
 160        proc.stdout_to_stderr = 1;
 161
 162        code = start_command(&proc);
 163        if (code)
 164                return code;
 165        for (cmd = commands; cmd; cmd = cmd->next) {
 166                if (!cmd->error_string) {
 167                        size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
 168                                sha1_to_hex(cmd->old_sha1),
 169                                sha1_to_hex(cmd->new_sha1),
 170                                cmd->ref_name);
 171                        if (write_in_full(proc.in, buf, n) != n)
 172                                break;
 173                }
 174        }
 175        close(proc.in);
 176        return finish_command(&proc);
 177}
 178
 179static int run_update_hook(struct command *cmd)
 180{
 181        static const char update_hook[] = "hooks/update";
 182        const char *argv[5];
 183
 184        if (access(update_hook, X_OK) < 0)
 185                return 0;
 186
 187        argv[0] = update_hook;
 188        argv[1] = cmd->ref_name;
 189        argv[2] = sha1_to_hex(cmd->old_sha1);
 190        argv[3] = sha1_to_hex(cmd->new_sha1);
 191        argv[4] = NULL;
 192
 193        return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
 194                                        RUN_COMMAND_STDOUT_TO_STDERR);
 195}
 196
 197static int is_ref_checked_out(const char *ref)
 198{
 199        if (is_bare_repository())
 200                return 0;
 201
 202        if (!head_name)
 203                return 0;
 204        return !strcmp(head_name, ref);
 205}
 206
 207static char *warn_unconfigured_deny_msg[] = {
 208        "Updating the currently checked out branch may cause confusion,",
 209        "as the index and work tree do not reflect changes that are in HEAD.",
 210        "As a result, you may see the changes you just pushed into it",
 211        "reverted when you run 'git diff' over there, and you may want",
 212        "to run 'git reset --hard' before starting to work to recover.",
 213        "",
 214        "You can set 'receive.denyCurrentBranch' configuration variable to",
 215        "'refuse' in the remote repository to forbid pushing into its",
 216        "current branch."
 217        "",
 218        "To allow pushing into the current branch, you can set it to 'ignore';",
 219        "but this is not recommended unless you arranged to update its work",
 220        "tree to match what you pushed in some other way.",
 221        "",
 222        "To squelch this message, you can set it to 'warn'.",
 223        "",
 224        "Note that the default will change in a future version of git",
 225        "to refuse updating the current branch unless you have the",
 226        "configuration variable set to either 'ignore' or 'warn'."
 227};
 228
 229static void warn_unconfigured_deny(void)
 230{
 231        int i;
 232        for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++)
 233                warning("%s", warn_unconfigured_deny_msg[i]);
 234}
 235
 236static char *warn_unconfigured_deny_delete_current_msg[] = {
 237        "Deleting the current branch can cause confusion by making the next",
 238        "'git clone' not check out any file.",
 239        "",
 240        "You can set 'receive.denyDeleteCurrent' configuration variable to",
 241        "'refuse' in the remote repository to disallow deleting the current",
 242        "branch.",
 243        "",
 244        "You can set it to 'ignore' to allow such a delete without a warning.",
 245        "",
 246        "To make this warning message less loud, you can set it to 'warn'.",
 247        "",
 248        "Note that the default will change in a future version of git",
 249        "to refuse deleting the current branch unless you have the",
 250        "configuration variable set to either 'ignore' or 'warn'."
 251};
 252
 253static void warn_unconfigured_deny_delete_current(void)
 254{
 255        int i;
 256        for (i = 0;
 257             i < ARRAY_SIZE(warn_unconfigured_deny_delete_current_msg);
 258             i++)
 259                warning("%s", warn_unconfigured_deny_delete_current_msg[i]);
 260}
 261
 262static const char *update(struct command *cmd)
 263{
 264        const char *name = cmd->ref_name;
 265        unsigned char *old_sha1 = cmd->old_sha1;
 266        unsigned char *new_sha1 = cmd->new_sha1;
 267        struct ref_lock *lock;
 268
 269        /* only refs/... are allowed */
 270        if (prefixcmp(name, "refs/") || check_ref_format(name + 5)) {
 271                error("refusing to create funny ref '%s' remotely", name);
 272                return "funny refname";
 273        }
 274
 275        if (is_ref_checked_out(name)) {
 276                switch (deny_current_branch) {
 277                case DENY_IGNORE:
 278                        break;
 279                case DENY_UNCONFIGURED:
 280                case DENY_WARN:
 281                        warning("updating the current branch");
 282                        if (deny_current_branch == DENY_UNCONFIGURED)
 283                                warn_unconfigured_deny();
 284                        break;
 285                case DENY_REFUSE:
 286                        error("refusing to update checked out branch: %s", name);
 287                        return "branch is currently checked out";
 288                }
 289        }
 290
 291        if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
 292                error("unpack should have generated %s, "
 293                      "but I can't find it!", sha1_to_hex(new_sha1));
 294                return "bad pack";
 295        }
 296
 297        if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
 298                if (deny_deletes && !prefixcmp(name, "refs/heads/")) {
 299                        error("denying ref deletion for %s", name);
 300                        return "deletion prohibited";
 301                }
 302
 303                if (!strcmp(name, head_name)) {
 304                        switch (deny_delete_current) {
 305                        case DENY_IGNORE:
 306                                break;
 307                        case DENY_WARN:
 308                        case DENY_UNCONFIGURED:
 309                                if (deny_delete_current == DENY_UNCONFIGURED)
 310                                        warn_unconfigured_deny_delete_current();
 311                                warning("deleting the current branch");
 312                                break;
 313                        case DENY_REFUSE:
 314                                error("refusing to delete the current branch: %s", name);
 315                                return "deletion of the current branch prohibited";
 316                        }
 317                }
 318        }
 319
 320        if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
 321            !is_null_sha1(old_sha1) &&
 322            !prefixcmp(name, "refs/heads/")) {
 323                struct object *old_object, *new_object;
 324                struct commit *old_commit, *new_commit;
 325                struct commit_list *bases, *ent;
 326
 327                old_object = parse_object(old_sha1);
 328                new_object = parse_object(new_sha1);
 329
 330                if (!old_object || !new_object ||
 331                    old_object->type != OBJ_COMMIT ||
 332                    new_object->type != OBJ_COMMIT) {
 333                        error("bad sha1 objects for %s", name);
 334                        return "bad ref";
 335                }
 336                old_commit = (struct commit *)old_object;
 337                new_commit = (struct commit *)new_object;
 338                bases = get_merge_bases(old_commit, new_commit, 1);
 339                for (ent = bases; ent; ent = ent->next)
 340                        if (!hashcmp(old_sha1, ent->item->object.sha1))
 341                                break;
 342                free_commit_list(bases);
 343                if (!ent) {
 344                        error("denying non-fast forward %s"
 345                              " (you should pull first)", name);
 346                        return "non-fast forward";
 347                }
 348        }
 349        if (run_update_hook(cmd)) {
 350                error("hook declined to update %s", name);
 351                return "hook declined";
 352        }
 353
 354        if (is_null_sha1(new_sha1)) {
 355                if (!parse_object(old_sha1)) {
 356                        warning ("Allowing deletion of corrupt ref.");
 357                        old_sha1 = NULL;
 358                }
 359                if (delete_ref(name, old_sha1, 0)) {
 360                        error("failed to delete %s", name);
 361                        return "failed to delete";
 362                }
 363                return NULL; /* good */
 364        }
 365        else {
 366                lock = lock_any_ref_for_update(name, old_sha1, 0);
 367                if (!lock) {
 368                        error("failed to lock %s", name);
 369                        return "failed to lock";
 370                }
 371                if (write_ref_sha1(lock, new_sha1, "push")) {
 372                        return "failed to write"; /* error() already called */
 373                }
 374                return NULL; /* good */
 375        }
 376}
 377
 378static char update_post_hook[] = "hooks/post-update";
 379
 380static void run_update_post_hook(struct command *cmd)
 381{
 382        struct command *cmd_p;
 383        int argc, status;
 384        const char **argv;
 385
 386        for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
 387                if (cmd_p->error_string)
 388                        continue;
 389                argc++;
 390        }
 391        if (!argc || access(update_post_hook, X_OK) < 0)
 392                return;
 393        argv = xmalloc(sizeof(*argv) * (2 + argc));
 394        argv[0] = update_post_hook;
 395
 396        for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
 397                char *p;
 398                if (cmd_p->error_string)
 399                        continue;
 400                p = xmalloc(strlen(cmd_p->ref_name) + 1);
 401                strcpy(p, cmd_p->ref_name);
 402                argv[argc] = p;
 403                argc++;
 404        }
 405        argv[argc] = NULL;
 406        status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
 407                        | RUN_COMMAND_STDOUT_TO_STDERR);
 408}
 409
 410static void execute_commands(const char *unpacker_error)
 411{
 412        struct command *cmd = commands;
 413        unsigned char sha1[20];
 414
 415        if (unpacker_error) {
 416                while (cmd) {
 417                        cmd->error_string = "n/a (unpacker error)";
 418                        cmd = cmd->next;
 419                }
 420                return;
 421        }
 422
 423        if (run_receive_hook(pre_receive_hook)) {
 424                while (cmd) {
 425                        cmd->error_string = "pre-receive hook declined";
 426                        cmd = cmd->next;
 427                }
 428                return;
 429        }
 430
 431        head_name = resolve_ref("HEAD", sha1, 0, NULL);
 432
 433        while (cmd) {
 434                cmd->error_string = update(cmd);
 435                cmd = cmd->next;
 436        }
 437}
 438
 439static void read_head_info(void)
 440{
 441        struct command **p = &commands;
 442        for (;;) {
 443                static char line[1000];
 444                unsigned char old_sha1[20], new_sha1[20];
 445                struct command *cmd;
 446                char *refname;
 447                int len, reflen;
 448
 449                len = packet_read_line(0, line, sizeof(line));
 450                if (!len)
 451                        break;
 452                if (line[len-1] == '\n')
 453                        line[--len] = 0;
 454                if (len < 83 ||
 455                    line[40] != ' ' ||
 456                    line[81] != ' ' ||
 457                    get_sha1_hex(line, old_sha1) ||
 458                    get_sha1_hex(line + 41, new_sha1))
 459                        die("protocol error: expected old/new/ref, got '%s'",
 460                            line);
 461
 462                refname = line + 82;
 463                reflen = strlen(refname);
 464                if (reflen + 82 < len) {
 465                        if (strstr(refname + reflen + 1, "report-status"))
 466                                report_status = 1;
 467                }
 468                cmd = xmalloc(sizeof(struct command) + len - 80);
 469                hashcpy(cmd->old_sha1, old_sha1);
 470                hashcpy(cmd->new_sha1, new_sha1);
 471                memcpy(cmd->ref_name, line + 82, len - 81);
 472                cmd->error_string = NULL;
 473                cmd->next = NULL;
 474                *p = cmd;
 475                p = &cmd->next;
 476        }
 477}
 478
 479static const char *parse_pack_header(struct pack_header *hdr)
 480{
 481        switch (read_pack_header(0, hdr)) {
 482        case PH_ERROR_EOF:
 483                return "eof before pack header was fully read";
 484
 485        case PH_ERROR_PACK_SIGNATURE:
 486                return "protocol error (pack signature mismatch detected)";
 487
 488        case PH_ERROR_PROTOCOL:
 489                return "protocol error (pack version unsupported)";
 490
 491        default:
 492                return "unknown error in parse_pack_header";
 493
 494        case 0:
 495                return NULL;
 496        }
 497}
 498
 499static const char *pack_lockfile;
 500
 501static const char *unpack(void)
 502{
 503        struct pack_header hdr;
 504        const char *hdr_err;
 505        char hdr_arg[38];
 506
 507        hdr_err = parse_pack_header(&hdr);
 508        if (hdr_err)
 509                return hdr_err;
 510        snprintf(hdr_arg, sizeof(hdr_arg),
 511                        "--pack_header=%"PRIu32",%"PRIu32,
 512                        ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
 513
 514        if (ntohl(hdr.hdr_entries) < unpack_limit) {
 515                int code, i = 0;
 516                const char *unpacker[4];
 517                unpacker[i++] = "unpack-objects";
 518                if (receive_fsck_objects)
 519                        unpacker[i++] = "--strict";
 520                unpacker[i++] = hdr_arg;
 521                unpacker[i++] = NULL;
 522                code = run_command_v_opt(unpacker, RUN_GIT_CMD);
 523                if (!code)
 524                        return NULL;
 525                return "unpack-objects abnormal exit";
 526        } else {
 527                const char *keeper[7];
 528                int s, status, i = 0;
 529                char keep_arg[256];
 530                struct child_process ip;
 531
 532                s = sprintf(keep_arg, "--keep=receive-pack %"PRIuMAX" on ", (uintmax_t) getpid());
 533                if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
 534                        strcpy(keep_arg + s, "localhost");
 535
 536                keeper[i++] = "index-pack";
 537                keeper[i++] = "--stdin";
 538                if (receive_fsck_objects)
 539                        keeper[i++] = "--strict";
 540                keeper[i++] = "--fix-thin";
 541                keeper[i++] = hdr_arg;
 542                keeper[i++] = keep_arg;
 543                keeper[i++] = NULL;
 544                memset(&ip, 0, sizeof(ip));
 545                ip.argv = keeper;
 546                ip.out = -1;
 547                ip.git_cmd = 1;
 548                status = start_command(&ip);
 549                if (status) {
 550                        return "index-pack fork failed";
 551                }
 552                pack_lockfile = index_pack_lockfile(ip.out);
 553                close(ip.out);
 554                status = finish_command(&ip);
 555                if (!status) {
 556                        reprepare_packed_git();
 557                        return NULL;
 558                }
 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                if (auto_gc) {
 688                        const char *argv_gc_auto[] = {
 689                                "gc", "--auto", "--quiet", NULL,
 690                        };
 691                        run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
 692                }
 693                if (auto_update_server_info)
 694                        update_server_info(0);
 695        }
 696        return 0;
 697}