Merge branch 'jc/diff-irreversible-delete'
[gitweb.git] / builtin / remote.c
index 6699bc571235167f5cae60106522c09a10ae341d..8424152269e309cb86e4ff530b9feacc23fc17a6 100644 (file)
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "builtin.h"
 #include "parse-options.h"
 #include "transport.h"
 #include "remote.h"
@@ -9,13 +9,13 @@
 
 static const char * const builtin_remote_usage[] = {
        "git remote [-v | --verbose]",
-       "git remote add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>",
+       "git remote add [-t <branch>] [-m <master>] [-f] [--mirror=<fetch|push>] <name> <url>",
        "git remote rename <old> <new>",
        "git remote rm <name>",
        "git remote set-head <name> (-a | -d | <branch>)",
        "git remote [-v | --verbose] show [-n] <name>",
        "git remote prune [-n | --dry-run] <name>",
-       "git remote [-v | --verbose] update [-p | --prune] [group | remote]",
+       "git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]",
        "git remote set-branches <name> [--add] <branch>...",
        "git remote set-url <name> <newurl> [<oldurl>]",
        "git remote set-url --add <name> <newurl>",
@@ -117,6 +117,11 @@ enum {
        TAGS_SET = 2
 };
 
+#define MIRROR_NONE 0
+#define MIRROR_FETCH 1
+#define MIRROR_PUSH 2
+#define MIRROR_BOTH (MIRROR_FETCH|MIRROR_PUSH)
+
 static int add_branch(const char *key, const char *branchname,
                const char *remotename, int mirror, struct strbuf *tmp)
 {
@@ -131,10 +136,33 @@ static int add_branch(const char *key, const char *branchname,
        return git_config_set_multivar(key, tmp->buf, "^$", 0);
 }
 
+static const char mirror_advice[] =
+"--mirror is dangerous and deprecated; please\n"
+"\t use --mirror=fetch or --mirror=push instead";
+
+static int parse_mirror_opt(const struct option *opt, const char *arg, int not)
+{
+       unsigned *mirror = opt->value;
+       if (not)
+               *mirror = MIRROR_NONE;
+       else if (!arg) {
+               warning("%s", mirror_advice);
+               *mirror = MIRROR_BOTH;
+       }
+       else if (!strcmp(arg, "fetch"))
+               *mirror = MIRROR_FETCH;
+       else if (!strcmp(arg, "push"))
+               *mirror = MIRROR_PUSH;
+       else
+               return error("unknown mirror argument: %s", arg);
+       return 0;
+}
+
 static int add(int argc, const char **argv)
 {
-       int fetch = 0, mirror = 0, fetch_tags = TAGS_DEFAULT;
-       struct string_list track = { NULL, 0, 0 };
+       int fetch = 0, fetch_tags = TAGS_DEFAULT;
+       unsigned mirror = MIRROR_NONE;
+       struct string_list track = STRING_LIST_INIT_NODUP;
        const char *master = NULL;
        struct remote *remote;
        struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
@@ -151,7 +179,9 @@ static int add(int argc, const char **argv)
                OPT_CALLBACK('t', "track", &track, "branch",
                        "branch(es) to track", opt_parse_track),
                OPT_STRING('m', "master", &master, "branch", "master branch"),
-               OPT_BOOLEAN(0, "mirror", &mirror, "no separate remotes"),
+               { OPTION_CALLBACK, 0, "mirror", &mirror, "push|fetch",
+                       "set up remote as a mirror to push to or fetch from",
+                       PARSE_OPT_OPTARG, parse_mirror_opt },
                OPT_END()
        };
 
@@ -161,6 +191,11 @@ static int add(int argc, const char **argv)
        if (argc < 2)
                usage_with_options(builtin_remote_add_usage, options);
 
+       if (mirror && master)
+               die("specifying a master branch makes no sense with --mirror");
+       if (mirror && track.nr)
+               die("specifying branches to track makes no sense with --mirror");
+
        name = argv[0];
        url = argv[1];
 
@@ -177,18 +212,19 @@ static int add(int argc, const char **argv)
        if (git_config_set(buf.buf, url))
                return 1;
 
-       strbuf_reset(&buf);
-       strbuf_addf(&buf, "remote.%s.fetch", name);
-
-       if (track.nr == 0)
-               string_list_append(&track, "*");
-       for (i = 0; i < track.nr; i++) {
-               if (add_branch(buf.buf, track.items[i].string,
-                               name, mirror, &buf2))
-                       return 1;
+       if (!mirror || mirror & MIRROR_FETCH) {
+               strbuf_reset(&buf);
+               strbuf_addf(&buf, "remote.%s.fetch", name);
+               if (track.nr == 0)
+                       string_list_append(&track, "*");
+               for (i = 0; i < track.nr; i++) {
+                       if (add_branch(buf.buf, track.items[i].string,
+                                      name, mirror, &buf2))
+                               return 1;
+               }
        }
 
-       if (mirror) {
+       if (mirror & MIRROR_PUSH) {
                strbuf_reset(&buf);
                strbuf_addf(&buf, "remote.%s.mirror", name);
                if (git_config_set(buf.buf, "true"))
@@ -507,7 +543,7 @@ static int add_branch_for_removal(const char *refname,
                        return 0;
        }
 
-       /* don't delete non-remote refs */
+       /* don't delete non-remote-tracking refs */
        if (prefixcmp(refname, "refs/remotes")) {
                /* advise user how to delete local branches */
                if (!prefixcmp(refname, "refs/heads/"))
@@ -596,7 +632,7 @@ static int mv(int argc, const char **argv)
        };
        struct remote *oldremote, *newremote;
        struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT;
-       struct string_list remote_branches = { NULL, 0, 0, 0 };
+       struct string_list remote_branches = STRING_LIST_INIT_NODUP;
        struct rename_info rename;
        int i;
 
@@ -734,8 +770,8 @@ static int rm(int argc, const char **argv)
        struct remote *remote;
        struct strbuf buf = STRBUF_INIT;
        struct known_remotes known_remotes = { NULL, NULL };
-       struct string_list branches = { NULL, 0, 0, 1 };
-       struct string_list skipped = { NULL, 0, 0, 1 };
+       struct string_list branches = STRING_LIST_INIT_DUP;
+       struct string_list skipped = STRING_LIST_INIT_DUP;
        struct branches_for_remote cb_data;
        int i, result;
 
@@ -791,9 +827,9 @@ static int rm(int argc, const char **argv)
 
        if (skipped.nr) {
                fprintf(stderr, skipped.nr == 1 ?
-                       "Note: A non-remote branch was not removed; "
+                       "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
                        "to delete it, use:\n" :
-                       "Note: Non-remote branches were not removed; "
+                       "Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
                        "to delete them, use:\n");
                for (i = 0; i < skipped.nr; i++)
                        fprintf(stderr, "  git branch -d %s\n",
@@ -1044,7 +1080,7 @@ static int show(int argc, const char **argv)
                OPT_END()
        };
        struct ref_states states;
-       struct string_list info_list = { NULL, 0, 0, 0 };
+       struct string_list info_list = STRING_LIST_INIT_NODUP;
        struct show_info info;
 
        argc = parse_options(argc, argv, NULL, options, builtin_remote_show_usage,
@@ -1200,7 +1236,7 @@ static int prune(int argc, const char **argv)
 {
        int dry_run = 0, result = 0;
        struct option options[] = {
-               OPT__DRY_RUN(&dry_run),
+               OPT__DRY_RUN(&dry_run, "dry run"),
                OPT_END()
        };
 
@@ -1483,7 +1519,7 @@ static int get_one_entry(struct remote *remote, void *priv)
 
 static int show_all(void)
 {
-       struct string_list list = { NULL, 0, 0 };
+       struct string_list list = STRING_LIST_INIT_NODUP;
        int result;
 
        list.strdup_strings = 1;
@@ -1512,7 +1548,7 @@ static int show_all(void)
 int cmd_remote(int argc, const char **argv, const char *prefix)
 {
        struct option options[] = {
-               OPT_BOOLEAN('v', "verbose", &verbose, "be verbose; must be placed before a subcommand"),
+               OPT__VERBOSE(&verbose, "be verbose; must be placed before a subcommand"),
                OPT_END()
        };
        int result;