fetch-pack.con commit Make git-repack use git-pack-intersect. (b4ad355)
   1#include "cache.h"
   2#include "refs.h"
   3#include "pkt-line.h"
   4#include "commit.h"
   5#include "tag.h"
   6#include <time.h>
   7#include <sys/wait.h>
   8
   9static int quiet;
  10static int verbose;
  11static const char fetch_pack_usage[] =
  12"git-fetch-pack [-q] [-v] [--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;
  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()
  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\n", sha1_to_hex(remote),
 161                        multi_ack ? " multi_ack" : "");
 162                fetching++;
 163        }
 164        packet_flush(fd[1]);
 165        if (!fetching)
 166                return 1;
 167
 168        flushes = 0;
 169        retval = -1;
 170        while ((sha1 = get_rev())) {
 171                packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
 172                if (verbose)
 173                        fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
 174                if (!(31 & ++count)) {
 175                        int ack;
 176
 177                        packet_flush(fd[1]);
 178                        flushes++;
 179
 180                        /*
 181                         * We keep one window "ahead" of the other side, and
 182                         * will wait for an ACK only on the next one
 183                         */
 184                        if (count == 32)
 185                                continue;
 186
 187                        do {
 188                                ack = get_ack(fd[0], result_sha1);
 189                                if (verbose && ack)
 190                                        fprintf(stderr, "got ack %d %s\n", ack,
 191                                                        sha1_to_hex(result_sha1));
 192                                if (ack == 1) {
 193                                        flushes = 0;
 194                                        multi_ack = 0;
 195                                        retval = 0;
 196                                        goto done;
 197                                } else if (ack == 2) {
 198                                        struct commit *commit =
 199                                                lookup_commit(result_sha1);
 200                                        mark_common(commit, 0, 1);
 201                                        retval = 0;
 202                                }
 203                        } while (ack);
 204                        flushes--;
 205                }
 206        }
 207done:
 208        packet_write(fd[1], "done\n");
 209        if (verbose)
 210                fprintf(stderr, "done\n");
 211        if (retval != 0) {
 212                multi_ack = 0;
 213                flushes++;
 214        }
 215        while (flushes || multi_ack) {
 216                int ack = get_ack(fd[0], result_sha1);
 217                if (ack) {
 218                        if (verbose)
 219                                fprintf(stderr, "got ack (%d) %s\n", ack,
 220                                        sha1_to_hex(result_sha1));
 221                        if (ack == 1)
 222                                return 0;
 223                        multi_ack = 1;
 224                        continue;
 225                }
 226                flushes--;
 227        }
 228        return retval;
 229}
 230
 231static struct commit_list *complete = NULL;
 232
 233static int mark_complete(const char *path, const unsigned char *sha1)
 234{
 235        struct object *o = parse_object(sha1);
 236
 237        while (o && o->type == tag_type) {
 238                struct tag *t = (struct tag *) o;
 239                if (!t->tagged)
 240                        break; /* broken repository */
 241                o->flags |= COMPLETE;
 242                o = parse_object(t->tagged->sha1);
 243        }
 244        if (o && o->type == commit_type) {
 245                struct commit *commit = (struct commit *)o;
 246                commit->object.flags |= COMPLETE;
 247                insert_by_date(commit, &complete);
 248        }
 249        return 0;
 250}
 251
 252static void mark_recent_complete_commits(unsigned long cutoff)
 253{
 254        while (complete && cutoff <= complete->item->date) {
 255                if (verbose)
 256                        fprintf(stderr, "Marking %s as complete\n",
 257                                sha1_to_hex(complete->item->object.sha1));
 258                pop_most_recent_commit(&complete, COMPLETE);
 259        }
 260}
 261
 262static void filter_refs(struct ref **refs, int nr_match, char **match)
 263{
 264        struct ref *prev, *current, *next;
 265
 266        if (!nr_match)
 267                return;
 268
 269        for (prev = NULL, current = *refs; current; current = next) {
 270                next = current->next;
 271                if ((!memcmp(current->name, "refs/", 5) &&
 272                                        check_ref_format(current->name + 5)) ||
 273                                !path_match(current->name, nr_match, match)) {
 274                        if (prev == NULL)
 275                                *refs = next;
 276                        else
 277                                prev->next = next;
 278                        free(current);
 279                } else
 280                        prev = current;
 281        }
 282}
 283
 284static int everything_local(struct ref **refs, int nr_match, char **match)
 285{
 286        struct ref *ref;
 287        int retval;
 288        unsigned long cutoff = 0;
 289
 290        track_object_refs = 0;
 291        save_commit_buffer = 0;
 292
 293        for (ref = *refs; ref; ref = ref->next) {
 294                struct object *o;
 295
 296                o = parse_object(ref->old_sha1);
 297                if (!o)
 298                        continue;
 299
 300                /* We already have it -- which may mean that we were
 301                 * in sync with the other side at some time after
 302                 * that (it is OK if we guess wrong here).
 303                 */
 304                if (o->type == commit_type) {
 305                        struct commit *commit = (struct commit *)o;
 306                        if (!cutoff || cutoff < commit->date)
 307                                cutoff = commit->date;
 308                }
 309        }
 310
 311        for_each_ref(mark_complete);
 312        if (cutoff)
 313                mark_recent_complete_commits(cutoff);
 314
 315        /*
 316         * Mark all complete remote refs as common refs.
 317         * Don't mark them common yet; the server has to be told so first.
 318         */
 319        for (ref = *refs; ref; ref = ref->next) {
 320                struct object *o = deref_tag(lookup_object(ref->old_sha1),
 321                                             NULL, 0);
 322
 323                if (!o || o->type != commit_type || !(o->flags & COMPLETE))
 324                        continue;
 325
 326                if (!(o->flags & SEEN)) {
 327                        rev_list_push((struct commit *)o, COMMON_REF | SEEN);
 328
 329                        mark_common((struct commit *)o, 1, 1);
 330                }
 331        }
 332
 333        filter_refs(refs, nr_match, match);
 334
 335        for (retval = 1, ref = *refs; ref ; ref = ref->next) {
 336                const unsigned char *remote = ref->old_sha1;
 337                unsigned char local[20];
 338                struct object *o;
 339
 340                o = lookup_object(remote);
 341                if (!o || !(o->flags & COMPLETE)) {
 342                        retval = 0;
 343                        if (!verbose)
 344                                continue;
 345                        fprintf(stderr,
 346                                "want %s (%s)\n", sha1_to_hex(remote),
 347                                ref->name);
 348                        continue;
 349                }
 350
 351                memcpy(ref->new_sha1, local, 20);
 352                if (!verbose)
 353                        continue;
 354                fprintf(stderr,
 355                        "already have %s (%s)\n", sha1_to_hex(remote),
 356                        ref->name);
 357        }
 358        return retval;
 359}
 360
 361static int fetch_pack(int fd[2], int nr_match, char **match)
 362{
 363        struct ref *ref;
 364        unsigned char sha1[20];
 365        int status;
 366        pid_t pid;
 367
 368        get_remote_heads(fd[0], &ref, 0, NULL, 0);
 369        if (server_supports("multi_ack")) {
 370                if (verbose)
 371                        fprintf(stderr, "Server supports multi_ack\n");
 372                multi_ack = 1;
 373        }
 374        if (!ref) {
 375                packet_flush(fd[1]);
 376                die("no matching remote head");
 377        }
 378        if (everything_local(&ref, nr_match, match)) {
 379                packet_flush(fd[1]);
 380                goto all_done;
 381        }
 382        if (find_common(fd, sha1, ref) < 0)
 383                fprintf(stderr, "warning: no common commits\n");
 384        pid = fork();
 385        if (pid < 0)
 386                die("git-fetch-pack: unable to fork off git-unpack-objects");
 387        if (!pid) {
 388                dup2(fd[0], 0);
 389                close(fd[0]);
 390                close(fd[1]);
 391                execlp("git-unpack-objects", "git-unpack-objects",
 392                       quiet ? "-q" : NULL, NULL);
 393                die("git-unpack-objects exec failed");
 394        }
 395        close(fd[0]);
 396        close(fd[1]);
 397        while (waitpid(pid, &status, 0) < 0) {
 398                if (errno != EINTR)
 399                        die("waiting for git-unpack-objects: %s", strerror(errno));
 400        }
 401        if (WIFEXITED(status)) {
 402                int code = WEXITSTATUS(status);
 403                if (code)
 404                        die("git-unpack-objects died with error code %d", code);
 405all_done:
 406                while (ref) {
 407                        printf("%s %s\n",
 408                               sha1_to_hex(ref->old_sha1), ref->name);
 409                        ref = ref->next;
 410                }
 411                return 0;
 412        }
 413        if (WIFSIGNALED(status)) {
 414                int sig = WTERMSIG(status);
 415                die("git-unpack-objects died of signal %d", sig);
 416        }
 417        die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
 418}
 419
 420int main(int argc, char **argv)
 421{
 422        int i, ret, nr_heads;
 423        char *dest = NULL, **heads;
 424        int fd[2];
 425        pid_t pid;
 426
 427        nr_heads = 0;
 428        heads = NULL;
 429        for (i = 1; i < argc; i++) {
 430                char *arg = argv[i];
 431
 432                if (*arg == '-') {
 433                        if (!strncmp("--exec=", arg, 7)) {
 434                                exec = arg + 7;
 435                                continue;
 436                        }
 437                        if (!strcmp("-q", arg)) {
 438                                quiet = 1;
 439                                continue;
 440                        }
 441                        if (!strcmp("-v", arg)) {
 442                                verbose = 1;
 443                                continue;
 444                        }
 445                        usage(fetch_pack_usage);
 446                }
 447                dest = arg;
 448                heads = argv + i + 1;
 449                nr_heads = argc - i - 1;
 450                break;
 451        }
 452        if (!dest)
 453                usage(fetch_pack_usage);
 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}