Permalink
Find file
executable file 492 lines (460 sloc) 14.3 KB
#!/bin/bash
test "$1" = "--verbose" && { VERBOSE=true ; shift ; }
test "$1" = "--batchmode" && { BATCHMODE=true ; shift ; }
DIR_TO_CHECK=$1
DESTINATIONDIR=$2
OSC_MODE=""
test -n "$DIR_TO_CHECK" || DIR_TO_CHECK=`pwd`
HELPERS_DIR="/usr/lib/obs/service/source_validators/helpers"
$HELPERS_DIR/check_input_filename "$DIR_TO_CHECK" || exit 1
test -z "$DESTINATIONDIR" -a -d "$DIR_TO_CHECK/.osc" && {
DESTINATIONDIR="$DIR_TO_CHECK/.osc"
OSC_MODE="true"
}
RETURN=0
RPMBUILD=rpm
test -x /usr/bin/rpmbuild && RPMBUILD=rpmbuild
#
# cleanup_and_exit
#
cleanup_and_exit () {
if [ -n "$TMPDIR" ];then
rm -rf $TMPDIR
fi
exit $1
}
#
# display a warning if the file is not in the spec file sources
#
warn_on_unmentioned_files () {
grep -a -x $1 $TMPDIR/sources > /dev/null || echo "(W) Attention, $1 is not mentioned in spec files as source or patch."
}
test "$VERBOSE" = true && echo -n "- checking if needed files are present and none stale "
#
# first make my TMPDIR
#
export TMPDIR=`mktemp -d -t check_if_valid_source_dir-XXXXXX 2>/dev/null || mktemp -d /var/tmp/check_if_valid_source_dir-XXXXXX` || cleanup_and_exit 1
#
# now create list of Sources.
#
MY_ARCH=`uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/`
case $MY_ARCH in
i386)
MY_ARCH="%ix86"
;;
arm)
MY_ARCH="%arm"
;;
esac
for i in $DIR_TO_CHECK/*.spec ; do
test -f "$i" || continue
sed '/^#%([^)]*$/,/^[^(]*)/d
/^#[^%]/d
/^#%(.*)/d
/^%.*%(echo.*)/{;p;d;}
/^%.*%([^)]*)/{
s@%([^)]*)@1@
}
/^%define/{
s@%(rpm -q.*)@1@
}
/^%define/{;p;d;}
/^%undefine/{;p;d;}
/^%nil/{;p;d;}
/^%{nil}/{;p;d;}
/^%global.*%(.*)/d
/^%global/{;p;d;}
/^%include/d
/^%[a-z]*_requires/d
/^%{[a-z]*_requires}/d
/^%{[a-z]*_preserve_bytecode}/d
/^%gconf_schemas_prereq/d
/^%requires_eq/{;p;d;}
/^%requires_ge/{;p;d;}
/^%ifarch/{
s@.*@%ifarch '$MY_ARCH'@
}
/^ExcludeArch:/d
/^%error/d
/^ExclusiveArch:/{
s@.*@ExclusiveArch: '$MY_ARCH'@
}
/^BuildArch.*:/{
s@.*@BuildArch: '$MY_ARCH'@
}
/^%if.*%{name}/{;p;d;}
/^%if[^a]/{
s@.*@%if 1@
}
/^%if/{;p;d;}
/^%{\!/{;p;d;}
/^%{?/{;p;d;}
/^%{expand/d
/^%error/{;p;d;}
/^%else/{
s@.*@%endif\n%if 1@
}
/^%(.*)/{;d;}
/^%end/{;p;d;}
/^%bcond/{;p;d;}
/^%{py/{;p;d;}
/^%py_r/{;p;d;}
/^%/{;s/.*//;q;}
/^Requires:/d
/^Requires(.*):/d
/^No[Ss]ource/d
/^NoPatch/d
/^BuildPrereq/d
/^Build[Rr]equires/d
/^Pre[Rr]eq/d
/^Icon/d
/^Recommends/d
/^Supplements/d
/^Suggests/d
/^Enhances/d
/^\([Ss]ource\|[Pp]atch\)[0-9]*:[ ]*/{
s/^\(\([Ss]ource\|[Pp]atch\)[0-9]*:[ ]*\)\(.*\)/##seen \1\3\n%{echo:\3 }/
}
s/^Release:.*<RELEASE.*>/Release: 0/
s/^\(Release:.*\)<CI_CNT>\(.*\)/\1_\2/
s/^\(Release:.*\)<B_CNT>\(.*\)/\1_\2/' $i >$TMPDIR/tmp.spec
grep -a ^Icon: "$i"|sed -n 's/^Icon:[ ]*/%{echo:/
/^%{echo:/s/$/ }/p' >>$TMPDIR/tmp.spec
grep -a -q ^Release "$i" || {
sed -e "/^Version/{;p;s@\(.*\)@Release: 0\
@;}" $TMPDIR/tmp.spec > $TMPDIR/tmp.spec.new
mv $TMPDIR/tmp.spec.new $TMPDIR/tmp.spec
}
while test `grep -a "^%if" $TMPDIR/tmp.spec | wc -l` \
-gt `grep -a "^%endif" $TMPDIR/tmp.spec | wc -l` ; do
echo "%endif" >> $TMPDIR/tmp.spec
done
while read line ; do
grep -qx "##seen $line" $TMPDIR/tmp.spec || echo "$line" | sed -e "s/^\(\([Ss]ource\|[Pp]atch\)[0-9]*:[ ]*\)\(.*\)/##seen \1\3\n%{echo:\3 }/" >> $TMPDIR/tmp.spec
done < <(grep -E "^Source:|^Source[0-9]*:|^Patch:|^Patch[0-9]*:" "$i")
echo "%description" >> $TMPDIR/tmp.spec
# hack for really strange specfiles with more than one Name:/Release:/Version: line
for nodup in Name Version Release Summary Group License ; do
sed -e "s@^$nodup:@X$nodup:@" -e "0,/^X$nodup:/{s@^X$nodup:@$nodup:@}" -e "s@^X$nodup:.*@@" $TMPDIR/tmp.spec > $TMPDIR/tmp.spec.2 && mv $TMPDIR/tmp.spec.2 $TMPDIR/tmp.spec
grep -q "^$nodup:" $TMPDIR/tmp.spec || {
echo "$nodup: any" > $TMPDIR/tmp.spec.2
cat $TMPDIR/tmp.spec >> $TMPDIR/tmp.spec.2
mv $TMPDIR/tmp.spec.2 $TMPDIR/tmp.spec
}
done
$RPMBUILD --nodeps -bp $TMPDIR/tmp.spec >> $TMPDIR/sources 2>&1 || {
$RPMBUILD --nodeps -bp $TMPDIR/tmp.spec
cleanup_and_exit 1
}
egrep -v '^warning' $TMPDIR/sources > $TMPDIR/sources.t && mv $TMPDIR/sources.t $TMPDIR/sources
done
for i in $DIR_TO_CHECK/*.dsc ; do
test -f "$i" || continue
( sed -ne '/^Files:/,$p' < "$i" | sed -e 1d | sed -e '/^[^ ]/,$d' | while read debchk debsize debfile ; do echo "$debfile" ; done ) >> $TMPDIR/sources
done
# Add debian only patches to the allowed sources list.
# but strip tailing -p1 arguments
test -f $DIR_TO_CHECK/debian.series && \
sed -e '/^$/d' -e '/^#/d' -e 's,[ \t]*-p[0123456789]*$,,' \
$DIR_TO_CHECK/debian.series >> $TMPDIR/sources
test -f $TMPDIR/sources || cleanup_and_exit
#
# check if all Sources, patches and the icon are present
#
touch $TMPDIR/sources.t
grep -aq "command not found" $TMPDIR/sources && {
echo "$0 seems to have problems evaluating macros in specfile."
COMD=`grep -a "command not found" $TMPDIR/sources | head -n 1 | sed -e "s@.*: \([^:]*\): command not found@\1@"`
echo "command \"$COMD\" is not available used in the following defines:"
grep -a "%define.*$COMD" $DIR_TO_CHECK/*.spec
cleanup_and_exit 1
}
for i in `cat $TMPDIR/sources` ; do
echo "${i##*/}" >> $TMPDIR/sources.t
done
mv $TMPDIR/sources.t $TMPDIR/sources
# XML validate files starting with _..
if [ -x $(type -p xmllint) ]; then
for i in $DIR_TO_CHECK/_service; do
test -f $i || continue
BASE=${i##*/}
xmllint --format $i >/dev/null || {
echo "(E) $(basename $i) is not valid XML"
RETURN=2
continue
}
# Check if _service is sane
if [ "$BASE" = "_service" ]; then
xmllint --format $i > $TMPDIR/_service
if egrep -q "service .*mode=." $TMPDIR/_service \
&& ! egrep -q "service .*mode=.(disabled|localrun)" \
$TMPDIR/_service; then
echo "(W) openSUSE: projects only allow 'disabled or 'localrun' services."
fi
fi
done
fi
check_tracked()
{
local file=${1##*/}
if ! test -f "$DIR_TO_CHECK/$file"; then
echo "(E) $file mentioned in spec file does not exist."
return 1
fi
if test "$OSC_MODE" = "true" ; then
if test -f "$DESTINATIONDIR/$file"; then
return 0
fi
if grep -qsFx "$file" "$DESTINATIONDIR/_to_be_added"; then
return 0
fi
echo "(E) $file mentioned in spec file is not tracked."
return 1
fi
}
if ! test -f "$DIR_TO_CHECK/_service"; then
for HASTOBETHER in `cat $TMPDIR/sources` ; do
check_tracked "$HASTOBETHER" || RETURN=2
done
fi
#
# Verify GPG keys
#
if [ -f $DIR_TO_CHECK/*.keyring 2>/dev/null ]; then
gpg -q --no-default-keyring --keyring $TMPDIR/.checkifvalidsourcedir-gpg-keyring --import $DIR_TO_CHECK/*.keyring
for i in $DIR_TO_CHECK/*.sig $DIR_TO_CHECK/*.sign $DIR_TO_CHECK/*.asc; do
if [ -f "$i" ]; then
validatefn=${i%.asc}
validatefn=${validatefn%.sig}
validatefn=${validatefn%.sign}
if [ -f "$validatefn" ]; then
gpg -q --no-default-keyring --keyring $TMPDIR/.checkifvalidsourcedir-gpg-keyring --verify "$i" || {
echo "(E) signature $i does not validate"
RETURN=2
}
else
if [ -f "$validatefn.gz" ]; then
TMPFILE=`mktemp`
zcat "$validatefn.gz" > $TMPFILE
gpg -q --no-default-keyring --keyring $TMPDIR/.checkifvalidsourcedir-gpg-keyring --verify "$i" "$TMPFILE" || {
echo "(E) signature $i does not validate"
RETURN=2
}
rm $TMPFILE
fi
if [ -f "$validatefn.bz2" ]; then
TMPFILE=`mktemp`
bzcat "$validatefn.bz2" > $TMPFILE
gpg -q --no-default-keyring --keyring $TMPDIR/.checkifvalidsourcedir-gpg-keyring --verify "$i" "$TMPFILE" || {
echo "(E) signature $i does not validate"
RETURN=2
}
rm $TMPFILE
fi
if [ -f "$validatefn.xz" ]; then
TMPFILE=`mktemp`
xzcat "$validatefn.xz" > $TMPFILE
gpg -q --no-default-keyring --keyring $TMPDIR/.checkifvalidsourcedir-gpg-keyring --verify "$i" "$TMPFILE" || {
echo "(E) signature $i does not validate"
RETURN=2
}
rm $TMPFILE
fi
fi
fi
done
rm $TMPDIR/.checkifvalidsourcedir-gpg-keyring
fi
#
# now check if everything is marked in spec files.
#
for i in $DIR_TO_CHECK/* $DIR_TO_CHECK/.* ; do
BASE=${i##*/}
case $BASE in
\.|\.\.) continue ;;
esac
# files to display first
case $BASE in
config-dist.sh | \
get_version_number.sh | \
get_release_number.sh | \
check-build.sh | \
baselibs.conf )
if test -n "$DESTINATIONDIR" -a -f "$DESTINATIONDIR/$BASE" && cmp -s "$DIR_TO_CHECK/$BASE" "$DESTINATIONDIR/$BASE" ; then
echo "- package has $BASE: (unchanged)"
else
echo "- package has $BASE: (new or modified)"
echo "--------------------------------------------------------------"
cat $DIR_TO_CHECK/$BASE
echo "--------------------------------------------------------------"
if test "$BATCHMODE" != true ; then
echo -n "Is this correct? [N/y/d] (y to ignore) "
read ANSWER
test "$ANSWER" = y -o "$ANSWER" = Y || {
if test "$ANSWER" = d -o "$ANSWER" = D ; then
rm -v -- "$DIR_TO_CHECK/$BASE"
else
echo ok, please fix it...
test "$RETURN" != "2" && RETURN=1
fi
}
else
echo "###ASK $DIR_TO_CHECK/$BASE"
fi
fi
# we want baselibs.conf in the src.rpm
if test "$BASE" = baselibs.conf; then
warn_on_unmentioned_files $BASE
fi
;;
*rpmlintrc)
if test -n "$DESTINATIONDIR" -a -f "$DESTINATIONDIR/$BASE" && cmp -s "$DIR_TO_CHECK/$BASE" "$DESTINATIONDIR/$BASE" ; then
echo "- package has $BASE: (unchanged)"
else
echo "- package has $BASE: (new or modified)"
echo "--------------------------------------------------------------"
cat $DIR_TO_CHECK/$BASE
echo "--------------------------------------------------------------"
if test "$BATCHMODE" != true ; then
echo -n "Is this correct? [N/y/d] (y to ignore) "
read ANSWER
test "$ANSWER" = y -o "$ANSWER" = Y || {
if test "$ANSWER" = d -o "$ANSWER" = D ; then
rm -v -- "$DIR_TO_CHECK/$BASE"
else
echo ok, please fix it...
test "$RETURN" != "2" && RETURN=1
fi
}
else
echo "###ASK $DIR_TO_CHECK/$BASE"
fi
fi
warn_on_unmentioned_files $BASE
LINE=$(egrep "^[^#]*setBadness" "$DIR_TO_CHECK/$BASE")
if [ "$LINE" != "" ]; then
if test "$BATCHMODE" != true ; then
echo "ERROR: Found possibly illegal rpmlintrc line:"
echo " $LINE"
echo -n "Is this correct? [N/y] (y to ignore) "
read ANSWER
test "$ANSWER" = y -o "$ANSWER" = Y || {
echo ok, please fix it...
test "$RETURN" != "2" && RETURN=1
}
else
echo "###ASK $DIR_TO_CHECK/$BASE"
fi
fi
;;
.*.spec)
rm -v -- "$DIR_TO_CHECK/$BASE"
;;
*.changes | \
*.lsm | \
*.spec | \
*.spec.in | \
*.changes.in | \
*.test | \
MD5SUMS | \
MD5SUMS.meta | \
Makefile | \
README.autobuild | \
bigpack | \
prepare-build.sh | \
minmem | \
needed_space_in_mb | \
pre_checkin.sh | \
newestfile | \
.osc | \
.bsinfo | \
.bsnote | \
.check_if_valid_source_dir | \
.setup | \
*.dsc | \
ready | \
_* | \
*.orig | \
*~ | \
.git | \
.gitignore | \
.emacs.backup | \
PKGBUILD | \
debian.changelog | \
debian.compat | \
debian.control | \
debian.copyright | \
debian.postinst | \
debian.postrm | \
debian.preinst | \
debian.prerm | \
debian.rules | \
debian.series | \
debian.tar.gz | \
debian.triggers | \
debian.format | \
debian.*.default | \
debian.*.dirs | \
debian.*.files | \
debian.*.init | \
debian.*.install | \
debian.*.logrotate | \
debian.*.postinst | \
debian.*.postrm | \
debian.*.preinst | \
debian.*.prerm | \
debian.*.lintian-overrides )
;;
*)
grep -a -x "$BASE" $TMPDIR/sources > /dev/null && continue
test -f $DIR_TO_CHECK/_service && egrep -q 'mode=.remoterun' $DIR_TO_CHECK/_service && continue
# be a bit more relaxed for osc, it won't upload directories anyway
[ -d "$DIR_TO_CHECK/$BASE" ] && [ -d $DIR_TO_CHECK/.osc ] && continue
# and source services on server side
[ -d "$DIR_TO_CHECK/$BASE" ] && [ -d $DIR_TO_CHECK/.old ] && continue
warn_on_unmentioned_files $BASE
if test "$RETURN" != "2" ; then
if [ -d "$DIR_TO_CHECK/$BASE" ] ; then
# be a bit more relaxed for osc, it won't upload directories anyway
if [ ! -d $DIR_TO_CHECK/.osc ] ; then
echo "!! $BASE is a directory !!"
if test "$BATCHMODE" != true ; then
echo " remove subtree with 'r'"
echo "ignore and continue with 'y'"
echo -n "Is this correct? [N/y/r] "
read ANSWER
test "$ANSWER" = y -o "$ANSWER" = Y || {
# r for remove is also accepted, to make it compatible with osc itself
if test "$ANSWER" = d -o "$ANSWER" = D -o "$ANSWER" = r -o "$ANSWER" = R; then
rm -Rfv -- "$DIR_TO_CHECK/$BASE"
else
echo ok, please fix it...
test "$RETURN" != "2" && RETURN=1
fi
}
else
echo "###ASK -r $DIR_TO_CHECK/$BASE"
fi
fi
else
if test "$BATCHMODE" != true ; then
echo -n "Is this correct? [N/y/d] (y to ignore) "
read ANSWER
test "$ANSWER" = y -o "$ANSWER" = Y || {
if test "$ANSWER" = d -o "$ANSWER" = D ; then
rm -v "$DIR_TO_CHECK/$BASE"
else
echo ok, please fix it...
test "$RETURN" != "2" && RETURN=1
fi
}
else
echo "###ASK $DIR_TO_CHECK/$BASE"
fi
fi
fi
;;
esac
done
test "$VERBOSE" = true && echo done
cleanup_and_exit $RETURN