]>
Commit | Line | Data |
---|---|---|
def88e9a LT |
1 | #include "cache.h" |
2 | #include "refs.h" | |
3 | #include "pkt-line.h" | |
4 | ||
5 | static const char upload_pack_usage[] = "git-upload-pack <dir>"; | |
6 | ||
fb9040cc LT |
7 | #define MAX_HAS (16) |
8 | #define MAX_NEEDS (16) | |
9 | static int nr_has = 0, nr_needs = 0; | |
10 | static unsigned char has_sha1[MAX_HAS][20]; | |
11 | static unsigned char needs_sha1[MAX_NEEDS][20]; | |
12 | ||
13 | static void create_pack_file(void) | |
14 | { | |
15 | /* | |
16 | * Here, we should do | |
17 | * | |
18 | * git-rev-list --objects needs_sha1 --not has_sha1 | | |
19 | * git-pack-objects --stdout | |
20 | * | |
21 | * but we don't. | |
22 | */ | |
23 | } | |
24 | ||
def88e9a LT |
25 | static int got_sha1(char *hex, unsigned char *sha1) |
26 | { | |
fb9040cc | 27 | int nr; |
def88e9a LT |
28 | if (get_sha1_hex(hex, sha1)) |
29 | die("git-upload-pack: expected SHA1 object, got '%s'", hex); | |
fb9040cc LT |
30 | if (!has_sha1_file(sha1)) |
31 | return 0; | |
32 | nr = nr_has; | |
33 | if (nr < MAX_HAS) { | |
34 | memcpy(has_sha1[nr], sha1, 20); | |
35 | nr_has = nr+1; | |
36 | } | |
37 | return 1; | |
def88e9a LT |
38 | } |
39 | ||
40 | static int get_common_commits(void) | |
41 | { | |
42 | static char line[1000]; | |
43 | unsigned char sha1[20]; | |
44 | int len; | |
45 | ||
46 | for(;;) { | |
47 | len = packet_read_line(0, line, sizeof(line)); | |
48 | ||
49 | if (!len) { | |
50 | packet_write(1, "NAK\n"); | |
51 | continue; | |
52 | } | |
53 | if (line[len-1] == '\n') | |
54 | line[--len] = 0; | |
55 | if (!strncmp(line, "have ", 5)) { | |
56 | if (got_sha1(line+5, sha1)) { | |
57 | packet_write(1, "ACK %s\n", sha1_to_hex(sha1)); | |
58 | break; | |
59 | } | |
60 | continue; | |
61 | } | |
62 | if (!strcmp(line, "done")) { | |
63 | packet_write(1, "NAK\n"); | |
64 | return -1; | |
65 | } | |
66 | die("git-upload-pack: expected SHA1 list, got '%s'", line); | |
67 | } | |
68 | ||
69 | for (;;) { | |
70 | len = packet_read_line(0, line, sizeof(line)); | |
71 | if (!len) | |
72 | break; | |
73 | if (!strncmp(line, "have ", 5)) { | |
74 | got_sha1(line+5, sha1); | |
75 | continue; | |
76 | } | |
77 | if (!strcmp(line, "done")) | |
78 | break; | |
79 | die("git-upload-pack: expected SHA1 list, got '%s'", line); | |
80 | } | |
81 | return 0; | |
82 | } | |
83 | ||
fb9040cc LT |
84 | static int receive_needs(void) |
85 | { | |
86 | static char line[1000]; | |
87 | int len, needs; | |
88 | ||
89 | needs = 0; | |
90 | for (;;) { | |
91 | len = packet_read_line(0, line, sizeof(line)); | |
92 | if (!len) | |
93 | return needs; | |
94 | ||
95 | /* | |
96 | * This is purely theoretical right now: git-fetch-pack only | |
97 | * ever asks for a single HEAD | |
98 | */ | |
99 | if (needs >= MAX_NEEDS) | |
100 | die("I'm only doing a max of %d requests", MAX_NEEDS); | |
101 | if (strncmp("want ", line, 5) || get_sha1_hex(line+5, needs_sha1[needs])) | |
102 | die("git-upload-pack: protocol error, expected to get sha, not '%s'", line); | |
103 | needs++; | |
104 | } | |
105 | } | |
106 | ||
def88e9a LT |
107 | static int send_ref(const char *refname, const unsigned char *sha1) |
108 | { | |
109 | packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname); | |
110 | return 0; | |
111 | } | |
112 | ||
113 | static int upload_pack(void) | |
114 | { | |
115 | for_each_ref(send_ref); | |
116 | packet_flush(1); | |
fb9040cc LT |
117 | nr_needs = receive_needs(); |
118 | if (!nr_needs) | |
119 | return 0; | |
def88e9a | 120 | get_common_commits(); |
fb9040cc | 121 | create_pack_file(); |
def88e9a LT |
122 | return 0; |
123 | } | |
124 | ||
125 | int main(int argc, char **argv) | |
126 | { | |
127 | const char *dir; | |
128 | if (argc != 2) | |
129 | usage(upload_pack_usage); | |
130 | dir = argv[1]; | |
131 | if (chdir(dir)) | |
132 | die("git-upload-pack unable to chdir to %s", dir); | |
133 | chdir(".git"); | |
134 | if (access("objects", X_OK) || access("refs", X_OK)) | |
135 | die("git-upload-pack: %s doesn't seem to be a git archive", dir); | |
136 | setenv("GIT_DIR", ".", 1); | |
137 | upload_pack(); | |
138 | return 0; | |
139 | } |