smart-http: support shallow fetch/clone

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy 2013-12-05 20:02:50 +07:00 committed by Junio C Hamano
parent 58f2ed051f
commit 16094885ca
6 changed files with 81 additions and 9 deletions

View File

@ -437,6 +437,13 @@ set by Git if the remote helper has the 'option' capability.
'option check-connectivity' \{'true'|'false'\}:: 'option check-connectivity' \{'true'|'false'\}::
Request the helper to check connectivity of a clone. Request the helper to check connectivity of a clone.
'option cloning \{'true'|'false'\}::
Notify the helper this is a clone request (i.e. the current
repository is guaranteed empty).
'option update-shallow \{'true'|'false'\}::
Allow to extend .git/shallow if the new refs require it.
SEE ALSO SEE ALSO
-------- --------
linkgit:git-remote[1] linkgit:git-remote[1]

View File

@ -3,6 +3,7 @@
#include "fetch-pack.h" #include "fetch-pack.h"
#include "remote.h" #include "remote.h"
#include "connect.h" #include "connect.h"
#include "sha1-array.h"
static const char fetch_pack_usage[] = static const char fetch_pack_usage[] =
"git fetch-pack [--all] [--stdin] [--quiet|-q] [--keep|-k] [--thin] " "git fetch-pack [--all] [--stdin] [--quiet|-q] [--keep|-k] [--thin] "
@ -46,6 +47,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
char **pack_lockfile_ptr = NULL; char **pack_lockfile_ptr = NULL;
struct child_process *conn; struct child_process *conn;
struct fetch_pack_args args; struct fetch_pack_args args;
struct sha1_array shallow = SHA1_ARRAY_INIT;
packet_trace_identity("fetch-pack"); packet_trace_identity("fetch-pack");
@ -113,6 +115,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
args.check_self_contained_and_connected = 1; args.check_self_contained_and_connected = 1;
continue; continue;
} }
if (!strcmp("--cloning", arg)) {
args.cloning = 1;
continue;
}
if (!strcmp("--update-shallow", arg)) {
args.update_shallow = 1;
continue;
}
usage(fetch_pack_usage); usage(fetch_pack_usage);
} }
@ -157,10 +167,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
args.verbose ? CONNECT_VERBOSE : 0); args.verbose ? CONNECT_VERBOSE : 0);
} }
get_remote_heads(fd[0], NULL, 0, &ref, 0, NULL, NULL); get_remote_heads(fd[0], NULL, 0, &ref, 0, NULL, &shallow);
ref = fetch_pack(&args, fd, conn, ref, dest, ref = fetch_pack(&args, fd, conn, ref, dest, sought, nr_sought,
sought, nr_sought, NULL, pack_lockfile_ptr); &shallow, pack_lockfile_ptr);
if (pack_lockfile) { if (pack_lockfile) {
printf("lock %s\n", pack_lockfile); printf("lock %s\n", pack_lockfile);
fflush(stdout); fflush(stdout);

View File

@ -10,6 +10,7 @@
#include "sideband.h" #include "sideband.h"
#include "argv-array.h" #include "argv-array.h"
#include "credential.h" #include "credential.h"
#include "sha1-array.h"
static struct remote *remote; static struct remote *remote;
/* always ends with a trailing slash */ /* always ends with a trailing slash */
@ -20,6 +21,8 @@ struct options {
unsigned long depth; unsigned long depth;
unsigned progress : 1, unsigned progress : 1,
check_self_contained_and_connected : 1, check_self_contained_and_connected : 1,
cloning : 1,
update_shallow : 1,
followtags : 1, followtags : 1,
dry_run : 1, dry_run : 1,
thin : 1; thin : 1;
@ -87,8 +90,23 @@ static int set_option(const char *name, const char *value)
string_list_append(&cas_options, val.buf); string_list_append(&cas_options, val.buf);
strbuf_release(&val); strbuf_release(&val);
return 0; return 0;
} } else if (!strcmp(name, "cloning")) {
else { if (!strcmp(value, "true"))
options.cloning = 1;
else if (!strcmp(value, "false"))
options.cloning = 0;
else
return -1;
return 0;
} else if (!strcmp(name, "update-shallow")) {
if (!strcmp(value, "true"))
options.update_shallow = 1;
else if (!strcmp(value, "false"))
options.update_shallow = 0;
else
return -1;
return 0;
} else {
return 1 /* unsupported */; return 1 /* unsupported */;
} }
} }
@ -99,6 +117,7 @@ struct discovery {
char *buf; char *buf;
size_t len; size_t len;
struct ref *refs; struct ref *refs;
struct sha1_array shallow;
unsigned proto_git : 1; unsigned proto_git : 1;
}; };
static struct discovery *last_discovery; static struct discovery *last_discovery;
@ -107,7 +126,7 @@ static struct ref *parse_git_refs(struct discovery *heads, int for_push)
{ {
struct ref *list = NULL; struct ref *list = NULL;
get_remote_heads(-1, heads->buf, heads->len, &list, get_remote_heads(-1, heads->buf, heads->len, &list,
for_push ? REF_NORMAL : 0, NULL, NULL); for_push ? REF_NORMAL : 0, NULL, &heads->shallow);
return list; return list;
} }
@ -168,6 +187,7 @@ static void free_discovery(struct discovery *d)
if (d) { if (d) {
if (d == last_discovery) if (d == last_discovery)
last_discovery = NULL; last_discovery = NULL;
free(d->shallow.sha1);
free(d->buf_alloc); free(d->buf_alloc);
free_refs(d->refs); free_refs(d->refs);
free(d); free(d);
@ -688,7 +708,7 @@ static int fetch_git(struct discovery *heads,
struct strbuf preamble = STRBUF_INIT; struct strbuf preamble = STRBUF_INIT;
char *depth_arg = NULL; char *depth_arg = NULL;
int argc = 0, i, err; int argc = 0, i, err;
const char *argv[16]; const char *argv[17];
argv[argc++] = "fetch-pack"; argv[argc++] = "fetch-pack";
argv[argc++] = "--stateless-rpc"; argv[argc++] = "--stateless-rpc";
@ -704,6 +724,10 @@ static int fetch_git(struct discovery *heads,
} }
if (options.check_self_contained_and_connected) if (options.check_self_contained_and_connected)
argv[argc++] = "--check-self-contained-and-connected"; argv[argc++] = "--check-self-contained-and-connected";
if (options.cloning)
argv[argc++] = "--cloning";
if (options.update_shallow)
argv[argc++] = "--update-shallow";
if (!options.progress) if (!options.progress)
argv[argc++] = "--no-progress"; argv[argc++] = "--no-progress";
if (options.depth) { if (options.depth) {

View File

@ -173,4 +173,31 @@ EOF
) )
' '
if test -n "$NO_CURL" -o -z "$GIT_TEST_HTTPD"; then
say 'skipping remaining tests, git built without http support'
test_done
fi
LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5536'}
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
test_expect_success 'clone http repository' '
git clone --bare --no-local shallow "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
git clone $HTTPD_URL/smart/repo.git clone &&
(
cd clone &&
git fsck &&
git log --format=%s origin/master >actual &&
cat <<EOF >expect &&
6
5
4
3
EOF
test_cmp expect actual
)
'
stop_httpd
test_done test_done

View File

@ -360,6 +360,12 @@ static int fetch_with_fetch(struct transport *transport,
data->transport_options.check_self_contained_and_connected) data->transport_options.check_self_contained_and_connected)
set_helper_option(transport, "check-connectivity", "true"); set_helper_option(transport, "check-connectivity", "true");
if (transport->cloning)
set_helper_option(transport, "cloning", "true");
if (data->transport_options.update_shallow)
set_helper_option(transport, "update-shallow", "true");
for (i = 0; i < nr_heads; i++) { for (i = 0; i < nr_heads; i++) {
const struct ref *posn = to_fetch[i]; const struct ref *posn = to_fetch[i];
if (posn->status & REF_STATUS_UPTODATE) if (posn->status & REF_STATUS_UPTODATE)

View File

@ -836,8 +836,6 @@ int main(int argc, char **argv)
if (!enter_repo(dir, strict)) if (!enter_repo(dir, strict))
die("'%s' does not appear to be a git repository", dir); die("'%s' does not appear to be a git repository", dir);
if (is_repository_shallow() && stateless_rpc)
die("attempt to push into a shallow repository");
git_config(upload_pack_config, NULL); git_config(upload_pack_config, NULL);
upload_pack(); upload_pack();