builtin-remote.con commit Makefile: test-parse-options depends on parse-options.h (26c117d)
   1#include "cache.h"
   2#include "parse-options.h"
   3#include "transport.h"
   4#include "remote.h"
   5#include "string-list.h"
   6#include "strbuf.h"
   7#include "run-command.h"
   8#include "refs.h"
   9
  10static const char * const builtin_remote_usage[] = {
  11        "git remote [-v | --verbose]",
  12        "git remote add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>",
  13        "git remote rename <old> <new>",
  14        "git remote rm <name>",
  15        "git remote set-head <name> [-a | -d | <branch>]",
  16        "git remote show [-n] <name>",
  17        "git remote prune [-n | --dry-run] <name>",
  18        "git remote [-v | --verbose] update [-p | --prune] [group]",
  19        NULL
  20};
  21
  22#define GET_REF_STATES (1<<0)
  23#define GET_HEAD_NAMES (1<<1)
  24#define GET_PUSH_REF_STATES (1<<2)
  25
  26static int verbose;
  27
  28static int show_all(void);
  29static int prune_remote(const char *remote, int dry_run);
  30
  31static inline int postfixcmp(const char *string, const char *postfix)
  32{
  33        int len1 = strlen(string), len2 = strlen(postfix);
  34        if (len1 < len2)
  35                return 1;
  36        return strcmp(string + len1 - len2, postfix);
  37}
  38
  39static int opt_parse_track(const struct option *opt, const char *arg, int not)
  40{
  41        struct string_list *list = opt->value;
  42        if (not)
  43                string_list_clear(list, 0);
  44        else
  45                string_list_append(arg, list);
  46        return 0;
  47}
  48
  49static int fetch_remote(const char *name)
  50{
  51        const char *argv[] = { "fetch", name, NULL, NULL };
  52        if (verbose) {
  53                argv[1] = "-v";
  54                argv[2] = name;
  55        }
  56        printf("Updating %s\n", name);
  57        if (run_command_v_opt(argv, RUN_GIT_CMD))
  58                return error("Could not fetch %s", name);
  59        return 0;
  60}
  61
  62static int add(int argc, const char **argv)
  63{
  64        int fetch = 0, mirror = 0;
  65        struct string_list track = { NULL, 0, 0 };
  66        const char *master = NULL;
  67        struct remote *remote;
  68        struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
  69        const char *name, *url;
  70        int i;
  71
  72        struct option options[] = {
  73                OPT_GROUP("add specific options"),
  74                OPT_BOOLEAN('f', "fetch", &fetch, "fetch the remote branches"),
  75                OPT_CALLBACK('t', "track", &track, "branch",
  76                        "branch(es) to track", opt_parse_track),
  77                OPT_STRING('m', "master", &master, "branch", "master branch"),
  78                OPT_BOOLEAN(0, "mirror", &mirror, "no separate remotes"),
  79                OPT_END()
  80        };
  81
  82        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
  83                             0);
  84
  85        if (argc < 2)
  86                usage_with_options(builtin_remote_usage, options);
  87
  88        name = argv[0];
  89        url = argv[1];
  90
  91        remote = remote_get(name);
  92        if (remote && (remote->url_nr > 1 || strcmp(name, remote->url[0]) ||
  93                        remote->fetch_refspec_nr))
  94                die("remote %s already exists.", name);
  95
  96        strbuf_addf(&buf2, "refs/heads/test:refs/remotes/%s/test", name);
  97        if (!valid_fetch_refspec(buf2.buf))
  98                die("'%s' is not a valid remote name", name);
  99
 100        strbuf_addf(&buf, "remote.%s.url", name);
 101        if (git_config_set(buf.buf, url))
 102                return 1;
 103
 104        strbuf_reset(&buf);
 105        strbuf_addf(&buf, "remote.%s.fetch", name);
 106
 107        if (track.nr == 0)
 108                string_list_append("*", &track);
 109        for (i = 0; i < track.nr; i++) {
 110                struct string_list_item *item = track.items + i;
 111
 112                strbuf_reset(&buf2);
 113                strbuf_addch(&buf2, '+');
 114                if (mirror)
 115                        strbuf_addf(&buf2, "refs/%s:refs/%s",
 116                                        item->string, item->string);
 117                else
 118                        strbuf_addf(&buf2, "refs/heads/%s:refs/remotes/%s/%s",
 119                                        item->string, name, item->string);
 120                if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
 121                        return 1;
 122        }
 123
 124        if (mirror) {
 125                strbuf_reset(&buf);
 126                strbuf_addf(&buf, "remote.%s.mirror", name);
 127                if (git_config_set(buf.buf, "true"))
 128                        return 1;
 129        }
 130
 131        if (fetch && fetch_remote(name))
 132                return 1;
 133
 134        if (master) {
 135                strbuf_reset(&buf);
 136                strbuf_addf(&buf, "refs/remotes/%s/HEAD", name);
 137
 138                strbuf_reset(&buf2);
 139                strbuf_addf(&buf2, "refs/remotes/%s/%s", name, master);
 140
 141                if (create_symref(buf.buf, buf2.buf, "remote add"))
 142                        return error("Could not setup master '%s'", master);
 143        }
 144
 145        strbuf_release(&buf);
 146        strbuf_release(&buf2);
 147        string_list_clear(&track, 0);
 148
 149        return 0;
 150}
 151
 152struct branch_info {
 153        char *remote_name;
 154        struct string_list merge;
 155        int rebase;
 156};
 157
 158static struct string_list branch_list;
 159
 160static const char *abbrev_ref(const char *name, const char *prefix)
 161{
 162        const char *abbrev = skip_prefix(name, prefix);
 163        if (abbrev)
 164                return abbrev;
 165        return name;
 166}
 167#define abbrev_branch(name) abbrev_ref((name), "refs/heads/")
 168
 169static int config_read_branches(const char *key, const char *value, void *cb)
 170{
 171        if (!prefixcmp(key, "branch.")) {
 172                const char *orig_key = key;
 173                char *name;
 174                struct string_list_item *item;
 175                struct branch_info *info;
 176                enum { REMOTE, MERGE, REBASE } type;
 177
 178                key += 7;
 179                if (!postfixcmp(key, ".remote")) {
 180                        name = xstrndup(key, strlen(key) - 7);
 181                        type = REMOTE;
 182                } else if (!postfixcmp(key, ".merge")) {
 183                        name = xstrndup(key, strlen(key) - 6);
 184                        type = MERGE;
 185                } else if (!postfixcmp(key, ".rebase")) {
 186                        name = xstrndup(key, strlen(key) - 7);
 187                        type = REBASE;
 188                } else
 189                        return 0;
 190
 191                item = string_list_insert(name, &branch_list);
 192
 193                if (!item->util)
 194                        item->util = xcalloc(sizeof(struct branch_info), 1);
 195                info = item->util;
 196                if (type == REMOTE) {
 197                        if (info->remote_name)
 198                                warning("more than one %s", orig_key);
 199                        info->remote_name = xstrdup(value);
 200                } else if (type == MERGE) {
 201                        char *space = strchr(value, ' ');
 202                        value = abbrev_branch(value);
 203                        while (space) {
 204                                char *merge;
 205                                merge = xstrndup(value, space - value);
 206                                string_list_append(merge, &info->merge);
 207                                value = abbrev_branch(space + 1);
 208                                space = strchr(value, ' ');
 209                        }
 210                        string_list_append(xstrdup(value), &info->merge);
 211                } else
 212                        info->rebase = git_config_bool(orig_key, value);
 213        }
 214        return 0;
 215}
 216
 217static void read_branches(void)
 218{
 219        if (branch_list.nr)
 220                return;
 221        git_config(config_read_branches, NULL);
 222}
 223
 224struct ref_states {
 225        struct remote *remote;
 226        struct string_list new, stale, tracked, heads, push;
 227        int queried;
 228};
 229
 230static int handle_one_branch(const char *refname,
 231        const unsigned char *sha1, int flags, void *cb_data)
 232{
 233        struct ref_states *states = cb_data;
 234        struct refspec refspec;
 235
 236        memset(&refspec, 0, sizeof(refspec));
 237        refspec.dst = (char *)refname;
 238        if (!remote_find_tracking(states->remote, &refspec)) {
 239                struct string_list_item *item;
 240                const char *name = abbrev_branch(refspec.src);
 241                /* symbolic refs pointing nowhere were handled already */
 242                if ((flags & REF_ISSYMREF) ||
 243                    string_list_has_string(&states->tracked, name) ||
 244                    string_list_has_string(&states->new, name))
 245                        return 0;
 246                item = string_list_append(name, &states->stale);
 247                item->util = xstrdup(refname);
 248        }
 249        return 0;
 250}
 251
 252static int get_ref_states(const struct ref *remote_refs, struct ref_states *states)
 253{
 254        struct ref *fetch_map = NULL, **tail = &fetch_map;
 255        struct ref *ref;
 256        int i;
 257
 258        for (i = 0; i < states->remote->fetch_refspec_nr; i++)
 259                if (get_fetch_map(remote_refs, states->remote->fetch + i, &tail, 1))
 260                        die("Could not get fetch map for refspec %s",
 261                                states->remote->fetch_refspec[i]);
 262
 263        states->new.strdup_strings = states->tracked.strdup_strings = 1;
 264        for (ref = fetch_map; ref; ref = ref->next) {
 265                unsigned char sha1[20];
 266                if (!ref->peer_ref || read_ref(ref->peer_ref->name, sha1))
 267                        string_list_append(abbrev_branch(ref->name), &states->new);
 268                else
 269                        string_list_append(abbrev_branch(ref->name), &states->tracked);
 270        }
 271        free_refs(fetch_map);
 272
 273        sort_string_list(&states->new);
 274        sort_string_list(&states->tracked);
 275        for_each_ref(handle_one_branch, states);
 276        sort_string_list(&states->stale);
 277
 278        return 0;
 279}
 280
 281struct push_info {
 282        char *dest;
 283        int forced;
 284        enum {
 285                PUSH_STATUS_CREATE = 0,
 286                PUSH_STATUS_DELETE,
 287                PUSH_STATUS_UPTODATE,
 288                PUSH_STATUS_FASTFORWARD,
 289                PUSH_STATUS_OUTOFDATE,
 290                PUSH_STATUS_NOTQUERIED,
 291        } status;
 292};
 293
 294static int get_push_ref_states(const struct ref *remote_refs,
 295        struct ref_states *states)
 296{
 297        struct remote *remote = states->remote;
 298        struct ref *ref, *local_refs, *push_map, **push_tail;
 299        if (remote->mirror)
 300                return 0;
 301
 302        local_refs = get_local_heads();
 303        push_map = copy_ref_list(remote_refs);
 304
 305        push_tail = &push_map;
 306        while (*push_tail)
 307                push_tail = &((*push_tail)->next);
 308        match_refs(local_refs, push_map, &push_tail, remote->push_refspec_nr,
 309                   remote->push_refspec, MATCH_REFS_NONE);
 310
 311        states->push.strdup_strings = 1;
 312        for (ref = push_map; ref; ref = ref->next) {
 313                struct string_list_item *item;
 314                struct push_info *info;
 315
 316                if (!ref->peer_ref)
 317                        continue;
 318                hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
 319
 320                item = string_list_append(abbrev_branch(ref->peer_ref->name),
 321                                          &states->push);
 322                item->util = xcalloc(sizeof(struct push_info), 1);
 323                info = item->util;
 324                info->forced = ref->force;
 325                info->dest = xstrdup(abbrev_branch(ref->name));
 326
 327                if (is_null_sha1(ref->new_sha1)) {
 328                        info->status = PUSH_STATUS_DELETE;
 329                } else if (!hashcmp(ref->old_sha1, ref->new_sha1))
 330                        info->status = PUSH_STATUS_UPTODATE;
 331                else if (is_null_sha1(ref->old_sha1))
 332                        info->status = PUSH_STATUS_CREATE;
 333                else if (has_sha1_file(ref->old_sha1) &&
 334                         ref_newer(ref->new_sha1, ref->old_sha1))
 335                        info->status = PUSH_STATUS_FASTFORWARD;
 336                else
 337                        info->status = PUSH_STATUS_OUTOFDATE;
 338        }
 339        free_refs(local_refs);
 340        free_refs(push_map);
 341        return 0;
 342}
 343
 344static int get_push_ref_states_noquery(struct ref_states *states)
 345{
 346        int i;
 347        struct remote *remote = states->remote;
 348        struct string_list_item *item;
 349        struct push_info *info;
 350
 351        if (remote->mirror)
 352                return 0;
 353
 354        states->push.strdup_strings = 1;
 355        if (!remote->push_refspec_nr) {
 356                item = string_list_append("(matching)", &states->push);
 357                info = item->util = xcalloc(sizeof(struct push_info), 1);
 358                info->status = PUSH_STATUS_NOTQUERIED;
 359                info->dest = xstrdup(item->string);
 360        }
 361        for (i = 0; i < remote->push_refspec_nr; i++) {
 362                struct refspec *spec = remote->push + i;
 363                if (spec->matching)
 364                        item = string_list_append("(matching)", &states->push);
 365                else if (strlen(spec->src))
 366                        item = string_list_append(spec->src, &states->push);
 367                else
 368                        item = string_list_append("(delete)", &states->push);
 369
 370                info = item->util = xcalloc(sizeof(struct push_info), 1);
 371                info->forced = spec->force;
 372                info->status = PUSH_STATUS_NOTQUERIED;
 373                info->dest = xstrdup(spec->dst ? spec->dst : item->string);
 374        }
 375        return 0;
 376}
 377
 378static int get_head_names(const struct ref *remote_refs, struct ref_states *states)
 379{
 380        struct ref *ref, *matches;
 381        struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
 382        struct refspec refspec;
 383
 384        refspec.force = 0;
 385        refspec.pattern = 1;
 386        refspec.src = refspec.dst = "refs/heads/*";
 387        states->heads.strdup_strings = 1;
 388        get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
 389        matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
 390                                    fetch_map, 1);
 391        for(ref = matches; ref; ref = ref->next)
 392                string_list_append(abbrev_branch(ref->name), &states->heads);
 393
 394        free_refs(fetch_map);
 395        free_refs(matches);
 396
 397        return 0;
 398}
 399
 400struct known_remote {
 401        struct known_remote *next;
 402        struct remote *remote;
 403};
 404
 405struct known_remotes {
 406        struct remote *to_delete;
 407        struct known_remote *list;
 408};
 409
 410static int add_known_remote(struct remote *remote, void *cb_data)
 411{
 412        struct known_remotes *all = cb_data;
 413        struct known_remote *r;
 414
 415        if (!strcmp(all->to_delete->name, remote->name))
 416                return 0;
 417
 418        r = xmalloc(sizeof(*r));
 419        r->remote = remote;
 420        r->next = all->list;
 421        all->list = r;
 422        return 0;
 423}
 424
 425struct branches_for_remote {
 426        struct remote *remote;
 427        struct string_list *branches, *skipped;
 428        struct known_remotes *keep;
 429};
 430
 431static int add_branch_for_removal(const char *refname,
 432        const unsigned char *sha1, int flags, void *cb_data)
 433{
 434        struct branches_for_remote *branches = cb_data;
 435        struct refspec refspec;
 436        struct string_list_item *item;
 437        struct known_remote *kr;
 438
 439        memset(&refspec, 0, sizeof(refspec));
 440        refspec.dst = (char *)refname;
 441        if (remote_find_tracking(branches->remote, &refspec))
 442                return 0;
 443
 444        /* don't delete a branch if another remote also uses it */
 445        for (kr = branches->keep->list; kr; kr = kr->next) {
 446                memset(&refspec, 0, sizeof(refspec));
 447                refspec.dst = (char *)refname;
 448                if (!remote_find_tracking(kr->remote, &refspec))
 449                        return 0;
 450        }
 451
 452        /* don't delete non-remote refs */
 453        if (prefixcmp(refname, "refs/remotes")) {
 454                /* advise user how to delete local branches */
 455                if (!prefixcmp(refname, "refs/heads/"))
 456                        string_list_append(abbrev_branch(refname),
 457                                           branches->skipped);
 458                /* silently skip over other non-remote refs */
 459                return 0;
 460        }
 461
 462        /* make sure that symrefs are deleted */
 463        if (flags & REF_ISSYMREF)
 464                return unlink(git_path("%s", refname));
 465
 466        item = string_list_append(refname, branches->branches);
 467        item->util = xmalloc(20);
 468        hashcpy(item->util, sha1);
 469
 470        return 0;
 471}
 472
 473struct rename_info {
 474        const char *old;
 475        const char *new;
 476        struct string_list *remote_branches;
 477};
 478
 479static int read_remote_branches(const char *refname,
 480        const unsigned char *sha1, int flags, void *cb_data)
 481{
 482        struct rename_info *rename = cb_data;
 483        struct strbuf buf = STRBUF_INIT;
 484        struct string_list_item *item;
 485        int flag;
 486        unsigned char orig_sha1[20];
 487        const char *symref;
 488
 489        strbuf_addf(&buf, "refs/remotes/%s", rename->old);
 490        if(!prefixcmp(refname, buf.buf)) {
 491                item = string_list_append(xstrdup(refname), rename->remote_branches);
 492                symref = resolve_ref(refname, orig_sha1, 1, &flag);
 493                if (flag & REF_ISSYMREF)
 494                        item->util = xstrdup(symref);
 495                else
 496                        item->util = NULL;
 497        }
 498
 499        return 0;
 500}
 501
 502static int migrate_file(struct remote *remote)
 503{
 504        struct strbuf buf = STRBUF_INIT;
 505        int i;
 506        char *path = NULL;
 507
 508        strbuf_addf(&buf, "remote.%s.url", remote->name);
 509        for (i = 0; i < remote->url_nr; i++)
 510                if (git_config_set_multivar(buf.buf, remote->url[i], "^$", 0))
 511                        return error("Could not append '%s' to '%s'",
 512                                        remote->url[i], buf.buf);
 513        strbuf_reset(&buf);
 514        strbuf_addf(&buf, "remote.%s.push", remote->name);
 515        for (i = 0; i < remote->push_refspec_nr; i++)
 516                if (git_config_set_multivar(buf.buf, remote->push_refspec[i], "^$", 0))
 517                        return error("Could not append '%s' to '%s'",
 518                                        remote->push_refspec[i], buf.buf);
 519        strbuf_reset(&buf);
 520        strbuf_addf(&buf, "remote.%s.fetch", remote->name);
 521        for (i = 0; i < remote->fetch_refspec_nr; i++)
 522                if (git_config_set_multivar(buf.buf, remote->fetch_refspec[i], "^$", 0))
 523                        return error("Could not append '%s' to '%s'",
 524                                        remote->fetch_refspec[i], buf.buf);
 525        if (remote->origin == REMOTE_REMOTES)
 526                path = git_path("remotes/%s", remote->name);
 527        else if (remote->origin == REMOTE_BRANCHES)
 528                path = git_path("branches/%s", remote->name);
 529        if (path)
 530                unlink_or_warn(path);
 531        return 0;
 532}
 533
 534static int mv(int argc, const char **argv)
 535{
 536        struct option options[] = {
 537                OPT_END()
 538        };
 539        struct remote *oldremote, *newremote;
 540        struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT;
 541        struct string_list remote_branches = { NULL, 0, 0, 0 };
 542        struct rename_info rename;
 543        int i;
 544
 545        if (argc != 3)
 546                usage_with_options(builtin_remote_usage, options);
 547
 548        rename.old = argv[1];
 549        rename.new = argv[2];
 550        rename.remote_branches = &remote_branches;
 551
 552        oldremote = remote_get(rename.old);
 553        if (!oldremote)
 554                die("No such remote: %s", rename.old);
 555
 556        if (!strcmp(rename.old, rename.new) && oldremote->origin != REMOTE_CONFIG)
 557                return migrate_file(oldremote);
 558
 559        newremote = remote_get(rename.new);
 560        if (newremote && (newremote->url_nr > 1 || newremote->fetch_refspec_nr))
 561                die("remote %s already exists.", rename.new);
 562
 563        strbuf_addf(&buf, "refs/heads/test:refs/remotes/%s/test", rename.new);
 564        if (!valid_fetch_refspec(buf.buf))
 565                die("'%s' is not a valid remote name", rename.new);
 566
 567        strbuf_reset(&buf);
 568        strbuf_addf(&buf, "remote.%s", rename.old);
 569        strbuf_addf(&buf2, "remote.%s", rename.new);
 570        if (git_config_rename_section(buf.buf, buf2.buf) < 1)
 571                return error("Could not rename config section '%s' to '%s'",
 572                                buf.buf, buf2.buf);
 573
 574        strbuf_reset(&buf);
 575        strbuf_addf(&buf, "remote.%s.fetch", rename.new);
 576        if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
 577                return error("Could not remove config section '%s'", buf.buf);
 578        for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
 579                char *ptr;
 580
 581                strbuf_reset(&buf2);
 582                strbuf_addstr(&buf2, oldremote->fetch_refspec[i]);
 583                ptr = strstr(buf2.buf, rename.old);
 584                if (ptr)
 585                        strbuf_splice(&buf2, ptr-buf2.buf, strlen(rename.old),
 586                                        rename.new, strlen(rename.new));
 587                if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
 588                        return error("Could not append '%s'", buf.buf);
 589        }
 590
 591        read_branches();
 592        for (i = 0; i < branch_list.nr; i++) {
 593                struct string_list_item *item = branch_list.items + i;
 594                struct branch_info *info = item->util;
 595                if (info->remote_name && !strcmp(info->remote_name, rename.old)) {
 596                        strbuf_reset(&buf);
 597                        strbuf_addf(&buf, "branch.%s.remote", item->string);
 598                        if (git_config_set(buf.buf, rename.new)) {
 599                                return error("Could not set '%s'", buf.buf);
 600                        }
 601                }
 602        }
 603
 604        /*
 605         * First remove symrefs, then rename the rest, finally create
 606         * the new symrefs.
 607         */
 608        for_each_ref(read_remote_branches, &rename);
 609        for (i = 0; i < remote_branches.nr; i++) {
 610                struct string_list_item *item = remote_branches.items + i;
 611                int flag = 0;
 612                unsigned char sha1[20];
 613
 614                resolve_ref(item->string, sha1, 1, &flag);
 615                if (!(flag & REF_ISSYMREF))
 616                        continue;
 617                if (delete_ref(item->string, NULL, REF_NODEREF))
 618                        die("deleting '%s' failed", item->string);
 619        }
 620        for (i = 0; i < remote_branches.nr; i++) {
 621                struct string_list_item *item = remote_branches.items + i;
 622
 623                if (item->util)
 624                        continue;
 625                strbuf_reset(&buf);
 626                strbuf_addstr(&buf, item->string);
 627                strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old),
 628                                rename.new, strlen(rename.new));
 629                strbuf_reset(&buf2);
 630                strbuf_addf(&buf2, "remote: renamed %s to %s",
 631                                item->string, buf.buf);
 632                if (rename_ref(item->string, buf.buf, buf2.buf))
 633                        die("renaming '%s' failed", item->string);
 634        }
 635        for (i = 0; i < remote_branches.nr; i++) {
 636                struct string_list_item *item = remote_branches.items + i;
 637
 638                if (!item->util)
 639                        continue;
 640                strbuf_reset(&buf);
 641                strbuf_addstr(&buf, item->string);
 642                strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old),
 643                                rename.new, strlen(rename.new));
 644                strbuf_reset(&buf2);
 645                strbuf_addstr(&buf2, item->util);
 646                strbuf_splice(&buf2, strlen("refs/remotes/"), strlen(rename.old),
 647                                rename.new, strlen(rename.new));
 648                strbuf_reset(&buf3);
 649                strbuf_addf(&buf3, "remote: renamed %s to %s",
 650                                item->string, buf.buf);
 651                if (create_symref(buf.buf, buf2.buf, buf3.buf))
 652                        die("creating '%s' failed", buf.buf);
 653        }
 654        return 0;
 655}
 656
 657static int remove_branches(struct string_list *branches)
 658{
 659        int i, result = 0;
 660        for (i = 0; i < branches->nr; i++) {
 661                struct string_list_item *item = branches->items + i;
 662                const char *refname = item->string;
 663                unsigned char *sha1 = item->util;
 664
 665                if (delete_ref(refname, sha1, 0))
 666                        result |= error("Could not remove branch %s", refname);
 667        }
 668        return result;
 669}
 670
 671static int rm(int argc, const char **argv)
 672{
 673        struct option options[] = {
 674                OPT_END()
 675        };
 676        struct remote *remote;
 677        struct strbuf buf = STRBUF_INIT;
 678        struct known_remotes known_remotes = { NULL, NULL };
 679        struct string_list branches = { NULL, 0, 0, 1 };
 680        struct string_list skipped = { NULL, 0, 0, 1 };
 681        struct branches_for_remote cb_data = {
 682                NULL, &branches, &skipped, &known_remotes
 683        };
 684        int i, result;
 685
 686        if (argc != 2)
 687                usage_with_options(builtin_remote_usage, options);
 688
 689        remote = remote_get(argv[1]);
 690        if (!remote)
 691                die("No such remote: %s", argv[1]);
 692
 693        known_remotes.to_delete = remote;
 694        for_each_remote(add_known_remote, &known_remotes);
 695
 696        strbuf_addf(&buf, "remote.%s", remote->name);
 697        if (git_config_rename_section(buf.buf, NULL) < 1)
 698                return error("Could not remove config section '%s'", buf.buf);
 699
 700        read_branches();
 701        for (i = 0; i < branch_list.nr; i++) {
 702                struct string_list_item *item = branch_list.items + i;
 703                struct branch_info *info = item->util;
 704                if (info->remote_name && !strcmp(info->remote_name, remote->name)) {
 705                        const char *keys[] = { "remote", "merge", NULL }, **k;
 706                        for (k = keys; *k; k++) {
 707                                strbuf_reset(&buf);
 708                                strbuf_addf(&buf, "branch.%s.%s",
 709                                                item->string, *k);
 710                                if (git_config_set(buf.buf, NULL)) {
 711                                        strbuf_release(&buf);
 712                                        return -1;
 713                                }
 714                        }
 715                }
 716        }
 717
 718        /*
 719         * We cannot just pass a function to for_each_ref() which deletes
 720         * the branches one by one, since for_each_ref() relies on cached
 721         * refs, which are invalidated when deleting a branch.
 722         */
 723        cb_data.remote = remote;
 724        result = for_each_ref(add_branch_for_removal, &cb_data);
 725        strbuf_release(&buf);
 726
 727        if (!result)
 728                result = remove_branches(&branches);
 729        string_list_clear(&branches, 1);
 730
 731        if (skipped.nr) {
 732                fprintf(stderr, skipped.nr == 1 ?
 733                        "Note: A non-remote branch was not removed; "
 734                        "to delete it, use:\n" :
 735                        "Note: Non-remote branches were not removed; "
 736                        "to delete them, use:\n");
 737                for (i = 0; i < skipped.nr; i++)
 738                        fprintf(stderr, "  git branch -d %s\n",
 739                                skipped.items[i].string);
 740        }
 741        string_list_clear(&skipped, 0);
 742
 743        return result;
 744}
 745
 746void clear_push_info(void *util, const char *string)
 747{
 748        struct push_info *info = util;
 749        free(info->dest);
 750        free(info);
 751}
 752
 753static void free_remote_ref_states(struct ref_states *states)
 754{
 755        string_list_clear(&states->new, 0);
 756        string_list_clear(&states->stale, 0);
 757        string_list_clear(&states->tracked, 0);
 758        string_list_clear(&states->heads, 0);
 759        string_list_clear_func(&states->push, clear_push_info);
 760}
 761
 762static int append_ref_to_tracked_list(const char *refname,
 763        const unsigned char *sha1, int flags, void *cb_data)
 764{
 765        struct ref_states *states = cb_data;
 766        struct refspec refspec;
 767
 768        if (flags & REF_ISSYMREF)
 769                return 0;
 770
 771        memset(&refspec, 0, sizeof(refspec));
 772        refspec.dst = (char *)refname;
 773        if (!remote_find_tracking(states->remote, &refspec))
 774                string_list_append(abbrev_branch(refspec.src), &states->tracked);
 775
 776        return 0;
 777}
 778
 779static int get_remote_ref_states(const char *name,
 780                                 struct ref_states *states,
 781                                 int query)
 782{
 783        struct transport *transport;
 784        const struct ref *remote_refs;
 785
 786        states->remote = remote_get(name);
 787        if (!states->remote)
 788                return error("No such remote: %s", name);
 789
 790        read_branches();
 791
 792        if (query) {
 793                transport = transport_get(NULL, states->remote->url_nr > 0 ?
 794                        states->remote->url[0] : NULL);
 795                remote_refs = transport_get_remote_refs(transport);
 796                transport_disconnect(transport);
 797
 798                states->queried = 1;
 799                if (query & GET_REF_STATES)
 800                        get_ref_states(remote_refs, states);
 801                if (query & GET_HEAD_NAMES)
 802                        get_head_names(remote_refs, states);
 803                if (query & GET_PUSH_REF_STATES)
 804                        get_push_ref_states(remote_refs, states);
 805        } else {
 806                for_each_ref(append_ref_to_tracked_list, states);
 807                sort_string_list(&states->tracked);
 808                get_push_ref_states_noquery(states);
 809        }
 810
 811        return 0;
 812}
 813
 814struct show_info {
 815        struct string_list *list;
 816        struct ref_states *states;
 817        int width, width2;
 818        int any_rebase;
 819};
 820
 821int add_remote_to_show_info(struct string_list_item *item, void *cb_data)
 822{
 823        struct show_info *info = cb_data;
 824        int n = strlen(item->string);
 825        if (n > info->width)
 826                info->width = n;
 827        string_list_insert(item->string, info->list);
 828        return 0;
 829}
 830
 831int show_remote_info_item(struct string_list_item *item, void *cb_data)
 832{
 833        struct show_info *info = cb_data;
 834        struct ref_states *states = info->states;
 835        const char *name = item->string;
 836
 837        if (states->queried) {
 838                const char *fmt = "%s";
 839                const char *arg = "";
 840                if (string_list_has_string(&states->new, name)) {
 841                        fmt = " new (next fetch will store in remotes/%s)";
 842                        arg = states->remote->name;
 843                } else if (string_list_has_string(&states->tracked, name))
 844                        arg = " tracked";
 845                else if (string_list_has_string(&states->stale, name))
 846                        arg = " stale (use 'git remote prune' to remove)";
 847                else
 848                        arg = " ???";
 849                printf("    %-*s", info->width, name);
 850                printf(fmt, arg);
 851                printf("\n");
 852        } else
 853                printf("    %s\n", name);
 854
 855        return 0;
 856}
 857
 858int add_local_to_show_info(struct string_list_item *branch_item, void *cb_data)
 859{
 860        struct show_info *show_info = cb_data;
 861        struct ref_states *states = show_info->states;
 862        struct branch_info *branch_info = branch_item->util;
 863        struct string_list_item *item;
 864        int n;
 865
 866        if (!branch_info->merge.nr || !branch_info->remote_name ||
 867            strcmp(states->remote->name, branch_info->remote_name))
 868                return 0;
 869        if ((n = strlen(branch_item->string)) > show_info->width)
 870                show_info->width = n;
 871        if (branch_info->rebase)
 872                show_info->any_rebase = 1;
 873
 874        item = string_list_insert(branch_item->string, show_info->list);
 875        item->util = branch_info;
 876
 877        return 0;
 878}
 879
 880int show_local_info_item(struct string_list_item *item, void *cb_data)
 881{
 882        struct show_info *show_info = cb_data;
 883        struct branch_info *branch_info = item->util;
 884        struct string_list *merge = &branch_info->merge;
 885        const char *also;
 886        int i;
 887
 888        if (branch_info->rebase && branch_info->merge.nr > 1) {
 889                error("invalid branch.%s.merge; cannot rebase onto > 1 branch",
 890                        item->string);
 891                return 0;
 892        }
 893
 894        printf("    %-*s ", show_info->width, item->string);
 895        if (branch_info->rebase) {
 896                printf("rebases onto remote %s\n", merge->items[0].string);
 897                return 0;
 898        } else if (show_info->any_rebase) {
 899                printf(" merges with remote %s\n", merge->items[0].string);
 900                also = "    and with remote";
 901        } else {
 902                printf("merges with remote %s\n", merge->items[0].string);
 903                also = "   and with remote";
 904        }
 905        for (i = 1; i < merge->nr; i++)
 906                printf("    %-*s %s %s\n", show_info->width, "", also,
 907                       merge->items[i].string);
 908
 909        return 0;
 910}
 911
 912int add_push_to_show_info(struct string_list_item *push_item, void *cb_data)
 913{
 914        struct show_info *show_info = cb_data;
 915        struct push_info *push_info = push_item->util;
 916        struct string_list_item *item;
 917        int n;
 918        if ((n = strlen(push_item->string)) > show_info->width)
 919                show_info->width = n;
 920        if ((n = strlen(push_info->dest)) > show_info->width2)
 921                show_info->width2 = n;
 922        item = string_list_append(push_item->string, show_info->list);
 923        item->util = push_item->util;
 924        return 0;
 925}
 926
 927/*
 928 * Sorting comparison for a string list that has push_info
 929 * structs in its util field
 930 */
 931static int cmp_string_with_push(const void *va, const void *vb)
 932{
 933        const struct string_list_item *a = va;
 934        const struct string_list_item *b = vb;
 935        const struct push_info *a_push = a->util;
 936        const struct push_info *b_push = b->util;
 937        int cmp = strcmp(a->string, b->string);
 938        return cmp ? cmp : strcmp(a_push->dest, b_push->dest);
 939}
 940
 941int show_push_info_item(struct string_list_item *item, void *cb_data)
 942{
 943        struct show_info *show_info = cb_data;
 944        struct push_info *push_info = item->util;
 945        char *src = item->string, *status = NULL;
 946
 947        switch (push_info->status) {
 948        case PUSH_STATUS_CREATE:
 949                status = "create";
 950                break;
 951        case PUSH_STATUS_DELETE:
 952                status = "delete";
 953                src = "(none)";
 954                break;
 955        case PUSH_STATUS_UPTODATE:
 956                status = "up to date";
 957                break;
 958        case PUSH_STATUS_FASTFORWARD:
 959                status = "fast forwardable";
 960                break;
 961        case PUSH_STATUS_OUTOFDATE:
 962                status = "local out of date";
 963                break;
 964        case PUSH_STATUS_NOTQUERIED:
 965                break;
 966        }
 967        if (status)
 968                printf("    %-*s %s to %-*s (%s)\n", show_info->width, src,
 969                        push_info->forced ? "forces" : "pushes",
 970                        show_info->width2, push_info->dest, status);
 971        else
 972                printf("    %-*s %s to %s\n", show_info->width, src,
 973                        push_info->forced ? "forces" : "pushes",
 974                        push_info->dest);
 975        return 0;
 976}
 977
 978static int show(int argc, const char **argv)
 979{
 980        int no_query = 0, result = 0, query_flag = 0;
 981        struct option options[] = {
 982                OPT_GROUP("show specific options"),
 983                OPT_BOOLEAN('n', NULL, &no_query, "do not query remotes"),
 984                OPT_END()
 985        };
 986        struct ref_states states;
 987        struct string_list info_list = { NULL, 0, 0, 0 };
 988        struct show_info info;
 989
 990        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
 991                             0);
 992
 993        if (argc < 1)
 994                return show_all();
 995
 996        if (!no_query)
 997                query_flag = (GET_REF_STATES | GET_HEAD_NAMES | GET_PUSH_REF_STATES);
 998
 999        memset(&states, 0, sizeof(states));
1000        memset(&info, 0, sizeof(info));
1001        info.states = &states;
1002        info.list = &info_list;
1003        for (; argc; argc--, argv++) {
1004                int i;
1005
1006                get_remote_ref_states(*argv, &states, query_flag);
1007
1008                printf("* remote %s\n  URL: %s\n", *argv,
1009                        states.remote->url_nr > 0 ?
1010                                states.remote->url[0] : "(no URL)");
1011                if (no_query)
1012                        printf("  HEAD branch: (not queried)\n");
1013                else if (!states.heads.nr)
1014                        printf("  HEAD branch: (unknown)\n");
1015                else if (states.heads.nr == 1)
1016                        printf("  HEAD branch: %s\n", states.heads.items[0].string);
1017                else {
1018                        printf("  HEAD branch (remote HEAD is ambiguous,"
1019                               " may be one of the following):\n");
1020                        for (i = 0; i < states.heads.nr; i++)
1021                                printf("    %s\n", states.heads.items[i].string);
1022                }
1023
1024                /* remote branch info */
1025                info.width = 0;
1026                for_each_string_list(add_remote_to_show_info, &states.new, &info);
1027                for_each_string_list(add_remote_to_show_info, &states.tracked, &info);
1028                for_each_string_list(add_remote_to_show_info, &states.stale, &info);
1029                if (info.list->nr)
1030                        printf("  Remote branch%s:%s\n",
1031                               info.list->nr > 1 ? "es" : "",
1032                                no_query ? " (status not queried)" : "");
1033                for_each_string_list(show_remote_info_item, info.list, &info);
1034                string_list_clear(info.list, 0);
1035
1036                /* git pull info */
1037                info.width = 0;
1038                info.any_rebase = 0;
1039                for_each_string_list(add_local_to_show_info, &branch_list, &info);
1040                if (info.list->nr)
1041                        printf("  Local branch%s configured for 'git pull':\n",
1042                               info.list->nr > 1 ? "es" : "");
1043                for_each_string_list(show_local_info_item, info.list, &info);
1044                string_list_clear(info.list, 0);
1045
1046                /* git push info */
1047                if (states.remote->mirror)
1048                        printf("  Local refs will be mirrored by 'git push'\n");
1049
1050                info.width = info.width2 = 0;
1051                for_each_string_list(add_push_to_show_info, &states.push, &info);
1052                qsort(info.list->items, info.list->nr,
1053                        sizeof(*info.list->items), cmp_string_with_push);
1054                if (info.list->nr)
1055                        printf("  Local ref%s configured for 'git push'%s:\n",
1056                                info.list->nr > 1 ? "s" : "",
1057                                no_query ? " (status not queried)" : "");
1058                for_each_string_list(show_push_info_item, info.list, &info);
1059                string_list_clear(info.list, 0);
1060
1061                free_remote_ref_states(&states);
1062        }
1063
1064        return result;
1065}
1066
1067static int set_head(int argc, const char **argv)
1068{
1069        int i, opt_a = 0, opt_d = 0, result = 0;
1070        struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
1071        char *head_name = NULL;
1072
1073        struct option options[] = {
1074                OPT_GROUP("set-head specific options"),
1075                OPT_BOOLEAN('a', "auto", &opt_a,
1076                            "set refs/remotes/<name>/HEAD according to remote"),
1077                OPT_BOOLEAN('d', "delete", &opt_d,
1078                            "delete refs/remotes/<name>/HEAD"),
1079                OPT_END()
1080        };
1081        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
1082                             0);
1083        if (argc)
1084                strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
1085
1086        if (!opt_a && !opt_d && argc == 2) {
1087                head_name = xstrdup(argv[1]);
1088        } else if (opt_a && !opt_d && argc == 1) {
1089                struct ref_states states;
1090                memset(&states, 0, sizeof(states));
1091                get_remote_ref_states(argv[0], &states, GET_HEAD_NAMES);
1092                if (!states.heads.nr)
1093                        result |= error("Cannot determine remote HEAD");
1094                else if (states.heads.nr > 1) {
1095                        result |= error("Multiple remote HEAD branches. "
1096                                        "Please choose one explicitly with:");
1097                        for (i = 0; i < states.heads.nr; i++)
1098                                fprintf(stderr, "  git remote set-head %s %s\n",
1099                                        argv[0], states.heads.items[i].string);
1100                } else
1101                        head_name = xstrdup(states.heads.items[0].string);
1102                free_remote_ref_states(&states);
1103        } else if (opt_d && !opt_a && argc == 1) {
1104                if (delete_ref(buf.buf, NULL, REF_NODEREF))
1105                        result |= error("Could not delete %s", buf.buf);
1106        } else
1107                usage_with_options(builtin_remote_usage, options);
1108
1109        if (head_name) {
1110                unsigned char sha1[20];
1111                strbuf_addf(&buf2, "refs/remotes/%s/%s", argv[0], head_name);
1112                /* make sure it's valid */
1113                if (!resolve_ref(buf2.buf, sha1, 1, NULL))
1114                        result |= error("Not a valid ref: %s", buf2.buf);
1115                else if (create_symref(buf.buf, buf2.buf, "remote set-head"))
1116                        result |= error("Could not setup %s", buf.buf);
1117                if (opt_a)
1118                        printf("%s/HEAD set to %s\n", argv[0], head_name);
1119                free(head_name);
1120        }
1121
1122        strbuf_release(&buf);
1123        strbuf_release(&buf2);
1124        return result;
1125}
1126
1127static int prune(int argc, const char **argv)
1128{
1129        int dry_run = 0, result = 0;
1130        struct option options[] = {
1131                OPT_GROUP("prune specific options"),
1132                OPT__DRY_RUN(&dry_run),
1133                OPT_END()
1134        };
1135
1136        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
1137                             0);
1138
1139        if (argc < 1)
1140                usage_with_options(builtin_remote_usage, options);
1141
1142        for (; argc; argc--, argv++)
1143                result |= prune_remote(*argv, dry_run);
1144
1145        return result;
1146}
1147
1148static int prune_remote(const char *remote, int dry_run)
1149{
1150        int result = 0, i;
1151        struct ref_states states;
1152        const char *dangling_msg = dry_run
1153                ? " %s will become dangling!\n"
1154                : " %s has become dangling!\n";
1155
1156        memset(&states, 0, sizeof(states));
1157        get_remote_ref_states(remote, &states, GET_REF_STATES);
1158
1159        if (states.stale.nr) {
1160                printf("Pruning %s\n", remote);
1161                printf("URL: %s\n",
1162                       states.remote->url_nr
1163                       ? states.remote->url[0]
1164                       : "(no URL)");
1165        }
1166
1167        for (i = 0; i < states.stale.nr; i++) {
1168                const char *refname = states.stale.items[i].util;
1169
1170                if (!dry_run)
1171                        result |= delete_ref(refname, NULL, 0);
1172
1173                printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
1174                       abbrev_ref(refname, "refs/remotes/"));
1175                warn_dangling_symref(dangling_msg, refname);
1176        }
1177
1178        free_remote_ref_states(&states);
1179        return result;
1180}
1181
1182static int get_one_remote_for_update(struct remote *remote, void *priv)
1183{
1184        struct string_list *list = priv;
1185        if (!remote->skip_default_update)
1186                string_list_append(remote->name, list);
1187        return 0;
1188}
1189
1190struct remote_group {
1191        const char *name;
1192        struct string_list *list;
1193} remote_group;
1194
1195static int get_remote_group(const char *key, const char *value, void *num_hits)
1196{
1197        if (!prefixcmp(key, "remotes.") &&
1198                        !strcmp(key + 8, remote_group.name)) {
1199                /* split list by white space */
1200                int space = strcspn(value, " \t\n");
1201                while (*value) {
1202                        if (space > 1) {
1203                                string_list_append(xstrndup(value, space),
1204                                                remote_group.list);
1205                                ++*((int *)num_hits);
1206                        }
1207                        value += space + (value[space] != '\0');
1208                        space = strcspn(value, " \t\n");
1209                }
1210        }
1211
1212        return 0;
1213}
1214
1215static int update(int argc, const char **argv)
1216{
1217        int i, result = 0, prune = 0;
1218        struct string_list list = { NULL, 0, 0, 0 };
1219        static const char *default_argv[] = { NULL, "default", NULL };
1220        struct option options[] = {
1221                OPT_GROUP("update specific options"),
1222                OPT_BOOLEAN('p', "prune", &prune,
1223                            "prune remotes after fetching"),
1224                OPT_END()
1225        };
1226
1227        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
1228                             PARSE_OPT_KEEP_ARGV0);
1229        if (argc < 2) {
1230                argc = 2;
1231                argv = default_argv;
1232        }
1233
1234        remote_group.list = &list;
1235        for (i = 1; i < argc; i++) {
1236                int groups_found = 0;
1237                remote_group.name = argv[i];
1238                result = git_config(get_remote_group, &groups_found);
1239                if (!groups_found && (i != 1 || strcmp(argv[1], "default"))) {
1240                        struct remote *remote;
1241                        if (!remote_is_configured(argv[i]))
1242                                die("No such remote or remote group: %s",
1243                                    argv[i]);
1244                        remote = remote_get(argv[i]);
1245                        string_list_append(remote->name, remote_group.list);
1246                }
1247        }
1248
1249        if (!result && !list.nr  && argc == 2 && !strcmp(argv[1], "default"))
1250                result = for_each_remote(get_one_remote_for_update, &list);
1251
1252        for (i = 0; i < list.nr; i++) {
1253                int err = fetch_remote(list.items[i].string);
1254                result |= err;
1255                if (!err && prune)
1256                        result |= prune_remote(list.items[i].string, 0);
1257        }
1258
1259        /* all names were strdup()ed or strndup()ed */
1260        list.strdup_strings = 1;
1261        string_list_clear(&list, 0);
1262
1263        return result;
1264}
1265
1266static int get_one_entry(struct remote *remote, void *priv)
1267{
1268        struct string_list *list = priv;
1269
1270        if (remote->url_nr > 0) {
1271                int i;
1272
1273                for (i = 0; i < remote->url_nr; i++)
1274                        string_list_append(remote->name, list)->util = (void *)remote->url[i];
1275        } else
1276                string_list_append(remote->name, list)->util = NULL;
1277
1278        return 0;
1279}
1280
1281static int show_all(void)
1282{
1283        struct string_list list = { NULL, 0, 0 };
1284        int result = for_each_remote(get_one_entry, &list);
1285
1286        if (!result) {
1287                int i;
1288
1289                sort_string_list(&list);
1290                for (i = 0; i < list.nr; i++) {
1291                        struct string_list_item *item = list.items + i;
1292                        if (verbose)
1293                                printf("%s\t%s\n", item->string,
1294                                        item->util ? (const char *)item->util : "");
1295                        else {
1296                                if (i && !strcmp((item - 1)->string, item->string))
1297                                        continue;
1298                                printf("%s\n", item->string);
1299                        }
1300                }
1301        }
1302        return result;
1303}
1304
1305int cmd_remote(int argc, const char **argv, const char *prefix)
1306{
1307        struct option options[] = {
1308                OPT__VERBOSE(&verbose),
1309                OPT_END()
1310        };
1311        int result;
1312
1313        argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
1314                PARSE_OPT_STOP_AT_NON_OPTION);
1315
1316        if (argc < 1)
1317                result = show_all();
1318        else if (!strcmp(argv[0], "add"))
1319                result = add(argc, argv);
1320        else if (!strcmp(argv[0], "rename"))
1321                result = mv(argc, argv);
1322        else if (!strcmp(argv[0], "rm"))
1323                result = rm(argc, argv);
1324        else if (!strcmp(argv[0], "set-head"))
1325                result = set_head(argc, argv);
1326        else if (!strcmp(argv[0], "show"))
1327                result = show(argc, argv);
1328        else if (!strcmp(argv[0], "prune"))
1329                result = prune(argc, argv);
1330        else if (!strcmp(argv[0], "update"))
1331                result = update(argc, argv);
1332        else {
1333                error("Unknown subcommand: %s", argv[0]);
1334                usage_with_options(builtin_remote_usage, options);
1335        }
1336
1337        return result ? 1 : 0;
1338}