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

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

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

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

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

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

	args[i++] = "git-rev-list";	/* 0 */
	args[i++] = "--objects";	/* 1 */
	while (refs) {
		char *buf = malloc(100);
		if (i > 900)
			die("git-rev-list environment overflow");
48 49
		if (!is_zero_sha1(refs->old_sha1) &&
		    has_sha1_file(refs->old_sha1)) {
50 51 52 53 54 55 56 57
			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));
		}
58 59 60 61 62 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
		refs = refs->next;
	}
	args[i] = NULL;
	execvp("git-rev-list", args);
	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 已提交
106
	return 0;
107
}
108

J
Junio C Hamano 已提交
109 110 111 112 113 114 115 116 117 118
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);
	}
}

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

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

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

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

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

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

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

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

179 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
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 已提交
210
static int send_pack(int in, int out, int nr_refspec, char **refspec)
211
{
212
	struct ref *ref;
213
	int new_refs;
214
	int ret = 0;
215 216
	int ask_for_status_report = 0;
	int expect_status_report = 0;
217

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

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

J
Junio C Hamano 已提交
226 227 228 229 230 231
	/* 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 已提交
232 233 234 235 236 237

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

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

		/* This part determines what can overwrite what.
		 * The rules are:
		 *
255 256
		 * (0) you can always use --force or +A:B notation to
		 *     selectively force individual ref pairs.
257 258 259 260 261 262 263 264 265 266 267
		 *
		 * (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.
		 */

268 269 270
		if (!force_update &&
		    !is_zero_sha1(ref->old_sha1) &&
		    !ref->force) {
271 272
			if (!has_sha1_file(ref->old_sha1) ||
			    !ref_newer(ref->peer_ref->new_sha1,
J
Junio C Hamano 已提交
273
				       ref->old_sha1)) {
274 275 276 277 278 279 280 281 282 283 284 285
				/* 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 已提交
286
				      ref->peer_ref->name);
287
				ret = -2;
J
Junio C Hamano 已提交
288 289
				continue;
			}
290
		}
J
Junio C Hamano 已提交
291 292 293
		memcpy(ref->new_sha1, ref->peer_ref->new_sha1, 20);
		if (is_zero_sha1(ref->new_sha1)) {
			error("cannot happen anymore");
294
			ret = -3;
295 296 297
			continue;
		}
		new_refs++;
298 299
		strcpy(old_hex, sha1_to_hex(ref->old_sha1));
		new_hex = sha1_to_hex(ref->new_sha1);
300 301 302 303 304 305 306 307 308 309 310

		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 已提交
311 312 313 314
		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);
315
	}
J
Junio C Hamano 已提交
316

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

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

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

J
Junio C Hamano 已提交
332

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

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

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