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