mirror of
https://github.com/git/git.git
synced 2025-01-19 22:13:32 +08:00
upload-pack: Do not choke on too many heads request.
Cloning from a repository with more than 256 refs (heads and tags included) will choke, because upload-pack has a built-in limit of feeding not more than MAX_NEEDS (currently 256) heads to underlying git-rev-list. This is a problem when cloning a repository with many tags, like http://www.linux-mips.org/pub/scm/linux.git, which has 290+ tags. This commit introduces a new flag, --all, to git-rev-list, to include all refs in the repository. Updated upload-pack detects requests that ask more than MAX_NEEDS refs, and sends everything back instead. We may probably want to tweak the definitions of MAX_NEEDS and MAX_HAS, but that is a separate topic. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
df34297af1
commit
e091eb9325
21
rev-list.c
21
rev-list.c
@ -1,4 +1,5 @@
|
||||
#include "cache.h"
|
||||
#include "refs.h"
|
||||
#include "tag.h"
|
||||
#include "commit.h"
|
||||
#include "tree.h"
|
||||
@ -489,6 +490,22 @@ static void handle_one_commit(struct commit *com, struct commit_list **lst)
|
||||
commit_list_insert(com, lst);
|
||||
}
|
||||
|
||||
/* for_each_ref() callback does not allow user data -- Yuck. */
|
||||
static struct commit_list **global_lst;
|
||||
|
||||
static int include_one_commit(const char *path, const unsigned char *sha1)
|
||||
{
|
||||
struct commit *com = get_commit_reference(path, 0);
|
||||
handle_one_commit(com, global_lst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_all(struct commit_list **lst)
|
||||
{
|
||||
global_lst = lst;
|
||||
for_each_ref(include_one_commit);
|
||||
global_lst = NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@ -542,6 +559,10 @@ int main(int argc, char **argv)
|
||||
bisect_list = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--all")) {
|
||||
handle_all(&list);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--objects")) {
|
||||
tag_objects = 1;
|
||||
tree_objects = 1;
|
||||
|
@ -32,6 +32,7 @@ static int revs_count = 0;
|
||||
static int is_rev_argument(const char *arg)
|
||||
{
|
||||
static const char *rev_args[] = {
|
||||
"--all",
|
||||
"--bisect",
|
||||
"--header",
|
||||
"--max-age=",
|
||||
|
@ -30,10 +30,18 @@ static void create_pack_file(void)
|
||||
|
||||
if (!pid) {
|
||||
int i;
|
||||
int args = nr_has + nr_needs + 5;
|
||||
char **argv = xmalloc(args * sizeof(char *));
|
||||
char *buf = xmalloc(args * 45);
|
||||
char **p = argv;
|
||||
int args;
|
||||
char **argv;
|
||||
char *buf;
|
||||
char **p;
|
||||
|
||||
if (MAX_NEEDS <= nr_needs)
|
||||
args = nr_has + 10;
|
||||
else
|
||||
args = nr_has + nr_needs + 5;
|
||||
argv = xmalloc(args * sizeof(char *));
|
||||
buf = xmalloc(args * 45);
|
||||
p = argv;
|
||||
|
||||
dup2(fd[1], 1);
|
||||
close(0);
|
||||
@ -41,10 +49,14 @@ static void create_pack_file(void)
|
||||
close(fd[1]);
|
||||
*p++ = "git-rev-list";
|
||||
*p++ = "--objects";
|
||||
for (i = 0; i < nr_needs; i++) {
|
||||
*p++ = buf;
|
||||
memcpy(buf, sha1_to_hex(needs_sha1[i]), 41);
|
||||
buf += 41;
|
||||
if (MAX_NEEDS <= nr_needs)
|
||||
*p++ = "--all";
|
||||
else {
|
||||
for (i = 0; i < nr_needs; i++) {
|
||||
*p++ = buf;
|
||||
memcpy(buf, sha1_to_hex(needs_sha1[i]), 41);
|
||||
buf += 41;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < nr_has; i++) {
|
||||
*p++ = buf;
|
||||
@ -129,18 +141,24 @@ static int receive_needs(void)
|
||||
|
||||
needs = 0;
|
||||
for (;;) {
|
||||
unsigned char dummy[20], *sha1_buf;
|
||||
len = packet_read_line(0, line, sizeof(line));
|
||||
if (!len)
|
||||
return needs;
|
||||
|
||||
/*
|
||||
* This is purely theoretical right now: git-fetch-pack only
|
||||
* ever asks for a single HEAD
|
||||
*/
|
||||
if (needs >= MAX_NEEDS)
|
||||
die("I'm only doing a max of %d requests", MAX_NEEDS);
|
||||
if (strncmp("want ", line, 5) || get_sha1_hex(line+5, needs_sha1[needs]))
|
||||
die("git-upload-pack: protocol error, expected to get sha, not '%s'", line);
|
||||
sha1_buf = dummy;
|
||||
if (needs == MAX_NEEDS) {
|
||||
fprintf(stderr,
|
||||
"warning: supporting only a max of %d requests. "
|
||||
"sending everything instead.\n",
|
||||
MAX_NEEDS);
|
||||
}
|
||||
else if (needs < MAX_NEEDS)
|
||||
sha1_buf = needs_sha1[needs];
|
||||
|
||||
if (strncmp("want ", line, 5) || get_sha1_hex(line+5, sha1_buf))
|
||||
die("git-upload-pack: protocol error, "
|
||||
"expected to get sha, not '%s'", line);
|
||||
needs++;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user