5d6ec40b75
The removal of the .git dir before creating the tarball is not anymore just an optimization. It is necessary to make the tarball reproducible. Also, without the removal, large tarballs (gigabytes) would be created for some linux trees. Update the comment accordingly. Reported-by: Baruch Siach <baruch@tkos.co.il> Signed-off-by: Ricardo Martincoski <ricardo.martincoski@gmail.com> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
105 lines
3.5 KiB
Bash
Executable File
105 lines
3.5 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 want the .git dir; we keep other .git files, in case they
|
|
# are the only files in their directory.
|
|
# The .git dir would generate non reproducible tarballs as it depends on
|
|
# the state of the remote server. It also would generate large tarballs
|
|
# (gigabytes for some linux trees) when a full clone took place.
|
|
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"
|
|
# Create GNU-format tarballs, since that's the format of the tarballs on
|
|
# sources.buildroot.org and used in the *.hash files
|
|
tar cf - --numeric-owner --owner=0 --group=0 --mtime="${date}" --format=gnu \
|
|
-T "${basename}.list.sorted" >"${output}.tar"
|
|
gzip -n <"${output}.tar" >"${output}"
|