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