Fetch from a packed repository on dumb servers.
[git.git] / git-fetch-dumb-http
1 #!/bin/sh
2 #
3 # Copyright (c) 2005, Junio C Hamano
4 #
5 # Called by git-fetch-script
6 # Exits 2 when the remote site does not support dumb server protocol.
7
8 # Usage: git-fetch-dumb-http <head-SHA1> <repo> [ <head> | tag <tag> ]
9
10 . git-sh-setup-script || die "Not a git archive"
11 head="$1"
12 shift
13 . git-parse-remote "$@"
14
15 merge_repo="$_remote_repo"
16 merge_head="$_remote_head"
17 merge_store="$_remote_store"
18
19 if [ -n "$GIT_SSL_NO_VERIFY" ]; then
20     curl_extra_args="-k"
21 fi
22 http_fetch () {
23         # $1 = Remote, $2 = Local
24         curl -ns $curl_extra_args "$1" >"$2"
25 }
26
27 # Try dumb server protocol
28
29 clone_tmp=".git/clone-tmp$$" &&
30 mkdir -p "$clone_tmp" || exit 1
31 trap "rm -rf $clone_tmp" 0 1 2 3 15
32 http_fetch "$merge_repo/info/refs" "$clone_tmp/refs" &&
33 http_fetch "$merge_repo/objects/info/packs" "$clone_tmp/packs" &&
34 http_fetch "$merge_repo/info/rev-cache" "$clone_tmp/rev-cache" || exit 2
35
36 # Which packs are we interested in?
37 has_missing=,
38 while read tag num sha1 type
39 do
40     case "$tag" in
41     T) ;;
42     *) continue ;;
43     esac
44     git-cat-file -t "$sha1" >/dev/null || has_missing="$has_missing$num,"
45 done <$clone_tmp/packs
46
47 # Slurp the pack index we do not have all objects for.
48 pack_ix=0
49 may_want_pack_count=0
50 while read tag pack
51 do
52     case "$tag" in
53     P) ;;
54     *) break ;; # P records always come first.
55     esac
56     case "$has_missing" in
57     *",$pack_ix,"*)
58        name=`expr "$pack" : '\(.*\)\.pack$'` &&
59        idx="$name.idx" &&
60        http_fetch "$merge_repo/objects/pack/$idx" "$clone_tmp/$idx" &&
61        # Note that idx file is sorted --- otherwise we need to sort it here.
62        git-show-index <"$clone_tmp/$idx" |
63        sed -e 's/^[^ ]* //' >"$clone_tmp/$name.toc" ||
64        exit 1
65        may_want_pack_count=`expr "$may_want_pack_count" + 1`
66        ;;
67     esac
68     pack_ix=`expr "$pack_ix" + 1`
69 done <$clone_tmp/packs
70
71 case "$may_want_pack_count" in
72 0)
73     exit 0 ;;
74 esac
75
76 # We want $head.  What are the head objects we are missing?
77 git-missing-revs $clone_tmp/rev-cache $head >$clone_tmp/missing-revs &&
78 sort -o $clone_tmp/missing-revs $clone_tmp/missing-revs || exit 2
79
80 for toc in $clone_tmp/*.toc
81 do
82     name=`expr $toc : '.*/\([^/]*\)\.toc'` &&
83     comm -12 $clone_tmp/missing-revs $toc >$clone_tmp/$name.can
84     # FIXME: this is stupid.
85     if test -s $clone_tmp/$name.can
86     then
87         pack="$name.pack" idx="$name.idx" &&
88         http_fetch "$merge_repo/objects/pack/$pack" "$clone_tmp/$pack" &&
89         git-verify-pack "$clone_tmp/$pack" &&
90         mkdir -p "$GIT_OBJECT_DIRECTORY/pack" &&
91         mv "$clone_tmp/$pack" "$clone_tmp/$idx" \
92             "$GIT_OBJECT_DIRECTORY/pack/" || {
93             # remote may just have a stale dumb server information files.
94             # and normal pull might succeed.
95             exit 2
96         }
97     fi
98 done
99
100 exit 0