send-pack.c 8.5 KB
Newer Older
1
#include "cache.h"
2
#include "commit.h"
3
#include "tag.h"
4
#include "refs.h"
5
#include "pkt-line.h"
6
#include "exec_cmd.h"
7

8
static const char send_pack_usage[] =
9 10
"git-send-pack [--all] [--exec=git-receive-pack] <remote> [<head>...]\n"
"  --all and explicit <head> specification are mutually exclusive.";
11
static const char *exec = "git-receive-pack";
12
static int verbose = 0;
13
static int send_all = 0;
14
static int force_update = 0;
15

16 17 18 19 20 21 22 23 24 25 26
static int is_zero_sha1(const unsigned char *sha1)
{
	int i;

	for (i = 0; i < 20; i++) {
		if (*sha1++)
			return 0;
	}
	return 1;
}

27 28 29
static void exec_pack_objects(void)
{
	static char *args[] = {
30
		"pack-objects",
31 32 33
		"--stdout",
		NULL
	};
34
	execv_git_cmd(args);
35 36 37 38 39 40 41 42
	die("git-pack-objects exec failed (%s)", strerror(errno));
}

static void exec_rev_list(struct ref *refs)
{
	static char *args[1000];
	int i = 0;

43
	args[i++] = "rev-list";	/* 0 */
44 45 46 47 48
	args[i++] = "--objects";	/* 1 */
	while (refs) {
		char *buf = malloc(100);
		if (i > 900)
			die("git-rev-list environment overflow");
49 50
		if (!is_zero_sha1(refs->old_sha1) &&
		    has_sha1_file(refs->old_sha1)) {
51 52 53 54 55 56 57 58
			args[i++] = buf;
			snprintf(buf, 50, "^%s", sha1_to_hex(refs->old_sha1));
			buf += 50;
		}
		if (!is_zero_sha1(refs->new_sha1)) {
			args[i++] = buf;
			snprintf(buf, 50, "%s", sha1_to_hex(refs->new_sha1));
		}
59 60 61
		refs = refs->next;
	}
	args[i] = NULL;
62
	execv_git_cmd(args);
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
	die("git-rev-list exec failed (%s)", strerror(errno));
}

static void rev_list(int fd, struct ref *refs)
{
	int pipe_fd[2];
	pid_t pack_objects_pid;

	if (pipe(pipe_fd) < 0)
		die("rev-list setup: pipe failed");
	pack_objects_pid = fork();
	if (!pack_objects_pid) {
		dup2(pipe_fd[0], 0);
		dup2(fd, 1);
		close(pipe_fd[0]);
		close(pipe_fd[1]);
		close(fd);
		exec_pack_objects();
		die("pack-objects setup failed");
	}
	if (pack_objects_pid < 0)
		die("pack-objects fork failed");
	dup2(pipe_fd[1], 1);
	close(pipe_fd[0]);
	close(pipe_fd[1]);
	close(fd);
	exec_rev_list(refs);
}

static int pack_objects(int fd, struct ref *refs)
{
	pid_t rev_list_pid;

	rev_list_pid = fork();
	if (!rev_list_pid) {
		rev_list(fd, refs);
		die("rev-list setup failed");
	}
	if (rev_list_pid < 0)
		die("rev-list fork failed");
	/*
	 * We don't wait for the rev-list pipeline in the parent:
	 * we end up waiting for the other end instead
	 */
L
Linus Torvalds 已提交
107
	return 0;
108
}
109

J
Junio C Hamano 已提交
110 111 112 113 114 115 116 117 118 119
static void unmark_and_free(struct commit_list *list, unsigned int mark)
{
	while (list) {
		struct commit_list *temp = list;
		temp->item->object.flags &= ~mark;
		list = temp->next;
		free(temp);
	}
}

120 121
static int ref_newer(const unsigned char *new_sha1,
		     const unsigned char *old_sha1)
122
{
123 124
	struct object *o;
	struct commit *old, *new;
J
Junio C Hamano 已提交
125 126
	struct commit_list *list, *used;
	int found = 0;
127

128 129 130
	/* Both new and old must be commit-ish and new is descendant of
	 * old.  Otherwise we require --force.
	 */
131
	o = deref_tag(parse_object(old_sha1), NULL, 0);
132
	if (!o || o->type != commit_type)
133
		return 0;
134 135
	old = (struct commit *) o;

136
	o = deref_tag(parse_object(new_sha1), NULL, 0);
137
	if (!o || o->type != commit_type)
138
		return 0;
139 140
	new = (struct commit *) o;

141 142
	if (parse_commit(new) < 0)
		return 0;
J
Junio C Hamano 已提交
143 144

	used = list = NULL;
145
	commit_list_insert(new, &list);
L
Linus Torvalds 已提交
146 147
	while (list) {
		new = pop_most_recent_commit(&list, 1);
J
Junio C Hamano 已提交
148 149 150 151 152
		commit_list_insert(new, &used);
		if (new == old) {
			found = 1;
			break;
		}
153
	}
J
Junio C Hamano 已提交
154 155 156
	unmark_and_free(list, 1);
	unmark_and_free(used, 1);
	return found;
157 158
}

J
Junio C Hamano 已提交
159 160
static struct ref *local_refs, **local_tail;
static struct ref *remote_refs, **remote_tail;
161

J
Junio C Hamano 已提交
162
static int one_local_ref(const char *refname, const unsigned char *sha1)
163 164
{
	struct ref *ref;
J
Junio C Hamano 已提交
165 166
	int len = strlen(refname) + 1;
	ref = xcalloc(1, sizeof(*ref) + len);
167 168
	memcpy(ref->new_sha1, sha1, 20);
	memcpy(ref->name, refname, len);
J
Junio C Hamano 已提交
169 170
	*local_tail = ref;
	local_tail = &ref->next;
171 172 173
	return 0;
}

J
Junio C Hamano 已提交
174 175 176 177 178 179
static void get_local_heads(void)
{
	local_tail = &local_refs;
	for_each_ref(one_local_ref);
}

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
static int receive_status(int in)
{
	char line[1000];
	int ret = 0;
	int len = packet_read_line(in, line, sizeof(line));
	if (len < 10 || memcmp(line, "unpack ", 7)) {
		fprintf(stderr, "did not receive status back\n");
		return -1;
	}
	if (memcmp(line, "unpack ok\n", 10)) {
		fputs(line, stderr);
		ret = -1;
	}
	while (1) {
		len = packet_read_line(in, line, sizeof(line));
		if (!len)
			break;
		if (len < 3 ||
		    (memcmp(line, "ok", 2) && memcmp(line, "ng", 2))) {
			fprintf(stderr, "protocol error: %s\n", line);
			ret = -1;
			break;
		}
		if (!memcmp(line, "ok", 2))
			continue;
		fputs(line, stderr);
		ret = -1;
	}
	return ret;
}

J
Junio C Hamano 已提交
211
static int send_pack(int in, int out, int nr_refspec, char **refspec)
212
{
213
	struct ref *ref;
214
	int new_refs;
215
	int ret = 0;
216 217
	int ask_for_status_report = 0;
	int expect_status_report = 0;
218

J
Junio C Hamano 已提交
219
	/* No funny business with the matcher */
220
	remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, 1);
J
Junio C Hamano 已提交
221
	get_local_heads();
222

223 224 225 226
	/* Does the other end support the reporting? */
	if (server_supports("report-status"))
		ask_for_status_report = 1;

J
Junio C Hamano 已提交
227 228 229 230 231 232
	/* match them up */
	if (!remote_tail)
		remote_tail = &remote_refs;
	if (match_refs(local_refs, remote_refs, &remote_tail,
		       nr_refspec, refspec, send_all))
		return -1;
D
Daniel Barkalow 已提交
233 234 235 236 237 238

	if (!remote_refs) {
		fprintf(stderr, "No refs in common and none specified; doing nothing.\n");
		return 0;
	}

239
	/*
J
Junio C Hamano 已提交
240
	 * Finally, tell the other end!
241
	 */
J
Junio C Hamano 已提交
242 243 244 245
	new_refs = 0;
	for (ref = remote_refs; ref; ref = ref->next) {
		char old_hex[60], *new_hex;
		if (!ref->peer_ref)
246
			continue;
247
		if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
248 249
			if (verbose)
				fprintf(stderr, "'%s': up-to-date\n", ref->name);
250 251 252 253 254 255
			continue;
		}

		/* This part determines what can overwrite what.
		 * The rules are:
		 *
256 257
		 * (0) you can always use --force or +A:B notation to
		 *     selectively force individual ref pairs.
258 259 260 261 262 263 264 265 266 267 268
		 *
		 * (1) if the old thing does not exist, it is OK.
		 *
		 * (2) if you do not have the old thing, you are not allowed
		 *     to overwrite it; you would not know what you are losing
		 *     otherwise.
		 *
		 * (3) if both new and old are commit-ish, and new is a
		 *     descendant of old, it is OK.
		 */

269 270 271
		if (!force_update &&
		    !is_zero_sha1(ref->old_sha1) &&
		    !ref->force) {
272 273
			if (!has_sha1_file(ref->old_sha1) ||
			    !ref_newer(ref->peer_ref->new_sha1,
J
Junio C Hamano 已提交
274
				       ref->old_sha1)) {
275 276 277 278 279 280 281 282 283 284 285 286
				/* We do not have the remote ref, or
				 * we know that the remote ref is not
				 * an ancestor of what we are trying to
				 * push.  Either way this can be losing
				 * commits at the remote end and likely
				 * we were not up to date to begin with.
				 */
				error("remote '%s' is not a strict "
				      "subset of local ref '%s'. "
				      "maybe you are not up-to-date and "
				      "need to pull first?",
				      ref->name,
J
Junio C Hamano 已提交
287
				      ref->peer_ref->name);
288
				ret = -2;
J
Junio C Hamano 已提交
289 290
				continue;
			}
291
		}
J
Junio C Hamano 已提交
292 293 294
		memcpy(ref->new_sha1, ref->peer_ref->new_sha1, 20);
		if (is_zero_sha1(ref->new_sha1)) {
			error("cannot happen anymore");
295
			ret = -3;
296 297 298
			continue;
		}
		new_refs++;
299 300
		strcpy(old_hex, sha1_to_hex(ref->old_sha1));
		new_hex = sha1_to_hex(ref->new_sha1);
301 302 303 304 305 306 307 308 309 310 311

		if (ask_for_status_report) {
			packet_write(out, "%s %s %s%c%s",
				     old_hex, new_hex, ref->name, 0,
				     "report-status");
			ask_for_status_report = 0;
			expect_status_report = 1;
		}
		else
			packet_write(out, "%s %s %s",
				     old_hex, new_hex, ref->name);
J
Junio C Hamano 已提交
312 313 314 315
		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);
316
	}
J
Junio C Hamano 已提交
317

318
	packet_flush(out);
319
	if (new_refs)
J
Junio C Hamano 已提交
320
		pack_objects(out, remote_refs);
321
	close(out);
322 323 324 325 326 327 328 329

	if (expect_status_report) {
		if (receive_status(in))
			ret = -4;
	}

	if (!new_refs && ret == 0)
		fprintf(stderr, "Everything up-to-date\n");
330
	return ret;
331 332
}

J
Junio C Hamano 已提交
333

334 335 336 337 338
int main(int argc, char **argv)
{
	int i, nr_heads = 0;
	char *dest = NULL;
	char **heads = NULL;
339 340
	int fd[2], ret;
	pid_t pid;
341

342
	setup_git_directory();
343
	argv++;
344 345
	for (i = 1; i < argc; i++, argv++) {
		char *arg = *argv;
346 347 348 349 350 351

		if (*arg == '-') {
			if (!strncmp(arg, "--exec=", 7)) {
				exec = arg + 7;
				continue;
			}
352 353 354 355
			if (!strcmp(arg, "--all")) {
				send_all = 1;
				continue;
			}
356 357 358 359
			if (!strcmp(arg, "--force")) {
				force_update = 1;
				continue;
			}
360 361 362 363
			if (!strcmp(arg, "--verbose")) {
				verbose = 1;
				continue;
			}
364 365
			usage(send_pack_usage);
		}
366 367 368 369
		if (!dest) {
			dest = arg;
			continue;
		}
370
		heads = argv;
371
		nr_heads = argc - i;
372 373 374 375
		break;
	}
	if (!dest)
		usage(send_pack_usage);
376 377
	if (heads && send_all)
		usage(send_pack_usage);
378
	pid = git_connect(fd, dest, exec);
379
	if (pid < 0)
380
		return 1;
381
	ret = send_pack(fd[0], fd[1], nr_heads, heads);
382 383
	close(fd[0]);
	close(fd[1]);
384
	finish_connect(pid);
385
	return ret;
386
}