fetch-pack.con commit blame: avoid "diff -u0". (604c86d)
   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] [--thin] [--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, use_thin_pack = 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(void)
  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%s\n", sha1_to_hex(remote),
 160                             (multi_ack ? " multi_ack" : ""),
 161                             (use_thin_pack ? " thin-pack" : ""));
 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        for (prev = NULL, current = *refs; current; current = next) {
 267                next = current->next;
 268                if ((!memcmp(current->name, "refs/", 5) &&
 269                                        check_ref_format(current->name + 5)) ||
 270                                !path_match(current->name, nr_match, match)) {
 271                        if (prev == NULL)
 272                                *refs = next;
 273                        else
 274                                prev->next = next;
 275                        free(current);
 276                } else
 277                        prev = current;
 278        }
 279}
 280
 281static int everything_local(struct ref **refs, int nr_match, char **match)
 282{
 283        struct ref *ref;
 284        int retval;
 285        unsigned long cutoff = 0;
 286
 287        track_object_refs = 0;
 288        save_commit_buffer = 0;
 289
 290        for (ref = *refs; ref; ref = ref->next) {
 291                struct object *o;
 292
 293                o = parse_object(ref->old_sha1);
 294                if (!o)
 295                        continue;
 296
 297                /* We already have it -- which may mean that we were
 298                 * in sync with the other side at some time after
 299                 * that (it is OK if we guess wrong here).
 300                 */
 301                if (o->type == commit_type) {
 302                        struct commit *commit = (struct commit *)o;
 303                        if (!cutoff || cutoff < commit->date)
 304                                cutoff = commit->date;
 305                }
 306        }
 307
 308        for_each_ref(mark_complete);
 309        if (cutoff)
 310                mark_recent_complete_commits(cutoff);
 311
 312        /*
 313         * Mark all complete remote refs as common refs.
 314         * Don't mark them common yet; the server has to be told so first.
 315         */
 316        for (ref = *refs; ref; ref = ref->next) {
 317                struct object *o = deref_tag(lookup_object(ref->old_sha1),
 318                                             NULL, 0);
 319
 320                if (!o || o->type != commit_type || !(o->flags & COMPLETE))
 321                        continue;
 322
 323                if (!(o->flags & SEEN)) {
 324                        rev_list_push((struct commit *)o, COMMON_REF | SEEN);
 325
 326                        mark_common((struct commit *)o, 1, 1);
 327                }
 328        }
 329
 330        filter_refs(refs, nr_match, match);
 331
 332        for (retval = 1, ref = *refs; ref ; ref = ref->next) {
 333                const unsigned char *remote = ref->old_sha1;
 334                unsigned char local[20];
 335                struct object *o;
 336
 337                o = lookup_object(remote);
 338                if (!o || !(o->flags & COMPLETE)) {
 339                        retval = 0;
 340                        if (!verbose)
 341                                continue;
 342                        fprintf(stderr,
 343                                "want %s (%s)\n", sha1_to_hex(remote),
 344                                ref->name);
 345                        continue;
 346                }
 347
 348                memcpy(ref->new_sha1, local, 20);
 349                if (!verbose)
 350                        continue;
 351                fprintf(stderr,
 352                        "already have %s (%s)\n", sha1_to_hex(remote),
 353                        ref->name);
 354        }
 355        return retval;
 356}
 357
 358static int fetch_pack(int fd[2], int nr_match, char **match)
 359{
 360        struct ref *ref;
 361        unsigned char sha1[20];
 362        int status;
 363
 364        get_remote_heads(fd[0], &ref, 0, NULL, 0);
 365        if (server_supports("multi_ack")) {
 366                if (verbose)
 367                        fprintf(stderr, "Server supports multi_ack\n");
 368                multi_ack = 1;
 369        }
 370        if (!ref) {
 371                packet_flush(fd[1]);
 372                die("no matching remote head");
 373        }
 374        if (everything_local(&ref, nr_match, match)) {
 375                packet_flush(fd[1]);
 376                goto all_done;
 377        }
 378        if (find_common(fd, sha1, ref) < 0)
 379                fprintf(stderr, "warning: no common commits\n");
 380
 381        if (keep_pack)
 382                status = receive_keep_pack(fd, "git-fetch-pack", quiet);
 383        else
 384                status = receive_unpack_pack(fd, "git-fetch-pack", quiet);
 385
 386        if (status)
 387                die("git-fetch-pack: fetch failed.");
 388
 389 all_done:
 390        while (ref) {
 391                printf("%s %s\n",
 392                       sha1_to_hex(ref->old_sha1), ref->name);
 393                ref = ref->next;
 394        }
 395        return 0;
 396}
 397
 398int main(int argc, char **argv)
 399{
 400        int i, ret, nr_heads;
 401        char *dest = NULL, **heads;
 402        int fd[2];
 403        pid_t pid;
 404
 405        setup_git_directory();
 406
 407        nr_heads = 0;
 408        heads = NULL;
 409        for (i = 1; i < argc; i++) {
 410                char *arg = argv[i];
 411
 412                if (*arg == '-') {
 413                        if (!strncmp("--exec=", arg, 7)) {
 414                                exec = arg + 7;
 415                                continue;
 416                        }
 417                        if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
 418                                quiet = 1;
 419                                continue;
 420                        }
 421                        if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
 422                                keep_pack = 1;
 423                                continue;
 424                        }
 425                        if (!strcmp("--thin", arg)) {
 426                                use_thin_pack = 1;
 427                                continue;
 428                        }
 429                        if (!strcmp("-v", arg)) {
 430                                verbose = 1;
 431                                continue;
 432                        }
 433                        usage(fetch_pack_usage);
 434                }
 435                dest = arg;
 436                heads = argv + i + 1;
 437                nr_heads = argc - i - 1;
 438                break;
 439        }
 440        if (!dest)
 441                usage(fetch_pack_usage);
 442        if (keep_pack)
 443                use_thin_pack = 0;
 444        pid = git_connect(fd, dest, exec);
 445        if (pid < 0)
 446                return 1;
 447        ret = fetch_pack(fd, nr_heads, heads);
 448        close(fd[0]);
 449        close(fd[1]);
 450        finish_connect(pid);
 451
 452        if (!ret && nr_heads) {
 453                /* If the heads to pull were given, we should have
 454                 * consumed all of them by matching the remote.
 455                 * Otherwise, 'git-fetch remote no-such-ref' would
 456                 * silently succeed without issuing an error.
 457                 */
 458                for (i = 0; i < nr_heads; i++)
 459                        if (heads[i] && heads[i][0]) {
 460                                error("no such remote ref %s", heads[i]);
 461                                ret = 1;
 462                        }
 463        }
 464
 465        return ret;
 466}