fetch-pack.con commit Shrink "struct object" a bit (885a86a)
   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 = NULL;
  28static int non_common_revs = 0, multi_ack = 0, use_thin_pack = 0;
  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 == TYPE_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                packet_write(fd[1], "want %s%s%s\n", sha1_to_hex(remote),
 169                             (multi_ack ? " multi_ack" : ""),
 170                             (use_thin_pack ? " thin-pack" : ""));
 171                fetching++;
 172        }
 173        packet_flush(fd[1]);
 174        if (!fetching)
 175                return 1;
 176
 177        flushes = 0;
 178        retval = -1;
 179        while ((sha1 = get_rev())) {
 180                packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
 181                if (verbose)
 182                        fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
 183                in_vain++;
 184                if (!(31 & ++count)) {
 185                        int ack;
 186
 187                        packet_flush(fd[1]);
 188                        flushes++;
 189
 190                        /*
 191                         * We keep one window "ahead" of the other side, and
 192                         * will wait for an ACK only on the next one
 193                         */
 194                        if (count == 32)
 195                                continue;
 196
 197                        do {
 198                                ack = get_ack(fd[0], result_sha1);
 199                                if (verbose && ack)
 200                                        fprintf(stderr, "got ack %d %s\n", ack,
 201                                                        sha1_to_hex(result_sha1));
 202                                if (ack == 1) {
 203                                        flushes = 0;
 204                                        multi_ack = 0;
 205                                        retval = 0;
 206                                        goto done;
 207                                } else if (ack == 2) {
 208                                        struct commit *commit =
 209                                                lookup_commit(result_sha1);
 210                                        mark_common(commit, 0, 1);
 211                                        retval = 0;
 212                                        in_vain = 0;
 213                                        got_continue = 1;
 214                                }
 215                        } while (ack);
 216                        flushes--;
 217                        if (got_continue && MAX_IN_VAIN < in_vain) {
 218                                if (verbose)
 219                                        fprintf(stderr, "giving up\n");
 220                                break; /* give up */
 221                        }
 222                }
 223        }
 224done:
 225        packet_write(fd[1], "done\n");
 226        if (verbose)
 227                fprintf(stderr, "done\n");
 228        if (retval != 0) {
 229                multi_ack = 0;
 230                flushes++;
 231        }
 232        while (flushes || multi_ack) {
 233                int ack = get_ack(fd[0], result_sha1);
 234                if (ack) {
 235                        if (verbose)
 236                                fprintf(stderr, "got ack (%d) %s\n", ack,
 237                                        sha1_to_hex(result_sha1));
 238                        if (ack == 1)
 239                                return 0;
 240                        multi_ack = 1;
 241                        continue;
 242                }
 243                flushes--;
 244        }
 245        return retval;
 246}
 247
 248static struct commit_list *complete = NULL;
 249
 250static int mark_complete(const char *path, const unsigned char *sha1)
 251{
 252        struct object *o = parse_object(sha1);
 253
 254        while (o && o->type == TYPE_TAG) {
 255                struct tag *t = (struct tag *) o;
 256                if (!t->tagged)
 257                        break; /* broken repository */
 258                o->flags |= COMPLETE;
 259                o = parse_object(t->tagged->sha1);
 260        }
 261        if (o && o->type == TYPE_COMMIT) {
 262                struct commit *commit = (struct commit *)o;
 263                commit->object.flags |= COMPLETE;
 264                insert_by_date(commit, &complete);
 265        }
 266        return 0;
 267}
 268
 269static void mark_recent_complete_commits(unsigned long cutoff)
 270{
 271        while (complete && cutoff <= complete->item->date) {
 272                if (verbose)
 273                        fprintf(stderr, "Marking %s as complete\n",
 274                                sha1_to_hex(complete->item->object.sha1));
 275                pop_most_recent_commit(&complete, COMPLETE);
 276        }
 277}
 278
 279static void filter_refs(struct ref **refs, int nr_match, char **match)
 280{
 281        struct ref **return_refs;
 282        struct ref *newlist = NULL;
 283        struct ref **newtail = &newlist;
 284        struct ref *ref, *next;
 285        struct ref *fastarray[32];
 286
 287        if (nr_match && !fetch_all) {
 288                if (ARRAY_SIZE(fastarray) < nr_match)
 289                        return_refs = xcalloc(nr_match, sizeof(struct ref *));
 290                else {
 291                        return_refs = fastarray;
 292                        memset(return_refs, 0, sizeof(struct ref *) * nr_match);
 293                }
 294        }
 295        else
 296                return_refs = NULL;
 297
 298        for (ref = *refs; ref; ref = next) {
 299                next = ref->next;
 300                if (!memcmp(ref->name, "refs/", 5) &&
 301                    check_ref_format(ref->name + 5))
 302                        ; /* trash */
 303                else if (fetch_all) {
 304                        *newtail = ref;
 305                        ref->next = NULL;
 306                        newtail = &ref->next;
 307                        continue;
 308                }
 309                else {
 310                        int order = path_match(ref->name, nr_match, match);
 311                        if (order) {
 312                                return_refs[order-1] = ref;
 313                                continue; /* we will link it later */
 314                        }
 315                }
 316                free(ref);
 317        }
 318
 319        if (!fetch_all) {
 320                int i;
 321                for (i = 0; i < nr_match; i++) {
 322                        ref = return_refs[i];
 323                        if (ref) {
 324                                *newtail = ref;
 325                                ref->next = NULL;
 326                                newtail = &ref->next;
 327                        }
 328                }
 329                if (return_refs != fastarray)
 330                        free(return_refs);
 331        }
 332        *refs = newlist;
 333}
 334
 335static int everything_local(struct ref **refs, int nr_match, char **match)
 336{
 337        struct ref *ref;
 338        int retval;
 339        unsigned long cutoff = 0;
 340
 341        track_object_refs = 0;
 342        save_commit_buffer = 0;
 343
 344        for (ref = *refs; ref; ref = ref->next) {
 345                struct object *o;
 346
 347                o = parse_object(ref->old_sha1);
 348                if (!o)
 349                        continue;
 350
 351                /* We already have it -- which may mean that we were
 352                 * in sync with the other side at some time after
 353                 * that (it is OK if we guess wrong here).
 354                 */
 355                if (o->type == TYPE_COMMIT) {
 356                        struct commit *commit = (struct commit *)o;
 357                        if (!cutoff || cutoff < commit->date)
 358                                cutoff = commit->date;
 359                }
 360        }
 361
 362        for_each_ref(mark_complete);
 363        if (cutoff)
 364                mark_recent_complete_commits(cutoff);
 365
 366        /*
 367         * Mark all complete remote refs as common refs.
 368         * Don't mark them common yet; the server has to be told so first.
 369         */
 370        for (ref = *refs; ref; ref = ref->next) {
 371                struct object *o = deref_tag(lookup_object(ref->old_sha1),
 372                                             NULL, 0);
 373
 374                if (!o || o->type != TYPE_COMMIT || !(o->flags & COMPLETE))
 375                        continue;
 376
 377                if (!(o->flags & SEEN)) {
 378                        rev_list_push((struct commit *)o, COMMON_REF | SEEN);
 379
 380                        mark_common((struct commit *)o, 1, 1);
 381                }
 382        }
 383
 384        filter_refs(refs, nr_match, match);
 385
 386        for (retval = 1, ref = *refs; ref ; ref = ref->next) {
 387                const unsigned char *remote = ref->old_sha1;
 388                unsigned char local[20];
 389                struct object *o;
 390
 391                o = lookup_object(remote);
 392                if (!o || !(o->flags & COMPLETE)) {
 393                        retval = 0;
 394                        if (!verbose)
 395                                continue;
 396                        fprintf(stderr,
 397                                "want %s (%s)\n", sha1_to_hex(remote),
 398                                ref->name);
 399                        continue;
 400                }
 401
 402                memcpy(ref->new_sha1, local, 20);
 403                if (!verbose)
 404                        continue;
 405                fprintf(stderr,
 406                        "already have %s (%s)\n", sha1_to_hex(remote),
 407                        ref->name);
 408        }
 409        return retval;
 410}
 411
 412static int fetch_pack(int fd[2], int nr_match, char **match)
 413{
 414        struct ref *ref;
 415        unsigned char sha1[20];
 416        int status;
 417
 418        get_remote_heads(fd[0], &ref, 0, NULL, 0);
 419        if (server_supports("multi_ack")) {
 420                if (verbose)
 421                        fprintf(stderr, "Server supports multi_ack\n");
 422                multi_ack = 1;
 423        }
 424        if (!ref) {
 425                packet_flush(fd[1]);
 426                die("no matching remote head");
 427        }
 428        if (everything_local(&ref, nr_match, match)) {
 429                packet_flush(fd[1]);
 430                goto all_done;
 431        }
 432        if (find_common(fd, sha1, ref) < 0)
 433                if (!keep_pack)
 434                        /* When cloning, it is not unusual to have
 435                         * no common commit.
 436                         */
 437                        fprintf(stderr, "warning: no common commits\n");
 438
 439        if (keep_pack)
 440                status = receive_keep_pack(fd, "git-fetch-pack", quiet);
 441        else
 442                status = receive_unpack_pack(fd, "git-fetch-pack", quiet);
 443
 444        if (status)
 445                die("git-fetch-pack: fetch failed.");
 446
 447 all_done:
 448        while (ref) {
 449                printf("%s %s\n",
 450                       sha1_to_hex(ref->old_sha1), ref->name);
 451                ref = ref->next;
 452        }
 453        return 0;
 454}
 455
 456int main(int argc, char **argv)
 457{
 458        int i, ret, nr_heads;
 459        char *dest = NULL, **heads;
 460        int fd[2];
 461        pid_t pid;
 462
 463        setup_git_directory();
 464
 465        nr_heads = 0;
 466        heads = NULL;
 467        for (i = 1; i < argc; i++) {
 468                char *arg = argv[i];
 469
 470                if (*arg == '-') {
 471                        if (!strncmp("--exec=", arg, 7)) {
 472                                exec = arg + 7;
 473                                continue;
 474                        }
 475                        if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
 476                                quiet = 1;
 477                                continue;
 478                        }
 479                        if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
 480                                keep_pack = 1;
 481                                continue;
 482                        }
 483                        if (!strcmp("--thin", arg)) {
 484                                use_thin_pack = 1;
 485                                continue;
 486                        }
 487                        if (!strcmp("--all", arg)) {
 488                                fetch_all = 1;
 489                                continue;
 490                        }
 491                        if (!strcmp("-v", arg)) {
 492                                verbose = 1;
 493                                continue;
 494                        }
 495                        usage(fetch_pack_usage);
 496                }
 497                dest = arg;
 498                heads = argv + i + 1;
 499                nr_heads = argc - i - 1;
 500                break;
 501        }
 502        if (!dest)
 503                usage(fetch_pack_usage);
 504        if (keep_pack)
 505                use_thin_pack = 0;
 506        pid = git_connect(fd, dest, exec);
 507        if (pid < 0)
 508                return 1;
 509        ret = fetch_pack(fd, nr_heads, heads);
 510        close(fd[0]);
 511        close(fd[1]);
 512        finish_connect(pid);
 513
 514        if (!ret && nr_heads) {
 515                /* If the heads to pull were given, we should have
 516                 * consumed all of them by matching the remote.
 517                 * Otherwise, 'git-fetch remote no-such-ref' would
 518                 * silently succeed without issuing an error.
 519                 */
 520                for (i = 0; i < nr_heads; i++)
 521                        if (heads[i] && heads[i][0]) {
 522                                error("no such remote ref %s", heads[i]);
 523                                ret = 1;
 524                        }
 525        }
 526
 527        return ret;
 528}