http_fetch () {
# $1 = Remote, $2 = Local
- curl -nsfL $curl_extra_args "$1" >"$2"
+ curl -nsfL $curl_extra_args "$1" >"$2" ||
+ case $? in
+ 126|127) exit ;;
+ *) return $? ;;
+ esac
}
clone_dumb_http () {
clone_tmp="$GIT_DIR/clone-tmp" &&
mkdir -p "$clone_tmp" || exit 1
if [ -n "$GIT_CURL_FTP_NO_EPSV" -o \
- "`git-config --bool http.noEPSV`" = true ]; then
+ "`git config --bool http.noEPSV`" = true ]; then
curl_extra_args="${curl_extra_args} --disable-epsv"
fi
http_fetch "$1/info/refs" "$clone_tmp/refs" ||
quiet=
local=no
-use_local=no
+use_local_hardlink=yes
local_shared=no
unset template
no_checkout=
use_separate_remote=t
depth=
no_progress=
+local_explicitly_asked_for=
test -t 1 || no_progress=--no-progress
while
case "$#,$1" in
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)
+ local_explicitly_asked_for=yes
+ 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" ;;
*/*)
die "'$2' is not suitable for an origin name"
esac
- git-check-ref-format "heads/$2" ||
+ git check-ref-format "heads/$2" ||
die "'$2' is not suitable for a branch name"
test -z "$origin_override" ||
die "Do not give more than one --origin options."
# Try using "humanish" part of source repo if user didn't specify one
[ -z "$dir" ] && dir=$(echo "$repo" | sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
[ -e "$dir" ] && die "destination directory '$dir' already exists."
-mkdir -p "$dir" &&
-D=$(cd "$dir" && pwd) &&
-trap 'err=$?; cd ..; rm -rf "$D"; exit $err' 0
-case "$bare" in
-yes)
- GIT_DIR="$D" ;;
-*)
- GIT_DIR="$D/.git" ;;
-esac && export GIT_DIR && git-init $quiet ${template+"$template"} || usage
+[ yes = "$bare" ] && unset GIT_WORK_TREE
+[ -n "$GIT_WORK_TREE" ] && [ -e "$GIT_WORK_TREE" ] &&
+die "working tree '$GIT_WORK_TREE' already exists."
+D=
+W=
+cleanup() {
+ err=$?
+ test -z "$D" && rm -rf "$dir"
+ test -z "$W" && test -n "$GIT_WORK_TREE" && rm -rf "$GIT_WORK_TREE"
+ cd ..
+ test -n "$D" && rm -rf "$D"
+ test -n "$W" && rm -rf "$W"
+ exit $err
+}
+trap cleanup 0
+mkdir -p "$dir" && D=$(cd "$dir" && pwd) || usage
+test -n "$GIT_WORK_TREE" && mkdir -p "$GIT_WORK_TREE" &&
+W=$(cd "$GIT_WORK_TREE" && pwd) && export GIT_WORK_TREE="$W"
+if test yes = "$bare" || test -n "$GIT_WORK_TREE"; then
+ GIT_DIR="$D"
+else
+ GIT_DIR="$D/.git"
+fi &&
+export GIT_DIR &&
+GIT_CONFIG="$GIT_DIR/config" git-init $quiet ${template+"$template"} || usage
+
+if test -n "$bare"
+then
+ GIT_CONFIG="$GIT_DIR/config" git config core.bare true
+fi
if test -n "$reference"
then
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."
-
- 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
+ die "cannot chdir to local '$repo/objects'."
- 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
+ elif test -n "$local_explicitly_asked_for"
+ then
+ 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
;;
*)
*)
continue ;;
esac
- git-update-ref -m "clone: from $repo" "$destname" "$sha1" ""
+ git update-ref -m "clone: from $repo" "$destname" "$sha1" ""
done < "$GIT_DIR/CLONE_HEAD"
fi
-cd "$D" || exit
+if test -n "$W"; then
+ cd "$W" || exit
+else
+ cd "$D" || exit
+fi
if test -z "$bare" && test -f "$GIT_DIR/REMOTE_HEAD"
then
)
# Upstream URL
- git-config remote."$origin".url "$repo" &&
+ git config remote."$origin".url "$repo" &&
# Set up the mappings to track the remote branches.
- git-config remote."$origin".fetch \
+ git config remote."$origin".fetch \
"+refs/heads/*:$remote_top/*" '^$' &&
# Write out remote.$origin config, and update our "$head_points_at".
case "$head_points_at" in
?*)
# Local default branch
- git-symbolic-ref HEAD "refs/heads/$head_points_at" &&
+ git symbolic-ref HEAD "refs/heads/$head_points_at" &&
# Tracking branch for the primary branch at the remote.
- git-update-ref HEAD "$head_sha1" &&
+ git update-ref HEAD "$head_sha1" &&
rm -f "refs/remotes/$origin/HEAD"
- git-symbolic-ref "refs/remotes/$origin/HEAD" \
+ git symbolic-ref "refs/remotes/$origin/HEAD" \
"refs/remotes/$origin/$head_points_at" &&
- git-config branch."$head_points_at".remote "$origin" &&
- git-config branch."$head_points_at".merge "refs/heads/$head_points_at"
+ git config branch."$head_points_at".remote "$origin" &&
+ git config branch."$head_points_at".merge "refs/heads/$head_points_at"
;;
'')
# Source had detached HEAD pointing nowhere
- git-update-ref --no-deref HEAD "$head_sha1" &&
+ git update-ref --no-deref HEAD "$head_sha1" &&
rm -f "refs/remotes/$origin/HEAD"
;;
esac
case "$no_checkout" in
'')
test "z$quiet" = z -a "z$no_progress" = z && v=-v || v=
- git-read-tree -m -u $v HEAD HEAD
+ git read-tree -m -u $v HEAD HEAD
esac
fi
rm -f "$GIT_DIR/CLONE_HEAD" "$GIT_DIR/REMOTE_HEAD"