aboutsummaryrefslogtreecommitdiff
path: root/lib/fetch.sh
blob: 201b733db3c5121465d55ebd09cdc95e7b29a3cd (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
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#!/bin/sh
# 
#   Copyright (C) 2013-2015 Linaro, Inc
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
# 

# Fetch a file from a remote machine.  All decision logic should be in this
# function, not in the fetch_<protocol> functions to avoid redundancy.
fetch()
{
    trace "$*"

    if test x"$1" = x; then
	error "No file name specified to fetch!"
	return 1
    fi

    local component=$1
    local getfile="`get_component_filespec ${component}`"
    local url="`get_component_url ${component}`"

    # This provides the infrastructure/ directory if ${getfile} contains it.
#    if test "`echo ${url} | grep -c infrastructure`" -gt 0; then
#	local dir="/infrastructure"
#    else
	local dir=""
#    fi

    # Forcing trumps ${supdate} and always results in sources being updated.
    if test x"${force}" != xyes; then
	if test x"${supdate}" = xno; then
	    if test -e "${local_snapshots}${dir}/${getfile}"; then
		notice "${getfile} already exists and updating has been disabled."
		return 0
	    fi
	    error "${getfile} doesn't exist and updating has been disabled."
	    return 1
	fi
	# else we'll update the file if the version in the reference dir or on
	# the server is newer than the local copy (if it exists).
    fi

    # If the user has specified a git_reference_dir, then we'll use it if the
    # file exists in the reference dir.
    if test -e "${git_reference_dir}${dir}/${getfile}" -a x"${force}" != xyes; then
	# This will always fetch if the version in the reference dir is newer.
	local protocol=reference
    else
	# Otherwise attempt to fetch remotely.
	local protocol=http
    fi

    # download from the file server or copy the file from the reference dir
    fetch_${protocol} ${component}
    if test $? -gt 0; then
	return 1
    fi

    # Fetch only supports fetching files which have an entry in the md5sums file.
    # An unlisted file should never get this far anyway.
    dryrun "check_md5sum ${component}"
    if test $? -gt 0; then
	  error "md5sums don't match!"
      if test x"${force}" != xyes; then
	    return 1
      fi
    fi

    notice "md5sums matched"
    return 0
}

# decompress and untar a fetched tarball
extract()
{
    trace "$*"

    local extractor=
    local taropt=
    local component=$1

    local url="`get_component_url ${component}`"
#    if test "`echo ${url} | grep -c infrastructure`" -gt 0; then
#	local dir="/infrastructure/"
#    else
	local dir=""
#    fi
    local file="`get_component_filespec ${component}`"
    local srcdir="`get_component_srcdir ${component}`"
    local version="`basename ${srcdir}`"

    local stamp=
    stamp="`get_stamp_name extract ${version}`"

    # Extract stamps go into srcdir
    local stampdir="${local_snapshots}${dir}"

    # Name of the downloaded tarball.
    local tarball="${local_snapshots}${dir}/${file}"

    # Initialize component data structures
    local builddir="`get_component_builddir ${component}`"

    local ret=
    # If the tarball hasn't changed, then we don't need to extract anything.
    check_stamp "${stampdir}" ${stamp} ${tarball} extract ${force}
    ret=$?
    if test $ret -eq 0; then
    	return 0
    elif test $ret -eq 255; then
    	# the ${tarball} isn't present.
    	return 1
    fi

    # Figure out how to decompress a tarball
    case "${file}" in
    	*.xz)
    	    local extractor="xz -d "
    	    local taropt="J"
    	    ;;
    	*.bz*)
    	    local extractor="bzip2 -d "
    	    local taropt="j"
    	    ;;
    	*.gz)
    	    local extractor="gunzip "
    	    local taropt="x"
    	    ;;
    	*) ;;
    esac

    local taropts="${taropt}xf"
    notice "Extracting from ${tarball}."
    dryrun "tar ${taropts} ${tarball} -C `dirname ${srcdir}`"

    # FIXME: this is hopefully a temporary hack for tarballs where the
    # directory name versions doesn't match the tarball version. This means
    # it's missing the -linaro-VERSION.YYYY.MM part.
    local name="`echo ${file} | sed -e 's:.tar\..*::'`"

    # dryrun has to skip this step otherwise execution will always drop into
    # this leg.
    if test x"${dryrun}" != xyes -a ! -d ${srcdir}; then
    	local dir2="`echo ${name} | sed -e 's:-linaro::' -e 's:-201[0-9\.\-]*::'`"
    	if test ! -d ${srcdir}; then
    	    dir2="${srcdir}/${dir2}"
    	    warning "${tarball} didn't extract to ${srcdir} as expected!"
    	    notice "Making a symbolic link from ${dir2} to ${srcdir}!"
    	    dryrun "ln -sf ${dir2} ${srcdir}"
    	else
    	    error "${srcdir} already exists!"
    	    return 1
    	fi
    fi

    create_stamp "${stampdir}" "${stamp}"
    return 0
}

# ---------------------------- private functions ------------------------------
# These functions are helper functions for fetch().  These are purpose specific
# functions and there should be little to no decision logic in these functions.
# Call these functions outside of fetch() with extreme caution.

# This function trusts that we know that we want to fetch a file from the
# server.  Unless $force=yes, wget will only download a copy if the version
# on the server is newer than the destination file.
fetch_http()
{
    trace "$*"

    local component=$1
    local getfile="`get_component_filespec ${component}`"
    if test x"${getfile}" = x; then
	error "No filespec specified for ${component} !"
	return 1
    fi
    local url="`get_component_url ${component}`/${getfile}"

    if test x"${url}" = x; then
	error "No URL specified for ${component} !"
	return 1
    fi

    # This provides the infrastructure/ directory if ${getfile} contains it.
#    if test "`echo ${url} | grep -c infrastructure`" -gt 0; then
#	local dir="/infrastructure"
#    else
	local dir=""
#    fi
    if test ! -d ${local_snapshots}${dir}; then
	mkdir -p ${local_snapshots}${dir}
    fi

    # You MUST have " " around ${wget_bin} or test ! -x will
    # 'succeed' if ${wget_bin} is an empty string.
    if test ! -x "${wget_bin}"; then
	error "wget executable not available (or not executable)."
	return 1
    fi

    # Force will cause us to overwrite the version in local_snapshots unconditionally.
    local overwrite_or_timestamp=
    if test x${force} = xyes; then
	# This is the only way to explicitly overwrite the destination file
	# with wget.
	overwrite_or_timestamp="-O ${local_snapshots}/${getfile}"
        notice "Downloading ${getfile} to ${local_snapshots} unconditionally."
    else
	# We only every download if the version on the server is newer than
	# the local version.
	overwrite_or_timestamp="-N"
        notice "Downloading ${getfile} to ${local_snapshots} if version on server is newer than local version."
    fi

    # NOTE: the timeout is short, and we only try twice to access the
    # remote host. This is to improve performance when offline, or
    # the remote host is offline.
    dryrun "${wget_bin} ${wget_quiet:+-q} --timeout=${wget_timeout}${wget_progress_style:+ --progress=${wget_progress_style}} --tries=2 --directory-prefix=${local_snapshots}/${dir} ${url} ${overwrite_or_timestamp}"
    if test $? -gt 0; then
       error "${url} doesn't exist on the remote machine !"
       return 1
    fi
    if test x"${dryrun}" != xyes -a ! -s ${local_snapshots}${dir}/${getfile}; then
       warning "downloaded file ${getfile} has zero data!"
       return 1
    fi
    dryrun "${wget_bin} ${wget_quiet:+-q} --timeout=${wget_timeout}${wget_progress_style:+ --progress=${wget_progress_style}} --tries=2 --directory-prefix=${local_snapshots}/${dir} ${url}.asc ${overwrite_or_timestamp}"
    if test x"${dryrun}" != xyes -a ! -s ${local_snapshots}${dir}/${getfile}.asc; then
       warning "downloaded file ${getfile}.asc has zero data!"
    fi

    return 0
}

# This function trusts that we know that we want to copy a file from the
# reference snapshots.  It only copies the file if the reference dir file is
# newer than the destination file (or if the destination file doesn't exist).
# If ${force}=yes then it will overwrite any existing file in local_snapshots
# whether it is newer or not.
fetch_reference()
{
    trace "$*"

    local getfile=$1
    local url="`get_component_url ${getfile}`"

    # Prevent error with empty variable-expansion.
    if test x"${getfile}" = x""; then
	error "fetch_reference() must be called with a parameter designating the file to fetch."
	return 1
    fi

    # This provides the infrastructure/ directory if ${getfile} contains it.
#    if test "`echo ${url} | grep -c infrastructure`" -gt 0; then
#	local dir="/infrastructure/"
#    else
	local dir=""
#    fi
    if test x"${dir}" = x"./"; then
	local dir=""
    else
	if test ! -d ${local_snapshots}/${dir}; then
	    mkdir -p ${local_snapshots}/${dir}
	fi
    fi

    # Force will cause an overwrite.
    if test x"${force}" != xyes; then
	local update_on_change="-u"
	notice "Copying ${getfile} from reference dir to ${local_snapshots} if reference copy is newer or ${getfile} doesn't exist."
    else
	notice "Copying ${getfile} from reference dir to ${local_snapshots} unconditionally."
    fi

    # Only copy if the source file in the reference dir is newer than
    # that file in the local_snapshots directory (if it exists).
    dryrun "cp${update_on_change:+ ${update_on_change}} ${git_reference_dir}${dir}/${getfile}*.tar.* ${local_snapshots}${dir}/"
    if test $? -gt 0; then
	error "Copying ${getfile} from reference dir to ${local_snapshots}${dir} failed."
	return 1
    fi
    return 0
}

# This is a single purpose function which will report whether the input getfile
# in $1 has an entry in the md5sum file and whether that entry's md5sum matches
# the actual file's downloaded md5sum.
check_md5sum()
{
    trace "$*"

    local tool="`basename $1`"

    local file="`get_component_filespec ${tool}`.asc"
    local url="`get_component_url ${tool}`"

#    if test "`echo ${url} | grep -c infrastructure`" -gt 0; then
#	local dir="/infrastructure/"
#    else
	local dir=""
#    fi

    if test ! -e "${local_snapshots}${dir}/${file}"; then
        error "No md5sum file for ${tool}!"
        return 1
    fi

    # Ask md5sum to verify the md5sum of the downloaded file against the hash in
    # the index.  md5sum must be executed from the snapshots directory.
    pushd ${local_snapshots}${dir} &>/dev/null
    dryrun "md5sum --status --check ${file}"
    md5sum_ret=$?
    popd &>/dev/null

    return $md5sum_ret
}