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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
#! /bin/sh -e
url=$1
rev=$2
expHash=$3
hashType=$NIX_HASH_ALGO
if test -z "$hashType"; then
hashType=sha256
fi
if test -z "$url"; then
echo "syntax: nix-prefetch-git URL [REVISION [EXPECTED-HASH]]" >&2
exit 1
fi
# If the hash was given, a file with that hash may already be in the
# store.
if test -n "$expHash"; then
finalPath=$(nix-store --print-fixed-path --recursive "$hashType" "$expHash" git-export)
if ! nix-store --check-validity "$finalPath" 2> /dev/null; then
finalPath=
fi
hash=$expHash
fi
init_remote(){
local url=$1;
git init;
git remote add origin $url;
}
# Return the reference of an hash if it exists on the remote repository.
ref_from_hash(){
local hash=$1;
git ls-remote origin | sed -n "\,$hash\t, { s,\(.*\)\t\(.*\),\2,; p; q}"
}
# Return the hash of a reference if it exists on the remote repository.
hash_from_ref(){
local ref=$1
git ls-remote origin | sed -n "\,\t$ref, { s,\(.*\)\t\(.*\),\1,; p; q}"
}
# Fetch everything and checkout the right sha1
checkout_hash(){
local hash="$1";
local ref="$2";
if test -z "$hash"; then
hash=$(hash_from_ref $ref);
fi;
git fetch origin || return 1
git checkout $hash || return 1
}
# Fetch only a branch/tag and checkout it.
checkout_ref(){
local hash="$1";
local ref="$2";
if test -n "$NIX_PREFETCH_GIT_DEEP_CLONE"; then
# The caller explicitly asked for a deep clone. Deep clones
# allow "git describe" and similar tools to work. See
# http://thread.gmane.org/gmane.linux.distributions.nixos/3569
# for a discussion.
return 1
fi
if test -z "$ref"; then
ref=$(ref_from_hash $hash);
fi;
if test -n "$ref"; then
# --depth option is ignored on http repository.
git fetch --depth 1 origin +"$ref" || return 1
git checkout FETCH_HEAD || return 1
else
return 1;
fi;
}
# Update submodules
init_submodules(){
# Add urls into .git/config file
git submodule init
# list submodule directories and their hashes
git submodule status |
while read l; do
# checkout each submodule
local hash=$(echo $l | sed 's,^-\([0-9a-f]*\) \(.*\)$,\1,');
local dir=$(echo $l | sed 's,^-\([0-9a-f]*\) \(.*\)$,\2,');
local url=$(sed -n "\,$dir, { :loop; n; s,^.*url = ,,; T loop; p; q }" .git/config);
clone "$dir" "$url" "$hash" "";
done;
}
clone(){
local top=$(pwd)
local dir="$1"
local url="$2"
local hash="$3"
local ref="$4"
cd $dir;
# Initialize the repository.
init_remote "$url";
# Download data from the repository.
checkout_ref "$hash" "$ref" ||
checkout_hash "$hash" "$ref" || (
echo 1>&2 "Unable to checkout $hash$ref from $url.";
exit 1;
)
# Checkout linked sources.
init_submodules;
if [ -f .topdeps ]; then
if tg help 2>&1 > /dev/null
then
echo "populating TopGit branches..."
tg remote --populate origin
else
echo "WARNING: would populate TopGit branches but TopGit is not available" >&2
echo "WARNING: install TopGit to fix the problem" >&2
fi
fi
cd $top;
}
# If we don't know the hash or a path with that hash doesn't exist,
# download the file and add it to the store.
if test -z "$finalPath"; then
tmpPath=/tmp/git-checkout-tmp-$$
tmpFile=$tmpPath/git-export
mkdir $tmpPath $tmpFile
trap "rm -rf $tmpPath" EXIT
# Perform the checkout.
case "$rev" in
HEAD|refs/*)
clone "$tmpFile" "$url" "" "$rev" 1>&2;;
[0-9a-f]*)
if test -z "$(echo $rev | tr -d 0123456789abcdef)"; then
clone "$tmpFile" "$url" "$rev" "" 1>&2;
else
echo 1>&2 "Bad commit hash or bad reference.";
exit 1;
fi;;
"")
clone "$tmpFile" "$url" "" "HEAD" 1>&2;;
esac
# Allow doing additional processing before .git removal
eval "$NIX_PREFETCH_GIT_CHECKOUT_HOOK"
if test "$NIX_PREFETCH_GIT_LEAVE_DOT_GIT" != 1
then
echo "removing \`.git'..." >&2
rm -rf $tmpFile/.git
fi
# Compute the hash.
hash=$(nix-hash --type $hashType $hashFormat $tmpFile)
if ! test -n "$QUIET"; then echo "hash is $hash" >&2; fi
# Add the downloaded file to the Nix store.
finalPath=$(nix-store --add-fixed --recursive "$hashType" $tmpFile)
if test -n "$expHash" -a "$expHash" != "$hash"; then
echo "hash mismatch for URL \`$url'"
exit 1
fi
fi
if ! test -n "$QUIET"; then echo "path is $finalPath" >&2; fi
echo $hash
if test -n "$PRINT_PATH"; then
echo $finalPath
fi
|