]> git.ipfire.org Git - thirdparty/git.git/blob - clone-pack.c
Merge branch 'fixes'
[thirdparty/git.git] / clone-pack.c
1 #include "cache.h"
2 #include "refs.h"
3 #include "pkt-line.h"
4 #include <sys/wait.h>
5
6 static int quiet;
7 static int keep_pack;
8 static const char clone_pack_usage[] =
9 "git-clone-pack [-q] [--keep] [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
10 static const char *exec = "git-upload-pack";
11
12 static void clone_handshake(int fd[2], struct ref *ref)
13 {
14 unsigned char sha1[20];
15
16 while (ref) {
17 packet_write(fd[1], "want %s\n", sha1_to_hex(ref->old_sha1));
18 ref = ref->next;
19 }
20 packet_flush(fd[1]);
21
22 /* We don't have nuttin' */
23 packet_write(fd[1], "done\n");
24 if (get_ack(fd[0], sha1))
25 error("Huh! git-clone-pack got positive ack for %s", sha1_to_hex(sha1));
26 }
27
28 static int is_master(struct ref *ref)
29 {
30 return !strcmp(ref->name, "refs/heads/master");
31 }
32
33 static void write_one_ref(struct ref *ref)
34 {
35 char *path = git_path("%s", ref->name);
36 int fd;
37 char *hex;
38
39 if (safe_create_leading_directories(path))
40 die("unable to create leading directory for %s", ref->name);
41 fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0666);
42 if (fd < 0)
43 die("unable to create ref %s", ref->name);
44 hex = sha1_to_hex(ref->old_sha1);
45 hex[40] = '\n';
46 if (write(fd, hex, 41) != 41)
47 die("unable to write ref %s", ref->name);
48 close(fd);
49 }
50
51 static void write_refs(struct ref *ref)
52 {
53 struct ref *head = NULL, *head_ptr, *master_ref;
54 char *head_path;
55
56 /* Upload-pack must report HEAD first */
57 if (!strcmp(ref->name, "HEAD")) {
58 head = ref;
59 ref = ref->next;
60 }
61 head_ptr = NULL;
62 master_ref = NULL;
63 while (ref) {
64 if (is_master(ref))
65 master_ref = ref;
66 if (head &&
67 !memcmp(ref->old_sha1, head->old_sha1, 20) &&
68 !strncmp(ref->name, "refs/heads/",11) &&
69 (!head_ptr || ref == master_ref))
70 head_ptr = ref;
71
72 write_one_ref(ref);
73 ref = ref->next;
74 }
75 if (!head) {
76 fprintf(stderr, "No HEAD in remote.\n");
77 return;
78 }
79
80 head_path = strdup(git_path("HEAD"));
81 if (!head_ptr) {
82 /*
83 * If we had a master ref, and it wasn't HEAD, we need to undo the
84 * symlink, and write a standalone HEAD. Give a warning, because that's
85 * really really wrong.
86 */
87 if (master_ref) {
88 error("HEAD doesn't point to any refs! Making standalone HEAD");
89 unlink(head_path);
90 }
91 write_one_ref(head);
92 free(head_path);
93 return;
94 }
95
96 /* We reset to the master branch if it's available */
97 if (master_ref)
98 return;
99
100 fprintf(stderr, "Setting HEAD to %s\n", head_ptr->name);
101
102 /*
103 * Uhhuh. Other end didn't have master. We start HEAD off with
104 * the first branch with the same value.
105 */
106 if (create_symref(head_path, head_ptr->name) < 0)
107 die("unable to link HEAD to %s", head_ptr->name);
108 free(head_path);
109 }
110
111 static int clone_by_unpack(int fd[2])
112 {
113 int status;
114 pid_t pid;
115
116 pid = fork();
117 if (pid < 0)
118 die("git-clone-pack: unable to fork off git-unpack-objects");
119 if (!pid) {
120 dup2(fd[0], 0);
121 close(fd[0]);
122 close(fd[1]);
123 execlp("git-unpack-objects", "git-unpack-objects",
124 quiet ? "-q" : NULL, NULL);
125 die("git-unpack-objects exec failed");
126 }
127 close(fd[0]);
128 close(fd[1]);
129 while (waitpid(pid, &status, 0) < 0) {
130 if (errno != EINTR)
131 die("waiting for git-unpack-objects: %s", strerror(errno));
132 }
133 if (WIFEXITED(status)) {
134 int code = WEXITSTATUS(status);
135 if (code)
136 die("git-unpack-objects died with error code %d", code);
137 return 0;
138 }
139 if (WIFSIGNALED(status)) {
140 int sig = WTERMSIG(status);
141 die("git-unpack-objects died of signal %d", sig);
142 }
143 die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
144 }
145
146 static int finish_pack(const char *pack_tmp_name)
147 {
148 int pipe_fd[2];
149 pid_t pid;
150 char idx[PATH_MAX];
151 char final[PATH_MAX];
152 char hash[41];
153 unsigned char sha1[20];
154 char *cp;
155 int err = 0;
156
157 if (pipe(pipe_fd) < 0)
158 die("git-clone-pack: unable to set up pipe");
159
160 strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */
161 cp = strrchr(idx, '/');
162 memcpy(cp, "/pidx", 5);
163
164 pid = fork();
165 if (pid < 0)
166 die("git-clone-pack: unable to fork off git-index-pack");
167 if (!pid) {
168 close(0);
169 dup2(pipe_fd[1], 1);
170 close(pipe_fd[0]);
171 close(pipe_fd[1]);
172 execlp("git-index-pack","git-index-pack",
173 "-o", idx, pack_tmp_name, NULL);
174 error("cannot exec git-index-pack <%s> <%s>",
175 idx, pack_tmp_name);
176 exit(1);
177 }
178 close(pipe_fd[1]);
179 if (read(pipe_fd[0], hash, 40) != 40) {
180 error("git-clone-pack: unable to read from git-index-pack");
181 err = 1;
182 }
183 close(pipe_fd[0]);
184
185 for (;;) {
186 int status, code;
187 int retval = waitpid(pid, &status, 0);
188
189 if (retval < 0) {
190 if (errno == EINTR)
191 continue;
192 error("waitpid failed (%s)", strerror(retval));
193 goto error_die;
194 }
195 if (WIFSIGNALED(status)) {
196 int sig = WTERMSIG(status);
197 error("git-index-pack died of signal %d", sig);
198 goto error_die;
199 }
200 if (!WIFEXITED(status)) {
201 error("git-index-pack died of unnatural causes %d",
202 status);
203 goto error_die;
204 }
205 code = WEXITSTATUS(status);
206 if (code) {
207 error("git-index-pack died with error code %d", code);
208 goto error_die;
209 }
210 if (err)
211 goto error_die;
212 break;
213 }
214 hash[40] = 0;
215 if (get_sha1_hex(hash, sha1)) {
216 error("git-index-pack reported nonsense '%s'", hash);
217 goto error_die;
218 }
219 /* Now we have pack in pack_tmp_name[], and
220 * idx in idx[]; rename them to their final names.
221 */
222 snprintf(final, sizeof(final),
223 "%s/pack/pack-%s.pack", get_object_directory(), hash);
224 move_temp_to_file(pack_tmp_name, final);
225 chmod(final, 0444);
226 snprintf(final, sizeof(final),
227 "%s/pack/pack-%s.idx", get_object_directory(), hash);
228 move_temp_to_file(idx, final);
229 chmod(final, 0444);
230 return 0;
231
232 error_die:
233 unlink(idx);
234 unlink(pack_tmp_name);
235 exit(1);
236 }
237
238 static int clone_without_unpack(int fd[2])
239 {
240 char tmpfile[PATH_MAX];
241 int ofd, ifd;
242
243 ifd = fd[0];
244 snprintf(tmpfile, sizeof(tmpfile),
245 "%s/pack-XXXXXX", get_object_directory());
246 ofd = mkstemp(tmpfile);
247 if (ofd < 0)
248 return error("unable to create temporary file %s", tmpfile);
249
250 while (1) {
251 char buf[8192];
252 ssize_t sz, wsz, pos;
253 sz = read(ifd, buf, sizeof(buf));
254 if (sz == 0)
255 break;
256 if (sz < 0) {
257 error("error reading pack (%s)", strerror(errno));
258 close(ofd);
259 unlink(tmpfile);
260 return -1;
261 }
262 pos = 0;
263 while (pos < sz) {
264 wsz = write(ofd, buf + pos, sz - pos);
265 if (wsz < 0) {
266 error("error writing pack (%s)",
267 strerror(errno));
268 close(ofd);
269 unlink(tmpfile);
270 return -1;
271 }
272 pos += wsz;
273 }
274 }
275 close(ofd);
276 return finish_pack(tmpfile);
277 }
278
279 static int clone_pack(int fd[2], int nr_match, char **match)
280 {
281 struct ref *refs;
282 int status;
283
284 get_remote_heads(fd[0], &refs, nr_match, match);
285 if (!refs) {
286 packet_flush(fd[1]);
287 die("no matching remote head");
288 }
289 clone_handshake(fd, refs);
290
291 if (keep_pack)
292 status = clone_without_unpack(fd);
293 else
294 status = clone_by_unpack(fd);
295
296 if (!status)
297 write_refs(refs);
298 return status;
299 }
300
301 static int clone_options(const char *var, const char *value)
302 {
303 if (!strcmp("clone.keeppack", var)) {
304 keep_pack = git_config_bool(var, value);
305 return 0;
306 }
307 if (!strcmp("clone.quiet", var)) {
308 quiet = git_config_bool(var, value);
309 return 0;
310 }
311 /*
312 * Put other local option parsing for this program
313 * here ...
314 */
315
316 /* Fall back on the default ones */
317 return git_default_config(var, value);
318 }
319
320 int main(int argc, char **argv)
321 {
322 int i, ret, nr_heads;
323 char *dest = NULL, **heads;
324 int fd[2];
325 pid_t pid;
326
327 git_config(clone_options);
328 nr_heads = 0;
329 heads = NULL;
330 for (i = 1; i < argc; i++) {
331 char *arg = argv[i];
332
333 if (*arg == '-') {
334 if (!strcmp("-q", arg)) {
335 quiet = 1;
336 continue;
337 }
338 if (!strncmp("--exec=", arg, 7)) {
339 exec = arg + 7;
340 continue;
341 }
342 if (!strcmp("--keep", arg)) {
343 keep_pack = 1;
344 continue;
345 }
346 usage(clone_pack_usage);
347 }
348 dest = arg;
349 heads = argv + i + 1;
350 nr_heads = argc - i - 1;
351 break;
352 }
353 if (!dest)
354 usage(clone_pack_usage);
355 pid = git_connect(fd, dest, exec);
356 if (pid < 0)
357 return 1;
358 ret = clone_pack(fd, nr_heads, heads);
359 close(fd[0]);
360 close(fd[1]);
361 finish_connect(pid);
362 return ret;
363 }