diff options
Diffstat (limited to 'builtin/remote.c')
| -rw-r--r-- | builtin/remote.c | 131 | 
1 files changed, 86 insertions, 45 deletions
diff --git a/builtin/remote.c b/builtin/remote.c index 48e0a6bf26..c810643815 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -1,4 +1,4 @@ -#include "cache.h" +#include "builtin.h"  #include "parse-options.h"  #include "transport.h"  #include "remote.h" @@ -9,13 +9,13 @@  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>)",  	"git remote [-v | --verbose] show [-n] <name>",  	"git remote prune [-n | --dry-run] <name>", -	"git remote [-v | --verbose] update [-p | --prune] [group | remote]", +	"git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]",  	"git remote set-branches <name> [--add] <branch>...",  	"git remote set-url <name> <newurl> [<oldurl>]",  	"git remote set-url --add <name> <newurl>", @@ -88,16 +88,6 @@ static inline int postfixcmp(const char *string, const char *postfix)  	return strcmp(string + len1 - len2, postfix);  } -static int opt_parse_track(const struct option *opt, const char *arg, int not) -{ -	struct string_list *list = opt->value; -	if (not) -		string_list_clear(list, 0); -	else -		string_list_append(list, arg); -	return 0; -} -  static int fetch_remote(const char *name)  {  	const char *argv[] = { "fetch", name, NULL, NULL }; @@ -117,6 +107,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)  { @@ -131,9 +126,32 @@ static int add_branch(const char *key, const char *branchname,  	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; @@ -148,10 +166,12 @@ static int add(int argc, const char **argv)  			    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_LIST('t', "track", &track, "branch", +				"branch(es) to 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()  	}; @@ -161,6 +181,11 @@ static int add(int argc, const char **argv)  	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 && !(mirror & MIRROR_FETCH) && track.nr) +		die("specifying branches to track makes sense only with fetch mirrors"); +  	name = argv[0];  	url = argv[1]; @@ -177,18 +202,19 @@ static int add(int argc, const char **argv)  	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")) @@ -323,7 +349,8 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat  		else  			string_list_append(&states->tracked, abbrev_branch(ref->name));  	} -	stale_refs = get_stale_heads(states->remote, fetch_map); +	stale_refs = get_stale_heads(states->remote->fetch, +				     states->remote->fetch_refspec_nr, fetch_map);  	for (ref = stale_refs; ref; ref = ref->next) {  		struct string_list_item *item =  			string_list_append(&states->stale, abbrev_branch(ref->name)); @@ -363,8 +390,8 @@ static int get_push_ref_states(const struct ref *remote_refs,  	local_refs = get_local_heads();  	push_map = copy_ref_list(remote_refs); -	match_refs(local_refs, &push_map, remote->push_refspec_nr, -		   remote->push_refspec, MATCH_REFS_NONE); +	match_push_refs(local_refs, &push_map, remote->push_refspec_nr, +			remote->push_refspec, MATCH_REFS_NONE);  	states->push.strdup_strings = 1;  	for (ref = push_map; ref; ref = ref->next) { @@ -507,7 +534,7 @@ static int add_branch_for_removal(const char *refname,  			return 0;  	} -	/* don't delete non-remote refs */ +	/* don't delete non-remote-tracking refs */  	if (prefixcmp(refname, "refs/remotes")) {  		/* advise user how to delete local branches */  		if (!prefixcmp(refname, "refs/heads/")) @@ -544,7 +571,7 @@ static int read_remote_branches(const char *refname,  	unsigned char orig_sha1[20];  	const char *symref; -	strbuf_addf(&buf, "refs/remotes/%s", rename->old); +	strbuf_addf(&buf, "refs/remotes/%s/", rename->old);  	if (!prefixcmp(refname, buf.buf)) {  		item = string_list_append(rename->remote_branches, xstrdup(refname));  		symref = resolve_ref(refname, orig_sha1, 1, &flag); @@ -595,10 +622,11 @@ static int mv(int argc, const char **argv)  		OPT_END()  	};  	struct remote *oldremote, *newremote; -	struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT; +	struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT, +		old_remote_context = STRBUF_INIT;  	struct string_list remote_branches = STRING_LIST_INIT_NODUP;  	struct rename_info rename; -	int i; +	int i, refspec_updated = 0;  	if (argc != 3)  		usage_with_options(builtin_remote_rename_usage, options); @@ -633,15 +661,25 @@ static int mv(int argc, const char **argv)  	strbuf_addf(&buf, "remote.%s.fetch", rename.new);  	if (git_config_set_multivar(buf.buf, NULL, NULL, 1))  		return error("Could not remove config section '%s'", buf.buf); +	strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old);  	for (i = 0; i < oldremote->fetch_refspec_nr; i++) {  		char *ptr;  		strbuf_reset(&buf2);  		strbuf_addstr(&buf2, oldremote->fetch_refspec[i]); -		ptr = strstr(buf2.buf, rename.old); -		if (ptr) -			strbuf_splice(&buf2, ptr-buf2.buf, strlen(rename.old), -					rename.new, strlen(rename.new)); +		ptr = strstr(buf2.buf, old_remote_context.buf); +		if (ptr) { +			refspec_updated = 1; +			strbuf_splice(&buf2, +				      ptr-buf2.buf + strlen(":refs/remotes/"), +				      strlen(rename.old), rename.new, +				      strlen(rename.new)); +		} else +			warning("Not updating non-default fetch respec\n" +				"\t%s\n" +				"\tPlease update the configuration manually if necessary.", +				buf2.buf); +  		if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))  			return error("Could not append '%s'", buf.buf);  	} @@ -659,6 +697,9 @@ static int mv(int argc, const char **argv)  		}  	} +	if (!refspec_updated) +		return 0; +  	/*  	 * First remove symrefs, then rename the rest, finally create  	 * the new symrefs. @@ -791,9 +832,9 @@ static int rm(int argc, const char **argv)  	if (skipped.nr) {  		fprintf(stderr, skipped.nr == 1 ? -			"Note: A non-remote branch was not removed; " +			"Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"  			"to delete it, use:\n" : -			"Note: Non-remote branches were not removed; " +			"Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"  			"to delete them, use:\n");  		for (i = 0; i < skipped.nr; i++)  			fprintf(stderr, "  git branch -d %s\n", @@ -1077,7 +1118,7 @@ static int show(int argc, const char **argv)  			url = states.remote->url;  			url_nr = states.remote->url_nr;  		} -		for (i=0; i < url_nr; i++) +		for (i = 0; i < url_nr; i++)  			printf("  Push  URL: %s\n", url[i]);  		if (!i)  			printf("  Push  URL: %s\n", "(no URL)"); @@ -1200,7 +1241,7 @@ static int prune(int argc, const char **argv)  {  	int dry_run = 0, result = 0;  	struct option options[] = { -		OPT__DRY_RUN(&dry_run), +		OPT__DRY_RUN(&dry_run, "dry run"),  		OPT_END()  	}; @@ -1358,7 +1399,7 @@ static int set_branches(int argc, const char **argv)  			     builtin_remote_setbranches_usage, 0);  	if (argc == 0) {  		error("no remote specified"); -		usage_with_options(builtin_remote_seturl_usage, options); +		usage_with_options(builtin_remote_setbranches_usage, options);  	}  	argv[argc] = NULL; @@ -1386,7 +1427,7 @@ static int set_url(int argc, const char **argv)  			    "delete URLs"),  		OPT_END()  	}; -	argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage, +	argc = parse_options(argc, argv, NULL, options, builtin_remote_seturl_usage,  			     PARSE_OPT_KEEP_ARGV0);  	if (add_mode && delete_mode) @@ -1512,7 +1553,7 @@ static int show_all(void)  int cmd_remote(int argc, const char **argv, const char *prefix)  {  	struct option options[] = { -		OPT_BOOLEAN('v', "verbose", &verbose, "be verbose; must be placed before a subcommand"), +		OPT__VERBOSE(&verbose, "be verbose; must be placed before a subcommand"),  		OPT_END()  	};  	int result;  | 
