1
#include "cache.h"
2
#include "transport.h"
3
-
3
+#include "quote.h"
4
#include "run-command.h"
5
#include "commit.h"
6
#include "diff.h"
13
struct child_process *helper;
14
FILE *out;
15
unsigned fetch : 1,
16
- option : 1;
16
+ option : 1,
17
+ push : 1;
18
};
19
20
static struct child_process *get_helper(struct transport *transport)
53
data->fetch = 1;
54
if (!strcmp(buf.buf, "option"))
55
data->option = 1;
56
+ if (!strcmp(buf.buf, "push"))
57
+ data->push = 1;
58
}
59
return data->helper;
60
}
217
return -1;
218
}
219
220
+static int push_refs(struct transport *transport,
221
+ struct ref *remote_refs, int flags)
222
+{
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;
228
+ struct ref *ref;
229
+
230
+ if (!remote_refs)
231
+ return 0;
232
+
233
+ helper = get_helper(transport);
234
+ if (!data->push)
235
+ return 1;
236
+
237
+ for (ref = remote_refs; ref; ref = ref->next) {
238
+ if (ref->peer_ref)
239
+ hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
240
+ else if (!mirror)
241
+ continue;
242
+
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;
247
+ continue;
248
+ }
249
+
250
+ if (force_all)
251
+ ref->force = 1;
252
+
253
+ strbuf_addstr(&buf, "push ");
254
+ if (!ref->deletion) {
255
+ if (ref->force)
256
+ strbuf_addch(&buf, '+');
257
+ if (ref->peer_ref)
258
+ strbuf_addstr(&buf, ref->peer_ref->name);
259
+ else
260
+ strbuf_addstr(&buf, sha1_to_hex(ref->new_sha1));
261
+ }
262
+ strbuf_addch(&buf, ':');
263
+ strbuf_addstr(&buf, ref->name);
264
+ strbuf_addch(&buf, '\n');
265
+ }
266
+
267
+ transport->verbose = flags & TRANSPORT_PUSH_VERBOSE ? 1 : 0;
268
+ standard_options(transport);
269
+
270
+ if (flags & TRANSPORT_PUSH_DRY_RUN) {
271
+ if (set_helper_option(transport, "dry-run", "true") != 0)
272
+ die("helper %s does not support dry-run", data->name);
273
+ }
274
+
275
+ strbuf_addch(&buf, '\n');
276
+ if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
277
+ exit(128);
278
+
279
+ ref = remote_refs;
280
+ while (1) {
281
+ char *refname, *msg;
282
+ int status;
283
+
284
+ strbuf_reset(&buf);
285
+ if (strbuf_getline(&buf, data->out, '\n') == EOF)
286
+ exit(128); /* child died, message supplied already */
287
+ if (!buf.len)
288
+ break;
289
+
290
+ if (!prefixcmp(buf.buf, "ok ")) {
291
+ status = REF_STATUS_OK;
292
+ refname = buf.buf + 3;
293
+ } else if (!prefixcmp(buf.buf, "error ")) {
294
+ status = REF_STATUS_REMOTE_REJECT;
295
+ refname = buf.buf + 6;
296
+ } else
297
+ die("expected ok/error, helper said '%s'\n", buf.buf);
298
+
299
+ msg = strchr(refname, ' ');
300
+ if (msg) {
301
+ struct strbuf msg_buf = STRBUF_INIT;
302
+ const char *end;
303
+
304
+ *msg++ = '\0';
305
+ if (!unquote_c_style(&msg_buf, msg, &end))
306
+ msg = strbuf_detach(&msg_buf, NULL);
307
+ else
308
+ msg = xstrdup(msg);
309
+ strbuf_release(&msg_buf);
310
+
311
+ if (!strcmp(msg, "no match")) {
312
+ status = REF_STATUS_NONE;
313
+ free(msg);
314
+ msg = NULL;
315
+ }
316
+ else if (!strcmp(msg, "up to date")) {
317
+ status = REF_STATUS_UPTODATE;
318
+ free(msg);
319
+ msg = NULL;
320
+ }
321
+ else if (!strcmp(msg, "non-fast forward")) {
322
+ status = REF_STATUS_REJECT_NONFASTFORWARD;
323
+ free(msg);
324
+ msg = NULL;
325
+ }
326
+ }
327
+
328
+ if (ref)
329
+ ref = find_ref_by_name(ref, refname);
330
+ if (!ref)
331
+ ref = find_ref_by_name(remote_refs, refname);
332
+ if (!ref) {
333
+ warning("helper reported unexpected status of %s", refname);
334
+ continue;
335
+ }
336
+
337
+ ref->status = status;
338
+ ref->remote_status = msg;
339
+ }
340
+ strbuf_release(&buf);
341
+ return 0;
342
+}
343
+
344
static struct ref *get_refs_list(struct transport *transport, int for_push)
345
{
346
struct helper_data *data = transport->data;
352
353
helper = get_helper(transport);
354
228
- write_str_in_full(helper->in, "list\n");
355
+ if (data->push && for_push)
356
+ write_str_in_full(helper->in, "list for-push\n");
357
+ else
358
+ write_str_in_full(helper->in, "list\n");
359
360
while (1) {
361
char *eov, *eon;
396
transport->set_option = set_helper_option;
397
transport->get_refs_list = get_refs_list;
398
transport->fetch = fetch;
399
+ transport->push_refs = push_refs;
400
transport->disconnect = disconnect_helper;
401
return 0;
402
}