diff options
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | builtin-fetch.c | 10 | ||||
| -rw-r--r-- | builtin-ls-remote.c | 74 | ||||
| -rw-r--r-- | builtin-send-pack.c (renamed from send-pack.c) | 168 | ||||
| -rw-r--r-- | builtin.h | 2 | ||||
| -rw-r--r-- | cache.h | 2 | ||||
| -rw-r--r-- | connect.c | 10 | ||||
| -rwxr-xr-x | contrib/examples/git-ls-remote.sh (renamed from git-ls-remote.sh) | 0 | ||||
| -rw-r--r-- | git.c | 3 | ||||
| -rw-r--r-- | http-push.c | 2 | ||||
| -rw-r--r-- | peek-remote.c | 73 | ||||
| -rw-r--r-- | receive-pack.c | 4 | ||||
| -rw-r--r-- | remote.c | 32 | ||||
| -rw-r--r-- | remote.h | 10 | ||||
| -rw-r--r-- | send-pack.h | 17 | ||||
| -rwxr-xr-x | t/t5405-send-pack-rewind.sh | 42 | ||||
| -rwxr-xr-x | t/t5512-ls-remote.sh | 52 | ||||
| -rw-r--r-- | transport.c | 61 | ||||
| -rw-r--r-- | transport.h | 6 | 
19 files changed, 368 insertions, 205 deletions
@@ -212,7 +212,6 @@ BASIC_LDFLAGS =  SCRIPT_SH = \  	git-bisect.sh git-checkout.sh \  	git-clean.sh git-clone.sh git-commit.sh \ -	git-ls-remote.sh \  	git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \  	git-pull.sh git-rebase.sh git-rebase--interactive.sh \  	git-repack.sh git-request-pull.sh \ @@ -241,7 +240,7 @@ PROGRAMS = \  	git-fast-import$X \  	git-daemon$X \  	git-merge-index$X git-mktag$X git-mktree$X git-patch-id$X \ -	git-peek-remote$X git-receive-pack$X \ +	git-receive-pack$X \  	git-send-pack$X git-shell$X \  	git-show-index$X \  	git-unpack-file$X \ @@ -347,6 +346,7 @@ BUILTIN_OBJS = \  	builtin-log.o \  	builtin-ls-files.o \  	builtin-ls-tree.o \ +	builtin-ls-remote.o \  	builtin-mailinfo.o \  	builtin-mailsplit.o \  	builtin-merge-base.o \ @@ -359,6 +359,7 @@ BUILTIN_OBJS = \  	builtin-push.o \  	builtin-read-tree.o \  	builtin-reflog.o \ +	builtin-send-pack.o \  	builtin-config.o \  	builtin-rerere.o \  	builtin-reset.o \ diff --git a/builtin-fetch.c b/builtin-fetch.c index 5f5b59bfdb..6b1750d28b 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -29,7 +29,7 @@ static void unlock_pack_on_signal(int signo)  }  static void add_merge_config(struct ref **head, -		           struct ref *remote_refs, +			   const struct ref *remote_refs,  		           struct branch *branch,  		           struct ref ***tail)  { @@ -77,7 +77,7 @@ static struct ref *get_ref_map(struct transport *transport,  	struct ref *ref_map = NULL;  	struct ref **tail = &ref_map; -	struct ref *remote_refs = transport_get_remote_refs(transport); +	const struct ref *remote_refs = transport_get_remote_refs(transport);  	if (ref_count || tags) {  		for (i = 0; i < ref_count; i++) { @@ -354,12 +354,12 @@ static struct ref *find_non_local_tags(struct transport *transport,  	struct path_list new_refs = { NULL, 0, 0, 1 };  	char *ref_name;  	int ref_name_len; -	unsigned char *ref_sha1; -	struct ref *tag_ref; +	const unsigned char *ref_sha1; +	const struct ref *tag_ref;  	struct ref *rm = NULL;  	struct ref *ref_map = NULL;  	struct ref **tail = &ref_map; -	struct ref *ref; +	const struct ref *ref;  	for_each_ref(add_existing, &existing_refs);  	for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) { diff --git a/builtin-ls-remote.c b/builtin-ls-remote.c new file mode 100644 index 0000000000..56f3f88023 --- /dev/null +++ b/builtin-ls-remote.c @@ -0,0 +1,74 @@ +#include "builtin.h" +#include "cache.h" +#include "transport.h" +#include "remote.h" + +static const char ls_remote_usage[] = +"git-ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>"; + +int cmd_ls_remote(int argc, const char **argv, const char *prefix) +{ +	int i; +	const char *dest = NULL; +	int nongit = 0; +	unsigned flags = 0; +	const char *uploadpack = NULL; + +	struct remote *remote; +	struct transport *transport; +	const struct ref *ref; + +	setup_git_directory_gently(&nongit); + +	for (i = 1; i < argc; i++) { +		const char *arg = argv[i]; + +		if (*arg == '-') { +			if (!prefixcmp(arg, "--upload-pack=")) { +				uploadpack = arg + 14; +				continue; +			} +			if (!prefixcmp(arg, "--exec=")) { +				uploadpack = arg + 7; +				continue; +			} +			if (!strcmp("--tags", arg)) { +				flags |= REF_TAGS; +				continue; +			} +			if (!strcmp("--heads", arg)) { +				flags |= REF_HEADS; +				continue; +			} +			if (!strcmp("--refs", arg)) { +				flags |= REF_NORMAL; +				continue; +			} +			usage(ls_remote_usage); +		} +		dest = arg; +		break; +	} + +	if (!dest || i != argc - 1) +		usage(ls_remote_usage); + +	remote = nongit ? NULL : remote_get(dest); +	if (remote && !remote->url_nr) +		die("remote %s has no configured URL", dest); +	transport = transport_get(remote, remote ? remote->url[0] : dest); +	if (uploadpack != NULL) +		transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack); + +	ref = transport_get_remote_refs(transport); + +	if (!ref) +		return 1; + +	while (ref) { +		if (check_ref_type(ref, flags)) +			printf("%s	%s\n", sha1_to_hex(ref->old_sha1), ref->name); +		ref = ref->next; +	} +	return 0; +} diff --git a/send-pack.c b/builtin-send-pack.c index b74fd454f2..5a0f5c681c 100644 --- a/send-pack.c +++ b/builtin-send-pack.c @@ -5,16 +5,15 @@  #include "pkt-line.h"  #include "run-command.h"  #include "remote.h" +#include "send-pack.h"  static const char send_pack_usage[] =  "git-send-pack [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"  "  --all and explicit <ref> specification are mutually exclusive."; -static const char *receivepack = "git-receive-pack"; -static int verbose; -static int send_all; -static int force_update; -static int use_thin_pack; -static int dry_run; + +static struct send_pack_args args = { +	/* .receivepack = */ "git-receive-pack", +};  /*   * Make a pack stream and spit it out into file descriptor fd @@ -26,7 +25,7 @@ static int pack_objects(int fd, struct ref *refs)  	 * the revision parameters to it via its stdin and  	 * let its stdout go back to the other end.  	 */ -	const char *args[] = { +	const char *argv[] = {  		"pack-objects",  		"--all-progress",  		"--revs", @@ -36,10 +35,10 @@ static int pack_objects(int fd, struct ref *refs)  	};  	struct child_process po; -	if (use_thin_pack) -		args[4] = "--thin"; +	if (args.use_thin_pack) +		argv[4] = "--thin";  	memset(&po, 0, sizeof(po)); -	po.argv = args; +	po.argv = argv;  	po.in = -1;  	po.out = fd;  	po.git_cmd = 1; @@ -196,7 +195,8 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)  		return;  	if (!remote_find_tracking(remote, &rs)) { -		fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); +		if (args.verbose) +			fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);  		if (is_null_sha1(ref->peer_ref->new_sha1)) {  			if (delete_ref(rs.dst, NULL))  				error("Failed to delete"); @@ -207,7 +207,18 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)  	}  } -static int send_pack(int in, int out, struct remote *remote, int nr_refspec, char **refspec) +static const char *prettify_ref(const char *name) +{ +	return name + ( +		!prefixcmp(name, "refs/heads/") ? 11 : +		!prefixcmp(name, "refs/tags/") ? 10 : +		!prefixcmp(name, "refs/remotes/") ? 13 : +		0); +} + +#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) + +static int do_send_pack(int in, int out, struct remote *remote, const char *dest, int nr_refspec, const char **refspec)  {  	struct ref *ref;  	int new_refs; @@ -215,6 +226,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha  	int ask_for_status_report = 0;  	int allow_deleting_refs = 0;  	int expect_status_report = 0; +	int shown_dest = 0;  	/* No funny business with the matcher */  	remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL); @@ -230,7 +242,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha  	if (!remote_tail)  		remote_tail = &remote_refs;  	if (match_refs(local_refs, remote_refs, &remote_tail, -		       nr_refspec, refspec, send_all)) +		       nr_refspec, refspec, args.send_all))  		return -1;  	if (!remote_refs) { @@ -246,21 +258,33 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha  	for (ref = remote_refs; ref; ref = ref->next) {  		char old_hex[60], *new_hex;  		int will_delete_ref; +		const char *pretty_ref; +		const char *pretty_peer;  		if (!ref->peer_ref)  			continue; +		if (!shown_dest) { +			fprintf(stderr, "To %s\n", dest); +			shown_dest = 1; +		} + +		pretty_ref = prettify_ref(ref->name); +		pretty_peer = prettify_ref(ref->peer_ref->name);  		will_delete_ref = is_null_sha1(ref->peer_ref->new_sha1);  		if (will_delete_ref && !allow_deleting_refs) { -			error("remote does not support deleting refs"); +			fprintf(stderr, " ! %-*s %s (remote does not support deleting refs)\n", +					SUMMARY_WIDTH, "[rejected]", pretty_ref);  			ret = -2;  			continue;  		}  		if (!will_delete_ref &&  		    !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) { -			if (verbose) -				fprintf(stderr, "'%s': up-to-date\n", ref->name); +			if (args.verbose) +				fprintf(stderr, " = %-*s %s -> %s\n", +					SUMMARY_WIDTH, "[up to date]", +					pretty_peer, pretty_ref);  			continue;  		} @@ -283,7 +307,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha  		 *     always allowed.  		 */ -		if (!force_update && +		if (!args.force_update &&  		    !will_delete_ref &&  		    !is_null_sha1(ref->old_sha1) &&  		    !ref->force) { @@ -297,12 +321,9 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha  				 * commits at the remote end and likely  				 * we were not up to date to begin with.  				 */ -				error("remote '%s' is not an ancestor of\n" -				      " local  '%s'.\n" -				      " Maybe you are not up-to-date and " -				      "need to pull first?", -				      ref->name, -				      ref->peer_ref->name); +				fprintf(stderr, " ! %-*s %s -> %s (non-fast forward)\n", +						SUMMARY_WIDTH, "[rejected]", +						pretty_peer, pretty_ref);  				ret = -2;  				continue;  			} @@ -313,7 +334,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha  		strcpy(old_hex, sha1_to_hex(ref->old_sha1));  		new_hex = sha1_to_hex(ref->new_sha1); -		if (!dry_run) { +		if (!args.dry_run) {  			if (ask_for_status_report) {  				packet_write(out, "%s %s %s%c%s",  					old_hex, new_hex, ref->name, 0, @@ -326,19 +347,46 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha  					old_hex, new_hex, ref->name);  		}  		if (will_delete_ref) -			fprintf(stderr, "deleting '%s'\n", ref->name); +			fprintf(stderr, " - %-*s %s\n", +				SUMMARY_WIDTH, "[deleting]", +				pretty_ref); +		else if (is_null_sha1(ref->old_sha1)) { +			const char *msg; + +			if (!prefixcmp(ref->name, "refs/tags/")) +				msg = "[new tag]"; +			else +				msg = "[new branch]"; +			fprintf(stderr, " * %-*s %s -> %s\n", +				SUMMARY_WIDTH, msg, +				pretty_peer, pretty_ref); +		}  		else { -			fprintf(stderr, "updating '%s'", ref->name); -			if (strcmp(ref->name, ref->peer_ref->name)) -				fprintf(stderr, " using '%s'", -					ref->peer_ref->name); -			fprintf(stderr, "\n  from %s\n  to   %s\n", -				old_hex, new_hex); +			char quickref[83]; +			char type = ' '; +			const char *msg = ""; +			const char *old_abb; +			old_abb = find_unique_abbrev(ref->old_sha1, DEFAULT_ABBREV); +			strcpy(quickref, old_abb ? old_abb : old_hex); +			if (ref_newer(ref->peer_ref->new_sha1, ref->old_sha1)) +				strcat(quickref, ".."); +			else { +				strcat(quickref, "..."); +				type = '+'; +				msg = " (forced update)"; +			} +			strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); + +			fprintf(stderr, " %c %-*s %s -> %s%s\n", +				type, +				SUMMARY_WIDTH, quickref, +				pretty_peer, pretty_ref, +				msg);  		}  	}  	packet_flush(out); -	if (new_refs && !dry_run) +	if (new_refs && !args.dry_run)  		ret = pack_objects(out, remote_refs);  	close(out); @@ -347,7 +395,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha  			ret = -4;  	} -	if (!dry_run && remote && ret == 0) { +	if (!args.dry_run && remote && ret == 0) {  		for (ref = remote_refs; ref; ref = ref->next)  			update_tracking_ref(remote, ref);  	} @@ -357,7 +405,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha  	return ret;  } -static void verify_remote_names(int nr_heads, char **heads) +static void verify_remote_names(int nr_heads, const char **heads)  {  	int i; @@ -378,30 +426,25 @@ static void verify_remote_names(int nr_heads, char **heads)  	}  } -int main(int argc, char **argv) +int cmd_send_pack(int argc, const char **argv, const char *prefix)  {  	int i, nr_heads = 0; -	char *dest = NULL; -	char **heads = NULL; -	int fd[2], ret; -	struct child_process *conn; -	char *remote_name = NULL; +	const char **heads = NULL; +	const char *remote_name = NULL;  	struct remote *remote = NULL; - -	setup_git_directory(); -	git_config(git_default_config); +	const char *dest = NULL;  	argv++;  	for (i = 1; i < argc; i++, argv++) { -		char *arg = *argv; +		const char *arg = *argv;  		if (*arg == '-') {  			if (!prefixcmp(arg, "--receive-pack=")) { -				receivepack = arg + 15; +				args.receivepack = arg + 15;  				continue;  			}  			if (!prefixcmp(arg, "--exec=")) { -				receivepack = arg + 7; +				args.receivepack = arg + 7;  				continue;  			}  			if (!prefixcmp(arg, "--remote=")) { @@ -409,23 +452,23 @@ int main(int argc, char **argv)  				continue;  			}  			if (!strcmp(arg, "--all")) { -				send_all = 1; +				args.send_all = 1;  				continue;  			}  			if (!strcmp(arg, "--dry-run")) { -				dry_run = 1; +				args.dry_run = 1;  				continue;  			}  			if (!strcmp(arg, "--force")) { -				force_update = 1; +				args.force_update = 1;  				continue;  			}  			if (!strcmp(arg, "--verbose")) { -				verbose = 1; +				args.verbose = 1;  				continue;  			}  			if (!strcmp(arg, "--thin")) { -				use_thin_pack = 1; +				args.use_thin_pack = 1;  				continue;  			}  			usage(send_pack_usage); @@ -434,15 +477,14 @@ int main(int argc, char **argv)  			dest = arg;  			continue;  		} -		heads = argv; +		heads = (const char **) argv;  		nr_heads = argc - i;  		break;  	}  	if (!dest)  		usage(send_pack_usage); -	if (heads && send_all) +	if (heads && args.send_all)  		usage(send_pack_usage); -	verify_remote_names(nr_heads, heads);  	if (remote_name) {  		remote = remote_get(remote_name); @@ -452,8 +494,22 @@ int main(int argc, char **argv)  		}  	} -	conn = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0); -	ret = send_pack(fd[0], fd[1], remote, nr_heads, heads); +	return send_pack(&args, dest, remote, nr_heads, heads); +} + +int send_pack(struct send_pack_args *my_args, +	      const char *dest, struct remote *remote, +	      int nr_heads, const char **heads) +{ +	int fd[2], ret; +	struct child_process *conn; + +	memcpy(&args, my_args, sizeof(args)); + +	verify_remote_names(nr_heads, heads); + +	conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0); +	ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);  	close(fd[0]);  	close(fd[1]);  	ret |= finish_connect(conn); @@ -48,6 +48,7 @@ extern int cmd_log(int argc, const char **argv, const char *prefix);  extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);  extern int cmd_ls_files(int argc, const char **argv, const char *prefix);  extern int cmd_ls_tree(int argc, const char **argv, const char *prefix); +extern int cmd_ls_remote(int argc, const char **argv, const char *prefix);  extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);  extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);  extern int cmd_merge_base(int argc, const char **argv, const char *prefix); @@ -69,6 +70,7 @@ extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);  extern int cmd_revert(int argc, const char **argv, const char *prefix);  extern int cmd_rm(int argc, const char **argv, const char *prefix);  extern int cmd_runstatus(int argc, const char **argv, const char *prefix); +extern int cmd_send_pack(int argc, const char **argv, const char *prefix);  extern int cmd_shortlog(int argc, const char **argv, const char *prefix);  extern int cmd_show(int argc, const char **argv, const char *prefix);  extern int cmd_show_branch(int argc, const char **argv, const char *prefix); @@ -504,7 +504,7 @@ struct ref {  #define REF_TAGS	(1u << 2)  #define CONNECT_VERBOSE       (1u << 0) -extern struct child_process *git_connect(int fd[2], char *url, const char *prog, int flags); +extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);  extern int finish_connect(struct child_process *conn);  extern int path_match(const char *path, int nr, char **match);  extern int get_ack(int fd, unsigned char *result_sha1); @@ -36,6 +36,11 @@ static int check_ref(const char *name, int len, unsigned int flags)  	return !(flags & ~REF_NORMAL);  } +int check_ref_type(const struct ref *ref, int flags) +{ +	return check_ref(ref->name, strlen(ref->name), flags); +} +  /*   * Read all the refs from the other end   */ @@ -476,9 +481,10 @@ char *get_port(char *host)   *   * If it returns, the connect is successful; it just dies on errors.   */ -struct child_process *git_connect(int fd[2], char *url, +struct child_process *git_connect(int fd[2], const char *url_orig,  				  const char *prog, int flags)  { +	char *url = xstrdup(url_orig);  	char *host, *path = url;  	char *end;  	int c; @@ -568,6 +574,7 @@ struct child_process *git_connect(int fd[2], char *url,  			     prog, path, 0,  			     target_host, 0);  		free(target_host); +		free(url);  		if (free_path)  			free(path);  		return NULL; @@ -619,6 +626,7 @@ struct child_process *git_connect(int fd[2], char *url,  	fd[0] = conn->out; /* read from child's stdout */  	fd[1] = conn->in;  /* write to child's stdin */  	strbuf_release(&cmd); +	free(url);  	if (free_path)  		free(path);  	return conn; diff --git a/git-ls-remote.sh b/contrib/examples/git-ls-remote.sh index fec70bbf88..fec70bbf88 100755 --- a/git-ls-remote.sh +++ b/contrib/examples/git-ls-remote.sh @@ -321,6 +321,7 @@ static void handle_internal_command(int argc, const char **argv)  		{ "log", cmd_log, RUN_SETUP | USE_PAGER },  		{ "ls-files", cmd_ls_files, RUN_SETUP },  		{ "ls-tree", cmd_ls_tree, RUN_SETUP }, +		{ "ls-remote", cmd_ls_remote },  		{ "mailinfo", cmd_mailinfo },  		{ "mailsplit", cmd_mailsplit },  		{ "merge-base", cmd_merge_base, RUN_SETUP }, @@ -328,6 +329,7 @@ static void handle_internal_command(int argc, const char **argv)  		{ "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },  		{ "name-rev", cmd_name_rev, RUN_SETUP },  		{ "pack-objects", cmd_pack_objects, RUN_SETUP }, +		{ "peek-remote", cmd_ls_remote },  		{ "pickaxe", cmd_blame, RUN_SETUP },  		{ "prune", cmd_prune, RUN_SETUP },  		{ "prune-packed", cmd_prune_packed, RUN_SETUP }, @@ -342,6 +344,7 @@ static void handle_internal_command(int argc, const char **argv)  		{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },  		{ "rm", cmd_rm, RUN_SETUP },  		{ "runstatus", cmd_runstatus, RUN_SETUP | NEED_WORK_TREE }, +		{ "send-pack", cmd_send_pack, RUN_SETUP },  		{ "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },  		{ "show-branch", cmd_show_branch, RUN_SETUP },  		{ "show", cmd_show, RUN_SETUP | USE_PAGER }, diff --git a/http-push.c b/http-push.c index 9314621a11..99328f5909 100644 --- a/http-push.c +++ b/http-push.c @@ -2393,7 +2393,7 @@ int main(int argc, char **argv)  	if (!remote_tail)  		remote_tail = &remote_refs;  	if (match_refs(local_refs, remote_refs, &remote_tail, -		       nr_refspec, refspec, push_all)) +		       nr_refspec, (const char **) refspec, push_all))  		return -1;  	if (!remote_refs) {  		fprintf(stderr, "No refs in common and none specified; doing nothing.\n"); diff --git a/peek-remote.c b/peek-remote.c deleted file mode 100644 index 8d20f7c9c6..0000000000 --- a/peek-remote.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "cache.h" -#include "refs.h" -#include "pkt-line.h" - -static const char peek_remote_usage[] = -"git-peek-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>"; -static const char *uploadpack = "git-upload-pack"; - -static int peek_remote(int fd[2], unsigned flags) -{ -	struct ref *ref; - -	get_remote_heads(fd[0], &ref, 0, NULL, flags); -	packet_flush(fd[1]); - -	while (ref) { -		printf("%s	%s\n", sha1_to_hex(ref->old_sha1), ref->name); -		ref = ref->next; -	} -	return 0; -} - -int main(int argc, char **argv) -{ -	int i, ret; -	char *dest = NULL; -	int fd[2]; -	struct child_process *conn; -	int nongit = 0; -	unsigned flags = 0; - -	setup_git_directory_gently(&nongit); - -	for (i = 1; i < argc; i++) { -		char *arg = argv[i]; - -		if (*arg == '-') { -			if (!prefixcmp(arg, "--upload-pack=")) { -				uploadpack = arg + 14; -				continue; -			} -			if (!prefixcmp(arg, "--exec=")) { -				uploadpack = arg + 7; -				continue; -			} -			if (!strcmp("--tags", arg)) { -				flags |= REF_TAGS; -				continue; -			} -			if (!strcmp("--heads", arg)) { -				flags |= REF_HEADS; -				continue; -			} -			if (!strcmp("--refs", arg)) { -				flags |= REF_NORMAL; -				continue; -			} -			usage(peek_remote_usage); -		} -		dest = arg; -		break; -	} - -	if (!dest || i != argc - 1) -		usage(peek_remote_usage); - -	conn = git_connect(fd, dest, uploadpack, 0); -	ret = peek_remote(fd, flags); -	close(fd[0]); -	close(fd[1]); -	ret |= finish_connect(conn); -	return !!ret; -} diff --git a/receive-pack.c b/receive-pack.c index 38e35c06b9..ed44b897f6 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -204,8 +204,6 @@ static const char *update(struct command *cmd)  			error("failed to delete %s", name);  			return "failed to delete";  		} -		fprintf(stderr, "%s: %s -> deleted\n", name, -			sha1_to_hex(old_sha1));  		return NULL; /* good */  	}  	else { @@ -217,8 +215,6 @@ static const char *update(struct command *cmd)  		if (write_ref_sha1(lock, new_sha1, "push")) {  			return "failed to write"; /* error() already called */  		} -		fprintf(stderr, "%s: %s -> %s\n", name, -			sha1_to_hex(old_sha1), sha1_to_hex(new_sha1));  		return NULL; /* good */  	}  } @@ -485,7 +485,7 @@ struct ref *alloc_ref(unsigned namelen)  	return ret;  } -static struct ref *copy_ref(struct ref *ref) +static struct ref *copy_ref(const struct ref *ref)  {  	struct ref *ret = xmalloc(sizeof(struct ref) + strlen(ref->name) + 1);  	memcpy(ret, ref, sizeof(struct ref) + strlen(ref->name) + 1); @@ -493,6 +493,18 @@ static struct ref *copy_ref(struct ref *ref)  	return ret;  } +struct ref *copy_ref_list(const struct ref *ref) +{ +	struct ref *ret = NULL; +	struct ref **tail = &ret; +	while (ref) { +		*tail = copy_ref(ref); +		ref = ref->next; +		tail = &((*tail)->next); +	} +	return ret; +} +  void free_refs(struct ref *ref)  {  	struct ref *next; @@ -710,7 +722,7 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,   * without thinking.   */  int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, -	       int nr_refspec, char **refspec, int all) +	       int nr_refspec, const char **refspec, int all)  {  	struct refspec *rs =  		parse_ref_spec(nr_refspec, (const char **) refspec); @@ -810,10 +822,10 @@ int branch_merge_matches(struct branch *branch,  	return ref_matches_abbrev(branch->merge[i]->src, refname);  } -static struct ref *get_expanded_map(struct ref *remote_refs, +static struct ref *get_expanded_map(const struct ref *remote_refs,  				    const struct refspec *refspec)  { -	struct ref *ref; +	const struct ref *ref;  	struct ref *ret = NULL;  	struct ref **tail = &ret; @@ -824,7 +836,7 @@ static struct ref *get_expanded_map(struct ref *remote_refs,  		if (strchr(ref->name, '^'))  			continue; /* a dereference item */  		if (!prefixcmp(ref->name, refspec->src)) { -			char *match; +			const char *match;  			struct ref *cpy = copy_ref(ref);  			match = ref->name + remote_prefix_len; @@ -842,9 +854,9 @@ static struct ref *get_expanded_map(struct ref *remote_refs,  	return ret;  } -static struct ref *find_ref_by_name_abbrev(struct ref *refs, const char *name) +static const struct ref *find_ref_by_name_abbrev(const struct ref *refs, const char *name)  { -	struct ref *ref; +	const struct ref *ref;  	for (ref = refs; ref; ref = ref->next) {  		if (ref_matches_abbrev(name, ref->name))  			return ref; @@ -852,9 +864,9 @@ static struct ref *find_ref_by_name_abbrev(struct ref *refs, const char *name)  	return NULL;  } -struct ref *get_remote_ref(struct ref *remote_refs, const char *name) +struct ref *get_remote_ref(const struct ref *remote_refs, const char *name)  { -	struct ref *ref = find_ref_by_name_abbrev(remote_refs, name); +	const struct ref *ref = find_ref_by_name_abbrev(remote_refs, name);  	if (!ref)  		return NULL; @@ -887,7 +899,7 @@ static struct ref *get_local_ref(const char *name)  	return ret;  } -int get_fetch_map(struct ref *remote_refs, +int get_fetch_map(const struct ref *remote_refs,  		  const struct refspec *refspec,  		  struct ref ***tail,  		  int missing_ok) @@ -44,6 +44,10 @@ struct refspec {  struct ref *alloc_ref(unsigned namelen); +struct ref *copy_ref_list(const struct ref *ref); + +int check_ref_type(const struct ref *ref, int flags); +  /*   * Frees the entire list and peers of elements.   */ @@ -57,7 +61,7 @@ void ref_remove_duplicates(struct ref *ref_map);  struct refspec *parse_ref_spec(int nr_refspec, const char **refspec);  int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, -	       int nr_refspec, char **refspec, int all); +	       int nr_refspec, const char **refspec, int all);  /*   * Given a list of the remote refs and the specification of things to @@ -71,10 +75,10 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,   * missing_ok is usually false, but when we are adding branch.$name.merge   * it is Ok if the branch is not at the remote anymore.   */ -int get_fetch_map(struct ref *remote_refs, const struct refspec *refspec, +int get_fetch_map(const struct ref *remote_refs, const struct refspec *refspec,  		  struct ref ***tail, int missing_ok); -struct ref *get_remote_ref(struct ref *remote_refs, const char *name); +struct ref *get_remote_ref(const struct ref *remote_refs, const char *name);  /*   * For the given remote, reads the refspec's src and sets the other fields. diff --git a/send-pack.h b/send-pack.h new file mode 100644 index 0000000000..7a24f71c77 --- /dev/null +++ b/send-pack.h @@ -0,0 +1,17 @@ +#ifndef SEND_PACK_H +#define SEND_PACK_H + +struct send_pack_args { +	const char *receivepack; +	unsigned verbose:1, +		send_all:1, +		force_update:1, +		use_thin_pack:1, +		dry_run:1; +}; + +int send_pack(struct send_pack_args *args, +	      const char *dest, struct remote *remote, +	      int nr_heads, const char **heads); + +#endif diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh new file mode 100755 index 0000000000..86abc62271 --- /dev/null +++ b/t/t5405-send-pack-rewind.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +test_description='forced push to replace commit we do not have' + +. ./test-lib.sh + +test_expect_success setup ' + +	>file1 && git add file1 && test_tick && +	git commit -m Initial && + +	mkdir another && ( +		cd another && +		git init && +		git fetch .. master:master +	) && + +	>file2 && git add file2 && test_tick && +	git commit -m Second + +' + +test_expect_success 'non forced push should die not segfault' ' + +	( +		cd another && +		git push .. master:master +		test $? = 1 +	) + +' + +test_expect_success 'forced push should succeed' ' + +	( +		cd another && +		git push .. +master:master +	) + +' + +test_done diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh new file mode 100755 index 0000000000..6ec5f7c48b --- /dev/null +++ b/t/t5512-ls-remote.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +test_description='git ls-remote' + +. ./test-lib.sh + +test_expect_success setup ' + +	>file && +	git add file && +	test_tick && +	git commit -m initial && +	git tag mark && +	git show-ref --tags -d | sed -e "s/ /	/" >expected.tag && +	( +		echo "$(git rev-parse HEAD)	HEAD" +		git show-ref -d	| sed -e "s/ /	/" +	) >expected.all && + +	git remote add self $(pwd)/.git + +' + +test_expect_success 'ls-remote --tags .git' ' + +	git ls-remote --tags .git >actual && +	diff -u expected.tag actual + +' + +test_expect_success 'ls-remote .git' ' + +	git ls-remote .git >actual && +	diff -u expected.all actual + +' + +test_expect_success 'ls-remote --tags self' ' + +	git ls-remote --tags self >actual && +	diff -u expected.tag actual + +' + +test_expect_success 'ls-remote self' ' + +	git ls-remote self >actual && +	diff -u expected.all actual + +' + +test_done diff --git a/transport.c b/transport.c index fa5cfbb09d..83677fca40 100644 --- a/transport.c +++ b/transport.c @@ -6,6 +6,7 @@  #endif  #include "pkt-line.h"  #include "fetch-pack.h" +#include "send-pack.h"  #include "walker.h"  #include "bundle.h"  #include "dir.h" @@ -141,7 +142,7 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)  	}  } -static struct ref *get_refs_via_rsync(const struct transport *transport) +static struct ref *get_refs_via_rsync(struct transport *transport)  {  	struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;  	struct ref dummy, *tail = &dummy; @@ -428,7 +429,7 @@ static int missing__target(int code, int result)  #define missing_target(a) missing__target((a)->http_code, (a)->curl_result) -static struct ref *get_refs_via_curl(const struct transport *transport) +static struct ref *get_refs_via_curl(struct transport *transport)  {  	struct buffer buffer;  	char *data, *start, *mid; @@ -525,7 +526,7 @@ struct bundle_transport_data {  	struct bundle_header header;  }; -static struct ref *get_refs_from_bundle(const struct transport *transport) +static struct ref *get_refs_from_bundle(struct transport *transport)  {  	struct bundle_transport_data *data = transport->data;  	struct ref *result = NULL; @@ -597,7 +598,7 @@ static int set_git_option(struct transport *connection,  	return 1;  } -static struct ref *get_refs_via_connect(const struct transport *transport) +static struct ref *get_refs_via_connect(struct transport *transport)  {  	struct git_transport_data *data = transport->data;  	struct ref *refs; @@ -650,48 +651,16 @@ static int fetch_refs_via_pack(struct transport *transport,  static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)  {  	struct git_transport_data *data = transport->data; -	const char **argv; -	char *rem; -	int argc; -	int err; +	struct send_pack_args args; -	argv = xmalloc((refspec_nr + 11) * sizeof(char *)); -	argv[0] = "send-pack"; -	argc = 1; -	if (flags & TRANSPORT_PUSH_ALL) -		argv[argc++] = "--all"; -	if (flags & TRANSPORT_PUSH_FORCE) -		argv[argc++] = "--force"; -	if (flags & TRANSPORT_PUSH_DRY_RUN) -		argv[argc++] = "--dry-run"; -	if (data->receivepack) { -		char *rp = xmalloc(strlen(data->receivepack) + 16); -		sprintf(rp, "--receive-pack=%s", data->receivepack); -		argv[argc++] = rp; -	} -	if (data->thin) -		argv[argc++] = "--thin"; -	rem = xmalloc(strlen(transport->remote->name) + 10); -	sprintf(rem, "--remote=%s", transport->remote->name); -	argv[argc++] = rem; -	argv[argc++] = transport->url; -	while (refspec_nr--) -		argv[argc++] = *refspec++; -	argv[argc] = NULL; -	err = run_command_v_opt(argv, RUN_GIT_CMD); -	switch (err) { -	case -ERR_RUN_COMMAND_FORK: -		error("unable to fork for %s", argv[0]); -	case -ERR_RUN_COMMAND_EXEC: -		error("unable to exec %s", argv[0]); -		break; -	case -ERR_RUN_COMMAND_WAITPID: -	case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: -	case -ERR_RUN_COMMAND_WAITPID_SIGNAL: -	case -ERR_RUN_COMMAND_WAITPID_NOEXIT: -		error("%s died with strange error", argv[0]); -	} -	return !!err; +	args.receivepack = data->receivepack; +	args.send_all = !!(flags & TRANSPORT_PUSH_ALL); +	args.force_update = !!(flags & TRANSPORT_PUSH_FORCE); +	args.use_thin_pack = data->thin; +	args.verbose = transport->verbose; +	args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN); + +	return send_pack(&args, transport->url, transport->remote, refspec_nr, refspec);  }  static int disconnect_git(struct transport *transport) @@ -783,7 +752,7 @@ int transport_push(struct transport *transport,  	return transport->push(transport, refspec_nr, refspec, flags);  } -struct ref *transport_get_remote_refs(struct transport *transport) +const struct ref *transport_get_remote_refs(struct transport *transport)  {  	if (!transport->remote_refs)  		transport->remote_refs = transport->get_refs_list(transport); diff --git a/transport.h b/transport.h index df12ea7424..d27f5629d2 100644 --- a/transport.h +++ b/transport.h @@ -8,7 +8,7 @@ struct transport {  	struct remote *remote;  	const char *url;  	void *data; -	struct ref *remote_refs; +	const struct ref *remote_refs;  	/**  	 * Returns 0 if successful, positive if the option is not @@ -18,7 +18,7 @@ struct transport {  	int (*set_option)(struct transport *connection, const char *name,  			  const char *value); -	struct ref *(*get_refs_list)(const struct transport *transport); +	struct ref *(*get_refs_list)(struct transport *transport);  	int (*fetch)(struct transport *transport, int refs_nr, struct ref **refs);  	int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags); @@ -61,7 +61,7 @@ int transport_set_option(struct transport *transport, const char *name,  int transport_push(struct transport *connection,  		   int refspec_nr, const char **refspec, int flags); -struct ref *transport_get_remote_refs(struct transport *transport); +const struct ref *transport_get_remote_refs(struct transport *transport);  int transport_fetch_refs(struct transport *transport, struct ref *refs);  void transport_unlock_pack(struct transport *transport);  | 
