remote-helpers: add support for an export command
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Sverre Rabbelier committed
Mar 29, 2010 at 11:48 UTC
73b49a759216bf33cc366eeac113ce00d8c49cc6
1 file changed
+120
-12
transport-helper.c
+120
-12
@@ -7,6 +7,7 @@
7
#include "revision.h"
8
#include "quote.h"
9
#include "remote.h"
10
+#include "string-list.h"
11
12
static int debug;
13
@@ -17,6 +18,7 @@ struct helper_data
18
FILE *out;
19
unsigned fetch : 1,
20
import : 1,
21
+ export : 1,
22
option : 1,
23
push : 1,
24
connect : 1,
@@ -163,6 +165,8 @@ static struct child_process *get_helper(struct transport *transport)
165
data->push = 1;
166
else if (!strcmp(capname, "import"))
167
data->import = 1;
168
+ else if (!strcmp(capname, "export"))
169
+ data->export = 1;
170
else if (!data->refspecs && !prefixcmp(capname, "refspec ")) {
171
ALLOC_GROW(refspecs,
172
refspec_nr + 1,
@@ -356,6 +360,33 @@ static int get_importer(struct transport *transport, struct child_process *fasti
360
return start_command(fastimport);
361
}
362
363
+static int get_exporter(struct transport *transport,
364
+ struct child_process *fastexport,
365
+ const char *export_marks,
366
+ const char *import_marks,
367
+ struct string_list *revlist_args)
368
+{
369
+ struct child_process *helper = get_helper(transport);
370
+ int argc = 0, i;
371
+ memset(fastexport, 0, sizeof(*fastexport));
372
+
373
+ /* we need to duplicate helper->in because we want to use it after
374
+ * fastexport is done with it. */
375
+ fastexport->out = dup(helper->in);
376
+ fastexport->argv = xcalloc(4 + revlist_args->nr, sizeof(*fastexport->argv));
377
+ fastexport->argv[argc++] = "fast-export";
378
+ if (export_marks)
379
+ fastexport->argv[argc++] = export_marks;
380
+ if (import_marks)
381
+ fastexport->argv[argc++] = import_marks;
382
+
383
+ for (i = 0; i < revlist_args->nr; i++)
384
+ fastexport->argv[argc++] = revlist_args->items[i].string;
385
+
386
+ fastexport->git_cmd = 1;
387
+ return start_command(fastexport);
388
+}
389
+
390
static int fetch_with_import(struct transport *transport,
391
int nr_heads, struct ref **to_fetch)
392
{
@@ -523,7 +554,7 @@ static int fetch(struct transport *transport,
554
return -1;
555
}
556
526
-static int push_refs(struct transport *transport,
557
+static int push_refs_with_push(struct transport *transport,
558
struct ref *remote_refs, int flags)
559
{
560
int force_all = flags & TRANSPORT_PUSH_FORCE;
@@ -533,17 +564,6 @@ static int push_refs(struct transport *transport,
564
struct child_process *helper;
565
struct ref *ref;
566
536
- if (process_connect(transport, 1)) {
537
- do_take_over(transport);
538
- return transport->push_refs(transport, remote_refs, flags);
539
- }
540
-
541
- if (!remote_refs) {
542
- fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
543
- "Perhaps you should specify a branch such as 'master'.\n");
544
- return 0;
545
- }
546
-
567
helper = get_helper(transport);
568
if (!data->push)
569
return 1;
@@ -662,6 +682,94 @@ static int push_refs(struct transport *transport,
682
return 0;
683
}
684
685
+static int push_refs_with_export(struct transport *transport,
686
+ struct ref *remote_refs, int flags)
687
+{
688
+ struct ref *ref;
689
+ struct child_process *helper, exporter;
690
+ struct helper_data *data = transport->data;
691
+ char *export_marks = NULL, *import_marks = NULL;
692
+ struct string_list revlist_args = { NULL, 0, 0 };
693
+ struct strbuf buf = STRBUF_INIT;
694
+
695
+ helper = get_helper(transport);
696
+
697
+ write_constant(helper->in, "export\n");
698
+
699
+ recvline(data, &buf);
700
+ if (debug)
701
+ fprintf(stderr, "Debug: Got export_marks '%s'\n", buf.buf);
702
+ if (buf.len) {
703
+ struct strbuf arg = STRBUF_INIT;
704
+ strbuf_addstr(&arg, "--export-marks=");
705
+ strbuf_addbuf(&arg, &buf);
706
+ export_marks = strbuf_detach(&arg, NULL);
707
+ }
708
+
709
+ recvline(data, &buf);
710
+ if (debug)
711
+ fprintf(stderr, "Debug: Got import_marks '%s'\n", buf.buf);
712
+ if (buf.len) {
713
+ struct strbuf arg = STRBUF_INIT;
714
+ strbuf_addstr(&arg, "--import-marks=");
715
+ strbuf_addbuf(&arg, &buf);
716
+ import_marks = strbuf_detach(&arg, NULL);
717
+ }
718
+
719
+ strbuf_reset(&buf);
720
+
721
+ for (ref = remote_refs; ref; ref = ref->next) {
722
+ char *private;
723
+ unsigned char sha1[20];
724
+
725
+ if (!data->refspecs)
726
+ continue;
727
+ private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
728
+ if (private && !get_sha1(private, sha1)) {
729
+ strbuf_addf(&buf, "^%s", private);
730
+ string_list_append(strbuf_detach(&buf, NULL), &revlist_args);
731
+ }
732
+
733
+ string_list_append(ref->name, &revlist_args);
734
+
735
+ }
736
+
737
+ if (get_exporter(transport, &exporter,
738
+ export_marks, import_marks, &revlist_args))
739
+ die("Couldn't run fast-export");
740
+
741
+ data->no_disconnect_req = 1;
742
+ finish_command(&exporter);
743
+ disconnect_helper(transport);
744
+ return 0;
745
+}
746
+
747
+static int push_refs(struct transport *transport,
748
+ struct ref *remote_refs, int flags)
749
+{
750
+ struct helper_data *data = transport->data;
751
+
752
+ if (process_connect(transport, 1)) {
753
+ do_take_over(transport);
754
+ return transport->push_refs(transport, remote_refs, flags);
755
+ }
756
+
757
+ if (!remote_refs) {
758
+ fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
759
+ "Perhaps you should specify a branch such as 'master'.\n");
760
+ return 0;
761
+ }
762
+
763
+ if (data->push)
764
+ return push_refs_with_push(transport, remote_refs, flags);
765
+
766
+ if (data->export)
767
+ return push_refs_with_export(transport, remote_refs, flags);
768
+
769
+ return -1;
770
+}
771
+
772
+
773
static int has_attribute(const char *attrs, const char *attr) {
774
int len;
775
if (!attrs)