upload-pack.con commit general improvements (43abf13)
   1#include "cache.h"
   2#include "config.h"
   3#include "refs.h"
   4#include "pkt-line.h"
   5#include "sideband.h"
   6#include "repository.h"
   7#include "object-store.h"
   8#include "tag.h"
   9#include "object.h"
  10#include "commit.h"
  11#include "diff.h"
  12#include "revision.h"
  13#include "list-objects.h"
  14#include "list-objects-filter.h"
  15#include "list-objects-filter-options.h"
  16#include "run-command.h"
  17#include "connect.h"
  18#include "sigchain.h"
  19#include "version.h"
  20#include "string-list.h"
  21#include "argv-array.h"
  22#include "prio-queue.h"
  23#include "protocol.h"
  24#include "quote.h"
  25#include "upload-pack.h"
  26#include "serve.h"
  27#include "commit-graph.h"
  28#include "commit-reach.h"
  29
  30/* Remember to update object flag allocation in object.h */
  31#define THEY_HAVE       (1u << 11)
  32#define OUR_REF         (1u << 12)
  33#define WANTED          (1u << 13)
  34#define COMMON_KNOWN    (1u << 14)
  35
  36#define SHALLOW         (1u << 16)
  37#define NOT_SHALLOW     (1u << 17)
  38#define CLIENT_SHALLOW  (1u << 18)
  39#define HIDDEN_REF      (1u << 19)
  40
  41#define ALL_FLAGS (THEY_HAVE | OUR_REF | WANTED | COMMON_KNOWN | SHALLOW | \
  42                NOT_SHALLOW | CLIENT_SHALLOW | HIDDEN_REF)
  43
  44static timestamp_t oldest_have;
  45
  46static int multi_ack;
  47static int no_done;
  48static int use_thin_pack, use_ofs_delta, use_include_tag;
  49static int no_progress, daemon_mode;
  50/* Allow specifying sha1 if it is a ref tip. */
  51#define ALLOW_TIP_SHA1  01
  52/* Allow request of a sha1 if it is reachable from a ref (possibly hidden ref). */
  53#define ALLOW_REACHABLE_SHA1    02
  54/* Allow request of any sha1. Implies ALLOW_TIP_SHA1 and ALLOW_REACHABLE_SHA1. */
  55#define ALLOW_ANY_SHA1  07
  56static unsigned int allow_unadvertised_object_request;
  57static int shallow_nr;
  58static struct object_array extra_edge_obj;
  59static unsigned int timeout;
  60static int keepalive = 5;
  61/* 0 for no sideband,
  62 * otherwise maximum packet size (up to 65520 bytes).
  63 */
  64static int use_sideband;
  65static int stateless_rpc;
  66static const char *pack_objects_hook;
  67
  68static int filter_capability_requested;
  69static int allow_filter;
  70static int allow_ref_in_want;
  71static struct list_objects_filter_options filter_options;
  72
  73static int allow_sideband_all;
  74
  75static void reset_timeout(void)
  76{
  77        alarm(timeout);
  78}
  79
  80static void send_client_data(int fd, const char *data, ssize_t sz)
  81{
  82        if (use_sideband) {
  83                send_sideband(1, fd, data, sz, use_sideband);
  84                return;
  85        }
  86        if (fd == 3)
  87                /* emergency quit */
  88                fd = 2;
  89        if (fd == 2) {
  90                /* XXX: are we happy to lose stuff here? */
  91                xwrite(fd, data, sz);
  92                return;
  93        }
  94        write_or_die(fd, data, sz);
  95}
  96
  97static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
  98{
  99        FILE *fp = cb_data;
 100        if (graft->nr_parent == -1)
 101                fprintf(fp, "--shallow %s\n", oid_to_hex(&graft->oid));
 102        return 0;
 103}
 104
 105static void create_pack_file(const struct object_array *have_obj,
 106                             const struct object_array *want_obj)
 107{
 108        struct child_process pack_objects = CHILD_PROCESS_INIT;
 109        char data[8193], progress[128];
 110        char abort_msg[] = "aborting due to possible repository "
 111                "corruption on the remote side.";
 112        int buffered = -1;
 113        ssize_t sz;
 114        int i;
 115        FILE *pipe_fd;
 116
 117        if (!pack_objects_hook)
 118                pack_objects.git_cmd = 1;
 119        else {
 120                argv_array_push(&pack_objects.args, pack_objects_hook);
 121                argv_array_push(&pack_objects.args, "git");
 122                pack_objects.use_shell = 1;
 123        }
 124
 125        if (shallow_nr) {
 126                argv_array_push(&pack_objects.args, "--shallow-file");
 127                argv_array_push(&pack_objects.args, "");
 128        }
 129        argv_array_push(&pack_objects.args, "pack-objects");
 130        argv_array_push(&pack_objects.args, "--revs");
 131        if (use_thin_pack)
 132                argv_array_push(&pack_objects.args, "--thin");
 133
 134        argv_array_push(&pack_objects.args, "--stdout");
 135        if (shallow_nr)
 136                argv_array_push(&pack_objects.args, "--shallow");
 137        if (!no_progress)
 138                argv_array_push(&pack_objects.args, "--progress");
 139        if (use_ofs_delta)
 140                argv_array_push(&pack_objects.args, "--delta-base-offset");
 141        if (use_include_tag)
 142                argv_array_push(&pack_objects.args, "--include-tag");
 143        if (filter_options.choice) {
 144                const char *spec =
 145                        expand_list_objects_filter_spec(&filter_options);
 146                if (pack_objects.use_shell) {
 147                        struct strbuf buf = STRBUF_INIT;
 148                        sq_quote_buf(&buf, spec);
 149                        argv_array_pushf(&pack_objects.args, "--filter=%s", buf.buf);
 150                        strbuf_release(&buf);
 151                } else {
 152                        argv_array_pushf(&pack_objects.args, "--filter=%s",
 153                                         spec);
 154                }
 155        }
 156
 157        pack_objects.in = -1;
 158        pack_objects.out = -1;
 159        pack_objects.err = -1;
 160
 161        if (start_command(&pack_objects))
 162                die("git upload-pack: unable to fork git-pack-objects");
 163
 164        pipe_fd = xfdopen(pack_objects.in, "w");
 165
 166        if (shallow_nr)
 167                for_each_commit_graft(write_one_shallow, pipe_fd);
 168
 169        for (i = 0; i < want_obj->nr; i++)
 170                fprintf(pipe_fd, "%s\n",
 171                        oid_to_hex(&want_obj->objects[i].item->oid));
 172        fprintf(pipe_fd, "--not\n");
 173        for (i = 0; i < have_obj->nr; i++)
 174                fprintf(pipe_fd, "%s\n",
 175                        oid_to_hex(&have_obj->objects[i].item->oid));
 176        for (i = 0; i < extra_edge_obj.nr; i++)
 177                fprintf(pipe_fd, "%s\n",
 178                        oid_to_hex(&extra_edge_obj.objects[i].item->oid));
 179        fprintf(pipe_fd, "\n");
 180        fflush(pipe_fd);
 181        fclose(pipe_fd);
 182
 183        /* We read from pack_objects.err to capture stderr output for
 184         * progress bar, and pack_objects.out to capture the pack data.
 185         */
 186
 187        while (1) {
 188                struct pollfd pfd[2];
 189                int pe, pu, pollsize;
 190                int ret;
 191
 192                reset_timeout();
 193
 194                pollsize = 0;
 195                pe = pu = -1;
 196
 197                if (0 <= pack_objects.out) {
 198                        pfd[pollsize].fd = pack_objects.out;
 199                        pfd[pollsize].events = POLLIN;
 200                        pu = pollsize;
 201                        pollsize++;
 202                }
 203                if (0 <= pack_objects.err) {
 204                        pfd[pollsize].fd = pack_objects.err;
 205                        pfd[pollsize].events = POLLIN;
 206                        pe = pollsize;
 207                        pollsize++;
 208                }
 209
 210                if (!pollsize)
 211                        break;
 212
 213                ret = poll(pfd, pollsize,
 214                        keepalive < 0 ? -1 : 1000 * keepalive);
 215
 216                if (ret < 0) {
 217                        if (errno != EINTR) {
 218                                error_errno("poll failed, resuming");
 219                                sleep(1);
 220                        }
 221                        continue;
 222                }
 223                if (0 <= pe && (pfd[pe].revents & (POLLIN|POLLHUP))) {
 224                        /* Status ready; we ship that in the side-band
 225                         * or dump to the standard error.
 226                         */
 227                        sz = xread(pack_objects.err, progress,
 228                                  sizeof(progress));
 229                        if (0 < sz)
 230                                send_client_data(2, progress, sz);
 231                        else if (sz == 0) {
 232                                close(pack_objects.err);
 233                                pack_objects.err = -1;
 234                        }
 235                        else
 236                                goto fail;
 237                        /* give priority to status messages */
 238                        continue;
 239                }
 240                if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
 241                        /* Data ready; we keep the last byte to ourselves
 242                         * in case we detect broken rev-list, so that we
 243                         * can leave the stream corrupted.  This is
 244                         * unfortunate -- unpack-objects would happily
 245                         * accept a valid packdata with trailing garbage,
 246                         * so appending garbage after we pass all the
 247                         * pack data is not good enough to signal
 248                         * breakage to downstream.
 249                         */
 250                        char *cp = data;
 251                        ssize_t outsz = 0;
 252                        if (0 <= buffered) {
 253                                *cp++ = buffered;
 254                                outsz++;
 255                        }
 256                        sz = xread(pack_objects.out, cp,
 257                                  sizeof(data) - outsz);
 258                        if (0 < sz)
 259                                ;
 260                        else if (sz == 0) {
 261                                close(pack_objects.out);
 262                                pack_objects.out = -1;
 263                        }
 264                        else
 265                                goto fail;
 266                        sz += outsz;
 267                        if (1 < sz) {
 268                                buffered = data[sz-1] & 0xFF;
 269                                sz--;
 270                        }
 271                        else
 272                                buffered = -1;
 273                        send_client_data(1, data, sz);
 274                }
 275
 276                /*
 277                 * We hit the keepalive timeout without saying anything; send
 278                 * an empty message on the data sideband just to let the other
 279                 * side know we're still working on it, but don't have any data
 280                 * yet.
 281                 *
 282                 * If we don't have a sideband channel, there's no room in the
 283                 * protocol to say anything, so those clients are just out of
 284                 * luck.
 285                 */
 286                if (!ret && use_sideband) {
 287                        static const char buf[] = "0005\1";
 288                        write_or_die(1, buf, 5);
 289                }
 290        }
 291
 292        if (finish_command(&pack_objects)) {
 293                error("git upload-pack: git-pack-objects died with error.");
 294                goto fail;
 295        }
 296
 297        /* flush the data */
 298        if (0 <= buffered) {
 299                data[0] = buffered;
 300                send_client_data(1, data, 1);
 301                fprintf(stderr, "flushed.\n");
 302        }
 303        if (use_sideband)
 304                packet_flush(1);
 305        return;
 306
 307 fail:
 308        send_client_data(3, abort_msg, sizeof(abort_msg));
 309        die("git upload-pack: %s", abort_msg);
 310}
 311
 312static int got_oid(const char *hex, struct object_id *oid,
 313                   struct object_array *have_obj)
 314{
 315        struct object *o;
 316        int we_knew_they_have = 0;
 317
 318        if (get_oid_hex(hex, oid))
 319                die("git upload-pack: expected SHA1 object, got '%s'", hex);
 320        if (!has_object_file(oid))
 321                return -1;
 322
 323        o = parse_object(the_repository, oid);
 324        if (!o)
 325                die("oops (%s)", oid_to_hex(oid));
 326        if (o->type == OBJ_COMMIT) {
 327                struct commit_list *parents;
 328                struct commit *commit = (struct commit *)o;
 329                if (o->flags & THEY_HAVE)
 330                        we_knew_they_have = 1;
 331                else
 332                        o->flags |= THEY_HAVE;
 333                if (!oldest_have || (commit->date < oldest_have))
 334                        oldest_have = commit->date;
 335                for (parents = commit->parents;
 336                     parents;
 337                     parents = parents->next)
 338                        parents->item->object.flags |= THEY_HAVE;
 339        }
 340        if (!we_knew_they_have) {
 341                add_object_array(o, NULL, have_obj);
 342                return 1;
 343        }
 344        return 0;
 345}
 346
 347static int ok_to_give_up(const struct object_array *have_obj,
 348                         struct object_array *want_obj)
 349{
 350        uint32_t min_generation = GENERATION_NUMBER_ZERO;
 351
 352        if (!have_obj->nr)
 353                return 0;
 354
 355        return can_all_from_reach_with_flag(want_obj, THEY_HAVE,
 356                                            COMMON_KNOWN, oldest_have,
 357                                            min_generation);
 358}
 359
 360static int get_common_commits(struct packet_reader *reader,
 361                              struct object_array *have_obj,
 362                              struct object_array *want_obj)
 363{
 364        struct object_id oid;
 365        char last_hex[GIT_MAX_HEXSZ + 1];
 366        int got_common = 0;
 367        int got_other = 0;
 368        int sent_ready = 0;
 369
 370        save_commit_buffer = 0;
 371
 372        for (;;) {
 373                const char *arg;
 374
 375                reset_timeout();
 376
 377                if (packet_reader_read(reader) != PACKET_READ_NORMAL) {
 378                        if (multi_ack == 2 && got_common
 379                            && !got_other && ok_to_give_up(have_obj, want_obj)) {
 380                                sent_ready = 1;
 381                                packet_write_fmt(1, "ACK %s ready\n", last_hex);
 382                        }
 383                        if (have_obj->nr == 0 || multi_ack)
 384                                packet_write_fmt(1, "NAK\n");
 385
 386                        if (no_done && sent_ready) {
 387                                packet_write_fmt(1, "ACK %s\n", last_hex);
 388                                return 0;
 389                        }
 390                        if (stateless_rpc)
 391                                exit(0);
 392                        got_common = 0;
 393                        got_other = 0;
 394                        continue;
 395                }
 396                if (skip_prefix(reader->line, "have ", &arg)) {
 397                        switch (got_oid(arg, &oid, have_obj)) {
 398                        case -1: /* they have what we do not */
 399                                got_other = 1;
 400                                if (multi_ack && ok_to_give_up(have_obj, want_obj)) {
 401                                        const char *hex = oid_to_hex(&oid);
 402                                        if (multi_ack == 2) {
 403                                                sent_ready = 1;
 404                                                packet_write_fmt(1, "ACK %s ready\n", hex);
 405                                        } else
 406                                                packet_write_fmt(1, "ACK %s continue\n", hex);
 407                                }
 408                                break;
 409                        default:
 410                                got_common = 1;
 411                                oid_to_hex_r(last_hex, &oid);
 412                                if (multi_ack == 2)
 413                                        packet_write_fmt(1, "ACK %s common\n", last_hex);
 414                                else if (multi_ack)
 415                                        packet_write_fmt(1, "ACK %s continue\n", last_hex);
 416                                else if (have_obj->nr == 1)
 417                                        packet_write_fmt(1, "ACK %s\n", last_hex);
 418                                break;
 419                        }
 420                        continue;
 421                }
 422                if (!strcmp(reader->line, "done")) {
 423                        if (have_obj->nr > 0) {
 424                                if (multi_ack)
 425                                        packet_write_fmt(1, "ACK %s\n", last_hex);
 426                                return 0;
 427                        }
 428                        packet_write_fmt(1, "NAK\n");
 429                        return -1;
 430                }
 431                die("git upload-pack: expected SHA1 list, got '%s'", reader->line);
 432        }
 433}
 434
 435static int is_our_ref(struct object *o)
 436{
 437        int allow_hidden_ref = (allow_unadvertised_object_request &
 438                        (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1));
 439        return o->flags & ((allow_hidden_ref ? HIDDEN_REF : 0) | OUR_REF);
 440}
 441
 442/*
 443 * on successful case, it's up to the caller to close cmd->out
 444 */
 445static int do_reachable_revlist(struct child_process *cmd,
 446                                struct object_array *src,
 447                                struct object_array *reachable)
 448{
 449        static const char *argv[] = {
 450                "rev-list", "--stdin", NULL,
 451        };
 452        struct object *o;
 453        char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */
 454        int i;
 455        const unsigned hexsz = the_hash_algo->hexsz;
 456
 457        cmd->argv = argv;
 458        cmd->git_cmd = 1;
 459        cmd->no_stderr = 1;
 460        cmd->in = -1;
 461        cmd->out = -1;
 462
 463        /*
 464         * If the next rev-list --stdin encounters an unknown commit,
 465         * it terminates, which will cause SIGPIPE in the write loop
 466         * below.
 467         */
 468        sigchain_push(SIGPIPE, SIG_IGN);
 469
 470        if (start_command(cmd))
 471                goto error;
 472
 473        namebuf[0] = '^';
 474        namebuf[hexsz + 1] = '\n';
 475        for (i = get_max_object_index(); 0 < i; ) {
 476                o = get_indexed_object(--i);
 477                if (!o)
 478                        continue;
 479                if (reachable && o->type == OBJ_COMMIT)
 480                        o->flags &= ~TMP_MARK;
 481                if (!is_our_ref(o))
 482                        continue;
 483                memcpy(namebuf + 1, oid_to_hex(&o->oid), hexsz);
 484                if (write_in_full(cmd->in, namebuf, hexsz + 2) < 0)
 485                        goto error;
 486        }
 487        namebuf[hexsz] = '\n';
 488        for (i = 0; i < src->nr; i++) {
 489                o = src->objects[i].item;
 490                if (is_our_ref(o)) {
 491                        if (reachable)
 492                                add_object_array(o, NULL, reachable);
 493                        continue;
 494                }
 495                if (reachable && o->type == OBJ_COMMIT)
 496                        o->flags |= TMP_MARK;
 497                memcpy(namebuf, oid_to_hex(&o->oid), hexsz);
 498                if (write_in_full(cmd->in, namebuf, hexsz + 1) < 0)
 499                        goto error;
 500        }
 501        close(cmd->in);
 502        cmd->in = -1;
 503        sigchain_pop(SIGPIPE);
 504
 505        return 0;
 506
 507error:
 508        sigchain_pop(SIGPIPE);
 509
 510        if (cmd->in >= 0)
 511                close(cmd->in);
 512        if (cmd->out >= 0)
 513                close(cmd->out);
 514        return -1;
 515}
 516
 517static int get_reachable_list(struct object_array *src,
 518                              struct object_array *reachable)
 519{
 520        struct child_process cmd = CHILD_PROCESS_INIT;
 521        int i;
 522        struct object *o;
 523        char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */
 524        const unsigned hexsz = the_hash_algo->hexsz;
 525
 526        if (do_reachable_revlist(&cmd, src, reachable) < 0)
 527                return -1;
 528
 529        while ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) {
 530                struct object_id oid;
 531                const char *p;
 532
 533                if (parse_oid_hex(namebuf, &oid, &p) || *p != '\n')
 534                        break;
 535
 536                o = lookup_object(the_repository, &oid);
 537                if (o && o->type == OBJ_COMMIT) {
 538                        o->flags &= ~TMP_MARK;
 539                }
 540        }
 541        for (i = get_max_object_index(); 0 < i; i--) {
 542                o = get_indexed_object(i - 1);
 543                if (o && o->type == OBJ_COMMIT &&
 544                    (o->flags & TMP_MARK)) {
 545                        add_object_array(o, NULL, reachable);
 546                                o->flags &= ~TMP_MARK;
 547                }
 548        }
 549        close(cmd.out);
 550
 551        if (finish_command(&cmd))
 552                return -1;
 553
 554        return 0;
 555}
 556
 557static int has_unreachable(struct object_array *src)
 558{
 559        struct child_process cmd = CHILD_PROCESS_INIT;
 560        char buf[1];
 561        int i;
 562
 563        if (do_reachable_revlist(&cmd, src, NULL) < 0)
 564                return 1;
 565
 566        /*
 567         * The commits out of the rev-list are not ancestors of
 568         * our ref.
 569         */
 570        i = read_in_full(cmd.out, buf, 1);
 571        if (i)
 572                goto error;
 573        close(cmd.out);
 574        cmd.out = -1;
 575
 576        /*
 577         * rev-list may have died by encountering a bad commit
 578         * in the history, in which case we do want to bail out
 579         * even when it showed no commit.
 580         */
 581        if (finish_command(&cmd))
 582                goto error;
 583
 584        /* All the non-tip ones are ancestors of what we advertised */
 585        return 0;
 586
 587error:
 588        sigchain_pop(SIGPIPE);
 589        if (cmd.out >= 0)
 590                close(cmd.out);
 591        return 1;
 592}
 593
 594static void check_non_tip(struct object_array *want_obj,
 595                          struct packet_writer *writer)
 596{
 597        int i;
 598
 599        /*
 600         * In the normal in-process case without
 601         * uploadpack.allowReachableSHA1InWant,
 602         * non-tip requests can never happen.
 603         */
 604        if (!stateless_rpc && !(allow_unadvertised_object_request & ALLOW_REACHABLE_SHA1))
 605                goto error;
 606        if (!has_unreachable(want_obj))
 607                /* All the non-tip ones are ancestors of what we advertised */
 608                return;
 609
 610error:
 611        /* Pick one of them (we know there at least is one) */
 612        for (i = 0; i < want_obj->nr; i++) {
 613                struct object *o = want_obj->objects[i].item;
 614                if (!is_our_ref(o)) {
 615                        packet_writer_error(writer,
 616                                            "upload-pack: not our ref %s",
 617                                            oid_to_hex(&o->oid));
 618                        die("git upload-pack: not our ref %s",
 619                            oid_to_hex(&o->oid));
 620                }
 621        }
 622}
 623
 624static void send_shallow(struct packet_writer *writer,
 625                         struct commit_list *result)
 626{
 627        while (result) {
 628                struct object *object = &result->item->object;
 629                if (!(object->flags & (CLIENT_SHALLOW|NOT_SHALLOW))) {
 630                        packet_writer_write(writer, "shallow %s",
 631                                            oid_to_hex(&object->oid));
 632                        register_shallow(the_repository, &object->oid);
 633                        shallow_nr++;
 634                }
 635                result = result->next;
 636        }
 637}
 638
 639static void send_unshallow(struct packet_writer *writer,
 640                           const struct object_array *shallows,
 641                           struct object_array *want_obj)
 642{
 643        int i;
 644
 645        for (i = 0; i < shallows->nr; i++) {
 646                struct object *object = shallows->objects[i].item;
 647                if (object->flags & NOT_SHALLOW) {
 648                        struct commit_list *parents;
 649                        packet_writer_write(writer, "unshallow %s",
 650                                            oid_to_hex(&object->oid));
 651                        object->flags &= ~CLIENT_SHALLOW;
 652                        /*
 653                         * We want to _register_ "object" as shallow, but we
 654                         * also need to traverse object's parents to deepen a
 655                         * shallow clone. Unregister it for now so we can
 656                         * parse and add the parents to the want list, then
 657                         * re-register it.
 658                         */
 659                        unregister_shallow(&object->oid);
 660                        object->parsed = 0;
 661                        parse_commit_or_die((struct commit *)object);
 662                        parents = ((struct commit *)object)->parents;
 663                        while (parents) {
 664                                add_object_array(&parents->item->object,
 665                                                 NULL, want_obj);
 666                                parents = parents->next;
 667                        }
 668                        add_object_array(object, NULL, &extra_edge_obj);
 669                }
 670                /* make sure commit traversal conforms to client */
 671                register_shallow(the_repository, &object->oid);
 672        }
 673}
 674
 675static int check_ref(const char *refname_full, const struct object_id *oid,
 676                     int flag, void *cb_data);
 677static void deepen(struct packet_writer *writer, int depth, int deepen_relative,
 678                   struct object_array *shallows, struct object_array *want_obj)
 679{
 680        if (depth == INFINITE_DEPTH && !is_repository_shallow(the_repository)) {
 681                int i;
 682
 683                for (i = 0; i < shallows->nr; i++) {
 684                        struct object *object = shallows->objects[i].item;
 685                        object->flags |= NOT_SHALLOW;
 686                }
 687        } else if (deepen_relative) {
 688                struct object_array reachable_shallows = OBJECT_ARRAY_INIT;
 689                struct commit_list *result;
 690
 691                /*
 692                 * Checking for reachable shallows requires that our refs be
 693                 * marked with OUR_REF.
 694                 */
 695                head_ref_namespaced(check_ref, NULL);
 696                for_each_namespaced_ref(check_ref, NULL);
 697
 698                get_reachable_list(shallows, &reachable_shallows);
 699                result = get_shallow_commits(&reachable_shallows,
 700                                             depth + 1,
 701                                             SHALLOW, NOT_SHALLOW);
 702                send_shallow(writer, result);
 703                free_commit_list(result);
 704                object_array_clear(&reachable_shallows);
 705        } else {
 706                struct commit_list *result;
 707
 708                result = get_shallow_commits(want_obj, depth,
 709                                             SHALLOW, NOT_SHALLOW);
 710                send_shallow(writer, result);
 711                free_commit_list(result);
 712        }
 713
 714        send_unshallow(writer, shallows, want_obj);
 715}
 716
 717static void deepen_by_rev_list(struct packet_writer *writer, int ac,
 718                               const char **av,
 719                               struct object_array *shallows,
 720                               struct object_array *want_obj)
 721{
 722        struct commit_list *result;
 723
 724        close_commit_graph(the_repository->objects);
 725        result = get_shallow_commits_by_rev_list(ac, av, SHALLOW, NOT_SHALLOW);
 726        send_shallow(writer, result);
 727        free_commit_list(result);
 728        send_unshallow(writer, shallows, want_obj);
 729}
 730
 731/* Returns 1 if a shallow list is sent or 0 otherwise */
 732static int send_shallow_list(struct packet_writer *writer,
 733                             int depth, int deepen_rev_list,
 734                             timestamp_t deepen_since,
 735                             struct string_list *deepen_not,
 736                             int deepen_relative,
 737                             struct object_array *shallows,
 738                             struct object_array *want_obj)
 739{
 740        int ret = 0;
 741
 742        if (depth > 0 && deepen_rev_list)
 743                die("git upload-pack: deepen and deepen-since (or deepen-not) cannot be used together");
 744        if (depth > 0) {
 745                deepen(writer, depth, deepen_relative, shallows, want_obj);
 746                ret = 1;
 747        } else if (deepen_rev_list) {
 748                struct argv_array av = ARGV_ARRAY_INIT;
 749                int i;
 750
 751                argv_array_push(&av, "rev-list");
 752                if (deepen_since)
 753                        argv_array_pushf(&av, "--max-age=%"PRItime, deepen_since);
 754                if (deepen_not->nr) {
 755                        argv_array_push(&av, "--not");
 756                        for (i = 0; i < deepen_not->nr; i++) {
 757                                struct string_list_item *s = deepen_not->items + i;
 758                                argv_array_push(&av, s->string);
 759                        }
 760                        argv_array_push(&av, "--not");
 761                }
 762                for (i = 0; i < want_obj->nr; i++) {
 763                        struct object *o = want_obj->objects[i].item;
 764                        argv_array_push(&av, oid_to_hex(&o->oid));
 765                }
 766                deepen_by_rev_list(writer, av.argc, av.argv, shallows, want_obj);
 767                argv_array_clear(&av);
 768                ret = 1;
 769        } else {
 770                if (shallows->nr > 0) {
 771                        int i;
 772                        for (i = 0; i < shallows->nr; i++)
 773                                register_shallow(the_repository,
 774                                                 &shallows->objects[i].item->oid);
 775                }
 776        }
 777
 778        shallow_nr += shallows->nr;
 779        return ret;
 780}
 781
 782static int process_shallow(const char *line, struct object_array *shallows)
 783{
 784        const char *arg;
 785        if (skip_prefix(line, "shallow ", &arg)) {
 786                struct object_id oid;
 787                struct object *object;
 788                if (get_oid_hex(arg, &oid))
 789                        die("invalid shallow line: %s", line);
 790                object = parse_object(the_repository, &oid);
 791                if (!object)
 792                        return 1;
 793                if (object->type != OBJ_COMMIT)
 794                        die("invalid shallow object %s", oid_to_hex(&oid));
 795                if (!(object->flags & CLIENT_SHALLOW)) {
 796                        object->flags |= CLIENT_SHALLOW;
 797                        add_object_array(object, NULL, shallows);
 798                }
 799                return 1;
 800        }
 801
 802        return 0;
 803}
 804
 805static int process_deepen(const char *line, int *depth)
 806{
 807        const char *arg;
 808        if (skip_prefix(line, "deepen ", &arg)) {
 809                char *end = NULL;
 810                *depth = (int)strtol(arg, &end, 0);
 811                if (!end || *end || *depth <= 0)
 812                        die("Invalid deepen: %s", line);
 813                return 1;
 814        }
 815
 816        return 0;
 817}
 818
 819static int process_deepen_since(const char *line, timestamp_t *deepen_since, int *deepen_rev_list)
 820{
 821        const char *arg;
 822        if (skip_prefix(line, "deepen-since ", &arg)) {
 823                char *end = NULL;
 824                *deepen_since = parse_timestamp(arg, &end, 0);
 825                if (!end || *end || !deepen_since ||
 826                    /* revisions.c's max_age -1 is special */
 827                    *deepen_since == -1)
 828                        die("Invalid deepen-since: %s", line);
 829                *deepen_rev_list = 1;
 830                return 1;
 831        }
 832        return 0;
 833}
 834
 835static int process_deepen_not(const char *line, struct string_list *deepen_not, int *deepen_rev_list)
 836{
 837        const char *arg;
 838        if (skip_prefix(line, "deepen-not ", &arg)) {
 839                char *ref = NULL;
 840                struct object_id oid;
 841                if (expand_ref(the_repository, arg, strlen(arg), &oid, &ref) != 1)
 842                        die("git upload-pack: ambiguous deepen-not: %s", line);
 843                string_list_append(deepen_not, ref);
 844                free(ref);
 845                *deepen_rev_list = 1;
 846                return 1;
 847        }
 848        return 0;
 849}
 850
 851static void receive_needs(struct packet_reader *reader, struct object_array *want_obj)
 852{
 853        struct object_array shallows = OBJECT_ARRAY_INIT;
 854        struct string_list deepen_not = STRING_LIST_INIT_DUP;
 855        int depth = 0;
 856        int has_non_tip = 0;
 857        timestamp_t deepen_since = 0;
 858        int deepen_rev_list = 0;
 859        int deepen_relative = 0;
 860        struct packet_writer writer;
 861
 862        shallow_nr = 0;
 863        packet_writer_init(&writer, 1);
 864        for (;;) {
 865                struct object *o;
 866                const char *features;
 867                struct object_id oid_buf;
 868                const char *arg;
 869
 870                reset_timeout();
 871                if (packet_reader_read(reader) != PACKET_READ_NORMAL)
 872                        break;
 873
 874                if (process_shallow(reader->line, &shallows))
 875                        continue;
 876                if (process_deepen(reader->line, &depth))
 877                        continue;
 878                if (process_deepen_since(reader->line, &deepen_since, &deepen_rev_list))
 879                        continue;
 880                if (process_deepen_not(reader->line, &deepen_not, &deepen_rev_list))
 881                        continue;
 882
 883                if (skip_prefix(reader->line, "filter ", &arg)) {
 884                        if (!filter_capability_requested)
 885                                die("git upload-pack: filtering capability not negotiated");
 886                        list_objects_filter_die_if_populated(&filter_options);
 887                        parse_list_objects_filter(&filter_options, arg);
 888                        continue;
 889                }
 890
 891                if (!skip_prefix(reader->line, "want ", &arg) ||
 892                    parse_oid_hex(arg, &oid_buf, &features))
 893                        die("git upload-pack: protocol error, "
 894                            "expected to get object ID, not '%s'", reader->line);
 895
 896                if (parse_feature_request(features, "deepen-relative"))
 897                        deepen_relative = 1;
 898                if (parse_feature_request(features, "multi_ack_detailed"))
 899                        multi_ack = 2;
 900                else if (parse_feature_request(features, "multi_ack"))
 901                        multi_ack = 1;
 902                if (parse_feature_request(features, "no-done"))
 903                        no_done = 1;
 904                if (parse_feature_request(features, "thin-pack"))
 905                        use_thin_pack = 1;
 906                if (parse_feature_request(features, "ofs-delta"))
 907                        use_ofs_delta = 1;
 908                if (parse_feature_request(features, "side-band-64k"))
 909                        use_sideband = LARGE_PACKET_MAX;
 910                else if (parse_feature_request(features, "side-band"))
 911                        use_sideband = DEFAULT_PACKET_MAX;
 912                if (parse_feature_request(features, "no-progress"))
 913                        no_progress = 1;
 914                if (parse_feature_request(features, "include-tag"))
 915                        use_include_tag = 1;
 916                if (allow_filter && parse_feature_request(features, "filter"))
 917                        filter_capability_requested = 1;
 918
 919                o = parse_object(the_repository, &oid_buf);
 920                if (!o) {
 921                        packet_writer_error(&writer,
 922                                            "upload-pack: not our ref %s",
 923                                            oid_to_hex(&oid_buf));
 924                        die("git upload-pack: not our ref %s",
 925                            oid_to_hex(&oid_buf));
 926                }
 927                if (!(o->flags & WANTED)) {
 928                        o->flags |= WANTED;
 929                        if (!((allow_unadvertised_object_request & ALLOW_ANY_SHA1) == ALLOW_ANY_SHA1
 930                              || is_our_ref(o)))
 931                                has_non_tip = 1;
 932                        add_object_array(o, NULL, want_obj);
 933                }
 934        }
 935
 936        /*
 937         * We have sent all our refs already, and the other end
 938         * should have chosen out of them. When we are operating
 939         * in the stateless RPC mode, however, their choice may
 940         * have been based on the set of older refs advertised
 941         * by another process that handled the initial request.
 942         */
 943        if (has_non_tip)
 944                check_non_tip(want_obj, &writer);
 945
 946        if (!use_sideband && daemon_mode)
 947                no_progress = 1;
 948
 949        if (depth == 0 && !deepen_rev_list && shallows.nr == 0)
 950                return;
 951
 952        if (send_shallow_list(&writer, depth, deepen_rev_list, deepen_since,
 953                              &deepen_not, deepen_relative, &shallows,
 954                              want_obj))
 955                packet_flush(1);
 956        object_array_clear(&shallows);
 957}
 958
 959/* return non-zero if the ref is hidden, otherwise 0 */
 960static int mark_our_ref(const char *refname, const char *refname_full,
 961                        const struct object_id *oid)
 962{
 963        struct object *o = lookup_unknown_object(oid);
 964
 965        if (ref_is_hidden(refname, refname_full)) {
 966                o->flags |= HIDDEN_REF;
 967                return 1;
 968        }
 969        o->flags |= OUR_REF;
 970        return 0;
 971}
 972
 973static int check_ref(const char *refname_full, const struct object_id *oid,
 974                     int flag, void *cb_data)
 975{
 976        const char *refname = strip_namespace(refname_full);
 977
 978        mark_our_ref(refname, refname_full, oid);
 979        return 0;
 980}
 981
 982static void format_symref_info(struct strbuf *buf, struct string_list *symref)
 983{
 984        struct string_list_item *item;
 985
 986        if (!symref->nr)
 987                return;
 988        for_each_string_list_item(item, symref)
 989                strbuf_addf(buf, " symref=%s:%s", item->string, (char *)item->util);
 990}
 991
 992static int send_ref(const char *refname, const struct object_id *oid,
 993                    int flag, void *cb_data)
 994{
 995        static const char *capabilities = "multi_ack thin-pack side-band"
 996                " side-band-64k ofs-delta shallow deepen-since deepen-not"
 997                " deepen-relative no-progress include-tag multi_ack_detailed";
 998        const char *refname_nons = strip_namespace(refname);
 999        struct object_id peeled;
1000
1001        if (mark_our_ref(refname_nons, refname, oid))
1002                return 0;
1003
1004        if (capabilities) {
1005                struct strbuf symref_info = STRBUF_INIT;
1006
1007                format_symref_info(&symref_info, cb_data);
1008                packet_write_fmt(1, "%s %s%c%s%s%s%s%s%s agent=%s\n",
1009                             oid_to_hex(oid), refname_nons,
1010                             0, capabilities,
1011                             (allow_unadvertised_object_request & ALLOW_TIP_SHA1) ?
1012                                     " allow-tip-sha1-in-want" : "",
1013                             (allow_unadvertised_object_request & ALLOW_REACHABLE_SHA1) ?
1014                                     " allow-reachable-sha1-in-want" : "",
1015                             stateless_rpc ? " no-done" : "",
1016                             symref_info.buf,
1017                             allow_filter ? " filter" : "",
1018                             git_user_agent_sanitized());
1019                strbuf_release(&symref_info);
1020        } else {
1021                packet_write_fmt(1, "%s %s\n", oid_to_hex(oid), refname_nons);
1022        }
1023        capabilities = NULL;
1024        if (!peel_ref(refname, &peeled))
1025                packet_write_fmt(1, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
1026        return 0;
1027}
1028
1029static int find_symref(const char *refname, const struct object_id *oid,
1030                       int flag, void *cb_data)
1031{
1032        const char *symref_target;
1033        struct string_list_item *item;
1034
1035        if ((flag & REF_ISSYMREF) == 0)
1036                return 0;
1037        symref_target = resolve_ref_unsafe(refname, 0, NULL, &flag);
1038        if (!symref_target || (flag & REF_ISSYMREF) == 0)
1039                die("'%s' is a symref but it is not?", refname);
1040        item = string_list_append(cb_data, strip_namespace(refname));
1041        item->util = xstrdup(strip_namespace(symref_target));
1042        return 0;
1043}
1044
1045static int upload_pack_config(const char *var, const char *value, void *unused)
1046{
1047        if (!strcmp("uploadpack.allowtipsha1inwant", var)) {
1048                if (git_config_bool(var, value))
1049                        allow_unadvertised_object_request |= ALLOW_TIP_SHA1;
1050                else
1051                        allow_unadvertised_object_request &= ~ALLOW_TIP_SHA1;
1052        } else if (!strcmp("uploadpack.allowreachablesha1inwant", var)) {
1053                if (git_config_bool(var, value))
1054                        allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1;
1055                else
1056                        allow_unadvertised_object_request &= ~ALLOW_REACHABLE_SHA1;
1057        } else if (!strcmp("uploadpack.allowanysha1inwant", var)) {
1058                if (git_config_bool(var, value))
1059                        allow_unadvertised_object_request |= ALLOW_ANY_SHA1;
1060                else
1061                        allow_unadvertised_object_request &= ~ALLOW_ANY_SHA1;
1062        } else if (!strcmp("uploadpack.keepalive", var)) {
1063                keepalive = git_config_int(var, value);
1064                if (!keepalive)
1065                        keepalive = -1;
1066        } else if (!strcmp("uploadpack.allowfilter", var)) {
1067                allow_filter = git_config_bool(var, value);
1068        } else if (!strcmp("uploadpack.allowrefinwant", var)) {
1069                allow_ref_in_want = git_config_bool(var, value);
1070        } else if (!strcmp("uploadpack.allowsidebandall", var)) {
1071                allow_sideband_all = git_config_bool(var, value);
1072        } else if (!strcmp("core.precomposeunicode", var)) {
1073                precomposed_unicode = git_config_bool(var, value);
1074        }
1075
1076        if (current_config_scope() != CONFIG_SCOPE_REPO) {
1077                if (!strcmp("uploadpack.packobjectshook", var))
1078                        return git_config_string(&pack_objects_hook, var, value);
1079        }
1080
1081        return parse_hide_refs_config(var, value, "uploadpack");
1082}
1083
1084void upload_pack(struct upload_pack_options *options)
1085{
1086        struct string_list symref = STRING_LIST_INIT_DUP;
1087        struct object_array want_obj = OBJECT_ARRAY_INIT;
1088        struct packet_reader reader;
1089
1090        stateless_rpc = options->stateless_rpc;
1091        timeout = options->timeout;
1092        daemon_mode = options->daemon_mode;
1093
1094        git_config(upload_pack_config, NULL);
1095
1096        head_ref_namespaced(find_symref, &symref);
1097
1098        if (options->advertise_refs || !stateless_rpc) {
1099                reset_timeout();
1100                head_ref_namespaced(send_ref, &symref);
1101                for_each_namespaced_ref(send_ref, &symref);
1102                advertise_shallow_grafts(1);
1103                packet_flush(1);
1104        } else {
1105                head_ref_namespaced(check_ref, NULL);
1106                for_each_namespaced_ref(check_ref, NULL);
1107        }
1108        string_list_clear(&symref, 1);
1109        if (options->advertise_refs)
1110                return;
1111
1112        packet_reader_init(&reader, 0, NULL, 0,
1113                           PACKET_READ_CHOMP_NEWLINE |
1114                           PACKET_READ_DIE_ON_ERR_PACKET);
1115
1116        receive_needs(&reader, &want_obj);
1117        if (want_obj.nr) {
1118                struct object_array have_obj = OBJECT_ARRAY_INIT;
1119                get_common_commits(&reader, &have_obj, &want_obj);
1120                create_pack_file(&have_obj, &want_obj);
1121        }
1122}
1123
1124struct upload_pack_data {
1125        struct object_array wants;
1126        struct string_list wanted_refs;
1127        struct oid_array haves;
1128
1129        struct object_array shallows;
1130        struct string_list deepen_not;
1131        int depth;
1132        timestamp_t deepen_since;
1133        int deepen_rev_list;
1134        int deepen_relative;
1135
1136        struct packet_writer writer;
1137
1138        unsigned stateless_rpc : 1;
1139
1140        unsigned use_thin_pack : 1;
1141        unsigned use_ofs_delta : 1;
1142        unsigned no_progress : 1;
1143        unsigned use_include_tag : 1;
1144        unsigned done : 1;
1145};
1146
1147static void upload_pack_data_init(struct upload_pack_data *data)
1148{
1149        struct object_array wants = OBJECT_ARRAY_INIT;
1150        struct string_list wanted_refs = STRING_LIST_INIT_DUP;
1151        struct oid_array haves = OID_ARRAY_INIT;
1152        struct object_array shallows = OBJECT_ARRAY_INIT;
1153        struct string_list deepen_not = STRING_LIST_INIT_DUP;
1154
1155        memset(data, 0, sizeof(*data));
1156        data->wants = wants;
1157        data->wanted_refs = wanted_refs;
1158        data->haves = haves;
1159        data->shallows = shallows;
1160        data->deepen_not = deepen_not;
1161        packet_writer_init(&data->writer, 1);
1162}
1163
1164static void upload_pack_data_clear(struct upload_pack_data *data)
1165{
1166        object_array_clear(&data->wants);
1167        string_list_clear(&data->wanted_refs, 1);
1168        oid_array_clear(&data->haves);
1169        object_array_clear(&data->shallows);
1170        string_list_clear(&data->deepen_not, 0);
1171}
1172
1173static int parse_want(struct packet_writer *writer, const char *line,
1174                      struct object_array *want_obj)
1175{
1176        const char *arg;
1177        if (skip_prefix(line, "want ", &arg)) {
1178                struct object_id oid;
1179                struct object *o;
1180
1181                if (get_oid_hex(arg, &oid))
1182                        die("git upload-pack: protocol error, "
1183                            "expected to get oid, not '%s'", line);
1184
1185                o = parse_object(the_repository, &oid);
1186                if (!o) {
1187                        packet_writer_error(writer,
1188                                            "upload-pack: not our ref %s",
1189                                            oid_to_hex(&oid));
1190                        die("git upload-pack: not our ref %s",
1191                            oid_to_hex(&oid));
1192                }
1193
1194                if (!(o->flags & WANTED)) {
1195                        o->flags |= WANTED;
1196                        add_object_array(o, NULL, want_obj);
1197                }
1198
1199                return 1;
1200        }
1201
1202        return 0;
1203}
1204
1205static int parse_want_ref(struct packet_writer *writer, const char *line,
1206                          struct string_list *wanted_refs,
1207                          struct object_array *want_obj)
1208{
1209        const char *arg;
1210        if (skip_prefix(line, "want-ref ", &arg)) {
1211                struct object_id oid;
1212                struct string_list_item *item;
1213                struct object *o;
1214
1215                if (read_ref(arg, &oid)) {
1216                        packet_writer_error(writer, "unknown ref %s", arg);
1217                        die("unknown ref %s", arg);
1218                }
1219
1220                item = string_list_append(wanted_refs, arg);
1221                item->util = oiddup(&oid);
1222
1223                o = parse_object_or_die(&oid, arg);
1224                if (!(o->flags & WANTED)) {
1225                        o->flags |= WANTED;
1226                        add_object_array(o, NULL, want_obj);
1227                }
1228
1229                return 1;
1230        }
1231
1232        return 0;
1233}
1234
1235static int parse_have(const char *line, struct oid_array *haves)
1236{
1237        const char *arg;
1238        if (skip_prefix(line, "have ", &arg)) {
1239                struct object_id oid;
1240
1241                if (get_oid_hex(arg, &oid))
1242                        die("git upload-pack: expected SHA1 object, got '%s'", arg);
1243                oid_array_append(haves, &oid);
1244                return 1;
1245        }
1246
1247        return 0;
1248}
1249
1250static void process_args(struct packet_reader *request,
1251                         struct upload_pack_data *data,
1252                         struct object_array *want_obj)
1253{
1254        while (packet_reader_read(request) != PACKET_READ_FLUSH) {
1255                const char *arg = request->line;
1256                const char *p;
1257
1258                /* process want */
1259                if (parse_want(&data->writer, arg, want_obj))
1260                        continue;
1261                if (allow_ref_in_want &&
1262                    parse_want_ref(&data->writer, arg, &data->wanted_refs,
1263                                   want_obj))
1264                        continue;
1265                /* process have line */
1266                if (parse_have(arg, &data->haves))
1267                        continue;
1268
1269                /* process args like thin-pack */
1270                if (!strcmp(arg, "thin-pack")) {
1271                        use_thin_pack = 1;
1272                        continue;
1273                }
1274                if (!strcmp(arg, "ofs-delta")) {
1275                        use_ofs_delta = 1;
1276                        continue;
1277                }
1278                if (!strcmp(arg, "no-progress")) {
1279                        no_progress = 1;
1280                        continue;
1281                }
1282                if (!strcmp(arg, "include-tag")) {
1283                        use_include_tag = 1;
1284                        continue;
1285                }
1286                if (!strcmp(arg, "done")) {
1287                        data->done = 1;
1288                        continue;
1289                }
1290
1291                /* Shallow related arguments */
1292                if (process_shallow(arg, &data->shallows))
1293                        continue;
1294                if (process_deepen(arg, &data->depth))
1295                        continue;
1296                if (process_deepen_since(arg, &data->deepen_since,
1297                                         &data->deepen_rev_list))
1298                        continue;
1299                if (process_deepen_not(arg, &data->deepen_not,
1300                                       &data->deepen_rev_list))
1301                        continue;
1302                if (!strcmp(arg, "deepen-relative")) {
1303                        data->deepen_relative = 1;
1304                        continue;
1305                }
1306
1307                if (allow_filter && skip_prefix(arg, "filter ", &p)) {
1308                        list_objects_filter_die_if_populated(&filter_options);
1309                        parse_list_objects_filter(&filter_options, p);
1310                        continue;
1311                }
1312
1313                if ((git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) ||
1314                     allow_sideband_all) &&
1315                    !strcmp(arg, "sideband-all")) {
1316                        data->writer.use_sideband = 1;
1317                        continue;
1318                }
1319
1320                /* ignore unknown lines maybe? */
1321                die("unexpected line: '%s'", arg);
1322        }
1323}
1324
1325static int process_haves(struct oid_array *haves, struct oid_array *common,
1326                         struct object_array *have_obj)
1327{
1328        int i;
1329
1330        /* Process haves */
1331        for (i = 0; i < haves->nr; i++) {
1332                const struct object_id *oid = &haves->oid[i];
1333                struct object *o;
1334                int we_knew_they_have = 0;
1335
1336                if (!has_object_file(oid))
1337                        continue;
1338
1339                oid_array_append(common, oid);
1340
1341                o = parse_object(the_repository, oid);
1342                if (!o)
1343                        die("oops (%s)", oid_to_hex(oid));
1344                if (o->type == OBJ_COMMIT) {
1345                        struct commit_list *parents;
1346                        struct commit *commit = (struct commit *)o;
1347                        if (o->flags & THEY_HAVE)
1348                                we_knew_they_have = 1;
1349                        else
1350                                o->flags |= THEY_HAVE;
1351                        if (!oldest_have || (commit->date < oldest_have))
1352                                oldest_have = commit->date;
1353                        for (parents = commit->parents;
1354                             parents;
1355                             parents = parents->next)
1356                                parents->item->object.flags |= THEY_HAVE;
1357                }
1358                if (!we_knew_they_have)
1359                        add_object_array(o, NULL, have_obj);
1360        }
1361
1362        return 0;
1363}
1364
1365static int send_acks(struct packet_writer *writer, struct oid_array *acks,
1366                     const struct object_array *have_obj,
1367                     struct object_array *want_obj)
1368{
1369        int i;
1370
1371        packet_writer_write(writer, "acknowledgments\n");
1372
1373        /* Send Acks */
1374        if (!acks->nr)
1375                packet_writer_write(writer, "NAK\n");
1376
1377        for (i = 0; i < acks->nr; i++) {
1378                packet_writer_write(writer, "ACK %s\n",
1379                                    oid_to_hex(&acks->oid[i]));
1380        }
1381
1382        if (ok_to_give_up(have_obj, want_obj)) {
1383                /* Send Ready */
1384                packet_writer_write(writer, "ready\n");
1385                return 1;
1386        }
1387
1388        return 0;
1389}
1390
1391static int process_haves_and_send_acks(struct upload_pack_data *data,
1392                                       struct object_array *have_obj,
1393                                       struct object_array *want_obj)
1394{
1395        struct oid_array common = OID_ARRAY_INIT;
1396        int ret = 0;
1397
1398        process_haves(&data->haves, &common, have_obj);
1399        if (data->done) {
1400                ret = 1;
1401        } else if (send_acks(&data->writer, &common, have_obj, want_obj)) {
1402                packet_writer_delim(&data->writer);
1403                ret = 1;
1404        } else {
1405                /* Add Flush */
1406                packet_writer_flush(&data->writer);
1407                ret = 0;
1408        }
1409
1410        oid_array_clear(&data->haves);
1411        oid_array_clear(&common);
1412        return ret;
1413}
1414
1415static void send_wanted_ref_info(struct upload_pack_data *data)
1416{
1417        const struct string_list_item *item;
1418
1419        if (!data->wanted_refs.nr)
1420                return;
1421
1422        packet_writer_write(&data->writer, "wanted-refs\n");
1423
1424        for_each_string_list_item(item, &data->wanted_refs) {
1425                packet_writer_write(&data->writer, "%s %s\n",
1426                                    oid_to_hex(item->util),
1427                                    item->string);
1428        }
1429
1430        packet_writer_delim(&data->writer);
1431}
1432
1433static void send_shallow_info(struct upload_pack_data *data,
1434                              struct object_array *want_obj)
1435{
1436        /* No shallow info needs to be sent */
1437        if (!data->depth && !data->deepen_rev_list && !data->shallows.nr &&
1438            !is_repository_shallow(the_repository))
1439                return;
1440
1441        packet_writer_write(&data->writer, "shallow-info\n");
1442
1443        if (!send_shallow_list(&data->writer, data->depth,
1444                               data->deepen_rev_list,
1445                               data->deepen_since, &data->deepen_not,
1446                               data->deepen_relative,
1447                               &data->shallows, want_obj) &&
1448            is_repository_shallow(the_repository))
1449                deepen(&data->writer, INFINITE_DEPTH, data->deepen_relative,
1450                       &data->shallows, want_obj);
1451
1452        packet_delim(1);
1453}
1454
1455enum fetch_state {
1456        FETCH_PROCESS_ARGS = 0,
1457        FETCH_SEND_ACKS,
1458        FETCH_SEND_PACK,
1459        FETCH_DONE,
1460};
1461
1462int upload_pack_v2(struct repository *r, struct argv_array *keys,
1463                   struct packet_reader *request)
1464{
1465        enum fetch_state state = FETCH_PROCESS_ARGS;
1466        struct upload_pack_data data;
1467        struct object_array have_obj = OBJECT_ARRAY_INIT;
1468        struct object_array want_obj = OBJECT_ARRAY_INIT;
1469
1470        clear_object_flags(ALL_FLAGS);
1471
1472        git_config(upload_pack_config, NULL);
1473
1474        upload_pack_data_init(&data);
1475        use_sideband = LARGE_PACKET_MAX;
1476
1477        while (state != FETCH_DONE) {
1478                switch (state) {
1479                case FETCH_PROCESS_ARGS:
1480                        process_args(request, &data, &want_obj);
1481
1482                        if (!want_obj.nr) {
1483                                /*
1484                                 * Request didn't contain any 'want' lines,
1485                                 * guess they didn't want anything.
1486                                 */
1487                                state = FETCH_DONE;
1488                        } else if (data.haves.nr) {
1489                                /*
1490                                 * Request had 'have' lines, so lets ACK them.
1491                                 */
1492                                state = FETCH_SEND_ACKS;
1493                        } else {
1494                                /*
1495                                 * Request had 'want's but no 'have's so we can
1496                                 * immedietly go to construct and send a pack.
1497                                 */
1498                                state = FETCH_SEND_PACK;
1499                        }
1500                        break;
1501                case FETCH_SEND_ACKS:
1502                        if (process_haves_and_send_acks(&data, &have_obj,
1503                                                        &want_obj))
1504                                state = FETCH_SEND_PACK;
1505                        else
1506                                state = FETCH_DONE;
1507                        break;
1508                case FETCH_SEND_PACK:
1509                        send_wanted_ref_info(&data);
1510                        send_shallow_info(&data, &want_obj);
1511
1512                        packet_writer_write(&data.writer, "packfile\n");
1513                        create_pack_file(&have_obj, &want_obj);
1514                        state = FETCH_DONE;
1515                        break;
1516                case FETCH_DONE:
1517                        continue;
1518                }
1519        }
1520
1521        upload_pack_data_clear(&data);
1522        object_array_clear(&have_obj);
1523        object_array_clear(&want_obj);
1524        return 0;
1525}
1526
1527int upload_pack_advertise(struct repository *r,
1528                          struct strbuf *value)
1529{
1530        if (value) {
1531                int allow_filter_value;
1532                int allow_ref_in_want;
1533                int allow_sideband_all_value;
1534
1535                strbuf_addstr(value, "shallow");
1536
1537                if (!repo_config_get_bool(the_repository,
1538                                         "uploadpack.allowfilter",
1539                                         &allow_filter_value) &&
1540                    allow_filter_value)
1541                        strbuf_addstr(value, " filter");
1542
1543                if (!repo_config_get_bool(the_repository,
1544                                         "uploadpack.allowrefinwant",
1545                                         &allow_ref_in_want) &&
1546                    allow_ref_in_want)
1547                        strbuf_addstr(value, " ref-in-want");
1548
1549                if (git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) ||
1550                    (!repo_config_get_bool(the_repository,
1551                                           "uploadpack.allowsidebandall",
1552                                           &allow_sideband_all_value) &&
1553                     allow_sideband_all_value))
1554                        strbuf_addstr(value, " sideband-all");
1555        }
1556
1557        return 1;
1558}