123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040 |
- #!/bin/ksh
- #
- # $OpenBSD: portcheck,v 1.112 2017/05/26 20:55:09 jca Exp $
- # Copyright (c) 2013 Vadim Zhukov
- #
- # Permission to use, copy, modify, and distribute this software for any
- # purpose with or without fee is hereby granted, provided that the above
- # copyright notice and this permission notice appear in all copies.
- #
- # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- set -e
- set +X
- set -u
- usage() {
- echo "usage: ${0##*/} [-dNP] [-p portsdir] [-x glob]" >&2
- echo " ${0##*/} -A [-dP] [-p portsdir] [-x glob] [subdir ...]" >&2
- exit 1
- }
- ############################################################
- # Parsing command line options
- #
- existing_port=true
- ignore_cvs=true
- plist_checks=true
- portsdir=
- rootrun=false
- debugging=false
- ignore_list=; unset ignore_list[0]
- while getopts "AdNPp:x:" OPT; do
- case $OPT in
- A)
- $existing_port || usage
- if ! $rootrun; then
- ignore_list[${#ignore_list[@]}]=.cvsignore
- ignore_list[${#ignore_list[@]}]=.fslckout
- ignore_list[${#ignore_list[@]}]=.git
- ignore_list[${#ignore_list[@]}]=.gitignore
- ignore_list[${#ignore_list[@]}]=.hg
- ignore_list[${#ignore_list[@]}]=.hgignore
- ignore_list[${#ignore_list[@]}]=.svn
- ignore_list[${#ignore_list[@]}]=FINISHED
- ignore_list[${#ignore_list[@]}]=INDEX
- ignore_list[${#ignore_list[@]}]=README
- ignore_list[${#ignore_list[@]}]=README.md
- ignore_list[${#ignore_list[@]}]=bulk
- ignore_list[${#ignore_list[@]}]=distfiles
- ignore_list[${#ignore_list[@]}]=infrastructure
- ignore_list[${#ignore_list[@]}]=lost+found
- ignore_list[${#ignore_list[@]}]=mystuff
- ignore_list[${#ignore_list[@]}]=openbsd-wip
- ignore_list[${#ignore_list[@]}]=packages
- ignore_list[${#ignore_list[@]}]=plist
- ignore_list[${#ignore_list[@]}]=pobj
- ignore_list[${#ignore_list[@]}]=tests
- ignore_list[${#ignore_list[@]}]=update
- fi
- rootrun=true
- ;;
- d)
- debugging=true
- ;;
- N)
- $rootrun && usage
- existing_port=false
- ignore_cvs=false
- ;;
- P)
- plist_checks=false
- ;;
- p)
- portsdir=$OPTARG
- ;;
- x)
- set -A ignore_list -- "${ignore_list[@]}" "$OPTARG"
- ;;
- *)
- usage
- ;;
- esac
- done
- if ! $rootrun && [[ -n $portsdir && ${PWD##"$portsdir"} == "$PWD" ]]; then
- cat >&2 <<EOE
- ${0##*/}: current directory does not seem to be under the
- specified root directory: $portsdir.
- EOE
- exit 3
- fi
- shift $(($OPTIND - 1))
- (($# > 0)) && ! $rootrun && usage
- (($# == 0)) && set -- .
- ############################################################
- # Detect path to root of directory tree of current port(s) and put it
- # in $portsdir, unless it was set by user above. As a last resort, we
- # use some heuristics based on the commonly used names.
- #
- # We also have a $pkgpath variable, that represents subdirectory under
- # root ports directory where the port(s) will be imported. In case we
- # use heuristics for determining $portsdir, we'll set up $pkgpath, too,
- # since we would get this info anyway.
- #
- # In make_args we write PORTSDIR_PATH override, that allows us to run
- # even in ports directory that is not on the PORTSDIR_PATH. This is
- # useful, for example, when you check your port on cvs.openbsd.org,
- # where you cannot just override mk.conf.
- #
- pkgpath=
- if [[ -z $portsdir ]]; then
- # idea from DPB/Vars.pm
- test_mf=$(cat <<EOF
- COMMENT = test
- CATEGORIES = test
- PKGPATH = test/a
- DISTNAME = test
- PERMIT_PACKAGE_CDROM=Yes
- IGNORE=Yes
- _MAKEFILE_INC_DONE=Yes
- ECHO_MSG=:
- .include <bsd.port.mk>
- SIGNING_PARAMETERS ?=
- EOF
- )
- IFS=:
- set -A portsdir_path -- \
- $( (echo "$test_mf" | make -C / -f - show=PORTSDIR_PATH 2>/dev/null) || true)
- unset IFS
- if ((${#portsdir_path[@]} > 0)); then
- for p in "${portsdir_path[@]}"; do
- if [[ -z $portsdir && ${PWD#"$p"} != "$PWD" ]]; then
- portsdir=$p
- elif [[ -n $portsdir && ${PWD#"$p"} != "$PWD" &&
- $p > $portsdir ]]; then
- portsdir=$p
- fi
- done
- fi
- fi
- if [[ -z $portsdir ]]; then
- # heuristics mode ON
- pkgpath=${PWD##*/ports/*(mystuff/|openbsd-wip/)}
- portsdir=${PWD%"/$pkgpath"}
- fi
- if [[ -z $portsdir ]]; then
- cat >&2 <<EOE
- ${0##*/}: could not detect root ports directory. Please provide
- one with -p option.
- EOE
- exit 2
- fi
- # This way we can run all checks even on cvs.openbsd.org and/or
- # when SKIPDIR framework is used
- set -A make_args -- \
- SKIPDIR= STARTAFTER= STARTDIR= \
- MASTER_SITE_OPENBSD= \
- PORTSDIR_PATH="$portsdir:$(cd /usr/ports && make -V PORTSDIR_PATH || true)"
- if $rootrun; then
- cd -- "$portsdir"
- echo "scanning ports under the $portsdir" >&2
- fi
- ############################################################
- # Support for SKIPDIR, STARTDIR and STARTAFTER, see ports(7)
- #
- SKIPDIR=${SKIPDIR:-}
- STARTDIR=${STARTDIR:-}
- STARTAFTER=${STARTAFTER:-}
- if [[ -n $STARTAFTER ]]; then
- STARTDIR=$STARTAFTER
- SKIPDIR="$SKIPDIR $STARTAFTER"
- fi
- path_parts_count() {
- (IFS=/; set -- $1; echo $#)
- }
- # true if directory given should be skipped based on STARTDIR
- # and/or SKIPDIR variable
- skip_dir() {
- $rootrun || return 1
- local dir=$(readlink -f "$1")
- dir=${dir##$portsdir*(/)}
- local startpartscount=$(path_parts_count "$STARTDIR")
- local dirpartscount=$(path_parts_count "$dir")
- if ((dirpartscount >= startpartscount)); then
- [[ -n $STARTDIR && $dir < $STARTDIR ]] && return 0
- fi
- local d
- for d in $SKIPDIR; do
- [[ $d == "$dir" ]] && return 0
- done
- return 1
- }
- ############################################################
- # List of well-known top-level port categories
- # in a form usable in pattern matching: "foo|bar|baz"
- #
- top_level_categories=$(xargs <<EOF | sed -e 's/ /|/g'
- archivers
- astro
- audio
- base
- benchmarks
- biology
- books
- cad
- chinese
- comms
- converters
- databases
- devel
- editors
- education
- emulators
- fonts
- games
- geo
- graphics
- inputmethods
- japanese
- java
- korean
- lang
- mail
- math
- meta
- misc
- multimedia
- net
- news
- perl5
- plan9
- print
- productivity
- security
- shells
- sysutils
- telephony
- tests
- textproc
- www
- x11
- EOF
- )
- ############################################################
- # List of variables that should not go into port Makefiles
- #
- user_settings=$(xargs <<EOF | sed -e 's/ /|/g'
- BASELOCALSTATEDIR
- BASESYSCONFDIR
- BATCH
- BUILD_ONCE
- BULK
- BULK_COOKIES_DIR
- CHECKSUM_PACKAGES
- CHECK_LIB_DEPENDS
- COPTS
- CXXOPTS
- DISTDIR
- ECHO_MSG
- ECHO_REORDER
- FAKEOBJDIR
- FETCH_CMD
- FETCH_PACKAGES
- FETCH_SYMLINK_DISTFILES
- FORCE_UPDATE
- FTP_PACKAGES
- IGNORE_IS_FATAL
- IGNORE_SILENT
- INTERACTIVE
- LIST_DB
- LOCKDIR
- LOCK_VERBOSE
- MASTER_SITE_BACKUP
- MASTER_SITE_OVERRIDE
- NO_CHECKSUM
- NO_DEPENDS
- NO_IGNORE
- PACKAGE_REPOSITORY
- PKG_ADD
- PKG_CREATE
- PKG_DBDIR
- PKG_DELETE
- PKG_INFO
- REFETCH
- SIGNING_PARAMETERS
- SUDO
- TEMPLATES
- TRY_BROKEN
- UNLOCK_CMD
- UPDATE_COOKIES_DIR
- USE_CCACHE
- VARBASE
- WARNINGS
- EOF
- )
- ############################################################
- # Check and fail routines
- #
- error=false
- err() {
- local prefix=
- while (($# > 0)); do
- printf "$prefix%s" "$1" >&2
- prefix=" "
- shift
- done
- echo >&2
- error=true
- }
- err_duplicated() {
- err "both $2 and some of its parents has $1"
- }
- err_coredump_found() {
- err "core dump file found: $1"
- }
- has_subdirs_only() {
- $debugging && echo "CALLED: has_subdirs_only($*)" >&2
- local dir=$1; shift
- ls -A "$dir" | {
- local has_files=false has_dirs=false
- while read F; do
- $ignore_cvs && [[ $F == CVS ]] && continue
- ignoring "$dir/$F" && continue
- if [[ -d $dir/$F ]]; then
- has_dirs=true
- else
- has_files=true
- fi
- done
- $has_dirs && ! $has_files
- }
- }
- ignoring() {
- ((${#ignore_list[*]} > 0)) || return 1
- local iglob
- for iglob in "${ignore_list[@]}"; do
- [[ ${1#./} == $iglob ]] && return 0
- done
- return 1
- }
- is_vcs_item() {
- [[ -d "$1" && ${1##*/} == @(CVS|.fslckout|.git|.hg|.svn) ]]
- }
- handle_extra_file() {
- ignoring "$1" && return 0
- # avoid warning, e.g., about ".*"
- test -e "$1" || return 0
- if is_vcs_item "$1"; then
- if ! $ignore_cvs || [[ ${1##*/} != CVS ]]; then
- err "VCS item detected: $1"
- fi
- elif [[ -f $1 && $1 == *.core ]]; then
- err_coredump_found "$1"
- elif [[ -d $1 ]]; then
- err "extra directory: $1"
- else
- err "extra file: $1"
- fi
- }
- # Make a path to .py[co] file looks like as if it's in the same dir
- # as the corresponding .py file, and has same basename. E.g.:
- # lib/python3.3/__pycache__/Foo/cpython-33.Bar.pyc
- # became:
- # lib/python2.7/Foo/Bar.pyc
- # which corresponds to:
- # lib/python2.7/Foo/Bar.py
- normalize_pyco() {
- local pyco=$1
- [[ $pyco == *.cpython-+([0-9]).py[co] ]] &&
- pyco=${pyco%.cpython-+([0-9]).py[co]}.${pyco##*.}
- [[ $pyco == */__pycache__/* ]] &&
- pyco=${pyco%/__pycache__/*}/${pyco##*/__pycache__/}
- printf "%s" "$pyco"
- }
- # Print out a ref to the particular subport/subpackage, if needed.
- # Port FLAVORs could also be handled, if provided.
- # Usage: portref directory [subpackage [flavor all_flavors]]
- portref() {
- local dir=$1; shift
- local subpkg= flavor all_flavors=
- if (($# > 0)); then
- subpkg=$1
- shift
- fi
- if (($# > 0)); then
- flavor=$1
- all_flavors=$2
- shift 2
- fi
- local ref=
- if [[ $dir != . ]]; then
- ref="${dir#./}"
- [[ -n $subpkg && $subpkg != "-" ]] && ref="$ref,$subpkg"
- else
- [[ $subpkg != "-" ]] && ref="$subpkg"
- fi
- if [[ -n $all_flavors ]]; then
- [[ -n $ref ]] && ref="$ref, "
- if [[ -z $flavor ]]; then
- ref="${ref}default FLAVOR"
- else
- ref="${ref}FLAVOR \"$flavor\""
- fi
- fi
- [[ -n $ref ]] && echo "in $ref: "
- }
- # Contains last SUBST_CMD. Filled by check_port_dir(), used
- # by check_port_hier() to lazily call the check_pkg_dir().
- last_subst_cmd=
- # Checks made:
- # * Whitelist filter of what could be in this directory.
- check_port_hier() {
- $debugging && echo "CALLED: check_port_hier($*)" >&2
- local distinfo_lives_upper pkg_lives_upper plist_lives_upper
- local dir=$1; shift
- for opt; do
- # looks unsafe but we do not pass anything except
- # "foo=true" and "foo=false" here
- eval "$opt"
- done
- distinfo_lives_upper=${distinfo_lives_upper:-false}
- pkg_lives_upper=${pkg_lives_upper:-false}
- plist_lives_upper=${plist_lives_upper:-false}
- local distinfo_exists=false
- [[ -f $dir/distinfo ]] && distinfo_exists=true
- $distinfo_exists && $distinfo_lives_upper &&
- err_duplicated distinfo "$dir"
- local pkg_exists=false tell_pkg_exists=$pkg_lives_upper
- if [[ -d $dir/pkg ]]; then
- pkg_exists=true
- tell_pkg_exists=true
- fi
- local plist_exists=false
- ls $dir/pkg/PLIST* >/dev/null 2>&1 && plist_exists=true
- $plist_lives_upper && $plist_exists &&
- err_duplicated "packing list(s)" "$dir"
- $distinfo_lives_upper && distinfo_exists=true
- $plist_lives_upper && plist_exists=true
- local recursive_args
- set -A recursive_args -- \
- distinfo_lives_upper=$distinfo_exists \
- pkg_lives_upper=$tell_pkg_exists \
- plist_lives_upper=$plist_exists
- local F
- for F in "$dir"/* "$dir"/.*; do
- F=${F#./}
- ignoring "$F" && continue
- if is_vcs_item "$F"; then
- if ! $ignore_cvs || [[ ${F##*/} != CVS ]]; then
- err "VCS item detected: $F"
- fi
- elif [[ -d $F ]]; then
- case "${F##*/}" in
- files|patches)
- check_${F##*/}_dir "$F"
- ;;
- pkg)
- # Do nothing, pkg_exists is already set,
- # and we need to read SUBST_CMD first.
- ;;
- patches?(-*))
- check_patches_dir "$F"
- ;;
- *)
- if ! ([[ -f $F/Makefile ]] ||
- ls $F/*.port.mk >/dev/null 2>&1) &&
- ! has_subdirs_only "$F"; then
- # Avoid extra spam
- err "not a port directory: $F"
- else
- local pkgpath_set=false
- [[ -n $pkgpath ]] && pkgpath_set=true
- check_port_dir "$F" "${recursive_args[@]}"
- $pkgpath_set || pkgpath=${pkgpath%/*}
- fi
- ;;
- esac
- else
- case "${F##*/}" in
- Makefile?(.inc)|*.port.mk)
- check_makefile "$F"
- ;;
- distinfo)
- ;;
- *)
- handle_extra_file "$F"
- ;;
- esac
- fi
- done
- $pkg_exists && check_pkg_dir "$dir"/pkg "$last_subst_cmd"
- $existing_port ||
- egrep -q '^ *SUBDIR[[:space:]]*\+?=' "$dir"/Makefile ||
- err missing subdir Makefile
- }
- # Checks made:
- # * Whitelist filter of what could be in this directory.
- check_port_dir() {
- $debugging && echo "CALLED: check_port_dir($*)" >&2
- local dir=$1; shift
- skip_dir "$dir" && return
- local distinfo_lives_upper pkg_lives_upper plist_lives_upper
- for opt; do
- # looks unsafe but we do not pass anything except
- # "foo=true" and "foo=false" here
- eval "$opt"
- done
- distinfo_lives_upper=${distinfo_lives_upper:-false}
- pkg_lives_upper=${pkg_lives_upper:-false}
- plist_lives_upper=${plist_lives_upper:-false}
-
- check_perms_in_dir "$dir"
- if [[ -f $dir/Makefile.inc ]] ||
- egrep -sq '^ *SUBDIR[[:space:]]*\+?=' "$dir"/Makefile ||
- has_subdirs_only "$dir"; then
- check_port_hier "${dir#./}" "${@:-}"
- return
- fi
- local F
- local distinfo_exists=false
- local mk_exists=false
- local pkg_exists=false
- local plist_exists=false
- local portmk_exists=true
- local non_portmk=0
- for F in "$dir"/* "$dir"/.*; do
- F=${F#./}
- ignoring "$F" && continue
- case ${F##*/} in
- Makefile)
- test -f "$F" || err "$F is not a file"
- check_makefile "$F"
- mk_exists=true
- ((++non_portmk))
- ;;
- distinfo)
- $distinfo_lives_upper && err_duplicated distinfo "$dir"
- distinfo_exists=true
- test -f "$F" || err "$F is not a file"
- ((++non_portmk))
- ;;
- *.port.mk)
- test -f "$F" || err "$F is not a file"
- check_makefile "$F"
- portmk_exists=true
- ;;
- files|patches)
- if [[ -d $F ]]; then
- check_${F##*/}_dir "$F"
- else
- err "$F" is not a directory
- fi
- ((++non_portmk))
- ;;
- pkg)
- if [[ -d $F ]]; then
- pkg_exists=true
- # Actual check to be done later, we need to gather
- # additional info through "make show=" call.
- ls "$F"/PLIST* >/dev/null 2>&1 &&
- plist_exists=true
- $plist_lives_upper && $plist_exists &&
- err_duplicated "packing list(s)" "$dir"
- else
- err "$F" is not a directory
- fi
- ((++non_portmk))
- ;;
- *)
- handle_extra_file "$F"
- ;;
- esac
- done
- # examples: lang/clang, www/mozilla
- $portmk_exists && ((non_portmk == 0)) && return
- $mk_exists || err no Makefile in "$dir"
- $pkg_exists || $pkg_lives_upper || err "no pkg/ in $dir"
- $distinfo_lives_upper && distinfo_exists=true
- $distinfo_exists || $existing_port || err "no distinfo in $dir"
- # Now gather and check some info via "make show=...".
- # We request all info at once for speed.
- local categories dist_subdir distfiles flavor flavors
- local gh_commit master_sites
- local multi_packages pkgpath_this pseudo_flavor pseudo_flavors
- local shared_libs subst_cmd
- local perm_pkg_cdrom perm_pkg_ftp perm_dist_ftp
- local show_items="CATEGORIES DIST_SUBDIR DISTFILES FLAVOR FLAVORS GH_COMMIT"
- local show_items="$show_items MASTER_SITES MULTI_PACKAGES PKGPATH"
- local show_items="$show_items PSEUDO_FLAVOR PSEUDO_FLAVORS"
- local show_items="$show_items SHARED_LIBS SUBST_CMD"
- local show_items="$show_items PERMIT_PACKAGE_CDROM PERMIT_PACKAGE_FTP"
- local show_items="$show_items PERMIT_DISTFILES_FTP"
- local read_ok=false
- local read_failed=false
- (cd -- "$dir"; make "${make_args[@]}" show="$show_items" || true) </dev/null |&
- read -pr categories &&
- read -pr dist_subdir &&
- read -pr distfiles &&
- read -pr flavor &&
- read -pr flavors &&
- read -pr gh_commit &&
- read -pr master_sites &&
- read -pr multi_packages &&
- read -pr pkgpath_this &&
- read -pr pseudo_flavor &&
- read -pr pseudo_flavors &&
- read -pr shared_libs &&
- read -pr subst_cmd &&
- read -pr perm_pkg_cdrom &&
- read -pr perm_pkg_ftp &&
- read -pr perm_dist_ftp &&
- read_ok=true
- if $read_ok; then
- exec 3<&p
- exec 3<&-
- wait
- else
- error=true
- return
- fi
- pseudo_flavor=$(echo "$pseudo_flavor" | sed -e 's/,/ /g')
- pseudo_flavor=${pseudo_flavor##" "}
- local f pf found
- local check_flavors=
- [[ $flavor != "$pseudo_flavor" ]] && unset check_flavors[0]
- for f in $flavors; do
- for pf in $pseudo_flavors; do
- [[ $f == "$pf" ]] && continue 2
- done
- [[ $f == debug ]] && continue # XXX
- check_flavors[${#check_flavors[@]}]=$f
- done
- check_categories "$dir" $categories
- check_distfiles "$dir" "$dist_subdir" $distfiles
- check_master_sites "$dir" $master_sites
- check_permit_dist "$dir" "$perm_pkg_cdrom" "$perm_pkg_ftp" \
- "$perm_dist_ftp"
- $pkg_exists && check_pkg_dir "$dir"/pkg "$subst_cmd"
- $existing_port || check_shlibs_versions "$dir" $shared_libs
- if [[ -n $gh_commit ]]; then
- local ghclen=$(echo -n "$gh_commit" | wc -c)
- if ((ghclen != 40)); then
- err "GH_COMMIT should be in full form (40 characters)"
- fi
- fi
- for _s in $multi_packages; do
- sub_checks "$dir" "$_s" "${check_flavors[@]}"
- done
- pkgpath=${pkgpath:-"$pkgpath_this"}
- last_subst_cmd="$subst_cmd"
- }
- # Checks made: obvious
- check_trailing_whitespace() {
- egrep -q '[[:space:]]+$' "$1" &&
- err "trailing whitespace in $1"
- }
- # Checks made: obvious
- check_newline_at_eof() {
- (( $(tail -1 -- "$1" | wc -l) == 0)) &&
- err "no newline at EOF in $1"
- }
- # Checks made:
- # * Every library in SHARED_LIBS has 0.0 version.
- check_shlibs_versions() {
- $debugging && echo "CALLED: check_shlibs_versions($*)" >&2
- local dir=$1; shift
- local lib
- local libver
- local portref=$(portref "$dir")
- while (($# > 1)); do
- lib=$1
- libver=$2
- if [[ $libver != 0.0 ]]; then
- err "${portref}the $lib shared library has" \
- "version $libver instead of 0.0"
- fi
- shift 2
- done
- }
- # Checks made:
- # * All top-level category names are well-known.
- check_categories() {
- $debugging && echo "CALLED: check_categories($*)" >&2
- local dir=$1; shift
- local portref=$(portref "$dir")
- for c in "$@"; do
- c=${c%%/*}
- if ! echo "$c" | egrep -q "^($top_level_categories)\$"; then
- err "${portref}non-standard top-level category: $c"
- fi
- done
- }
- # Checks made:
- # * Distfiles with useless names go into DIST_SUBDIR or have {url} suffix.
- check_distfiles() {
- $debugging && echo "CALLED: check_distfiles($*)" >&2
- local dir=$1; shift
- local dist_subdir=$1; shift
- local portref=$(portref "$dir")
- # do not care about absent distfiles, this is fine for meta ports
- while (($# > 1)); do
- # try to catch "version-only" names, but not anything more
- if [[ $1 == ?(v)?(.)+([0-9])?(.+([0-9]))*(.+([a-z])) &&
- -z $dist_subdir && $1 != *\{*\} ]]; then
- err "${portref}badly named distfile $1 without" \
- "DIST_SUBDIR or {url} postfix"
- fi
- shift
- done
- }
- # Checks made:
- # * No unreliable (without fixed distfiles) hosting listed in MASTER_SITES.
- check_master_sites() {
- $debugging && echo "CALLED: check_master_sites($*)" >&2
- local dir=$1; shift
- local portref=$(portref "$dir")
- local name
- while (($# > 1)); do
- case "$1" in
- http?(s)://bitbucket.com/*) name=BitBucket;;
- http?(s)://gitorious.com/*) name=Gitorious;;
- *) name=;;
- esac
- [[ -n $name ]] && err "$portref$name does not hold real" \
- "releases, please host the distfiles somewhere" \
- "else or ask someone to do this for you"
- shift
- done
- }
- # Run checks that are FLAVOR/SUBPACKAGE-dependent.
- sub_checks() {
- $debugging && echo "CALLED: sub_checks($*)" >&2
- local dir=$1; shift
- local subpkg=$1; shift
- local flavor
- for flavor in "$@"; do
- # avoid extra noise
- [[ ${flavor#no_} != ${flavor} &&
- ${subpkg#-} == ${flavor#no_} ]] &&
- continue
- (
- cd -- "$dir"
- portref=$(portref "$dir" "$subpkg" "$flavor" "$*")
- export SUBPACKAGE="$subpkg" FLAVOR="$flavor"
- local wantlib_var=WANTLIB${subpkg%-}
- local vars="COMMENT$subpkg FULLPKGNAME$subpkg"
- vars="$vars MODULES"
- vars="$vars PKG_ARCH$subpkg $wantlib_var WANTLIB-"
- vars="$vars PERMIT_PACKAGE_CDROM${subpkg%-}"
- vars="$vars PERMIT_PACKAGE_FTP${subpkg%-}"
- make "${make_args[@]}" show="$vars" | {
- local comment fullpkgname modules pkg_arch
- local wantlib perm_pkg_cdrom perm_pkg_ftp
- read -r comment
- read -r fullpkgname
- read -r modules
- read -r pkg_arch
- read -r wantlib
- read -r wantlib_ss
- read -r perm_pkg_cdrom
- read -r perm_pkg_ftp
- if [[ $comment == @(a|an|the)" "* ]]; then
- err "${portref}no leading articles in" \
- "COMMENT${subpkg%-}, please"
- fi
- if [[ $pkg_arch == "*" && -n $wantlib ]]; then
- if [[ $subpkg != - || -n $wantlib_ss ]]; then
- err "${portref}non-empty $wantlib_var for" \
- "arch-independent package"
- fi
- fi
- check_wantlib "$portref" "$modules" $wantlib
- check_permit_subpkg "$portref" "$subpkg" \
- "$perm_pkg_cdrom" "$perm_pkg_ftp"
- if $plist_checks; then
- (make "${make_args[@]}" \
- print-plist-with-depends || true) \
- </dev/null |&
- check_plist "$portref" "$fullpkgname" \
- "$flavor" "${subpkg%-}" "$modules"
- check_lib_depends "$portref" "$subpkg" \
- "$modules" "$wantlib"
- wait
- fi
- ! $error
- } || error=true
- ! $error
- ) || error=true
- done
- wait
- }
- # Checks made:
- # * If package installs system-wide icons, it should have the
- # x11/gtk+3,-guic dependency and @exec/@unexec-delete with
- # %D/bin/gtk-update-icon-cache -q -t %D/share/icons/$theme
- # for each icon theme used in package. If there is an
- # index.theme provided, then, instead of gtk-update-icon-cache,
- # @unexec-delete should contain the following command:
- # rm -f %D/share/icons/$theme/icon-theme.cache
- #
- # * If package adds a MIME type handler, it should have the
- # devel/desktop-file-utils dependency and @exec/@unexec-delete with
- # %D/bin/update-desktop-database . Unfortunately, it's hard to tell
- # if there is a MIME type handler in .desktop file, so we just
- # trigger if any .desktop files are added to
- # ${PREFIX}/share/applications/ .
- #
- # * If package adds a MIME types package, it should have the
- # misc/shared-mime-info dependency and @exec/@unexec-delete with
- # %D/bin/update-mime-database %D/share/mime
- #
- # * If package adds a GLib schema, it should have @exec/@unexec-delete
- # with %D/bin/glib-compile-schemas %D/share/glib-2.0/schemas >/dev/null
- # and "devel/dconf" in MODULES (or at least RDEP on devel/dconf).
- #
- # * If package installs .mo files under ${PREFIX}/share/locale/, then
- # run-time dependency on devel/gettext should exists.
- #
- # * If package installs files under ${PREFIX}/share/dbus-1/system-services/,
- # it must have a run-time dependency on x11/dbus,-suid.
- #
- # * Each .py should have corresponding .pyc files, to avoid
- # generation of the latter at run-time.
- #
- # * Manual (man and info) pages should go under ${PREFIX}/{man,info},
- # not under ${PREFIx}/share/{man,info}.
- #
- # * Manual pages shouldn't be compressed.
- check_plist() {
- $debugging && echo "CALLED: check_plist($*)" >&2
- local portref=$1; shift
- local fullpkgname=$1; shift
- local flavor_list=$1; shift
- local subpkg=$1; shift
- local modules_list=$1; shift
- local flavor is_static=false
- for flavor in $flavor_list; do
- [[ $flavor == static ]] && is_static=true
- done
- local guic_dep=false
- local guic_dep_needed=false
- local guic_exec_cnt=0
- local guic_unexec_cnt=0
- local mime_dep=false
- local mime_dep_needed=false
- local mime_exec_cnt=0
- local mime_unexec_cnt=0
- local mimepkg_dep=false
- local mimepkg_dep_needed=false
- local mimepkg_exec_cnt=0
- local mimepkg_unexec_cnt=0
- local dconf_module
- if [[ $modules_list == ?(* )devel/dconf?( *) ]]; then
- dconf_module=true
- else
- dconf_module=false
- fi
- local dconf_dep=false
- local dconf_dep_needed=false
- local dconf_exec_cnt=0
- local dconf_unexec_cnt=0
- # Lists of icon themes discovered through reading
- # @file, @exec and @unexec lines, accordingly.
- local icon_themes= exec_icon_themes= unexec_icon_themes=
- # List of icon themes that remove cache file
- local rm_cache_themes=
- local gettext_dep=false
- local translation_found=false
- local dbus_suid_dep=false
- local dbus_suid_dep_needed=false
- # Lists of .py, .pyc and .pyo items found, accordingly
- local py_files= pyc_files= pyo_files=
- unset py_files[0] pyc_files[0] pyo_files[0]
- local wrong_man=false wrong_info=false
- local regsh=false unregsh=false
- local regsh_exec=false unregsh_exec=false
- # Temporary ones
- local app l theme varname py
- while read -pr l; do
- case "$l" in
- "@comment "*)
- # ignore
- ;;
- share/icons/*/*/*|share/icons/*/@(index.theme|iconrc?(-png)))
- # Themes have at least two levels in depth.
- #
- # We match directories by purpose, this helps to catch
- # update-plist fuckups, when directories go into one
- # package and actual icons go in another.
- guic_dep_needed=true
- theme=${l#share/icons/}
- theme=${theme%%/*}
- # wrap with the '/' characters to avoid erroneous matching
- echo "$icon_themes" | fgrep -q "/$theme/" ||
- icon_themes="$icon_themes /$theme/"
- if [[ "$l" = "share/icons/$theme/index.theme" ]]; then
- echo "$rm_cache_themes" | fgrep -q "/$theme/" ||
- err "${portref}missing @unexec-delete rm -f" \
- "%D/share/icons/$theme/icon-theme.cache"
- fi
- ;;
- share/icons/*(*/))
- # Do not match intermediate directories to avoid false
- # positives.
- ;;
- share/icons/*.xpm)
- app=${l#share/icons/}
- app=${app%%/*}
- app=${app%%.*}
- err "${portref}installs icon ${l##*/} in ${l%/*}, it" \
- "should likely go in share/pixmaps/ instead"
- ;;
- share/icons/default.*)
- ;;
- share/icons/*)
- app=${l#share/icons/}
- app=${app%%/*}
- app=${app%%.*}
- err "${portref}installs icon ${l##*/} in ${l%/*}, it" \
- "should go in share/$app/icons/ or like instead"
- ;;
- "@depend x11/gtk+3,-guic"*)
- guic_dep=true
- ;;
- "@exec %D/bin/gtk-update-icon-cache -q -t %D/share/icons/"*)
- theme=${l##*/}
- varname=$(echo "$theme" | sed -e 's/[^a-zA-Z_]/_/g')
- ((++guic_exec_cnt))
- eval "((++guic_exec_cnt_$varname))"
- exec_icon_themes="$exec_icon_themes /$theme/"
- ;;
- "@unexec-delete %D/bin/gtk-update-icon-cache -q -t %D/share/icons/"*)
- theme=${l##*/}
- varname=$(echo "$theme" | sed -e 's/[^a-zA-Z_]/_/g')
- ((++guic_unexec_cnt))
- eval "((++guic_unexec_cnt_$varname))"
- unexec_icon_themes="$unexec_icon_themes /$theme/"
- ;;
- "@unexec-delete rm -f "%D/share/icons/*/icon-theme.cache)
- # as an alternative, port could zap the theme entirely
- theme=${l#*/icons/}
- theme=${theme%/icon-theme.cache}
- varname=$(echo "$theme" | sed -e 's/[^a-zA-Z_]/_/g')
- ((++guic_unexec_cnt))
- eval "((++guic_unexec_cnt_$varname))"
- unexec_icon_themes="$unexec_icon_themes /$theme/"
- rm_cache_themes="$rm_cache_themes /$theme/"
- if echo "$icon_themes" | fgrep -q "/$theme/"; then
- err "${portref}the @unexec-delete line removing" \
- "%D/share/icons/$theme/icon-theme.cache" \
- "does not preceed all of the icon theme" \
- "$theme files"
- fi
- ;;
- @?(un)exec?(-delete|-update)" %D/bin/gtk-update-icon-cache"*)
- err "${portref}incorrect gtk-update-icon-cache" \
- "invocation: ${l#@* }"
- ;;
- share/applications/*(*/)*.desktop)
- mime_dep_needed=true
- ;;
- "@depend devel/desktop-file-utils"*)
- mime_dep=true
- ;;
- "@exec %D/bin/update-desktop-database")
- ((++mime_exec_cnt))
- ;;
- "@unexec-delete %D/bin/update-desktop-database")
- ((++mime_unexec_cnt))
- ;;
- @?(un)exec?(-delete|-update)" %D/bin/update-desktop-database"*)
- err "${portref}incorrect update-desktop-database" \
- "invocation: ${l#@* }"
- ;;
- share/mime/packages/*.xml)
- mimepkg_dep_needed=true
- ;;
- "@depend misc/shared-mime-info"*)
- mimepkg_dep=true
- ;;
- "@exec %D/bin/update-mime-database %D/share/mime")
- ((++mimepkg_exec_cnt))
- ;;
- "@unexec-delete %D/bin/update-mime-database %D/share/mime")
- ((++mimepkg_unexec_cnt))
- ;;
- @?(un)exec?(-delete|-update)" %D/bin/update-mime-database"*)
- err "${portref}incorrect update-mime-database" \
- "invocation: ${l#@* }"
- ;;
- share/glib-2.0/schemas/*.xml)
- dconf_dep_needed=true
- ;;
- "@depend devel/dconf"*)
- dconf_dep=true
- ;;
- "@exec %D/bin/glib-compile-schemas %D/share/glib-2.0/schemas >/dev/null")
- ((++dconf_exec_cnt))
- ;;
- "@unexec-delete %D/bin/glib-compile-schemas %D/share/glib-2.0/schemas >/dev/null")
- ((++dconf_unexec_cnt))
- ;;
- @?(un)exec?(-delete|-update)" %D/bin/glib-compile-schemas"*)
- err "${portref}incorrect glib-compile-schemas" \
- "invocation: ${l#@* }"
- ;;
- "@depend devel/gettext"*)
- gettext_dep=true
- ;;
- share/locale/*/*/*.mo)
- translation_found=true
- ;;
- share/dbus-1/system-services/*)
- dbus_suid_dep_needed=true
- ;;
- "@depend x11/dbus,-suid"*)
- dbus_suid_dep=true
- ;;
- lib/ghc/*/register.sh)
- regsh=true
- ;;
- lib/ghc/*/unregister.sh)
- unregsh=true
- ;;
- "@exec /usr/bin/env HOME=/nonexistent "%D/lib/ghc/*/register.sh" -v0")
- regsh_exec=true
- ;;
- "@unexec /usr/bin/env HOME=/nonexistent "%D/lib/ghc/*/unregister.sh" -v0 --force")
- unregsh_exec=true
- if $unregsh; then
- err "${portref}unregister.sh call placed before" \
- "script itself in PLIST${subpkg}"
- fi
- ;;
- # XXX KSH arrays are limited to 10239 items
- share/@(doc|*(*/)examples)+(/*).py|?(s)bin/*.py)
- # ignore
- ;;
- *.py)
- py_files[${#py_files[@]}]=$l
- ;;
- *.pyc)
- pyc_files[${#pyc_files[@]}]=$(normalize_pyco "$l")
- ;;
- *.pyo)
- pyo_files[${#pyo_files[@]}]=$(normalize_pyco "$l")
- ;;
- share/man/*)
- wrong_man=true
- ;;
- share/info/*)
- wrong_info=true
- ;;
- "@man "*.gz)
- err "${portref}compressed $l"
- ;;
- esac
- done
- # gtk-update-icon-cache
- $guic_dep_needed && ! $guic_dep &&
- [[ $fullpkgname != gtk-update-icon-cache-* ]] &&
- err "${portref}missing RDEP on x11/gtk+3,-guic"
- local cnt
- for theme in $icon_themes; do
- theme=${theme#/}
- theme=${theme%/}
- varname=$(echo "$theme" | sed -e 's/[^a-zA-Z_]/_/g')
- ((guic_exec_cnt--)) || true
- ((guic_unexec_cnt--)) || true
- eval "((guic_exec_cnt_$varname--)) || true"
- eval "((guic_unexec_cnt_$varname--)) || true"
- eval "cnt=\$guic_exec_cnt_$varname"
- if (($cnt > 0)); then
- err "${portref}extra @exec of gtk-update-icon-cache" \
- "for icon theme $theme"
- ((guic_exec_cnt--)) || true
- elif (($cnt < 0)); then
- err "${portref}missing @exec of gtk-update-icon-cache" \
- "for icon theme $theme"
- fi
- eval "cnt=\$guic_unexec_cnt_$varname"
- if (($cnt > 0)); then
- err "${portref}extra @unexec-delete of gtk-update-icon-cache" \
- "for icon theme $theme"
- ((guic_unexec_cnt--)) || true
- elif (($cnt < 0)); then
- err "${portref}missing @unexec-delete of gtk-update-icon-cache" \
- "for icon theme $theme"
- fi
- done
- for theme in $exec_icon_themes; do
- theme=${theme#/}
- theme=${theme%/}
- echo "$icon_themes" | fgrep -q "/$theme/" ||
- err "${portref}doing @exec of gtk-update-icon-cache" \
- "for absent icon theme $theme"
- done
- for theme in $unexec_icon_themes; do
- theme=${theme#/}
- theme=${theme%/}
- echo "$icon_themes" | fgrep -q "/$theme/" ||
- err "${portref}doing @unexec-delete of gtk-update-icon-cache" \
- "for absent icon theme $theme"
- done
- ((guic_exec_cnt > 0)) &&
- err "${portref}extra @exec of gtk-update-icon-cache"
- ((guic_unexec_cnt > 0)) &&
- err "${portref}extra @unexec-delete of gtk-update-icon-cache"
- # desktop-file-utils (simplier than previous, isn't it?)
- $mime_dep_needed && ! $mime_dep &&
- [[ $fullpkgname != desktop-file-utils-* ]] &&
- err "${portref}missing RDEP on devel/desktop-file-utils"
- if $mime_dep_needed; then
- ((mime_exec_cnt--)) || true
- ((mime_unexec_cnt--)) || true
- fi
- if ((mime_exec_cnt > 0)) &&
- [[ $fullpkgname != desktop-file-utils-* ]]; then
- err "${portref}extra @exec of update-desktop-database"
- elif ((mime_exec_cnt < 0)); then
- err "${portref}missing @exec of update-desktop-database"
- fi
- if ((mime_unexec_cnt > 0)); then
- err "${portref}extra @unexec-delete of update-desktop-database"
- elif ((mime_unexec_cnt < 0)); then
- err "${portref}missing @unexec-delete of update-desktop-database"
- fi
- # update-mime-database (same as previous)
- $mimepkg_dep_needed && ! $mimepkg_dep &&
- [[ $fullpkgname != shared-mime-info-* ]] &&
- err "${portref}missing RDEP on misc/shared-mime-info"
- if $mimepkg_dep_needed; then
- ((mimepkg_exec_cnt--)) || true
- ((mimepkg_unexec_cnt--)) || true
- fi
- if ((mimepkg_exec_cnt > 0)) &&
- [[ $fullpkgname != shared-mime-info-* ]]; then
- err "${portref}extra @exec of update-mime-database"
- elif ((mimepkg_exec_cnt < 0)); then
- err "${portref}missing @exec of update-mime-database"
- fi
- if ((mimepkg_unexec_cnt > 0)); then
- err "${portref}extra @unexec-delete of update-mime-database"
- elif ((mimepkg_unexec_cnt < 0)); then
- err "${portref}missing @unexec-delete of update-mime-database"
- fi
- # glib-compile-schemas (almost same as previous)
- #
- # TODO: detect situation of extra devel/dconf in MODULES
- # (requires investigation of all subpackages).
- if $dconf_dep_needed; then
- if ! $dconf_module; then
- err "${portref}GLib2 XML schemas found without" \
- "devel/dconf in MODULES"
- elif ! $dconf_dep; then
- err "${portref}missing" \
- "RUN_DEPENDS${subpkg}+=\${MODDCONF_RUN_DEPENDS}"
- fi
- fi
- if $dconf_dep_needed; then
- ((dconf_exec_cnt--)) || true
- ((dconf_unexec_cnt--)) || true
- fi
- if ((dconf_exec_cnt > 0)) &&
- [[ $fullpkgname != glib2-* ]]; then
- err "${portref}extra @exec of glib-compile-schemas"
- elif ((dconf_exec_cnt < 0)); then
- err "${portref}missing @exec of glib-compile-schemas"
- fi
- if ((dconf_unexec_cnt > 0)); then
- err "${portref}extra @unexec-delete of glib-compile-schemas"
- elif ((dconf_unexec_cnt < 0)); then
- err "${portref}missing @unexec-delete of glib-compile-schemas"
- fi
- # gettext
- $translation_found && ! $gettext_dep && ! $is_static &&
- [[ $fullpkgname != gettext-* ]] &&
- err "${portref}translation file(s) found without" \
- "devel/gettext dependency in RUN_DEPENDS"
- # dbus,-suid
- if $dbus_suid_dep_needed && ! $dbus_suid_dep; then
- err "${portref}missing" \
- "RUN_DEPENDS${subpkg}+=x11/dbus,-suid"
- fi
- # Haskell register/unregister
- if $regsh && ! $regsh_exec; then
- err "${portref}missing @exec of register.sh"
- fi
- if $unregsh && ! $unregsh_exec; then
- err "${portref}missing @unexec of unregister.sh"
- fi
- # Python modules
- ((${#py_files[@]} > 0)) && set -sA py_files -- "${py_files[@]}"
- ((${#pyc_files[@]} > 0)) && set -sA pyc_files -- "${pyc_files[@]}"
- ((${#pyo_files[@]} > 0)) && set -sA pyo_files -- "${pyo_files[@]}"
- local ic=0 io=0
- if ((${#py_files[@]} > 0)); then for py in "${py_files[@]}"; do
- while [[ $ic -lt ${#pyc_files[@]} ]]; do
- [[ ${pyc_files[$ic]} < "$py"c ]] || break
- # allowed behaviour
- #err "${portref}compiled Python module without" \
- # "source, expected: ${pyc_files[$ic]%c}"
- ((++ic))
- done
- if [[ $ic -lt ${#pyc_files[@]} &&
- ${pyc_files[$ic]} == "$py"c ]]; then
- ((++ic))
- else
- err "${portref}Python module without" \
- "compiled version, consider using" \
- "\${MODPY_BIN} \${MODPY_LIBDIR}/compileall.py: $py"
- fi
- while [[ $io -lt ${#pyo_files[@]} ]]; do
- [[ ${pyo_files[$io]} < "$py"o ]] || break
- # allowed behaviour
- #err "${portref}optimized Python module without" \
- # "source, expected: ${pyo_files[$io]%o}"
- ((++io))
- done
- if [[ $io -lt ${#pyo_files[@]} &&
- ${pyo_files[$io]} == "$py"o ]]; then
- ((++io))
- # too much noise, maybe enable in the future
- #else
- # err "${portref}Python module without" \
- # "optimized version: $py"
- fi
- done; fi
- # allowed behaviour
- #while (($ic < ${#pyc_files[@]})); do
- # err "${portref}compiled Python module without source," \
- # "expected: ${pyc_files[$ic]%c}"
- # ((++ic))
- #done
- # allowed behaviour
- #while (($io < ${#pyo_files[@]})); do
- # err "${portref}optimized Python module without source," \
- # "expected: ${pyo_files[$io]%o}"
- # ((++io))
- #done
- $wrong_man && err "${portref}manual pages should go under" \
- "\${PREFIX}/man/ rather than under \${PREFIX}/share/man/"
- $wrong_info && err "${portref}info pages should go under" \
- "\${PREFIX}/info/ rather than under \${PREFIX}/share/info/"
- }
- # Checks made:
- # * devel/gettext dependency is not forgotten.
- # * lib/kde/ and lib/kde4/ prefixes not missing where applicable.
- # * stdc++ doesn't get into WANTLIB when gcc4.port.mk is used.
- check_wantlib() {
- local portref="$1"; shift
- local modules="$1"; shift
- local phonon_s_wantlib=false
- local kde3_module=false
- local kde4_module=false
- local phonon_module=false
- local gcc4_module=false
- local v
- for v in $modules; do case $v in
- gcc4) gcc4_module=true;;
- multimedia/phonon) phonon_module=true;;
- x11/kde) kde3_module=true;;
- x11/kde4) kde4_module=true;;
- esac; done
- for v; do case $v in
- phonon_s?(?(">")=+([0-9])))
- phonon_s_wantlib=true
- ;;
- @(smbclient|wbclient)?(?('>')=+([0-9])))
- err "$portref$v instead of lib/samba/$v" \
- "in WANTLIB"
- ;;
- @(DCOP|soundserver_idl|vcard)?(?('>')=+([0-9])))
- err "$portref$v instead of \${KDE}/$v" \
- "in WANTLIB (check other libs, too!)"
- ;;
- @(kdecore|kdeui|kio)?(?('>')=+([0-9])))
- if $kde4_module; then
- err "$portref$v instead of \${KDE4LIB}/$v" \
- "in WANTLIB (check other libs, too!)"
- elif $kde3_module; then
- err "$portref$v instead of \${KDE}/$v" \
- "in WANTLIB (check other libs, too!)"
- else
- err "$portref$v WANTLIB without x11/kde*" \
- "in MODULES (check other libs, too!)"
- fi
- ;;
- stdc++?(?('>')=+([0-9])))
- if $gcc4_module; then
- err "$portref$v in WANTLIB when gcc4 is" \
- "in MODULES; run port-lib-depends-check" \
- "and if stdc++ is still there, check" \
- "actual build thoroughly, it's broken"
- fi
- esac; done
- if $phonon_s_wantlib && ! $phonon_module; then
- err "${portref}missing multimedia/phonon in MODULES"
- fi
- true
- }
- # Checks made:
- # * Each library mentioned in WANTLIB is accessible either:
- # a) as a part of base system, in /usr/lib or /usr/X11R6/lib;
- # b) via LIB_DEPENDS directly, or via deeper dependency of LIB_DEPENDS.
- check_lib_depends() {
- $debugging && echo "CALLED: check_lib_depends($*)" >&2
- local portref="$1"; shift
- local subpkg="$1"; shift
- local modules="$1"; shift
- local wantlib="$1"; shift
- # The idea as follows: build full list of run-time dependencies, but
- # without RUN_DEPENDS begin involved.
- #
- # Then we look at libs in each pkgpath we got, and strip those
- # from WANTLIB. We also strip system libraries from /usr/lib
- # and /usr/X11R6/lib. And all WANTLIBs coming from MODULES are stripped
- # too, supposing that authors of those MODULES know what they're doing
- # (without stripping 'em, we'll get many false positives).
- #
- # If there are any non-stripped items in WANTLIB, we found a problem.
- #
- # XXX those checks do not take actual versions into account!
- # get list of all WANTLIBs coming from MODULES
- local m modvars=
- for m in $modules; do
- m=${m##*/}
- case $m in
- python)
- m=py
- ;;
- esac
- m=$(echo "MOD${m}_WANTLIB" | tr a-z A-Z)
- modvars="$modvars $m"
- done
- local l modlibs=
- make "${make_args[@]}" show="$modvars" </dev/null |&
- while read -pr l; do
- modlibs="$modlibs $l"
- done
- wait # make sure process exited before possible return below
- # strip WANTLIBs coming from MODULES
- local libsleft wl
- for l in $modlibs; do
- libsleft=
- for wl in $wantlib; do
- if [[ $l != "$wl" ]]; then
- libsleft="$libsleft $wl"
- elif $debugging; then
- echo "WANTLIB ITEM $wl COMES FROM MODULES"
- fi
- done
- [[ -n $libsleft ]] || return 0 # all libs found
- wantlib=$libsleft
- done
- # prepare easy-to-use WANTLIB list in $checklibs
- local wlprefix checklibs=
- for wl in $wantlib; do
- wl=${wl%%[><=]*}
- wlprefix=${wl%/*}
- [[ $wlprefix == "$wl" ]] && wlprefix=lib
- wl=${wl##*/}
- checklibs="$checklibs ${wlprefix}/lib$wl"
- done
- # strip system libraries
- local d
- for d in /usr /usr/X11R6; do
- for l in $d/lib/lib*.@(so*(.+([0-9]))|a); do
- libsleft=
- for wl in $checklibs; do
- if [[ $l != +(/*)/${wl}.@(so*(.+([0-9]))|a) ]]; then
- libsleft="$libsleft $wl"
- elif $debugging; then
- echo "FOUND WANTLIB ITEM $wl: $l"
- fi
- done
- [[ -n $libsleft ]] || return 0 # all libs found
- checklibs=$libsleft
- done
- done
- # get deep list of LDEPs
- local lmake_args="${make_args[@]}"
- lmake_args[${#lmake_args[@]}]="RUN_DEPENDS="
- lmake_args[${#lmake_args[@]}]="RUN_DEPENDS$subpkg="
- # Rely on the fact we're already in the port directory, see sub_checks().
- # XXX ignoring make errors for now
- local pure_lib_deps=$(make "${lmake_args[@]}" show-run-depends | sort)
- [[ -n $pure_lib_deps ]] || return 0
- # SUBDIR doesn't accept newline-separated values
- set -A pure_lib_deps -- $pure_lib_deps
- (
- # strip libraries from ports
- # TODO cache print-plist-libs output?
- cd -- /usr/ports # XXX "$portsdir" fails for openbsd-wip and like
- unset FLAVOR SUBPACKAGE
- make "${make_args[@]}" SUBDIR="${pure_lib_deps[*]}" \
- print-plist-libs </dev/null 2>/dev/null |&
- while read -pr l; do
- case $l in
- "===> "*)
- ;;
- *)
- libsleft=
- for wl in $checklibs; do
- if [[ $l != +(/*)/${wl}.@(so*(.+([0-9]))|a) ]]; then
- libsleft="$libsleft $wl"
- elif $debugging; then
- echo "FOUND WANTLIB ITEM $wl: $l"
- fi
- done
- [[ -n $libsleft ]] || exit 0 # all libs found
- checklibs=$libsleft
- ;;
- esac
- done
- # prettify list of WANTLIBs left and print it
- libsleft=
- for wl in $checklibs; do
- libsleft="$libsleft ${wl##*/lib}"
- done
- err "${portref}the following libraries in WANTLIB${subpkg%-}" \
- "look like masked by RUN_DEPENDS${subpkg%-}:$libsleft"
- wait
- ! $error
- ) || error=true
- }
- # Checks made:
- # * No extra PERMIT_DISTFILES_FTP variables in Makefile.
- # * PERMIT_DISTFILES_FTP should not contain just "No" but a reason.
- #
- # Runs in the port directory.
- # XXX does not handle Makefile.inc and other .include cases correctly.
- check_permit_dist() {
- $debugging && echo "CALLED: check_permit_dist($*)" >&2
- local portref=$(portref $1); shift
- local perm_pkg_cdrom=$(echo "$1" | tr '[:upper:]' '[:lower:]')
- local perm_pkg_ftp=$(echo "$2" | tr '[:upper:]' '[:lower:]')
- local perm_dist_ftp=$(echo "$3" | tr '[:upper:]' '[:lower:]')
- if [[ ($perm_pkg_cdrom == yes || $perm_pkg_ftp == yes) && \
- $perm_dist_ftp == yes ]]; then
- egrep -sq "^ *PERMIT_DISTFILES_FTP[[:space:]]*=" Makefile &&
- err "${portref}extra PERMIT_DISTFILES_FTP line(-s)"
- fi
- if [[ $perm_dist_ftp == no ]]; then
- err "${portref}PERMIT_DISTFILES_FTP should be either" \
- "\"Yes\" or a reason for being non-redistributable"
- fi
- true
- }
- # Checks made:
- # * No extra PERMIT_PACKAGE_FTP variables in Makefile.
- # * PERMIT_PACKAGE_* should not contain just "No" but a reason.
- #
- # Runs in the port directory.
- # XXX does not handle Makefile.inc and other .include cases correctly.
- check_permit_subpkg() {
- $debugging && echo "CALLED: check_permit_subpkg($*)" >&2
- local portref=$1; shift
- local subpkg=${1%-}; shift
- local perm_pkg_cdrom=$(echo "$1" | tr '[:upper:]' '[:lower:]')
- local perm_pkg_ftp=$(echo "$2" | tr '[:upper:]' '[:lower:]')
- if [[ $perm_pkg_cdrom == yes && $perm_pkg_ftp == yes ]]; then
- egrep -q "^ *PERMIT_PACKAGE_FTP${subpkg}[[:space:]]*=" Makefile &&
- err "${portref}extra PERMIT_PACKAGE_FTP lines"
- fi
- if [[ $perm_pkg_cdrom == no ]]; then
- err "${portref} PERMIT_PACKAGE_CDROM should be either" \
- "\"Yes\" or a reason for being non-redistributable"
- fi
- if [[ $perm_pkg_ftp == no ]]; then
- err "${portref} PERMIT_PACKAGE_FTP should be either" \
- "\"Yes\" or a reason for being non-redistributable"
- fi
- true
- }
- # Checks made:
- # * Directory is not empty
- # * No '*.core' files present
- check_files_dir() {
- $debugging && echo "CALLED: check_files_dir($*)" >&2
- find -f "$1" -- -type f | {
- local empty=true
- local mode
- while read F; do
- ignoring "$F" && continue
- mode=$(stat -f %p "$F" || true)
- (( (0$mode & 0111) != 0 )) &&
- err "executable file: $F"
- empty=false
- [[ $F == *.core ]] &&
- err_coredump_found "$F"
- done
- $empty && err "there are no files, please remove the $1 directory"
- ! $error
- } || error=true
- }
- # Checks made:
- # * The patch is not empty.
- # * The patch contains an OpenBSD RCS tag.
- check_patch() {
- local F=$1
- test -f "$F" || {
- err "$F is not a file"
- return
- }
- if [ -s "$F" ]; then
- head -n 1 -- "$F" | egrep -q '^\$OpenBSD.*\$$' ||
- err "$F does not have \$OpenBSD\$ RCS tag at the top"
- else
- err "$F is empty and should be removed"
- fi
- }
- # Checks made:
- # * Each patch contains OpenBSD RCS tag.
- # * Directory is not empty and consists only of plain files starting
- # with 'patch-' and not ending with '.orig'.
- check_patches_dir() {
- $debugging && echo "CALLED: check_patches_dir($*)" >&2
- local empty=true
- local F
- check_perms_in_dir "$1"
- for F in "$1"/* "$1"/.*; do case "${F##*/}" in
- patch-*.orig)
- handle_extra_file "$F"
- ;;
- patch-*)
- empty=false
- $rootrun || check_patch "$F"
- ;;
- *)
- handle_extra_file "$F"
- ;;
- esac; done
- $empty && err "there are no patches, please remove the $1 directory instead"
- }
- # Checks made:
- # * Directory is not empty and consist only of plain files with fixed names.
- # * PFRAG, PLIST, README and .rc files contain appropriate OpenBSD RCS
- # tags; other files should NOT contain OpenBSD RCS tag.
- # * PFRAG.shared should be merged into PLIST.
- # * No trailing whitespace for DESCR, MESSAGE, README, UNMESSAGE and
- # .rc files (PLIST and PFRAG are better checked with "make package").
- # * See also check_plist_file().
- check_pkg_dir() {
- $debugging && echo "CALLED: check_pkg_dir($*)" >&2
- local dir=$1; shift
- local subst_cmd
- if (($# > 0)); then
- # XXX should find the way to always obtain SUBST_CMD
- subst_cmd=$1
- shift
- fi
- local empty=true
- local F
- local plist
- check_perms_in_dir "$dir"
- dir="${dir#./}"
- for F in "$dir"/* "$dir"/.*; do case "${F##*/}" in
- DESCR?(-*))
- empty=false
- [[ -f $F ]] ||
- err "$F is not a file"
- check_trailing_whitespace "$F"
- check_newline_at_eof "$F"
- check_long_lines "$F"
- check_hardcoded "$F"
- [[ -n $subst_cmd ]] && check_subst_vars "$F" "$subst_cmd"
- egrep -q '\$OpenBSD.*\$' "$F" &&
- err "$F should not contain \$OpenBSD\$ tag"
- ;;
- PFRAG.shared?(-*))
- empty=false
- [[ -n $subst_cmd ]] && check_subst_vars "$F" "$subst_cmd"
- check_plist_file "$F"
- plist=PLIST${F##*/PFRAG.+([!-])}
- err "$F should be merged into $plist"
- ;;
- PFRAG.*|PLIST?(-*))
- empty=false
- [[ -n $subst_cmd ]] && check_subst_vars "$F" "$subst_cmd"
- check_plist_file "$F"
- ;;
- README?(-*))
- [[ -f $F ]] ||
- err "$F is not a file"
- [[ -n $subst_cmd ]] && check_subst_vars "$F" "$subst_cmd"
- check_trailing_whitespace "$F"
- check_newline_at_eof "$F"
- check_long_lines "$F"
- check_hardcoded "$F"
- head -n 1 -- "$F" |
- egrep -q '^(#[[:space:]]*)?\$OpenBSD(:.*)?\$$' ||
- err "$F does not have \$OpenBSD\$ RCS tag at the top"
- ;;
- *.rc)
- [[ -f $F ]] ||
- err "$F is not a file"
- [[ ${F##*/} == [A-Za-z_]*([A-Za-z0-9_]).rc ]] ||
- err "$F name will not work in rc.subr(8)"
- check_trailing_whitespace "$F"
- check_long_lines "$F"
- check_hardcoded "$F"
- head -n 5 -- "$F" |
- egrep -q '^#[[:space:]]*\$OpenBSD(:.*)?\$$' ||
- err "$F does not have \$OpenBSD\$ RCS tag at the top"
- ;;
- MESSAGE?(-*)|UNMESSAGE?(-*))
- [[ -f $F ]] ||
- err "$F is not a file"
- [[ -n $subst_cmd ]] && check_subst_vars "$F" "$subst_cmd"
- check_trailing_whitespace "$F"
- check_newline_at_eof "$F"
- check_long_lines "$F"
- check_hardcoded "$F"
- egrep -q '\$OpenBSD.*\$' "$F" &&
- err "$F should not contain \$OpenBSD\$ tag"
- ;;
- *)
- handle_extra_file "$F"
- ;;
- esac; done
- $empty && err "$dir directory does not contain either DESCR, PFRAG or PLIST files"
- }
- # Checks made:
- # * There are no hardcoded /usr/local or /var paths in file.
- # /var/log, /var/run and /var/tmp are perfectly fine, though.
- check_hardcoded() {
- $debugging && echo "CALLED: check_hardcoded($*)" >&2
- perl -n -e 'BEGIN { $ec=0; }
- if (m,/usr/local\b,o) { $ec=1; close ARGV; }
- if (m,/var((?:/+[^/\s]+)*)(?:\s.*)?$,o) {
- unless ($1 =~ m,^/+(?:log|run|tmp),o) {
- $ec=1; close ARGV;
- }
- }
- END { $? = $ec; }' \
- "$1" || err "hardcoded paths detected in $1, consider using" \
- "SUBST_VARS and TRUEPREFIX/LOCALBASE/LOCALSTATEDIR/VARBASE"
- }
- # Checks made:
- # * There are no lines longer than 80 characters that have at least
- # one space (avoids warnings on long URLs etc.).
- check_long_lines() {
- $debugging && echo "CALLED: check_long_lines($*)" >&2
- local file=$1; shift
- local n=$(awk <"$file" \
- '/[[:space:]]/ && length > 80 { n++ } END { print n+0 }')
- (($n > 0 )) &&
- err "$n line(s) longer than 80 chars in $file"
- }
- # Checks made:
- # * There is an OpenBSD RCS tag at the top.
- # * No items with ${FULLPKGNAME} are allowed, except readme.
- # * No empty lines.
- check_plist_file() {
- $debugging && echo "CALLED: check_plist_file($*)" >&2
- [[ -f $1 ]] ||
- err "$1 is not a file"
- head -n 1 -- "$1" |
- egrep -q '^@comment \$OpenBSD.*\$$' ||
- err "$1 does not have \$OpenBSD\$ RCS tag at the top"
- # Do not match just '${FULLPKGNAME}' because many ports use the
- # following trick:
- # @cwd ${LOCALBASE}/share/doc/pkg-readmes
- # ${FULLPKGNAME}
- egrep -v '^(share/doc/pkg-readmes/\$\{FULLPKGNAME\}|@comment .*)$' "$1" |
- egrep '.\$\{FULLPKGNAME\}|\$\{FULLPKGNAME\}.' >&2 &&
- err "$1 contains item(s) with \${FULLPKGNAME} in it, see above"
- egrep -q '^[[:space:]]*$' "$1" && err "$1 contains empty lines"
- }
- # Checks made:
- # * Every variable referenced by ${[A-Z]+} should be in ${SUBST_VARS}.
- check_subst_vars() {
- $debugging && echo "CALLED: check_subst_vars($*)" >&2
- local F=$1; shift
- local subst_cmd=$1; shift
- # Add variables sometimes referenced in port docs.
- eval "$subst_cmd" -DPATH=test -DWRKSRC=test <"$F" |
- egrep '\$\{[A-Z]+\}' >&2 &&
- err "looks like misspelled variables in $F, see above"
- }
- # Checks made:
- # * Contains OpenBSD RCS tag at the top line.
- # * No REVISION marks present in given file (unless in update mode).
- # * Each REVISION mark presents only once.
- # * BUILD_DEPENDS, MODULES and PERMIT_DISTFILES_FTP are not defined in
- # VAR-subpkg manner.
- # * No trailing whitespace.
- # * SHARED_LIBS are not defined inside ".if" statements.
- # * Variables are not assigned via "=" twice outside of .if statemets.
- # * No user settings present.
- # * SHARED_ONLY not defined
- check_makefile() {
- $debugging && echo "CALLED: check_makefile($*)" >&2
- local F="$1"
- check_trailing_whitespace "$F"
- check_long_lines "$F"
- check_hardcoded "$F"
- head -n 1 -- "$F" |
- egrep -q '^#[[:space:]]*\$OpenBSD.*\$' ||
- err "$F does not have \$OpenBSD\$ RCS tag at the top"
- local iflevel=0 l lnum=0 revs= t r mkvars= var duprevfound
- # do not unset mkvars, having empty element(-s) is fine
- unset revs[0]
- local tab="$(print '\t')"
- while IFS= read -r l; do ((++lnum))
- set -A t -- $l
- duprevfound=false
- if echo "$l" | egrep -q "^ *($user_settings)[[:>:]].*\$"; then
- err "user settings in port: $l"
- fi
- case $l in
- *(" ")REVISION*)
- $existing_port ||
- err "REVISION mark found at $F:$lnum"
- var=${t[0]%=}
- if ((${#revs[@]} > 0)); then
- for r in "${revs[@]}"; do
- if [[ $var == "$r" ]]; then
- err "duplicated $r in $F"
- # avoid dup error messages
- duprevfound=true
- break
- fi
- done
- fi
- revs[${#revs[@]}]=${t[0]}
- ;;
- *(" ")@(BUILD_DEPENDS|MODULES|PERMIT_DISTFILES_FTP)-*)
- err "${l%%-*} is not a subpackageble variable, see $F:$lnum"
- ;;
- *(" ").*(" "|"$tab")if*)
- ((++iflevel))
- ;;
- *(" ").*(" "|"$tab")endif*)
- ((iflevel--))
- ;;
- *(" ")SHARED_LIBS*(" "|"$tab")*(+|:|!)=*)
- if ((iflevel > 0)); then
- err "should not be inside .if block ($F:$lnum): $l"
- fi
- ;;
- *(" ")SHARED_ONLY*(" "|"$tab")*(+|:|!|\?)=*)
- err "SHARED_ONLY is deprecated ($F:$lnum)"
- ;;
- esac
- if [[ $l == *(" ")+([A-Za-z0-9_-])*(" "|"$tab")?(\?)=* ]] &&
- ((iflevel == 0)) && ! $duprevfound; then
- var=${t[0]%?(\?)=*}
- for v in "${mkvars[@]}"; do
- if [[ $v == "$var" ]]; then
- err "duplicated assignment of $v" \
- "at $F:$lnum"
- break
- fi
- done
- mkvars[${#mkvars[@]}]=$var
- fi
- done <"$F"
- }
- # Checks made:
- # * None of executable bits (111) are set on plain files.
- check_perms_in_dir() {
- $debugging && echo "CALLED: check_perms_in_dir($*)" >&2
- (find -f "$1" -- -maxdepth 1 -type f \
- \( -perm -100 -or -perm -010 -or -perm 001 \) \
- </dev/null || true) |&
- local F
- while read -pr F; do
- F=${F#./}
- ignoring "$F" && continue
- err "executable file: ${F#./}"
- done
- }
- ############################################################
- # Run checks. Also calculate and show pkgpath variable,
- # unless we're checking the ports tree root dir.
- #
- for D; do
- if [[ $D == /* ]]; then
- err "absolute path $D ignored"
- continue
- fi
- if [[ $D == *(*/)..*(/*) ]]; then
- err "too many .. in $D, skipping"
- continue
- fi
- check_port_dir "$D"
- done
- if ! $rootrun; then
- [[ -z $pkgpath ]] && pkgpath=${PWD##"$portsdir/"}
- if [[ $pkgpath == "$PWD" ]]; then
- cat >&2 <<EOE
- ${0##*/}: could not determine PKGPATH. Please help me with the -p option.
- EOE
- exit 2
- fi
- echo "$pkgpath"
- fi
- ! $error
|