summaryrefslogtreecommitdiff
path: root/builtin-upload-tar.c
blob: 06a945a4b16b1b604847527fbac3aca3c7fa3a73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
 * Copyright (c) 2006 Junio C Hamano
 */
#include "cache.h"
#include "pkt-line.h"
#include "exec_cmd.h"
#include "builtin.h"

static const char upload_tar_usage[] = "git-upload-tar <repo>";

static int nak(const char *reason)
{
	packet_write(1, "NACK %s\n", reason);
	packet_flush(1);
	return 1;
}

int cmd_upload_tar(int argc, const char **argv, const char *prefix)
{
	int len;
	const char *dir = argv[1];
	char buf[8192];
	unsigned char sha1[20];
	char *base = NULL;
	char hex[41];
	int ac;
	const char *av[4];

	if (argc != 2)
		usage(upload_tar_usage);
	if (strlen(dir) < sizeof(buf)-1)
		strcpy(buf, dir); /* enter-repo smudges its argument */
	else
		packet_write(1, "NACK insanely long repository name %s\n", dir);
	if (!enter_repo(buf, 0)) {
		packet_write(1, "NACK not a git archive %s\n", dir);
		packet_flush(1);
		return 1;
	}

	len = packet_read_line(0, buf, sizeof(buf));
	if (len < 5 || strncmp("want ", buf, 5))
		return nak("expected want");
	if (buf[len-1] == '\n')
		buf[--len] = 0;
	if (get_sha1(buf + 5, sha1))
		return nak("expected sha1");
        strcpy(hex, sha1_to_hex(sha1));

	len = packet_read_line(0, buf, sizeof(buf));
	if (len) {
		if (len < 5 || strncmp("base ", buf, 5))
			return nak("expected (optional) base");
		if (buf[len-1] == '\n')
			buf[--len] = 0;
		base = xstrdup(buf + 5);
		len = packet_read_line(0, buf, sizeof(buf));
	}
	if (len)
		return nak("expected flush");

	packet_write(1, "ACK\n");
	packet_flush(1);

	ac = 0;
	av[ac++] = "tar-tree";
	av[ac++] = hex;
	if (base)
		av[ac++] = base;
	av[ac++] = NULL;
	execv_git_cmd(av);
	/* should it return that is an error */
	return 1;
}