builtin-remote.con commit git: add --no-replace-objects option to disable replacing (b0fa7ab)
   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;
 299        if (remote->mirror)
 300                return 0;
 301
 302        local_refs = get_local_heads();
 303        push_map = copy_ref_list(remote_refs);
 304
 305        match_refs(local_refs, &push_map, remote->push_refspec_nr,
 306                   remote->push_refspec, MATCH_REFS_NONE);
 307
 308        states->push.strdup_strings = 1;
 309        for (ref = push_map; ref; ref = ref->next) {
 310                struct string_list_item *item;
 311                struct push_info *info;
 312
 313                if (!ref->peer_ref)
 314                        continue;
 315                hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
 316
 317                item = string_list_append(abbrev_branch(ref->peer_ref->name),
 318                                          &states->push);
 319                item->util = xcalloc(sizeof(struct push_info), 1);
 320                info = item->util;
 321                info->forced = ref->force;
 322                info->dest = xstrdup(abbrev_branch(ref->name));
 323
 324                if (is_null_sha1(ref->new_sha1)) {
 325                        info->status = PUSH_STATUS_DELETE;
 326                } else if (!hashcmp(ref->old_sha1, ref->new_sha1))
 327                        info->status = PUSH_STATUS_UPTODATE;
 328                else if (is_null_sha1(ref->old_sha1))
 329                        info->status = PUSH_STATUS_CREATE;
 330                else if (has_sha1_file(ref->old_sha1) &&
 331                         ref_newer(ref->new_sha1, ref->old_sha1))
 332                        info->status = PUSH_STATUS_FASTFORWARD;
 333                else
 334                        info->status = PUSH_STATUS_OUTOFDATE;
 335        }
 336        free_refs(local_refs);
 337        free_refs(push_map);
 338        return 0;
 339}
 340
 341static int get_push_ref_states_noquery(struct ref_states *states)
 342{
 343        int i;
 344        struct remote *remote = states->remote;
 345        struct string_list_item *item;
 346        struct push_info *info;
 347
 348        if (remote->mirror)
 349                return 0;
 350
 351        states->push.strdup_strings = 1;
 352        if (!remote->push_refspec_nr) {
 353                item = string_list_append("(matching)", &states->push);
 354                info = item->util = xcalloc(sizeof(struct push_info), 1);
 355                info->status = PUSH_STATUS_NOTQUERIED;
 356                info->dest = xstrdup(item->string);
 357        }
 358        for (i = 0; i < remote->push_refspec_nr; i++) {
 359                struct refspec *spec = remote->push + i;
 360                if (spec->matching)
 361                        item = string_list_append("(matching)", &states->push);
 362                else if (strlen(spec->src))
 363                        item = string_list_append(spec->src, &states->push);
 364                else
 365                        item = string_list_append("(delete)", &states->push);
 366
 367                info = item->util = xcalloc(sizeof(struct push_info), 1);
 368                info->forced = spec->force;
 369                info->status = PUSH_STATUS_NOTQUERIED;
 370                info->dest = xstrdup(spec->dst ? spec->dst : item->string);
 371        }
 372        return 0;
 373}
 374
 375static int get_head_names(const struct ref *remote_refs, struct ref_states *states)
 376{
 377        struct ref *ref, *matches;
 378        struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
 379        struct refspec refspec;
 380
 381        refspec.force = 0;
 382        refspec.pattern = 1;
 383        refspec.src = refspec.dst = "refs/heads/*";
 384        states->heads.strdup_strings = 1;
 385        get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
 386        matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
 387                                    fetch_map, 1);
 388        for (ref = matches; ref; ref = ref->next)
 389                string_list_append(abbrev_branch(ref->name), &states->heads);
 390
 391        free_refs(fetch_map);
 392        free_refs(matches);
 393
 394        return 0;
 395}
 396
 397struct known_remote {
 398        struct known_remote *next;
 399        struct remote *remote;
 400};
 401
 402struct known_remotes {
 403        struct remote *to_delete;
 404        struct known_remote *list;
 405};
 406
 407static int add_known_remote(struct remote *remote, void *cb_data)
 408{
 409        struct known_remotes *all = cb_data;
 410        struct known_remote *r;
 411
 412        if (!strcmp(all->to_delete->name, remote->name))
 413                return 0;
 414
 415        r = xmalloc(sizeof(*r));
 416        r->remote = remote;
 417        r->next = all->list;
 418        all->list = r;
 419        return 0;
 420}
 421
 422struct branches_for_remote {
 423        struct remote *remote;
 424        struct string_list *branches, *skipped;
 425        struct known_remotes *keep;
 426};
 427
 428static int add_branch_for_removal(const char *refname,
 429        const unsigned char *sha1, int flags, void *cb_data)
 430{
 431        struct branches_for_remote *branches = cb_data;
 432        struct refspec refspec;
 433        struct string_list_item *item;
 434        struct known_remote *kr;
 435
 436        memset(&refspec, 0, sizeof(refspec));
 437        refspec.dst = (char *)refname;
 438        if (remote_find_tracking(branches->remote, &refspec))
 439                return 0;
 440
 441        /* don't delete a branch if another remote also uses it */
 442        for (kr = branches->keep->list; kr; kr = kr->next) {
 443                memset(&refspec, 0, sizeof(refspec));
 444                refspec.dst = (char *)refname;
 445                if (!remote_find_tracking(kr->remote, &refspec))
 446                        return 0;
 447        }
 448
 449        /* don't delete non-remote refs */
 450        if (prefixcmp(refname, "refs/remotes")) {
 451                /* advise user how to delete local branches */
 452                if (!prefixcmp(refname, "refs/heads/"))
 453                        string_list_append(abbrev_branch(refname),
 454                                           branches->skipped);
 455                /* silently skip over other non-remote refs */
 456                return 0;
 457        }
 458
 459        /* make sure that symrefs are deleted */
 460        if (flags & REF_ISSYMREF)
 461                return unlink(git_path("%s", refname));
 462
 463        item = string_list_append(refname, branches->branches);
 464        item->util = xmalloc(20);
 465        hashcpy(item->util, sha1);
 466
 467        return 0;
 468}
 469
 470struct rename_info {
 471        const char *old;
 472        const char *new;
 473        struct string_list *remote_branches;
 474};
 475
 476static int read_remote_branches(const char *refname,
 477        const unsigned char *sha1, int flags, void *cb_data)
 478{
 479        struct rename_info *rename = cb_data;
 480        struct strbuf buf = STRBUF_INIT;
 481        struct string_list_item *item;
 482        int flag;
 483        unsigned char orig_sha1[20];
 484        const char *symref;
 485
 486        strbuf_addf(&buf, "refs/remotes/%s", rename->old);
 487        if (!prefixcmp(refname, buf.buf)) {
 488                item = string_list_append(xstrdup(refname), rename->remote_branches);
 489                symref = resolve_ref(refname, orig_sha1, 1, &flag);
 490                if (flag & REF_ISSYMREF)
 491                        item->util = xstrdup(symref);
 492                else
 493                        item->util = NULL;
 494        }
 495
 496        return 0;
 497}
 498
 499static int migrate_file(struct remote *remote)
 500{
 501        struct strbuf buf = STRBUF_INIT;
 502        int i;
 503        char *path = NULL;
 504
 505        strbuf_addf(&buf, "remote.%s.url", remote->name);
 506        for (i = 0; i < remote->url_nr; i++)
 507                if (git_config_set_multivar(buf.buf, remote->url[i], "^$", 0))
 508                        return error("Could not append '%s' to '%s'",
 509                                        remote->url[i], buf.buf);
 510        strbuf_reset(&buf);
 511        strbuf_addf(&buf, "remote.%s.push", remote->name);
 512        for (i = 0; i < remote->push_refspec_nr; i++)
 513                if (git_config_set_multivar(buf.buf, remote->push_refspec[i], "^$", 0))
 514                        return error("Could not append '%s' to '%s'",
 515                                        remote->push_refspec[i], buf.buf);
 516        strbuf_reset(&buf);
 517        strbuf_addf(&buf, "remote.%s.fetch", remote->name);
 518        for (i = 0; i < remote->fetch_refspec_nr; i++)
 519                if (git_config_set_multivar(buf.buf, remote->fetch_refspec[i], "^$", 0))
 520                        return error("Could not append '%s' to '%s'",
 521                                        remote->fetch_refspec[i], buf.buf);
 522        if (remote->origin == REMOTE_REMOTES)
 523                path = git_path("remotes/%s", remote->name);
 524        else if (remote->origin == REMOTE_BRANCHES)
 525                path = git_path("branches/%s", remote->name);
 526        if (path)
 527                unlink_or_warn(path);
 528        return 0;
 529}
 530
 531static int mv(int argc, const char **argv)
 532{
 533        struct option options[] = {
 534                OPT_END()
 535        };
 536        struct remote *oldremote, *newremote;
 537        struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT;
 538        struct string_list remote_branches = { NULL, 0, 0, 0 };
 539        struct rename_info rename;
 540        int i;
 541
 542        if (argc != 3)
 543                usage_with_options(builtin_remote_usage, options);
 544
 545        rename.old = argv[1];
 546        rename.new = argv[2];
 547        rename.remote_branches = &remote_branches;
 548
 549        oldremote = remote_get(rename.old);
 550        if (!oldremote)
 551                die("No such remote: %s", rename.old);
 552
 553        if (!strcmp(rename.old, rename.new) && oldremote->origin != REMOTE_CONFIG)
 554                return migrate_file(oldremote);
 555
 556        newremote = remote_get(rename.new);
 557        if (newremote && (newremote->url_nr > 1 || newremote->fetch_refspec_nr))
 558                die("remote %s already exists.", rename.new);
 559
 560        strbuf_addf(&buf, "refs/heads/test:refs/remotes/%s/test", rename.new);
 561        if (!valid_fetch_refspec(buf.buf))
 562                die("'%s' is not a valid remote name", rename.new);
 563
 564        strbuf_reset(&buf);
 565        strbuf_addf(&buf, "remote.%s", rename.old);
 566        strbuf_addf(&buf2, "remote.%s", rename.new);
 567        if (git_config_rename_section(buf.buf, buf2.buf) < 1)
 568                return error("Could not rename config section '%s' to '%s'",
 569                                buf.buf, buf2.buf);
 570
 571        strbuf_reset(&buf);
 572        strbuf_addf(&buf, "remote.%s.fetch", rename.new);
 573        if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
 574                return error("Could not remove config section '%s'", buf.buf);
 575        for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
 576                char *ptr;
 577
 578                strbuf_reset(&buf2);
 579                strbuf_addstr(&buf2, oldremote->fetch_refspec[i]);
 580                ptr = strstr(buf2.buf, rename.old);
 581                if (ptr)
 582                        strbuf_splice(&buf2, ptr-buf2.buf, strlen(rename.old),
 583                                        rename.new, strlen(rename.new));
 584                if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
 585                        return error("Could not append '%s'", buf.buf);
 586        }
 587
 588        read_branches();
 589        for (i = 0; i < branch_list.nr; i++) {
 590                struct string_list_item *item = branch_list.items + i;
 591                struct branch_info *info = item->util;
 592                if (info->remote_name && !strcmp(info->remote_name, rename.old)) {
 593                        strbuf_reset(&buf);
 594                        strbuf_addf(&buf, "branch.%s.remote", item->string);
 595                        if (git_config_set(buf.buf, rename.new)) {
 596                                return error("Could not set '%s'", buf.buf);
 597                        }
 598                }
 599        }
 600
 601        /*
 602         * First remove symrefs, then rename the rest, finally create
 603         * the new symrefs.
 604         */
 605        for_each_ref(read_remote_branches, &rename);
 606        for (i = 0; i < remote_branches.nr; i++) {
 607                struct string_list_item *item = remote_branches.items + i;
 608                int flag = 0;
 609                unsigned char sha1[20];
 610
 611                resolve_ref(item->string, sha1, 1, &flag);
 612                if (!(flag & REF_ISSYMREF))
 613                        continue;
 614                if (delete_ref(item->string, NULL, REF_NODEREF))
 615                        die("deleting '%s' failed", item->string);
 616        }
 617        for (i = 0; i < remote_branches.nr; i++) {
 618                struct string_list_item *item = remote_branches.items + i;
 619
 620                if (item->util)
 621                        continue;
 622                strbuf_reset(&buf);
 623                strbuf_addstr(&buf, item->string);
 624                strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old),
 625                                rename.new, strlen(rename.new));
 626                strbuf_reset(&buf2);
 627                strbuf_addf(&buf2, "remote: renamed %s to %s",
 628                                item->string, buf.buf);
 629                if (rename_ref(item->string, buf.buf, buf2.buf))
 630                        die("renaming '%s' failed", item->string);
 631        }
 632        for (i = 0; i < remote_branches.nr; i++) {
 633                struct string_list_item *item = remote_branches.items + i;
 634
 635                if (!item->util)
 636                        continue;
 637                strbuf_reset(&buf);
 638                strbuf_addstr(&buf, item->string);
 639                strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old),
 640                                rename.new, strlen(rename.new));
 641                strbuf_reset(&buf2);
 642                strbuf_addstr(&buf2, item->util);
 643                strbuf_splice(&buf2, strlen("refs/remotes/"), strlen(rename.old),
 644                                rename.new, strlen(rename.new));
 645                strbuf_reset(&buf3);
 646                strbuf_addf(&buf3, "remote: renamed %s to %s",
 647                                item->string, buf.buf);
 648                if (create_symref(buf.buf, buf2.buf, buf3.buf))
 649                        die("creating '%s' failed", buf.buf);
 650        }
 651        return 0;
 652}
 653
 654static int remove_branches(struct string_list *branches)
 655{
 656        int i, result = 0;
 657        for (i = 0; i < branches->nr; i++) {
 658                struct string_list_item *item = branches->items + i;
 659                const char *refname = item->string;
 660                unsigned char *sha1 = item->util;
 661
 662                if (delete_ref(refname, sha1, 0))
 663                        result |= error("Could not remove branch %s", refname);
 664        }
 665        return result;
 666}
 667
 668static int rm(int argc, const char **argv)
 669{
 670        struct option options[] = {
 671                OPT_END()
 672        };
 673        struct remote *remote;
 674        struct strbuf buf = STRBUF_INIT;
 675        struct known_remotes known_remotes = { NULL, NULL };
 676        struct string_list branches = { NULL, 0, 0, 1 };
 677        struct string_list skipped = { NULL, 0, 0, 1 };
 678        struct branches_for_remote cb_data = {
 679                NULL, &branches, &skipped, &known_remotes
 680        };
 681        int i, result;
 682
 683        if (argc != 2)
 684                usage_with_options(builtin_remote_usage, options);
 685
 686        remote = remote_get(argv[1]);
 687        if (!remote)
 688                die("No such remote: %s", argv[1]);
 689
 690        known_remotes.to_delete = remote;
 691        for_each_remote(add_known_remote, &known_remotes);
 692
 693        strbuf_addf(&buf, "remote.%s", remote->name);
 694        if (git_config_rename_section(buf.buf, NULL) < 1)
 695                return error("Could not remove config section '%s'", buf.buf);
 696
 697        read_branches();
 698        for (i = 0; i < branch_list.nr; i++) {
 699                struct string_list_item *item = branch_list.items + i;
 700                struct branch_info *info = item->util;
 701                if (info->remote_name && !strcmp(info->remote_name, remote->name)) {
 702                        const char *keys[] = { "remote", "merge", NULL }, **k;
 703                        for (k = keys; *k; k++) {
 704                                strbuf_reset(&buf);
 705                                strbuf_addf(&buf, "branch.%s.%s",
 706                                                item->string, *k);
 707                                if (git_config_set(buf.buf, NULL)) {
 708                                        strbuf_release(&buf);
 709                                        return -1;
 710                                }
 711                        }
 712                }
 713        }
 714
 715        /*
 716         * We cannot just pass a function to for_each_ref() which deletes
 717         * the branches one by one, since for_each_ref() relies on cached
 718         * refs, which are invalidated when deleting a branch.
 719         */
 720        cb_data.remote = remote;
 721        result = for_each_ref(add_branch_for_removal, &cb_data);
 722        strbuf_release(&buf);
 723
 724        if (!result)
 725                result = remove_branches(&branches);
 726        string_list_clear(&branches, 1);
 727
 728        if (skipped.nr) {
 729                fprintf(stderr, skipped.nr == 1 ?
 730                        "Note: A non-remote branch was not removed; "
 731                        "to delete it, use:\n" :
 732                        "Note: Non-remote branches were not removed; "
 733                        "to delete them, use:\n");
 734                for (i = 0; i < skipped.nr; i++)
 735                        fprintf(stderr, "  git branch -d %s\n",
 736                                skipped.items[i].string);
 737        }
 738        string_list_clear(&skipped, 0);
 739
 740        return result;
 741}
 742
 743static void clear_push_info(void *util, const char *string)
 744{
 745        struct push_info *info = util;
 746        free(info->dest);
 747        free(info);
 748}
 749
 750static void free_remote_ref_states(struct ref_states *states)
 751{
 752        string_list_clear(&states->new, 0);
 753        string_list_clear(&states->stale, 0);
 754        string_list_clear(&states->tracked, 0);
 755        string_list_clear(&states->heads, 0);
 756        string_list_clear_func(&states->push, clear_push_info);
 757}
 758
 759static int append_ref_to_tracked_list(const char *refname,
 760        const unsigned char *sha1, int flags, void *cb_data)
 761{
 762        struct ref_states *states = cb_data;
 763        struct refspec refspec;
 764
 765        if (flags & REF_ISSYMREF)
 766                return 0;
 767
 768        memset(&refspec, 0, sizeof(refspec));
 769        refspec.dst = (char *)refname;
 770        if (!remote_find_tracking(states->remote, &refspec))
 771                string_list_append(abbrev_branch(refspec.src), &states->tracked);
 772
 773        return 0;
 774}
 775
 776static int get_remote_ref_states(const char *name,
 777                                 struct ref_states *states,
 778                                 int query)
 779{
 780        struct transport *transport;
 781        const struct ref *remote_refs;
 782
 783        states->remote = remote_get(name);
 784        if (!states->remote)
 785                return error("No such remote: %s", name);
 786
 787        read_branches();
 788
 789        if (query) {
 790                transport = transport_get(states->remote, states->remote->url_nr > 0 ?
 791                        states->remote->url[0] : NULL);
 792                remote_refs = transport_get_remote_refs(transport);
 793                transport_disconnect(transport);
 794
 795                states->queried = 1;
 796                if (query & GET_REF_STATES)
 797                        get_ref_states(remote_refs, states);
 798                if (query & GET_HEAD_NAMES)
 799                        get_head_names(remote_refs, states);
 800                if (query & GET_PUSH_REF_STATES)
 801                        get_push_ref_states(remote_refs, states);
 802        } else {
 803                for_each_ref(append_ref_to_tracked_list, states);
 804                sort_string_list(&states->tracked);
 805                get_push_ref_states_noquery(states);
 806        }
 807
 808        return 0;
 809}
 810
 811struct show_info {
 812        struct string_list *list;
 813        struct ref_states *states;
 814        int width, width2;
 815        int any_rebase;
 816};
 817
 818static int add_remote_to_show_info(struct string_list_item *item, void *cb_data)
 819{
 820        struct show_info *info = cb_data;
 821        int n = strlen(item->string);
 822        if (n > info->width)
 823                info->width = n;
 824        string_list_insert(item->string, info->list);
 825        return 0;
 826}
 827
 828static int show_remote_info_item(struct string_list_item *item, void *cb_data)
 829{
 830        struct show_info *info = cb_data;
 831        struct ref_states *states = info->states;
 832        const char *name = item->string;
 833
 834        if (states->queried) {
 835                const char *fmt = "%s";
 836                const char *arg = "";
 837                if (string_list_has_string(&states->new, name)) {
 838                        fmt = " new (next fetch will store in remotes/%s)";
 839                        arg = states->remote->name;
 840                } else if (string_list_has_string(&states->tracked, name))
 841                        arg = " tracked";
 842                else if (string_list_has_string(&states->stale, name))
 843                        arg = " stale (use 'git remote prune' to remove)";
 844                else
 845                        arg = " ???";
 846                printf("    %-*s", info->width, name);
 847                printf(fmt, arg);
 848                printf("\n");
 849        } else
 850                printf("    %s\n", name);
 851
 852        return 0;
 853}
 854
 855static int add_local_to_show_info(struct string_list_item *branch_item, void *cb_data)
 856{
 857        struct show_info *show_info = cb_data;
 858        struct ref_states *states = show_info->states;
 859        struct branch_info *branch_info = branch_item->util;
 860        struct string_list_item *item;
 861        int n;
 862
 863        if (!branch_info->merge.nr || !branch_info->remote_name ||
 864            strcmp(states->remote->name, branch_info->remote_name))
 865                return 0;
 866        if ((n = strlen(branch_item->string)) > show_info->width)
 867                show_info->width = n;
 868        if (branch_info->rebase)
 869                show_info->any_rebase = 1;
 870
 871        item = string_list_insert(branch_item->string, show_info->list);
 872        item->util = branch_info;
 873
 874        return 0;
 875}
 876
 877static int show_local_info_item(struct string_list_item *item, void *cb_data)
 878{
 879        struct show_info *show_info = cb_data;
 880        struct branch_info *branch_info = item->util;
 881        struct string_list *merge = &branch_info->merge;
 882        const char *also;
 883        int i;
 884
 885        if (branch_info->rebase && branch_info->merge.nr > 1) {
 886                error("invalid branch.%s.merge; cannot rebase onto > 1 branch",
 887                        item->string);
 888                return 0;
 889        }
 890
 891        printf("    %-*s ", show_info->width, item->string);
 892        if (branch_info->rebase) {
 893                printf("rebases onto remote %s\n", merge->items[0].string);
 894                return 0;
 895        } else if (show_info->any_rebase) {
 896                printf(" merges with remote %s\n", merge->items[0].string);
 897                also = "    and with remote";
 898        } else {
 899                printf("merges with remote %s\n", merge->items[0].string);
 900                also = "   and with remote";
 901        }
 902        for (i = 1; i < merge->nr; i++)
 903                printf("    %-*s %s %s\n", show_info->width, "", also,
 904                       merge->items[i].string);
 905
 906        return 0;
 907}
 908
 909static int add_push_to_show_info(struct string_list_item *push_item, void *cb_data)
 910{
 911        struct show_info *show_info = cb_data;
 912        struct push_info *push_info = push_item->util;
 913        struct string_list_item *item;
 914        int n;
 915        if ((n = strlen(push_item->string)) > show_info->width)
 916                show_info->width = n;
 917        if ((n = strlen(push_info->dest)) > show_info->width2)
 918                show_info->width2 = n;
 919        item = string_list_append(push_item->string, show_info->list);
 920        item->util = push_item->util;
 921        return 0;
 922}
 923
 924/*
 925 * Sorting comparison for a string list that has push_info
 926 * structs in its util field
 927 */
 928static int cmp_string_with_push(const void *va, const void *vb)
 929{
 930        const struct string_list_item *a = va;
 931        const struct string_list_item *b = vb;
 932        const struct push_info *a_push = a->util;
 933        const struct push_info *b_push = b->util;
 934        int cmp = strcmp(a->string, b->string);
 935        return cmp ? cmp : strcmp(a_push->dest, b_push->dest);
 936}
 937
 938static int show_push_info_item(struct string_list_item *item, void *cb_data)
 939{
 940        struct show_info *show_info = cb_data;
 941        struct push_info *push_info = item->util;
 942        char *src = item->string, *status = NULL;
 943
 944        switch (push_info->status) {
 945        case PUSH_STATUS_CREATE:
 946                status = "create";
 947                break;
 948        case PUSH_STATUS_DELETE:
 949                status = "delete";
 950                src = "(none)";
 951                break;
 952        case PUSH_STATUS_UPTODATE:
 953                status = "up to date";
 954                break;
 955        case PUSH_STATUS_FASTFORWARD:
 956                status = "fast forwardable";
 957                break;
 958        case PUSH_STATUS_OUTOFDATE:
 959                status = "local out of date";
 960                break;
 961        case PUSH_STATUS_NOTQUERIED:
 962                break;
 963        }
 964        if (status)
 965                printf("    %-*s %s to %-*s (%s)\n", show_info->width, src,
 966                        push_info->forced ? "forces" : "pushes",
 967                        show_info->width2, push_info->dest, status);
 968        else
 969                printf("    %-*s %s to %s\n", show_info->width, src,
 970                        push_info->forced ? "forces" : "pushes",
 971                        push_info->dest);
 972        return 0;
 973}
 974
 975static int show(int argc, const char **argv)
 976{
 977        int no_query = 0, result = 0, query_flag = 0;
 978        struct option options[] = {
 979                OPT_GROUP("show specific options"),
 980                OPT_BOOLEAN('n', NULL, &no_query, "do not query remotes"),
 981                OPT_END()
 982        };
 983        struct ref_states states;
 984        struct string_list info_list = { NULL, 0, 0, 0 };
 985        struct show_info info;
 986
 987        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
 988                             0);
 989
 990        if (argc < 1)
 991                return show_all();
 992
 993        if (!no_query)
 994                query_flag = (GET_REF_STATES | GET_HEAD_NAMES | GET_PUSH_REF_STATES);
 995
 996        memset(&states, 0, sizeof(states));
 997        memset(&info, 0, sizeof(info));
 998        info.states = &states;
 999        info.list = &info_list;
1000        for (; argc; argc--, argv++) {
1001                int i;
1002                const char **url;
1003                int url_nr;
1004
1005                get_remote_ref_states(*argv, &states, query_flag);
1006
1007                printf("* remote %s\n", *argv);
1008                printf("  Fetch URL: %s\n", states.remote->url_nr > 0 ?
1009                        states.remote->url[0] : "(no URL)");
1010                if (states.remote->pushurl_nr) {
1011                        url = states.remote->pushurl;
1012                        url_nr = states.remote->pushurl_nr;
1013                } else {
1014                        url = states.remote->url;
1015                        url_nr = states.remote->url_nr;
1016                }
1017                for (i=0; i < url_nr; i++)
1018                        printf("  Push  URL: %s\n", url[i]);
1019                if (!i)
1020                        printf("  Push  URL: %s\n", "(no URL)");
1021                if (no_query)
1022                        printf("  HEAD branch: (not queried)\n");
1023                else if (!states.heads.nr)
1024                        printf("  HEAD branch: (unknown)\n");
1025                else if (states.heads.nr == 1)
1026                        printf("  HEAD branch: %s\n", states.heads.items[0].string);
1027                else {
1028                        printf("  HEAD branch (remote HEAD is ambiguous,"
1029                               " may be one of the following):\n");
1030                        for (i = 0; i < states.heads.nr; i++)
1031                                printf("    %s\n", states.heads.items[i].string);
1032                }
1033
1034                /* remote branch info */
1035                info.width = 0;
1036                for_each_string_list(add_remote_to_show_info, &states.new, &info);
1037                for_each_string_list(add_remote_to_show_info, &states.tracked, &info);
1038                for_each_string_list(add_remote_to_show_info, &states.stale, &info);
1039                if (info.list->nr)
1040                        printf("  Remote branch%s:%s\n",
1041                               info.list->nr > 1 ? "es" : "",
1042                                no_query ? " (status not queried)" : "");
1043                for_each_string_list(show_remote_info_item, info.list, &info);
1044                string_list_clear(info.list, 0);
1045
1046                /* git pull info */
1047                info.width = 0;
1048                info.any_rebase = 0;
1049                for_each_string_list(add_local_to_show_info, &branch_list, &info);
1050                if (info.list->nr)
1051                        printf("  Local branch%s configured for 'git pull':\n",
1052                               info.list->nr > 1 ? "es" : "");
1053                for_each_string_list(show_local_info_item, info.list, &info);
1054                string_list_clear(info.list, 0);
1055
1056                /* git push info */
1057                if (states.remote->mirror)
1058                        printf("  Local refs will be mirrored by 'git push'\n");
1059
1060                info.width = info.width2 = 0;
1061                for_each_string_list(add_push_to_show_info, &states.push, &info);
1062                qsort(info.list->items, info.list->nr,
1063                        sizeof(*info.list->items), cmp_string_with_push);
1064                if (info.list->nr)
1065                        printf("  Local ref%s configured for 'git push'%s:\n",
1066                                info.list->nr > 1 ? "s" : "",
1067                                no_query ? " (status not queried)" : "");
1068                for_each_string_list(show_push_info_item, info.list, &info);
1069                string_list_clear(info.list, 0);
1070
1071                free_remote_ref_states(&states);
1072        }
1073
1074        return result;
1075}
1076
1077static int set_head(int argc, const char **argv)
1078{
1079        int i, opt_a = 0, opt_d = 0, result = 0;
1080        struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
1081        char *head_name = NULL;
1082
1083        struct option options[] = {
1084                OPT_GROUP("set-head specific options"),
1085                OPT_BOOLEAN('a', "auto", &opt_a,
1086                            "set refs/remotes/<name>/HEAD according to remote"),
1087                OPT_BOOLEAN('d', "delete", &opt_d,
1088                            "delete refs/remotes/<name>/HEAD"),
1089                OPT_END()
1090        };
1091        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
1092                             0);
1093        if (argc)
1094                strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
1095
1096        if (!opt_a && !opt_d && argc == 2) {
1097                head_name = xstrdup(argv[1]);
1098        } else if (opt_a && !opt_d && argc == 1) {
1099                struct ref_states states;
1100                memset(&states, 0, sizeof(states));
1101                get_remote_ref_states(argv[0], &states, GET_HEAD_NAMES);
1102                if (!states.heads.nr)
1103                        result |= error("Cannot determine remote HEAD");
1104                else if (states.heads.nr > 1) {
1105                        result |= error("Multiple remote HEAD branches. "
1106                                        "Please choose one explicitly with:");
1107                        for (i = 0; i < states.heads.nr; i++)
1108                                fprintf(stderr, "  git remote set-head %s %s\n",
1109                                        argv[0], states.heads.items[i].string);
1110                } else
1111                        head_name = xstrdup(states.heads.items[0].string);
1112                free_remote_ref_states(&states);
1113        } else if (opt_d && !opt_a && argc == 1) {
1114                if (delete_ref(buf.buf, NULL, REF_NODEREF))
1115                        result |= error("Could not delete %s", buf.buf);
1116        } else
1117                usage_with_options(builtin_remote_usage, options);
1118
1119        if (head_name) {
1120                unsigned char sha1[20];
1121                strbuf_addf(&buf2, "refs/remotes/%s/%s", argv[0], head_name);
1122                /* make sure it's valid */
1123                if (!resolve_ref(buf2.buf, sha1, 1, NULL))
1124                        result |= error("Not a valid ref: %s", buf2.buf);
1125                else if (create_symref(buf.buf, buf2.buf, "remote set-head"))
1126                        result |= error("Could not setup %s", buf.buf);
1127                if (opt_a)
1128                        printf("%s/HEAD set to %s\n", argv[0], head_name);
1129                free(head_name);
1130        }
1131
1132        strbuf_release(&buf);
1133        strbuf_release(&buf2);
1134        return result;
1135}
1136
1137static int prune(int argc, const char **argv)
1138{
1139        int dry_run = 0, result = 0;
1140        struct option options[] = {
1141                OPT_GROUP("prune specific options"),
1142                OPT__DRY_RUN(&dry_run),
1143                OPT_END()
1144        };
1145
1146        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
1147                             0);
1148
1149        if (argc < 1)
1150                usage_with_options(builtin_remote_usage, options);
1151
1152        for (; argc; argc--, argv++)
1153                result |= prune_remote(*argv, dry_run);
1154
1155        return result;
1156}
1157
1158static int prune_remote(const char *remote, int dry_run)
1159{
1160        int result = 0, i;
1161        struct ref_states states;
1162        const char *dangling_msg = dry_run
1163                ? " %s will become dangling!\n"
1164                : " %s has become dangling!\n";
1165
1166        memset(&states, 0, sizeof(states));
1167        get_remote_ref_states(remote, &states, GET_REF_STATES);
1168
1169        if (states.stale.nr) {
1170                printf("Pruning %s\n", remote);
1171                printf("URL: %s\n",
1172                       states.remote->url_nr
1173                       ? states.remote->url[0]
1174                       : "(no URL)");
1175        }
1176
1177        for (i = 0; i < states.stale.nr; i++) {
1178                const char *refname = states.stale.items[i].util;
1179
1180                if (!dry_run)
1181                        result |= delete_ref(refname, NULL, 0);
1182
1183                printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
1184                       abbrev_ref(refname, "refs/remotes/"));
1185                warn_dangling_symref(dangling_msg, refname);
1186        }
1187
1188        free_remote_ref_states(&states);
1189        return result;
1190}
1191
1192static int get_one_remote_for_update(struct remote *remote, void *priv)
1193{
1194        struct string_list *list = priv;
1195        if (!remote->skip_default_update)
1196                string_list_append(remote->name, list);
1197        return 0;
1198}
1199
1200static struct remote_group {
1201        const char *name;
1202        struct string_list *list;
1203} remote_group;
1204
1205static int get_remote_group(const char *key, const char *value, void *num_hits)
1206{
1207        if (!prefixcmp(key, "remotes.") &&
1208                        !strcmp(key + 8, remote_group.name)) {
1209                /* split list by white space */
1210                int space = strcspn(value, " \t\n");
1211                while (*value) {
1212                        if (space > 1) {
1213                                string_list_append(xstrndup(value, space),
1214                                                remote_group.list);
1215                                ++*((int *)num_hits);
1216                        }
1217                        value += space + (value[space] != '\0');
1218                        space = strcspn(value, " \t\n");
1219                }
1220        }
1221
1222        return 0;
1223}
1224
1225static int update(int argc, const char **argv)
1226{
1227        int i, result = 0, prune = 0;
1228        struct string_list list = { NULL, 0, 0, 0 };
1229        static const char *default_argv[] = { NULL, "default", NULL };
1230        struct option options[] = {
1231                OPT_GROUP("update specific options"),
1232                OPT_BOOLEAN('p', "prune", &prune,
1233                            "prune remotes after fetching"),
1234                OPT_END()
1235        };
1236
1237        argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
1238                             PARSE_OPT_KEEP_ARGV0);
1239        if (argc < 2) {
1240                argc = 2;
1241                argv = default_argv;
1242        }
1243
1244        remote_group.list = &list;
1245        for (i = 1; i < argc; i++) {
1246                int groups_found = 0;
1247                remote_group.name = argv[i];
1248                result = git_config(get_remote_group, &groups_found);
1249                if (!groups_found && (i != 1 || strcmp(argv[1], "default"))) {
1250                        struct remote *remote;
1251                        if (!remote_is_configured(argv[i]))
1252                                die("No such remote or remote group: %s",
1253                                    argv[i]);
1254                        remote = remote_get(argv[i]);
1255                        string_list_append(remote->name, remote_group.list);
1256                }
1257        }
1258
1259        if (!result && !list.nr  && argc == 2 && !strcmp(argv[1], "default"))
1260                result = for_each_remote(get_one_remote_for_update, &list);
1261
1262        for (i = 0; i < list.nr; i++) {
1263                int err = fetch_remote(list.items[i].string);
1264                result |= err;
1265                if (!err && prune)
1266                        result |= prune_remote(list.items[i].string, 0);
1267        }
1268
1269        /* all names were strdup()ed or strndup()ed */
1270        list.strdup_strings = 1;
1271        string_list_clear(&list, 0);
1272
1273        return result;
1274}
1275
1276static int get_one_entry(struct remote *remote, void *priv)
1277{
1278        struct string_list *list = priv;
1279        struct strbuf url_buf = STRBUF_INIT;
1280        const char **url;
1281        int i, url_nr;
1282
1283        if (remote->url_nr > 0) {
1284                strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]);
1285                string_list_append(remote->name, list)->util =
1286                                strbuf_detach(&url_buf, NULL);
1287        } else
1288                string_list_append(remote->name, list)->util = NULL;
1289        if (remote->pushurl_nr) {
1290                url = remote->pushurl;
1291                url_nr = remote->pushurl_nr;
1292        } else {
1293                url = remote->url;
1294                url_nr = remote->url_nr;
1295        }
1296        for (i = 0; i < url_nr; i++)
1297        {
1298                strbuf_addf(&url_buf, "%s (push)", url[i]);
1299                string_list_append(remote->name, list)->util =
1300                                strbuf_detach(&url_buf, NULL);
1301        }
1302
1303        return 0;
1304}
1305
1306static int show_all(void)
1307{
1308        struct string_list list = { NULL, 0, 0 };
1309        int result;
1310
1311        list.strdup_strings = 1;
1312        result = for_each_remote(get_one_entry, &list);
1313
1314        if (!result) {
1315                int i;
1316
1317                sort_string_list(&list);
1318                for (i = 0; i < list.nr; i++) {
1319                        struct string_list_item *item = list.items + i;
1320                        if (verbose)
1321                                printf("%s\t%s\n", item->string,
1322                                        item->util ? (const char *)item->util : "");
1323                        else {
1324                                if (i && !strcmp((item - 1)->string, item->string))
1325                                        continue;
1326                                printf("%s\n", item->string);
1327                        }
1328                }
1329        }
1330        string_list_clear(&list, 1);
1331        return result;
1332}
1333
1334int cmd_remote(int argc, const char **argv, const char *prefix)
1335{
1336        struct option options[] = {
1337                OPT__VERBOSE(&verbose),
1338                OPT_END()
1339        };
1340        int result;
1341
1342        argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
1343                PARSE_OPT_STOP_AT_NON_OPTION);
1344
1345        if (argc < 1)
1346                result = show_all();
1347        else if (!strcmp(argv[0], "add"))
1348                result = add(argc, argv);
1349        else if (!strcmp(argv[0], "rename"))
1350                result = mv(argc, argv);
1351        else if (!strcmp(argv[0], "rm"))
1352                result = rm(argc, argv);
1353        else if (!strcmp(argv[0], "set-head"))
1354                result = set_head(argc, argv);
1355        else if (!strcmp(argv[0], "show"))
1356                result = show(argc, argv);
1357        else if (!strcmp(argv[0], "prune"))
1358                result = prune(argc, argv);
1359        else if (!strcmp(argv[0], "update"))
1360                result = update(argc, argv);
1361        else {
1362                error("Unknown subcommand: %s", argv[0]);
1363                usage_with_options(builtin_remote_usage, options);
1364        }
1365
1366        return result ? 1 : 0;
1367}