зеркало из https://github.com/microsoft/git.git
Merge branch 'db/no-separate-ls-remote-connection' (early part)
* 'db/no-separate-ls-remote-connection' (early part): Fix "git clone" for git:// protocol Reduce the number of connects when fetching
This commit is contained in:
Коммит
40aab8119f
|
@ -7,6 +7,7 @@
|
|||
#include "pack.h"
|
||||
#include "sideband.h"
|
||||
#include "fetch-pack.h"
|
||||
#include "remote.h"
|
||||
#include "run-command.h"
|
||||
|
||||
static int transfer_unpack_limit = -1;
|
||||
|
@ -548,14 +549,14 @@ static int get_pack(int xd[2], char **pack_lockfile)
|
|||
}
|
||||
|
||||
static struct ref *do_fetch_pack(int fd[2],
|
||||
const struct ref *orig_ref,
|
||||
int nr_match,
|
||||
char **match,
|
||||
char **pack_lockfile)
|
||||
{
|
||||
struct ref *ref;
|
||||
struct ref *ref = copy_ref_list(orig_ref);
|
||||
unsigned char sha1[20];
|
||||
|
||||
get_remote_heads(fd[0], &ref, 0, NULL, 0);
|
||||
if (is_repository_shallow() && !server_supports("shallow"))
|
||||
die("Server does not support shallow clients");
|
||||
if (server_supports("multi_ack")) {
|
||||
|
@ -573,10 +574,6 @@ static struct ref *do_fetch_pack(int fd[2],
|
|||
fprintf(stderr, "Server supports side-band\n");
|
||||
use_sideband = 1;
|
||||
}
|
||||
if (!ref) {
|
||||
packet_flush(fd[1]);
|
||||
die("no matching remote head");
|
||||
}
|
||||
if (everything_local(&ref, nr_match, match)) {
|
||||
packet_flush(fd[1]);
|
||||
goto all_done;
|
||||
|
@ -650,8 +647,10 @@ static void fetch_pack_setup(void)
|
|||
int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i, ret, nr_heads;
|
||||
struct ref *ref;
|
||||
struct ref *ref = NULL;
|
||||
char *dest = NULL, **heads;
|
||||
int fd[2];
|
||||
struct child_process *conn;
|
||||
|
||||
nr_heads = 0;
|
||||
heads = NULL;
|
||||
|
@ -706,45 +705,20 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
|
|||
if (!dest)
|
||||
usage(fetch_pack_usage);
|
||||
|
||||
ref = fetch_pack(&args, dest, nr_heads, heads, NULL);
|
||||
ret = !ref;
|
||||
|
||||
while (ref) {
|
||||
printf("%s %s\n",
|
||||
sha1_to_hex(ref->old_sha1), ref->name);
|
||||
ref = ref->next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ref *fetch_pack(struct fetch_pack_args *my_args,
|
||||
const char *dest,
|
||||
int nr_heads,
|
||||
char **heads,
|
||||
char **pack_lockfile)
|
||||
{
|
||||
int i, ret;
|
||||
int fd[2];
|
||||
struct child_process *conn;
|
||||
struct ref *ref;
|
||||
struct stat st;
|
||||
|
||||
fetch_pack_setup();
|
||||
memcpy(&args, my_args, sizeof(args));
|
||||
if (args.depth > 0) {
|
||||
if (stat(git_path("shallow"), &st))
|
||||
st.st_mtime = 0;
|
||||
}
|
||||
|
||||
conn = git_connect(fd, (char *)dest, args.uploadpack,
|
||||
args.verbose ? CONNECT_VERBOSE : 0);
|
||||
if (heads && nr_heads)
|
||||
nr_heads = remove_duplicates(nr_heads, heads);
|
||||
ref = do_fetch_pack(fd, nr_heads, heads, pack_lockfile);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
ret = finish_connect(conn);
|
||||
args.verbose ? CONNECT_VERBOSE : 0);
|
||||
if (conn) {
|
||||
get_remote_heads(fd[0], &ref, 0, NULL, 0);
|
||||
|
||||
ref = fetch_pack(&args, fd, conn, ref, dest, nr_heads, heads, NULL);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
if (finish_connect(conn))
|
||||
ref = NULL;
|
||||
} else {
|
||||
ref = NULL;
|
||||
}
|
||||
ret = !ref;
|
||||
|
||||
if (!ret && nr_heads) {
|
||||
/* If the heads to pull were given, we should have
|
||||
|
@ -758,8 +732,42 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
|
|||
ret = 1;
|
||||
}
|
||||
}
|
||||
while (ref) {
|
||||
printf("%s %s\n",
|
||||
sha1_to_hex(ref->old_sha1), ref->name);
|
||||
ref = ref->next;
|
||||
}
|
||||
|
||||
if (!ret && args.depth > 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ref *fetch_pack(struct fetch_pack_args *my_args,
|
||||
int fd[], struct child_process *conn,
|
||||
const struct ref *ref,
|
||||
const char *dest,
|
||||
int nr_heads,
|
||||
char **heads,
|
||||
char **pack_lockfile)
|
||||
{
|
||||
struct stat st;
|
||||
struct ref *ref_cpy;
|
||||
|
||||
fetch_pack_setup();
|
||||
memcpy(&args, my_args, sizeof(args));
|
||||
if (args.depth > 0) {
|
||||
if (stat(git_path("shallow"), &st))
|
||||
st.st_mtime = 0;
|
||||
}
|
||||
|
||||
if (heads && nr_heads)
|
||||
nr_heads = remove_duplicates(nr_heads, heads);
|
||||
if (!ref) {
|
||||
packet_flush(fd[1]);
|
||||
die("no matching remote head");
|
||||
}
|
||||
ref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile);
|
||||
|
||||
if (args.depth > 0) {
|
||||
struct cache_time mtime;
|
||||
char *shallow = git_path("shallow");
|
||||
int fd;
|
||||
|
@ -787,8 +795,5 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
|
|||
}
|
||||
}
|
||||
|
||||
if (ret)
|
||||
ref = NULL;
|
||||
|
||||
return ref;
|
||||
return ref_cpy;
|
||||
}
|
||||
|
|
|
@ -557,6 +557,8 @@ static int do_fetch(struct transport *transport,
|
|||
|
||||
free_refs(fetch_map);
|
||||
|
||||
transport_disconnect(transport);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
|
|||
transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);
|
||||
|
||||
ref = transport_get_remote_refs(transport);
|
||||
transport_disconnect(transport);
|
||||
|
||||
if (!ref)
|
||||
return 1;
|
||||
|
|
20
connect.c
20
connect.c
|
@ -474,14 +474,18 @@ char *get_port(char *host)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct child_process no_fork;
|
||||
|
||||
/*
|
||||
* This returns NULL if the transport protocol does not need fork(2), or a
|
||||
* struct child_process object if it does. Once done, finish the connection
|
||||
* with finish_connect() with the value returned from this function
|
||||
* (it is safe to call finish_connect() with NULL to support the former
|
||||
* case).
|
||||
* This returns a dummy child_process if the transport protocol does not
|
||||
* need fork(2), or a struct child_process object if it does. Once done,
|
||||
* finish the connection with finish_connect() with the value returned from
|
||||
* this function (it is safe to call finish_connect() with NULL to support
|
||||
* the former case).
|
||||
*
|
||||
* If it returns, the connect is successful; it just dies on errors.
|
||||
* If it returns, the connect is successful; it just dies on errors (this
|
||||
* will hopefully be changed in a libification effort, to return NULL when
|
||||
* the connection failed).
|
||||
*/
|
||||
struct child_process *git_connect(int fd[2], const char *url_orig,
|
||||
const char *prog, int flags)
|
||||
|
@ -579,7 +583,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
|
|||
free(url);
|
||||
if (free_path)
|
||||
free(path);
|
||||
return NULL;
|
||||
return &no_fork;
|
||||
}
|
||||
|
||||
conn = xcalloc(1, sizeof(*conn));
|
||||
|
@ -637,7 +641,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
|
|||
int finish_connect(struct child_process *conn)
|
||||
{
|
||||
int code;
|
||||
if (!conn)
|
||||
if (!conn || conn == &no_fork)
|
||||
return 0;
|
||||
|
||||
code = finish_command(conn);
|
||||
|
|
|
@ -16,6 +16,8 @@ struct fetch_pack_args
|
|||
};
|
||||
|
||||
struct ref *fetch_pack(struct fetch_pack_args *args,
|
||||
int fd[], struct child_process *conn,
|
||||
const struct ref *ref,
|
||||
const char *dest,
|
||||
int nr_heads,
|
||||
char **heads,
|
||||
|
|
51
transport.c
51
transport.c
|
@ -562,6 +562,8 @@ struct git_transport_data {
|
|||
unsigned thin : 1;
|
||||
unsigned keep : 1;
|
||||
int depth;
|
||||
struct child_process *conn;
|
||||
int fd[2];
|
||||
const char *uploadpack;
|
||||
const char *receivepack;
|
||||
};
|
||||
|
@ -592,20 +594,20 @@ static int set_git_option(struct transport *connection,
|
|||
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;
|
||||
}
|
||||
|
@ -616,7 +618,7 @@ static int fetch_refs_via_pack(struct transport *transport,
|
|||
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;
|
||||
|
@ -631,13 +633,27 @@ static int fetch_refs_via_pack(struct transport *transport,
|
|||
|
||||
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);
|
||||
|
||||
refs = transport_get_remote_refs(transport);
|
||||
if (!data->conn) {
|
||||
struct ref *refs_tmp;
|
||||
connect_setup(transport);
|
||||
get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0);
|
||||
free_refs(refs_tmp);
|
||||
}
|
||||
|
||||
refs = fetch_pack(&args, data->fd, data->conn, 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;
|
||||
|
||||
for (i = 0; i < nr_heads; i++)
|
||||
free(origh[i]);
|
||||
free(origh);
|
||||
free(heads);
|
||||
free_refs(refs);
|
||||
free(dest);
|
||||
return (refs ? 0 : -1);
|
||||
}
|
||||
|
@ -660,7 +676,15 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -720,6 +744,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
|
|||
ret->disconnect = disconnect_git;
|
||||
|
||||
data->thin = 1;
|
||||
data->conn = NULL;
|
||||
data->uploadpack = "git-upload-pack";
|
||||
if (remote && remote->uploadpack)
|
||||
data->uploadpack = remote->uploadpack;
|
||||
|
|
Загрузка…
Ссылка в новой задаче