Add a remote.*.mirror configuration option
This patch adds a remote.*.mirror configuration option that, when set, automatically puts git-push in --mirror mode for that remote. Furthermore, the option is set automatically by `git remote add --mirror'. The code in remote.c to parse remote.*.skipdefaultupdate had a subtle problem: a comment in the code indicated that special care was needed for boolean options, but this care was not used in parsing the option. Since I was touching related code, I did this fix too. [jc: and I further fixed up the "ignore boolean" code.] Signed-off-by: Paolo Bonzini <bonzini@gnu.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Paolo Bonzini committed
Apr 17, 2008 at 13:17 UTC
84bb2dfd9f4873c9ca19537efe62219b09ec03bf
8 files changed
+104
-36
Documentation/config.txt
+4
@@ -910,6 +910,10 @@ remote.<name>.push::
910
The default set of "refspec" for linkgit:git-push[1]. See
911
linkgit:git-push[1].
912
913
+remote.<name>.mirror::
914
+ If true, pushing to this remote will automatically behave
915
+ as if the `\--mirror` option was given on the command line.
916
+
917
remote.<name>.skipDefaultUpdate::
918
If true, this remote will be skipped by default when updating
919
using the update subcommand of linkgit:git-remote[1].
Documentation/git-push.txt
+3
-1
@@ -69,7 +69,9 @@ the remote repository.
69
be mirrored to the remote repository. Newly created local
70
refs will be pushed to the remote end, locally updated refs
71
will be force updated on the remote end, and deleted refs
72
- will be removed from the remote end.
72
+ will be removed from the remote end. This is the default
73
+ if the configuration option `remote.<remote>.mirror` is
74
+ set.
75
76
\--dry-run::
77
Do everything except actually send the updates.
Documentation/git-remote.txt
+4
-2
@@ -47,9 +47,11 @@ With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
47
up to point at remote's `<master>` branch instead of whatever
48
branch the `HEAD` at the remote repository actually points at.
49
+
50
-In mirror mode, enabled with `--mirror`, the refs will not be stored
50
+In mirror mode, enabled with `\--mirror`, the refs will not be stored
51
in the 'refs/remotes/' namespace, but in 'refs/heads/'. This option
52
-only makes sense in bare repositories.
52
+only makes sense in bare repositories. If a remote uses mirror
53
+mode, furthermore, `git push` will always behave as if `\--mirror`
54
+was passed.
55
56
'rm'::
57
builtin-push.c
+16
-8
@@ -56,6 +56,17 @@ static int do_push(const char *repo, int flags)
56
if (!remote)
57
die("bad repository '%s'", repo);
58
59
+ if (remote->mirror)
60
+ flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
61
+
62
+ if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) && refspec)
63
+ return -1;
64
+
65
+ if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
66
+ (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
67
+ return error("--all and --mirror are incompatible");
68
+ }
69
+
70
if (!refspec
71
&& !(flags & TRANSPORT_PUSH_ALL)
72
&& remote->push_refspec_nr) {
@@ -95,6 +106,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
106
int dry_run = 0;
107
int force = 0;
108
int tags = 0;
109
+ int rc;
110
const char *repo = NULL; /* default repository */
111
112
struct option options[] = {
@@ -130,14 +142,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)
142
repo = argv[0];
143
set_refspecs(argv + 1, argc - 1);
144
}
133
- if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) && refspec)
134
- usage_with_options(push_usage, options);
145
136
- if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
137
- (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
138
- error("--all and --mirror are incompatible");
146
+ rc = do_push(repo, flags);
147
+ if (rc == -1)
148
usage_with_options(push_usage, options);
140
- }
141
-
142
- return do_push(repo, flags);
149
+ else
150
+ return rc;
151
}
builtin-remote.c
+7
@@ -117,6 +117,13 @@ static int add(int argc, const char **argv)
117
return 1;
118
}
119
120
+ if (mirror) {
121
+ strbuf_reset(&buf);
122
+ strbuf_addf(&buf, "remote.%s.mirror", name);
123
+ if (git_config_set(buf.buf, "yes"))
124
+ return 1;
125
+ }
126
+
127
if (fetch && fetch_remote(name))
128
return 1;
129
remote.c
+29
-24
@@ -337,44 +337,49 @@ static int handle_config(const char *key, const char *value)
337
return 0;
338
}
339
remote = make_remote(name, subkey - name);
340
- if (!value) {
341
- /* if we ever have a boolean variable, e.g. "remote.*.disabled"
342
- * [remote "frotz"]
343
- * disabled
344
- * is a valid way to set it to true; we get NULL in value so
345
- * we need to handle it here.
346
- *
347
- * if (!strcmp(subkey, ".disabled")) {
348
- * val = git_config_bool(key, value);
349
- * return 0;
350
- * } else
351
- *
352
- */
353
- return 0; /* ignore unknown booleans */
354
- }
355
- if (!strcmp(subkey, ".url")) {
356
- add_url(remote, xstrdup(value));
340
+ if (!strcmp(subkey, ".mirror"))
341
+ remote->mirror = git_config_bool(key, value);
342
+ else if (!strcmp(subkey, ".skipdefaultupdate"))
343
+ remote->skip_default_update = git_config_bool(key, value);
344
+
345
+ else if (!strcmp(subkey, ".url")) {
346
+ const char *v;
347
+ if (git_config_string(&v, key, value))
348
+ return -1;
349
+ add_url(remote, v);
350
} else if (!strcmp(subkey, ".push")) {
358
- add_push_refspec(remote, xstrdup(value));
351
+ const char *v;
352
+ if (git_config_string(&v, key, value))
353
+ return -1;
354
+ add_push_refspec(remote, v);
355
} else if (!strcmp(subkey, ".fetch")) {
360
- add_fetch_refspec(remote, xstrdup(value));
356
+ const char *v;
357
+ if (git_config_string(&v, key, value))
358
+ return -1;
359
+ add_fetch_refspec(remote, v);
360
} else if (!strcmp(subkey, ".receivepack")) {
361
+ const char *v;
362
+ if (git_config_string(&v, key, value))
363
+ return -1;
364
if (!remote->receivepack)
363
- remote->receivepack = xstrdup(value);
365
+ remote->receivepack = v;
366
else
367
error("more than one receivepack given, using the first");
368
} else if (!strcmp(subkey, ".uploadpack")) {
369
+ const char *v;
370
+ if (git_config_string(&v, key, value))
371
+ return -1;
372
if (!remote->uploadpack)
368
- remote->uploadpack = xstrdup(value);
373
+ remote->uploadpack = v;
374
else
375
error("more than one uploadpack given, using the first");
376
} else if (!strcmp(subkey, ".tagopt")) {
377
if (!strcmp(value, "--no-tags"))
378
remote->fetch_tags = -1;
379
} else if (!strcmp(subkey, ".proxy")) {
375
- remote->http_proxy = xstrdup(value);
376
- } else if (!strcmp(subkey, ".skipdefaultupdate"))
377
- remote->skip_default_update = 1;
380
+ return git_config_string((const char **)&remote->http_proxy,
381
+ key, value);
382
+ }
383
return 0;
384
}
385
remote.h
+1
@@ -26,6 +26,7 @@ struct remote {
26
*/
27
int fetch_tags;
28
int skip_default_update;
29
+ int mirror;
30
31
const char *receivepack;
32
const char *uploadpack;
t/t5517-push-mirror.sh
+40
-1
@@ -25,7 +25,7 @@ mk_repo_pair () {
25
(
26
cd master &&
27
git init &&
28
- git config remote.up.url ../mirror
28
+ git remote add $1 up ../mirror
29
)
30
}
31
@@ -225,4 +225,43 @@ test_expect_success 'push mirror adds, updates and removes tags together' '
225
226
'
227
228
+test_expect_success 'remote.foo.mirror adds and removes branches' '
229
+
230
+ mk_repo_pair --mirror &&
231
+ (
232
+ cd master &&
233
+ echo one >foo && git add foo && git commit -m one &&
234
+ git branch keep master &&
235
+ git branch remove master &&
236
+ git push up &&
237
+ git branch -D remove
238
+ git push up
239
+ ) &&
240
+ (
241
+ cd mirror &&
242
+ git show-ref -s --verify refs/heads/keep &&
243
+ invert git show-ref -s --verify refs/heads/remove
244
+ )
245
+
246
+'
247
+
248
+test_expect_success 'remote.foo.mirror=no has no effect' '
249
+
250
+ mk_repo_pair &&
251
+ (
252
+ cd master &&
253
+ echo one >foo && git add foo && git commit -m one &&
254
+ git config --add remote.up.mirror no &&
255
+ git branch keep master &&
256
+ git push --mirror up &&
257
+ git branch -D keep &&
258
+ git push up
259
+ ) &&
260
+ (
261
+ cd mirror &&
262
+ git show-ref -s --verify refs/heads/keep
263
+ )
264
+
265
+'
266
+
267
test_done