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