Merge branch 'jc/clone'
* jc/clone: git-clone: aggressively optimize local clone behaviour. connect: accept file:// URL scheme
This commit is contained in:
commit
fa548703d1
@ -9,7 +9,8 @@ git-clone - Clone a repository into a new directory
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-clone' [--template=<template_directory>] [-l [-s]] [-q] [-n] [--bare]
|
||||
'git-clone' [--template=<template_directory>]
|
||||
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare]
|
||||
[-o <name>] [-u <upload-pack>] [--reference <repository>]
|
||||
[--depth <depth>] <repository> [<directory>]
|
||||
|
||||
@ -40,8 +41,19 @@ OPTIONS
|
||||
this flag bypasses normal "git aware" transport
|
||||
mechanism and clones the repository by making a copy of
|
||||
HEAD and everything under objects and refs directories.
|
||||
The files under .git/objects/ directory are hardlinked
|
||||
to save space when possible.
|
||||
The files under `.git/objects/` directory are hardlinked
|
||||
to save space when possible. This is now the default when
|
||||
the source repository is specified with `/path/to/repo`
|
||||
syntax, so it essentially is a no-op option. To force
|
||||
copying instead of hardlinking (which may be desirable
|
||||
if you are trying to make a back-up of your repository),
|
||||
but still avoid the usual "git aware" transport
|
||||
mechanism, `--no-hardlinks` can be used.
|
||||
|
||||
--no-hardlinks::
|
||||
Optimize the cloning process from a repository on a
|
||||
local filesystem by copying files under `.git/objects`
|
||||
directory.
|
||||
|
||||
--shared::
|
||||
-s::
|
||||
|
@ -15,11 +15,11 @@ to name the remote repository:
|
||||
- ssh://{startsb}user@{endsb}host.xz/~/path/to/repo.git
|
||||
===============================================================
|
||||
|
||||
SSH is the default transport protocol. You can optionally specify
|
||||
which user to log-in as, and an alternate, scp-like syntax is also
|
||||
supported. Both syntaxes support username expansion,
|
||||
as does the native git protocol. The following three are
|
||||
identical to the last three above, respectively:
|
||||
SSH is the default transport protocol over the network. You can
|
||||
optionally specify which user to log-in as, and an alternate,
|
||||
scp-like syntax is also supported. Both syntaxes support
|
||||
username expansion, as does the native git protocol. The following
|
||||
three are identical to the last three above, respectively:
|
||||
|
||||
===============================================================
|
||||
- {startsb}user@{endsb}host.xz:/path/to/repo.git/
|
||||
@ -27,8 +27,12 @@ identical to the last three above, respectively:
|
||||
- {startsb}user@{endsb}host.xz:path/to/repo.git
|
||||
===============================================================
|
||||
|
||||
To sync with a local directory, use:
|
||||
To sync with a local directory, you can use:
|
||||
|
||||
===============================================================
|
||||
- /path/to/repo.git/
|
||||
- file:///path/to/repo.git/
|
||||
===============================================================
|
||||
|
||||
They are mostly equivalent, except when cloning. See
|
||||
gitlink:git-clone[1] for details.
|
||||
|
12
connect.c
12
connect.c
@ -145,6 +145,8 @@ static enum protocol get_protocol(const char *name)
|
||||
return PROTO_SSH;
|
||||
if (!strcmp(name, "ssh+git"))
|
||||
return PROTO_SSH;
|
||||
if (!strcmp(name, "file"))
|
||||
return PROTO_LOCAL;
|
||||
die("I don't handle protocol '%s'", name);
|
||||
}
|
||||
|
||||
@ -498,13 +500,13 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
|
||||
end = host;
|
||||
|
||||
path = strchr(end, c);
|
||||
if (c == ':') {
|
||||
if (path) {
|
||||
if (path) {
|
||||
if (c == ':') {
|
||||
protocol = PROTO_SSH;
|
||||
*path++ = '\0';
|
||||
} else
|
||||
path = host;
|
||||
}
|
||||
}
|
||||
} else
|
||||
path = end;
|
||||
|
||||
if (!path || !*path)
|
||||
die("No path specified. See 'man git-pull' for valid url syntax");
|
||||
|
64
git-clone.sh
64
git-clone.sh
@ -87,7 +87,7 @@ Perhaps git-update-server-info needs to be run there?"
|
||||
|
||||
quiet=
|
||||
local=no
|
||||
use_local=no
|
||||
use_local_hardlink=yes
|
||||
local_shared=no
|
||||
unset template
|
||||
no_checkout=
|
||||
@ -108,9 +108,13 @@ while
|
||||
no_checkout=yes ;;
|
||||
*,--na|*,--nak|*,--nake|*,--naked|\
|
||||
*,-b|*,--b|*,--ba|*,--bar|*,--bare) bare=yes ;;
|
||||
*,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;;
|
||||
*,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local)
|
||||
use_local_hardlink=yes ;;
|
||||
*,--no-h|*,--no-ha|*,--no-har|*,--no-hard|*,--no-hardl|\
|
||||
*,--no-hardli|*,--no-hardlin|*,--no-hardlink|*,--no-hardlinks)
|
||||
use_local_hardlink=no ;;
|
||||
*,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared)
|
||||
local_shared=yes; use_local=yes ;;
|
||||
local_shared=yes; ;;
|
||||
1,--template) usage ;;
|
||||
*,--template)
|
||||
shift; template="--template=$1" ;;
|
||||
@ -249,34 +253,36 @@ fi
|
||||
rm -f "$GIT_DIR/CLONE_HEAD"
|
||||
|
||||
# We do local magic only when the user tells us to.
|
||||
case "$local,$use_local" in
|
||||
yes,yes)
|
||||
case "$local" in
|
||||
yes)
|
||||
( cd "$repo/objects" ) ||
|
||||
die "-l flag seen but repository '$repo' is not local."
|
||||
die "cannot chdir to local '$repo/objects'."
|
||||
|
||||
case "$local_shared" in
|
||||
no)
|
||||
# See if we can hardlink and drop "l" if not.
|
||||
sample_file=$(cd "$repo" && \
|
||||
find objects -type f -print | sed -e 1q)
|
||||
|
||||
# objects directory should not be empty since we are cloning!
|
||||
test -f "$repo/$sample_file" || exit
|
||||
|
||||
l=
|
||||
if ln "$repo/$sample_file" "$GIT_DIR/objects/sample" 2>/dev/null
|
||||
then
|
||||
l=l
|
||||
fi &&
|
||||
rm -f "$GIT_DIR/objects/sample" &&
|
||||
cd "$repo" &&
|
||||
find objects -depth -print | cpio -pumd$l "$GIT_DIR/" || exit 1
|
||||
;;
|
||||
yes)
|
||||
mkdir -p "$GIT_DIR/objects/info"
|
||||
echo "$repo/objects" >> "$GIT_DIR/objects/info/alternates"
|
||||
;;
|
||||
esac
|
||||
if test "$local_shared" = yes
|
||||
then
|
||||
mkdir -p "$GIT_DIR/objects/info"
|
||||
echo "$repo/objects" >>"$GIT_DIR/objects/info/alternates"
|
||||
else
|
||||
l= &&
|
||||
if test "$use_local_hardlink" = yes
|
||||
then
|
||||
# See if we can hardlink and drop "l" if not.
|
||||
sample_file=$(cd "$repo" && \
|
||||
find objects -type f -print | sed -e 1q)
|
||||
# objects directory should not be empty because
|
||||
# we are cloning!
|
||||
test -f "$repo/$sample_file" || exit
|
||||
if ln "$repo/$sample_file" "$GIT_DIR/objects/sample" 2>/dev/null
|
||||
then
|
||||
rm -f "$GIT_DIR/objects/sample"
|
||||
l=l
|
||||
else
|
||||
echo >&2 "Warning: -l asked but cannot hardlink to $repo"
|
||||
fi
|
||||
fi &&
|
||||
cd "$repo" &&
|
||||
find objects -depth -print | cpio -pumd$l "$GIT_DIR/" || exit 1
|
||||
fi
|
||||
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
|
||||
;;
|
||||
*)
|
||||
|
@ -129,7 +129,7 @@ pull_to_client 2nd "B" $((64*3))
|
||||
|
||||
pull_to_client 3rd "A" $((1*3)) # old fails
|
||||
|
||||
test_expect_success "clone shallow" "git-clone --depth 2 . shallow"
|
||||
test_expect_success "clone shallow" "git-clone --depth 2 file://`pwd`/. shallow"
|
||||
|
||||
(cd shallow; git count-objects -v) > count.shallow
|
||||
|
||||
|
@ -51,7 +51,7 @@ diff expected current'
|
||||
cd "$base_dir"
|
||||
|
||||
test_expect_success 'cloning with reference (no -l -s)' \
|
||||
'git clone --reference B A D'
|
||||
'git clone --reference B file://`pwd`/A D'
|
||||
|
||||
cd "$base_dir"
|
||||
|
||||
|
@ -43,4 +43,21 @@ test_expect_success 'local clone from x.git that does not exist' '
|
||||
fi
|
||||
'
|
||||
|
||||
test_expect_success 'With -no-hardlinks, local will make a copy' '
|
||||
cd "$D" &&
|
||||
git clone --bare --no-hardlinks x w &&
|
||||
cd w &&
|
||||
linked=$(find objects -type f ! -links 1 | wc -l) &&
|
||||
test "$linked" = 0
|
||||
'
|
||||
|
||||
test_expect_success 'Even without -l, local will make a hardlink' '
|
||||
cd "$D" &&
|
||||
rm -fr w &&
|
||||
git clone -l --bare x w &&
|
||||
cd w &&
|
||||
copied=$(find objects -type f -links 1 | wc -l) &&
|
||||
test "$copied" = 0
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user