allow cloning a repository "shallowly"
By specifying a depth, you can now clone a repository such that all fetched ancestor-chains' length is at most "depth". For example, if the upstream repository has only 2 branches ("A" and "B"), which are linear, and you specify depth 3, you will get A, A~1, A~2, A~3, B, B~1, B~2, and B~3. The ends are automatically made shallow commits. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
ed09aef06f
commit
016e6ccbe0
61
fetch-pack.c
61
fetch-pack.c
@ -11,8 +11,9 @@ static int keep_pack;
|
||||
static int quiet;
|
||||
static int verbose;
|
||||
static int fetch_all;
|
||||
static int depth;
|
||||
static const char fetch_pack_usage[] =
|
||||
"git-fetch-pack [--all] [-q] [-v] [-k] [--thin] [--exec=upload-pack] [host:]directory <refs>...";
|
||||
"git-fetch-pack [--all] [-q] [-v] [-k] [--thin] [--exec=upload-pack] [--depth=<n>] [host:]directory <refs>...";
|
||||
static const char *exec = "git-upload-pack";
|
||||
|
||||
#define COMPLETE (1U << 0)
|
||||
@ -182,10 +183,29 @@ static int find_common(int fd[2], unsigned char *result_sha1,
|
||||
}
|
||||
if (is_repository_shallow())
|
||||
write_shallow_commits(fd[1], 1);
|
||||
if (depth > 0)
|
||||
packet_write(fd[1], "deepen %d", depth);
|
||||
packet_flush(fd[1]);
|
||||
if (!fetching)
|
||||
return 1;
|
||||
|
||||
if (depth > 0) {
|
||||
char line[1024];
|
||||
unsigned char sha1[20];
|
||||
int len;
|
||||
|
||||
while ((len = packet_read_line(fd[0], line, sizeof(line)))) {
|
||||
if (!strncmp("shallow ", line, 8)) {
|
||||
if (get_sha1_hex(line + 8, sha1))
|
||||
die("invalid shallow line: %s", line);
|
||||
/* no need making it shallow if we have it already */
|
||||
if (lookup_object(sha1))
|
||||
continue;
|
||||
register_shallow(sha1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flushes = 0;
|
||||
retval = -1;
|
||||
while ((sha1 = get_rev())) {
|
||||
@ -576,6 +596,8 @@ int main(int argc, char **argv)
|
||||
char *dest = NULL, **heads;
|
||||
int fd[2];
|
||||
pid_t pid;
|
||||
struct stat st;
|
||||
struct lock_file lock;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
@ -609,6 +631,12 @@ int main(int argc, char **argv)
|
||||
verbose = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp("--depth=", arg, 8)) {
|
||||
depth = strtol(arg + 8, NULL, 0);
|
||||
if (stat(git_path("shallow"), &st))
|
||||
st.st_mtime = 0;
|
||||
continue;
|
||||
}
|
||||
usage(fetch_pack_usage);
|
||||
}
|
||||
dest = arg;
|
||||
@ -618,6 +646,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if (!dest)
|
||||
usage(fetch_pack_usage);
|
||||
if (is_repository_shallow() && depth > 0)
|
||||
die("Deepening of a shallow repository not yet supported!");
|
||||
pid = git_connect(fd, dest, exec);
|
||||
if (pid < 0)
|
||||
return 1;
|
||||
@ -639,5 +669,34 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret && depth > 0) {
|
||||
struct cache_time mtime;
|
||||
char *shallow = git_path("shallow");
|
||||
int fd;
|
||||
|
||||
mtime.sec = st.st_mtime;
|
||||
#ifdef USE_NSEC
|
||||
mtime.usec = st.st_mtim.usec;
|
||||
#endif
|
||||
if (stat(shallow, &st)) {
|
||||
if (mtime.sec)
|
||||
die("shallow file was removed during fetch");
|
||||
} else if (st.st_mtime != mtime.sec
|
||||
#ifdef USE_NSEC
|
||||
|| st.st_mtim.usec != mtime.usec
|
||||
#endif
|
||||
)
|
||||
die("shallow file was changed during fetch");
|
||||
|
||||
fd = hold_lock_file_for_update(&lock, shallow, 1);
|
||||
if (!write_shallow_commits(fd, 0)) {
|
||||
unlink(lock.filename);
|
||||
rollback_lock_file(&lock);
|
||||
} else {
|
||||
close(fd);
|
||||
commit_lock_file(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
return !!ret;
|
||||
}
|
||||
|
19
git-clone.sh
19
git-clone.sh
@ -14,7 +14,7 @@ die() {
|
||||
}
|
||||
|
||||
usage() {
|
||||
die "Usage: $0 [--template=<template_directory>] [--use-immingled-remote] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [-n] <repo> [<dir>]"
|
||||
die "Usage: $0 [--template=<template_directory>] [--use-immingled-remote] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--depth <n>] [-n] <repo> [<dir>]"
|
||||
}
|
||||
|
||||
get_repo_base() {
|
||||
@ -116,6 +116,7 @@ reference=
|
||||
origin=
|
||||
origin_override=
|
||||
use_separate_remote=t
|
||||
depth=
|
||||
while
|
||||
case "$#,$1" in
|
||||
0,*) break ;;
|
||||
@ -161,6 +162,10 @@ while
|
||||
*,-u|*,--upload-pack)
|
||||
shift
|
||||
upload_pack="--exec=$1" ;;
|
||||
1,--depth) usage;;
|
||||
*,--depth)
|
||||
shift
|
||||
depth="--depth=$1";;
|
||||
*,-*) usage ;;
|
||||
*) break ;;
|
||||
esac
|
||||
@ -265,6 +270,10 @@ yes,yes)
|
||||
*)
|
||||
case "$repo" in
|
||||
rsync://*)
|
||||
case "$depth" in
|
||||
"") ;;
|
||||
*) die "shallow over rsync not supported" ;;
|
||||
esac
|
||||
rsync $quiet -av --ignore-existing \
|
||||
--exclude info "$repo/objects/" "$GIT_DIR/objects/" ||
|
||||
exit
|
||||
@ -293,6 +302,10 @@ yes,yes)
|
||||
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
|
||||
;;
|
||||
https://*|http://*|ftp://*)
|
||||
case "$depth" in
|
||||
"") ;;
|
||||
*) die "shallow over http or ftp not supported" ;;
|
||||
esac
|
||||
if test -z "@@NO_CURL@@"
|
||||
then
|
||||
clone_dumb_http "$repo" "$D"
|
||||
@ -302,8 +315,8 @@ yes,yes)
|
||||
;;
|
||||
*)
|
||||
case "$upload_pack" in
|
||||
'') git-fetch-pack --all -k $quiet "$repo" ;;
|
||||
*) git-fetch-pack --all -k $quiet "$upload_pack" "$repo" ;;
|
||||
'') git-fetch-pack --all -k $quiet $depth "$repo" ;;
|
||||
*) git-fetch-pack --all -k $quiet "$upload_pack" $depth "$repo" ;;
|
||||
esac >"$GIT_DIR/CLONE_HEAD" ||
|
||||
die "fetch-pack from '$repo' failed."
|
||||
;;
|
||||
|
@ -488,7 +488,7 @@ static void receive_needs(void)
|
||||
{
|
||||
struct object_array shallows = {0, 0, NULL};
|
||||
static char line[1000];
|
||||
int len;
|
||||
int len, depth = 0;
|
||||
|
||||
for (;;) {
|
||||
struct object *o;
|
||||
@ -509,6 +509,13 @@ static void receive_needs(void)
|
||||
add_object_array(object, NULL, &shallows);
|
||||
continue;
|
||||
}
|
||||
if (!strncmp("deepen ", line, 7)) {
|
||||
char *end;
|
||||
depth = strtol(line + 7, &end, 0);
|
||||
if (end == line + 7 || depth <= 0)
|
||||
die("Invalid deepen: %s", line);
|
||||
continue;
|
||||
}
|
||||
if (strncmp("want ", line, 5) ||
|
||||
get_sha1_hex(line+5, sha1_buf))
|
||||
die("git-upload-pack: protocol error, "
|
||||
@ -540,6 +547,18 @@ static void receive_needs(void)
|
||||
add_object_array(o, NULL, &want_obj);
|
||||
}
|
||||
}
|
||||
if (depth > 0) {
|
||||
struct commit_list *result, *backup;
|
||||
if (shallows.nr > 0)
|
||||
die("Deepening a shallow repository not yet supported");
|
||||
backup = result = get_shallow_commits(&want_obj, depth);
|
||||
while (result) {
|
||||
packet_write(1, "shallow %s",
|
||||
sha1_to_hex(result->item->object.sha1));
|
||||
result = result->next;
|
||||
}
|
||||
free_commit_list(backup);
|
||||
}
|
||||
if (shallows.nr > 0) {
|
||||
int i;
|
||||
for (i = 0; i < shallows.nr; i++)
|
||||
|
Loading…
Reference in New Issue
Block a user