4 #include "run-command.h"
12 struct child_process
*helper
;
17 static struct child_process
*get_helper(struct transport
*transport
)
19 struct helper_data
*data
= transport
->data
;
20 struct strbuf buf
= STRBUF_INIT
;
21 struct child_process
*helper
;
27 helper
= xcalloc(1, sizeof(*helper
));
31 helper
->argv
= xcalloc(4, sizeof(*helper
->argv
));
32 strbuf_addf(&buf
, "remote-%s", data
->name
);
33 helper
->argv
[0] = strbuf_detach(&buf
, NULL
);
34 helper
->argv
[1] = transport
->remote
->name
;
35 helper
->argv
[2] = transport
->url
;
37 if (start_command(helper
))
38 die("Unable to run helper: git %s", helper
->argv
[0]);
39 data
->helper
= helper
;
41 write_str_in_full(helper
->in
, "capabilities\n");
43 file
= xfdopen(helper
->out
, "r");
45 if (strbuf_getline(&buf
, file
, '\n') == EOF
)
46 exit(128); /* child died, message supplied already */
50 if (!strcmp(buf
.buf
, "fetch"))
52 if (!strcmp(buf
.buf
, "import"))
58 static int disconnect_helper(struct transport
*transport
)
60 struct helper_data
*data
= transport
->data
;
62 write_str_in_full(data
->helper
->in
, "\n");
63 close(data
->helper
->in
);
64 finish_command(data
->helper
);
65 free((char *)data
->helper
->argv
[0]);
66 free(data
->helper
->argv
);
73 static int fetch_with_fetch(struct transport
*transport
,
74 int nr_heads
, struct ref
**to_fetch
)
76 struct child_process
*helper
= get_helper(transport
);
77 FILE *file
= xfdopen(helper
->out
, "r");
79 struct strbuf buf
= STRBUF_INIT
;
81 for (i
= 0; i
< nr_heads
; i
++) {
82 const struct ref
*posn
= to_fetch
[i
];
83 if (posn
->status
& REF_STATUS_UPTODATE
)
86 strbuf_addf(&buf
, "fetch %s %s\n",
87 sha1_to_hex(posn
->old_sha1
), posn
->name
);
88 write_in_full(helper
->in
, buf
.buf
, buf
.len
);
91 if (strbuf_getline(&buf
, file
, '\n') == EOF
)
92 exit(128); /* child died, message supplied already */
97 static int get_importer(struct transport
*transport
, struct child_process
*fastimport
)
99 struct child_process
*helper
= get_helper(transport
);
100 memset(fastimport
, 0, sizeof(*fastimport
));
101 fastimport
->in
= helper
->out
;
102 fastimport
->argv
= xcalloc(5, sizeof(*fastimport
->argv
));
103 fastimport
->argv
[0] = "fast-import";
104 fastimport
->argv
[1] = "--quiet";
106 fastimport
->git_cmd
= 1;
107 return start_command(fastimport
);
110 static int fetch_with_import(struct transport
*transport
,
111 int nr_heads
, struct ref
**to_fetch
)
113 struct child_process fastimport
;
114 struct child_process
*helper
= get_helper(transport
);
117 struct strbuf buf
= STRBUF_INIT
;
119 if (get_importer(transport
, &fastimport
))
120 die("Couldn't run fast-import");
122 for (i
= 0; i
< nr_heads
; i
++) {
124 if (posn
->status
& REF_STATUS_UPTODATE
)
127 strbuf_addf(&buf
, "import %s\n", posn
->name
);
128 write_in_full(helper
->in
, buf
.buf
, buf
.len
);
131 disconnect_helper(transport
);
132 finish_command(&fastimport
);
134 for (i
= 0; i
< nr_heads
; i
++) {
136 if (posn
->status
& REF_STATUS_UPTODATE
)
138 read_ref(posn
->name
, posn
->old_sha1
);
143 static int fetch(struct transport
*transport
,
144 int nr_heads
, struct ref
**to_fetch
)
146 struct helper_data
*data
= transport
->data
;
150 for (i
= 0; i
< nr_heads
; i
++)
151 if (!(to_fetch
[i
]->status
& REF_STATUS_UPTODATE
))
158 return fetch_with_fetch(transport
, nr_heads
, to_fetch
);
161 return fetch_with_import(transport
, nr_heads
, to_fetch
);
166 static int has_attribute(const char *attrs
, const char *attr
) {
173 const char *space
= strchrnul(attrs
, ' ');
174 if (len
== space
- attrs
&& !strncmp(attrs
, attr
, len
))
182 static struct ref
*get_refs_list(struct transport
*transport
, int for_push
)
184 struct child_process
*helper
;
185 struct ref
*ret
= NULL
;
186 struct ref
**tail
= &ret
;
188 struct strbuf buf
= STRBUF_INIT
;
191 helper
= get_helper(transport
);
193 write_str_in_full(helper
->in
, "list\n");
195 file
= xfdopen(helper
->out
, "r");
198 if (strbuf_getline(&buf
, file
, '\n') == EOF
)
199 exit(128); /* child died, message supplied already */
204 eov
= strchr(buf
.buf
, ' ');
206 die("Malformed response in ref list: %s", buf
.buf
);
207 eon
= strchr(eov
+ 1, ' ');
211 *tail
= alloc_ref(eov
+ 1);
212 if (buf
.buf
[0] == '@')
213 (*tail
)->symref
= xstrdup(buf
.buf
+ 1);
214 else if (buf
.buf
[0] != '?')
215 get_sha1_hex(buf
.buf
, (*tail
)->old_sha1
);
217 if (has_attribute(eon
+ 1, "unchanged")) {
218 (*tail
)->status
|= REF_STATUS_UPTODATE
;
219 read_ref((*tail
)->name
, (*tail
)->old_sha1
);
222 tail
= &((*tail
)->next
);
224 strbuf_release(&buf
);
226 for (posn
= ret
; posn
; posn
= posn
->next
)
227 resolve_remote_symref(posn
, ret
);
232 int transport_helper_init(struct transport
*transport
, const char *name
)
234 struct helper_data
*data
= xcalloc(sizeof(*data
), 1);
237 transport
->data
= data
;
238 transport
->get_refs_list
= get_refs_list
;
239 transport
->fetch
= fetch
;
240 transport
->disconnect
= disconnect_helper
;