fetch-pack.con commit git-pickaxe: tighten sanity checks. (ae86ad6)
   1#include "cache.h"
   2#include "refs.h"
   3#include "pkt-line.h"
   4#include "commit.h"
   5#include "tag.h"
   6
   7static int keep_pack;
   8static int quiet;
   9static int verbose;
  10static int fetch_all;
  11static const char fetch_pack_usage[] =
  12"git-fetch-pack [--all] [-q] [-v] [-k] [--thin] [--exec=upload-pack] [host:]directory <refs>...";
  13static const char *exec = "git-upload-pack";
  14
  15#define COMPLETE        (1U << 0)
  16#define COMMON          (1U << 1)
  17#define COMMON_REF      (1U << 2)
  18#define SEEN            (1U << 3)
  19#define POPPED          (1U << 4)
  20
  21/*
  22 * After sending this many "have"s if we do not get any new ACK , we
  23 * give up traversing our history.
  24 */
  25#define MAX_IN_VAIN 256
  26
  27static struct commit_list *rev_list;
  28static int non_common_revs, multi_ack, use_thin_pack, use_sideband;
  29
  30static void rev_list_push(struct commit *commit, int mark)
  31{
  32        if (!(commit->object.flags & mark)) {
  33                commit->object.flags |= mark;
  34
  35                if (!(commit->object.parsed))
  36                        parse_commit(commit);
  37
  38                insert_by_date(commit, &rev_list);
  39
  40                if (!(commit->object.flags & COMMON))
  41                        non_common_revs++;
  42        }
  43}
  44
  45static int rev_list_insert_ref(const char *path, const unsigned char *sha1)
  46{
  47        struct object *o = deref_tag(parse_object(sha1), path, 0);
  48
  49        if (o && o->type == OBJ_COMMIT)
  50                rev_list_push((struct commit *)o, SEEN);
  51
  52        return 0;
  53}
  54
  55/*
  56   This function marks a rev and its ancestors as common.
  57   In some cases, it is desirable to mark only the ancestors (for example
  58   when only the server does not yet know that they are common).
  59*/
  60
  61static void mark_common(struct commit *commit,
  62                int ancestors_only, int dont_parse)
  63{
  64        if (commit != NULL && !(commit->object.flags & COMMON)) {
  65                struct object *o = (struct object *)commit;
  66
  67                if (!ancestors_only)
  68                        o->flags |= COMMON;
  69
  70                if (!(o->flags & SEEN))
  71                        rev_list_push(commit, SEEN);
  72                else {
  73                        struct commit_list *parents;
  74
  75                        if (!ancestors_only && !(o->flags & POPPED))
  76                                non_common_revs--;
  77                        if (!o->parsed && !dont_parse)
  78                                parse_commit(commit);
  79
  80                        for (parents = commit->parents;
  81                                        parents;
  82                                        parents = parents->next)
  83                                mark_common(parents->item, 0, dont_parse);
  84                }
  85        }
  86}
  87
  88/*
  89  Get the next rev to send, ignoring the common.
  90*/
  91
  92static const unsigned char* get_rev(void)
  93{
  94        struct commit *commit = NULL;
  95
  96        while (commit == NULL) {
  97                unsigned int mark;
  98                struct commit_list* parents;
  99
 100                if (rev_list == NULL || non_common_revs == 0)
 101                        return NULL;
 102
 103                commit = rev_list->item;
 104                if (!(commit->object.parsed))
 105                        parse_commit(commit);
 106                commit->object.flags |= POPPED;
 107                if (!(commit->object.flags & COMMON))
 108                        non_common_revs--;
 109        
 110                parents = commit->parents;
 111
 112                if (commit->object.flags & COMMON) {
 113                        /* do not send "have", and ignore ancestors */
 114                        commit = NULL;
 115                        mark = COMMON | SEEN;
 116                } else if (commit->object.flags & COMMON_REF)
 117                        /* send "have", and ignore ancestors */
 118                        mark = COMMON | SEEN;
 119                else
 120                        /* send "have", also for its ancestors */
 121                        mark = SEEN;
 122
 123                while (parents) {
 124                        if (!(parents->item->object.flags & SEEN))
 125                                rev_list_push(parents->item, mark);
 126                        if (mark & COMMON)
 127                                mark_common(parents->item, 1, 0);
 128                        parents = parents->next;
 129                }
 130
 131                rev_list = rev_list->next;
 132        }
 133
 134        return commit->object.sha1;
 135}
 136
 137static int find_common(int fd[2], unsigned char *result_sha1,
 138                       struct ref *refs)
 139{
 140        int fetching;
 141        int count = 0, flushes = 0, retval;
 142        const unsigned char *sha1;
 143        unsigned in_vain = 0;
 144        int got_continue = 0;
 145
 146        for_each_ref(rev_list_insert_ref);
 147
 148        fetching = 0;
 149        for ( ; refs ; refs = refs->next) {
 150                unsigned char *remote = refs->old_sha1;
 151                struct object *o;
 152
 153                /*
 154                 * If that object is complete (i.e. it is an ancestor of a
 155                 * local ref), we tell them we have it but do not have to
 156                 * tell them about its ancestors, which they already know
 157                 * about.
 158                 *
 159                 * We use lookup_object here because we are only
 160                 * interested in the case we *know* the object is
 161                 * reachable and we have already scanned it.
 162                 */
 163                if (((o = lookup_object(remote)) != NULL) &&
 164                                (o->flags & COMPLETE)) {
 165                        continue;
 166                }
 167
 168                if (!fetching)
 169                        packet_write(fd[1], "want %s%s%s%s%s\n",
 170                                     sha1_to_hex(remote),
 171                                     (multi_ack ? " multi_ack" : ""),
 172                                     (use_sideband == 2 ? " side-band-64k" : ""),
 173                                     (use_sideband == 1 ? " side-band" : ""),
 174                                     (use_thin_pack ? " thin-pack" : ""));
 175                else
 176                        packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
 177                fetching++;
 178        }
 179        packet_flush(fd[1]);
 180        if (!fetching)
 181                return 1;
 182
 183        flushes = 0;
 184        retval = -1;
 185        while ((sha1 = get_rev())) {
 186                packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
 187                if (verbose)
 188                        fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
 189                in_vain++;
 190                if (!(31 & ++count)) {
 191                        int ack;
 192
 193                        packet_flush(fd[1]);
 194                        flushes++;
 195
 196                        /*
 197                         * We keep one window "ahead" of the other side, and
 198                         * will wait for an ACK only on the next one
 199                         */
 200                        if (count == 32)
 201                                continue;
 202
 203                        do {
 204                                ack = get_ack(fd[0], result_sha1);
 205                                if (verbose && ack)
 206                                        fprintf(stderr, "got ack %d %s\n", ack,
 207                                                        sha1_to_hex(result_sha1));
 208                                if (ack == 1) {
 209                                        flushes = 0;
 210                                        multi_ack = 0;
 211                                        retval = 0;
 212                                        goto done;
 213                                } else if (ack == 2) {
 214                                        struct commit *commit =
 215                                                lookup_commit(result_sha1);
 216                                        mark_common(commit, 0, 1);
 217                                        retval = 0;
 218                                        in_vain = 0;
 219                                        got_continue = 1;
 220                                }
 221                        } while (ack);
 222                        flushes--;
 223                        if (got_continue && MAX_IN_VAIN < in_vain) {
 224                                if (verbose)
 225                                        fprintf(stderr, "giving up\n");
 226                                break; /* give up */
 227                        }
 228                }
 229        }
 230done:
 231        packet_write(fd[1], "done\n");
 232        if (verbose)
 233                fprintf(stderr, "done\n");
 234        if (retval != 0) {
 235                multi_ack = 0;
 236                flushes++;
 237        }
 238        while (flushes || multi_ack) {
 239                int ack = get_ack(fd[0], result_sha1);
 240                if (ack) {
 241                        if (verbose)
 242                                fprintf(stderr, "got ack (%d) %s\n", ack,
 243                                        sha1_to_hex(result_sha1));
 244                        if (ack == 1)
 245                                return 0;
 246                        multi_ack = 1;
 247                        continue;
 248                }
 249                flushes--;
 250        }
 251        return retval;
 252}
 253
 254static struct commit_list *complete;
 255
 256static int mark_complete(const char *path, const unsigned char *sha1)
 257{
 258        struct object *o = parse_object(sha1);
 259
 260        while (o && o->type == OBJ_TAG) {
 261                struct tag *t = (struct tag *) o;
 262                if (!t->tagged)
 263                        break; /* broken repository */
 264                o->flags |= COMPLETE;
 265                o = parse_object(t->tagged->sha1);
 266        }
 267        if (o && o->type == OBJ_COMMIT) {
 268                struct commit *commit = (struct commit *)o;
 269                commit->object.flags |= COMPLETE;
 270                insert_by_date(commit, &complete);
 271        }
 272        return 0;
 273}
 274
 275static void mark_recent_complete_commits(unsigned long cutoff)
 276{
 277        while (complete && cutoff <= complete->item->date) {
 278                if (verbose)
 279                        fprintf(stderr, "Marking %s as complete\n",
 280                                sha1_to_hex(complete->item->object.sha1));
 281                pop_most_recent_commit(&complete, COMPLETE);
 282        }
 283}
 284
 285static void filter_refs(struct ref **refs, int nr_match, char **match)
 286{
 287        struct ref **return_refs;
 288        struct ref *newlist = NULL;
 289        struct ref **newtail = &newlist;
 290        struct ref *ref, *next;
 291        struct ref *fastarray[32];
 292
 293        if (nr_match && !fetch_all) {
 294                if (ARRAY_SIZE(fastarray) < nr_match)
 295                        return_refs = xcalloc(nr_match, sizeof(struct ref *));
 296                else {
 297                        return_refs = fastarray;
 298                        memset(return_refs, 0, sizeof(struct ref *) * nr_match);
 299                }
 300        }
 301        else
 302                return_refs = NULL;
 303
 304        for (ref = *refs; ref; ref = next) {
 305                next = ref->next;
 306                if (!memcmp(ref->name, "refs/", 5) &&
 307                    check_ref_format(ref->name + 5))
 308                        ; /* trash */
 309                else if (fetch_all) {
 310                        *newtail = ref;
 311                        ref->next = NULL;
 312                        newtail = &ref->next;
 313                        continue;
 314                }
 315                else {
 316                        int order = path_match(ref->name, nr_match, match);
 317                        if (order) {
 318                                return_refs[order-1] = ref;
 319                                continue; /* we will link it later */
 320                        }
 321                }
 322                free(ref);
 323        }
 324
 325        if (!fetch_all) {
 326                int i;
 327                for (i = 0; i < nr_match; i++) {
 328                        ref = return_refs[i];
 329                        if (ref) {
 330                                *newtail = ref;
 331                                ref->next = NULL;
 332                                newtail = &ref->next;
 333                        }
 334                }
 335                if (return_refs != fastarray)
 336                        free(return_refs);
 337        }
 338        *refs = newlist;
 339}
 340
 341static int everything_local(struct ref **refs, int nr_match, char **match)
 342{
 343        struct ref *ref;
 344        int retval;
 345        unsigned long cutoff = 0;
 346
 347        track_object_refs = 0;
 348        save_commit_buffer = 0;
 349
 350        for (ref = *refs; ref; ref = ref->next) {
 351                struct object *o;
 352
 353                o = parse_object(ref->old_sha1);
 354                if (!o)
 355                        continue;
 356
 357                /* We already have it -- which may mean that we were
 358                 * in sync with the other side at some time after
 359                 * that (it is OK if we guess wrong here).
 360                 */
 361                if (o->type == OBJ_COMMIT) {
 362                        struct commit *commit = (struct commit *)o;
 363                        if (!cutoff || cutoff < commit->date)
 364                                cutoff = commit->date;
 365                }
 366        }
 367
 368        for_each_ref(mark_complete);
 369        if (cutoff)
 370                mark_recent_complete_commits(cutoff);
 371
 372        /*
 373         * Mark all complete remote refs as common refs.
 374         * Don't mark them common yet; the server has to be told so first.
 375         */
 376        for (ref = *refs; ref; ref = ref->next) {
 377                struct object *o = deref_tag(lookup_object(ref->old_sha1),
 378                                             NULL, 0);
 379
 380                if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
 381                        continue;
 382
 383                if (!(o->flags & SEEN)) {
 384                        rev_list_push((struct commit *)o, COMMON_REF | SEEN);
 385
 386                        mark_common((struct commit *)o, 1, 1);
 387                }
 388        }
 389
 390        filter_refs(refs, nr_match, match);
 391
 392        for (retval = 1, ref = *refs; ref ; ref = ref->next) {
 393                const unsigned char *remote = ref->old_sha1;
 394                unsigned char local[20];
 395                struct object *o;
 396
 397                o = lookup_object(remote);
 398                if (!o || !(o->flags & COMPLETE)) {
 399                        retval = 0;
 400                        if (!verbose)
 401                                continue;
 402                        fprintf(stderr,
 403                                "want %s (%s)\n", sha1_to_hex(remote),
 404                                ref->name);
 405                        continue;
 406                }
 407
 408                hashcpy(ref->new_sha1, local);
 409                if (!verbose)
 410                        continue;
 411                fprintf(stderr,
 412                        "already have %s (%s)\n", sha1_to_hex(remote),
 413                        ref->name);
 414        }
 415        return retval;
 416}
 417
 418static int fetch_pack(int fd[2], int nr_match, char **match)
 419{
 420        struct ref *ref;
 421        unsigned char sha1[20];
 422        int status;
 423
 424        get_remote_heads(fd[0], &ref, 0, NULL, 0);
 425        if (server_supports("multi_ack")) {
 426                if (verbose)
 427                        fprintf(stderr, "Server supports multi_ack\n");
 428                multi_ack = 1;
 429        }
 430        if (server_supports("side-band-64k")) {
 431                if (verbose)
 432                        fprintf(stderr, "Server supports side-band-64k\n");
 433                use_sideband = 2;
 434        }
 435        else if (server_supports("side-band")) {
 436                if (verbose)
 437                        fprintf(stderr, "Server supports side-band\n");
 438                use_sideband = 1;
 439        }
 440        if (!ref) {
 441                packet_flush(fd[1]);
 442                die("no matching remote head");
 443        }
 444        if (everything_local(&ref, nr_match, match)) {
 445                packet_flush(fd[1]);
 446                goto all_done;
 447        }
 448        if (find_common(fd, sha1, ref) < 0)
 449                if (!keep_pack)
 450                        /* When cloning, it is not unusual to have
 451                         * no common commit.
 452                         */
 453                        fprintf(stderr, "warning: no common commits\n");
 454
 455        if (keep_pack)
 456                status = receive_keep_pack(fd, "git-fetch-pack", quiet, use_sideband);
 457        else
 458                status = receive_unpack_pack(fd, "git-fetch-pack", quiet, use_sideband);
 459
 460        if (status)
 461                die("git-fetch-pack: fetch failed.");
 462
 463 all_done:
 464        while (ref) {
 465                printf("%s %s\n",
 466                       sha1_to_hex(ref->old_sha1), ref->name);
 467                ref = ref->next;
 468        }
 469        return 0;
 470}
 471
 472int main(int argc, char **argv)
 473{
 474        int i, ret, nr_heads;
 475        char *dest = NULL, **heads;
 476        int fd[2];
 477        pid_t pid;
 478
 479        setup_git_directory();
 480
 481        nr_heads = 0;
 482        heads = NULL;
 483        for (i = 1; i < argc; i++) {
 484                char *arg = argv[i];
 485
 486                if (*arg == '-') {
 487                        if (!strncmp("--exec=", arg, 7)) {
 488                                exec = arg + 7;
 489                                continue;
 490                        }
 491                        if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
 492                                quiet = 1;
 493                                continue;
 494                        }
 495                        if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
 496                                keep_pack = 1;
 497                                continue;
 498                        }
 499                        if (!strcmp("--thin", arg)) {
 500                                use_thin_pack = 1;
 501                                continue;
 502                        }
 503                        if (!strcmp("--all", arg)) {
 504                                fetch_all = 1;
 505                                continue;
 506                        }
 507                        if (!strcmp("-v", arg)) {
 508                                verbose = 1;
 509                                continue;
 510                        }
 511                        usage(fetch_pack_usage);
 512                }
 513                dest = arg;
 514                heads = argv + i + 1;
 515                nr_heads = argc - i - 1;
 516                break;
 517        }
 518        if (!dest)
 519                usage(fetch_pack_usage);
 520        if (keep_pack)
 521                use_thin_pack = 0;
 522        pid = git_connect(fd, dest, exec);
 523        if (pid < 0)
 524                return 1;
 525        ret = fetch_pack(fd, nr_heads, heads);
 526        close(fd[0]);
 527        close(fd[1]);
 528        ret |= finish_connect(pid);
 529
 530        if (!ret && nr_heads) {
 531                /* If the heads to pull were given, we should have
 532                 * consumed all of them by matching the remote.
 533                 * Otherwise, 'git-fetch remote no-such-ref' would
 534                 * silently succeed without issuing an error.
 535                 */
 536                for (i = 0; i < nr_heads; i++)
 537                        if (heads[i] && heads[i][0]) {
 538                                error("no such remote ref %s", heads[i]);
 539                                ret = 1;
 540                        }
 541        }
 542
 543        return !!ret;
 544}