4 #include "run-command.h"
13 struct child_process
*helper
;
20 static struct child_process
*get_helper(struct transport
*transport
)
22 struct helper_data
*data
= transport
->data
;
23 struct strbuf buf
= STRBUF_INIT
;
24 struct child_process
*helper
;
29 helper
= xcalloc(1, sizeof(*helper
));
33 helper
->argv
= xcalloc(4, sizeof(*helper
->argv
));
34 strbuf_addf(&buf
, "remote-%s", data
->name
);
35 helper
->argv
[0] = strbuf_detach(&buf
, NULL
);
36 helper
->argv
[1] = transport
->remote
->name
;
37 helper
->argv
[2] = transport
->url
;
39 if (start_command(helper
))
40 die("Unable to run helper: git %s", helper
->argv
[0]);
41 data
->helper
= helper
;
43 write_str_in_full(helper
->in
, "capabilities\n");
45 data
->out
= xfdopen(helper
->out
, "r");
47 if (strbuf_getline(&buf
, data
->out
, '\n') == EOF
)
48 exit(128); /* child died, message supplied already */
52 if (!strcmp(buf
.buf
, "fetch"))
54 if (!strcmp(buf
.buf
, "option"))
56 if (!strcmp(buf
.buf
, "push"))
62 static int disconnect_helper(struct transport
*transport
)
64 struct helper_data
*data
= transport
->data
;
66 write_str_in_full(data
->helper
->in
, "\n");
67 close(data
->helper
->in
);
69 finish_command(data
->helper
);
70 free((char *)data
->helper
->argv
[0]);
71 free(data
->helper
->argv
);
79 static const char *unsupported_options
[] = {
81 TRANS_OPT_RECEIVEPACK
,
85 static const char *boolean_options
[] = {
91 static int set_helper_option(struct transport
*transport
,
92 const char *name
, const char *value
)
94 struct helper_data
*data
= transport
->data
;
95 struct child_process
*helper
= get_helper(transport
);
96 struct strbuf buf
= STRBUF_INIT
;
97 int i
, ret
, is_bool
= 0;
102 for (i
= 0; i
< ARRAY_SIZE(unsupported_options
); i
++) {
103 if (!strcmp(name
, unsupported_options
[i
]))
107 for (i
= 0; i
< ARRAY_SIZE(boolean_options
); i
++) {
108 if (!strcmp(name
, boolean_options
[i
])) {
114 strbuf_addf(&buf
, "option %s ", name
);
116 strbuf_addstr(&buf
, value
? "true" : "false");
118 quote_c_style(value
, &buf
, NULL
, 0);
119 strbuf_addch(&buf
, '\n');
121 if (write_in_full(helper
->in
, buf
.buf
, buf
.len
) != buf
.len
)
122 die_errno("cannot send option to %s", data
->name
);
125 if (strbuf_getline(&buf
, data
->out
, '\n') == EOF
)
126 exit(128); /* child died, message supplied already */
128 if (!strcmp(buf
.buf
, "ok"))
130 else if (!prefixcmp(buf
.buf
, "error")) {
132 } else if (!strcmp(buf
.buf
, "unsupported"))
135 warning("%s unexpectedly said: '%s'", data
->name
, buf
.buf
);
138 strbuf_release(&buf
);
142 static void standard_options(struct transport
*t
)
147 int no_progress
= v
< 0 || (!t
->progress
&& !isatty(1));
149 set_helper_option(t
, "progress", !no_progress
? "true" : "false");
151 n
= snprintf(buf
, sizeof(buf
), "%d", v
+ 1);
152 if (n
>= sizeof(buf
))
153 die("impossibly large verbosity value");
154 set_helper_option(t
, "verbosity", buf
);
157 static int fetch_with_fetch(struct transport
*transport
,
158 int nr_heads
, const struct ref
**to_fetch
)
160 struct helper_data
*data
= transport
->data
;
162 struct strbuf buf
= STRBUF_INIT
;
164 standard_options(transport
);
166 for (i
= 0; i
< nr_heads
; i
++) {
167 const struct ref
*posn
= to_fetch
[i
];
168 if (posn
->status
& REF_STATUS_UPTODATE
)
171 strbuf_addf(&buf
, "fetch %s %s\n",
172 sha1_to_hex(posn
->old_sha1
), posn
->name
);
175 strbuf_addch(&buf
, '\n');
176 if (write_in_full(data
->helper
->in
, buf
.buf
, buf
.len
) != buf
.len
)
177 die_errno("cannot send fetch to %s", data
->name
);
181 if (strbuf_getline(&buf
, data
->out
, '\n') == EOF
)
182 exit(128); /* child died, message supplied already */
184 if (!prefixcmp(buf
.buf
, "lock ")) {
185 const char *name
= buf
.buf
+ 5;
186 if (transport
->pack_lockfile
)
187 warning("%s also locked %s", data
->name
, name
);
189 transport
->pack_lockfile
= xstrdup(name
);
194 warning("%s unexpectedly said: '%s'", data
->name
, buf
.buf
);
196 strbuf_release(&buf
);
200 static int fetch(struct transport
*transport
,
201 int nr_heads
, const struct ref
**to_fetch
)
203 struct helper_data
*data
= transport
->data
;
207 for (i
= 0; i
< nr_heads
; i
++)
208 if (!(to_fetch
[i
]->status
& REF_STATUS_UPTODATE
))
215 return fetch_with_fetch(transport
, nr_heads
, to_fetch
);
220 static int push_refs(struct transport
*transport
,
221 struct ref
*remote_refs
, int flags
)
223 int force_all
= flags
& TRANSPORT_PUSH_FORCE
;
224 int mirror
= flags
& TRANSPORT_PUSH_MIRROR
;
225 struct helper_data
*data
= transport
->data
;
226 struct strbuf buf
= STRBUF_INIT
;
227 struct child_process
*helper
;
233 helper
= get_helper(transport
);
237 for (ref
= remote_refs
; ref
; ref
= ref
->next
) {
239 hashcpy(ref
->new_sha1
, ref
->peer_ref
->new_sha1
);
243 ref
->deletion
= is_null_sha1(ref
->new_sha1
);
244 if (!ref
->deletion
&&
245 !hashcmp(ref
->old_sha1
, ref
->new_sha1
)) {
246 ref
->status
= REF_STATUS_UPTODATE
;
253 strbuf_addstr(&buf
, "push ");
254 if (!ref
->deletion
) {
256 strbuf_addch(&buf
, '+');
258 strbuf_addstr(&buf
, ref
->peer_ref
->name
);
260 strbuf_addstr(&buf
, sha1_to_hex(ref
->new_sha1
));
262 strbuf_addch(&buf
, ':');
263 strbuf_addstr(&buf
, ref
->name
);
264 strbuf_addch(&buf
, '\n');
269 transport
->verbose
= flags
& TRANSPORT_PUSH_VERBOSE
? 1 : 0;
270 standard_options(transport
);
272 if (flags
& TRANSPORT_PUSH_DRY_RUN
) {
273 if (set_helper_option(transport
, "dry-run", "true") != 0)
274 die("helper %s does not support dry-run", data
->name
);
277 strbuf_addch(&buf
, '\n');
278 if (write_in_full(helper
->in
, buf
.buf
, buf
.len
) != buf
.len
)
287 if (strbuf_getline(&buf
, data
->out
, '\n') == EOF
)
288 exit(128); /* child died, message supplied already */
292 if (!prefixcmp(buf
.buf
, "ok ")) {
293 status
= REF_STATUS_OK
;
294 refname
= buf
.buf
+ 3;
295 } else if (!prefixcmp(buf
.buf
, "error ")) {
296 status
= REF_STATUS_REMOTE_REJECT
;
297 refname
= buf
.buf
+ 6;
299 die("expected ok/error, helper said '%s'\n", buf
.buf
);
301 msg
= strchr(refname
, ' ');
303 struct strbuf msg_buf
= STRBUF_INIT
;
307 if (!unquote_c_style(&msg_buf
, msg
, &end
))
308 msg
= strbuf_detach(&msg_buf
, NULL
);
311 strbuf_release(&msg_buf
);
313 if (!strcmp(msg
, "no match")) {
314 status
= REF_STATUS_NONE
;
318 else if (!strcmp(msg
, "up to date")) {
319 status
= REF_STATUS_UPTODATE
;
323 else if (!strcmp(msg
, "non-fast forward")) {
324 status
= REF_STATUS_REJECT_NONFASTFORWARD
;
331 ref
= find_ref_by_name(ref
, refname
);
333 ref
= find_ref_by_name(remote_refs
, refname
);
335 warning("helper reported unexpected status of %s", refname
);
339 ref
->status
= status
;
340 ref
->remote_status
= msg
;
342 strbuf_release(&buf
);
346 static struct ref
*get_refs_list(struct transport
*transport
, int for_push
)
348 struct helper_data
*data
= transport
->data
;
349 struct child_process
*helper
;
350 struct ref
*ret
= NULL
;
351 struct ref
**tail
= &ret
;
353 struct strbuf buf
= STRBUF_INIT
;
355 helper
= get_helper(transport
);
357 if (data
->push
&& for_push
)
358 write_str_in_full(helper
->in
, "list for-push\n");
360 write_str_in_full(helper
->in
, "list\n");
364 if (strbuf_getline(&buf
, data
->out
, '\n') == EOF
)
365 exit(128); /* child died, message supplied already */
370 eov
= strchr(buf
.buf
, ' ');
372 die("Malformed response in ref list: %s", buf
.buf
);
373 eon
= strchr(eov
+ 1, ' ');
377 *tail
= alloc_ref(eov
+ 1);
378 if (buf
.buf
[0] == '@')
379 (*tail
)->symref
= xstrdup(buf
.buf
+ 1);
380 else if (buf
.buf
[0] != '?')
381 get_sha1_hex(buf
.buf
, (*tail
)->old_sha1
);
382 tail
= &((*tail
)->next
);
384 strbuf_release(&buf
);
386 for (posn
= ret
; posn
; posn
= posn
->next
)
387 resolve_remote_symref(posn
, ret
);
392 int transport_helper_init(struct transport
*transport
, const char *name
)
394 struct helper_data
*data
= xcalloc(sizeof(*data
), 1);
397 transport
->data
= data
;
398 transport
->set_option
= set_helper_option
;
399 transport
->get_refs_list
= get_refs_list
;
400 transport
->fetch
= fetch
;
401 transport
->push_refs
= push_refs
;
402 transport
->disconnect
= disconnect_helper
;