4f87aa7db5
Currently, there are two failure paths in the wrapper: - if the tar fails, then the error is ignored because it is on the left-hand-side of a pipe; - if the find fails, then the error is ignored because it is a process substitution (and there is a pipe, too). While the former could be fixed with "set -o pipefail", the latter can not be fixed thusly and we must use an intemediate file for it. So, fix both issues by using intermediate files, both to generate the list of files to include in the archive, and generate the archive in a temporary tarball. Fixes the following build issue, where the find is failing for whatever unknown reason: http://autobuild.buildroot.net/results/20f/20fd76d2256eee81837f7e9bbaefbe79d7645ae9/ And this one, where the process substitution failed, also for an unknown reason: http://autobuild.buildroot.org/results/018/018971ea9227b386fe25d3c264c7e80b843a9f68/ Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
100 lines
3.1 KiB
Bash
Executable File
100 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# We want to catch any unexpected failure, and exit immediately
|
|
set -e
|
|
|
|
# Download helper for git, to be called from the download wrapper script
|
|
#
|
|
# Call it as:
|
|
# .../git [-q] [-r] OUT_FILE REPO_URL CSET BASENAME
|
|
#
|
|
# -q Be quiet.
|
|
# -r Clone and archive sub-modules.
|
|
#
|
|
# Environment:
|
|
# GIT : the git command to call
|
|
|
|
verbose=
|
|
recurse=0
|
|
while getopts :qr OPT; do
|
|
case "${OPT}" in
|
|
q) verbose=-q; exec >/dev/null;;
|
|
r) recurse=1;;
|
|
\?) printf "unknown option '%s'\n" "${OPTARG}" >&2; exit 1;;
|
|
esac
|
|
done
|
|
shift $((OPTIND-1))
|
|
|
|
output="${1}"
|
|
repo="${2}"
|
|
cset="${3}"
|
|
basename="${4}"
|
|
|
|
shift 4 # Get rid of our options
|
|
|
|
# Caller needs to single-quote its arguments to prevent them from
|
|
# being expanded a second time (in case there are spaces in them)
|
|
_git() {
|
|
eval ${GIT} "${@}"
|
|
}
|
|
|
|
# Try a shallow clone, since it is faster than a full clone - but that only
|
|
# works if the version is a ref (tag or branch). Before trying to do a shallow
|
|
# clone we check if ${cset} is in the list provided by git ls-remote. If not
|
|
# we fall back on a full clone.
|
|
#
|
|
# Messages for the type of clone used are provided to ease debugging in case of
|
|
# problems
|
|
git_done=0
|
|
if [ -n "$(_git ls-remote "'${repo}'" "'${cset}'" 2>&1)" ]; then
|
|
printf "Doing shallow clone\n"
|
|
if _git clone ${verbose} "${@}" --depth 1 -b "'${cset}'" "'${repo}'" "'${basename}'"; then
|
|
git_done=1
|
|
else
|
|
printf "Shallow clone failed, falling back to doing a full clone\n"
|
|
fi
|
|
fi
|
|
if [ ${git_done} -eq 0 ]; then
|
|
printf "Doing full clone\n"
|
|
_git clone ${verbose} "${@}" "'${repo}'" "'${basename}'"
|
|
fi
|
|
|
|
pushd "${basename}" >/dev/null
|
|
|
|
# Try to get the special refs exposed by some forges (pull-requests for
|
|
# github, changes for gerrit...). There is no easy way to know whether
|
|
# the cset the user passed us is such a special ref or a tag or a sha1
|
|
# or whatever else. We'll eventually fail at checking out that cset,
|
|
# below, if there is an issue anyway. Since most of the cset we're gonna
|
|
# have to clone are not such special refs, consign the output to oblivion
|
|
# so as not to alarm unsuspecting users, but still trace it as a warning.
|
|
if ! _git fetch origin "'${cset}:${cset}'" >/dev/null 2>&1; then
|
|
printf "Could not fetch special ref '%s'; assuming it is not special.\n" "${cset}"
|
|
fi
|
|
|
|
# Checkout the required changeset, so that we can update the required
|
|
# submodules.
|
|
_git checkout -q "'${cset}'"
|
|
|
|
# Get date of commit to generate a reproducible archive.
|
|
# %cD is RFC2822, so it's fully qualified, with TZ and all.
|
|
date="$( _git log -1 --pretty=format:%cD )"
|
|
|
|
# There might be submodules, so fetch them.
|
|
if [ ${recurse} -eq 1 ]; then
|
|
_git submodule update --init --recursive
|
|
fi
|
|
|
|
# We do not need the .git dir; we keep other .git files, in case they
|
|
# are the only files in their directory.
|
|
rm -rf .git
|
|
|
|
popd >/dev/null
|
|
|
|
# Generate the archive, sort with the C locale so that it is reproducible
|
|
find "${basename}" -not -type d >"${basename}.list"
|
|
LC_ALL=C sort <"${basename}.list" >"${basename}.list.sorted"
|
|
tar cf - --numeric-owner --owner=0 --group=0 --mtime="${date}" \
|
|
-T "${basename}.list.sorted" >"${output}.tar"
|
|
gzip -n <"${output}.tar" >"${output}"
|