Code

Merge branch 'jk/maint-remote-mirror-safer'
authorJunio C Hamano <gitster@pobox.com>
Wed, 6 Apr 2011 17:38:14 +0000 (10:38 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 6 Apr 2011 17:38:14 +0000 (10:38 -0700)
* jk/maint-remote-mirror-safer:
  remote: deprecate --mirror
  remote: separate the concept of push and fetch mirrors
  remote: disallow some nonsensical option combinations

1  2 
Documentation/git-remote.txt
builtin/remote.c

index 37bd3e538894206b7b79022a58c72e9a75263513,ddcbcc00aeaf43f830a7f33c3302ec3843e9e197..528f34a13106836c1eace8c5d8972543b6fcc121
@@@ -10,7 -10,7 +10,7 @@@ SYNOPSI
  --------
  [verse]
  'git remote' [-v | --verbose]
- 'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror] <name> <url>
+ 'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>
  'git remote rename' <old> <new>
  'git remote rm' <name>
  'git remote set-head' <name> (-a | -d | <branch>)
@@@ -67,11 -67,14 +67,14 @@@ multiple branches without grabbing all 
  With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
  up to point at remote's `<master>` branch. See also the set-head command.
  +
- In mirror mode, enabled with `\--mirror`, the refs will not be stored
- in the 'refs/remotes/' namespace, but in 'refs/heads/'.  This option
- only makes sense in bare repositories.  If a remote uses mirror
- mode, furthermore, `git push` will always behave as if `\--mirror`
- was passed.
+ When a fetch mirror is created with `\--mirror=fetch`, the refs will not
+ be stored in the 'refs/remotes/' namespace, but rather everything in
+ 'refs/' on the remote will be directly mirrored into 'refs/' in the
+ local repository. This option only makes sense in bare repositories,
+ because a fetch would overwrite any local commits.
+ +
+ When a push mirror is created with `\--mirror=push`, then `git push`
+ will always behave as if `\--mirror` was passed.
  
  'rename'::
  
@@@ -214,6 -217,16 +217,6 @@@ linkgit:git-fetch[1
  linkgit:git-branch[1]
  linkgit:git-config[1]
  
 -Author
 -------
 -Written by Junio Hamano
 -
 -
 -Documentation
 ---------------
 -Documentation by J. Bruce Fields and the git-list <git@vger.kernel.org>.
 -
 -
  GIT
  ---
  Part of the linkgit:git[1] suite
diff --combined builtin/remote.c
index b71ecd228f5c27bc436602469d3090eb860a1222,eb1229d68917131e98c4830fa184045f82fcedad..8424152269e309cb86e4ff530b9feacc23fc17a6
@@@ -1,4 -1,4 +1,4 @@@
 -#include "cache.h"
 +#include "builtin.h"
  #include "parse-options.h"
  #include "transport.h"
  #include "remote.h"
@@@ -9,7 -9,7 +9,7 @@@
  
  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>)",
@@@ -117,6 -117,11 +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)
  {
        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;
+       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;
                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()
        };
  
        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];
  
        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"))