diff options
Diffstat (limited to 'scripts/functions')
-rw-r--r-- | scripts/functions | 160 |
1 files changed, 130 insertions, 30 deletions
diff --git a/scripts/functions b/scripts/functions index 0b8fba5..ab235d8 100644 --- a/scripts/functions +++ b/scripts/functions @@ -13,7 +13,7 @@ CT_LoadConfig() { # It also sets KERNEL/ARCH/... for file inclusion below. Does not handle # recursive definitions yet. We don't need arrays at this point. CT_TestOrAbort "Configuration file not found. Please create one." -r .config - . .config + . ./.config # Prefixing with ./ prevents Bash from searching $PATH # Include sub-scripts instead of calling them: that way, we do not have to # export any variable, nor re-parse the configuration and functions files. @@ -37,7 +37,7 @@ CT_LoadConfig() { oldvals="" try=0 while [ "$try" -le 10 ]; do - . .config + . ./.config # Prefixing with ./ prevents Bash from searching $PATH vals=`set | ${grep} -E '^CT_'` if [ "$oldvals" = "$vals" ]; then break @@ -287,6 +287,7 @@ CT_DoLog() { y,*"warning:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};; y,*"WARNING:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};; *"error:"*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};; + *"Error:"*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};; *"make["*"]: ***"*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};; *) cur_L="${LEVEL}"; cur_l="${level}";; esac @@ -751,7 +752,9 @@ CT_DoGetFile() } # This function saves the specified to local storage if possible, -# and if so, symlinks it for later usage +# and if so, symlinks it for later usage. This function is called from +# the `if' condition (via the CT_GetFile) and therefore must return +# on error rather than relying on the shell's ERR trap to catch it. # Usage: CT_SaveLocal </full/path/file.name> CT_SaveLocal() { @@ -761,9 +764,22 @@ CT_SaveLocal() if [ "${CT_SAVE_TARBALLS}" = "y" ]; then CT_DoLog EXTRA "Saving '${basename}' to local storage" # The file may already exist if downloads are forced: remove it first - CT_DoExecLog ALL rm -f "${CT_LOCAL_TARBALLS_DIR}/${basename}" - CT_DoExecLog ALL mv -f "${file}" "${CT_LOCAL_TARBALLS_DIR}" - CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}" "${file}" + if ! CT_DoExecLog ALL rm -f "${CT_LOCAL_TARBALLS_DIR}/${basename}"; then + return 1 + fi + if ! CT_DoExecLog ALL mv -f "${file}" "${CT_LOCAL_TARBALLS_DIR}"; then + # Move may have failed if the local tarball storage is on a different + # filesystem. Fallback to copy+delete. + if ! CT_DoExecLog ALL cp -f "${file}" "${CT_LOCAL_TARBALLS_DIR}"; then + return 1 + fi + if ! CT_DoExecLog ALL rm -f "${file}"; then + return 1 + fi + fi + if ! CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${basename}" "${file}"; then + return 1 + fi fi } @@ -886,7 +902,12 @@ CT_DoVerifySignature() CT_Popd # If we get here, verification succeeded. - CT_SaveLocal "${CT_TARBALLS_DIR}/${sigfile}${ext}" + if ! CT_SaveLocal "${CT_TARBALLS_DIR}/${sigfile}${ext}"; then + CT_Popd + return 1 + fi + + return 0 } # Download the file from one of the URLs passed as argument @@ -971,7 +992,9 @@ CT_GetFile() CT_DoExecLog ALL rm "${CT_TARBALLS_DIR}/${basename}${ext}" return 1 fi - CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}${ext}" + if ! CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}${ext}"; then + return 1 + fi return 0 fi done @@ -1003,9 +1026,15 @@ CT_DoConfigSub() { # Normally, each step is executed in a sub-shell and thus cannot modify the # environment for the next step(s). When this is needed, it can do so by # invoking this function. -# Usage: CT_EnvModify VAR VALUE +# Usage: CT_EnvModify [export] VAR VALUE CT_EnvModify() { - echo "${1}=\"${2}\"" >> "${CT_BUILD_DIR}/env.modify.sh" + local e + if [ "$1" = "export" ]; then + shift + e="export " + fi + eval "${e}${1}=\"${2}\"" + echo "${e}${1}=\"${2}\"" >> "${CT_BUILD_DIR}/env.modify.sh" } # Compute the target tuple from what is provided by the user @@ -1793,7 +1822,6 @@ CT_GetVersion_hg() # to clone if cset is not known and a branch is given. if [ -z "${devel_revision}" ]; then if [ -z "${devel_branch}" ]; then - # Mercurial does not allow querying branches devel_revision=`hg identify "${devel_url}"` else CT_DoLog WARN "${pkg_name}: Mercurial cannot query non-default branch, will clone" @@ -1830,46 +1858,97 @@ CT_GetVersion_git() CT_Abort "${pkg_name}: cannot specify both branch and changeset for Git" fi - devel_branch="${devel_branch:-master}" + # Do not modify devel_branch so that we can check if it has been set by user + # in CT_Download_git. + local branch="${devel_branch:-master}" + if [ -z "${devel_revision}" ]; then - local matches=`git ls-remote --exit-code "${devel_url}" --refs "${devel_branch}" \ + local matches=`git ls-remote --exit-code "${devel_url}" --refs "${branch}" \ || echo "not found"` local best using ref # Cannot test $?, setting a trap on ERR prevents bash from returning the # status code. if [ "${matches}" = "not found" ]; then - CT_Abort "Failed to find git ref ${devel_branch} at ${devel_url}" + CT_Abort "Failed to find git ref ${branch} at ${devel_url}" fi if [ `echo "${matches}" | wc -l` -gt 1 ]; then - if echo "${matches}" | grep '[[:space:]]\(refs/heads/\)\?'"${devel_branch}\$" >/dev/null; then + if echo "${matches}" | grep '[[:space:]]\(refs/heads/\)\?'"${branch}\$" >/dev/null; then # Try exact match, or prepended with "refs/heads". Some projects (e.g. binutils) # have refs/original/refs/heads/master as well as refs/heads/master, and # `git ls-remote refs/heads/master` prints both. - best=`echo "${matches}" | grep '[[:space:]]\(refs/heads/\)\?'"${devel_branch}\$"` + best=`echo "${matches}" | grep '[[:space:]]\(refs/heads/\)\?'"${branch}\$"` using="best match" else best=`echo "${matches}" | head -n1` using="first" fi ref=`echo "${best}" | sed 's/.*[[:space:]]//'` - CT_DoLog WARN "Ambiguous ref ${devel_branch} at ${devel_url}, using ${using} (${ref})" + CT_DoLog WARN "Ambiguous ref ${branch} at ${devel_url}, using ${using} (${ref})" else best="${matches}" fi - devel_revision=`echo "${best}" | cut -c1-8` - CT_DoLog DEBUG "ref ${devel_branch} at ${devel_url} has cset of ${devel_revision}" + # Similarly, do not modify the devel_revision, we'll need to know if it + # has been set by the user in CT_Download_git. + unique_id=`echo "${best}" | cut -c1-8` + CT_DoLog DEBUG "ref ${branch} at ${devel_url} has cset of ${unique_id}" + else + unique_id=`echo "${devel_revision}" | cut -c1-8` fi - unique_id="${devel_revision}" } # Retrieve sources from Git. CT_Download_git() { - # Git does not allow making a shallow clone of a specific commit. - CT_DoExecLog ALL git clone "${devel_url}" "${pkg_name}" - CT_Pushd "${pkg_name}" - CT_DoExecLog ALL git checkout "${devel_revision}" -- + local new_unique_id fetched=n shallow_id + + # Some of these operations are part of a `git clone`, but fetching a specific commit + # (if it is supported by the server) is not expressable as a `git clone`. + CT_mkdir_pushd "${pkg_name}" + CT_DoExecLog ALL git init + CT_DoExecLog ALL git remote add origin "${devel_url}" + + if [ -z "${devel_revision}" ]; then + # Configuration didn't care about a specific commit; we'll use the most recent + # commit on the branch and will update the unique_id (and warn the user) if it + # differs from what we've previously determined. + shallow_id="${devel_branch:-master}" + else + local tmp=`echo "${devel_revision}" | sed 's/^[0-9a-z]\{40\}//'` + + if [ -z "${tmp}" ]; then + shallow_id="${devel_revision}" + else + CT_DoLog WARN "Git only allows full 40-character SHA-1 hashes to identify a commit for shallow clone." + fi + fi + + if [ -n "${shallow_id}" ]; then + if CT_DoExecLog ALL git fetch --quiet --depth 1 origin "${shallow_id}"; then + CT_DoExecLog ALL git checkout --quiet FETCH_HEAD -- + else + # Git 2.15 and newer (which must be the case on both the client and the server) + # allows fetching a single commit so long as the server is configured + # to allow it (by having uploadpack.allowReachableSHA1InWant=true set + # in its config). + CT_DoLog WARN "Shallow clone failed (likely disallowed on the server)." + shallow_id= + fi + fi + + if [ -z "${shallow_id}" ]; then + # In this case, we already determined the changeset we need + CT_DoLog WARN "Falling back to full clone; may take some time..." + CT_DoExecLog ALL git fetch --quiet origin + CT_DoExecLog ALL git checkout --quiet "${unique_id}" -- + fi + + new_unique_id=`git rev-parse HEAD | cut -c1-8` + if [ "${new_unique_id}" != "${unique_id}" ]; then + CT_DoLog EXTRA "Revision being fetched changed to ${new_unique_id}; source repository had more revisions pushed?" + unique_id="${new_unique_id}" + fi + CT_DoExecLog ALL rm -rf .git CT_Popd } @@ -1897,7 +1976,7 @@ CT_PackageRun() for v in basename pkg_name version pkg_dir \ src_release mirrors archive_filename archive_dirname archive_formats signature_format \ src_devel devel_vcs devel_url devel_branch devel_revision devel_subdir devel_bootstrap \ - src_custom custom_location; do + src_custom custom_location patch_order; do eval "local ${v}=\${CT_${use}_${v^^}}" done @@ -1980,10 +2059,10 @@ CT_DoFetch() if [ "${CT_FORBID_DOWNLOAD}" = "y" ]; then CT_DoLog WARN "Downloads forbidden, not trying ${devel_vcs} retrieval" - return 1 + CT_Abort "${pkg_name}: cannot check out" fi - CT_DoLog EXTRA "Retrieving '${basename}' (${devel_vcs} ${devel_url} ${devel_branch} ${devel_revision})" + CT_DoLog EXTRA "Checking out '${basename}' (${devel_vcs} ${devel_url}${devel_branch:+, branch ${devel_branch}}${devel_revision:+, revision ${devel_revision}})" CT_MktempDir tmp_dir CT_Pushd "${tmp_dir}" CT_Download_${devel_vcs} @@ -1995,7 +2074,9 @@ CT_DoFetch() CT_DoExecLog ALL mv "${pkg_name}${devel_subdir:+/${devel_subdir}}" "${basename}" CT_DoExecLog ALL tar cjf "${CT_TARBALLS_DIR}/${basename}.tar.bz2" "${basename}" - CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2" + if ! CT_SaveLocal "${CT_TARBALLS_DIR}/${basename}.tar.bz2"; then + CT_Abort "${pkg_name}: failed to save to local storage" + fi CT_Popd CT_DoExecLog ALL rm -rf "${tmp_dir}" @@ -2055,6 +2136,11 @@ CT_DoExtractPatch() local local_patch_dir local overlay + # Inherit global value if requested + if [ "${patch_order}" = "global" ]; then + patch_order="${CT_PATCH_ORDER}" + fi + # If using overlay, prepare it first - we need to determine where to unpack # this component. if [ "${CT_TARGET_USE_OVERLAY}" = "y" -a ! -d "${CT_BUILD_DIR}/overlay" ]; then @@ -2071,7 +2157,7 @@ CT_DoExtractPatch() # and no overlays. Otherwise, this source directory is custom-tailored for this # particular configuration and cannot be reused by different configurations. if [ "${src_custom}" != "y" -a \ - "${CT_PATCH_ORDER}" = "bundled" -a \ + "${patch_order}" = "bundled" -a \ ! -d "${CT_BUILD_DIR}/overlay/${dir_name}" ]; then src_dir="${CT_COMMON_SRC_DIR}" else @@ -2120,7 +2206,7 @@ CT_DoExtractPatch() bundled_patch_dir="${CT_LIB_DIR}/packages/${pkg_dir}" local_patch_dir="${CT_LOCAL_PATCH_DIR}/${pkg_dir}" - case "${CT_PATCH_ORDER}" in + case "${patch_order}" in bundled) patch_dirs=("${bundled_patch_dir}");; local) patch_dirs=("${local_patch_dir}");; bundled,local) patch_dirs=("${bundled_patch_dir}" "${local_patch_dir}");; @@ -2159,6 +2245,20 @@ CT_DoExtractPatch() CT_DoExecLog ALL "${CT_CONFIG_SHELL}" -c "${devel_bootstrap}" fi + # Fix up the timestamps on the file we may be patching: otherwise, we may + # have a circular dependency. For example, we need make to build autoconf + # and automake companion tools, but we need autoconf and automake to regenerate + # aclocal.m4 or config.h.in after the patch touches configure.ac. Instead, + # assume the patch fixes all the files it needs. + find . -type f -name "aclocal.m4" \ + -exec touch {} \; -exec echo touch {} \; | CT_DoLog ALL + find . -type f -name "config.h.in" \ + -exec touch {} \; -exec echo touch {} \; | CT_DoLog ALL + find . -type f -name "Makefile.in" \ + -exec touch {} \; -exec echo touch {} \; | CT_DoLog ALL + find . -type f -name "configure" \ + -exec touch {} \; -exec echo touch {} \; | CT_DoLog ALL + if [ -n "${patchfunc}" ]; then ${patchfunc} fi |