diff options
Diffstat (limited to 'git-clone.sh')
-rwxr-xr-x | git-clone.sh | 166 |
1 files changed, 108 insertions, 58 deletions
diff --git a/git-clone.sh b/git-clone.sh index d45618d9af..18003ab4b3 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -2,7 +2,7 @@ # # Copyright (c) 2005, Linus Torvalds # Copyright (c) 2005, Junio C Hamano -# +# # Clone a repository into a different directory that does not yet exist. # See git-sh-setup why. @@ -43,7 +43,7 @@ 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" || @@ -72,11 +72,22 @@ Perhaps git-update-server-info needs to be run there?" rm -fr "$clone_tmp" http_fetch "$1/HEAD" "$GIT_DIR/REMOTE_HEAD" || rm -f "$GIT_DIR/REMOTE_HEAD" + if test -f "$GIT_DIR/REMOTE_HEAD"; then + head_sha1=`cat "$GIT_DIR/REMOTE_HEAD"` + case "$head_sha1" in + 'ref: refs/'*) + ;; + *) + git-http-fetch $v -a "$head_sha1" "$1" || + rm -f "$GIT_DIR/REMOTE_HEAD" + ;; + esac + fi } quiet= local=no -use_local=no +use_local_hardlink=yes local_shared=no unset template no_checkout= @@ -88,6 +99,7 @@ origin_override= use_separate_remote=t depth= no_progress= +local_explicitly_asked_for= test -t 1 || no_progress=--no-progress while case "$#,$1" in @@ -97,9 +109,14 @@ while no_checkout=yes ;; *,--na|*,--nak|*,--nake|*,--naked|\ *,-b|*,--b|*,--ba|*,--bar|*,--bare) bare=yes ;; - *,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;; - *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared) - local_shared=yes; 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; ;; 1,--template) usage ;; *,--template) shift; template="--template=$1" ;; @@ -121,7 +138,7 @@ while */*) 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." @@ -176,15 +193,36 @@ dir="$2" # 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 ${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 @@ -222,34 +260,37 @@ 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." - - 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) + die "cannot chdir to local '$repo/objects'." - # 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 + 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 ;; *) @@ -334,11 +375,15 @@ then *) 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 @@ -377,37 +422,42 @@ then ) ) + # Upstream URL + git config remote."$origin".url "$repo" && + + # Set up the mappings to track the remote branches. + 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. - origin_track="$remote_top/$head_points_at" && - git-update-ref HEAD "$head_sha1" && - - # Upstream URL - git-config remote."$origin".url "$repo" && + git update-ref HEAD "$head_sha1" && - # Set up the mappings to track the remote branches. - git-config remote."$origin".fetch \ - "+refs/heads/*:$remote_top/*" '^$' && 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" && + 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" trap - 0 - |