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