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