diff options
author | Junio C Hamano <junkio@cox.net> | 2005-07-26 05:42:18 (GMT) |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2005-07-31 18:56:44 (GMT) |
commit | 96155e55e175e7fed1d8ebd73557d339f35629d8 (patch) | |
tree | beefc211f75f0fc195f8992d696353881fc9fa16 /git-fetch-dumb-http | |
parent | 80bd6f3064a6009cd18a4dab9ce6d29681cec4af (diff) | |
download | git-96155e55e175e7fed1d8ebd73557d339f35629d8.zip git-96155e55e175e7fed1d8ebd73557d339f35629d8.tar.gz git-96155e55e175e7fed1d8ebd73557d339f35629d8.tar.bz2 |
Fetch from a packed repository on dumb servers.
Implement fetching from a packed repository over http/https
using the dumb server support files.
I consider some parts of the logic should be in a separate C
program, but it appears to work with my simple tests. I have
backburnered it for a bit too long for my liking, so let's throw
it out in the open and see what happens.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'git-fetch-dumb-http')
-rwxr-xr-x | git-fetch-dumb-http | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/git-fetch-dumb-http b/git-fetch-dumb-http new file mode 100755 index 0000000..0034296 --- /dev/null +++ b/git-fetch-dumb-http @@ -0,0 +1,100 @@ +#!/bin/sh +# +# Copyright (c) 2005, Junio C Hamano +# +# Called by git-fetch-script +# Exits 2 when the remote site does not support dumb server protocol. + +# Usage: git-fetch-dumb-http <head-SHA1> <repo> [ <head> | tag <tag> ] + +. git-sh-setup-script || die "Not a git archive" +head="$1" +shift +. git-parse-remote "$@" + +merge_repo="$_remote_repo" +merge_head="$_remote_head" +merge_store="$_remote_store" + +if [ -n "$GIT_SSL_NO_VERIFY" ]; then + curl_extra_args="-k" +fi +http_fetch () { + # $1 = Remote, $2 = Local + curl -ns $curl_extra_args "$1" >"$2" +} + +# Try dumb server protocol + +clone_tmp=".git/clone-tmp$$" && +mkdir -p "$clone_tmp" || exit 1 +trap "rm -rf $clone_tmp" 0 1 2 3 15 +http_fetch "$merge_repo/info/refs" "$clone_tmp/refs" && +http_fetch "$merge_repo/objects/info/packs" "$clone_tmp/packs" && +http_fetch "$merge_repo/info/rev-cache" "$clone_tmp/rev-cache" || exit 2 + +# Which packs are we interested in? +has_missing=, +while read tag num sha1 type +do + case "$tag" in + T) ;; + *) continue ;; + esac + git-cat-file -t "$sha1" >/dev/null || has_missing="$has_missing$num," +done <$clone_tmp/packs + +# Slurp the pack index we do not have all objects for. +pack_ix=0 +may_want_pack_count=0 +while read tag pack +do + case "$tag" in + P) ;; + *) break ;; # P records always come first. + esac + case "$has_missing" in + *",$pack_ix,"*) + name=`expr "$pack" : '\(.*\)\.pack$'` && + idx="$name.idx" && + http_fetch "$merge_repo/objects/pack/$idx" "$clone_tmp/$idx" && + # Note that idx file is sorted --- otherwise we need to sort it here. + git-show-index <"$clone_tmp/$idx" | + sed -e 's/^[^ ]* //' >"$clone_tmp/$name.toc" || + exit 1 + may_want_pack_count=`expr "$may_want_pack_count" + 1` + ;; + esac + pack_ix=`expr "$pack_ix" + 1` +done <$clone_tmp/packs + +case "$may_want_pack_count" in +0) + exit 0 ;; +esac + +# We want $head. What are the head objects we are missing? +git-missing-revs $clone_tmp/rev-cache $head >$clone_tmp/missing-revs && +sort -o $clone_tmp/missing-revs $clone_tmp/missing-revs || exit 2 + +for toc in $clone_tmp/*.toc +do + name=`expr $toc : '.*/\([^/]*\)\.toc'` && + comm -12 $clone_tmp/missing-revs $toc >$clone_tmp/$name.can + # FIXME: this is stupid. + if test -s $clone_tmp/$name.can + then + pack="$name.pack" idx="$name.idx" && + http_fetch "$merge_repo/objects/pack/$pack" "$clone_tmp/$pack" && + git-verify-pack "$clone_tmp/$pack" && + mkdir -p "$GIT_OBJECT_DIRECTORY/pack" && + mv "$clone_tmp/$pack" "$clone_tmp/$idx" \ + "$GIT_OBJECT_DIRECTORY/pack/" || { + # remote may just have a stale dumb server information files. + # and normal pull might succeed. + exit 2 + } + fi +done + +exit 0 |