@matheusbsbs / matheus-bagliano / commits / 3d8b69495f
Fork 0

Add git remote set-branches

Add ‘git remote set-branches’ for changing the list of tracked refs for a remote repository with one "porcelain-level" command. This complements the longstanding ‘git remote add --track’ option. The interface is based on the ‘git remote set-url’ subcommand. git remote set-branches base --add C git remote set-branches base A B D git remote set-branches base --delete D; # not implemented Suggested-by: martin f. krafft <madduck@debian.org> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jonathan Nieder committed May 19, 2010 at 13:38 UTC 3d8b69495fd1132d5af6d7f46425cca97a937d97
3 files changed +192 -11
Documentation/git-remote.txt
+13
@@ -14,6 +14,7 @@ SYNOPSIS
14 'git remote rename' <old> <new>
15 'git remote rm' <name>
16 'git remote set-head' <name> (-a | -d | <branch>)
17 +'git remote set-branches' <name> [--add] <branch>...
18 'git remote set-url' [--push] <name> <newurl> [<oldurl>]
19 'git remote set-url --add' [--push] <name> <newurl>
20 'git remote set-url --delete' [--push] <name> <url>
@@ -104,6 +105,18 @@ remote set-head origin master" will set `$GIT_DIR/refs/remotes/origin/HEAD` to
105 `refs/remotes/origin/master` already exists; if not it must be fetched first.
106 +
107
108 +'set-branches'::
109 +
110 +Changes the list of branches tracked by the named remote.
111 +This can be used to track a subset of the available remote branches
112 +after the initial setup for a remote.
113 ++
114 +The named branches will be interpreted as if specified with the
115 +`-t` option on the 'git remote add' command line.
116 ++
117 +With `--add`, instead of replacing the list of currently tracked
118 +branches, adds to that list.
119 +
120 'set-url'::
121
122 Changes URL remote points to. Sets first URL remote points to matching
builtin/remote.c
+91 -11
@@ -16,6 +16,7 @@ static const char * const builtin_remote_usage[] = {
16 "git remote [-v | --verbose] show [-n] <name>",
17 "git remote prune [-n | --dry-run] <name>",
18 "git remote [-v | --verbose] update [-p | --prune] [group | remote]",
19 + "git remote set-branches <name> [--add] <branch>...",
20 "git remote set-url <name> <newurl> [<oldurl>]",
21 "git remote set-url --add <name> <newurl>",
22 "git remote set-url --delete <name> <url>",
@@ -42,6 +43,12 @@ static const char * const builtin_remote_sethead_usage[] = {
43 NULL
44 };
45
46 +static const char * const builtin_remote_setbranches_usage[] = {
47 + "git remote set-branches <name> <branch>...",
48 + "git remote set-branches --add <name> <branch>...",
49 + NULL
50 +};
51 +
52 static const char * const builtin_remote_show_usage[] = {
53 "git remote show [<options>] <name>",
54 NULL
@@ -104,6 +111,20 @@ static int fetch_remote(const char *name)
111 return 0;
112 }
113
114 +static int add_branch(const char *key, const char *branchname,
115 + const char *remotename, int mirror, struct strbuf *tmp)
116 +{
117 + strbuf_reset(tmp);
118 + strbuf_addch(tmp, '+');
119 + if (mirror)
120 + strbuf_addf(tmp, "refs/%s:refs/%s",
121 + branchname, branchname);
122 + else
123 + strbuf_addf(tmp, "refs/heads/%s:refs/remotes/%s/%s",
124 + branchname, remotename, branchname);
125 + return git_config_set_multivar(key, tmp->buf, "^$", 0);
126 +}
127 +
128 static int add(int argc, const char **argv)
129 {
130 int fetch = 0, mirror = 0;
@@ -151,17 +172,8 @@ static int add(int argc, const char **argv)
172 if (track.nr == 0)
173 string_list_append("*", &track);
174 for (i = 0; i < track.nr; i++) {
154 - struct string_list_item *item = track.items + i;
155 -
156 - strbuf_reset(&buf2);
157 - strbuf_addch(&buf2, '+');
158 - if (mirror)
159 - strbuf_addf(&buf2, "refs/%s:refs/%s",
160 - item->string, item->string);
161 - else
162 - strbuf_addf(&buf2, "refs/heads/%s:refs/remotes/%s/%s",
163 - item->string, name, item->string);
164 - if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
175 + if (add_branch(buf.buf, track.items[i].string,
176 + name, mirror, &buf2))
177 return 1;
178 }
179
@@ -1265,6 +1277,72 @@ static int update(int argc, const char **argv)
1277 return run_command_v_opt(fetch_argv, RUN_GIT_CMD);
1278 }
1279
1280 +static int remove_all_fetch_refspecs(const char *remote, const char *key)
1281 +{
1282 + return git_config_set_multivar(key, NULL, NULL, 1);
1283 +}
1284 +
1285 +static int add_branches(struct remote *remote, const char **branches,
1286 + const char *key)
1287 +{
1288 + const char *remotename = remote->name;
1289 + int mirror = remote->mirror;
1290 + struct strbuf refspec = STRBUF_INIT;
1291 +
1292 + for (; *branches; branches++)
1293 + if (add_branch(key, *branches, remotename, mirror, &refspec)) {
1294 + strbuf_release(&refspec);
1295 + return 1;
1296 + }
1297 +
1298 + strbuf_release(&refspec);
1299 + return 0;
1300 +}
1301 +
1302 +static int set_remote_branches(const char *remotename, const char **branches,
1303 + int add_mode)
1304 +{
1305 + struct strbuf key = STRBUF_INIT;
1306 + struct remote *remote;
1307 +
1308 + strbuf_addf(&key, "remote.%s.fetch", remotename);
1309 +
1310 + if (!remote_is_configured(remotename))
1311 + die("No such remote '%s'", remotename);
1312 + remote = remote_get(remotename);
1313 +
1314 + if (!add_mode && remove_all_fetch_refspecs(remotename, key.buf)) {
1315 + strbuf_release(&key);
1316 + return 1;
1317 + }
1318 + if (add_branches(remote, branches, key.buf)) {
1319 + strbuf_release(&key);
1320 + return 1;
1321 + }
1322 +
1323 + strbuf_release(&key);
1324 + return 0;
1325 +}
1326 +
1327 +static int set_branches(int argc, const char **argv)
1328 +{
1329 + int add_mode = 0;
1330 + struct option options[] = {
1331 + OPT_BOOLEAN('\0', "add", &add_mode, "add branch"),
1332 + OPT_END()
1333 + };
1334 +
1335 + argc = parse_options(argc, argv, NULL, options,
1336 + builtin_remote_setbranches_usage, 0);
1337 + if (argc == 0) {
1338 + error("no remote specified");
1339 + usage_with_options(builtin_remote_seturl_usage, options);
1340 + }
1341 + argv[argc] = NULL;
1342 +
1343 + return set_remote_branches(argv[0], argv + 1, add_mode);
1344 +}
1345 +
1346 static int set_url(int argc, const char **argv)
1347 {
1348 int i, push_mode = 0, add_mode = 0, delete_mode = 0;
@@ -1430,6 +1508,8 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
1508 result = rm(argc, argv);
1509 else if (!strcmp(argv[0], "set-head"))
1510 result = set_head(argc, argv);
1511 + else if (!strcmp(argv[0], "set-branches"))
1512 + result = set_branches(argc, argv);
1513 else if (!strcmp(argv[0], "set-url"))
1514 result = set_url(argc, argv);
1515 else if (!strcmp(argv[0], "show"))
t/t5505-remote.sh
+88
@@ -534,6 +534,94 @@ test_expect_success 'show empty remote' '
534 )
535 '
536
537 +test_expect_success 'remote set-branches requires a remote' '
538 + test_must_fail git remote set-branches &&
539 + test_must_fail git remote set-branches --add
540 +'
541 +
542 +test_expect_success 'remote set-branches' '
543 + echo "+refs/heads/*:refs/remotes/scratch/*" >expect.initial &&
544 + sort <<-\EOF >expect.add &&
545 + +refs/heads/*:refs/remotes/scratch/*
546 + +refs/heads/other:refs/remotes/scratch/other
547 + EOF
548 + sort <<-\EOF >expect.replace &&
549 + +refs/heads/maint:refs/remotes/scratch/maint
550 + +refs/heads/master:refs/remotes/scratch/master
551 + +refs/heads/next:refs/remotes/scratch/next
552 + EOF
553 + sort <<-\EOF >expect.add-two &&
554 + +refs/heads/maint:refs/remotes/scratch/maint
555 + +refs/heads/master:refs/remotes/scratch/master
556 + +refs/heads/next:refs/remotes/scratch/next
557 + +refs/heads/pu:refs/remotes/scratch/pu
558 + +refs/heads/t/topic:refs/remotes/scratch/t/topic
559 + EOF
560 + sort <<-\EOF >expect.setup-ffonly &&
561 + refs/heads/master:refs/remotes/scratch/master
562 + +refs/heads/next:refs/remotes/scratch/next
563 + EOF
564 + sort <<-\EOF >expect.respect-ffonly &&
565 + refs/heads/master:refs/remotes/scratch/master
566 + +refs/heads/next:refs/remotes/scratch/next
567 + +refs/heads/pu:refs/remotes/scratch/pu
568 + EOF
569 +
570 + git clone .git/ setbranches &&
571 + (
572 + cd setbranches &&
573 + git remote rename origin scratch &&
574 + git config --get-all remote.scratch.fetch >config-result &&
575 + sort <config-result >../actual.initial &&
576 +
577 + git remote set-branches scratch --add other &&
578 + git config --get-all remote.scratch.fetch >config-result &&
579 + sort <config-result >../actual.add &&
580 +
581 + git remote set-branches scratch maint master next &&
582 + git config --get-all remote.scratch.fetch >config-result &&
583 + sort <config-result >../actual.replace &&
584 +
585 + git remote set-branches --add scratch pu t/topic &&
586 + git config --get-all remote.scratch.fetch >config-result &&
587 + sort <config-result >../actual.add-two &&
588 +
589 + git config --unset-all remote.scratch.fetch &&
590 + git config remote.scratch.fetch \
591 + refs/heads/master:refs/remotes/scratch/master &&
592 + git config --add remote.scratch.fetch \
593 + +refs/heads/next:refs/remotes/scratch/next &&
594 + git config --get-all remote.scratch.fetch >config-result &&
595 + sort <config-result >../actual.setup-ffonly &&
596 +
597 + git remote set-branches --add scratch pu &&
598 + git config --get-all remote.scratch.fetch >config-result &&
599 + sort <config-result >../actual.respect-ffonly
600 + ) &&
601 + test_cmp expect.initial actual.initial &&
602 + test_cmp expect.add actual.add &&
603 + test_cmp expect.replace actual.replace &&
604 + test_cmp expect.add-two actual.add-two &&
605 + test_cmp expect.setup-ffonly actual.setup-ffonly &&
606 + test_cmp expect.respect-ffonly actual.respect-ffonly
607 +'
608 +
609 +test_expect_success 'remote set-branches with --mirror' '
610 + echo "+refs/*:refs/*" >expect.initial &&
611 + echo "+refs/heads/master:refs/heads/master" >expect.replace &&
612 + git clone --mirror .git/ setbranches-mirror &&
613 + (
614 + cd setbranches-mirror &&
615 + git remote rename origin scratch &&
616 + git config --get-all remote.scratch.fetch >../actual.initial &&
617 +
618 + git remote set-branches scratch heads/master &&
619 + git config --get-all remote.scratch.fetch >../actual.replace
620 + ) &&
621 + test_cmp expect.initial actual.initial &&
622 + test_cmp expect.replace actual.replace
623 +'
624 +
625 test_expect_success 'new remote' '
626 git remote add someremote foo &&
627 echo foo >expect &&