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