send-pack: move core code to libgit.a

send_pack() is used by transport.c, part of libgit.a while it stays in builtin/send-pack.c. Move it to send-pack.c so that we won't get undefined reference if a program that uses libgit.a happens to pull it in. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Jeff King <peff@peff.net>

Nguyễn Thái Ngọc Duy committed Oct 26, 2012 at 22:53 UTC f5d942e1ede7ce5e74537d3021df9fdc179a8377
4 files changed +350 -333
Makefile
+1
@@ -798,6 +798,7 @@ LIB_OBJS += rerere.o
798 LIB_OBJS += resolve-undo.o
799 LIB_OBJS += revision.o
800 LIB_OBJS += run-command.o
801 +LIB_OBJS += send-pack.o
802 LIB_OBJS += sequencer.o
803 LIB_OBJS += server-info.o
804 LIB_OBJS += setup.o
builtin/send-pack.c
-333
@@ -16,164 +16,6 @@ static const char send_pack_usage[] =
16
17 static struct send_pack_args args;
18
19 -static int feed_object(const unsigned char *sha1, int fd, int negative)
20 -{
21 - char buf[42];
22 -
23 - if (negative && !has_sha1_file(sha1))
24 - return 1;
25 -
26 - memcpy(buf + negative, sha1_to_hex(sha1), 40);
27 - if (negative)
28 - buf[0] = '^';
29 - buf[40 + negative] = '\n';
30 - return write_or_whine(fd, buf, 41 + negative, "send-pack: send refs");
31 -}
32 -
33 -/*
34 - * Make a pack stream and spit it out into file descriptor fd
35 - */
36 -static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra, struct send_pack_args *args)
37 -{
38 - /*
39 - * The child becomes pack-objects --revs; we feed
40 - * the revision parameters to it via its stdin and
41 - * let its stdout go back to the other end.
42 - */
43 - const char *argv[] = {
44 - "pack-objects",
45 - "--all-progress-implied",
46 - "--revs",
47 - "--stdout",
48 - NULL,
49 - NULL,
50 - NULL,
51 - NULL,
52 - NULL,
53 - };
54 - struct child_process po;
55 - int i;
56 -
57 - i = 4;
58 - if (args->use_thin_pack)
59 - argv[i++] = "--thin";
60 - if (args->use_ofs_delta)
61 - argv[i++] = "--delta-base-offset";
62 - if (args->quiet || !args->progress)
63 - argv[i++] = "-q";
64 - if (args->progress)
65 - argv[i++] = "--progress";
66 - memset(&po, 0, sizeof(po));
67 - po.argv = argv;
68 - po.in = -1;
69 - po.out = args->stateless_rpc ? -1 : fd;
70 - po.git_cmd = 1;
71 - if (start_command(&po))
72 - die_errno("git pack-objects failed");
73 -
74 - /*
75 - * We feed the pack-objects we just spawned with revision
76 - * parameters by writing to the pipe.
77 - */
78 - for (i = 0; i < extra->nr; i++)
79 - if (!feed_object(extra->array[i], po.in, 1))
80 - break;
81 -
82 - while (refs) {
83 - if (!is_null_sha1(refs->old_sha1) &&
84 - !feed_object(refs->old_sha1, po.in, 1))
85 - break;
86 - if (!is_null_sha1(refs->new_sha1) &&
87 - !feed_object(refs->new_sha1, po.in, 0))
88 - break;
89 - refs = refs->next;
90 - }
91 -
92 - close(po.in);
93 -
94 - if (args->stateless_rpc) {
95 - char *buf = xmalloc(LARGE_PACKET_MAX);
96 - while (1) {
97 - ssize_t n = xread(po.out, buf, LARGE_PACKET_MAX);
98 - if (n <= 0)
99 - break;
100 - send_sideband(fd, -1, buf, n, LARGE_PACKET_MAX);
101 - }
102 - free(buf);
103 - close(po.out);
104 - po.out = -1;
105 - }
106 -
107 - if (finish_command(&po))
108 - return -1;
109 - return 0;
110 -}
111 -
112 -static int receive_status(int in, struct ref *refs)
113 -{
114 - struct ref *hint;
115 - char line[1000];
116 - int ret = 0;
117 - int len = packet_read_line(in, line, sizeof(line));
118 - if (len < 10 || memcmp(line, "unpack ", 7))
119 - return error("did not receive remote status");
120 - if (memcmp(line, "unpack ok\n", 10)) {
121 - char *p = line + strlen(line) - 1;
122 - if (*p == '\n')
123 - *p = '\0';
124 - error("unpack failed: %s", line + 7);
125 - ret = -1;
126 - }
127 - hint = NULL;
128 - while (1) {
129 - char *refname;
130 - char *msg;
131 - len = packet_read_line(in, line, sizeof(line));
132 - if (!len)
133 - break;
134 - if (len < 3 ||
135 - (memcmp(line, "ok ", 3) && memcmp(line, "ng ", 3))) {
136 - fprintf(stderr, "protocol error: %s\n", line);
137 - ret = -1;
138 - break;
139 - }
140 -
141 - line[strlen(line)-1] = '\0';
142 - refname = line + 3;
143 - msg = strchr(refname, ' ');
144 - if (msg)
145 - *msg++ = '\0';
146 -
147 - /* first try searching at our hint, falling back to all refs */
148 - if (hint)
149 - hint = find_ref_by_name(hint, refname);
150 - if (!hint)
151 - hint = find_ref_by_name(refs, refname);
152 - if (!hint) {
153 - warning("remote reported status on unknown ref: %s",
154 - refname);
155 - continue;
156 - }
157 - if (hint->status != REF_STATUS_EXPECTING_REPORT) {
158 - warning("remote reported status on unexpected ref: %s",
159 - refname);
160 - continue;
161 - }
162 -
163 - if (line[0] == 'o' && line[1] == 'k')
164 - hint->status = REF_STATUS_OK;
165 - else {
166 - hint->status = REF_STATUS_REMOTE_REJECT;
167 - ret = -1;
168 - }
169 - if (msg)
170 - hint->remote_status = xstrdup(msg);
171 - /* start our next search from the next ref */
172 - hint = hint->next;
173 - }
174 - return ret;
175 -}
176 -
19 static void print_helper_status(struct ref *ref)
20 {
21 struct strbuf buf = STRBUF_INIT;
@@ -227,181 +69,6 @@ static void print_helper_status(struct ref *ref)
69 strbuf_release(&buf);
70 }
71
230 -static int sideband_demux(int in, int out, void *data)
231 -{
232 - int *fd = data, ret;
233 -#ifdef NO_PTHREADS
234 - close(fd[1]);
235 -#endif
236 - ret = recv_sideband("send-pack", fd[0], out);
237 - close(out);
238 - return ret;
239 -}
240 -
241 -int send_pack(struct send_pack_args *args,
242 - int fd[], struct child_process *conn,
243 - struct ref *remote_refs,
244 - struct extra_have_objects *extra_have)
245 -{
246 - int in = fd[0];
247 - int out = fd[1];
248 - struct strbuf req_buf = STRBUF_INIT;
249 - struct ref *ref;
250 - int new_refs;
251 - int allow_deleting_refs = 0;
252 - int status_report = 0;
253 - int use_sideband = 0;
254 - int quiet_supported = 0;
255 - int agent_supported = 0;
256 - unsigned cmds_sent = 0;
257 - int ret;
258 - struct async demux;
259 -
260 - /* Does the other end support the reporting? */
261 - if (server_supports("report-status"))
262 - status_report = 1;
263 - if (server_supports("delete-refs"))
264 - allow_deleting_refs = 1;
265 - if (server_supports("ofs-delta"))
266 - args->use_ofs_delta = 1;
267 - if (server_supports("side-band-64k"))
268 - use_sideband = 1;
269 - if (server_supports("quiet"))
270 - quiet_supported = 1;
271 - if (server_supports("agent"))
272 - agent_supported = 1;
273 -
274 - if (!remote_refs) {
275 - fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
276 - "Perhaps you should specify a branch such as 'master'.\n");
277 - return 0;
278 - }
279 -
280 - /*
281 - * Finally, tell the other end!
282 - */
283 - new_refs = 0;
284 - for (ref = remote_refs; ref; ref = ref->next) {
285 - if (!ref->peer_ref && !args->send_mirror)
286 - continue;
287 -
288 - /* Check for statuses set by set_ref_status_for_push() */
289 - switch (ref->status) {
290 - case REF_STATUS_REJECT_NONFASTFORWARD:
291 - case REF_STATUS_UPTODATE:
292 - continue;
293 - default:
294 - ; /* do nothing */
295 - }
296 -
297 - if (ref->deletion && !allow_deleting_refs) {
298 - ref->status = REF_STATUS_REJECT_NODELETE;
299 - continue;
300 - }
301 -
302 - if (!ref->deletion)
303 - new_refs++;
304 -
305 - if (args->dry_run) {
306 - ref->status = REF_STATUS_OK;
307 - } else {
308 - char *old_hex = sha1_to_hex(ref->old_sha1);
309 - char *new_hex = sha1_to_hex(ref->new_sha1);
310 - int quiet = quiet_supported && (args->quiet || !args->progress);
311 -
312 - if (!cmds_sent && (status_report || use_sideband ||
313 - quiet || agent_supported)) {
314 - packet_buf_write(&req_buf,
315 - "%s %s %s%c%s%s%s%s%s",
316 - old_hex, new_hex, ref->name, 0,
317 - status_report ? " report-status" : "",
318 - use_sideband ? " side-band-64k" : "",
319 - quiet ? " quiet" : "",
320 - agent_supported ? " agent=" : "",
321 - agent_supported ? git_user_agent_sanitized() : ""
322 - );
323 - }
324 - else
325 - packet_buf_write(&req_buf, "%s %s %s",
326 - old_hex, new_hex, ref->name);
327 - ref->status = status_report ?
328 - REF_STATUS_EXPECTING_REPORT :
329 - REF_STATUS_OK;
330 - cmds_sent++;
331 - }
332 - }
333 -
334 - if (args->stateless_rpc) {
335 - if (!args->dry_run && cmds_sent) {
336 - packet_buf_flush(&req_buf);
337 - send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX);
338 - }
339 - } else {
340 - safe_write(out, req_buf.buf, req_buf.len);
341 - packet_flush(out);
342 - }
343 - strbuf_release(&req_buf);
344 -
345 - if (use_sideband && cmds_sent) {
346 - memset(&demux, 0, sizeof(demux));
347 - demux.proc = sideband_demux;
348 - demux.data = fd;
349 - demux.out = -1;
350 - if (start_async(&demux))
351 - die("send-pack: unable to fork off sideband demultiplexer");
352 - in = demux.out;
353 - }
354 -
355 - if (new_refs && cmds_sent) {
356 - if (pack_objects(out, remote_refs, extra_have, args) < 0) {
357 - for (ref = remote_refs; ref; ref = ref->next)
358 - ref->status = REF_STATUS_NONE;
359 - if (args->stateless_rpc)
360 - close(out);
361 - if (git_connection_is_socket(conn))
362 - shutdown(fd[0], SHUT_WR);
363 - if (use_sideband)
364 - finish_async(&demux);
365 - return -1;
366 - }
367 - }
368 - if (args->stateless_rpc && cmds_sent)
369 - packet_flush(out);
370 -
371 - if (status_report && cmds_sent)
372 - ret = receive_status(in, remote_refs);
373 - else
374 - ret = 0;
375 - if (args->stateless_rpc)
376 - packet_flush(out);
377 -
378 - if (use_sideband && cmds_sent) {
379 - if (finish_async(&demux)) {
380 - error("error in sideband demultiplexer");
381 - ret = -1;
382 - }
383 - close(demux.out);
384 - }
385 -
386 - if (ret < 0)
387 - return ret;
388 -
389 - if (args->porcelain)
390 - return 0;
391 -
392 - for (ref = remote_refs; ref; ref = ref->next) {
393 - switch (ref->status) {
394 - case REF_STATUS_NONE:
395 - case REF_STATUS_UPTODATE:
396 - case REF_STATUS_OK:
397 - break;
398 - default:
399 - return -1;
400 - }
401 - }
402 - return 0;
403 -}
404 -
72 int cmd_send_pack(int argc, const char **argv, const char *prefix)
73 {
74 int i, nr_refspecs = 0;
send-pack.c new
+344
@@ -0,0 +1,344 @@
1 +#include "builtin.h"
2 +#include "commit.h"
3 +#include "refs.h"
4 +#include "pkt-line.h"
5 +#include "sideband.h"
6 +#include "run-command.h"
7 +#include "remote.h"
8 +#include "send-pack.h"
9 +#include "quote.h"
10 +#include "transport.h"
11 +#include "version.h"
12 +
13 +static int feed_object(const unsigned char *sha1, int fd, int negative)
14 +{
15 + char buf[42];
16 +
17 + if (negative && !has_sha1_file(sha1))
18 + return 1;
19 +
20 + memcpy(buf + negative, sha1_to_hex(sha1), 40);
21 + if (negative)
22 + buf[0] = '^';
23 + buf[40 + negative] = '\n';
24 + return write_or_whine(fd, buf, 41 + negative, "send-pack: send refs");
25 +}
26 +
27 +/*
28 + * Make a pack stream and spit it out into file descriptor fd
29 + */
30 +static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra, struct send_pack_args *args)
31 +{
32 + /*
33 + * The child becomes pack-objects --revs; we feed
34 + * the revision parameters to it via its stdin and
35 + * let its stdout go back to the other end.
36 + */
37 + const char *argv[] = {
38 + "pack-objects",
39 + "--all-progress-implied",
40 + "--revs",
41 + "--stdout",
42 + NULL,
43 + NULL,
44 + NULL,
45 + NULL,
46 + NULL,
47 + };
48 + struct child_process po;
49 + int i;
50 +
51 + i = 4;
52 + if (args->use_thin_pack)
53 + argv[i++] = "--thin";
54 + if (args->use_ofs_delta)
55 + argv[i++] = "--delta-base-offset";
56 + if (args->quiet || !args->progress)
57 + argv[i++] = "-q";
58 + if (args->progress)
59 + argv[i++] = "--progress";
60 + memset(&po, 0, sizeof(po));
61 + po.argv = argv;
62 + po.in = -1;
63 + po.out = args->stateless_rpc ? -1 : fd;
64 + po.git_cmd = 1;
65 + if (start_command(&po))
66 + die_errno("git pack-objects failed");
67 +
68 + /*
69 + * We feed the pack-objects we just spawned with revision
70 + * parameters by writing to the pipe.
71 + */
72 + for (i = 0; i < extra->nr; i++)
73 + if (!feed_object(extra->array[i], po.in, 1))
74 + break;
75 +
76 + while (refs) {
77 + if (!is_null_sha1(refs->old_sha1) &&
78 + !feed_object(refs->old_sha1, po.in, 1))
79 + break;
80 + if (!is_null_sha1(refs->new_sha1) &&
81 + !feed_object(refs->new_sha1, po.in, 0))
82 + break;
83 + refs = refs->next;
84 + }
85 +
86 + close(po.in);
87 +
88 + if (args->stateless_rpc) {
89 + char *buf = xmalloc(LARGE_PACKET_MAX);
90 + while (1) {
91 + ssize_t n = xread(po.out, buf, LARGE_PACKET_MAX);
92 + if (n <= 0)
93 + break;
94 + send_sideband(fd, -1, buf, n, LARGE_PACKET_MAX);
95 + }
96 + free(buf);
97 + close(po.out);
98 + po.out = -1;
99 + }
100 +
101 + if (finish_command(&po))
102 + return -1;
103 + return 0;
104 +}
105 +
106 +static int receive_status(int in, struct ref *refs)
107 +{
108 + struct ref *hint;
109 + char line[1000];
110 + int ret = 0;
111 + int len = packet_read_line(in, line, sizeof(line));
112 + if (len < 10 || memcmp(line, "unpack ", 7))
113 + return error("did not receive remote status");
114 + if (memcmp(line, "unpack ok\n", 10)) {
115 + char *p = line + strlen(line) - 1;
116 + if (*p == '\n')
117 + *p = '\0';
118 + error("unpack failed: %s", line + 7);
119 + ret = -1;
120 + }
121 + hint = NULL;
122 + while (1) {
123 + char *refname;
124 + char *msg;
125 + len = packet_read_line(in, line, sizeof(line));
126 + if (!len)
127 + break;
128 + if (len < 3 ||
129 + (memcmp(line, "ok ", 3) && memcmp(line, "ng ", 3))) {
130 + fprintf(stderr, "protocol error: %s\n", line);
131 + ret = -1;
132 + break;
133 + }
134 +
135 + line[strlen(line)-1] = '\0';
136 + refname = line + 3;
137 + msg = strchr(refname, ' ');
138 + if (msg)
139 + *msg++ = '\0';
140 +
141 + /* first try searching at our hint, falling back to all refs */
142 + if (hint)
143 + hint = find_ref_by_name(hint, refname);
144 + if (!hint)
145 + hint = find_ref_by_name(refs, refname);
146 + if (!hint) {
147 + warning("remote reported status on unknown ref: %s",
148 + refname);
149 + continue;
150 + }
151 + if (hint->status != REF_STATUS_EXPECTING_REPORT) {
152 + warning("remote reported status on unexpected ref: %s",
153 + refname);
154 + continue;
155 + }
156 +
157 + if (line[0] == 'o' && line[1] == 'k')
158 + hint->status = REF_STATUS_OK;
159 + else {
160 + hint->status = REF_STATUS_REMOTE_REJECT;
161 + ret = -1;
162 + }
163 + if (msg)
164 + hint->remote_status = xstrdup(msg);
165 + /* start our next search from the next ref */
166 + hint = hint->next;
167 + }
168 + return ret;
169 +}
170 +
171 +static int sideband_demux(int in, int out, void *data)
172 +{
173 + int *fd = data, ret;
174 +#ifdef NO_PTHREADS
175 + close(fd[1]);
176 +#endif
177 + ret = recv_sideband("send-pack", fd[0], out);
178 + close(out);
179 + return ret;
180 +}
181 +
182 +int send_pack(struct send_pack_args *args,
183 + int fd[], struct child_process *conn,
184 + struct ref *remote_refs,
185 + struct extra_have_objects *extra_have)
186 +{
187 + int in = fd[0];
188 + int out = fd[1];
189 + struct strbuf req_buf = STRBUF_INIT;
190 + struct ref *ref;
191 + int new_refs;
192 + int allow_deleting_refs = 0;
193 + int status_report = 0;
194 + int use_sideband = 0;
195 + int quiet_supported = 0;
196 + int agent_supported = 0;
197 + unsigned cmds_sent = 0;
198 + int ret;
199 + struct async demux;
200 +
201 + /* Does the other end support the reporting? */
202 + if (server_supports("report-status"))
203 + status_report = 1;
204 + if (server_supports("delete-refs"))
205 + allow_deleting_refs = 1;
206 + if (server_supports("ofs-delta"))
207 + args->use_ofs_delta = 1;
208 + if (server_supports("side-band-64k"))
209 + use_sideband = 1;
210 + if (server_supports("quiet"))
211 + quiet_supported = 1;
212 + if (server_supports("agent"))
213 + agent_supported = 1;
214 +
215 + if (!remote_refs) {
216 + fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
217 + "Perhaps you should specify a branch such as 'master'.\n");
218 + return 0;
219 + }
220 +
221 + /*
222 + * Finally, tell the other end!
223 + */
224 + new_refs = 0;
225 + for (ref = remote_refs; ref; ref = ref->next) {
226 + if (!ref->peer_ref && !args->send_mirror)
227 + continue;
228 +
229 + /* Check for statuses set by set_ref_status_for_push() */
230 + switch (ref->status) {
231 + case REF_STATUS_REJECT_NONFASTFORWARD:
232 + case REF_STATUS_UPTODATE:
233 + continue;
234 + default:
235 + ; /* do nothing */
236 + }
237 +
238 + if (ref->deletion && !allow_deleting_refs) {
239 + ref->status = REF_STATUS_REJECT_NODELETE;
240 + continue;
241 + }
242 +
243 + if (!ref->deletion)
244 + new_refs++;
245 +
246 + if (args->dry_run) {
247 + ref->status = REF_STATUS_OK;
248 + } else {
249 + char *old_hex = sha1_to_hex(ref->old_sha1);
250 + char *new_hex = sha1_to_hex(ref->new_sha1);
251 + int quiet = quiet_supported && (args->quiet || !args->progress);
252 +
253 + if (!cmds_sent && (status_report || use_sideband ||
254 + quiet || agent_supported)) {
255 + packet_buf_write(&req_buf,
256 + "%s %s %s%c%s%s%s%s%s",
257 + old_hex, new_hex, ref->name, 0,
258 + status_report ? " report-status" : "",
259 + use_sideband ? " side-band-64k" : "",
260 + quiet ? " quiet" : "",
261 + agent_supported ? " agent=" : "",
262 + agent_supported ? git_user_agent_sanitized() : ""
263 + );
264 + }
265 + else
266 + packet_buf_write(&req_buf, "%s %s %s",
267 + old_hex, new_hex, ref->name);
268 + ref->status = status_report ?
269 + REF_STATUS_EXPECTING_REPORT :
270 + REF_STATUS_OK;
271 + cmds_sent++;
272 + }
273 + }
274 +
275 + if (args->stateless_rpc) {
276 + if (!args->dry_run && cmds_sent) {
277 + packet_buf_flush(&req_buf);
278 + send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX);
279 + }
280 + } else {
281 + safe_write(out, req_buf.buf, req_buf.len);
282 + packet_flush(out);
283 + }
284 + strbuf_release(&req_buf);
285 +
286 + if (use_sideband && cmds_sent) {
287 + memset(&demux, 0, sizeof(demux));
288 + demux.proc = sideband_demux;
289 + demux.data = fd;
290 + demux.out = -1;
291 + if (start_async(&demux))
292 + die("send-pack: unable to fork off sideband demultiplexer");
293 + in = demux.out;
294 + }
295 +
296 + if (new_refs && cmds_sent) {
297 + if (pack_objects(out, remote_refs, extra_have, args) < 0) {
298 + for (ref = remote_refs; ref; ref = ref->next)
299 + ref->status = REF_STATUS_NONE;
300 + if (args->stateless_rpc)
301 + close(out);
302 + if (git_connection_is_socket(conn))
303 + shutdown(fd[0], SHUT_WR);
304 + if (use_sideband)
305 + finish_async(&demux);
306 + return -1;
307 + }
308 + }
309 + if (args->stateless_rpc && cmds_sent)
310 + packet_flush(out);
311 +
312 + if (status_report && cmds_sent)
313 + ret = receive_status(in, remote_refs);
314 + else
315 + ret = 0;
316 + if (args->stateless_rpc)
317 + packet_flush(out);
318 +
319 + if (use_sideband && cmds_sent) {
320 + if (finish_async(&demux)) {
321 + error("error in sideband demultiplexer");
322 + ret = -1;
323 + }
324 + close(demux.out);
325 + }
326 +
327 + if (ret < 0)
328 + return ret;
329 +
330 + if (args->porcelain)
331 + return 0;
332 +
333 + for (ref = remote_refs; ref; ref = ref->next) {
334 + switch (ref->status) {
335 + case REF_STATUS_NONE:
336 + case REF_STATUS_UPTODATE:
337 + case REF_STATUS_OK:
338 + break;
339 + default:
340 + return -1;
341 + }
342 + }
343 + return 0;
344 +}
transport.h
+5
@@ -175,4 +175,9 @@ void transport_print_push_status(const char *dest, struct ref *refs,
175 typedef void alternate_ref_fn(const struct ref *, void *);
176 extern void for_each_alternate_ref(alternate_ref_fn, void *);
177
178 +struct send_pack_args;
179 +extern int send_pack(struct send_pack_args *args,
180 + int fd[], struct child_process *conn,
181 + struct ref *remote_refs,
182 + struct extra_have_objects *extra_have);
183 #endif