kumquat-buildroot/support/download/git
Yann E. MORIN 4f87aa7db5 support/download: make the git wrapper more robust
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>
2016-10-25 23:49:35 +02:00

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}"