blob: 4f2207099c0b6f436a224e5b0c333e645e45ddd1 [file] [log] [blame]
# Copyright 2015 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Functions used to parse a package list file.
#
# A PACKAGES.TXT file has the following format:
#
# - Empty lines, and lines starting with a dash (#) are ignored.
# - Each line has several fields like <NAME>=<VALUE>
# - Valid <NAME>s and corresponding values are:
#
# URL=<url>
# Download URL for the source package. The package's
# basename and version number will be extracted from it.
#
# GIT=<url>
# GIT URL to be cloned and packed as a tarball in the
# archive directory. Package name will be <basename>-<revision>.tar.xz
# where <basename> is the GIT url basename, and <revision> is the
# branch or commit SHA1.
#
# SVN=<url>
# SVN URL to be checked out and packed as a tarball in the archive
# directory. Package name will be <basename>-<revision>.tar.xz
# where <basename> is the SVN url basename, and <revision> is the
# revision number after @.
#
# BASENAME=<name>
# Optional package base name. If not provided, the base name will
# be extracted from the URL/GIT/SVN value.
#
# BRANCH=<name>
# GIT branch name, only needed when GIT=<url> is also used, ignored
# otherwise.
#
# SHA1=<sha1>
# Optional SHA-1 hash for the source package. If URL=<url> is used,
# this is optional, and if present, the content of the downloaded
# package will be checked against this value.
#
# If GIT=<url> is used, this is the SHA1 of the list of files inside
# the tarball created by the downloader. The commit itself is
# specified through BRANCH=<name>
#
# SRCDIR=<subdir>
# Optional source sub-directory after extraction of the
# package. Normally, foo-bar-1.2.tar.gz extracts into
# a sub-directory named 'foo-bar-1.2', but there are a
# few exceptions where this is not the case.
#
# For example, when MesaLib-10.4.2.tar.gz is extracted,
# the 'Mesa-10.4.2' directory is created. SRCDIR=<subdir>
# is a way to override the default value derived from
# the package's full name.
#
# DSTDIR=<subdir>
# Optional destination sub-directory. In certain cases, it is
# necessary to rename the destination directory from something
# different from SRCDIR (e.g. Qt packages should all uncompress
# into the same source directory, but they come in tarballs that
# extract to separate directories like qtbase-XXX/ and qtsvg-XXX/.
#
# By setting a non-empty value here, the content of SRCDIR will be
# recursively copied into the DSTDIR sub-directory. This happens
# after all patches have been applied in SRCDIR.
#
# Usage:
#
# 1) Call 'package_list_parse_file /path/to/PACKAGES.TXT' to
# parse the package list file and record its content.
#
# 2) Use other package_list_get_XXX functions to retrieve
# information about a package. Each package is identified
# by its 'base name', which is the unversioned name of
# the package (e.g. 'zlib-2.1.8.tar.gz' has a base name
# of 'zlib').
#
# 3) One can use 'package_list_get_packages' to retrieve a list
# of all the package base names.
# Set to 1 to enable debugging this parser, 0 to disable.
_SHU_DEBUG_PARSER=0
if [ "$_SHU_DEBUG_PARSER" = "1" ]; then
_shu_parser_log () {
log "$@"
}
else
_shu_parser_log () { true; }
fi
# Extract the version of a given package-name. Assumes the following format:
# <name>-<version><extension>
#
# Where <name> can contain hyphens (-) but not <version> or <extension>,
# and <extension> is one of the extensions known to package_file_strip_ext
# $1: Package name (e.g. 'zlib-1.2.8.tar.gz')
# Out: Package version number (e.g. '1.2.8')
_shu_package_name_extract_version () {
package_file_strip_ext "$1" | sed -e 's|.*-\([^-]*\)$|\1|g'
}
# Extract the base name of a given package file. Assumes the same format as
# _shu_package_name_extract_basename.
# $1: Package name (e.g. 'zlib-1.2.8.tar.gz')
# Out: Package base name (e.g. 'zlib')
_shu_package_name_extract_basename () {
package_file_strip_ext "$1" | sed -e 's|^\(.*\)-[^-]*$|\1|g'
}
# Return the name of a package without its archive suffix (.zip/.tar.gz/etc).
# $1: Package file path.
# Out: Package file path without zip/tarball extension.
package_file_strip_ext () {
case $1 in
*.zip)
printf %s "${1%.zip}"
;;
*.tar.gz)
printf %s "${1%.tar.gz}"
;;
*.tar.bz2)
printf %s "${1%.tar.bz2}"
;;
*.tar.xz)
printf %s "${1%.tar.xz}"
;;
*)
printf %s "$1"
esac
}
# Set the value of a given package field.
# $1: Package index (e.g. '1')
# $2: Field name (e.g. 'URL')
# $3: Value
_shu_pkg_set_var () {
var_assign _SHU_PKG_${2}__${1} "$3"
}
# Get the value of a given package field.
# $1: Package index (e.g. '1')
# $2: Field name (e.g. 'URL')
_shu_pkg_get_var () {
var_value _SHU_PKG_${2}__${1}
}
# Find the index of a given package from its basename
# $1: Package basename (e.g. 'pkg-config')
# Out: index in _SHU_PKG_ lists (e.g. '1'), or '' if not found.
_shu_pkg_find_basename_index () {
local N=0
while [ "$N" -lt "$_SHU_PKG_COUNT" ]; do
N=$(( $N + 1 ))
if [ "$(_shu_pkg_get_var $N BASENAME)" = "$1" ]; then
echo "$N"
return 0
fi
done
}
# Parse the package list file, and record its content.
# One can later use package_list_XXX functions to probe its content.
#
# $1: package list file.
package_list_parse_file () {
local PACKAGES="$1"
_shu_parser_log "Trying to parse: $PACKAGES"
# Small sanity check
if [ ! -f "$PACKAGES" ]; then
panic "Missing packages list file: $PACKAGES"
fi
local PKG_BASENAME PKG_URL PKG_SHA1 PKG_PATCHES PKG_FILE PKG_VERSION
local PKG_LIST PKG_SRC_DIR PKG_GIT PKG_BRANCH
local OLD_IFS="$IFS"
local IFS="$OLD_IFS"
local COUNT=0
local LINE_NUMBER=0
local LINE
IFS="
"
for LINE in $(cat "$1"); do
IFS=$OLD_IFS
LINE_NUMBER=$(( $LINE_NUMBER + 1 ))
_shu_parser_log "$LINE_NUMBER: LINE=[$LINE]"
PKG_URL=
PKG_GIT=
PKG_SVN=
PKG_BRANCH=
PKG_BASENAME=
PKG_SHA1=
PKG_FILE=
PKG_PATCHES=
PKG_VERSION=
PKG_SRC_DIR=
PKG_DST_DIR=
# Skip empty lines, and comment lines that start with #
if [ -z "$LINE" -o "${LINE##\#}" != "${LINE}" ]; then
continue
fi
local FIELD
for FIELD in $LINE; do
_shu_parser_log " FIELD=[$FIELD]"
case $FIELD in
SHA1=*)
PKG_SHA1=${FIELD#SHA1=}
;;
URL=*)
PKG_URL=${FIELD#URL=}
;;
BASENAME=*)
PKG_BASENAME=${FIELD##BASENAME=}
;;
BRANCH=*)
PKG_BRANCH=${FIELD#BRANCH=}
;;
GIT=*)
PKG_GIT=${FIELD#GIT=}
;;
SVN=*)
PKG_SVN=${FIELD#SVN=}
;;
PATCHES=*)
PKG_PATCHES=${FIELD#PATCHES=}
;;
SRCDIR=*)
PKG_SRC_DIR=${FIELD#SRCDIR=}
;;
DSTDIR=*)
PKG_DST_DIR=${FIELD#DSTDIR=}
;;
*)
dump "WARNING: Unknown package field [$FIELD] on line $LINE_NUMBER: $1"
;;
esac
done
if [ "$PKG_URL" ]; then
if [ "$PKG_GIT" ]; then
panic "Cannot use both URL=<url> and GIT=<url> on line $LINE_NUMBER: $1"
fi
if [ "$PKG_SVN" ]; then
panic "Cannot use both URL=<url> and SVN=<url> on line $LINE_NUMBER: $1"
fi
PKG_FILE=$(basename "$PKG_URL")
if [ -z "$PKG_BASENAME" ]; then
PKG_BASENAME=$(_shu_package_name_extract_basename "$PKG_FILE")
fi
PKG_VERSION=$(_shu_package_name_extract_version "$PKG_FILE")
elif [ "$PKG_GIT" ]; then
if [ "$PKG_SVN" ]; then
panic "Cannot use both GIT=<url> and SVN=<url> on line $LINE_NUMBER: $1"
fi
if [ -z "$PKG_BRANCH" ]; then
panic "Missing BRANCH=<name> on line $LINE_NUMBER: $1"
fi
PKG_FILE=$(basename "$PKG_GIT")
PKG_FILE=${PKG_FILE%.git} # Remove any .git suffix.
if [ -z "$PKG_BASENAME" ]; then
PKG_BASENAME=$PKG_FILE
fi
PKG_FILE=$PKG_BASENAME-$PKG_BRANCH.tar.xz
PKG_VERSION=$PKG_BRANCH
elif [ "$PKG_SVN" ]; then
if [ -z "$PKG_BRANCH" ]; then
panic "Missing BRANCH=<name> on line $LINE_NUMBER: $1"
fi
PKG_FILE=$(basename "$PKG_SVN")
if [ -z "$PKG_BASENAME" ]; then
PKG_BASENAME=$PKG_FILE
fi
PKG_FILE=$PKG_BASENAME-$PKG_BRANCH.tar.xz
PKG_VERSION=$PKG_BRANCH
else
panic "Missing URL=<url>, GIT=<url> or SVN=<url> field in package list line $LINE_NUMBER: $1"
fi
_shu_parser_log " BASENAME=$PKG_BASENAME FILE=$PKG_FILE"
if [ -z "$PKG_SRC_DIR" ]; then
PKG_SRC_DIR=$PKG_BASENAME-$PKG_VERSION
_shu_parser_log " SRC_DIR=$PKG_SRC_DIR"
fi
if [ -z "$PKG_DST_DIR" ]; then
PKG_DST_DIR=$PKG_SRC_DIR
fi
_shu_parser_log " DST_DIR=$PKG_DST_DIR"
# Save the package information now.
COUNT=$(( $COUNT + 1 ))
_shu_pkg_set_var $COUNT BASENAME "$PKG_BASENAME"
_shu_pkg_set_var $COUNT VERSION "$PKG_VERSION"
_shu_pkg_set_var $COUNT FILE "$PKG_FILE"
_shu_pkg_set_var $COUNT SRC_DIR "$PKG_SRC_DIR"
_shu_pkg_set_var $COUNT DST_DIR "$PKG_DST_DIR"
_shu_pkg_set_var $COUNT URL "$PKG_URL"
_shu_pkg_set_var $COUNT GIT "$PKG_GIT"
_shu_pkg_set_var $COUNT SVN "$PKG_SVN"
_shu_pkg_set_var $COUNT SHA1 "$PKG_SHA1"
_shu_pkg_set_var $COUNT PATCHES "$PKG_PATCHES"
var_append PKG_LIST "$PKG_BASENAME"
done
_SHU_PKG_COUNT=$COUNT
_SHU_PKG_LIST=$PKG_LIST
}
# Get the value of a named field for a packaged identified by basename.
# $1: Package basename (e.g. 'zlib')
# $2: Field name (e.g. 'URL')
# Out: field value, or empty if not defined.
_shu_package_list_get_field () {
local N
N=$(_shu_pkg_find_basename_index "$1")
if [ "$N" ]; then
_shu_pkg_get_var $N $2
fi
}
# Return the version of a given package.
# $1: unversioned and un-suffixed package prefix (e.g. 'zlib')
# Out: package version (e.g. '1.2.8')
package_list_get_version () {
local N
N=$(_shu_pkg_find_basename_index "$1")
if [ "$N" ]; then
printf %s $(_shu_pkg_get_var $N VERSION)
fi
}
# Return the full name of a given package.
# $1: unversioned and unsuffixed package prefix (e.g. 'zlib')
# Out: package full name (e.g. 'zlib-1.2.8')
package_list_get_full_name () {
local N
N=$(_shu_pkg_find_basename_index "$1")
if [ "$N" ]; then
printf %s $(_shu_pkg_get_var $N BASENAME)-$(_shu_pkg_get_var $N VERSION)
fi
}
# Return the archive file name of a given package.
# $1: unversioned and un-suffixed package prefix (e.g. 'zlib')
# Out: package tarball name (e.g. 'zlib-1.2.8.tar.gz')
package_list_get_filename () {
_shu_package_list_get_field "$1" FILE
}
# Return the URL of a given package, if any.
# $1: unversioned and un-suffixed package prefix (e.g. 'zlib')
# Out: package URL (e.g. 'ftp://someserver/somepath/zlib-1.2.8.tar.gz')
package_list_get_url () {
_shu_package_list_get_field "$1" URL
}
# Return the git URL of a given package, if any.
# $1: unversioned and un-suffixed package prefix (e.g. 'zlib')
# Out: package URL (e.g. 'git://git.qemu-project.org/dtc.git')
package_list_get_git_url () {
_shu_package_list_get_field "$1" GIT
}
# Return the git SVM of a given package, if any.
# $1: unversioned and un-suffixed package prefix (e.g. 'zlib')
# Out: package URL (e.g. 'svn://svn.project.org/trunk/something@version')
package_list_get_svn_url () {
_shu_package_list_get_field "$1" SVN
}
package_list_get_git_branch () {
_shu_package_list_get_field "$1" BRANCH
}
# Return the SHA1 of a given package, if any.
# $1: unversioned and un-suffixed package prefix (e.g. 'zlib')
# Out: package SHA1
package_list_get_sha1 () {
_shu_package_list_get_field "$1" SHA1
}
# Return the patches tarball of a given package, if any.
# $1: unversioned and un-suffixed package prefix (e.g. 'glib')
# Out: package tarball name (e.g. 'glib-2.1.8-patches.tar.xz')
package_list_get_patches () {
_shu_package_list_get_field "$1" PATCHES
}
# Return the source sub-directory name of a given package.
# $1: unversioned and un-suffixed package prefix (e.g. 'MesaLib')
# Out: source sub-directory (e.g. 'Mesa-10.4.2')
package_list_get_src_dir () {
_shu_package_list_get_field "$1" DST_DIR
}
package_list_get_unpack_src_dir () {
_shu_package_list_get_field "$1" SRC_DIR
}
# Return the list of all unversioned package names.
package_list_get_packages () {
printf %s "$_SHU_PKG_LIST"
}
# Unpack and eventually patch a given source package.
#
# $1: unversioned and unsuffixed package name (e.g. 'zlib')
# $2: source archive directory.
# $3: destination directory.
package_list_unpack_and_patch () {
local PKG_NAME="$1"
local SRC_DIR="$2"
local DST_DIR="$3"
local PKG_VERSION PKG_PACKAGE PKG_PATCHES_DIR PKG_PATCHES_PACKAGE
local PKG_DIR PKG_DST_DIR PATCH PKG_FULLNAME
PKG_VERSION=$(package_list_get_version $PKG_NAME)
if [ -z "$PKG_VERSION" ]; then
panic "Cannot find version for package $PKG_NAME!"
fi
PKG_FULLNAME=$(package_list_get_full_name $PKG_NAME)
dump "Extracting $PKG_FULLNAME"
PKG_FILE=$(package_list_get_filename $PKG_NAME)
mkdir -p "$DST_DIR" &&
unpack_archive "$SRC_DIR/$PKG_FILE" "$DST_DIR" ||
panic "Could not unpack $PKG_FULLNAME"
PKG_DIR=$DST_DIR/$(package_list_get_unpack_src_dir $PKG_NAME)
if [ ! -d "$PKG_DIR" ]; then
panic "Missing extracted directory: $PKG_DIR"
fi
PKG_PATCHES_DIR=$PKG_FULLNAME-patches
PKG_PATCHES_FILE=$SRC_DIR/${PKG_PATCHES_DIR}.tar.xz
if [ -f "$PKG_PATCHES_FILE" ]; then
log "Patching $PKG_FULLNAME"
unpack_archive "$PKG_PATCHES_FILE" "$DST_DIR"
for PATCH in $(cd "$DST_DIR" && ls "$PKG_PATCHES_DIR"/*.patch); do
log "Applying patch: $PATCH"
(cd "$PKG_DIR" && run patch -p1 < "../$PATCH") ||
panic "Could not apply $PATCH"
done
fi
PKG_DST_DIR=$DST_DIR/$(package_list_get_src_dir $PKG_NAME)
if [ "$PKG_DST_DIR" != "$PKG_DIR" ]; then
log "Copying sources from $PKG_DIR into $PKG_DST_DIR"
copy_directory "$PKG_DIR" "$PKG_DST_DIR"
fi
}