Skip to content

Commit 84bb2df

Browse files
bonzinigitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5909ca9 commit 84bb2df

File tree

8 files changed

+104
-36
lines changed

8 files changed

+104
-36
lines changed

Documentation/config.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,10 @@ remote.<name>.push::
910910
The default set of "refspec" for linkgit:git-push[1]. See
911911
linkgit:git-push[1].
912912

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+
913917
remote.<name>.skipDefaultUpdate::
914918
If true, this remote will be skipped by default when updating
915919
using the update subcommand of linkgit:git-remote[1].

Documentation/git-push.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ the remote repository.
6969
be mirrored to the remote repository. Newly created local
7070
refs will be pushed to the remote end, locally updated refs
7171
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.
7375

7476
\--dry-run::
7577
Do everything except actually send the updates.

Documentation/git-remote.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
4747
up to point at remote's `<master>` branch instead of whatever
4848
branch the `HEAD` at the remote repository actually points at.
4949
+
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
5151
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.
5355

5456
'rm'::
5557

builtin-push.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ static int do_push(const char *repo, int flags)
5656
if (!remote)
5757
die("bad repository '%s'", repo);
5858

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+
5970
if (!refspec
6071
&& !(flags & TRANSPORT_PUSH_ALL)
6172
&& remote->push_refspec_nr) {
@@ -95,6 +106,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
95106
int dry_run = 0;
96107
int force = 0;
97108
int tags = 0;
109+
int rc;
98110
const char *repo = NULL; /* default repository */
99111

100112
struct option options[] = {
@@ -130,14 +142,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)
130142
repo = argv[0];
131143
set_refspecs(argv + 1, argc - 1);
132144
}
133-
if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) && refspec)
134-
usage_with_options(push_usage, options);
135145

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)
139148
usage_with_options(push_usage, options);
140-
}
141-
142-
return do_push(repo, flags);
149+
else
150+
return rc;
143151
}

builtin-remote.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ static int add(int argc, const char **argv)
117117
return 1;
118118
}
119119

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+
120127
if (fetch && fetch_remote(name))
121128
return 1;
122129

remote.c

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -337,44 +337,49 @@ static int handle_config(const char *key, const char *value)
337337
return 0;
338338
}
339339
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);
357350
} 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);
359355
} 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);
361360
} else if (!strcmp(subkey, ".receivepack")) {
361+
const char *v;
362+
if (git_config_string(&v, key, value))
363+
return -1;
362364
if (!remote->receivepack)
363-
remote->receivepack = xstrdup(value);
365+
remote->receivepack = v;
364366
else
365367
error("more than one receivepack given, using the first");
366368
} else if (!strcmp(subkey, ".uploadpack")) {
369+
const char *v;
370+
if (git_config_string(&v, key, value))
371+
return -1;
367372
if (!remote->uploadpack)
368-
remote->uploadpack = xstrdup(value);
373+
remote->uploadpack = v;
369374
else
370375
error("more than one uploadpack given, using the first");
371376
} else if (!strcmp(subkey, ".tagopt")) {
372377
if (!strcmp(value, "--no-tags"))
373378
remote->fetch_tags = -1;
374379
} 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+
}
378383
return 0;
379384
}
380385

remote.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct remote {
2626
*/
2727
int fetch_tags;
2828
int skip_default_update;
29+
int mirror;
2930

3031
const char *receivepack;
3132
const char *uploadpack;

t/t5517-push-mirror.sh

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ mk_repo_pair () {
2525
(
2626
cd master &&
2727
git init &&
28-
git config remote.up.url ../mirror
28+
git remote add $1 up ../mirror
2929
)
3030
}
3131

@@ -225,4 +225,43 @@ test_expect_success 'push mirror adds, updates and removes tags together' '
225225
226226
'
227227

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+
228267
test_done

0 commit comments

Comments
 (0)