builtin-remote.con commit builtin-remote: Make "remote -v" display push urls (4a4b4cd)
   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                const char **url;
1006                int url_nr;
1007
1008                get_remote_ref_states(*argv, &states, query_flag);
1009
1010                printf("* remote %s\n", *argv);
1011                printf("  Fetch URL: %s\n", states.remote->url_nr > 0 ?
1012                        states.remote->url[0] : "(no URL)");
1013                if (states.remote->pushurl_nr) {
1014                        url = states.remote->pushurl;
1015                        url_nr = states.remote->pushurl_nr;
1016                } else {
1017                        url = states.remote->url;
1018                        url_nr = states.remote->url_nr;
1019                }
1020                for (i=0; i < url_nr; i++)
1021                        printf("  Push  URL: %s\n", url[i]);
1022                if (!i)
1023                        printf("  Push  URL: %s\n", "(no URL)");
1024                if (no_query)
1025                        printf("  HEAD branch: (not queried)\n");
1026                else if (!states.heads.nr)
1027                        printf("  HEAD branch: (unknown)\n");
1028                else if (states.heads.nr == 1)
1029                        printf("  HEAD branch: %s\n", states.heads.items[0].string);
1030                else {
1031                        printf("  HEAD branch (remote HEAD is ambiguous,"
1032                               " may be one of the following):\n");
1033                        for (i = 0; i < states.heads.nr; i++)
1034                                printf("    %s\n", states.heads.items[i].string);
1035                }
1036
1037                /* remote branch info */
1038                info.width = 0;
1039                for_each_string_list(add_remote_to_show_info, &states.new, &info);
1040                for_each_string_list(add_remote_to_show_info, &states.tracked, &info);
1041                for_each_string_list(add_remote_to_show_info, &states.stale, &info);
1042                if (info.list->nr)
1043                        printf("  Remote branch%s:%s\n",
1044                               info.list->nr > 1 ? "es" : "",
1045                                no_query ? " (status not queried)" : "");
1046                for_each_string_list(show_remote_info_item, info.list, &info);
1047                string_list_clear(info.list, 0);
1048
1049                /* git pull info */
1050                info.width = 0;
1051                info.any_rebase = 0;
1052                for_each_string_list(add_local_to_show_info, &branch_list, &info);
1053                if (info.list->nr)
1054                        printf("  Local branch%s configured for 'git pull':\n",
1055                               info.list->nr > 1 ? "es" : "");
1056                for_each_string_list(show_local_info_item, info.list, &info);
1057                string_list_clear(info.list, 0);
1058
1059                /* git push info */
1060                if (states.remote->mirror)
1061                        printf("  Local refs will be mirrored by 'git push'\n");
1062
1063                info.width = info.width2 = 0;
1064                for_each_string_list(add_push_to_show_info, &states.push, &info);
1065                qsort(info.list->items, info.list->nr,
1066                        sizeof(*info.list->items), cmp_string_with_push);
1067                if (info.list->nr)
1068                        printf("  Local ref%s configured for 'git push'%s:\n",
1069                                info.list->nr > 1 ? "s" : "",
1070                                no_query ? " (status not queried)" : "");
1071                for_each_string_list(show_push_info_item, info.list, &info);
1072                string_list_clear(info.list, 0);
1073
1074                free_remote_ref_states(&states);
1075        }
1076
1077        return result;
1078}
1079
1080static int set_head(int argc, const char **argv)
1081{
1082        int i, opt_a = 0, opt_d = 0, result = 0;
1083        struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
1084        char *head_name = NULL;
1085
1086        struct option options[] = {
1087                OPT_GROUP("set-head specific options"),
1088                OPT_BOOLEAN('a', "auto", &opt_a,
1089                            "set refs/remotes/<name>/HEAD according to remote"),
1090                OPT_BOOLEAN('d', "delete", &opt_d,
1091                            "delete refs/remotes/<name>/HEAD"),
1092                OPT_END()
1093        };
1094        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
1095                             0);
1096        if (argc)
1097                strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
1098
1099        if (!opt_a && !opt_d && argc == 2) {
1100                head_name = xstrdup(argv[1]);
1101        } else if (opt_a && !opt_d && argc == 1) {
1102                struct ref_states states;
1103                memset(&states, 0, sizeof(states));
1104                get_remote_ref_states(argv[0], &states, GET_HEAD_NAMES);
1105                if (!states.heads.nr)
1106                        result |= error("Cannot determine remote HEAD");
1107                else if (states.heads.nr > 1) {
1108                        result |= error("Multiple remote HEAD branches. "
1109                                        "Please choose one explicitly with:");
1110                        for (i = 0; i < states.heads.nr; i++)
1111                                fprintf(stderr, "  git remote set-head %s %s\n",
1112                                        argv[0], states.heads.items[i].string);
1113                } else
1114                        head_name = xstrdup(states.heads.items[0].string);
1115                free_remote_ref_states(&states);
1116        } else if (opt_d && !opt_a && argc == 1) {
1117                if (delete_ref(buf.buf, NULL, REF_NODEREF))
1118                        result |= error("Could not delete %s", buf.buf);
1119        } else
1120                usage_with_options(builtin_remote_usage, options);
1121
1122        if (head_name) {
1123                unsigned char sha1[20];
1124                strbuf_addf(&buf2, "refs/remotes/%s/%s", argv[0], head_name);
1125                /* make sure it's valid */
1126                if (!resolve_ref(buf2.buf, sha1, 1, NULL))
1127                        result |= error("Not a valid ref: %s", buf2.buf);
1128                else if (create_symref(buf.buf, buf2.buf, "remote set-head"))
1129                        result |= error("Could not setup %s", buf.buf);
1130                if (opt_a)
1131                        printf("%s/HEAD set to %s\n", argv[0], head_name);
1132                free(head_name);
1133        }
1134
1135        strbuf_release(&buf);
1136        strbuf_release(&buf2);
1137        return result;
1138}
1139
1140static int prune(int argc, const char **argv)
1141{
1142        int dry_run = 0, result = 0;
1143        struct option options[] = {
1144                OPT_GROUP("prune specific options"),
1145                OPT__DRY_RUN(&dry_run),
1146                OPT_END()
1147        };
1148
1149        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
1150                             0);
1151
1152        if (argc < 1)
1153                usage_with_options(builtin_remote_usage, options);
1154
1155        for (; argc; argc--, argv++)
1156                result |= prune_remote(*argv, dry_run);
1157
1158        return result;
1159}
1160
1161static int prune_remote(const char *remote, int dry_run)
1162{
1163        int result = 0, i;
1164        struct ref_states states;
1165        const char *dangling_msg = dry_run
1166                ? " %s will become dangling!\n"
1167                : " %s has become dangling!\n";
1168
1169        memset(&states, 0, sizeof(states));
1170        get_remote_ref_states(remote, &states, GET_REF_STATES);
1171
1172        if (states.stale.nr) {
1173                printf("Pruning %s\n", remote);
1174                printf("URL: %s\n",
1175                       states.remote->url_nr
1176                       ? states.remote->url[0]
1177                       : "(no URL)");
1178        }
1179
1180        for (i = 0; i < states.stale.nr; i++) {
1181                const char *refname = states.stale.items[i].util;
1182
1183                if (!dry_run)
1184                        result |= delete_ref(refname, NULL, 0);
1185
1186                printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
1187                       abbrev_ref(refname, "refs/remotes/"));
1188                warn_dangling_symref(dangling_msg, refname);
1189        }
1190
1191        free_remote_ref_states(&states);
1192        return result;
1193}
1194
1195static int get_one_remote_for_update(struct remote *remote, void *priv)
1196{
1197        struct string_list *list = priv;
1198        if (!remote->skip_default_update)
1199                string_list_append(remote->name, list);
1200        return 0;
1201}
1202
1203struct remote_group {
1204        const char *name;
1205        struct string_list *list;
1206} remote_group;
1207
1208static int get_remote_group(const char *key, const char *value, void *num_hits)
1209{
1210        if (!prefixcmp(key, "remotes.") &&
1211                        !strcmp(key + 8, remote_group.name)) {
1212                /* split list by white space */
1213                int space = strcspn(value, " \t\n");
1214                while (*value) {
1215                        if (space > 1) {
1216                                string_list_append(xstrndup(value, space),
1217                                                remote_group.list);
1218                                ++*((int *)num_hits);
1219                        }
1220                        value += space + (value[space] != '\0');
1221                        space = strcspn(value, " \t\n");
1222                }
1223        }
1224
1225        return 0;
1226}
1227
1228static int update(int argc, const char **argv)
1229{
1230        int i, result = 0, prune = 0;
1231        struct string_list list = { NULL, 0, 0, 0 };
1232        static const char *default_argv[] = { NULL, "default", NULL };
1233        struct option options[] = {
1234                OPT_GROUP("update specific options"),
1235                OPT_BOOLEAN('p', "prune", &prune,
1236                            "prune remotes after fetching"),
1237                OPT_END()
1238        };
1239
1240        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
1241                             PARSE_OPT_KEEP_ARGV0);
1242        if (argc < 2) {
1243                argc = 2;
1244                argv = default_argv;
1245        }
1246
1247        remote_group.list = &list;
1248        for (i = 1; i < argc; i++) {
1249                int groups_found = 0;
1250                remote_group.name = argv[i];
1251                result = git_config(get_remote_group, &groups_found);
1252                if (!groups_found && (i != 1 || strcmp(argv[1], "default"))) {
1253                        struct remote *remote;
1254                        if (!remote_is_configured(argv[i]))
1255                                die("No such remote or remote group: %s",
1256                                    argv[i]);
1257                        remote = remote_get(argv[i]);
1258                        string_list_append(remote->name, remote_group.list);
1259                }
1260        }
1261
1262        if (!result && !list.nr  && argc == 2 && !strcmp(argv[1], "default"))
1263                result = for_each_remote(get_one_remote_for_update, &list);
1264
1265        for (i = 0; i < list.nr; i++) {
1266                int err = fetch_remote(list.items[i].string);
1267                result |= err;
1268                if (!err && prune)
1269                        result |= prune_remote(list.items[i].string, 0);
1270        }
1271
1272        /* all names were strdup()ed or strndup()ed */
1273        list.strdup_strings = 1;
1274        string_list_clear(&list, 0);
1275
1276        return result;
1277}
1278
1279static int get_one_entry(struct remote *remote, void *priv)
1280{
1281        struct string_list *list = priv;
1282        const char **url;
1283        int i, url_nr;
1284        void **utilp;
1285
1286        if (remote->url_nr > 0) {
1287                utilp = &(string_list_append(remote->name, list)->util);
1288                *utilp = malloc(strlen(remote->url[0])+strlen(" (fetch)")+1);
1289                strcpy((char *) *utilp, remote->url[0]);
1290                strcat((char *) *utilp, " (fetch)");
1291        } else
1292                string_list_append(remote->name, list)->util = NULL;
1293        if (remote->pushurl_nr) {
1294                url = remote->pushurl;
1295                url_nr = remote->pushurl_nr;
1296        } else {
1297                url = remote->url;
1298                url_nr = remote->url_nr;
1299        }
1300        for (i = 0; i < url_nr; i++)
1301        {
1302                utilp = &(string_list_append(remote->name, list)->util);
1303                *utilp = malloc(strlen(url[i])+strlen(" (push)")+1);
1304                strcpy((char *) *utilp, url[i]);
1305                strcat((char *) *utilp, " (push)");
1306        }
1307
1308        return 0;
1309}
1310
1311static int show_all(void)
1312{
1313        struct string_list list = { NULL, 0, 0 };
1314        int result;
1315
1316        list.strdup_strings = 1;
1317        result = for_each_remote(get_one_entry, &list);
1318
1319        if (!result) {
1320                int i;
1321
1322                sort_string_list(&list);
1323                for (i = 0; i < list.nr; i++) {
1324                        struct string_list_item *item = list.items + i;
1325                        if (verbose)
1326                                printf("%s\t%s\n", item->string,
1327                                        item->util ? (const char *)item->util : "");
1328                        else {
1329                                if (i && !strcmp((item - 1)->string, item->string))
1330                                        continue;
1331                                printf("%s\n", item->string);
1332                        }
1333                }
1334        }
1335        string_list_clear(&list, 1);
1336        return result;
1337}
1338
1339int cmd_remote(int argc, const char **argv, const char *prefix)
1340{
1341        struct option options[] = {
1342                OPT__VERBOSE(&verbose),
1343                OPT_END()
1344        };
1345        int result;
1346
1347        argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
1348                PARSE_OPT_STOP_AT_NON_OPTION);
1349
1350        if (argc < 1)
1351                result = show_all();
1352        else if (!strcmp(argv[0], "add"))
1353                result = add(argc, argv);
1354        else if (!strcmp(argv[0], "rename"))
1355                result = mv(argc, argv);
1356        else if (!strcmp(argv[0], "rm"))
1357                result = rm(argc, argv);
1358        else if (!strcmp(argv[0], "set-head"))
1359                result = set_head(argc, argv);
1360        else if (!strcmp(argv[0], "show"))
1361                result = show(argc, argv);
1362        else if (!strcmp(argv[0], "prune"))
1363                result = prune(argc, argv);
1364        else if (!strcmp(argv[0], "update"))
1365                result = update(argc, argv);
1366        else {
1367                error("Unknown subcommand: %s", argv[0]);
1368                usage_with_options(builtin_remote_usage, options);
1369        }
1370
1371        return result ? 1 : 0;
1372}