#!/bin/bash # pbuilder -- personal Debian package builder # Copyright (C) 2001,2002,2003,2005-2007 Junichi Uekawa # Copyright (C) 2007 Loïc Minier # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # module to satisfy build dependencies; common functions package_versions() { local PACKAGE="$1" LC_ALL=C $CHROOTEXEC /usr/bin/apt-cache show "$PACKAGE" | sed -n 's/^Version: //p' } candidate_version() { local PACKAGE="$1" LC_ALL=C $CHROOTEXEC apt-cache policy "$PACKAGE" | sed -n 's/ *Candidate: //p' } checkbuilddep_versiondeps() { local PACKAGE="$1" local COMPARESTRING="$2" local DEPSVERSION="$3" local PACKAGEVERSIONS=$( package_versions "$PACKAGE" | xargs) # no versioned provides. if [ "${FORCEVERSION}" = "yes" ]; then return 0; fi for PACKAGEVERSION in $PACKAGEVERSIONS ; do if dpkg --compare-versions "$PACKAGEVERSION" "$COMPARESTRING" "$DEPSVERSION"; then # satisfies depends return 0; fi done echo " Tried versions: $PACKAGEVERSIONS" # cannot satisfy depends return 1; } get_source_control_field() { local field="$1" sed -n -e "s/^$field://i" -e ' t store /^-----BEGIN PGP SIGNED MESSAGE-----$/ { : pgploop n /^$/ d b pgploop } /^$/q d : store H : loop n /^#/ b loop /^[ \t]/ b store x # output on single line s/\n//g # change series of tabs and spaces into a space s/[\t ]\+/ /g # normalize space before and after commas s/ *, */, /g # normalize space before and after pipes s/ *| */ | /g # normalize space before and after parentheses s/ *( */ (/g s/ *) */)/g # normalize space before and after brackets s/ *\[ */ [/g s/ *\] */]/g # normalize space after exclamation mark s/! */!/g # normalize space between operator and version s/(\(>>\|>=\|>\|==\|=\|<=\|<<\|<\|!=\) *\([^)]*\))/(\1 \2)/g # normalize space at beginning and end of line s/^ *// s/ *$// p' \ "$DEBIAN_CONTROL" } get_build_deps() { local output output="`get_source_control_field "Build-Depends"`" output="${output%, }" if [ "$BINARY_ARCH" = no ]; then output="${output:+$output, }`get_source_control_field "Build-Depends-Indep"`" output="${output%, }" fi echo "$output" } get_build_conflicts() { local output output="`get_source_control_field "Build-Conflicts"`" if [ "$BINARY_ARCH" = no ]; then output="${output:+$output, }`get_source_control_field "Build-Conflicts-Indep"`" fi echo "$output" } # filter out dependencies sent on input not for this arch; deps can have # multiple lines; output is on a single line or "" if empty filter_arch_deps() { local arch="$1" local INSTALLPKGMULTI local INSTALLPKG # split on "," sed 's/[[:space:]]*,[[:space:]]*/\n/g' | while read INSTALLPKGMULTI; do echo "$INSTALLPKGMULTI" | # split on "|" sed 's/[[:space:]]*|[[:space:]]*/\n/g' | while read INSTALLPKG; do if echo "$INSTALLPKG" | grep -q '\['; then if checkbuilddep_archdeps "$INSTALLPKG" "$arch"; then continue fi fi # output the selected package echo "$INSTALLPKG" done | # remove the arch list and add " | " between entries sed 's/\[.*\]//; $,$! s/$/ |/' | xargs --no-run-if-empty done | # add ", " between entries sed '$,$! s/$/,/' | xargs --no-run-if-empty } # filter out dependencies sent on input not for selected build profiles; deps # can have multiple lines; output is on a single line or "" if empty filter_restriction_deps() { local profiles="$1" local INSTALLPKGMULTI local INSTALLPKG # split on "," sed 's/[[:space:]]*,[[:space:]]*/\n/g' | while read INSTALLPKGMULTI; do echo "$INSTALLPKGMULTI" | # split on "|" sed 's/[[:space:]]*|[[:space:]]*/\n/g' | while read INSTALLPKG; do if echo "$INSTALLPKG" | grep -q '<'; then if checkbuilddep_restrictiondeps "$INSTALLPKG" "$profiles"; then continue fi fi # output the selected package echo "$INSTALLPKG" done | # remove the restriction list and add " | " between entries sed 's/<.*>//; $,$! s/$/ |/' | xargs --no-run-if-empty done | # add ", " between entries sed '$,$! s/$/,/' | xargs --no-run-if-empty } checkbuilddep_archdeps() { # returns FALSE on INSTALL local INSTALLPKG="$1" local ARCH="$2" # architectures listed between [ and ] for this dep local DEP_ARCHES="$(echo "$INSTALLPKG" | sed -e 's/.*\[\(.*\)\].*/\1/' -e 'y|/| |')" local PKG="$(echo "$INSTALLPKG" | cut -d ' ' -f 1)" local USE_IT local IGNORE_IT local INCLUDE # Use 'dpkg-architecture' to support architecture wildcards. for d in $DEP_ARCHES; do if echo "$d" | grep -q '!'; then d="$(echo $d | sed 's/!//')" if dpkg-architecture -a$ARCH -i$d; then IGNORE_IT="yes" fi else if dpkg-architecture -a$ARCH -i$d; then USE_IT="yes" fi INCLUDE="yes" fi done if [ $IGNORE_IT ] && [ $USE_IT ]; then printf "W: inconsistent arch restriction on $PKG: " >&2 printf "$DEP_ARCHES depedency\n" >&2 fi if [ $IGNORE_IT ] || ( [ $INCLUDE ] && [ ! $USE_IT ] ); then return 0 fi return 1 } checkbuilddep_restrictiondeps() { # returns FALSE on INSTALL local INSTALLPKG="$1" local PROFILES="$2" # restrictions listed between < and > for this dep local DEP_RESTRICTIONS="$(echo "$INSTALLPKG" | sed -e 's/[^<]*<\(.*\)>.*/\1/' -e 's/>\s\+ /dev/null; then # package versions returned by APT, in reversed order PACKAGEVERSIONS="$( package_versions "$PACKAGE" | tac | xargs )" CANDIDATE_VERSION="$( candidate_version "$PACKAGE" )" COMPARESTRING="$(echo "$INSTALLPKG" | tr "/" " " | sed 's/^.*( *\(<<\|<=\|>=\|=\|<\|>>\|>\) *\(.*\)).*$/\1/')" DEPSVERSION="$(echo "$INSTALLPKG" | tr "/" " " | sed 's/^.*( *\(<<\|<=\|>=\|=\|<\|>>\|>\) *\(.*\)).*$/\2/')" # if strictly versionned, we skip to outputting that version if [ "=" = "$COMPARESTRING" ]; then PACKAGE_WITHVERSION="$PACKAGE=$DEPSVERSION" else # try the candidate version, then all available versions (asc) for VERSION in $CANDIDATE_VERSION $PACKAGEVERSIONS; do if dpkg --compare-versions "$VERSION" "$COMPARESTRING" "$DEPSVERSION"; then if [ $VERSION != $CANDIDATE_VERSION ]; then PACKAGE_WITHVERSION="$PACKAGE=$VERSION" fi break; fi done fi fi echo "$PACKAGE_WITHVERSION" } print_help() { # print out help message cat < --help: give help --control: specify control file (debian/control, *.dsc) --chroot: operate inside chroot --binary-all: include binary-all --binary-arch: include binary-arch only --echo: echo mode, do nothing. (--force-version required for most operation) --force-version: skip version check. --continue-fail: continue even when failed. EOF }