struct ref *ref = NULL;
struct ref *last_ref = NULL;
+ struct walker *walker;
+
if (!transport->data)
transport->data = get_http_walker(transport->url,
transport->remote);
+ walker = transport->data;
+
refs_url = xmalloc(strlen(transport->url) + 11);
sprintf(refs_url, "%s/info/refs", transport->url);
strbuf_release(&buffer);
+ ref = alloc_ref_from_str("HEAD");
+ if (!walker->fetch_ref(walker, ref) &&
+ !resolve_remote_symref(ref, refs)) {
+ ref->next = refs;
+ refs = ref;
+ } else {
+ free(ref);
+ }
+
return refs;
}
die ("Could not read bundle '%s'.", transport->url);
for (i = 0; i < data->header.references.nr; i++) {
struct ref_list_entry *e = data->header.references.list + i;
- struct ref *ref = alloc_ref(strlen(e->name) + 1);
+ struct ref *ref = alloc_ref_from_str(e->name);
hashcpy(ref->old_sha1, e->sha1);
- strcpy(ref->name, e->name);
ref->next = result;
result = ref;
}
struct git_transport_data {
unsigned thin : 1;
unsigned keep : 1;
+ unsigned followtags : 1;
int depth;
+ struct child_process *conn;
+ int fd[2];
const char *uploadpack;
const char *receivepack;
};
} else if (!strcmp(name, TRANS_OPT_THIN)) {
data->thin = !!value;
return 0;
+ } else if (!strcmp(name, TRANS_OPT_FOLLOWTAGS)) {
+ data->followtags = !!value;
+ return 0;
} else if (!strcmp(name, TRANS_OPT_KEEP)) {
data->keep = !!value;
return 0;
return 1;
}
+static int connect_setup(struct transport *transport)
+{
+ struct git_transport_data *data = transport->data;
+ data->conn = git_connect(data->fd, transport->url, data->uploadpack, 0);
+ return 0;
+}
+
static struct ref *get_refs_via_connect(struct transport *transport)
{
struct git_transport_data *data = transport->data;
struct ref *refs;
- int fd[2];
- char *dest = xstrdup(transport->url);
- struct child_process *conn = git_connect(fd, dest, data->uploadpack, 0);
-
- get_remote_heads(fd[0], &refs, 0, NULL, 0);
- packet_flush(fd[1]);
- finish_connect(conn);
-
- free(dest);
+ connect_setup(transport);
+ get_remote_heads(data->fd[0], &refs, 0, NULL, 0);
return refs;
}
struct git_transport_data *data = transport->data;
char **heads = xmalloc(nr_heads * sizeof(*heads));
char **origh = xmalloc(nr_heads * sizeof(*origh));
- struct ref *refs;
+ const struct ref *refs;
char *dest = xstrdup(transport->url);
struct fetch_pack_args args;
int i;
+ struct ref *refs_tmp = NULL;
memset(&args, 0, sizeof(args));
args.uploadpack = data->uploadpack;
args.keep_pack = data->keep;
args.lock_pack = 1;
args.use_thin_pack = data->thin;
+ args.include_tag = data->followtags;
args.verbose = transport->verbose > 0;
args.depth = data->depth;
for (i = 0; i < nr_heads; i++)
origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
- refs = fetch_pack(&args, dest, nr_heads, heads, &transport->pack_lockfile);
+
+ if (!data->conn) {
+ connect_setup(transport);
+ get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0);
+ }
+
+ refs = fetch_pack(&args, data->fd, data->conn,
+ refs_tmp ? refs_tmp : transport->remote_refs,
+ dest, nr_heads, heads, &transport->pack_lockfile);
+ close(data->fd[0]);
+ close(data->fd[1]);
+ if (finish_connect(data->conn))
+ refs = NULL;
+ data->conn = NULL;
+
+ free_refs(refs_tmp);
for (i = 0; i < nr_heads; i++)
free(origh[i]);
free(origh);
free(heads);
- free_refs(refs);
free(dest);
return (refs ? 0 : -1);
}
static int disconnect_git(struct transport *transport)
{
- free(transport->data);
+ struct git_transport_data *data = transport->data;
+ if (data->conn) {
+ packet_flush(data->fd[1]);
+ close(data->fd[0]);
+ close(data->fd[1]);
+ finish_connect(data->conn);
+ }
+
+ free(data);
return 0;
}
ret->disconnect = disconnect_git;
data->thin = 1;
+ data->conn = NULL;
data->uploadpack = "git-upload-pack";
if (remote && remote->uploadpack)
data->uploadpack = remote->uploadpack;