aboutsummaryrefslogtreecommitdiff
path: root/git-fetch-dumb-http
blob: 0034296ac4986082793ed289d8546d57ed39408a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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