From: Junio C Hamano Date: Fri, 18 Jun 2010 18:16:55 +0000 (-0700) Subject: Merge branch 'jn/remote-set-branches' X-Git-Tag: v1.7.2-rc0~57 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/1c5d6b2a401576f74c76f56dae0204604235705c?hp=-c Merge branch 'jn/remote-set-branches' * jn/remote-set-branches: Add git remote set-branches Conflicts: builtin/remote.c --- 1c5d6b2a401576f74c76f56dae0204604235705c diff --combined Documentation/git-remote.txt index ebaaadc178,de4386bf7e..aa021b0cb8 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@@ -10,10 -10,11 +10,11 @@@ SYNOPSI -------- [verse] 'git remote' [-v | --verbose] -'git remote add' [-t ] [-m ] [-f] [--mirror] +'git remote add' [-t ] [-m ] [-f] [--tags|--no-tags] [--mirror] 'git remote rename' 'git remote rm' 'git remote set-head' (-a | -d | ) + 'git remote set-branches' [--add] ... 'git remote set-url' [--push] [] 'git remote set-url --add' [--push] 'git remote set-url --delete' [--push] @@@ -51,12 -52,6 +52,12 @@@ update remote-tracking branches / With `-f` option, `git fetch ` is run immediately after the remote information is set up. + +With `--tags` option, `git fetch ` imports every tag from the +remote repository. ++ +With `--no-tags` option, `git fetch ` does not import tags from +the remote repository. ++ With `-t ` option, instead of the default glob refspec for the remote to track all branches under `$GIT_DIR/remotes//`, a refspec to track only `` @@@ -110,6 -105,18 +111,18 @@@ remote set-head origin master" will se `refs/remotes/origin/master` already exists; if not it must be fetched first. + + 'set-branches':: + + Changes the list of branches tracked by the named remote. + This can be used to track a subset of the available remote branches + after the initial setup for a remote. + + + The named branches will be interpreted as if specified with the + `-t` option on the 'git remote add' command line. + + + With `--add`, instead of replacing the list of currently tracked + branches, adds to that list. + 'set-url':: Changes URL remote points to. Sets first URL remote points to matching diff --combined builtin/remote.c index 0e99a9957d,c4d17b52bc..4745957b96 --- a/builtin/remote.c +++ b/builtin/remote.c @@@ -16,6 -16,7 +16,7 @@@ static const char * const builtin_remot "git remote [-v | --verbose] show [-n] ", "git remote prune [-n | --dry-run] ", "git remote [-v | --verbose] update [-p | --prune] [group | remote]", + "git remote set-branches [--add] ...", "git remote set-url []", "git remote set-url --add ", "git remote set-url --delete ", @@@ -42,6 -43,12 +43,12 @@@ static const char * const builtin_remot NULL }; + static const char * const builtin_remote_setbranches_usage[] = { + "git remote set-branches ...", + "git remote set-branches --add ...", + NULL + }; + static const char * const builtin_remote_show_usage[] = { "git remote show [] ", NULL @@@ -104,15 -111,23 +111,29 @@@ static int fetch_remote(const char *nam return 0; } +enum { + TAGS_UNSET = 0, + TAGS_DEFAULT = 1, + TAGS_SET = 2 +}; + + static int add_branch(const char *key, const char *branchname, + const char *remotename, int mirror, struct strbuf *tmp) + { + strbuf_reset(tmp); + strbuf_addch(tmp, '+'); + if (mirror) + strbuf_addf(tmp, "refs/%s:refs/%s", + branchname, branchname); + else + strbuf_addf(tmp, "refs/heads/%s:refs/remotes/%s/%s", + branchname, remotename, branchname); + return git_config_set_multivar(key, tmp->buf, "^$", 0); + } + static int add(int argc, const char **argv) { - int fetch = 0, mirror = 0; + int fetch = 0, mirror = 0, fetch_tags = TAGS_DEFAULT; struct string_list track = { NULL, 0, 0 }; const char *master = NULL; struct remote *remote; @@@ -122,11 -137,6 +143,11 @@@ struct option options[] = { OPT_BOOLEAN('f', "fetch", &fetch, "fetch the remote branches"), + OPT_SET_INT(0, "tags", &fetch_tags, + "import all tags and associated objects when fetching", + TAGS_SET), + OPT_SET_INT(0, NULL, &fetch_tags, + "or do not fetch any tag at all (--no-tags)", TAGS_UNSET), OPT_CALLBACK('t', "track", &track, "branch", "branch(es) to track", opt_parse_track), OPT_STRING('m', "master", &master, "branch", "master branch"), @@@ -162,17 -172,8 +183,8 @@@ if (track.nr == 0) string_list_append("*", &track); for (i = 0; i < track.nr; i++) { - struct string_list_item *item = track.items + i; - - strbuf_reset(&buf2); - strbuf_addch(&buf2, '+'); - if (mirror) - strbuf_addf(&buf2, "refs/%s:refs/%s", - item->string, item->string); - else - strbuf_addf(&buf2, "refs/heads/%s:refs/remotes/%s/%s", - item->string, name, item->string); - if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0)) + if (add_branch(buf.buf, track.items[i].string, + name, mirror, &buf2)) return 1; } @@@ -183,14 -184,6 +195,14 @@@ return 1; } + if (fetch_tags != TAGS_DEFAULT) { + strbuf_reset(&buf); + strbuf_addf(&buf, "remote.%s.tagopt", name); + if (git_config_set(buf.buf, + fetch_tags == TAGS_SET ? "--tags" : "--no-tags")) + return 1; + } + if (fetch && fetch_remote(name)) return 1; @@@ -1284,6 -1277,72 +1296,72 @@@ static int update(int argc, const char return run_command_v_opt(fetch_argv, RUN_GIT_CMD); } + static int remove_all_fetch_refspecs(const char *remote, const char *key) + { + return git_config_set_multivar(key, NULL, NULL, 1); + } + + static int add_branches(struct remote *remote, const char **branches, + const char *key) + { + const char *remotename = remote->name; + int mirror = remote->mirror; + struct strbuf refspec = STRBUF_INIT; + + for (; *branches; branches++) + if (add_branch(key, *branches, remotename, mirror, &refspec)) { + strbuf_release(&refspec); + return 1; + } + + strbuf_release(&refspec); + return 0; + } + + static int set_remote_branches(const char *remotename, const char **branches, + int add_mode) + { + struct strbuf key = STRBUF_INIT; + struct remote *remote; + + strbuf_addf(&key, "remote.%s.fetch", remotename); + + if (!remote_is_configured(remotename)) + die("No such remote '%s'", remotename); + remote = remote_get(remotename); + + if (!add_mode && remove_all_fetch_refspecs(remotename, key.buf)) { + strbuf_release(&key); + return 1; + } + if (add_branches(remote, branches, key.buf)) { + strbuf_release(&key); + return 1; + } + + strbuf_release(&key); + return 0; + } + + static int set_branches(int argc, const char **argv) + { + int add_mode = 0; + struct option options[] = { + OPT_BOOLEAN('\0', "add", &add_mode, "add branch"), + OPT_END() + }; + + argc = parse_options(argc, argv, NULL, options, + builtin_remote_setbranches_usage, 0); + if (argc == 0) { + error("no remote specified"); + usage_with_options(builtin_remote_seturl_usage, options); + } + argv[argc] = NULL; + + return set_remote_branches(argv[0], argv + 1, add_mode); + } + static int set_url(int argc, const char **argv) { int i, push_mode = 0, add_mode = 0, delete_mode = 0; @@@ -1449,6 -1508,8 +1527,8 @@@ int cmd_remote(int argc, const char **a result = rm(argc, argv); else if (!strcmp(argv[0], "set-head")) result = set_head(argc, argv); + else if (!strcmp(argv[0], "set-branches")) + result = set_branches(argc, argv); else if (!strcmp(argv[0], "set-url")) result = set_url(argc, argv); else if (!strcmp(argv[0], "show")) diff --combined t/t5505-remote.sh index 41f17e7693,8aaf53ed81..4c498b1902 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@@ -320,69 -320,6 +320,69 @@@ test_expect_success 'add alt && prune' git rev-parse --verify refs/remotes/origin/side2) ' +cat >test/expect <<\EOF +some-tag +EOF + +test_expect_success 'add with reachable tags (default)' ' + (cd one && + >foobar && + git add foobar && + git commit -m "Foobar" && + git tag -a -m "Foobar tag" foobar-tag && + git reset --hard HEAD~1 && + git tag -a -m "Some tag" some-tag) && + (mkdir add-tags && + cd add-tags && + git init && + git remote add -f origin ../one && + git tag -l some-tag >../test/output && + git tag -l foobar-tag >>../test/output && + test_must_fail git config remote.origin.tagopt) && + test_cmp test/expect test/output +' + +cat >test/expect <<\EOF +some-tag +foobar-tag +--tags +EOF + +test_expect_success 'add --tags' ' + (rm -rf add-tags && + mkdir add-tags && + cd add-tags && + git init && + git remote add -f --tags origin ../one && + git tag -l some-tag >../test/output && + git tag -l foobar-tag >>../test/output && + git config remote.origin.tagopt >>../test/output) && + test_cmp test/expect test/output +' + +cat >test/expect <<\EOF +--no-tags +EOF + +test_expect_success 'add --no-tags' ' + (rm -rf add-tags && + mkdir add-no-tags && + cd add-no-tags && + git init && + git remote add -f --no-tags origin ../one && + git tag -l some-tag >../test/output && + git tag -l foobar-tag >../test/output && + git config remote.origin.tagopt >>../test/output) && + (cd one && + git tag -d some-tag foobar-tag) && + test_cmp test/expect test/output +' + +test_expect_success 'reject --no-no-tags' ' + (cd add-no-tags && + test_must_fail git remote add -f --no-no-tags neworigin ../one) +' + cat > one/expect << EOF apis/master apis/side @@@ -597,6 -534,94 +597,94 @@@ test_expect_success 'show empty remote ) ' + test_expect_success 'remote set-branches requires a remote' ' + test_must_fail git remote set-branches && + test_must_fail git remote set-branches --add + ' + + test_expect_success 'remote set-branches' ' + echo "+refs/heads/*:refs/remotes/scratch/*" >expect.initial && + sort <<-\EOF >expect.add && + +refs/heads/*:refs/remotes/scratch/* + +refs/heads/other:refs/remotes/scratch/other + EOF + sort <<-\EOF >expect.replace && + +refs/heads/maint:refs/remotes/scratch/maint + +refs/heads/master:refs/remotes/scratch/master + +refs/heads/next:refs/remotes/scratch/next + EOF + sort <<-\EOF >expect.add-two && + +refs/heads/maint:refs/remotes/scratch/maint + +refs/heads/master:refs/remotes/scratch/master + +refs/heads/next:refs/remotes/scratch/next + +refs/heads/pu:refs/remotes/scratch/pu + +refs/heads/t/topic:refs/remotes/scratch/t/topic + EOF + sort <<-\EOF >expect.setup-ffonly && + refs/heads/master:refs/remotes/scratch/master + +refs/heads/next:refs/remotes/scratch/next + EOF + sort <<-\EOF >expect.respect-ffonly && + refs/heads/master:refs/remotes/scratch/master + +refs/heads/next:refs/remotes/scratch/next + +refs/heads/pu:refs/remotes/scratch/pu + EOF + + git clone .git/ setbranches && + ( + cd setbranches && + git remote rename origin scratch && + git config --get-all remote.scratch.fetch >config-result && + sort ../actual.initial && + + git remote set-branches scratch --add other && + git config --get-all remote.scratch.fetch >config-result && + sort ../actual.add && + + git remote set-branches scratch maint master next && + git config --get-all remote.scratch.fetch >config-result && + sort ../actual.replace && + + git remote set-branches --add scratch pu t/topic && + git config --get-all remote.scratch.fetch >config-result && + sort ../actual.add-two && + + git config --unset-all remote.scratch.fetch && + git config remote.scratch.fetch \ + refs/heads/master:refs/remotes/scratch/master && + git config --add remote.scratch.fetch \ + +refs/heads/next:refs/remotes/scratch/next && + git config --get-all remote.scratch.fetch >config-result && + sort ../actual.setup-ffonly && + + git remote set-branches --add scratch pu && + git config --get-all remote.scratch.fetch >config-result && + sort ../actual.respect-ffonly + ) && + test_cmp expect.initial actual.initial && + test_cmp expect.add actual.add && + test_cmp expect.replace actual.replace && + test_cmp expect.add-two actual.add-two && + test_cmp expect.setup-ffonly actual.setup-ffonly && + test_cmp expect.respect-ffonly actual.respect-ffonly + ' + + test_expect_success 'remote set-branches with --mirror' ' + echo "+refs/*:refs/*" >expect.initial && + echo "+refs/heads/master:refs/heads/master" >expect.replace && + git clone --mirror .git/ setbranches-mirror && + ( + cd setbranches-mirror && + git remote rename origin scratch && + git config --get-all remote.scratch.fetch >../actual.initial && + + git remote set-branches scratch heads/master && + git config --get-all remote.scratch.fetch >../actual.replace + ) && + test_cmp expect.initial actual.initial && + test_cmp expect.replace actual.replace + ' + test_expect_success 'new remote' ' git remote add someremote foo && echo foo >expect &&