obs-build-20180831/ 0000755 0001750 0001750 00000000000 13350372745 012251 5 ustar alee alee obs-build-20180831/build-recipe-spec 0000644 0001750 0001750 00000022570 13350372713 015471 0 ustar alee alee #
# spec specific functions.
#
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
recipe_setup_spec() {
TOPDIR=`chroot $BUILD_ROOT su -c "rpm --eval '%_topdir'" - $BUILD_USER`
if test -z "$TOPDIR"; then
cleanup_and_exit 1 "Error: TOPDIR empty"
fi
test "$DO_INIT_TOPDIR" = false || rm -rf "$BUILD_ROOT$TOPDIR"
for i in BUILD RPMS/`uname -m` RPMS/i386 RPMS/noarch SOURCES SPECS SRPMS BUILDROOT OTHER ; do
mkdir -p $BUILD_ROOT$TOPDIR/$i
done
chown -R "$ABUILD_UID:$ABUILD_GID" "$BUILD_ROOT$TOPDIR"
mkdir -p $BUILD_ROOT$TOPDIR/SOURCES
cp -p "$MYSRCDIR"/* $BUILD_ROOT$TOPDIR/SOURCES/
}
recipe_prepare_spec() {
# fixup specfile
args=()
if test -n "$RELEASE" ; then
args[${#args[@]}]="--release"
args[${#args[@]}]="$RELEASE"
fi
if test -n "$BUILD_FLAVOR" ; then
args[${#args[@]}]="--buildflavor"
args[${#args[@]}]="$BUILD_FLAVOR"
fi
if test -n "$OBS_PACKAGE" ; then
args[${#args[@]}]="--obspackage"
args[${#args[@]}]="$OBS_PACKAGE"
fi
if test -n "$CHANGELOG" -a -f "$BUILD_ROOT/.build-changelog" ; then
args[${#args[@]}]="--changelog"
args[${#args[@]}]="$BUILD_ROOT/.build-changelog"
fi
substitutedeps "${args[@]}" --root "$BUILD_ROOT" --dist "$BUILD_DIST" --archpath "$BUILD_ARCH" --configdir "$CONFIG_DIR" "$BUILD_ROOT$TOPDIR/SOURCES/$RECIPEFILE" "$BUILD_ROOT/.spec.new" || cleanup_and_exit 1
# fix rpmrc if we are compiling for i686
test -f $BUILD_ROOT/usr/lib/rpm/rpmrc_i586 && mv $BUILD_ROOT/usr/lib/rpm/rpmrc_i586 $BUILD_ROOT/usr/lib/rpm/rpmrc
if test -e $BUILD_ROOT/usr/lib/rpm/rpmrc -a "$BUILD_ARCH" != "${BUILD_ARCH#i686}" ; then
mv $BUILD_ROOT/usr/lib/rpm/rpmrc $BUILD_ROOT/usr/lib/rpm/rpmrc_i586
sed -e 's/^buildarchtranslate: athlon.*/buildarchtranslate: athlon: i686/' -e 's/^buildarchtranslate: i686.*/buildarchtranslate: i686: i686/' < $BUILD_ROOT/usr/lib/rpm/rpmrc_i586 > $BUILD_ROOT/usr/lib/rpm/rpmrc
fi
# extract macros from configuration
rawcfgmacros=.rpmmacros
test "$BUILDTYPE" = debbuild && rawcfgmacros=.debmacros
queryconfig rawmacros --dist "$BUILD_DIST" --archpath "$BUILD_ARCH" --configdir "$CONFIG_DIR" > $BUILD_ROOT/root/$rawcfgmacros
if test -n "$BUILD_DEBUG" && test "$BUILDTYPE" != debbuild ; then
echo '
%prep %{?!__debug_package:%{?_build_create_debug:%?_build_insert_debug_package}}%%prep
%package %{?!__debug_package:%{?_build_create_debug:%?_build_insert_debug_package}}%%package
%_build_insert_debug_package \
%global __debug_package 1 \
%undefine _enable_debug_packages \
%debug_package
' >> $BUILD_ROOT/root/$rawcfgmacros
fi
if test -n "$BUILD_JOBS" ; then
cat >> $BUILD_ROOT/root/$rawcfgmacros <<-EOF
%jobs $BUILD_JOBS
%_smp_mflags -j$BUILD_JOBS
EOF
fi
test $BUILD_USER = abuild && cp -p $BUILD_ROOT/root/$rawcfgmacros $BUILD_ROOT/home/abuild/$rawcfgmacros
# extract optflags from configuration
queryconfig --dist "$BUILD_DIST" --configdir "$CONFIG_DIR" --archpath "$BUILD_ARCH" optflags ${BUILD_DEBUG:+debug} > $BUILD_ROOT/root/.rpmrc
test $BUILD_USER = abuild && cp -p $BUILD_ROOT/root/.rpmrc $BUILD_ROOT/home/abuild/.rpmrc
if test -z "$ABUILD_TARGET"; then
ABUILD_TARGET=$(queryconfig target --dist "$BUILD_DIST" --configdir "$CONFIG_DIR" --archpath "$BUILD_ARCH" )
test -z "$ABUILD_TARGET" || echo "build target is $ABUILD_TARGET"
fi
# report specfile changes
if test -f $BUILD_ROOT/.spec.new ; then
if ! cmp -s $BUILD_ROOT$TOPDIR/SOURCES/$RECIPEFILE $BUILD_ROOT/.spec.new ; then
echo -----------------------------------------------------------------
echo "I have the following modifications for $RECIPEFILE:"
sed -e "/^%changelog/q" $BUILD_ROOT$TOPDIR/SOURCES/$RECIPEFILE > $BUILD_ROOT/.spec.t1
sed -e "/^%changelog/q" $BUILD_ROOT/.spec.new > $BUILD_ROOT/.spec.t2
diff $BUILD_ROOT/.spec.t1 $BUILD_ROOT/.spec.t2
rm -f $BUILD_ROOT/.spec.t1 $BUILD_ROOT/.spec.t2
mv $BUILD_ROOT/.spec.new $BUILD_ROOT$TOPDIR/SOURCES/$RECIPEFILE
else
rm -f $BUILD_ROOT/.spec.new
fi
fi
}
recipe_build_spec() {
test -z "$BUILD_RPM_BUILD_STAGE" && BUILD_RPM_BUILD_STAGE=-ba
rpmbuild=rpmbuild
test -x $BUILD_ROOT/usr/bin/rpmbuild || rpmbuild=rpm
test "$BUILDTYPE" = debbuild && rpmbuild=debbuild
# XXX: move _srcdefattr to macro file?
rpmbopts=("$BUILD_RPM_BUILD_STAGE" "--define" "_srcdefattr (-,root,root)")
if test "$DO_CHECKS" != true ; then
if chroot "$BUILD_ROOT" "$rpmbuild" --nocheck --help >/dev/null 2>&1; then
rpmbopts[${#rpmbopts[@]}]="--nocheck"
else
echo "warning: --nocheck is not supported by this $rpmbuild version"
fi
fi
if test "$rpmbuild" == "rpmbuild" ; then
# use only --nosignature for rpm v4
rpmbopts[${#rpmbopts[@]}]="--nosignature"
fi
if test -n "$ABUILD_TARGET" ; then
rpmbopts[${#rpmbopts[@]}]="--target=$ABUILD_TARGET"
fi
if test -n "$BUILD_DEBUG" ; then
rpmbopts[${#rpmbopts[@]}]='--define'
rpmbopts[${#rpmbopts[@]}]="_build_create_debug 1"
fi
if test -n "$DISTURL" ; then
rpmbopts[${#rpmbopts[@]}]='--define'
rpmbopts[${#rpmbopts[@]}]="disturl $DISTURL"
fi
if test -n "$RSYNCDONE" ; then
rpmbopts[${#rpmbopts[@]}]='--define'
rpmbopts[${#rpmbopts[@]}]="RSYNCDONE 1"
fi
buildrootoverride=$(queryconfig --dist "$BUILD_DIST" --configdir "$CONFIG_DIR" --archpath "$BUILD_ARCH" buildflags rpm-buildroot-override)
if test -n "$buildrootoverride" ; then
rpmbopts[${#rpmbopts[@]}]='--buildroot'
rpmbopts[${#rpmbopts[@]}]="$buildrootoverride"
fi
# su involves a shell which would require even more
# complicated quoting to bypass than this
toshellscript $rpmbuild \
"${definesnstuff[@]}" \
"${rpmbopts[@]}" \
"$TOPDIR/SOURCES/$RECIPEFILE" \
> $BUILD_ROOT/.build.command
chmod 755 $BUILD_ROOT/.build.command
check_exit
if test -n "$RUN_SHELL"; then
chroot $BUILD_ROOT su -
else
chroot $BUILD_ROOT su -c /.build.command - $BUILD_USER < /dev/null && BUILD_SUCCEEDED=true
fi
}
recipe_resultdirs_spec() {
echo RPMS SRPMS
}
recipe_cleanup_spec() {
:
}
recipe_unpack_srcrpm() {
test -n "$LIST_STATE" || echo "processing src rpm $SRCDIR/$RECIPEFILE ..."
MYSRCDIR="$BUILD_ROOT/.build-srcdir"
rm -rf "$MYSRCDIR"
mkdir -p "$MYSRCDIR"
cd $MYSRCDIR || cleanup_and_exit 1
$BUILD_DIR/unrpm -q $SRCDIR/$RECIPEFILE || {
cleanup_and_exit 1 "could not unpack $RECIPEFILE."
}
for RECIPEFILE in *.spec ; do : ; done
}
# post build functions... move somewhere else?
recipe_check_file_owners() {
echo "... checking for files with abuild user/group"
BADFILE=
while read un gn fn ; do
if test "$un" = abuild -o "$gn" = abuild -o "$un" = ${ABUILD_UID} -o "$gn" = ${ABUILD_GID} ; then
echo " $un $gn $fn"
BADFILE=true
fi
done < <(rpm -qp --qf '[%{FILEUSERNAME} %{FILEGROUPNAME} %{FILENAMES}\n]' $RPMS)
if test -n "$BADFILE" ; then
cleanup_and_exit 1 "please fix your filelist (e.g. add defattr)"
fi
}
recipe_run_rpmlint() {
if ! test -x "$BUILD_ROOT/opt/testing/bin/rpmlint" ; then
return
fi
LINT_RPM_FILE_LIST=($(find $BUILD_ROOT/$TOPDIR/RPMS \
\( -name "*-debuginfo-*" -o -name "*-debugsource-*" \
-o -name "*-32bit-*" -o -name "*-64bit-*" \
-o -name "*-x86-*" -o -name "*-ia32-*" \) -prune \
-o -type f -name '*.rpm' -print))
SRPM_FILE_LIST=($(find $BUILD_ROOT/$TOPDIR/SRPMS -type f -name "*.rpm"))
echo
echo "RPMLINT report:"
echo "==============="
rpmlint_logfile=$TOPDIR/OTHER/rpmlint.log
rm -f "$BUILD_ROOT$rpmlint_logfile"
ret=0
chroot $BUILD_ROOT su -s /opt/testing/bin/rpmlint "$BUILD_USER" -- \
--info ${LINT_RPM_FILE_LIST[*]#$BUILD_ROOT} \
${SRPM_FILE_LIST[*]#$BUILD_ROOT} > >(tee "$BUILD_ROOT$rpmlint_logfile") 2>&1 || ret=1
echo
if test "$ret" = 1 ; then
cleanup_and_exit 1
fi
}
recipe_compare_oldpackages() {
if test -x "$BUILD_ROOT/usr/lib/build/same-build-result.sh" ; then
echo "... comparing built packages with the former built"
if chroot $BUILD_ROOT /usr/lib/build/same-build-result.sh /.build.oldpackages "$TOPDIR/RPMS" "$TOPDIR/SRPMS"; then
chroot $BUILD_ROOT touch /.build/.same_result_marker
# XXX: dirty build service hack. fix bs_worker. Search for
# 'same_result_marker' for traces of a first try to get rid of this
if test -n "$REASON" -a -n "$DISTURL" ; then
exitcode=2
fi
fi
fi
}
recipe_create_deltarpms() {
if test -x "$BUILD_ROOT/usr/bin/makedeltarpm" -a -x $BUILD_ROOT/usr/lib/build/mkdrpms ; then
echo "... creating delta rpms"
ds=("$BUILD_ROOT/$TOPDIR"/RPMS/* "$BUILD_ROOT$TOPDIR/SRPMS")
chroot $BUILD_ROOT /usr/lib/build/mkdrpms /.build.oldpackages "${ds[@]#$BUILD_ROOT}"
fi
}
obs-build-20180831/t/ 0000755 0001750 0001750 00000000000 13350372713 012507 5 ustar alee alee obs-build-20180831/t/standard.livebuild 0000644 0001750 0001750 00000074000 13350372713 016211 0 ustar alee alee ./PaxHeaders.10269/auto 0000644 0000000 0000000 00000000132 12222266372 013110 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1404999252.606063979
30 ctime=1404999250.918084803
auto/ 0000755 0001750 0000144 00000000000 12222266372 012701 5 ustar 00jblunck users 0000000 0000000 auto/PaxHeaders.10269/clean 0000644 0000000 0000000 00000000132 12222266372 014035 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1404999250.918084803
30 ctime=1404999250.918084803
auto/clean 0000755 0001750 0000144 00000000240 12222266372 013705 0 ustar 00jblunck users 0000000 0000000 #!/bin/sh
set -e
lb clean noauto "${@}"
rm -f config/binary config/bootstrap config/chroot config/common config/source
rm -f config/control
rm -f build.log
auto/PaxHeaders.10269/config 0000644 0000000 0000000 00000000132 12222266372 014220 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1404999250.918084803
30 ctime=1404999250.918084803
auto/config 0000755 0001750 0000144 00000000626 12222266372 014100 0 ustar 00jblunck users 0000000 0000000 #!/bin/sh
set -e
case "$(dpkg --print-architecture)" in
amd64)
_LINUX_FLAVOURS="amd64"
_SOURCE="false"
;;
i386)
_LINUX_FLAVOURS="486 686-pae"
_SOURCE="true"
;;
esac
lb config noauto \
--clean \
--ignore-system-defaults \
--mode debian \
--debian-installer live \
--linux-flavours "${_LINUX_FLAVOURS}" \
--linux-packages "linux-image linux-headers" \
--source "${_SOURCE}" \
"${@}"
auto/PaxHeaders.10269/build 0000644 0000000 0000000 00000000132 12222266372 014052 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1404999250.918084803
30 ctime=1404999250.918084803
auto/build 0000755 0001750 0000144 00000000112 12222266372 013720 0 ustar 00jblunck users 0000000 0000000 #!/bin/sh
set -e
lb build noauto "${@}" && echo $? 2>&1 | tee build.log
./PaxHeaders.10269/config 0000644 0000000 0000000 00000000132 12222300375 013375 x ustar 00 0000000 0000000 30 mtime=1380548861.684530853
30 atime=1404999252.606063979
30 ctime=1404999250.918084803
config/ 0000755 0001750 0000144 00000000000 12222300375 013166 5 ustar 00jblunck users 0000000 0000000 config/PaxHeaders.10269/bootloaders 0000644 0000000 0000000 00000000132 12222304630 015553 x ustar 00 0000000 0000000 30 mtime=1380551064.696527946
30 atime=1404999252.606063979
30 ctime=1404999250.918084803
config/bootloaders/ 0000755 0001750 0000144 00000000000 12222304630 015501 5 ustar 00jblunck users 0000000 0000000 config/PaxHeaders.10269/package-lists 0000644 0000000 0000000 00000000132 12357312571 016001 x ustar 00 0000000 0000000 30 mtime=1404933497.776159592
30 atime=1404999252.606063979
30 ctime=1404999250.918084803
config/package-lists/ 0000755 0001750 0000144 00000000000 12357312571 015727 5 ustar 00jblunck users 0000000 0000000 config/package-lists/PaxHeaders.10269/installer.list.chroot 0000644 0000000 0000000 00000000132 12222266372 022243 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404999250.918084803
30 ctime=1404999250.918084803
config/package-lists/installer.list.chroot 0000644 0001750 0000144 00000000037 12222266372 022114 0 ustar 00jblunck users 0000000 0000000 debian-installer-launcher
sudo
config/package-lists/PaxHeaders.10269/live.list.chroot 0000644 0000000 0000000 00000000132 12222266372 021205 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404999250.918084803
30 ctime=1404999250.918084803
config/package-lists/live.list.chroot 0000644 0001750 0000144 00000000027 12222266372 021055 0 ustar 00jblunck users 0000000 0000000 live-manual
live-tools
config/package-lists/PaxHeaders.10269/localization.list.chroot 0000644 0000000 0000000 00000000132 12222266372 022736 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404999250.918084803
30 ctime=1404999250.918084803
config/package-lists/localization.list.chroot 0000644 0001750 0000144 00000000034 12222266372 022604 0 ustar 00jblunck users 0000000 0000000 task-english
console-tools
config/package-lists/PaxHeaders.10269/standard.list.chroot 0000644 0000000 0000000 00000000132 12222266372 022046 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404999250.918084803
30 ctime=1404999250.918084803
config/package-lists/standard.list.chroot 0000644 0001750 0000144 00000000072 12222266372 021716 0 ustar 00jblunck users 0000000 0000000 ! Packages Priority standard
task-laptop
task-ssh-server
config/package-lists/PaxHeaders.10269/memtest 0000644 0000000 0000000 00000000132 12222266372 017455 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404999250.918084803
30 ctime=1404999250.918084803
config/package-lists/memtest 0000644 0001750 0000144 00000000013 12222266372 017320 0 ustar 00jblunck users 0000000 0000000 memtest86+
config/PaxHeaders.10269/archives 0000644 0000000 0000000 00000000132 12357513140 015051 x ustar 00 0000000 0000000 30 mtime=1404999264.309919538
30 atime=1404999252.606063979
30 ctime=1404999264.309919538
config/archives/ 0000755 0001750 0000144 00000000000 12357513140 014777 5 ustar 00jblunck users 0000000 0000000 config/archives/PaxHeaders.10269/debian.key.chroot 0000644 0000000 0000000 00000000132 12222300432 020344 x ustar 00 0000000 0000000 30 mtime=1380548890.449530815
30 atime=1404999250.918084803
30 ctime=1404999250.918084803
config/archives/debian.key.chroot 0000644 0001750 0000144 00000000045 12222300432 020214 0 ustar 00jblunck users 0000000 0000000 a73043cf-7b16-42dc-b0d9-3031ed4370be
./PaxHeaders.10269/README 0000644 0000000 0000000 00000000132 12222266372 013075 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404999250.918084803
30 ctime=1404999250.918084803
README 0000644 0001750 0000144 00000000771 12222266372 012616 0 ustar 00jblunck users 0000000 0000000 This is the configuration tree for:
Debian Standard
A software called live-build can be used to automatically build images from
this configuration tree.
live-build can be obtained from .
On Debian based systems, live-build can be installed with:
# apt-get install live-build
More information about live-build and the Live Systems project can be found on
its homepage at and in the manual at
.
obs-build-20180831/t/directory.livebuild 0000644 0001750 0001750 00000074000 13350372713 016415 0 ustar alee alee ./PaxHeaders.21794/directory 0000644 0000000 0000000 00000000132 12361532117 014146 x ustar 00 0000000 0000000 30 mtime=1405531215.102319719
30 atime=1405531213.970331813
30 ctime=1405531215.102319719
directory/ 0000755 0001750 0000144 00000000000 12361532117 013732 5 ustar 00jblunck users 0000000 0000000 directory/PaxHeaders.21794/README 0000644 0000000 0000000 00000000132 12222266372 014751 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/README 0000644 0001750 0000144 00000000771 12222266372 014622 0 ustar 00jblunck users 0000000 0000000 This is the configuration tree for:
Debian Standard
A software called live-build can be used to automatically build images from
this configuration tree.
live-build can be obtained from .
On Debian based systems, live-build can be installed with:
# apt-get install live-build
More information about live-build and the Live Systems project can be found on
its homepage at and in the manual at
.
directory/PaxHeaders.21794/auto 0000644 0000000 0000000 00000000132 12222266372 014764 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/auto/ 0000755 0001750 0000144 00000000000 12222266372 014705 5 ustar 00jblunck users 0000000 0000000 directory/auto/PaxHeaders.21794/clean 0000644 0000000 0000000 00000000132 12222266372 016046 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/auto/clean 0000755 0001750 0000144 00000000240 12222266372 015711 0 ustar 00jblunck users 0000000 0000000 #!/bin/sh
set -e
lb clean noauto "${@}"
rm -f config/binary config/bootstrap config/chroot config/common config/source
rm -f config/control
rm -f build.log
directory/auto/PaxHeaders.21794/config 0000644 0000000 0000000 00000000132 12222266372 016231 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/auto/config 0000755 0001750 0000144 00000000626 12222266372 016104 0 ustar 00jblunck users 0000000 0000000 #!/bin/sh
set -e
case "$(dpkg --print-architecture)" in
amd64)
_LINUX_FLAVOURS="amd64"
_SOURCE="false"
;;
i386)
_LINUX_FLAVOURS="486 686-pae"
_SOURCE="true"
;;
esac
lb config noauto \
--clean \
--ignore-system-defaults \
--mode debian \
--debian-installer live \
--linux-flavours "${_LINUX_FLAVOURS}" \
--linux-packages "linux-image linux-headers" \
--source "${_SOURCE}" \
"${@}"
directory/auto/PaxHeaders.21794/build 0000644 0000000 0000000 00000000132 12222266372 016063 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/auto/build 0000755 0001750 0000144 00000000112 12222266372 015724 0 ustar 00jblunck users 0000000 0000000 #!/bin/sh
set -e
lb build noauto "${@}" && echo $? 2>&1 | tee build.log
directory/PaxHeaders.21794/config 0000644 0000000 0000000 00000000132 12222300375 015251 x ustar 00 0000000 0000000 30 mtime=1380548861.684530853
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/config/ 0000755 0001750 0000144 00000000000 12222300375 015172 5 ustar 00jblunck users 0000000 0000000 directory/config/PaxHeaders.21794/bootloaders 0000644 0000000 0000000 00000000132 12222304630 017564 x ustar 00 0000000 0000000 30 mtime=1380551064.696527946
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/config/bootloaders/ 0000755 0001750 0000144 00000000000 12222304630 017505 5 ustar 00jblunck users 0000000 0000000 directory/config/PaxHeaders.21794/package-lists 0000644 0000000 0000000 00000000132 12357312571 020012 x ustar 00 0000000 0000000 30 mtime=1404933497.776159592
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/config/package-lists/ 0000755 0001750 0000144 00000000000 12357312571 017733 5 ustar 00jblunck users 0000000 0000000 directory/config/package-lists/PaxHeaders.21794/installer.list.chroot 0000644 0000000 0000000 00000000132 12222266372 024254 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/config/package-lists/installer.list.chroot 0000644 0001750 0000144 00000000037 12222266372 024120 0 ustar 00jblunck users 0000000 0000000 debian-installer-launcher
sudo
directory/config/package-lists/PaxHeaders.21794/live.list.chroot 0000644 0000000 0000000 00000000132 12222266372 023216 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/config/package-lists/live.list.chroot 0000644 0001750 0000144 00000000027 12222266372 023061 0 ustar 00jblunck users 0000000 0000000 live-manual
live-tools
directory/config/package-lists/PaxHeaders.21794/localization.list.chroot 0000644 0000000 0000000 00000000132 12222266372 024747 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/config/package-lists/localization.list.chroot 0000644 0001750 0000144 00000000034 12222266372 024610 0 ustar 00jblunck users 0000000 0000000 task-english
console-tools
directory/config/package-lists/PaxHeaders.21794/standard.list.chroot 0000644 0000000 0000000 00000000132 12222266372 024057 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/config/package-lists/standard.list.chroot 0000644 0001750 0000144 00000000072 12222266372 023722 0 ustar 00jblunck users 0000000 0000000 ! Packages Priority standard
task-laptop
task-ssh-server
directory/config/package-lists/PaxHeaders.21794/memtest 0000644 0000000 0000000 00000000132 12222266372 021466 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/config/package-lists/memtest 0000644 0001750 0000144 00000000013 12222266372 021324 0 ustar 00jblunck users 0000000 0000000 memtest86+
directory/config/PaxHeaders.21794/archives 0000644 0000000 0000000 00000000132 12357513140 017062 x ustar 00 0000000 0000000 30 mtime=1404999264.309919538
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/config/archives/ 0000755 0001750 0000144 00000000000 12357513140 017003 5 ustar 00jblunck users 0000000 0000000 directory/config/archives/PaxHeaders.21794/debian.key.chroot 0000644 0000000 0000000 00000000132 12222300432 022355 x ustar 00 0000000 0000000 30 mtime=1380548890.449530815
30 atime=1405531215.102319719
30 ctime=1405531215.102319719
directory/config/archives/debian.key.chroot 0000644 0001750 0000144 00000000045 12222300432 022220 0 ustar 00jblunck users 0000000 0000000 a73043cf-7b16-42dc-b0d9-3031ed4370be
obs-build-20180831/t/requires.t 0000644 0001750 0001750 00000004302 13350372713 014532 0 ustar alee alee #!/usr/bin/perl -w
use strict;
use Test::More tests => 20;
require 't/testlib.pm';
my $repo = <<'EOR';
P: a = 1-1
R: b
P: b = 1-1
P: c = 1-1
R: p
P: d = 1-1 p
P: e = 1-1 p
P: f = 1-1
R: n
P: ign2 = 1-1
R: ign1
P: ign3 = 1-1
R: ign4
P: ign5 = 1-1 ign4
P: ign6 = 1-1
R: ign7
P: ign8 = 1-1
R: ign7
P: g = 1-1 h
P: h = 1-1
EOR
my $config = setuptest($repo, 'Ignore: ign1 ign5 ign6:ign7');
my $config2 = setuptest($repo, 'Prefer: d');
my $config3 = setuptest($repo, 'Prefer: -d');
my @r;
@r = expand($config);
is_deeply(\@r, [1], 'install nothing');
@r = expand($config, 'n');
is_deeply(\@r, [undef, 'nothing provides n'], 'install n');
@r = expand($config, 'f');
is_deeply(\@r, [undef, 'nothing provides n needed by f'], 'install f');
@r = expand($config, "a");
is_deeply(\@r, [1, 'a', 'b'], 'install a');
@r = expand($config, "c");
is_deeply(\@r, [undef, 'have choice for p needed by c: d e'], 'install c');
@r = expand($config2, "c");
is_deeply(\@r, [1, 'c', 'd'], 'install c with prefer');
@r = expand($config3, "c");
is_deeply(\@r, [1, 'c', 'e'], 'install c with neg prefer');
@r = expand($config, "ign1");
is_deeply(\@r, [undef, 'nothing provides ign1'], 'install ign1');
@r = expand($config, "ign2");
is_deeply(\@r, [1, 'ign2'], 'install ign2');
@r = expand($config, "ign3");
is_deeply(\@r, [1, 'ign3'], 'install ign3');
@r = expand($config, "ign6");
is_deeply(\@r, [1, 'ign6'], 'install ign6');
@r = expand($config, "ign8");
is_deeply(\@r, [undef, 'nothing provides ign7 needed by ign8'], 'install ign8');
@r = expand($config, "ign2", "-ign2");
is_deeply(\@r, [1, 'ign2'], 'install ign2 -ign2');
@r = expand($config, "ign8", "-ign7");
is_deeply(\@r, [1, 'ign8'], 'install ign8 -ign7');
@r = expand($config2, "ign5", "-ign5");
is_deeply(\@r, [1, 'ign5'], 'install ign5 -ign5');
@r = expand($config2, "ign4", "-ign5");
is_deeply(\@r, [1, 'ign5'], 'install ign4 -ign5');
@r = expand($config, "ign5");
is_deeply(\@r, [1, 'ign5'], 'install ign5');
@r = expand($config, "ign4");
is_deeply(\@r, [1, 'ign5'], 'install ign4');
@r = expand($config, "h");
is_deeply(\@r, [1, 'h'], 'install h');
@r = expand($config, "--directdepsend--", "h");
is_deeply(\@r, [undef, 'have choice for h: g h'], 'install --directdepsend-- h');
obs-build-20180831/t/determinism.t 0000644 0001750 0001750 00000000517 13350372713 015217 0 ustar alee alee #!/usr/bin/perl -w
use strict;
use Test::More tests => 1;
require 't/testlib.pm';
my $repo = <<'EOR';
P: a = 1-1
R: b c
P: b1 = 1-1 b
C: c1
P: b2 = 1-1 b
P: c1 = 1-1 c
P: c2 = 1-1 c
EOR
my $config = setuptest($repo, 'Prefer: b1 c1');
my @r;
@r = expand($config, 'a');
is_deeply(\@r, [undef, 'b1 conflicts with c1'], 'install a');
obs-build-20180831/t/ordep.t 0000644 0001750 0001750 00000001151 13350372713 014003 0 ustar alee alee #!/usr/bin/perl -w
use strict;
use Test::More tests => 4;
require 't/testlib.pm';
my $repo = <<'EOR';
P: a = 1-1
R: x | y
P: b = 1-1
R: d | e
P: c = 1-1
R: d | f
P: d = 1-1
P: e = 1-1
P: f = 1-1
P: g = 1-1
R: x | e | d
EOR
my $config = setuptest($repo, "Binarytype: deb\nPrefer: f\n");
my @r;
@r = expand($config, 'a');
is_deeply(\@r, [undef, 'nothing provides x | y needed by a'], 'install a');
@r = expand($config, 'b');
is_deeply(\@r, [1, 'b', 'd'], 'install b');
@r = expand($config, 'c');
is_deeply(\@r, [1, 'c', 'f'], 'install c');
@r = expand($config, 'g');
is_deeply(\@r, [1, 'e', 'g'], 'install g');
obs-build-20180831/t/recommends.t 0000644 0001750 0001750 00000001144 13350372713 015030 0 ustar alee alee #!/usr/bin/perl -w
use strict;
use Test::More tests => 4;
require 't/testlib.pm';
my $repo = <<'EOR';
P: a = 1-1
R: p
P: b = 1-1 p
P: c = 1-1 p
P: d = 1-1
r: b
P: e = 1-1
r: c
EOR
my $config = setuptest($repo);
my @r;
@r = expand($config, 'a');
is_deeply(\@r, [undef, 'have choice for p needed by a: b c'], 'install a');
@r = expand($config, 'a', 'd');
is_deeply(\@r, [1, 'a', 'b', 'd'], 'install a d');
@r = expand($config, 'a', 'e');
is_deeply(\@r, [1, 'a', 'c', 'e'], 'install a e');
@r = expand($config, 'a', 'd', 'e');
is_deeply(\@r, [undef, 'have choice for p needed by a: b c'], 'install a d e');
obs-build-20180831/t/changelog2spec.t 0000644 0001750 0001750 00000001761 13350372713 015565 0 ustar alee alee #!/usr/bin/perl -w
use strict;
use Test::More tests => 11;
sub onetest(@)
{
my $expected = shift;
my $actual = `./changelog2spec --selftest @_`;
is($actual, $expected, "changelog2spec --selftest @_");
}
my @tests=(
# format is 1:specfile 2:expected-changes 3++:list-of-changes-files
[qw"rpm rpm python-rpm rpm"],
[qw"python-rpm python-rpm python-rpm rpm"],
[qw"antlr antlr antlr antlr-bootstrap"],
[qw"antlr anyunrelated anyunrelated"],
[qw"antlr-bootstrap antlr-bootstrap antlr antlr-bootstrap"],
[qw"antlr-bootstrap antlr antlr"],
[qw"antlr-bootstrap antlr antlr antlr-other"],
[qw"foo _service:obs_scm:foo foo _service:obs_scm:foo"],
[qw"_service:obs_scm:foo _service:obs_scm:foo foo _service:obs_scm:foo"],
[qw"_service:obs_scm:foo foo foo foo-bar"],
[qw"_service:obs_scm:foo-bar foo foo foo-other"],
);
for my $t (@tests) {
my @tmp=@$t;
my $file=shift(@tmp);
foreach(0..$#tmp) {$tmp[$_].=".changes"}
my $expected=shift(@tmp);
onetest($expected, $file, @tmp);
}
obs-build-20180831/t/richdeps.t 0000644 0001750 0001750 00000013323 13350372713 014477 0 ustar alee alee #!/usr/bin/perl -w
use strict;
use Test::More tests => 45;
require 't/testlib.pm';
my $repo = <<'EOR';
P: a = 1-1
R: (b if c) d
P: b = 1-1
P: c = 1-1
P: d = 1-1
R: c
P: n1 = 1-1
R: n
P: n2 = 1-1
C: d
P: i = 1-1
P: j = 1-1
R: k
P: k = 1-1
C: (i and j)
P: lr = 1-1
R: (b if b)
P: lc1 = 1-1
C: (b if b)
P: lc2 = 1-1
C: (n if n)
P: m = 1-1
C: (b and (n if b))
P: cx = 1-1
C: (b and cx and d)
P: ign1 = 1-1
R: (ign and b)
P: ign2 = 1-1
R: (ign or b)
P: ign3 = 1-1
R: (b if ign)
P: ign4 = 1-1
R: (ign if b)
P: bad1 = 1-1
R: (n foo m)
P: bad2 = 1-1
C: (n foo m)
P: sc = 1-1
C: (a or sc) (n or sc)
P: ifelse = 1-1
R: (b if i else c)
P: unless = 1-1
C: (b unless i)
P: unlesselse = 1-1
C: (b unless i else c)
P: wa = 1-1 wx
P: wb = 1-1 wx wy
P: wc = 1-1 wy
EOR
my $config = setuptest($repo, 'Ignore: ign');
my @r;
@r = expand($config, "()");
is_deeply(\@r, [undef, 'cannot parse dependency ()'], 'install ()');
@r = expand($config, "(n and )");
is_deeply(\@r, [undef, 'cannot parse dependency (n and )'], 'install (n and )');
@r = expand($config, "(n foo m)");
is_deeply(\@r, [undef, 'cannot parse dependency (n foo m)'], 'install (n foo m)');
@r = expand($config, "n");
is_deeply(\@r, [undef, 'nothing provides n'], 'install n');
@r = expand($config, "(n or o)");
is_deeply(\@r, [undef, 'nothing provides (n or o)'], 'install (n or o)');
@r = expand($config, "(n and o)");
is_deeply(\@r, [undef, 'nothing provides (n and o)'], 'install (n and o)');
@r = expand($config, "n1");
is_deeply(\@r, [undef, "nothing provides n needed by n1"], "install n1");
@r = expand($config, "(n2 and d)");
is_deeply(\@r, [undef, 'n2 conflicts with d'], "install (n2 and d)");
@r = expand($config, "(n2 or d)");
is_deeply(\@r, [undef, "have choice for (n2 or d): d n2"], "install (n2 or d)");
@r = expand($config, "a");
is_deeply(\@r, [1, qw{a b c d}], "install a");
@r = expand($config, 'i', 'j');
is_deeply(\@r, [undef, '(provider k conflicts with i)', '(provider k conflicts with j)', "conflict for providers of k needed by j"], "install i j");
# test corner cases
@r = expand($config, "(b if b)");
is_deeply(\@r, [1], 'install (b if b)');
@r = expand($config, "(n if n)");
is_deeply(\@r, [1], 'install (n if n)');
@r = expand($config, "lr");
is_deeply(\@r, [1, 'lr'], 'install lr');
@r = expand($config, "lc1");
is_deeply(\@r, [undef, '(provider b is in conflict with lc1)', 'conflict for providers of (b if b) needed by lc1'], 'install lc1');
@r = expand($config, "lc2");
is_deeply(\@r, [undef, 'lc2 conflicts with always true (n if n)'], 'install lc2');
@r = expand($config, "m");
is_deeply(\@r, [1, 'm'], 'install m');
# complex config from the job
@r = expand($config, 'b', 'c', 'd', '!(b and c and d)');
is_deeply(\@r, [undef, 'conflicts with b', 'conflicts with c', 'conflicts with d'], 'install b c d !(b and c and d)');
@r = expand($config, '!(n if n)');
is_deeply(\@r, [undef, 'conflict with always true (n if n)'], 'install !(n if n)');
@r = expand($config, 'b', 'cx', 'd');
is_deeply(\@r, [undef, 'cx conflicts with b', 'cx conflicts with d'], 'install b cx d');
@r = expand($config, 'ign');
is_deeply(\@r, [undef, 'nothing provides ign'], 'install ign');
@r = expand($config, 'ign1');
is_deeply(\@r, [1, 'b', 'ign1'], 'install ign1');
@r = expand($config, 'ign2');
is_deeply(\@r, [1, 'ign2'], 'install ign2');
@r = expand($config, 'ign3');
is_deeply(\@r, [1, 'ign3'], 'install ign3');
@r = expand($config, 'b', 'ign4');
is_deeply(\@r, [1, 'b', 'ign4'], 'install b ign4');
@r = expand($config, '(ign and b)');
is_deeply(\@r, [undef, 'nothing provides (ign and b)'], 'install b');
@r = expand($config, 'bad1');
is_deeply(\@r, [undef, 'cannot parse dependency (n foo m) from bad1'], 'install bad1');
@r = expand($config, 'bad2');
is_deeply(\@r, [undef, 'cannot parse dependency (n foo m) from bad2'], 'install bad2');
@r = expand($config, 'sc', 'b');
is_deeply(\@r, [1, 'b', 'sc'], 'install sc b');
@r = expand($config, 'ifelse');
is_deeply(\@r, [undef, 'have choice for (b if i else c) needed by ifelse: c i'], 'install ifelse');
@r = expand($config, 'ifelse', 'i');
is_deeply(\@r, [1, 'b', 'i', 'ifelse'], 'install ifelse i');
@r = expand($config, 'ifelse', 'c');
is_deeply(\@r, [1, 'c', 'ifelse'], 'install ifelse c');
@r = expand($config, 'unless', 'b');
is_deeply(\@r, [1, 'b', 'i', 'unless'], 'install unless b');
@r = expand($config, 'unless', 'b', '!i');
is_deeply(\@r, [undef, '(provider i is in conflict)', 'conflict for providers of (b unless i) needed by unless'], 'install unless b !i');
@r = expand($config, 'unlesselse', 'b', 'c');
is_deeply(\@r, [undef, '(provider i is in conflict with unlesselse)', 'conflict for providers of (b unless i else c) needed by unlesselse'], 'install unlesselse b c');
@r = expand($config, 'unlesselse', 'b');
is_deeply(\@r, [1, 'b', 'i', 'unlesselse'], 'install unlesselse b');
@r = expand($config, 'unlesselse', 'c');
is_deeply(\@r, [1, 'c', 'unlesselse'], 'install unlesselse c');
@r = expand($config, '(wx and wy)');
is_deeply(\@r, [undef, 'have choice for (wx and wy): wa wb', 'have choice for (wx and wy): wb wc'], 'install (wx and wy)');
@r = expand($config, '(wx with wy)');
is_deeply(\@r, [1, 'wb'], 'install (wx with wy)');
@r = expand($config, '(wx without wy)');
is_deeply(\@r, [1, 'wa'], 'install (wx without wy)');
@r = expand($config, '(wy without wx)');
is_deeply(\@r, [1, 'wc'], 'install (wy without wx)');
@r = expand($config, '(wa with wa)');
is_deeply(\@r, [1, 'wa'], 'install (wa with wa)');
@r = expand($config, '(wa with nnn)');
is_deeply(\@r, [undef, 'nothing provides (wa with nnn)'], 'install (wa with nnn)');
@r = expand($config, '(wa without wa)');
is_deeply(\@r, [undef, 'nothing provides (wa without wa)'], 'install (wa without wa)');
@r = expand($config, '(wa without nnn)');
is_deeply(\@r, [1, 'wa'], 'install (wa without nnn)');
obs-build-20180831/t/testlib.pm 0000644 0001750 0001750 00000000706 13350372713 014516 0 ustar alee alee
use Build;
sub expand {
my ($c, @r) = Build::expand(@_);
return ($c, sort(@r));
}
sub setuptest {
my ($repo, $conf) = @_;
my $l = '';
my $id = '';
for (split("\n", $repo)) {
$id = "$1.noarch-0/0/0:" if /^P: (\S+)/;
s/:/:$id/;
$l .= "$_\n";
}
local *F;
open(F, '<', \$l);
my $config = Build::read_config('noarch', [ split("\n", $conf || '') ]);
Build::readdeps($config, undef, \*F);
close F;
return $config;
}
1;
obs-build-20180831/t/conflicts.t 0000644 0001750 0001750 00000004122 13350372713 014657 0 ustar alee alee #!/usr/bin/perl -w
use strict;
use Test::More tests => 13;
require 't/testlib.pm';
my $repo = <<'EOR';
P: a = 1-1
R: p
P: b = 1-1 p
P: c = 1-1 p
P: d = 1-1
C: b
P: e = 1-1
C: c
P: f = 1-1
C: p
P: g = 1-1
C: b c
P: h = 1-1
R: f
P: i = 1-1
P: j = 1-1
P: k = 1-1
R: j
P: l = 1-1
R: b d
P: m = 1-1
C: m
EOR
my $config = setuptest($repo, "Conflict: i:j");
my @r;
# test that conflicts can fix choices
@r = expand($config, 'a');
is_deeply(\@r, [undef, 'have choice for p needed by a: b c'], 'install a');
@r = expand($config, 'a', 'd');
is_deeply(\@r, [1, 'a', 'c', 'd'], 'install a d');
@r = expand($config, 'a', 'e');
is_deeply(\@r, [1, 'a', 'b', 'e'], 'install a e');
# test test conflicting all providers works
@r = expand($config, 'a', 'd', 'e');
is_deeply(\@r, [undef, '(provider b is in conflict with d)', '(provider c is in conflict with e)', 'conflict for providers of p needed by a'], 'install a d e');
@r = expand($config, 'a', 'f');
is_deeply(\@r, [undef, '(provider b is in conflict with f)', '(provider c is in conflict with f)', 'conflict for providers of p needed by a'], 'install a f');
# test that conflicting jobs work
@r = expand($config, 'b', 'f');
is_deeply(\@r, [undef, 'f conflicts with b'], 'install b f');
@r = expand($config, 'b', 'h');
is_deeply(\@r, [undef, '(provider f conflicts with b)', 'conflict for providers of f needed by h'], 'install b h');
# test conflicts specified in the job
@r = expand($config, 'i', '!i');
is_deeply(\@r, [undef, 'i is in conflict'], 'install i !i');
@r = expand($config, 'k', '!j');
is_deeply(\@r, [undef, '(provider j is in conflict)', 'conflict for providers of j needed by k'], 'install k !j');
# test conflicts from project config
@r = expand($config, 'i', 'j');
is_deeply(\@r, [undef, 'i conflicts with j', 'j conflicts with i'], 'install i j');
@r = expand($config, 'i', 'k');
is_deeply(\@r, [undef, '(provider j is in conflict with i)', 'conflict for providers of j needed by k'], 'install i k');
@r = expand($config, 'l');
is_deeply(\@r, [undef, 'd conflicts with b'], 'install l');
@r = expand($config, 'm');
is_deeply(\@r, [1, 'm'], 'install m');
obs-build-20180831/t/dist 0000755 0001750 0001750 00000002711 13350372713 013401 0 ustar alee alee #!/usr/bin/perl -w
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
use strict;
use Test::More tests => 9;
use Build;
sub d {
Build::dist_canon($_[0], $_[1]||'i586');
}
is(d("UnitedLinux 1.0 (x86-64)"), "ul1-x86_64");
is(d("SuSE SLES-8 (ia64)"), "sles8-ia64");
is(d("SuSE Linux 8.2 (x86-64)"), "8.2-x86_64");
is(d("SuSE SLES-9 (x86-64)"), "sles9-x86_64");
is(d("SUSE Linux 10.1 (PPC64)"), "10.1-ppc64");
is(d("SUSE Linux Enterprise 10 (PPC)"), "sles10-ppc");
is(d("openSUSE 10.3 (X86-64)"), "10.3-x86_64");
is(d("SUSE Linux Enterprise 11"), "sles11-i386");
is(d("openSUSE 11.3"), "11.3-i386");
obs-build-20180831/t/obsoletes.t 0000644 0001750 0001750 00000002443 13350372713 014676 0 ustar alee alee #!/usr/bin/perl -w
use strict;
use Test::More tests => 9;
require 't/testlib.pm';
my $repo = <<'EOR';
P: a = 1-1
R: p
P: b = 1-1 p
P: c = 1-1 p
P: d = 1-1
O: b
P: e = 1-1
O: c
P: f = 1-1
O: p
P: g = 1-1
O: b c
P: h = 1-1
R: b d
EOR
my $config = setuptest($repo);
my @r;
@r = expand($config, 'a');
is_deeply(\@r, [undef, 'have choice for p needed by a: b c'], 'install a');
@r = expand($config, 'a', 'd');
is_deeply(\@r, [1, 'a', 'c', 'd'], 'install a d');
@r = expand($config, 'a', 'e');
is_deeply(\@r, [1, 'a', 'b', 'e'], 'install a e');
@r = expand($config, 'a', 'd', 'e');
is_deeply(\@r, [undef, '(provider b is obsoleted by d)', '(provider c is obsoleted by e)', 'conflict for providers of p needed by a'], 'install a d e');
@r = expand($config, 'a', 'f');
is_deeply(\@r, [undef, 'have choice for p needed by a: b c'], 'install a f');
@r = expand($config, 'b', 'd');
is_deeply(\@r, [undef, 'd obsoletes b'], 'install b d');
@r = expand($config, 'h');
is_deeply(\@r, [undef, 'd obsoletes b'], 'install h');
@r = expand($config, 'h', 'd');
is_deeply(\@r, [undef, '(provider b is obsoleted by d)', 'conflict for providers of b needed by h'], 'install h d');
@r = expand($config, 'h', 'b');
is_deeply(\@r, [undef, '(provider d obsoletes b)', 'conflict for providers of d needed by h'], 'install h b');
obs-build-20180831/t/live-build 0000755 0001750 0001750 00000003736 13350372713 014502 0 ustar alee alee #!/usr/bin/perl -w -I ..
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
use strict;
use Test::More tests => 5;
use Build::LiveBuild;
use Data::Dumper;
use Digest::MD5 qw(md5_hex);
my $VAR = '
a
b
#comment
! whatever
';
is(Build::LiveBuild::filter($VAR), 'a
b
');
my $DEB_ARCHIVE = '
# comment
deb obs://openSUSE.org:Debian:7.0/standard wheezy main contrib
deb-src obs://openSUSE.org:Debian:7.0/standard wheezy main contrib
';
my $DEB_ARCHIVE_RESULT = "\$VAR1 = 'openSUSE.org:Debian:7.0/standard';
";
is(Dumper(Build::LiveBuild::parse_archive($DEB_ARCHIVE)), $DEB_ARCHIVE_RESULT);
my $config = {};
$Data::Dumper::Sortkeys = 1;
is(md5_hex(Dumper(Build::LiveBuild::parse( $config, 'standard.livebuild'))),
'9cfb69e8f0581293f207342edacd19e7');
#print Dumper(Build::LiveBuild::parse( $config, 'standard.livebuild'));
is(md5_hex(Dumper(Build::LiveBuild::parse( $config, 'directory.livebuild'))),
'bc803d2b4a375d9a02b3242117f6c93a');
#print Dumper(Build::LiveBuild::parse( $config, 'directory.livebuild'));
is(md5_hex(Dumper(Build::LiveBuild::parse( $config, 'bad.livebuild'))),
'1e596160978007d1014e9c5e38574700');
#print Dumper(Build::LiveBuild::parse( $config, 'bad.livebuild'));
obs-build-20180831/t/bad.livebuild 0000644 0001750 0001750 00000120000 13350372713 015127 0 ustar alee alee ./PaxHeaders.6730/auto 0000644 0000000 0000000 00000000132 12222266372 013026 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
auto/ 0000755 0001750 0000144 00000000000 12222266372 012701 5 ustar 00jblunck users 0000000 0000000 auto/PaxHeaders.6730/clean 0000644 0000000 0000000 00000000132 12222266372 013753 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
auto/clean 0000755 0001750 0000144 00000000240 12222266372 013705 0 ustar 00jblunck users 0000000 0000000 #!/bin/sh
set -e
lb clean noauto "${@}"
rm -f config/binary config/bootstrap config/chroot config/common config/source
rm -f config/control
rm -f build.log
auto/PaxHeaders.6730/config 0000644 0000000 0000000 00000000132 12222266372 014136 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
auto/config 0000755 0001750 0000144 00000000626 12222266372 014100 0 ustar 00jblunck users 0000000 0000000 #!/bin/sh
set -e
case "$(dpkg --print-architecture)" in
amd64)
_LINUX_FLAVOURS="amd64"
_SOURCE="false"
;;
i386)
_LINUX_FLAVOURS="486 686-pae"
_SOURCE="true"
;;
esac
lb config noauto \
--clean \
--ignore-system-defaults \
--mode debian \
--debian-installer live \
--linux-flavours "${_LINUX_FLAVOURS}" \
--linux-packages "linux-image linux-headers" \
--source "${_SOURCE}" \
"${@}"
auto/PaxHeaders.6730/build 0000644 0000000 0000000 00000000132 12222266372 013770 x ustar 00 0000000 0000000 30 mtime=1380543738.699537615
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
auto/build 0000755 0001750 0000144 00000000112 12222266372 013720 0 ustar 00jblunck users 0000000 0000000 #!/bin/sh
set -e
lb build noauto "${@}" && echo $? 2>&1 | tee build.log
./PaxHeaders.6730/config 0000644 0000000 0000000 00000000132 12222300375 013313 x ustar 00 0000000 0000000 30 mtime=1380548861.684530853
30 atime=1404933484.298323059
30 ctime=1404933481.152361217
config/ 0000755 0001750 0000144 00000000000 12222300375 013166 5 ustar 00jblunck users 0000000 0000000 config/PaxHeaders.6730/bootloaders 0000644 0000000 0000000 00000000132 12222304630 015471 x ustar 00 0000000 0000000 30 mtime=1380551064.696527946
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
config/bootloaders/ 0000755 0001750 0000144 00000000000 12222304630 015501 5 ustar 00jblunck users 0000000 0000000 config/PaxHeaders.6730/package-lists 0000644 0000000 0000000 00000000132 12357312571 015717 x ustar 00 0000000 0000000 30 mtime=1404933497.776159592
30 atime=1404933498.247153879
30 ctime=1404933497.776159592
config/package-lists/ 0000755 0001750 0000144 00000000000 12357312571 015727 5 ustar 00jblunck users 0000000 0000000 config/package-lists/PaxHeaders.6730/installer.list.chroot 0000644 0000000 0000000 00000000132 12222266372 022161 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
config/package-lists/installer.list.chroot 0000644 0001750 0000144 00000000037 12222266372 022114 0 ustar 00jblunck users 0000000 0000000 debian-installer-launcher
sudo
config/package-lists/PaxHeaders.6730/live.list.chroot 0000644 0000000 0000000 00000000132 12222266372 021123 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
config/package-lists/live.list.chroot 0000644 0001750 0000144 00000000027 12222266372 021055 0 ustar 00jblunck users 0000000 0000000 live-manual
live-tools
config/package-lists/PaxHeaders.6730/localization.list.chroot 0000644 0000000 0000000 00000000132 12222266372 022654 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
config/package-lists/localization.list.chroot 0000644 0001750 0000144 00000000034 12222266372 022604 0 ustar 00jblunck users 0000000 0000000 task-english
console-tools
config/package-lists/PaxHeaders.6730/standard.list.chroot 0000644 0000000 0000000 00000000132 12222266372 021764 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404933490.584246818
30 ctime=1404933481.152361217
config/package-lists/standard.list.chroot 0000644 0001750 0000144 00000000072 12222266372 021716 0 ustar 00jblunck users 0000000 0000000 ! Packages Priority standard
task-laptop
task-ssh-server
config/package-lists/PaxHeaders.6730/memtest 0000644 0000000 0000000 00000000132 12222266372 017373 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404933486.633294738
30 ctime=1404933497.776159592
config/package-lists/memtest 0000644 0001750 0000144 00000000013 12222266372 017320 0 ustar 00jblunck users 0000000 0000000 memtest86+
config/PaxHeaders.6730/archives 0000644 0000000 0000000 00000000132 12222302706 014762 x ustar 00 0000000 0000000 30 mtime=1380550086.359529237
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
config/archives/ 0000755 0001750 0000144 00000000000 12222302706 014772 5 ustar 00jblunck users 0000000 0000000 config/archives/PaxHeaders.6730/debian.list.chroot 0000644 0000000 0000000 00000000132 12222302676 020461 x ustar 00 0000000 0000000 30 mtime=1380550078.121529248
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
config/archives/debian.list.chroot 0000644 0001750 0000144 00000000202 12222302676 020406 0 ustar 00jblunck users 0000000 0000000 deb obs://openSUSE.org:Debian:7.0/standard wheezy main contrib
deb-src obs://openSUSE.org:Debian:7.0/standard wheezy main contrib
config/archives/PaxHeaders.6730/debian.key.chroot 0000644 0000000 0000000 00000000132 12222300432 020262 x ustar 00 0000000 0000000 30 mtime=1380548890.449530815
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
config/archives/debian.key.chroot 0000644 0001750 0000144 00000000045 12222300432 020214 0 ustar 00jblunck users 0000000 0000000 a73043cf-7b16-42dc-b0d9-3031ed4370be
./PaxHeaders.6730/README 0000644 0000000 0000000 00000000132 12222266372 013013 x ustar 00 0000000 0000000 30 mtime=1380543738.739537615
30 atime=1404933481.152361217
30 ctime=1404933481.152361217
README 0000644 0001750 0000144 00000000771 12222266372 012616 0 ustar 00jblunck users 0000000 0000000 This is the configuration tree for:
Debian Standard
A software called live-build can be used to automatically build images from
this configuration tree.
live-build can be obtained from .
On Debian based systems, live-build can be installed with:
# apt-get install live-build
More information about live-build and the Live Systems project can be found on
its homepage at and in the manual at
.
obs-build-20180831/getbuildids 0000755 0001750 0001750 00000004013 13350372713 014467 0 ustar alee alee #!/usr/bin/perl -w
################################################################
#
# Copyright (c) 2016 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
BEGIN {
unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
}
use Build;
use strict;
sub getbuildid {
my ($pkg) = @_;
my $d = Build::query($pkg, 'evra' => 1, 'buildtime' => 1);
return $d ? Build::getbuildid($d) : undef;
}
if (@ARGV && $ARGV[0] eq 'cachecheck') {
my $pkg;
my $buildid;
my $dst;
while () {
chomp;
if (/^PKG (\S+) (.+)$/) {
($pkg, $buildid, $dst) = ($1, $2, undef);
} elsif (/^PKG (\S+)$/) {
($pkg, $buildid, $dst) = ($1, undef, undef);
} elsif (/^DST (.+)$/) {
$dst = $1;
unlink($dst) if -e $dst;
} elsif (/^CACHE (.+)$/) {
next unless $dst;
my $cpkg = $1;
next unless -s $cpkg;
if ($buildid) {
my $bid = getbuildid($cpkg);
next unless $bid;
if ($bid =~ / 0-/) {
my $buildid2 = $buildid;
$buildid2 =~ s/ .*?-/0-/;
next if $bid ne $buildid2;
} else {
next if $bid ne $buildid;
}
}
symlink($cpkg, $dst);
$dst = undef; # first hit wins
}
}
exit(0);
}
while () {
chomp;
my $dst = $_;
my $buildid = getbuildid($dst);
next unless $buildid;
open(F, '>', "$dst.buildid") || next;
print F "$buildid\n";
close(F);
}
obs-build-20180831/README 0000644 0001750 0001750 00000000652 13350372713 013127 0 ustar alee alee
This is a tool to build binary packages in a safe and reproducible
way. The default is to build in a chroot sandbox, but it also
supports building in a virtual machine for better security.
The build tool can work with multiple package and recipe formats.
The currently supported package formats are deb, rpm, and arch.
The supported recipe formats are spec, dsc, kiwi, and PKGBUILD.
See the man page for more information.
obs-build-20180831/dummyhttpserver 0000755 0001750 0001750 00000012027 13350372713 015456 0 ustar alee alee #!/usr/bin/perl
# dead-simple HTTP server
# serves current directory on localhost:80
use Socket;
use POSIX;
use Fcntl qw(:DEFAULT :flock);
use strict;
$| = 1;
my ($build_root, $dir) = @ARGV;
if (defined($build_root)) {
chroot($build_root) || die("chroot $build_root: $!\n");
chdir('/') || die("chdir /: $!\n");
}
if (defined($dir)) {
chdir($dir) || die("chdir $dir: $!\n");
}
my $tcpproto = getprotobyname('tcp');
my $acceptsock;
socket($acceptsock , PF_INET, SOCK_STREAM, $tcpproto) || die "socket: $!\n";
setsockopt($acceptsock, SOL_SOCKET, SO_REUSEADDR, pack("l",1));
bind($acceptsock, sockaddr_in(80, inet_aton('127.0.0.1'))) || die "bind: $!\n";
listen($acceptsock , 512) || die "listen: $!\n";
my $sock;
my $status;
sub reply {
my ($str, @hdrs) = @_;
if (@hdrs && $hdrs[0] =~ /^status: ((\d+).*)/i) {
$status = $2;
$hdrs[0] = "HTTP/1.1 $1";
$hdrs[0] =~ s/:/ /g;
} else {
$status = 200;
unshift @hdrs, "HTTP/1.1 200 OK";
}
push @hdrs, "Cache-Control: no-cache";
push @hdrs, "Connection: close";
push @hdrs, "Content-Length: ".length($str) if defined($str);
my $data = join("\r\n", @hdrs)."\r\n\r\n";
$data .= $str if defined $str;
fcntl($sock, F_SETFL,O_NONBLOCK);
my $dummy = '';
1 while sysread($sock, $dummy, 1024, 0);
fcntl($sock, F_SETFL,0);
my $l;
while (length($data)) {
$l = syswrite($sock, $data, length($data));
die("write error: $!\n") unless $l;
$data = substr($data, $l);
}
}
sub reply_error {
my ($errstr) = @_;
my $code = 400;
my $tag = 'Error';
if ($errstr =~ /^(\d+)\s+([^\r\n]*)/) {
$code = $1;
$tag = $2;
} elsif ($errstr =~ /^([^\r\n]+)/) {
$tag = $1;
}
reply("$errstr\n", "Status: $code $tag", 'Content-Type: text/plain');
}
sub readrequest {
my $qu = '';
my $request;
while (1) {
if ($qu =~ /^(.*?)\r?\n/s) {
$request = $1;
last;
}
die($qu eq '' ? "empty query\n" : "received truncated query\n") if !sysread($sock, $qu, 1024, length($qu));
}
my ($act, $path, $vers, undef) = split(' ', $request, 4);
die("400 No method name\n") if !$act;
if ($vers) {
die("501 Unsupported method: $act\n") if $act ne 'GET' && $act ne 'HEAD';
# read in all headers
while ($qu !~ /^(.*?)\r?\n\r?\n(.*)$/s) {
die("501 received truncated query\n") if !sysread($sock, $qu, 1024, length($qu));
}
$qu =~ /^(.*?)\r?\n\r?\n(.*)$/s; # redo regexp to work around perl bug
$qu = $2;
} else {
die("501 Bad method, must be GET\n") if $act ne 'GET';
$qu = '';
}
my $query_string = '';
if ($path =~ /^(.*?)\?(.*)$/) {
$path = $1;
$query_string = $2;
}
$path =~ s/%([a-fA-F0-9]{2})/chr(hex($1))/ge; # unescape path
die("501 invalid path\n") unless $path =~ /^\//s; # forbid relative paths
die("501 invalid path\n") if $path =~ /\0/s;
# do simple path substitutions
while (1) {
next if $path =~ s!//!/!;
next if $path =~ s!/\.(?:/|$)!/!;
next if $path =~ s!/[^/]+/\.\.(?:/|$)!/!;
next if $path =~ s!/\.\.(?:/|$)!/!;
last;
}
return ($path, $query_string, $qu);
}
sub escape {
my ($d) = @_;
$d =~ s/&/&/sg;
$d =~ s/</sg;
$d =~ s/>/>/sg;
$d =~ s/"/"/sg;
return $d;
}
while (1) {
my $peeraddr = accept($sock, $acceptsock);
next unless $peeraddr;
my $pid = fork();
last if defined($pid) && !$pid;
close $sock;
1 while waitpid(-1, POSIX::WNOHANG) > 0;
}
close($acceptsock);
my $path = '?';
eval {
($path) = readrequest();
my $lpath = ".$path";
if (-d $lpath) {
if ($path !~ /\/$/) {
my $rpath = "$path/";
$rpath =~ s/([\000-\040<>;\"#\?&\+=%[\177-\377])/sprintf("%%%02X",ord($1))/sge;
;
reply('', 'Status: 301 Moved Permanently', "Location: $rpath");
} else {
my %d;
my $dir;
if (opendir($dir, $lpath)) {
%d = map {$_ => 1} readdir($dir);
closedir($dir);
}
delete $d{'.'};
delete $d{'..'};
my $body = "\n";
$body .= "Directory listing for ".escape($path)."\n";
$body .= "\n";
$body .= "Directory listing for ".escape($path)."
\n";
$body .= "
\n\n
\n\n\n";
reply($body, 'Content-type: text/html');
}
} elsif (-e _) {
my $f;
open($f, '<', $lpath) || die("500 $lpath: $!\n");
my @s = stat($f);
die("stat: $!\n") unless @s;
my $l = $s[7];
reply(undef, "Content-Length: $l", 'Content-Type: application/octet-stream');
my $data;
while (1) {
last unless $l;
my $r = sysread($f, $data, 8192);
$data = substr($data, 0, $l) if length($data) > $l;
$l -= length($data);
while (length($data)) {
my $l2 = syswrite($sock, $data, length($data));
die("socket write: $!\n") unless $l2;
$data = substr($data, $l2);
}
}
close($f);
} else {
die("404 File not found\n");
}
};
reply_error($@) if $@;
close $sock;
print "[$status $path]";
obs-build-20180831/mkbaselibs 0000755 0001750 0001750 00000102521 13350372713 014307 0 ustar alee alee #!/usr/bin/perl -w
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
use POSIX;
use strict;
use File::Temp qw/tempfile tempdir/;
# See: http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html#S3-RPM-FILE-FORMAT-HEADER-TAG-LISTING
# cf http://search.cpan.org/~davecross/Parse-RPM-Spec-0.01/lib/Parse/RPM/Spec.pm
my %STAG = (
"NAME" => 1000,
"VERSION" => 1001,
"RELEASE" => 1002,
"EPOCH" => 1003,
"SERIAL" => 1003,
"SUMMARY" => 1004,
"DESCRIPTION" => 1005,
"BUILDTIME" => 1006,
"BUILDHOST" => 1007,
"INSTALLTIME" => 1008,
"SIZE" => 1009,
"DISTRIBUTION" => 1010,
"VENDOR" => 1011,
"GIF" => 1012,
"XPM" => 1013,
"LICENSE" => 1014,
"COPYRIGHT" => 1014,
"PACKAGER" => 1015,
"GROUP" => 1016,
"SOURCE" => 1018,
"PATCH" => 1019,
"URL" => 1020,
"OS" => 1021,
"ARCH" => 1022,
"PREIN" => 1023,
"POSTIN" => 1024,
"PREUN" => 1025,
"POSTUN" => 1026,
"OLDFILENAMES" => 1027,
"FILESIZES" => 1028,
"FILESTATES" => 1029,
"FILEMODES" => 1030,
"FILERDEVS" => 1033,
"FILEMTIMES" => 1034,
"FILEMD5S" => 1035,
"FILELINKTOS" => 1036,
"FILEFLAGS" => 1037,
"FILEUSERNAME" => 1039,
"FILEGROUPNAME" => 1040,
"ICON" => 1043,
"SOURCERPM" => 1044,
"FILEVERIFYFLAGS" => 1045,
"ARCHIVESIZE" => 1046,
"PROVIDENAME" => 1047,
"PROVIDES" => 1047,
"REQUIREFLAGS" => 1048,
"REQUIRENAME" => 1049,
"REQUIREVERSION" => 1050,
"NOSOURCE" => 1051,
"NOPATCH" => 1052,
"CONFLICTFLAGS" => 1053,
"CONFLICTNAME" => 1054,
"CONFLICTVERSION" => 1055,
"EXCLUDEARCH" => 1059,
"EXCLUDEOS" => 1060,
"EXCLUSIVEARCH" => 1061,
"EXCLUSIVEOS" => 1062,
"RPMVERSION" => 1064,
"TRIGGERSCRIPTS" => 1065,
"TRIGGERNAME" => 1066,
"TRIGGERVERSION" => 1067,
"TRIGGERFLAGS" => 1068,
"TRIGGERINDEX" => 1069,
"VERIFYSCRIPT" => 1079,
"CHANGELOGTIME" => 1080,
"CHANGELOGNAME" => 1081,
"CHANGELOGTEXT" => 1082,
"PREINPROG" => 1085,
"POSTINPROG" => 1086,
"PREUNPROG" => 1087,
"POSTUNPROG" => 1088,
"BUILDARCHS" => 1089,
"OBSOLETENAME" => 1090,
"OBSOLETES" => 1090,
"VERIFYSCRIPTPROG" => 1091,
"TRIGGERSCRIPTPROG" => 1092,
"COOKIE" => 1094,
"FILEDEVICES" => 1095,
"FILEINODES" => 1096,
"FILELANGS" => 1097,
"PREFIXES" => 1098,
"INSTPREFIXES" => 1099,
"SOURCEPACKAGE" => 1106,
"PROVIDEFLAGS" => 1112,
"PROVIDEVERSION" => 1113,
"OBSOLETEFLAGS" => 1114,
"OBSOLETEVERSION" => 1115,
"DIRINDEXES" => 1116,
"BASENAMES" => 1117,
"DIRNAMES" => 1118,
"OPTFLAGS" => 1122,
"DISTURL" => 1123,
"PAYLOADFORMAT" => 1124,
"PAYLOADCOMPRESSOR" => 1125,
"PAYLOADFLAGS" => 1126,
"INSTALLCOLOR" => 1127,
"INSTALLTID" => 1128,
"REMOVETID" => 1129,
"RHNPLATFORM" => 1131,
"PLATFORM" => 1132,
"PATCHESNAME" => 1133,
"PATCHESFLAGS" => 1134,
"PATCHESVERSION" => 1135,
"CACHECTIME" => 1136,
"CACHEPKGPATH" => 1137,
"CACHEPKGSIZE" => 1138,
"CACHEPKGMTIME" => 1139,
"FILECOLORS" => 1140,
"FILECLASS" => 1141,
"CLASSDICT" => 1142,
"FILEDEPENDSX" => 1143,
"FILEDEPENDSN" => 1144,
"DEPENDSDICT" => 1145,
"SOURCEPKGID" => 1146,
"PRETRANS" => 1151,
"POSTTRANS" => 1152,
"PRETRANSPROG" => 1153,
"POSTTRANSPROG" => 1154,
"DISTTAG" => 1155,
"SUGGESTSNAME" => 1156,
"SUGGESTSVERSION" => 1157,
"SUGGESTSFLAGS" => 1158,
"ENHANCESNAME" => 1159,
"ENHANCESVERSION" => 1160,
"ENHANCESFLAGS" => 1161,
"PRIORITY" => 1162,
"CVSID" => 1163,
);
# do not mix numeric tags with symbolic tags.
# special symbolic tag 'FILENAME' exists.
# This function seems to take a set of tags and populates a global
# hash-table (%res) with data obtained by doing a binary unpack() on
# the raw package
# http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html
sub rpmq_many {
my $rpm = shift;
my @stags = @_;
my $need_filenames = grep { $_ eq 'FILENAMES' } @stags;
push @stags, 'BASENAMES', 'DIRNAMES', 'DIRINDEXES', 'OLDFILENAMES' if $need_filenames;
@stags = grep { $_ ne 'FILENAMES' } @stags if $need_filenames;
my %stags = map {0+($STAG{$_} or $_) => $_} @stags;
my ($magic, $sigtype, $headmagic, $cnt, $cntdata, $lead, $head, $index, $data, $tag, $type, $offset, $count);
local *RPM;
if (ref($rpm) eq 'ARRAY') {
($headmagic, $cnt, $cntdata) = unpack('N@8NN', $rpm->[0]);
if ($headmagic != 0x8eade801) {
warn("Bad rpm\n");
return ();
}
if (length($rpm->[0]) < 16 + $cnt * 16 + $cntdata) {
warn("Bad rpm\n");
return ();
}
$index = substr($rpm->[0], 16, $cnt * 16);
$data = substr($rpm->[0], 16 + $cnt * 16, $cntdata);
} else {
return () unless open(RPM, "<$rpm");
if (read(RPM, $lead, 96) != 96) {
warn("Bad rpm $rpm\n");
close RPM;
return ();
}
($magic, $sigtype) = unpack('N@78n', $lead);
if ($magic != 0xedabeedb || $sigtype != 5) {
warn("Bad rpm $rpm\n");
close RPM;
return ();
}
if (read(RPM, $head, 16) != 16) {
warn("Bad rpm $rpm\n");
close RPM;
return ();
}
($headmagic, $cnt, $cntdata) = unpack('N@8NN', $head);
if ($headmagic != 0x8eade801) {
warn("Bad rpm $rpm\n");
close RPM;
return ();
}
if (read(RPM, $index, $cnt * 16) != $cnt * 16) {
warn("Bad rpm $rpm\n");
close RPM;
return ();
}
$cntdata = ($cntdata + 7) & ~7;
if (read(RPM, $data, $cntdata) != $cntdata) {
warn("Bad rpm $rpm\n");
close RPM;
return ();
}
}
my %res = ();
if (ref($rpm) eq 'ARRAY' && @stags && @$rpm > 1) {
my %res2 = &rpmq_many([ $rpm->[1] ], @stags);
%res = (%res, %res2);
return %res;
}
if (ref($rpm) ne 'ARRAY' && @stags) {
if (read(RPM, $head, 16) != 16) {
warn("Bad rpm $rpm\n");
close RPM;
return ();
}
($headmagic, $cnt, $cntdata) = unpack('N@8NN', $head);
if ($headmagic != 0x8eade801) {
warn("Bad rpm $rpm\n");
close RPM;
return ();
}
if (read(RPM, $index, $cnt * 16) != $cnt * 16) {
warn("Bad rpm $rpm\n");
close RPM;
return ();
}
if (read(RPM, $data, $cntdata) != $cntdata) {
warn("Bad rpm $rpm\n");
close RPM;
return ();
}
}
close RPM if ref($rpm) ne 'ARRAY';
return %res unless @stags; # nothing to do
while($cnt-- > 0) {
($tag, $type, $offset, $count, $index) = unpack('N4a*', $index);
$tag = 0+$tag;
if ($stags{$tag}) {
eval {
my $otag = $stags{$tag};
if ($type == 0) {
$res{$otag} = [ '' ];
} elsif ($type == 1) {
$res{$otag} = [ unpack("\@${offset}c$count", $data) ];
} elsif ($type == 2) {
$res{$otag} = [ unpack("\@${offset}c$count", $data) ];
} elsif ($type == 3) {
$res{$otag} = [ unpack("\@${offset}n$count", $data) ];
} elsif ($type == 4) {
$res{$otag} = [ unpack("\@${offset}N$count", $data) ];
} elsif ($type == 5) {
$res{$otag} = [ undef ];
} elsif ($type == 6) {
$res{$otag} = [ unpack("\@${offset}Z*", $data) ];
} elsif ($type == 7) {
$res{$otag} = [ unpack("\@${offset}a$count", $data) ];
} elsif ($type == 8 || $type == 9) {
my $d = unpack("\@${offset}a*", $data);
my @res = split("\0", $d, $count + 1);
$res{$otag} = [ splice @res, 0, $count ];
} else {
$res{$otag} = [ undef ];
}
};
if ($@) {
warn("Bad rpm $rpm: $@\n");
return ();
}
}
}
if ($need_filenames) {
if ($res{'OLDFILENAMES'}) {
$res{'FILENAMES'} = [ @{$res{'OLDFILENAMES'}} ];
} else {
my $i = 0;
$res{'FILENAMES'} = [ map {"$res{'DIRNAMES'}->[$res{'DIRINDEXES'}->[$i++]]$_"} @{$res{'BASENAMES'}} ];
}
}
return %res;
}
sub rpmq_add_flagsvers {
my $res = shift;
my $name = shift;
my $flags = shift;
my $vers = shift;
return unless $res;
my @flags = @{$res->{$flags} || []};
my @vers = @{$res->{$vers} || []};
for (@{$res->{$name}}) {
if (@flags && ($flags[0] & 0xe) && @vers) {
$_ .= ' ';
$_ .= '<' if $flags[0] & 2;
$_ .= '>' if $flags[0] & 4;
$_ .= '=' if $flags[0] & 8;
$_ .= " $vers[0]";
}
shift @flags;
shift @vers;
}
}
my @preamble = qw{
Name Version Release Epoch Summary Copyright License Distribution
Disturl Vendor Group Packager Url Icon Prefixes
};
my $rpm;
my $arch;
my $config = '';
my $targettype;
my $targetarch;
my $prefix;
my $extension;
my $configdir;
my $targetname;
my $legacyversion;
my @baselib;
my @config;
my @provides;
my @obsoletes;
my @requires;
my @prerequires;
my @conflicts;
my @recommends;
my @supplements;
my @suggests;
my @prein;
my @postin;
my @preun;
my @postun;
my $autoreqprov;
my $verbose;
my %target_matched;
my @filesystem;
# Used for each package by
sub parse_config {
my $target = shift;
my $pkgname = shift;
my $pkgver = shift;
my $pkghasmatched;
my $pkgmatches = 1;
my $packageseen = 0;
$prefix = '';
$legacyversion = '';
$extension = '';
$configdir = '';
$targetname = '';
($targetarch, $targettype) = split(':', $target, 2);
@baselib = ();
@config = ();
@provides = ();
@obsoletes = ();
@requires = ();
@recommends = ();
@supplements = ();
@suggests = ();
@prerequires = ();
@conflicts = ();
@prein = ();
@postin = ();
@preun = ();
@postun = ();
$autoreqprov = 'on';
my $match1 = '';
for (split("\n", $config)) {
s/^\s+//;
s/\s+$//;
next if $_ eq '' || $_ =~ /^#/;
if ($_ eq 'end_of_config') {
$pkgmatches = 0;
$packageseen = 0;
next;
}
s/\/$targettype/g;
s/\/$targetarch/g;
s/\/$pkgname/g;
s/\/$pkgver/g;
s/\/$prefix/g;
s/\/$extension/g;
s/\/$configdir/g;
s/\/$match1/g;
if (/^arch\s+/) {
next unless s/^arch\s+\Q$arch\E\s+//;
}
next if /^targets\s+/;
if (/\s+package\s+[-+_a-zA-Z0-9]+$/) {
$pkgmatches = 0; # XXX: hack for targettype/targetarch conditional
$packageseen = 1;
}
if (/\s+package\s+\/[-+_a-zA-Z0-9]+\/$/) {
$pkgmatches = 0; # XXX: hack
$packageseen = 1;
}
if (/^targettype\s+/) {
next unless s/^targettype\s+\Q$targettype\E\s+//;
}
if (/^targetarch\s+/) {
next unless s/^targetarch\s+\Q$targetarch\E\s+//;
}
if (/^prefix\s+(.*?)$/) { $prefix = $1; next; }
if (/^legacyversion\s+(.*?)$/) { $legacyversion = $1; next; }
if (/^extension\s+(.*?)$/) { $extension = $1; next; }
if (/^configdir\s+(.*?)$/) { $configdir= $1; next; }
if (/^targetname\s+(.*?)$/) {
$targetname = $1 if $pkgmatches || !$packageseen;
next;
}
$_ = "baselib $_" if /^[\+\-\"]/;
$_ = "package $_" if /^[-+_a-zA-Z0-9]+$/;
if (/^package\s+\/(.*?)\/$/) {
my $pm = $1;
$packageseen = 1;
$pkgmatches = $pkgname =~ /$pm/;
$match1 = defined($1) ? $1 : '' if $pkgmatches;
$pkghasmatched |= $pkgmatches if $pkgname =~ /-debuginfo$/ && $target_matched{$target};
next;
}
if (/^package\s+(.*?)$/) {
$packageseen = 1;
$pkgmatches = $1 eq $pkgname;
$pkghasmatched |= $pkgmatches;
next;
}
next unless $pkgmatches;
return 0 if $_ eq 'block!';
if (/^provides\s+(.*?)$/) { push @provides, $1; next; }
if (/^requires\s+(.*?)$/) { push @requires, $1; next; }
if (/^recommends\s+(.*?)$/) { push @recommends, $1; next; }
if (/^supplements\s+(.*?)$/) { push @supplements, $1; next; }
if (/^suggests\s+(.*?)$/) { push @suggests, $1; next; }
if (/^prereq\s+(.*?)$/) { push @prerequires, $1; next; }
if (/^obsoletes\s+(.*?)$/) { push @obsoletes, $1; next; }
if (/^conflicts\s+(.*?)$/) { push @conflicts, $1; next; }
if (/^baselib\s+(.*?)$/) { push @baselib, $1; next; }
if (/^config\s+(.*?)$/) { push @config, $1; next; }
if (/^pre(in)?\s+(.*?)$/) { push @prein, $2; next; }
if (/^post(in)?\s+(.*?)$/) { push @postin, $2; next; }
if (/^preun\s+(.*?)$/) { push @preun, $1; next; }
if (/^postun\s+(.*?)$/) { push @preun, $1; next; }
if (/^autoreqprov\s+(.*?)$/) {$autoreqprov = $1; next; }
die("bad line: $_\n");
}
return $pkghasmatched;
}
sub read_config {
my $cfname = shift;
local *F;
open(F, "<$cfname") || die("$cfname: $!\n");
my @cf = ;
close F;
$config .= join('', @cf);
# add end of config marker to reset package matching
$config .= "\nend_of_config\n";
}
sub get_targets {
my $architecture = shift;
my $conf = shift;
my %targets;
for (split("\n", $conf)) {
if (/^arch\s+/) {
next unless s/^arch\s+\Q$architecture\E\s+//;
}
if (/^targets\s+(.*?)$/) {
$targets{$_} = 1 for split(' ', $1);
}
}
my @targets = sort keys %targets;
return @targets;
}
# Packages listed in config file
sub get_pkgnames {
my %rpms;
for (split("\n", $config)) {
if (/^(.*\s+)?package\s+([-+_a-zA-Z0-9]+)\s*$/) { # eg : arch ppc package libnuma-devel
$rpms{$2} = 1;
} elsif (/^\s*([-+_a-zA-Z0-9]+)\s*$/) { # eg: readline-devel
$rpms{$1} = 1;
}
}
return sort keys %rpms;
}
# Packages listed in config file - debian variant (can have "." in package names)
sub get_debpkgnames {
my %debs;
for (split("\n", $config)) {
if (/^(.*\s+)?package\s+([-+_a-zA-Z0-9.]+)\s*$/) { # eg : arch ppc package libnuma-devel
$debs{$2} = 1;
} elsif (/^\s*([-+_a-zA-Z0-9.]+)\s*$/) { # eg: readline-devel
$debs{$1} = 1;
}
}
return sort keys %debs;
}
sub handle_rpms {
for $rpm (@_) {
my @stags = map {uc($_)} @preamble;
push @stags, 'DESCRIPTION';
push @stags, 'FILENAMES', 'FILEMODES', 'FILEUSERNAME', 'FILEGROUPNAME', 'FILEFLAGS', 'FILEVERIFYFLAGS';
push @stags, 'CHANGELOGTIME', 'CHANGELOGNAME', 'CHANGELOGTEXT';
push @stags, 'ARCH', 'SOURCERPM', 'RPMVERSION';
push @stags, 'BUILDTIME';
my %res = rpmq_many($rpm, @stags);
die("$rpm: bad rpm\n") unless $res{'NAME'};
my $rname = $res{'NAME'}->[0];
my $sname = $res{'SOURCERPM'}->[0];
die("$rpm is a sourcerpm\n") unless $sname;
die("bad sourcerpm: $sname\n") unless $sname =~ /^(.*)-([^-]+)-([^-]+)\.(no)?src\.rpm$/;
$sname = $1;
my $sversion = $2;
my $srelease = $3;
$arch = $res{'ARCH'}->[0];
my @targets = get_targets($arch, $config);
if (!@targets) {
print "no targets for arch $arch, skipping $rname\n";
next;
}
for my $target (@targets) {
next unless parse_config($target, $res{'NAME'}->[0], $res{'VERSION'}->[0]);
die("targetname not set\n") unless $targetname;
$target_matched{$target} = 1;
my %ghosts;
my @rpmfiles = @{$res{'FILENAMES'}};
my @ff = @{$res{'FILEFLAGS'}};
for (@rpmfiles) {
$ghosts{$_} = 1 if $ff[0] & (1 << 6);
shift @ff;
}
my %files;
my %cfiles;
my %moves;
my %symlinks;
for my $r (@baselib) {
my $rr = substr($r, 1);
if (substr($r, 0, 1) eq '+') {
if ($rr =~ /^(.*?)\s*->\s*(.*?)$/) {
if (grep {$_ eq $1} @rpmfiles) {
$files{$1} = 1;
$moves{$1} = $2;
}
} else {
for (grep {/$rr/} @rpmfiles) {
$files{$_} = 1;
delete $moves{$_};
}
}
} elsif (substr($r, 0, 1) eq '-') {
delete $files{$_} for grep {/$rr/} keys %files;
} elsif (substr($r, 0, 1) eq '"') {
$rr =~ s/\"$//;
if ($rr =~ /^(.*?)\s*->\s*(.*?)$/) {
$symlinks{$1} = $2;
} else {
die("bad baselib string rule: $r\n");
}
} else {
die("bad baselib rule: $r\n");
}
}
if ($configdir) {
for my $r (@config) {
my $rr = substr($r, 1);
if (substr($r, 0, 1) eq '+') {
$cfiles{$_} = 1 for grep {/$rr/} grep {!$ghosts{$_}} @rpmfiles;
} elsif (substr($r, 0, 1) eq '-') {
delete $cfiles{$_} for grep {/$rr/} keys %cfiles;
} else {
die("bad config rule: $r\n");
}
}
}
$files{$_} = 1 for keys %cfiles;
if (!%files) {
print "$rname($target): empty filelist, skipping rpm\n";
next;
}
my $i = 0;
for (@{$res{'FILENAMES'}}) {
$files{$_} = $i if $files{$_};
$i++;
}
my %cpiodirs;
for (keys %files) {
next if $cfiles{$_} || $moves{$_};
my $fn = $_;
next unless $fn =~ s/\/[^\/]+$//;
$cpiodirs{$fn} = 1;
}
my %alldirs;
for (keys %files) {
next if $cfiles{$_};
my $fn = $_;
if ($moves{$fn}) {
$fn = $moves{$fn};
next unless $fn =~ s/\/[^\/]+$//;
$alldirs{$fn} = 1;
} else {
next unless $fn =~ s/\/[^\/]+$//;
$alldirs{"$prefix$fn"} = 1;
}
}
$alldirs{$_} = 1 for keys %symlinks;
$alldirs{$configdir} = 1 if %cfiles;
my $ad;
for $ad (keys %alldirs) {
$alldirs{$ad} = 1 while $ad =~ s/\/[^\/]+$//;
}
for (keys %files) {
next if $cfiles{$_};
my $fn = $_;
if ($moves{$fn}) {
delete $alldirs{$moves{$fn}};
} else {
delete $alldirs{"$prefix$fn"};
}
}
delete $alldirs{$_} for keys %symlinks;
$ad = $prefix;
delete $alldirs{$ad};
delete $alldirs{$ad} while $ad =~ s/\/[^\/]+$//;
delete $alldirs{$_} for @filesystem;
print "$rname($target): writing specfile...\n";
my ($fh, $specfile) = tempfile(SUFFIX => ".spec");
open(SPEC, ">&=", $fh) || die("open: $!\n");
for my $p (@preamble) {
my $pt = uc($p);
next unless $res{$pt};
my $d = $res{$pt}->[0];
$d =~ s/%/%%/g;
if ($p eq 'Name') {
print SPEC "Name: $sname\n";
next;
}
if ($p eq 'Version') {
print SPEC "Version: $sversion\n";
next;
}
if ($p eq 'Release') {
print SPEC "Release: $srelease\n";
next;
}
if ($p eq 'Disturl') {
print SPEC "%define disturl $d\n";
next;
}
print SPEC "$p: $d\n";
}
print SPEC "Source: $rpm\n";
print SPEC "NoSource: 0\n" if $res{'SOURCERPM'}->[0] =~ /\.nosrc\.rpm$/;
print SPEC "BuildRoot: %{_tmppath}/baselibs-%{name}-%{version}-build\n";
print SPEC "%define _target_cpu $targetarch\n";
print SPEC "%define __os_install_post %{nil}\n";
print SPEC "%description\nUnneeded main package. Ignore.\n\n";
print SPEC "%package -n $targetname\n";
for my $p (@preamble) {
next if $p eq 'Name' || $p eq 'Disturl';
my $pt = uc($p);
next unless $res{$pt};
my $d = $res{$pt}->[0];
$d =~ s/%/%%/g;
if ($pt eq 'VERSION' && $legacyversion) {
$d = $legacyversion;
} elsif ($pt eq 'RELEASE' && $legacyversion) {
my @bt = localtime($res{'BUILDTIME'}->[0]);
$bt[5] += 1900;
$bt[4] += 1;
$d = sprintf("%04d%02d%02d%02d%02d\n", @bt[5,4,3,2,1]);
}
print SPEC "$p: $d\n";
}
print SPEC "Autoreqprov: $autoreqprov\n";
for my $ar ([\@provides, 'provides'],
[\@prerequires, 'prereq'],
[\@requires, 'requires'],
[\@recommends, 'recommends'],
[\@supplements, 'supplements'],
[\@obsoletes, 'obsoletes'],
[\@conflicts, 'conflicts']) {
my @a = @{$ar->[0]};
my @na = ();
for (@a) {
if (substr($_, 0, 1) eq '"') {
die("bad $ar->[1] rule: $_\n") unless /^\"(.*)\"$/;
push @na, $1;
} elsif (substr($_, 0, 1) eq '-') {
my $ra = substr($_, 1);
@na = grep {!/$ra/} @na;
} else {
die("bad $ar->[1] rule: $_\n");
}
}
print SPEC ucfirst($ar->[1]).": $_\n" for @na;
}
my $cpiopre = '';
$cpiopre = './' if $res{'RPMVERSION'}->[0] !~ /^3/;
my $d = $res{'DESCRIPTION'}->[0];
$d =~ s/%/%%/g;
if ($legacyversion) {
$d = "This rpm was re-packaged from $res{'NAME'}->[0]-$res{'VERSION'}->[0]-$res{'RELEASE'}->[0]\n\n$d";
}
print SPEC "\n%description -n $targetname\n";
print SPEC "$d\n";
print SPEC "%prep\n";
print SPEC "%build\n";
print SPEC "%install\n";
print SPEC "rm -rf \$RPM_BUILD_ROOT\n";
print SPEC "mkdir \$RPM_BUILD_ROOT\n";
print SPEC "cd \$RPM_BUILD_ROOT\n";
my @cfl = grep {!$cfiles{$_} && !$moves{$_}} sort keys %files;
if (@cfl) {
if ($prefix ne '') {
print SPEC "mkdir -p \$RPM_BUILD_ROOT$prefix\n";
print SPEC "pushd \$RPM_BUILD_ROOT$prefix\n";
}
print SPEC "cat <.filelist\n";
print SPEC "$_\n" for map {$cpiopre.substr($_, 1)} @cfl;
print SPEC "EOFL\n";
print SPEC "mkdir -p \$RPM_BUILD_ROOT$prefix$_\n" for sort keys %cpiodirs;
print SPEC "rpm2cpio $rpm | cpio -i -d -v -E .filelist\n";
print SPEC "rm .filelist\n";
if (%ghosts) {
for my $fn (grep {$ghosts{$_}} @cfl) {
my $fnm = $fn;
$fnm = '.' unless $fnm =~ s/\/[^\/]+$//;
print SPEC "mkdir -p \$RPM_BUILD_ROOT$prefix$fnm\n";
print SPEC "touch \$RPM_BUILD_ROOT$prefix$fn\n";
}
}
if ($prefix ne '') {
print SPEC "popd\n";
}
}
if (%cfiles || %moves) {
print SPEC "mkdir -p .cfiles\n";
print SPEC "pushd .cfiles\n";
print SPEC "cat <.filelist\n";
print SPEC "$_\n" for map {$cpiopre.substr($_, 1)} grep {$cfiles{$_} || $moves{$_}} sort keys %files;
print SPEC "EOFL\n";
print SPEC "rpm2cpio $rpm | cpio -i -d -v -E .filelist\n";
print SPEC "popd\n";
if (%cfiles) {
print SPEC "mkdir -p \$RPM_BUILD_ROOT$configdir\n";
print SPEC "mv .cfiles$_ \$RPM_BUILD_ROOT$configdir\n" for sort keys %cfiles;
}
for my $fn (sort keys %moves) {
my $fnm = $moves{$fn};
$fnm = '.' unless $fnm =~ s/\/[^\/]+$//;
print SPEC "mkdir -p \$RPM_BUILD_ROOT$fnm\n";
print SPEC "mv .cfiles$fn \$RPM_BUILD_ROOT$moves{$fn}\n";
}
print SPEC "rm -rf .cfiles\n";
}
for my $fn (sort keys %symlinks) {
my $fnm = $fn;
$fnm = '.' unless $fnm =~ s/\/[^\/]+$//;
print SPEC "mkdir -p \$RPM_BUILD_ROOT$fnm\n";
print SPEC "ln -s $symlinks{$fn} \$RPM_BUILD_ROOT$fn\n";
}
if ($prefix ne '' && grep {/\.so.*$/} @cfl) {
@postin = () if @postin == 1 && $postin[0] =~ /^\"-p.*ldconfig/;
unshift @postin, "\"/sbin/ldconfig -r $prefix\"";
}
if (@prein) {
print SPEC "%pre -n $targetname";
print SPEC $prein[0] =~ /^\"-p/ ? " " : "\n";
for (@prein) {
die("bad prein rule: $_\n") unless /^\"(.*)\"$/;
print SPEC "$1\n";
}
}
if (@postin) {
print SPEC "%post -n $targetname";
print SPEC $postin[0] =~ /^\"-p/ ? " " : "\n";
for (@postin) {
die("bad postin rule: $_\n") unless /^\"(.*)\"$/;
print SPEC "$1\n";
}
}
if (@preun) {
print SPEC "%preun -n $targetname";
print SPEC $preun[0] =~ /^\"-p/ ? " " : "\n";
for (@preun) {
die("bad preun rule: $_\n") unless /^\"(.*)\"$/;
print SPEC "$1\n";
}
}
if (@postun) {
print SPEC "%postun -n $targetname";
print SPEC $postun[0] =~ /^\"-p/ ? " " : "\n";
for (@postun) {
die("bad postun rule: $_\n") unless /^\"(.*)\"$/;
print SPEC "$1\n";
}
}
print SPEC "\n%clean\n";
print SPEC "\nrm -rf \$RPM_BUILD_ROOT\n\n";
print SPEC "%files -n $targetname\n";
for my $file (sort keys %alldirs) {
print SPEC "%dir %attr(0755,root,root) $file\n";
}
for my $file (keys %files) {
my $fi = $files{$file};
my $fm = $res{'FILEMODES'}->[$fi];
my $fv = $res{'FILEVERIFYFLAGS'}->[$fi];
my $ff = $res{'FILEFLAGS'}->[$fi];
if (POSIX::S_ISDIR($fm)) {
print SPEC "%dir ";
}
if ($ff & ((1 << 3) | (1 << 4))) {
print SPEC "%config(missingok noreplace) ";
} elsif ($ff & (1 << 3)) {
print SPEC "%config(missingok) ";
} elsif ($ff & (1 << 4)) {
print SPEC "%config(noreplace) ";
} elsif ($ff & (1 << 0)) {
print SPEC "%config ";
}
print SPEC "%doc " if $ff & (1 << 1);
print SPEC "%ghost " if $ff & (1 << 6);
print SPEC "%license " if $ff & (1 << 7);
print SPEC "%readme " if $ff & (1 << 8);
if ($fv != 4294967295) {
print SPEC "%verify(";
if ($fv & 2147483648) {
print SPEC "not ";
$fv ^= 4294967295;
}
print SPEC "md5 " if $fv & (1 << 0);
print SPEC "size " if $fv & (1 << 1);
print SPEC "link " if $fv & (1 << 2);
print SPEC "user " if $fv & (1 << 3);
print SPEC "group " if $fv & (1 << 4);
print SPEC "mtime " if $fv & (1 << 5);
print SPEC "mode " if $fv & (1 << 6);
print SPEC "rdev " if $fv & (1 << 7);
print SPEC ") ";
}
#sigh, no POSIX::S_ISLNK ...
if (($fm & 0170000) == 0120000) {
printf SPEC "%%attr(-,%s,%s) ", $res{'FILEUSERNAME'}->[$fi], $res{'FILEGROUPNAME'}->[$fi];
} else {
printf SPEC "%%attr(%03o,%s,%s) ", $fm & 07777, $res{'FILEUSERNAME'}->[$fi], $res{'FILEGROUPNAME'}->[$fi];
}
if ($cfiles{$file}) {
my $fn = $file;
$fn =~ s/.*\///;
print SPEC "$configdir/$fn\n";
} else {
if ($moves{$file}) {
print SPEC "$moves{$file}\n";
} else {
print SPEC "$prefix$file\n";
}
}
}
for (keys %symlinks) {
printf SPEC "%%attr(-,root,root) $_\n";
}
if ($res{'CHANGELOGTEXT'}) {
print SPEC "\n%changelog -n $targetname\n";
my @ct = @{$res{'CHANGELOGTIME'}};
my @cn = @{$res{'CHANGELOGNAME'}};
my @wdays = qw{Sun Mon Tue Wed Thu Fri Sat};
my @months = qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec};
for my $cc (@{$res{'CHANGELOGTEXT'}}) {
my @lt = localtime($ct[0]);
my $cc2 = $cc;
my $cn2 = $cn[0];
$cc2 =~ s/%/%%/g;
$cn2 =~ s/%/%%/g;
printf SPEC "* %s %s %02d %04d %s\n%s\n", $wdays[$lt[6]], $months[$lt[4]], $lt[3], 1900 + $lt[5], $cn2, $cc2;
shift @ct;
shift @cn;
}
}
close(SPEC) || die("$specfile: $!\n");
print "$rname($target): running build...\n";
if (system("rpmbuild -bb $specfile".($verbose ? '' : '>/dev/null 2>&1'))) {
print "rpmbuild failed: $?\n";
print "re-running in verbose mode:\n";
system("rpmbuild -bb $specfile 2>&1");
exit(1);
}
unlink($specfile);
}
}
}
################################################################
sub handle_debs {
eval {
require Parse::DebControl;
};
if ($@){
print "mkbaselibs needs the perl module Parse::DebControl\n".
"Error. baselibs-deb.conf specified but mkbaselibs can't run\n".
"Please ensure that 'osc meta prjconf' contains the following line:\n".
" Support: libparse-debcontrol-perl\n";
return;
};
# for each deb:
# look in the config file to see if we should be doing anything
#
# Unpack the deb control data using dpkg-deb
# for each target
# Unpack the deb control data *and* file data using dpkg-deb
# process the config file for this package modifying control and moving files
# repackage the target deb
for my $deb (@_) {
# http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-binarycontrolfiles
# unpack the outer loop control file - this gives us eg: the arch
my $base = tempdir() || die("tempdir: $!\n");
system "dpkg -e $deb ${base}/DEBIAN" || die "dpkg -e failed on $deb";
my $controlParser = new Parse::DebControl;
$controlParser->DEBUG();
my $keys = $controlParser->parse_file("${base}/DEBIAN/control");
# print Dumper($keys);
# DebControl supports multiple paragraphs of control data but
# debian/control in a .deb only has one (whereas a debian/control
# in a build root contains many)
# So extract the ref to the first one.
my %control = %{@{$keys}[0]};
# Validate this is a binary deb and get the control data
my $d_name = $control{'Package'};
my $d_version = $control{'Version'};
$arch = $control{'Architecture'}; # set global $arch
# examine the
# arch targets [:] [[:]...]
# line and get a list of target_arch-es
my @targets = get_targets($arch, $config);
if (!@targets) {
print "no targets for arch $arch, skipping $d_name\n";
next; # there may be more debs to handle
}
for my $target (@targets) {
next unless parse_config($target, $d_name, $d_version);
die("targetname not set\n") unless $targetname; # set in the global_conf
$target_matched{$target} = 1;
my $baseTarget = "${base}/$target";
# Unpack a .deb to work on. We have to do this each time as we
# manipulate the unpacked files.
system "mkdir ${base}/$target";
system "dpkg -e $deb ${baseTarget}/DEBIAN" || die "dpkg -e failed on $deb";
# Note that extracting to $prefix does the clever move to /lib-x86/ or whatever
system "dpkg -x $deb ${baseTarget}/$prefix" || die "dpkg -x failed on $deb";
# Reset the control data
$keys = $controlParser->parse_file("${baseTarget}/DEBIAN/control");
%control = %{@{$keys}[0]};
# Force the architecture
$control{'Architecture'} = $targetarch;
# Currently this script does not manipulate any files
# If needed they are all unpacked in ${baseTarget}
# we don't need a dsc/spec file.. all done by just moving files around
# and running dpkg -b ${base} $NEW_DEB
#
# my $dscfile = "/usr/src/packages/DSCS/mkbaselibs$$.dsc";
print "$d_name($target): writing dscfile...\n";
# We can Use Parse::DebControl write_file to create the new control file
# just modify tags in there
# We'll use requires -> Depends:
map s/^"(.*)"$/$1/, @requires; # remove leading/trailing "s
$control{"Depends"} = @requires ? join(", ", @requires) : ""; # join array if exists or reset it to ""
map s/^"(.*)"$/$1/, @prerequires;
$control{"Pre-Depends"} = @prerequires ? join(", ", @prerequires) : "";
map s/^"(.*)"$/$1/, @provides;
$control{"Provides"} = @provides ? join(", ", @provides) : "";
map s/^"(.*)"$/$1/, @recommends;
$control{"Recommends"} = @recommends ? join(", ", @recommends) : "";
map s/^"(.*)"$/$1/, @suggests;
$control{"Suggests"} = @suggests ? join(", ", @suggests) : "";
map s/^"(.*)"$/$1/, @obsoletes;
$control{"Replaces"} = @obsoletes ? join(", ", @obsoletes) : "";
map s/^"(.*)"$/$1/, @conflicts;
$control{"Conflicts"} = @conflicts ? join(", ", @conflicts) : "";
map s/^"(.*)"$/$1/, @supplements;
$control{"Enhances"} = @supplements ? join(", ", @supplements) : "";
# Tidy up the various control files.
# the md5sums are regenerated by dpkg-deb when building
foreach my $c_file ( qw(conffiles postins postrm preinst prerm) ) {
unlink "${baseTarget}/DEBIAN/$c_file";
}
# Create them if needed
if (@prein) {
map s/^"(.*)"$/$1/, @prein; # remove leading/trailing "s
open(my $SCRIPT, ">${baseTarget}/DEBIAN/preinst");
print $SCRIPT join("\n", @prein) ;
chmod(0755, $SCRIPT);
close($SCRIPT);
}
if (@postin) {
map s/^"(.*)"$/$1/, @postin;
open(my $SCRIPT, ">${baseTarget}/DEBIAN/postinst");
print $SCRIPT join("\n", @postin) ;
chmod(0755, $SCRIPT);
close($SCRIPT);
}
if (@preun) {
map s/^"(.*)"$/$1/, @preun;
open(my $SCRIPT, ">${baseTarget}/DEBIAN/prerm");
print $SCRIPT join("\n", @preun) ;
chmod(0755, $SCRIPT);
close($SCRIPT);
}
if (@postun) {
map s/^"(.*)"$/$1/, @postun;
open(my $SCRIPT, ">${baseTarget}/DEBIAN/postrm");
print $SCRIPT join("\n", @postun) ;
chmod(0755, $SCRIPT);
close($SCRIPT);
}
# Don't forget to rename the package - or it will replace/uninstall the /-based one
$control{"Package"} = "${d_name}-${targettype}";
$controlParser->write_file("${baseTarget}/DEBIAN/control", \%control, {clobberFile => 1, addNewline=>1 } );
system "dpkg -b ${baseTarget} /usr/src/packages/DEBS/${d_name}-${targettype}_${d_version}_${targetarch}.deb" || die "dpkg -b failed on $deb";
system "rm -rf ${baseTarget}";
}
system "rm -rf ${base}";
}
}
while (@ARGV) {
if ($ARGV[0] eq '-v') {
$verbose = 1;
shift @ARGV;
} elsif ($ARGV[0] eq '-c') {
shift @ARGV;
read_config($ARGV[0]);
shift @ARGV;
} else {
last;
}
}
# args is a list of full pathnames to rpm/deb files
die("Usage: mkbaselibs [-v] [-c config] \n") unless @ARGV;
my %goodpkgs = map {$_ => 1} get_pkgnames(); # These are packages named in the config file
my @pkgs = @ARGV;
my @rpms;
my @debugrpms;
for my $rpm (@pkgs) {
my $rpmn = $rpm;
unless (-f $rpm) {
warn ("$rpm does not exist, skipping\n");
next;
}
my @rpmfiles = `rpm -qp --queryformat "[%{FILENAMES}\n]" $rpm`;
if (!@rpmfiles) {
warn ("$rpm is empty, skipping\n");
next;
}
next if $rpm =~ /\.(no)?src\.rpm$/; # ignore source rpms
next if $rpm =~ /\.spm$/;
$rpmn =~ s/.*\///; # Remove leading path info
$rpmn =~ s/-[^-]+-[^-]+\.[^\.]+\.rpm$/\.rpm/; # remove all version info
$rpmn =~ s/\.rpm$//; # remove extension
push @rpms, $rpm if $goodpkgs{$rpmn};
if ($rpmn =~ s/-debuginfo$//) {
push @debugrpms, $rpm if $goodpkgs{$rpmn};
}
}
for (@rpms) {
die("$_: need absolute path to package\n") unless /^\//;
}
my %debs_to_process = map {$_ => 1} get_debpkgnames(); # These are packages named in the config file
my @debs;
for my $deb (@pkgs) {
my $debn = $deb;
next unless $debn =~ /\.deb$/;
my @debfiles = `dpkg --contents $deb`;
if (!@debfiles) {
warn ("$deb is empty, skipping\n");
next;
}
$debn =~ s/.*\///; # Remove leading path info
$debn =~ s/_[^_]+_[^_]+\.deb$//; # remove all version info and extension
push @debs, $deb if $debs_to_process{$debn};
print "ignoring $deb as $debn not in baselibs.conf\n" if !$debs_to_process{$debn};
}
for (@debs) {
die("$_: need absolute path to package\n") unless /^\//;
}
exit 0 unless @rpms or @debs;
if (@rpms) {
@filesystem = split("\n", `rpm -ql filesystem 2>/dev/null`);
die("filesystem rpm is not installed\n") unless @filesystem;
handle_rpms(@rpms);
handle_rpms(@debugrpms);
}
if (@debs) {
handle_debs(@debs);
}
obs-build-20180831/emulator/ 0000755 0001750 0001750 00000000000 13350372713 014074 5 ustar alee alee obs-build-20180831/emulator/emulator.sh 0000755 0001750 0001750 00000002647 13350372713 016274 0 ustar alee alee #!/bin/bash
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
echo "ERROR: the emulator.sh script needs to be changed to support your emulator!"
exit 1
###
### Example for the aarch64 emulator:
###
LOG=$(mktemp)
./Foundation_v8 --image ./img-foundation.axf \
--block-device "$1" \
--network=none &> $LOG &
while test 0$(grep -c terminal_0: $LOG ) -lt 1; do
echo ".."
sleep 1
done
cat $LOG
# terminal_0: Listening for serial connection on port 5012
PORT=$(grep terminal_0: $LOG | head -n 1 | cut -d " " -f 8)
rm -f $LOG
# telnet dies when emulator is quiting
telnet 127.0.0.1 $PORT || exit 0
obs-build-20180831/build-vm-emulator 0000644 0001750 0001750 00000004744 13350372713 015545 0 ustar alee alee #
# generic emulator specific functions
#
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
vm_verify_options_emulator() {
if test -f "$BUILD_DIR/emulator/verify-options.sh"; then
. "$BUILD_DIR/emulator/verify-options.sh"
else
VM_SWAP=
fi
}
vm_startup_emulator() {
pushd "$BUILD_DIR/emulator"
if test -z "$EMULATOR_SCRIPT" ; then
EMULATOR_SCRIPT=./emulator.sh
elif test "${EMULATOR_SCRIPT:0:1}" != / ; then
EMULATOR_SCRIPT="./$EMULATOR_SCRIPT"
fi
set -- "$EMULATOR_SCRIPT" "$VM_ROOT" "$VM_SWAP"
echo "$@"
if ! "$@"; then
popd
cleanup_and_exit 3 "ERROR: The emulator returned with a failure"
fi
popd
test -n "$VM_SWAP" && return
# Emulators may not offer to use a second swap space.
# So we just mount the filesystem.
# WARNING: This is not safe against attacks.
mkdir -p $BUILD_ROOT/.build.packages
cd $BUILD_ROOT/.build.packages || cleanup_and_exit 1
mkdir -p .mount
mount $VM_ROOT -o loop .mount
if test -e .mount/.build.packages ; then
cp -a .mount/.build.packages/* .
fi
exitcode=`cat .mount/.build/_exitcode`
umount .mount
rmdir .mount
cleanup_and_exit "$exitcode"
}
vm_kill_emulator() {
if ! fuser -k -TERM "$VM_ROOT" ; then
cleanup_and_exit 1 "could not kill build in $VM_ROOT"
fi
}
vm_fixup_emulator() {
# emulator may not be able to hand over kernel parameters
ln -sf /.build/build $BUILD_ROOT/sbin/init
}
vm_attach_root_emulator() {
:
}
vm_attach_swap_emulator() {
:
}
vm_detach_root_emulator() {
:
}
vm_detach_swap_emulator() {
:
}
vm_cleanup_emulator() {
:
}
vm_sysrq_emulator() {
:
}
vm_wipe_emulator() {
:
}
obs-build-20180831/common_functions 0000755 0001750 0001750 00000011360 13350372713 015553 0 ustar alee alee #!/bin/bash
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
build_host_arch() {
: ${BUILD_HOST_ARCH:=`uname -m`}
# the linux kernel only knows armv7l, armv7hl is a userland definition
test armv7l == "$BUILD_HOST_ARCH" && BUILD_HOST_ARCH=armv7hl
BUILD_INITVM_ARCH="$BUILD_HOST_ARCH"
# avoid multiple initvm.* helpers for i586 and i686
test i686 != "$BUILD_INITVM_ARCH" || BUILD_INITVM_ARCH=i586
}
extend_build_arch() {
case $BUILD_ARCH in
aarch64) BUILD_ARCH="aarch64:aarch64_ilp32:armv8l" ;;
aarch64_ilp32) BUILD_ARCH="aarch64_ilp32:aarch64:armv8l" ;;
armv8l) BUILD_ARCH="armv8l" ;; # armv8l is aarch64 in 32bit mode. not a superset of armv7
armv7hl) BUILD_ARCH="armv7hl:armv7l:armv6hl:armv6l:armv5tel" ;;
armv7l) BUILD_ARCH="armv7l:armv6l:armv5tel" ;;
armv6hl) BUILD_ARCH="armv6hl:armv6l:armv5tel" ;;
armv6l) BUILD_ARCH="armv6l:armv5tel" ;;
armv5tel) BUILD_ARCH="armv5tel" ;;
m68k) BUILD_ARCH="m68k" ;;
mips64) BUILD_ARCH="mips64:mips" ;;
mips) BUILD_ARCH="mips" ;;
i686) BUILD_ARCH="i686:i586:i486:i386" ;;
i586) BUILD_ARCH="i586:i486:i386" ;;
i486) BUILD_ARCH="i486:i386" ;;
i386) BUILD_ARCH="i386" ;;
ia64) BUILD_ARCH="ia64" ;;
parisc64) BUILD_ARCH="hppa64:hppa" ;;
parisc) BUILD_ARCH="hppa" ;;
ppc) BUILD_ARCH="ppc" ;;
ppc64) BUILD_ARCH="ppc64:ppc" ;;
ppc64le) BUILD_ARCH="ppc64le" ;;
riscv64) BUILD_ARCH="riscv64" ;;
s390x) BUILD_ARCH="s390x:s390" ;;
s390) BUILD_ARCH="s390" ;;
sparc64v) BUILD_ARCH="sparc64v:sparc64:sparcv9v:sparcv9:sparcv8:sparc" ;;
sparc64) BUILD_ARCH="sparc64:sparcv9:sparcv8:sparc" ;;
sparcv9v) BUILD_ARCH="sparcv9v:sparcv9:sparcv8:sparc" ;;
sparcv9) BUILD_ARCH="sparcv9:sparcv8:sparc" ;;
sparcv8) BUILD_ARCH="sparcv8:sparc" ;;
sparc) BUILD_ARCH="sparc" ;;
x86_64) BUILD_ARCH="x86_64:i686:i586:i486:i386" ;;
esac
}
set_build_arch() {
build_host_arch
if test -z "$BUILD_ARCH" ; then
BUILD_ARCH="$BUILD_HOST_ARCH"
fi
extend_build_arch
if test "$BUILD_ARCH" != "${BUILD_ARCH#i686}" ; then
cpuflags=`grep ^flags /proc/cpuinfo`
cpuflags="$cpuflags "
if test "$cpuflags" = "${cpuflags/ cx8 /}" -o "$cpuflags" = "${cpuflags/ cmov /}"; then
echo "Your cpu doesn't support i686 rpms. Exit."
cleanup_and_exit 1
fi
fi
}
check_exit() {
if test -e $BUILD_ROOT/exit; then
echo "exit ..."
cleanup_and_exit 1
fi
}
check_use_emulator() {
INITVM_NAME=
# check if the extended host arch contains the build arch
local old_build_arch="$BUILD_ARCH"
local arch="${BUILD_ARCH%%:*}"
BUILD_ARCH="$BUILD_HOST_ARCH"
extend_build_arch
BUILD_ARCH=":$BUILD_ARCH:"
if test "$BUILD_ARCH" != "${BUILD_ARCH/:$arch:/}" ; then
# native supported arch, no emulator
BUILD_ARCH="$old_build_arch"
return 1
fi
BUILD_ARCH="$old_build_arch"
# to run the qemu initialization in the vm, we need to
# register it with a static program or shell script
INITVM_NAME="initvm.$BUILD_INITVM_ARCH"
if test -e "$BUILD_DIR/$INITVM_NAME" -a -e "$BUILD_DIR/qemu-reg" ; then
chmod 0755 "$BUILD_DIR/$INITVM_NAME"
return 0 # chroot build, we need to run
fi
# XXX: error?
echo "Warning: cross compile not possible due to missing static binaries. please install build-initvm package for that purpose."
echo " check that the right architecture is available for your build host, you need $INITVM_NAME for this one."
INITVM_NAME=
return 1
}
# usage:
# progress_setup LIST
# for I in $LIST; do
# progress_step LIST
# action $I
# done
# $1 name of a textual list
progress_setup() {
eval "$1__ARRAY__=(\$$1)"
eval "$1__INDEX__=1"
eval "$1__LENGTH__=\${#$1__ARRAY__[@]}"
}
# $1 name of a textual list
# $2 optional, printf format for 2 numeric arguments (current, total)
progress_step() {
local IDX=$1__INDEX__
local LEN=$1__LENGTH__
printf "${2-[%d/%d] }" $(($IDX++)) ${!LEN}
}
obs-build-20180831/createyastdeps 0000755 0001750 0001750 00000004253 13350372713 015216 0 ustar alee alee #!/usr/bin/perl -w
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
BEGIN {
unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
}
use Build ':rpm';
use Build::Susetags;
use Getopt::Long;
use File::Path qw(mkpath);
use strict;
Getopt::Long::Configure("no_ignore_case");
my $opt_zypp;
my $cachedir = "/var/cache/build";
GetOptions ("zypp=s" => \$opt_zypp, "cachedir=s" => \$cachedir) or exit(1);
for my $url (@ARGV) {
# XXX: use descrdir/datadir from content file
my $descrdir = 'suse/setup/descr';
my $datadir = 'suse';
my $dir;
my $baseurl = $url;
if ($opt_zypp) {
$dir = $opt_zypp;
} elsif ($url =~ /^(?:ftps?|https?):\/\/([^\/]*)\/?/) {
my $repoid = Digest::MD5::md5_hex($url);
$dir = "$cachedir/$repoid/";
$baseurl .= '/' unless $baseurl =~ /\/$/;
mkpath($dir);
system("$INC[0]/download", "$dir/", "${baseurl}$descrdir/packages.gz");
$descrdir = '.';
} else {
$dir = $url;
}
$dir .= '/' unless $dir =~ /\/$/;
$baseurl .= '/' unless $baseurl =~ /\/$/;
my $packages = "$dir$descrdir/packages";
$packages = "$packages.gz" if ! -e $packages && -e "$packages.gz";
Build::Susetags::parse($packages, sub {
my $xurl = $baseurl;
# multi cd support hack
$xurl =~ s/1\/$/$_[0]->{'medium'}/ if $_[0]->{'medium'};
$xurl .= "$datadir/" if $datadir;
Build::writedeps(\*STDOUT, $_[0], $xurl);
}, 'addselfprovides' => 1);
}
obs-build-20180831/debtransformzip 0000755 0001750 0001750 00000002032 13350372713 015400 0 ustar alee alee #! /bin/bash
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
if test $# -ne 2; then
exit 1
fi
zip="$1"
tar="$2"
tmp=$(mktemp -d)
unzip -q -d "$tmp" -- "$zip" || exit 1
( cd "$tmp" && tar czO * ) >"$tar" || exit 1
rm -r "$tmp"
exit 0
obs-build-20180831/order 0000755 0001750 0001750 00000005054 13350372713 013311 0 ustar alee alee #!/usr/bin/perl -w
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
BEGIN {
unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
}
use Build;
use strict;
my ($dist, $archs, $configdir, $manifest);
$configdir = ($::ENV{'BUILD_DIR'} || '/usr/lib/build') . '/configs';
while (@ARGV) {
if ($ARGV[0] eq '--dist') {
shift @ARGV;
$dist = shift @ARGV;
next;
}
if ($ARGV[0] eq '--archpath') {
shift @ARGV;
$archs = shift @ARGV;
next;
}
if ($ARGV[0] eq '--configdir') {
shift @ARGV;
$configdir = shift @ARGV;
next;
}
if (@ARGV && $ARGV[0] eq '--manifest') {
shift @ARGV;
$manifest = shift @ARGV;
next;
}
last;
}
die("usage: order [--manifest manifest] cachedir [packages...]\n") unless @ARGV;
my $cachedir = shift @ARGV;
my @p;
if ($manifest) {
if ($manifest eq '-') {
@p = ;
} else {
local *F;
open(F, '<', $manifest) || die("$manifest: $!\n");
@p = ;
close F;
}
chomp @p;
}
push @p, @ARGV;
my $config = Build::read_config_dist($dist, $archs, $configdir);
my %deps;
my %bins;
for my $p (@p) {
my $q;
for my $suf ('rpm', 'deb', 'arch') {
next unless -f "$cachedir/$p.$suf";
if (! -s "$cachedir/$p.$suf") {
$q = {'provides' => [], 'requires' => []}; # package from preinstallimage, no need to order
last;
}
$q = Build::query("$cachedir/$p.$suf", 'filelist' => 1, 'alldeps' => 1, 'addselfprovides' => 1, 'normalizedeps' => 1);
die("bad binary: $p.$suf\n") unless $q;
push @{$q->{'provides'}}, @{$q->{'filelist'}} if $suf eq 'rpm' && $q->{'filelist'};
delete $q->{'filelist'};
last;
}
die("binary not found: $p\n") unless $q;
$deps{$p} = $q;
}
Build::readdeps($config, undef, \%deps);
@p = Build::order($config, @p);
print "@p\n";
obs-build-20180831/createdirdeps 0000755 0001750 0001750 00000005732 13350372713 015017 0 ustar alee alee #!/usr/bin/perl -w
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
BEGIN {
unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
}
use Build;
use Getopt::Long;
use strict;
Getopt::Long::Configure("no_ignore_case");
my $oldfile;
GetOptions ("oldfile=s" => \$oldfile) or exit(1);
sub queryfromfilename {
my ($fn) = @_;
$fn =~ s/.*\///;
return {'name' => $1, 'arch' => $2} if $fn =~ /^(.*)-[^-]+-[^-]+\.([^\. ]+)\.rpm$/;
return {'name' => $1, 'arch' => $2} if $fn =~ /^([^_]*)_(?:[^_]*)_([^_]*)\.deb$/;
return {'name' => $1, 'arch' => $2} if $fn =~ /^(.*)-[^-]+-[^-]+-([^-]+)\.pkg\.tar\.[gx]z$/;
return undef;
}
######################################################################
my %old;
if (defined($oldfile) && open(F, '<', $oldfile)) {
while () {
chomp;
$old{$1} = $_ if /^([PRrCOI]:[^ ]+): /;
}
close F;
}
my %seen;
for my $dir (@ARGV) {
my $cmd = "find $dir -follow -type f \\( -name \"*.rpm\" -o -name \"*.deb\" -o -name \"*.pkg.tar.gz\" -o -name \"*.pkg.tar.xz\" \\) -a ! -name \"*src.rpm\" -printf '\%T@/\%s/\%i \%p\\n'";
open(F, '-|', $cmd) or next;
while () {
chomp;
next unless /^([\d\.]+\/\d+\/\d+) (.*)$/;
my $id = $1;
my $path = $2;
# newer find version add a fraction part to %T@, strip it
$id =~ s/^(\d+)\.\d+/$1/;
next if $path =~ /\.(?:patch|delta)\.rpm$/; # not good for building...
if (%old) {
my $q = queryfromfilename($path);
if ($q && defined($q->{'name'}) && defined($q->{'arch'})) {
my $idx = "$q->{'name'}.$q->{'arch'}-$id";
if ($old{"I:$idx"} && $old{"P:$idx"}) {
# reuse old data
next if $seen{$idx};
$seen{$idx} = 1;
print "F:$idx: $path\n";
for (qw{P R C O I r s}) {
print $old{"$_:$idx"}."\n" if $old{"$_:$idx"};
}
next;
}
}
}
my $q = Build::query($path, 'addselfprovides' => 1, 'conflicts' => 1, 'evra' => 1, 'buildtime' => 1, 'weakdeps' => 1);
next unless $q && defined($q->{'name'}) && defined($q->{'arch'}) && defined($q->{'version'});
my $idx = "$q->{'name'}.$q->{'arch'}-$id";
next if $seen{$idx};
$seen{$idx} = 1;
$q->{'id'} = $id;
$q->{'location'} = $path;
Build::writedeps(\*STDOUT, $q);
}
close F;
}
obs-build-20180831/build-vm 0000644 0001750 0001750 00000077517 13350372713 013727 0 ustar alee alee #
# VM specific functions for the build script
#
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
# defaults for vm_img_mkfs
vm_img_mkfs_ext4_options='-O ^has_journal,^huge_file,^resize_inode,sparse_super'
vm_img_mkfs_ext4_extra='-E lazy_itable_init,discard'
vm_img_mkfs_ext4="mkfs.ext4 -m 0 -q -F $vm_img_mkfs_ext4_options"
vm_img_tunefs_ext4='tune2fs -c 0'
vm_img_mkfs_ext3='mkfs.ext3 -m 0 -q -F'
vm_img_tunefs_ext3='tune2fs -c 0 -o journal_data_writeback'
vm_img_mkfs_ext2='mkfs.ext2 -m 0 -q -F'
vm_img_tunefs_ext2='tune2fs -c 0'
vm_img_mkfs_reiserfs='mkreiserfs -q -f'
vm_img_mkfs_btrfs='mkfs.btrfs'
vm_img_mkfs_xfs='mkfs.xfs -f'
# ignore not backward compatible ext fs options like metadata_csum
# Only protecting nonroot from root inside guest -> but anyone can be root inside guest
# so disabling spectre/meltdown mitigations doesn't hurt security and gains performance
vm_linux_kernel_parameter="ext4.allow_unsupported=1 kpti=off pti=off spectre_v2=off"
# guest visible devices
VM_ROOTDEV=/dev/hda1
VM_SWAPDEV=/dev/hda2
VM_TYPE=
VM_ROOT=
VM_SWAP=
VM_ROOT_TYPE=
VM_SWAP_TYPE=
VM_KERNEL=
VM_INITRD=
VM_WORKER=
VM_SERVER=
VM_MEMSIZE=
VM_NETOPT=()
VM_NETDEVOPT=()
VM_DEVICEOPT=()
VM_TELNET=
VM_CONSOLE_INPUT=
VM_USER=
VMDISK_ROOTSIZE=4096
VMDISK_SWAPSIZE=1024
VMDISK_FILESYSTEM=
VMDISK_MOUNT_OPTIONS=__default
VMDISK_CLEAN=
VM_HOSTNAME=
# zvm specific?
VM_WORKER_NO=
# kvm specific?
HUGETLBFSPATH=
VM_CUSTOMOPT=
# emulator specific?
EMULATOR_SCRIPT=
# openstack specific
VM_OPENSTACK_FLAVOR=
for i in ec2 emulator kvm lxc openstack qemu uml xen zvm docker pvm; do
. "$BUILD_DIR/build-vm-$i"
done
VM_WATCHDOG=
VM_WATCHDOG_PID=
# the following functions just call the corresponding vm versions
vm_verify_options() {
vm_verify_options_$VM_TYPE "$@"
}
vm_attach_root() {
vm_attach_root_$VM_TYPE "$@"
}
vm_attach_swap() {
vm_attach_swap_$VM_TYPE "$@"
}
vm_detach_root() {
vm_detach_root_$VM_TYPE "$@"
}
vm_detach_swap() {
vm_detach_swap_$VM_TYPE "$@"
}
vm_fixup() {
vm_fixup_$VM_TYPE "$@"
}
vm_startup() {
vm_startup_$VM_TYPE "$@"
}
vm_sysrq() {
vm_sysrq_$VM_TYPE "$@"
}
vm_kill() {
vm_kill_$VM_TYPE "$@"
}
vm_cleanup() {
kill_watchdog
vm_cleanup_$VM_TYPE "$@"
}
vm_parse_options() {
case ${PARAM/#--/-} in
-vm-emulator-script|-emulator-script)
needarg
EMULATOR_SCRIPT="$ARG"
shift
;;
-xen|-kvm|-uml|-qemu|-emulator)
VM_TYPE=${PARAM##*-}
test -z "$VM_ROOT" && VM_ROOT=1
if test -n "$ARG" ; then
VM_ROOT="$ARG"
shift
fi
;;
-zvm|-lxc)
VM_TYPE=${PARAM##*-}
shift
;;
-vm-type)
needarg
VM_TYPE="$ARG"
case "$VM_TYPE" in
lxc|docker) ;;
ec2|xen|kvm|uml|qemu|emulator|openstack|zvm|pvm)
test -z "$VM_ROOT" && VM_ROOT=1
;;
none|chroot) VM_TYPE= ;;
*)
cleanup_and_exit 1 "VM '$VM_TYPE' is not supported"
;;
esac
shift
;;
-vm-worker)
needarg
VM_WORKER="$ARG"
shift
;;
-vm-worker-nr|-vm-worker-no)
needarg
VM_WORKER_NO="$ARG"
shift
;;
-vm-server|-vm-region)
needarg
VM_SERVER="$ARG"
shift
;;
-vm-disk)
needarg
VM_ROOT="$ARG"
shift
;;
-vm-swap|-xenswap|-swap)
needarg
VM_SWAP="$ARG"
shift
;;
-vm-memory|-xenmemory|-memory)
needarg
VM_MEMSIZE="$ARG"
shift
;;
-vm-kernel)
needarg
VM_KERNEL="$ARG"
shift
;;
-vm-initrd)
needarg
VM_INITRD="$ARG"
shift
;;
-vm-disk-size|-vmdisk-rootsize)
needarg
VMDISK_ROOTSIZE="$ARG"
shift
;;
-vm-swap-size|-vmdisk-swapsize)
needarg
VMDISK_SWAPSIZE="$ARG"
shift
;;
-vm-disk-filesystem|-vmdisk-filesystem)
needarg
VMDISK_FILESYSTEM="$ARG"
shift
;;
-vm-disk-mount-options|-vmdisk-mount-options)
needarg
VMDISK_MOUNT_OPTIONS="$ARG"
# silly code for compat with old bs_worker versions...
if test "$1" != "----noarg=$PARAM" -a "$ARG" != "${ARG#\"}" -a "$ARG" != "${ARG%\"}" ; then
VMDISK_MOUNT_OPTIONS="${VMDISK_MOUNT_OPTIONS#\"}"
VMDISK_MOUNT_OPTIONS="${VMDISK_MOUNT_OPTIONS%\"}"
fi
shift
;;
-vm-disk-clean|-vmdisk-clean)
# delete old root/swap to get rid of the old blocks
VMDISK_CLEAN=true
;;
-vm-hugetlbfs|-hugetlbfs)
needarg
HUGETLBFSPATH="$ARG"
shift
;;
-vm-watchdog)
VM_WATCHDOG=true
;;
-vm-user)
needarg
VM_USER="$ARG"
shift
;;
-vm-enable-console)
VM_CONSOLE_INPUT=true
;;
-vm-telnet)
needarg
VM_TELNET="$ARG"
shift
;;
-vm-net)
needarg
VM_NETOPT=("${VM_NETOPT[@]}" "$ARG")
shift
;;
-vm-netdev)
needarg
VM_NETDEVOPT=("${VM_NETDEVOPT[@]}" "$ARG")
shift
;;
-vm-device)
needarg
VM_DEVICEOPT=("${VM_DEVICEOPT[@]}" "$ARG")
shift
;;
-vm-custom-opt)
needarg
VM_CUSTOMOPT="$ARG"
shift
;;
-openstack-flavor)
needarg
VM_OPENSTACK_FLAVOR="$ARG"
shift
;;
-*)
return 1
;;
esac
nextargs=("$@")
return 0
}
vm_set_buildstatus() {
if test -n "$VM_ROOT" -a -n "$VM_SWAP" -a "$VM_SWAP_TYPE" != unattached -a -e "$VM_SWAP" ; then
echo -n "BUILDSTATUS$1" >"$VM_SWAP"
fi
}
#
# shutdown the system from inside the VM
#
vm_shutdown() {
test -n "$VM_WATCHDOG" && echo "### VM INTERACTION START ###"
cd /
test -n "$1" || set 1
if test -n "$VM_SWAP" -a -e "$VM_SWAP" ; then
swapoff "$VM_SWAP" 2>/dev/null
echo -n "BUILDSTATUS$1" >"$VM_SWAP"
fi
exec >&0 2>&0 # so that the logging tee finishes
sleep 1 # wait till tee terminates
test "$VM_TYPE" = lxc -o "$VM_TYPE" = docker && exit $1
kill -9 -1 # goodbye cruel world
if ! test -x /sbin/halt ; then
test -e /proc/sysrq-trigger || mount -n -tproc none /proc
sync
sleep 2 # like halt does
if test -e /proc/sysrq-trigger; then
echo o > /proc/sysrq-trigger
sleep 5 # wait for sysrq to take effect
else
echo "Warning: VM doesn't support sysrq and /sbin/halt not installed"
fi
else
sync # halt from systemd is not syncing anymore.
halt -f -p
fi
echo "Warning: clean shut down of the VM didn't work"
exit $1 # init died...
}
vm_img_create() {
local img="$1"
local size="$2"
if test -e "${img}" ; then
local origsize=$(cat "${img}.size" 2> /dev/null)
if test -z "$origsize" -o "$origsize" != "$size" ; then
echo "Resizing $img (${size}M)"
fi
else
echo "Creating $img (${size}M)"
rm -f "${img}.size"
fi
mkdir -p "${img%/*}" || cleanup_and_exit 3
# truncate file to the desired size
dd if=/dev/zero of="$img" bs=1M count=0 seek="$size" || cleanup_and_exit 3
echo "$size" > "${img}.size"
# allocate blocks
if type -p fallocate > /dev/null ; then
fallocate -p -l "${size}M" "$img" 2> /dev/null
errout=$( fallocate -l "${size}M" "$img" 2>&1 )
if test $? != 0; then
echo $errout
if test "${errout/Operation not supported/}" = "$errout"; then
# Do not fail on not support file systems, eg ext2 or ext3
cleanup_and_exit 3
fi
fi
fi
}
vm_img_wipe() {
vm_wipe_$VM_TYPE "$@"
if test -n "$VM_ROOT" -a "$VM_ROOT_TYPE" = file ; then
rm -f "$VM_ROOT"
fi
if test -n "$VM_SWAP" -a "$VM_SWAP_TYPE" = file ; then
rm -f "$VM_SWAP"
fi
}
vm_img_mkfs() {
local fs="$1"
local img="$2"
local mkfs tunefs
eval "mkfs=\"\$vm_img_mkfs_${fs}\""
eval "mkfs_exta_options=\"\$vm_img_mkfs_${fs}_extra\""
eval "tunefs=\"\$vm_img_tunefs_${fs}\""
local labelopt=
test "$VM_ROOTDEV" != "${VM_ROOTDEV#LABEL=}" && labelopt="-L ${VM_ROOTDEV#LABEL=}"
if test -z "$mkfs"; then
cleanup_and_exit 3 "filesystem \"$fs\" is not supported"
fi
echo "Creating $fs filesystem on $img"
export MKE2FS_SYNC=0
if ! $mkfs $labelopt $mkfs_exta_options "$img" ; then
if test -z "$mkfs_exta_options" ; then
cleanup_and_exit 3
else
echo "Filesystem creation failed, trying again without extra options..."
$mkfs $labelopt "$img" || cleanup_and_exit 3
fi
fi
if test -n "$tunefs" ; then
$tunefs "$img" || cleanup_and_exit 3
fi
}
background_monitor_process() {
max_disk=0
max_mem=0
while sleep 5; do
test -e /.build/_statistics.exit && exit 0
# memory usage
if test -e /proc/meminfo ; then
memtotal=0
while read key value unit; do
case $key in
MemTotal:|SwapTotal:) memtotal=$(( $memtotal + $value )) ;;
MemFree:|SwapFree:|SwapCached:|Cached:|Buffers:) memtotal=$(( $memtotal - $value )) ;;
esac
done < /proc/meminfo
if test ${memtotal} -gt $max_mem ; then
max_mem="${memtotal}"
echo -n $(( $max_mem / 1024 )) > /.build/_statistics.memory.new && mv /.build/_statistics.memory.new /.build/_statistics.memory
fi
fi
# disk storage usage
if type -p df >& /dev/null; then
c=(`df -m / 2>/dev/null | tail -n 1`)
if test ${c[2]} -gt $max_disk ; then
max_disk="${c[2]}"
echo -n $max_disk > /.build/_statistics.df.new && mv /.build/_statistics.df.new /.build/_statistics.df
fi
fi
done
}
background_watchdog() {
WATCHDOG_START=
WATCHDOG_TIMEOUT=300
BUILD_OPTIONS_PARSED=
while sleep 5 ; do
WATCH=$(grep -a "### VM INTERACTION" "$LOGFILE" | tr '\0' a | tail -n 1)
case $WATCH in
*VM\ INTERACTION\ START*) test -n "$WATCHDOG_START" || WATCHDOG_START=`date +%s` ;;
*VM\ INTERACTION\ END*) WATCHDOG_START= ;;
esac
if test -n "$WATCHDOG_START" ; then
NOW=`date +%s`
ELAPSED=$((NOW-WATCHDOG_START))
if test $ELAPSED -gt $WATCHDOG_TIMEOUT ; then
# kill the VM
echo "### WATCHDOG TRIGGERED, KILLING VM ###"
vm_kill
exit 0
fi
fi
done
}
start_watchdog() {
local wf=$(mktemp)
( background_watchdog & echo $! > "$wf" )
read VM_WATCHDOG_PID < "$wf"
rm -f "$wf"
}
kill_watchdog() {
test -n "$VM_WATCHDOG_PID" && kill "$VM_WATCHDOG_PID"
VM_WATCHDOG_PID=
}
vm_set_personality_syscall() {
local archname
archname=`perl -V:archname 2>/dev/null`
archname="${archname#archname=?}"
case "$archname" in
x86_64*) PERSONALITY_SYSCALL=135 ;;
alpha*) PERSONALITY_SYSCALL=324 ;;
sparc*) PERSONALITY_SYSCALL=191 ;;
ia64*) PERSONALITY_SYSCALL=1140 ;;
i?86*|ppc*|aarch64*|arm*|sh4|cris|m68k*|s390*|unicore32|microblaze|riscv*) PERSONALITY_SYSCALL=136 ;;
*) cleanup_and_exit 1 "Unknown architecture personality: '$archname'" ;;
esac
}
# used before calling kvm or xen
linux64() {
perl -e 'syscall('$PERSONALITY_SYSCALL', 0); exec(@ARGV) || die("$ARGV[0]: $!\n")' "$@"
}
vm_start_statistics() {
if test "$DO_STATISTICS" = 1 ; then
rm -f /.build/_statistics.exit
( background_monitor_process & )
fi
}
vm_exit_statistics() {
if test "$DO_STATISTICS" = 1 ; then
rm -f /.build/_statistics.exit
fi
}
vm_detect_2nd_stage() {
if test ! -e /.build/build.data -o -n "$BUILD_IGNORE_2ND_STAGE" ; then
return 1
fi
. /.build/build.data
if test -z "$VM_TYPE" ; then
return 1
fi
BUILD_OPTIONS_PARSED=true
if test $$ -eq 1 || test $$ -eq 2 ; then
# ignore special init signals if we're init
# we're using ' ' instead of '' so that the signal handlers
# are reset in the child processes
trap ' ' HUP TERM
$0 "$@"
cleanup_and_exit $?
fi
test -n "$VM_WATCHDOG" -a -z "$PERSONALITY_SET" && echo "### VM INTERACTION END ###"
echo "2nd stage started in virtual machine"
# fedora packages sometimes do not have the needed links
ldconfig
BUILD_ROOT=/
BUILD_DIR=/.build
echo "machine type: `uname -m`"
echo "Linux version: `uname -rv`"
echo "Increasing log level from now on..."
echo 4 > /proc/sysrq-trigger
if test "$PERSONALITY" != 0 -a -z "$PERSONALITY_SET" ; then
export PERSONALITY_SET=true
echo "switching personality to $PERSONALITY..."
# this is 32bit perl/glibc, thus the 32bit syscall number
exec perl -e 'syscall(136, '$PERSONALITY') == -1 && warn("personality: $!\n");exec "/.build/build" || die("/.build/build: $!\n")'
fi
RUNNING_IN_VM=true
test -e /proc/version || mount -orw -n -tproc none /proc
if test "$VM_TYPE" != lxc -a "$VM_TYPE" != docker ; then
mount -n ${VMDISK_MOUNT_OPTIONS},remount,rw /
fi
umount /run >/dev/null 2>&1
# mount /sys
if ! test -e /sys/block; then
mkdir -p /sys
mount -orw -n -tsysfs sysfs /sys
# Docker already has sysfs mounted ro elsewhere,
# need to remount rw explicitly.
mount -o remount,rw sysfs /sys
fi
# qemu inside of xen does not work, check again with kvm later before enabling this
# if test -e /dev/kqemu ; then
# # allow abuild user to run qemu
# chmod 0666 /dev/kqemu
# fi
test -d /dev/shm || rm -f /dev/shm
mkdir -p /dev/pts
mkdir -p /dev/shm
mount -n -tdevpts -omode=0620,gid=5 none /dev/pts
mount -n -ttmpfs none /dev/shm
if test -n "$VM_SWAP" ; then
if test "$VM_SWAP" != "${VM_SWAP#LABEL=}" ; then
i=$(blkid -l -o device -t "$VM_SWAP")
if test "$i" = "${i#/}" ; then
cleanup_and_exit 1 "could not find swap device with $VM_SWAP"
fi
echo "resolved swap device $VM_SWAP to $i"
VM_SWAP=$i
fi
for i in 1 2 3 4 5 6 7 8 9 10 ; do
test -e "$VM_SWAP" && break
test $i = 1 && echo "waiting for $VM_SWAP to appear"
echo -n .
sleep 1
done
test $i = 1 || echo
# recreate the swap device manually if it didn't exist for some
# reason, hardcoded to hda2 atm
if ! test -b "$VM_SWAP" ; then
rm -f "$VM_SWAP"
umask 027
mknod "$VM_SWAP" b 3 2
umask 022
fi
# Do not rely on external system writing the signature, it might differ...
mkswap "$VM_SWAP"
swapon -v "$VM_SWAP" || exit 1
fi
HOST="$VM_HOSTNAME"
# repair dracut damage, see bsc#922676
test -L /var/run -a ! -e /var/run && rm -f /var/run
test -L /var/lock -a ! -e /var/lock && rm -f /var/lock
# start a process monitoring max filesystem usage during build
vm_start_statistics
if test ! -e /dev/.udev ; then
echo "WARNING: udev not running, creating extra device nodes"
test -e /dev/fd || ln -sf /proc/self/fd /dev/fd
test -e /etc/mtab || ln -sf /proc/mounts /etc/mtab
fi
# set date to build start on broken systems (now < build start)
if test $(date '+%s') -lt $(date -r /.build/.date '+%s') ; then
echo -n "WARNING: system has a broken clock, setting it to a newer time: "
date -s `cat /.build/.date`
fi
# Enable Core dump generation
mkdir -p "$BUILD_ROOT/.build/cores"
echo "/.build/cores/%p" > /proc/sys/kernel/core_pattern
return 0
}
vm_set_filesystem_type() {
vmfstype=""
if test -n "$BUILD_DIST" ; then
# testing for build specific filesystem, which are more important then worker defaults
vmfstype=`queryconfig --dist "$BUILD_DIST" --configdir "$CONFIG_DIR" --archpath "$BUILD_ARCH" buildflags vmfstype`
fi
test -n "$vmfstype" && VMDISK_FILESYSTEM="$vmfstype"
# use either commandline specified fs or ext3 as fallback
test -n "$VMDISK_FILESYSTEM" || VMDISK_FILESYSTEM=ext3
}
vm_set_mount_options() {
if test "$VMDISK_MOUNT_OPTIONS" = __default; then
if test "$VMDISK_FILESYSTEM" = reiserfs ; then
VMDISK_MOUNT_OPTIONS='-o data=writeback,commit=150,noatime'
elif test "$VMDISK_FILESYSTEM" = btrfs ; then
VMDISK_MOUNT_OPTIONS='-o nobarrier,noatime'
elif test "$VMDISK_FILESYSTEM" = "ext4" ; then
VMDISK_MOUNT_OPTIONS='-o noatime'
elif test "$VMDISK_FILESYSTEM" = "ext3" ; then
VMDISK_MOUNT_OPTIONS='-o data=writeback,nobarrier,commit=150,noatime'
elif test "$VMDISK_FILESYSTEM" = "ext2" ; then
VMDISK_MOUNT_OPTIONS='-o noacl,noatime'
elif test "$VMDISK_FILESYSTEM" = "xfs" ; then
VMDISK_MOUNT_OPTIONS='-o noatime'
else
VMDISK_MOUNT_OPTIONS='-o noatime'
fi
fi
}
vm_set_defaults() {
# setup root/swap defaults and type, called after option verification
if test "$VM_ROOT" = 1 ; then
VM_ROOT="$BUILD_ROOT.img"
if test -z "$VM_SWAP" -a "$VM_TYPE" != emulator ; then
VM_SWAP="$BUILD_ROOT.swap"
fi
fi
if test -n "$VM_ROOT" -a -z "$VM_ROOT_TYPE" ; then
VM_ROOT_TYPE=file
test -b "$VM_ROOT" && VM_ROOT_TYPE=device
fi
if test -n "$VM_SWAP" -a -z "$VM_SWAP_TYPE" ; then
VM_SWAP_TYPE=file
test -b "$VM_SWAP" && VM_SWAP_TYPE=device
fi
}
#
# create file system and swap space, mount file system to $BUILD_ROOT
#
vm_setup() {
vm_set_filesystem_type
vm_set_mount_options
echo "VM_ROOT: $VM_ROOT, VM_SWAP: $VM_SWAP"
vm_attach_root
# this should not be needed, but sometimes a xen instance got lost
test "$VM_TYPE" = xen && vm_purge_xen
if test -n "$VMDISK_CLEAN" ; then
# delete old root/swap to get rid of the old blocks
if test -n "$VM_ROOT" -a "$VM_ROOT_TYPE" = file -a -f "$VM_ROOT" ; then
echo "Deleting old $VM_ROOT"
rm -f "$VM_ROOT"
fi
if test -n "$VM_SWAP" -a "$VM_SWAP_TYPE" = file -a -f "$VM_SWAP" ; then
echo "Deleting old $VM_SWAP"
rm -f "$VM_SWAP"
fi
fi
if test "$VM_ROOT_TYPE" = file ; then
if test -n "$CLEAN_BUILD" ; then
vm_img_create "$VM_ROOT" "$VMDISK_ROOTSIZE"
else
local origrootsize
test -e "$VM_ROOT" -a -e "${VM_ROOT}.size" && origrootsize=$(cat "${VM_ROOT}.size" 2>/dev/null)
if test -z "$origrootsize" -o "$origrootsize" != "$VMDISK_ROOTSIZE" ; then
# the size has changed, re-create file system
vm_img_create "$VM_ROOT" "$VMDISK_ROOTSIZE"
vm_img_mkfs "$VMDISK_FILESYSTEM" "$VM_ROOT" || cleanup_and_exit 3
fi
fi
fi
if test -n "$VM_SWAP" -a "$VM_SWAP_TYPE" = file ; then
vm_img_create "$VM_SWAP" "$VMDISK_SWAPSIZE"
fi
if test ! -e "$VM_ROOT" ; then
cleanup_and_exit 3 "you need to create $VM_ROOT first"
fi
if test -n "$CLEAN_BUILD" ; then
vm_img_mkfs "$VMDISK_FILESYSTEM" "$VM_ROOT" || cleanup_and_exit 3
fi
# now mount root/swap
mkdir_build_root
if test -w /root ; then
if test -b $VM_ROOT ; then
# mount device directly
mount $VMDISK_MOUNT_OPTIONS $VM_ROOT $BUILD_ROOT || cleanup_and_exit 3
else
mount ${VMDISK_MOUNT_OPTIONS},loop $VM_ROOT $BUILD_ROOT || cleanup_and_exit 3
fi
else
if ! mount $BUILD_ROOT; then
echo "mounting the build root failed. An fstab entry is probably missing or incorrect."
echo "/etc/fstab should contain an entry like this:"
echo "$VM_ROOT $BUILD_ROOT auto noauto,user,loop 0 0"
cleanup_and_exit 3
fi
fi
if test -n "$VM_SWAP" ; then
vm_attach_swap
dd if=/dev/zero of="$VM_SWAP" bs=1024 count=1 conv=notrunc 2>/dev/null
if test "$VM_SWAPDEV" != "${VM_SWAPDEV#LABEL=}"; then
# call mkswap to set a label
mkswap -L "${VM_SWAPDEV#LABEL=}" "$VM_SWAP"
fi
vm_detach_swap
# mkswap happens inside of the vm
fi
}
vm_update_hostarch() {
local kernel="$vm_kernel"
local hostarchfile
local newhostarch
if test -z "$VM_KERNEL" -a -e "$BUILD_ROOT/.build.kernel.$VM_TYPE" ; then
kernel="$BUILD_ROOT/.build.kernel.$VM_TYPE"
hostarchfile="$BUILD_ROOT/.build.hostarch.$VM_TYPE"
elif test -n "$kernel" -a -e "$kernel" -a -e "$kernel.hostarch" ; then
hostarchfile="$kernel.hostarch"
fi
if test -n "$hostarchfile" -a -e "$hostarchfile"; then
newhostarch=`cat "$hostarchfile"`
elif test -n "$kernel" -a -e "$kernel" ; then
case `objdump -f "$kernel" | sed -ne 's/.*file format //p'` in
elf64-powerpcle) newhostarch=ppc64le ;;
elf64-powerpc) newhostarch=ppc64 ;;
esac
fi
if test -n "$newhostarch" -a "$newhostarch" != "$BUILD_HOST_ARCH" ; then
echo "setting hostarch to $newhostarch"
BUILD_HOST_ARCH="$newhostarch"
# update BUILD_INITVM_ARCH
build_host_arch
fi
}
#
# prepare for vm startup
#
vm_first_stage() {
vm_set_personality_syscall
rm -rf "$BUILD_ROOT/.build"
mkdir -p "$BUILD_ROOT/.build"
TIME_PREINSTALL=
if test "$DO_INIT" = true ; then
# do first stage of init_buildsystem
rm -f $BUILD_ROOT/.build.success
set -- init_buildsystem --configdir "$CONFIG_DIR" --cachedir "$CACHE_DIR" --prepare "${initbuildsysstuff[@]}" "${definesnstuff[@]}" "${repos[@]}" $CLEAN_BUILD $USEUSEDFORBUILD $RPMLIST "$MYSRCDIR/$RECIPEFILE" $ADDITIONAL_PACKS
echo "$* ..."
start_time=`date +%s`
"$@" || cleanup_and_exit 1
check_exit
TIME_PREINSTALL=$(( `date +%s` - $start_time ))
unset start_time
if test ! -w /root ; then
# remove setuid bit if files belong to user to make e.g. mount work
find $BUILD_ROOT/{bin,sbin,usr/bin,usr/sbin} -type f -uid $UID -perm /4000 -print0 | xargs -0 --no-run-if-empty chmod -s
fi
copy_oldpackages
fi
# start up VM, rerun ourself
cp -a $BUILD_DIR/. $BUILD_ROOT/.build
if ! test "$MYSRCDIR" = $BUILD_ROOT/.build-srcdir ; then
rm -rf "$BUILD_ROOT/.build-srcdir"
mkdir "$BUILD_ROOT/.build-srcdir"
if test "$BUILDTYPE" = kiwi -o "$BUILDTYPE" = docker -o "$BUILDTYPE" = fissile -o "$BUILDTYPE" = podman ; then
cp -pRL "$MYSRCDIR"/* $BUILD_ROOT/.build-srcdir
else
cp -p "$MYSRCDIR"/* $BUILD_ROOT/.build-srcdir
fi
MYSRCDIR=$BUILD_ROOT/.build-srcdir
else
# cwd is at $BUILD_ROOT/.build-srcdir which we want to
# umount later so step aside
cd "$SRCDIR"
fi
# do vm specific fixups
vm_fixup
# update the hostarch
if test -n "$VM_ROOT" ; then
vm_update_hostarch
fi
# the watchdog needs a log file
test -n "$LOGFILE" || VM_WATCHDOG=
# put our config into .build/build.data
Q="'\''"
echo "RECIPEFILE='${RECIPEFILE//"'"/$Q}'" > $BUILD_ROOT/.build/build.data
echo "BUILD_JOBS='${BUILD_JOBS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "BUILD_ARCH='${BUILD_ARCH//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "BUILD_RPMS='${BUILD_RPMS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
case $BUILD_DIST in
*/*)
cp $BUILD_DIST $BUILD_ROOT/.build/build.dist
BUILD_DIST=/.build/build.dist
;;
esac
echo "BUILD_DIST='${BUILD_DIST//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "RELEASE='${RELEASE//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "BUILD_DEBUG='${BUILD_DEBUG//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "SIGNDUMMY='${SIGNDUMMY//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "DO_LINT='${DO_LINT//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "DO_CHECKS='${DO_CHECKS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "NOROOTFORBUILD='${NOROOTFORBUILD//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "CREATE_BASELIBS='$CREATE_BASELIBS'" >> $BUILD_ROOT/.build/build.data
echo "REASON='${REASON//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "CHANGELOG='${CHANGELOG//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "INCARNATION='${INCARNATION//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "DISTURL='${DISTURL//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "DO_INIT='${DO_INIT//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "DO_INIT_TOPDIR='${DO_INIT_TOPDIR//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "KIWI_PARAMETERS='${KIWI_PARAMETERS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "VM_TELNET='${VM_TELNET//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
echo "VM_CONSOLE_INPUT='${VM_CONSOLE_INPUT//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
test -n "$VM_SWAP" && echo "VM_SWAP='${VM_SWAPDEV//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
test -n "$VMDISK_MOUNT_OPTIONS" && echo "VMDISK_MOUNT_OPTIONS='${VMDISK_MOUNT_OPTIONS//"'"/$Q}'" >> $BUILD_ROOT/.build/build.data
PERSONALITY=0
test -n "$PERSONALITY_SYSCALL" && PERSONALITY=`perl -e 'print syscall('$PERSONALITY_SYSCALL', 0)."\n"'`
test "$PERSONALITY" = -1 && PERSONALITY=0 # syscall failed?
case $(uname -m) in
ppc|ppcle|s390) PERSONALITY=8 ;; # ppc/s390 kernel never tells us if a 32bit personality is active, assume we run on 64bit
aarch64) test "$BUILD_ARCH" != "${BUILD_ARCH#armv[567]}" && PERSONALITY=8 ;; # workaround, to be removed
esac
test "$VM_TYPE" = lxc -o "$VM_TYPE" = docker && PERSONALITY=0
echo "PERSONALITY='$PERSONALITY'" >> $BUILD_ROOT/.build/build.data
echo "VM_HOSTNAME='$HOST'" >> $BUILD_ROOT/.build/build.data
echo -n "definesnstuff=(" >> $BUILD_ROOT/.build/build.data
shellquote "${definesnstuff[@]}" >> $BUILD_ROOT/.build/build.data
echo ")" >> $BUILD_ROOT/.build/build.data
echo -n "repos=(" >> $BUILD_ROOT/.build/build.data
shellquote "${repos[@]}" >> $BUILD_ROOT/.build/build.data
echo ")" >> $BUILD_ROOT/.build/build.data
echo "VM_TYPE='$VM_TYPE'" >> $BUILD_ROOT/.build/build.data
echo "RUN_SHELL='$RUN_SHELL'" >> $BUILD_ROOT/.build/build.data
echo "DO_STATISTICS='$DO_STATISTICS'" >> $BUILD_ROOT/.build/build.data
echo "TIME_PREINSTALL='$TIME_PREINSTALL'" >> $BUILD_ROOT/.build/build.data
echo "VM_WATCHDOG='$VM_WATCHDOG'" >> $BUILD_ROOT/.build/build.data
echo "BUILDENGINE='$BUILDENGINE'" >> $BUILD_ROOT/.build/build.data
echo "CCACHE='$CCACHE'" >> $BUILD_ROOT/.build/build.data
echo "ABUILD_TARGET='$ABUILD_TARGET'" >> $BUILD_ROOT/.build/build.data
echo "BUILD_FLAVOR='$BUILD_FLAVOR'" >> $BUILD_ROOT/.build/build.data
echo "OBS_PACKAGE='$OBS_PACKAGE'" >> $BUILD_ROOT/.build/build.data
# fallback time for broken hosts
date '+@%s' > $BUILD_ROOT/.build/.date
# we're done with the root file system, unmount
umount -n $BUILD_ROOT/proc/sys/fs/binfmt_misc 2> /dev/null || true
umount -n $BUILD_ROOT/proc 2> /dev/null || true
umount -n $BUILD_ROOT/dev/pts 2> /dev/null || true
umount -n $BUILD_ROOT/dev/shm 2> /dev/null || true
umount -n $BUILD_ROOT/mnt 2> /dev/null || true
vm_init_script="/.build/build"
if check_use_emulator ; then
vm_init_script="/.build/$INITVM_NAME"
fi
if test -n "$VM_ROOT" ; then
# copy out kernel & initrd (if they exist) during unmounting VM image
KERNEL_TEMP_DIR=
if test -z "$VM_KERNEL" -a -e "$BUILD_ROOT/.build.kernel.$VM_TYPE" ; then
KERNEL_TEMP_DIR=`mktemp -d`
cp "$BUILD_ROOT/.build.kernel.$VM_TYPE" "$KERNEL_TEMP_DIR/kernel"
if test -e "$BUILD_ROOT/.build.initrd.$VM_TYPE" ; then
cp "$BUILD_ROOT/.build.initrd.$VM_TYPE" "$KERNEL_TEMP_DIR/initrd"
fi
fi
check_exit
# needs to work otherwise we have a corrupted file system
if ! umount $BUILD_ROOT; then
rm -rf "$KERNEL_TEMP_DIR"
cleanup_and_exit 3
fi
# copy back the kernel and set it for VM
if test -n "$KERNEL_TEMP_DIR" ; then
mkdir -p "$BUILD_ROOT/boot"
mv "$KERNEL_TEMP_DIR/kernel" "$BUILD_ROOT/boot/kernel"
vm_kernel="$BUILD_ROOT/boot/kernel"
if test -e "$KERNEL_TEMP_DIR/initrd" ; then
mv "$KERNEL_TEMP_DIR/initrd" "$BUILD_ROOT/boot/initrd"
test -z "$VM_INITRD" && vm_initrd="$BUILD_ROOT/boot/initrd"
fi
rmdir "$KERNEL_TEMP_DIR"
fi
fi
vm_detach_root
echo "booting $VM_TYPE..."
# start watchdog if requested
if test -n "$VM_WATCHDOG" ; then
start_watchdog
echo "### VM INTERACTION START ###"
fi
vm_startup
# kill watchdog again
if test -n "$VM_WATCHDOG" ; then
echo "### VM INTERACTION END ###"
kill_watchdog
fi
vm_attach_root
if test -n "$VM_SWAP" ; then
vm_attach_swap
BUILDSTATUS=$(dd if="$VM_SWAP" bs=12 count=1 2>/dev/null | tr '\0' a)
case $BUILDSTATUS in
BUILDSTATUS[02])
mkdir -p $BUILD_ROOT/.build.packages
cd $BUILD_ROOT/.build.packages || cleanup_and_exit 1
echo "build: extracting built packages..."
extractbuild --disk "$VM_ROOT" --input "$VM_SWAP" --skip 512 -v || cleanup_and_exit 3
if test "$DO_STATISTICS" = 1 ; then
mkdir -p OTHER
TIME_TOTAL=$(( `date +%s` - $TIME_START_TIME ))
echo "TIME_total: $TIME_TOTAL" >> OTHER/_statistics
fi
cleanup_and_exit ${BUILDSTATUS#BUILDSTATUS}
;;
BUILDSTATUS*)
cleanup_and_exit ${BUILDSTATUS#BUILDSTATUS}
;;
*)
echo "No buildstatus set, either the base system is broken (kernel/initrd/udev/glibc/bash/perl)"
echo "or the build host has a kernel or hardware problem..."
cleanup_and_exit 3
;;
esac
cleanup_and_exit 1
fi
}
vm_save_statistics() {
echo "... saving statistics"
local sys_mounted otherdir
otherdir="$BUILD_ROOT$TOPDIR/OTHER"
test -n "$TIME_PREINSTALL" && echo "TIME_preinstall: $TIME_PREINSTALL" >> $otherdir/_statistics
test -n "$TIME_INSTALL" && echo "TIME_install: $TIME_INSTALL" >> $otherdir/_statistics
if test -e /.build/_statistics.df ; then
echo -n "MAX_mb_used_on_disk: " >> $otherdir/_statistics
cat /.build/_statistics.df >> $otherdir/_statistics
echo "" >> $otherdir/_statistics
rm /.build/_statistics.df
fi
if test -e /.build/_statistics.memory ; then
echo -n "MAX_mb_used_memory: " >> $otherdir/_statistics
cat /.build/_statistics.memory >> $otherdir/_statistics
echo "" >> $otherdir/_statistics
rm /.build/_statistics.memory
fi
if ! test -e /sys/block; then
mkdir -p /sys
mount -n sys /sys -t sysfs
sys_mounted=1
fi
device="hda1"
test -e /dev/sda && device="sda"
test -e /dev/vda && device="vda"
test -e /dev/xvda && device="xvda" # in newer XEN setups
test -e /dev/dasda && device="dasda" # in z/VM
test -e /dev/nfhd0 && device="nfhd0" # in aranym
if test -e /sys/block/${device}/stat ; then
disk=(`cat /sys/block/${device}/stat`)
test "0${disk[0]}" -gt 0 && echo "IO_requests_read: ${disk[0]}" >> $otherdir/_statistics
test "0${disk[2]}" -gt 0 && echo "IO_sectors_read: ${disk[2]}" >> $otherdir/_statistics
test "0${disk[4]}" -gt 0 && echo "IO_requests_write: ${disk[4]}" >> $otherdir/_statistics
test "0${disk[6]}" -gt 0 && echo "IO_sectors_write: ${disk[6]}" >> $otherdir/_statistics
else
echo "ERROR: no root disk device found, yet another new device name?"
ls -l /sys/block/
fi
test -n "$sys_mounted" && umount /sys
}
# args: resultdirs
vm_wrapup_build() {
test "$DO_STATISTICS" = 1 && vm_save_statistics
if test -n "$VM_SWAP"; then
echo "... saving built packages"
swapoff "$VM_SWAP"
pushd "$BUILD_ROOT$TOPDIR" >/dev/null
find "$@" -print0 | computeblocklists --padstart 512 --padend 512 -v --manifest - -0 > "$VM_SWAP" || cleanup_and_exit 1
popd >/dev/null
fi
}
vm_setup_network() {
if test -x /sbin/ip ; then
ip addr add 127.0.0.1/8 dev lo
ip addr add ::1/128 dev lo
ip link set lo up
else
ifconfig lo 127.0.0.1 up
ifconfig lo add ::1/128
fi
if test -n "$VM_TELNET"; then
VM_TELNET_DEVICE=$( cd /sys/class/net/; echo * )
VM_TELNET_DEVICE=${VM_TELNET_DEVICE#lo }
VM_TELNET_DEVICE=${VM_TELNET_DEVICE%% *}
if test -z "$VM_TELNET_DEVICE" ; then
cleanup_and_exit 1 "ERROR: no network device found for telnet server"
fi
if test -x /sbin/ip ; then
ip addr add 10.0.2.15/8 dev ${VM_TELNET_DEVICE}
ip addr add ::1/24 dev ${VM_TELNET_DEVICE}
ip link set ${VM_TELNET_DEVICE} up
elif test -x /sbin/ifconfig ; then
ifconfig ${VM_TELNET_DEVICE} 10.0.2.15 up
ifconfig ${VM_TELNET_DEVICE} add ::1/24
else
cleanup_and_exit 1 "ERROR: neither /sbin/ifconfig nor /sbin/ip is installed, please specify correct package via -x option"
fi
fi
if test -n "$VM_HOSTNAME" ; then
hostname "$VM_HOSTNAME"
fi
if test -n "$VM_TELNET"; then
echo WARNING: telnet option used, setting up telnet server ${VM_TELNET_DEVICE}
if test -x /usr/sbin/in.telnetd; then
( /usr/sbin/in.telnetd -L /.build/telnet_login_wrapper -debug 23 & )
else
cleanup_and_exit 1 "ERROR: /usr/sbin/in.telnetd is not installed, please specify correct package via -x option"
fi
fi
}
obs-build-20180831/computeblocklists 0000755 0001750 0001750 00000023116 13350372713 015743 0 ustar alee alee #!/usr/bin/perl -w
# compute the blocks used by a file
# usage:
# computeblocklists [options]
# options:
# --padstart NUM, --padend NUM, --verbose
#
# output:
#
#
# a block is either a number or a range (start-end)
#
################################################################
#
# Copyright (c) 1995-2018 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
use strict;
# the ioctls we use
my $FIBMAP = 1;
my $FIGETBSZ = 2;
my $FIEMAP = 0xc020660b; # _IOWR('f', 11, struct fiemap)
# powerpc, mips, sparc, and alpha have 3 direction bits
# and represent _IOC_NONE as 1 instead of 0.
sub alt_ioctl($) {
my ($ioctl_nr) = @_;
my $size = ($ioctl_nr >> 16) & 0x3fff;
my $dir = ($ioctl_nr >> 30);
my $base = $ioctl_nr & 0x1fffffff;
die "invalid size $size" if ($size > (1 << 13));
return $base | ($dir + 1) << 29;
}
#
# Use FIBMAP to gather block lists, block-by-block
# This is the older, slower way to iterate over file extents but
# will generally work on older kernels. The block number also
# must fit into an integer limiting the size of the file system.
#
sub fibmap_blocklist($$$) {
my ($fd, $filesize, $bsize) = @_;
my $exts = '';
my $blocks = int(($filesize + $bsize - 1) / $bsize);
die("file is too big for fibmap\n") if $blocks * $bsize < $filesize;
my ($firstblock, $lastblock);
for (my $cnt = 0; $cnt < $blocks; ++$cnt) {
my $block = pack('I', $cnt);
if (not defined ioctl($fd, $FIBMAP, $block)) {
if (not defined ioctl($fd, alt_ioctl($FIBMAP), $block)) {
die("fibmap ioctl: $!\n");
}
}
$block = unpack('I', $block);
if (defined($firstblock) && $block == ($firstblock ? $lastblock + 1 : 0)) {
$lastblock++; # continue run
next;
}
# finish old run
$exts .= "-$lastblock" if defined($firstblock) && $firstblock != $lastblock;
# start new run
$exts .= " $block";
$firstblock = $lastblock = $block;
}
# finish last run
$exts .= "-$lastblock" if defined($firstblock) && $firstblock != $lastblock;
return $exts;
}
#
# Use the FIEMAP ioctl to gather block lists, defined extent at a time
# This is the newer way to gather extent information. We iterate the file
# up to 50 extents at a time, each describing a contiguous, non-hole, range.
#
# see /usr/include/linux/fiemap.h for definitions of the flags used below
#
my $q_emu = 0; # 0=no emu, 1=little endian, 2=big endian
sub pack_Q {
my ($v) = @_;
return pack('Q', $v) unless $q_emu;
my $v1 = int($v / 4294967296);
my $v2 = int($v - 4294967296 * $v1);
($v1, $v2) = ($v2, $v1) if $q_emu == 1;
return pack('LL', $v1, $v2);
}
sub unpack_Q {
return unpack('Q', $_[0]) unless $q_emu;
my ($v1, $v2) = unpack('LL', $_[0]);
($v1, $v2) = ($v2, $v1) if $q_emu == 1;
my $v = $v1 * 4294967296 + $v2;
die("unpack_Q: number too big\n") if int($v - 4294967296 * $v1) != $v2;
return $v;
}
# Convert a size into a block number and an offset.
sub bytes_in_blocks($$) {
my ($bytes, $bsize) = @_;
my $blk = int($bytes / ($bsize * 65536)) * 65536; # work with 32bit int
$blk += int(($bytes - $blk * $bsize) / $bsize);
return ($blk, $bytes - $blk * $bsize);
}
# Create an extent descriptor
sub createext($$$;$) {
my ($start, $end, $bsize, $islast) = @_;
die if $start > $end;
my ($startblk, $startoff) = bytes_in_blocks($start, $bsize);
my ($endblk, $endoff) = bytes_in_blocks($end, $bsize);
$endoff = $bsize - 1 if $islast;
my $ext = " $startblk";
$ext .= ":$startoff" if $startoff != 0;
if ($startblk != $endblk || $endoff != $bsize - 1) {
$ext .= "-$endblk";
$ext .= ":$endoff" if $endoff != $bsize - 1;
}
return $ext;
}
sub fiemap_blocklist($$$) {
my ($file, $filesize, $bsize) = @_;
# check if pack/unpack supports the Q template
$q_emu = 0;
eval { die if unpack('Q', pack('Q', 1)) != 1 };
if ($@) {
# nope, fallback to encode/decode helpers
$q_emu = unpack('C', pack('L', 1)) ? 1 : 2;
}
my $exts = '';
my $offset = 0;
while ($offset < $filesize) {
my $flags_in = 0x00000001; # FIEMAP_FLAG_SYNC
my $x = pack("a8a8IIIx4.", pack_Q($offset), pack_Q($filesize), $flags_in, 0, 50, 4096);
if (not defined ioctl($file, $FIEMAP, $x)) {
if (not defined ioctl($file, alt_ioctl($FIEMAP), $x)) {
die("fiemap ioctl: $!\n");
}
}
my ($flags, $count, @extents) = unpack('x16IIx8(a8a8a8a8a8IIII)[50]', $x);
last if $count == 0; # rest is a hole
for (my $i = 0; $i < $count; $i++) {
$extents[$_] = unpack_Q($extents[$_]) for 0, 1, 2;
my ($logical, $physical, $length, $resv1, $resv2, $flags) = splice(@extents, 0, 9);
die("logical offset outside of file?\n") if $logical < 0 || $logical >= $filesize;
die("going back in file?\n") if $offset > $logical;
die("extent with bad size?\n") if $length <= 0;
# add a hole entry if needed
$exts .= createext(0, $logical - $offset - 1, $bsize) if $offset < $logical;
my $islast = $logical + $length >= $filesize ? 1 : 0;
# Not a hole but for these purposes we should treat it as one
if ($flags & 0x00000800) { # UNWRITTEN
$exts .= createext(0, $length - 1, $bsize, $islast);
} elsif ($flags & 0x00000008) { # ENCODED
die("extent mapped but is encoded\n");
# UNKNOWN|DELALLOC|DATA_ENCRYPTED|NOT_ALIGNED|DATA_INLINE|DATA_TAIL
} elsif ($flags & 0x00000786) {
die("extent cannot be block-mapped\n");
} else {
$exts .= createext($physical, $physical + $length - 1, $bsize, $islast);
}
$offset = $logical + $length;
}
}
$exts .= createext(0, $filesize - $offset - 1, $bsize, 1) if $offset < $filesize;
return $exts;
}
my ($opt_padstart, $opt_padend, $opt_verbose, $opt_manifest, $opt_mani0, $opt_fibmap);
$opt_verbose = 0;
while (@ARGV) {
if ($ARGV[0] eq '--padstart') {
shift @ARGV;
$opt_padstart = shift @ARGV;
next;
}
if ($ARGV[0] eq '--padend') {
shift @ARGV;
$opt_padend = shift @ARGV;
next;
}
if ($ARGV[0] eq '--verbose' || $ARGV[0] eq '-v') {
shift @ARGV;
$opt_verbose++;
next;
}
if ($ARGV[0] eq '-0') {
shift @ARGV;
$opt_mani0 = 1;
next;
}
if ($ARGV[0] eq '--manifest') {
shift @ARGV;
$opt_manifest = shift @ARGV;
next;
}
if ($ARGV[0] eq '--fibmap') {
shift @ARGV;
$opt_fibmap = 1;
next;
}
last;
}
print "\n"x$opt_padstart if $opt_padstart;
if ($opt_manifest) {
if ($opt_manifest eq '-') {
open(MANIFEST, '<&STDIN') || die("STDIN dup: $!\n");
} else {
open(MANIFEST, '<', $opt_manifest) || die("$opt_manifest: $!\n");
}
}
while (1) {
my $file;
if (@ARGV) {
$file = shift @ARGV;
} elsif ($opt_manifest) {
if ($opt_mani0) {
local $/ = "\0";
$file = ;
last unless defined $file;
$file =~ s/\0$//s;
} else {
$file = ;
last unless defined $file;
chomp $file;
}
} else {
last;
}
my $n = $file;
$n =~ s/([\000-\037 %])/sprintf("%%%02X", ord($1))/ges;
if (-l $file) {
print STDERR "$file\n" if $opt_verbose && !($opt_verbose == 1 && $file =~ /^KIWI\/.*\//);
my $c = readlink($file);
die("$file: readlink: $!\n") unless defined $c;
if ("/$c/" =~ /\/\.?\//s) {
print STDERR "$file: bad symlink ($c), ignored\n";
next;
}
if ("/$c/" =~ /^((?:\/\.\.)+)\/(.*?)$/s) {
my ($head, $tail) = ($1, $2);
if (("/$tail/" =~ /\/\.\.\//s) || (($head =~ y!/!!) > ($file =~ y!/!!))) {
print STDERR "$file: bad symlink ($c), ignored\n";
next;
}
} else {
if ("/$c/" =~ /\/\.\.\//s) {
print STDERR "$file: bad symlink ($c), ignored\n";
next;
}
}
$c =~ s/([\000-\037 %])/sprintf("%%%02X", ord($1))/ges;
print "l $n $c\n";
next;
} elsif (-d _) {
print STDERR "$file\n" if $opt_verbose && ($opt_verbose > 1 || $file =~ /^KIWI\/[^\/]*$/);
print "d $n\n";
next;
} elsif (! -f _) {
print STDERR "$file: unsupported file type, ignored\n";
next;
}
print STDERR "$file\n" if $opt_verbose && !($opt_verbose == 1 && $file =~ /^KIWI\/.*\//);
my $fd = undef;
if (!open($fd, '<', $file)) {
print STDERR "$file: $!\n";
next;
}
my @stat = stat($fd);
die unless @stat;
my $filesize = $stat[7];
if ($filesize == 0) {
print "f $n 0\n";
close($fd);
next;
}
my $bsize = pack('I', 0);
if (not defined ioctl($fd, $FIGETBSZ, $bsize)) {
if (not defined ioctl($fd, alt_ioctl($FIGETBSZ), $bsize)) {
die("$file: FIGETBSZ failed: $!\n");
}
}
$bsize = unpack('I', $bsize);
die("$file: illegal blocksize $bsize\n") unless $bsize > 0;
my $exts;
if (!$opt_fibmap) {
eval { $exts = fiemap_blocklist($fd, $filesize, $bsize) };
warn($@) if $@;
}
if (!defined($exts)) {
eval { $exts = fibmap_blocklist($fd, $filesize, $bsize) };
warn($@) if $@;
}
die "$file: could not get extent list\n" unless defined $exts;
print "f $n $filesize $bsize$exts\n";
close($fd);
}
print "\n"x$opt_padend if $opt_padend;
obs-build-20180831/livebuild_pre_run.template 0000755 0001750 0001750 00000004161 13350372713 017517 0 ustar alee alee #!/bin/bash
#
# This is a template for a livebuild_pre_run script. These scripts are
# executed by build_livebuild.sh in the chroot environment.
#
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
fix_debootstrap()
{
# debootstrap in Debian 7.0 does not like dash
if [ -x /usr/sbin/debootstrap ] ; then
sed -i 's|^#!/bin/sh|#!/bin/bash|' /usr/sbin/debootstrap
fi
}
fix_lb_bootstrap_archive-keys()
{
if [ -e /usr/lib/live/build/bootstrap_archive-keys ] ; then
sed -i '/apt-get update/{ s/^/#/ }' \
/usr/lib/live/build/bootstrap_archive-keys
fi
}
#
# main
#
: ${TOPDIR:=/usr/src/packages}
# Distribution and live-build specific hooks
fix_debootstrap
fix_lb_bootstrap_archive-keys
# Expand configuration based on defaults
cd $TOPDIR/LIVEBUILD_ROOT && lb config || exit 1
# Replace all occurances of LB_MIRROR with local repository
sed -i "s|^\(LB_MIRROR_[^=]\+=\).*|\1\"file:$TOPDIR/SOURCES/repos/\"|" \
$TOPDIR/LIVEBUILD_ROOT/config/bootstrap
sed -i "s|^\(LB_PARENT_MIRROR_[^=]\+=\).*|\1\"file:$TOPDIR/SOURCES/repos/\"|" \
$TOPDIR/LIVEBUILD_ROOT/config/bootstrap
# Prevent debootstrap from cleaning our cache
sed -i 's|^\(LB_CACHE_PACKAGES=\).*|\1"false"|' \
$TOPDIR/LIVEBUILD_ROOT/config/common
# Disable GPG checking
sed -i 's|^\(LB_APT_SECURE=\).*|\1"false"|' \
$TOPDIR/LIVEBUILD_ROOT/config/common
obs-build-20180831/runservices 0000755 0001750 0001750 00000006456 13350372713 014555 0 ustar alee alee #!/usr/bin/perl -w
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
BEGIN {
unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
}
use POSIX;
use File::Temp ();
use File::Copy ();
use strict;
use Build::SimpleXML;
my $servicedir = '/usr/lib/obs/service';
my $buildroot = '';
sub ls {
local *D;
opendir(D, $_[0]) || return ();
my @r = grep {$_ ne '.' && $_ ne '..'} readdir(D);
closedir D;
return @r;
}
sub run_services {
my ($xml) = @_;
my $servicexml = Build::SimpleXML::parse($xml);
die("not a valid _service file\n") unless $servicexml && $servicexml->{'services'};
$servicexml = $servicexml->{'services'}->[0];
my $tempdir;
if ($buildroot ne '') {
$tempdir = File::Temp::tempdir('CLEANUP' => 1, 'DIR' => "$buildroot/tmp");
die("bad tempdir\n") unless $tempdir =~ s/^\Q$buildroot\E//;
} else {
$tempdir = File::Temp::tempdir('CLEANUP' => 1);
}
# take default version setting
for my $s (@{$servicexml->{'service'} || []}) {
# buildtime only is default
next unless $s->{'mode'} && $s->{'mode'} eq 'buildtime';
die("missing name in service\n") unless $s->{'name'};
if (! -x "$buildroot$servicedir/$s->{'name'}") {
die("service '$s->{'name'}' configured to run, but is not available\n");
}
my @run;
push @run, "$servicedir/$s->{'name'}";
for my $param (@{$s->{'param'}}) {
next if $param->{'name'} eq 'outdir';
next unless $param->{'_content'};
push @run, "--$param->{'name'}";
push @run, $param->{'_content'};
}
push @run, "--outdir";
push @run, $tempdir;
my $pid = fork();
die("fork: $!\n") unless defined $pid;
if ($pid == 0) {
if ($buildroot ne '') {
chroot($buildroot) || die("chroot $buildroot: $!\n");
}
exec(@run);
die("$run[0]: $!\n");
}
1 while waitpid($pid, 0) != $pid;
die("service run failed for service '$s->{'name'}'\n") if $?;
# copy back
for my $file (grep {!/^[:\.]/} ls("$buildroot$tempdir")) {
File::Copy::move("$buildroot$tempdir/$file", $file) if -f "$buildroot$tempdir/$file";
}
}
}
if (@ARGV > 1 && $ARGV[0] eq '--buildroot') {
shift @ARGV;
$buildroot = shift @ARGV;
$buildroot = '' if $buildroot && $buildroot eq '/';
$buildroot =~ s@//+@/@; # or we may fail with 'bad tempdir' later.
die("bad buildroot\n") unless $buildroot eq '' || $buildroot =~ /^\//;
}
local *F;
open(F, '<', '_service') || die("_service: $!\n");
my $xml = '';
1 while sysread(F, $xml, 4096, length($xml)) > 0;
close F;
run_services($xml);
obs-build-20180831/build.conf.example 0000644 0001750 0001750 00000001540 13350372713 015644 0 ustar alee alee # Example configuration for buildroot and parameter whitelisting.
# Can be used to make multi-user environments more secure. Everything is
# allowed by default if no whitelist is defined.
#
# List of whitelisted build roots.
# %user will be replaced with $SUDO_USER (or $USER when running without sudo)
#
# ALLOW_BUILD_ROOT: /var/tmp/%user/build-root
# ALLOW_BUILD_ROOT: /var/tmp/build-root
# List of whitelisted parameters. Allowed parameters
# must be listed in double dash format.
#
# ALLOW_PARAM: --arch
# ALLOW_PARAM: --changelog
# ALLOW_PARAM: --clean
# ALLOW_PARAM: --dist
# ALLOW_PARAM: --jobs
# ALLOW_PARAM: --noinit
# ALLOW_PARAM: --norootforbuild
# ALLOW_PARAM: --root
# ALLOW_PARAM: --rpmlist
#
# Specific parameter arguments can be whitelisted (other arguments
# are not allowed in that case):
#
# ALLOW_PARAM: --jobs 1
obs-build-20180831/build-recipe-appimage 0000644 0001750 0001750 00000010103 13350372713 016307 0 ustar alee alee #################################################################
#
# AppImage specific functions.
#
# Author: Adrian Schroeter
#
################################################################
#
# Copyright (c) 2017 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
recipe_setup_appimage() {
TOPDIR=/usr/src/packages
test "$DO_INIT_TOPDIR" = false || rm -rf "$BUILD_ROOT$TOPDIR"
for i in OTHER SOURCES APPIMAGE_ROOT ; do
mkdir -p "$BUILD_ROOT$TOPDIR/$i"
done
chown -R "$ABUILD_UID:$ABUILD_GID" "$BUILD_ROOT$TOPDIR"
if test "$MYSRCDIR" = $BUILD_ROOT/.build-srcdir ; then
mv "$MYSRCDIR"/* $BUILD_ROOT$TOPDIR/SOURCES/
else
cp -p "$MYSRCDIR"/* $BUILD_ROOT$TOPDIR/SOURCES/
fi
rawcfgmacros=.rpmmacros
test "$BUILDTYPE" = debbuild && rawcfgmacros=.debmacros
queryconfig rawmacros --dist "$BUILD_DIST" --archpath "$BUILD_ARCH" --configdir "$CONFIG_DIR" > $BUILD_ROOT/root/$rawcfgmacros
}
recipe_prepare_appimage() {
:
}
# Variables:
# $BUILD_ROOT is the chroot
# $TOPDIR/SOURCES includes the appimages sources
# $TOPDIR/$APPIMAGE_ROOT where appimage will be called
# $RECIPEFILE the name of the appimage.yml config file
recipe_build_appimage() {
local ARCH DEB
if [ -x "$BUILD_ROOT/bin/rpm" ]; then
ARCH=$(chroot $BUILD_ROOT su -c "rpm --eval '%{_target_cpu}'")
else
ARCH=$(chroot $BUILD_ROOT su -c "dpkg-architecture -qDEB_BUILD_ARCH")
DEB=1
fi
local DIST="OBS"
test -z "${ARCH}" -o -z "${DIST}" && cleanup_and_exit 1
test -d $BUILD_ROOT/.build.binaries || cleanup_and_exit 1 "missing $BUILD_ROOT/.build.binaries"
if test "$DO_INIT" = true; then
if test -n "$DEB" -a ! -d "$BUILD_ROOT/.build.binaries/dists" ; then
echo "creating debian repository metadata..."
createrepo_debian $BUILD_ROOT/.build.binaries ${ARCH} ${DIST}
# setup /etc/apt/sources.list
mkdir -p "$BUILD_ROOT/etc/apt"
echo "deb [trusted=yes] file:/.build.binaries OBS main" >> "$BUILD_ROOT/etc/apt/sources.list"
fi
if test -z "$DEB" -a ! -d "$BUILD_ROOT/.build.binaries/repodata" ; then
echo "creating repository metadata..."
if [ -x "$BUILD_ROOT/usr/bin/createrepo_c" ]; then
chroot "$BUILD_ROOT" /usr/bin/createrepo_c /.build.binaries
elif [ -x "$BUILD_ROOT/usr/bin/createrepo" ]; then
chroot "$BUILD_ROOT" /usr/bin/createrepo /.build.binaries
else
cleanup_and_exit 1 "No createrepo found in build root"
fi
fi
fi
release_option=""
if test -n "$RELEASE" ; then
release_option="--release $RELEASE"
fi
chroot $BUILD_ROOT su -c "cd $TOPDIR/SOURCES && ARCH=$ARCH /usr/lib/appimagetool/pkg2appimage $release_option" - root \
|| cleanup_and_exit 1
# extract build result basenames
local build_results=""
for i in $BUILD_ROOT/$TOPDIR/OTHER/* ; do
test -f "$i" || continue
case "${i##*/}" in
*.AppImage|*.AppImage.digest|*.AppImage.zsync)
build_results="${build_results}\n${i%%.snap}"
;;
*)
;;
esac
done
# Fail the build if no build results are found
if [ -z "${build_results}" ] ; then
cleanup_and_exit 1 "No live-build result found"
fi
BUILD_SUCCEEDED=true
}
recipe_resultdirs_appimage() {
:
}
recipe_cleanup_appimage() {
:
}
# Local Variables:
# mode: Shell-script
# End:
obs-build-20180831/createmdkdeps 0000755 0001750 0001750 00000003203 13350372713 015003 0 ustar alee alee #!/usr/bin/perl -w
################################################################
#
# Copyright (c) 2015 SUSE Linux GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
# Mandriva/Mageia support
BEGIN {
unshift @INC, ($::ENV{"BUILD_DIR"} || "/usr/lib/build");
}
use strict;
use Build ':mdk';
use Build::Mdkrepo;
use Digest::MD5 ();
use File::Path;
use Getopt::Long;
Getopt::Long::Configure("no_ignore_case");
my $cachedir = "/var/cache/build";
GetOptions("cachedir=s" => \$cachedir) or exit(1);
for my $url (@ARGV) {
die("$url: not an remote mandriva/mageia repo") unless $url =~ /^(:?ftps?|https?):\/\/([^\/]*)\/?/;
my $repoid = Digest::MD5::md5_hex($url);
my $dir = "$cachedir/$repoid";
$url .= '/' unless $url =~ /\/$/;
File::Path::mkpath($dir);
system("$INC[0]/download", $dir, "${url}media_info/synthesis.hdlist.cz");
Build::Mdkrepo::parse("$dir/synthesis.hdlist.cz", sub { Build::writedeps(\*STDOUT, $_[0], $url) }, 'addselfprovides' => 1);
}
obs-build-20180831/spectool 0000755 0001750 0001750 00000025234 13350372713 014030 0 ustar alee alee #!/usr/bin/perl -w
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
=head1 spectool
spectool - tool to work with rpm spec files
=head1 SYNOPSIS
spectool [options] specfiles...
=head1 OPTIONS
=over 4
=item B<--help>
display help as manpage
=item B<--dist>=I
set distribution, e.g. "11.1-i586" or path to config
=item B<--archpath>=I
compatible architecture separated by colon, e.g. C.
Autotected if missing.
=item B<--configdir>=I
path to config files if B<--dist> didn't specify a full path
=item B<--define>=I
=item B<--with>=I
=item B<--without>=I
same meaning as in rpmbuild
=item B<--tag>=I
print tag from spec file, e.g. C. Regexp is also possible,
e.g. C
=item B<--sources>
print package source files. If a file C or
C.sources> is present verify the checksums against
that.
=over 4
=item B<--update>
update the checksums
=item B<--download>
download missing sources
=back
=back
=head1 DESCRIPTION
The B<--sources> option allows to manage a sources file in a way
similar to Fedora. The sources file lists the check sums and file
names of the binary files specified in the spec file.
B<--sources> without further options compares the check sums of all
files and prints a report consisting of a character that describes
the status of the file and the file name. Meaning of the characters
is as follows:
=over 4
=item B<.> check sum matches
=item B check sum broken
=item B file is missing, checksum known. Can be verified after download
=item B<-> file is missing and checksum unknown
=item B<_> file is present but checksum unknown
=item B text file, will be skipped for check sums
=item B> check sum known but not referenced from spec file
=back
Additionally specifying B<--update> recomputes all check sums and
updates the sources file.
With B<--download> all missing files are downloaded if the spec file
has an http or ftp url.
=head2 FORMAT OF THE SOURCES FILE
Lines of the form
=head2 NAME OF THE SOURCES FILE
A file named C is preferred if present for compatibility
with Fedora. It only contains md5 sums. If that file is not present
the C<.spec> suffix of the spec file is replaced with C<.sources>
and the this name used as sources file (e.g. C ->
C). In this file sha1 is preferred. Also, the name of
the algorithm is prepended with colon to the check sum.
=cut
my $builddir;
BEGIN {
$builddir = ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
unshift @INC, $builddir;
}
use strict;
use Build;
use Pod::Usage;
use Getopt::Long;
Getopt::Long::Configure("no_ignore_case");
my (@opt_showtag, $opt_sources, $opt_update, $opt_download);
sub parse_depfile;
my ($dist, $rpmdeps, $archs, $configdir, $useusedforbuild);
my %options;
GetOptions (
\%options,
"help" => sub { pod2usage(-exitstatus => 0, -verbose => 2) },
"dist=s" => \$dist,
"archpath=s" => \$archs,
"configdir=s" => \$configdir,
"define=s" => sub { Build::define($_[1]) },
"with=s" => sub { Build::define("_with_".$_[1]." --with-".$_[1]) },
"without=s" => sub { Build::define("_without_".$_[1]." --without-".$_[1]) },
"tag=s" => \@opt_showtag,
"sources" => \$opt_sources,
"update" => \$opt_update,
"download" => \$opt_download,
"download-force",
"download-recompress=s",
"download-outdir=s",
"download-compare=s",
"download-delete-identical",
) or pod2usage(1);
pod2usage(1) unless @ARGV;
my $ua;
my @specs = @ARGV;
die "--download must be used together with --sources\n" if ($opt_download && !$opt_sources);
die "--update must be used together with --sources\n" if ($opt_update && !$opt_sources);
$options{'download-recompress'} ||= 'auto';
$options{'download-outdir'}.='/' if ($options{'download-outdir'} && $options{'download-outdir'} !~ /\/$/);
$options{'download-outdir'} ||= '';
$options{'download-compare'}.='/' if ($options{'download-compare'} && $options{'download-compare'} !~ /\/$/);
$options{'download-compare'} ||= '';
my @archs;
if (!defined $archs) {
use POSIX qw/uname/;
my %archmap = qw/x86_64 i686 i686 i586 i586 i486 i486 i386/;
my @a = uname();
push @archs, $a[4];
while(exists $archmap{$archs[-1]}) {
push @archs, $archmap{$archs[-1]};
}
} else {
@archs = split(':', $archs);
}
push @archs, 'noarch' unless grep {$_ eq 'noarch'} @archs;
unless ($dist) {
$dist = 'spectool';
# $dist = `rpm -q --qf '%{DISTRIBUTION}' rpm 2>/dev/null`;
# $dist = Build::dist_canon($dist||'', $archs[0]);
}
if($dist !~ /\// && !defined $configdir) {
if($0 =~ /^\//) {
use File::Basename qw/dirname/;
$configdir = dirname($0).'/configs';
undef $configdir unless -e $configdir.'/sl11.3.conf';
} else {
$configdir = $builddir.'/configs';
undef $configdir unless -e $configdir.'/sl11.3.conf';
}
if(!defined $configdir) {
print STDERR "please specify config dir\n";
}
}
#######################################################################
# param: array to fill, spec file
# return: file name
sub read_sources_digests($$)
{
my $files = shift;
my $spec = shift;
my $srcfile = 'sources';
if (! -r $srcfile) {
$srcfile = $spec;
$srcfile =~ s/spec$/sources/;
}
if (open (F, '<', $srcfile)) {
while() {
chomp;
my ($sum, $file) = split(/ +/, $_, 2);
$files->{$file} = $sum;
}
close F;
}
return $srcfile;
}
# param: file, oldsum
# return: newsum or undef if match
sub check_sum($$)
{
my $file = shift;
my $oldsum = shift || 'sha1:';
my $sum;
my $type = 'md5:';
if($oldsum =~ /^(\S+:)/) {
$type = $1;
} else {
$oldsum = $type.$oldsum;
}
if ($type eq 'md5:') {
$sum = $type.`md5sum $file` || die "md5sum failed\n";
} elsif ($type eq 'sha1:') {
$sum = $type.`sha1sum $file` || die "sha1sum failed\n";
} else {
die "unsupported digest type '$type'\n";
}
$sum =~ s/ .*//s;
if($sum ne $oldsum) {
return $sum;
}
return undef;
}
sub download($$)
{
my ($url, $dest) = @_;
my $retry = 3;
while ($retry--) {
my $res = $ua->mirror($url, $dest);
last if $res->is_success;
# if it's a redirect we probably got a bad mirror and should just retry
return 0 unless $retry && $res->previous;
warn "retrying $url\n";
}
return 1;
}
#######################################################################
my $ret = 0;
for my $spec (@specs) {
my $cf = Build::read_config_dist($dist, $archs[0], $configdir);
my $parsed = Build::parse($cf, $spec);
if (!defined $parsed) {
die "can't parse $spec\n";
}
for my $tag (@opt_showtag) {
if($tag =~ /^\/(.+)\/$/) {
my $expr = $1;
for my $t (keys %$parsed) {
if ($t =~ $expr) {
push @opt_showtag, $t;
}
}
} else {
if(exists $parsed->{lc $tag}) {
print $tag, ": ";
my $v = $parsed->{lc $tag};
$v = join(' ', @$v) if (ref $v eq 'ARRAY');
print $v, "\n";
} else {
print STDERR "$tag does not exist\n";
}
}
}
if ($opt_sources) {
my $files = {};
my $srcfile = read_sources_digests($files, $spec);
if ($opt_download) {
unless ($ua) {
use LWP::UserAgent;
$ua = LWP::UserAgent->new(
agent => "openSUSE build service",
env_proxy => 1,
timeout => 42);
}
for my $t (keys %$parsed) {
next unless ($t =~ /^(?:source|patch)\d*/);
my $url = $parsed->{$t};
next unless $url =~ /^(?:https?|ftp):\/\//;
my $file = $url;
$file =~ s/.*\///;
my $src = $options{'download-compare'}.$file;
next if -e $src && !($options{'download-force'} || $options{'download-delete-identical'});
print "Downloading $file...\n";
my $dest = $options{'download-outdir'}.$file;
print "$url -> $dest\n";
if(!download($url, $dest) && $options{'download-recompress'} ne 'no') {
# TODO
# let's see if the file was recompressed
if($url =~ s/\.bz2$/.gz/ && $file =~ s/\.bz2$/.gz/
&& !download($url, $dest)) {
if(system('bznew', $dest) == 0) {
print STDERR "Used $file and recompressed to bz2 instead\n";
} else {
unlink $dest;
}
} else {
print STDERR "Downloading $file failed\n";
}
}
if ($options{'download-delete-identical'} && $options{'download-outdir'}
&& system('cmp', '-s', $dest, $src) == 0) {
unlink($dest);
}
}
}
if ($opt_update) {
my $changed;
for my $t (keys %$parsed) {
next unless ($t =~ /^(?:source|patch)\d*/);
my $file = $parsed->{$t};
$file =~ s/.*\///;
next unless -B $file;
my $sum = check_sum($file, ($files->{$file} || ($srcfile eq 'sources'?'md5:':'sha1:')));
if($sum) {
print STDERR "update $file\n";
$files->{$file} = $sum;
$changed = 1;
}
}
if($changed) {
if(open(F, '>', $srcfile)) {
for my $file (keys %$files) {
$files->{$file} =~ s/^md5:// if $srcfile eq 'sources';
print F $files->{$file}, ' ', $file, "\n";
}
close F;
}
}
} else {
for my $t (keys %$parsed) {
next unless ($t =~ /^(?:source|patch)\d*/);
my $file = $parsed->{$t};
$file =~ s/.*\///;
if (!exists $files->{$file}) {
if (! -e $file) {
print '- ';
} elsif (-B $file) {
print '_ ';
} else {
print 't ';
}
} elsif (! -e $file) {
print 'd ';
delete $files->{$file};
} else {
my $sum = check_sum($file, $files->{$file});
if($sum) {
print '! ';
$ret = 1;
} else {
print '. ';
}
delete $files->{$file};
}
print $parsed->{$t}, "\n";
}
for my $file (keys %$files) {
print "? $file\n";
}
}
}
}
exit $ret;
obs-build-20180831/build-recipe-preinstallimage 0000644 0001750 0001750 00000005000 13350372713 017704 0 ustar alee alee #
# preinstall specific functions.
#
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
recipe_setup_preinstallimage() {
# should never be called
cleanup_and_exit 1
}
recipe_prepare_preinstallimage() {
:
}
recipe_build_preinstallimage() {
echo "creating preinstall image..."
test -d "$BUILD_ROOT/.preinstall_image" || cleanup_and_exit 1
cd $BUILD_ROOT || cleanup_and_exit 1
TAR="tar"
if test -x /usr/bin/bsdtar; then
TAR="/usr/bin/bsdtar --format gnutar --chroot"
fi
TOPDIRS=
for DIR in .* * ; do
case "$DIR" in
.|..) continue ;;
.build.kernel.*) ;; # to be packaged
.build.hostarch.*) ;; # to be packaged
.build.initrd.*) ;; # to be packaged
.build*) continue ;;
.preinstallimage*) continue ;;
.srcfiles*) continue ;;
.pkgs) continue ;;
.rpm-cache) continue ;;
installed-pkg) continue ;;
proc|sys) continue ;;
esac
TOPDIRS="$TOPDIRS $DIR"
done
if ! $TAR -czf .preinstallimage.$$.tar.gz --one-file-system $TOPDIRS ; then
cleanup_and_exit 1
fi
echo "image created."
TOPDIR=/usr/src/packages
mkdir -p $BUILD_ROOT$TOPDIR/OTHER
rm -f $BUILD_ROOT$TOPDIR/OTHER/preinstallimage.info
for PKG in $BUILD_ROOT/.preinstall_image/* ; do
PKG=${PKG##*/}
read PKG_HDRMD5 PKGID < $BUILD_ROOT/.preinstall_image/$PKG
test -n "$PKG_HDRMD5" || cleanup_and_exit 1
echo "$PKG_HDRMD5 $PKG" >> $BUILD_ROOT$TOPDIR/OTHER/preinstallimage.info
done
mv $BUILD_ROOT/.preinstallimage.$$.tar.gz $BUILD_ROOT$TOPDIR/OTHER/preinstallimage.tar.gz
rm -f $BUILD_ROOT/.build.packages
ln -s ${TOPDIR#/} $BUILD_ROOT/.build.packages
test -d "$SRCDIR" && cd "$SRCDIR"
}
recipe_resultdirs_preinstallimage() {
:
}
recipe_cleanup_preinstallimage() {
:
}
obs-build-20180831/build-vm-qemu 0000644 0001750 0001750 00000002560 13350372713 014656 0 ustar alee alee #
# qemu specific functions
#
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
# just forward everything to kvm...
vm_verify_options_qemu() {
vm_verify_options_kvm
}
vm_startup_qemu() {
vm_startup_kvm
}
vm_kill_qemu() {
vm_kill_kvm
}
vm_fixup_qemu() {
vm_setup_kvm
}
vm_attach_root_qemu() {
vm_attach_root_kvm
}
vm_attach_swap_qemu() {
vm_attach_swap_kvm
}
vm_detach_root_qemu() {
vm_detach_root_kvm
}
vm_detach_swap_qemu() {
vm_detach_swap_kvm
}
vm_cleanup_qemu() {
vm_cleanup_kvm
}
vm_sysrq_qemu() {
:
}
vm_wipe_qemu() {
:
}
obs-build-20180831/build-recipe-debbuild 0000644 0001750 0001750 00000003354 13350372713 016310 0 ustar alee alee #
# debbuild specific functions.
#
################################################################
#
# Copyright (c) 2015 SUSE Linux GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
recipe_setup_debbuild() {
TOPDIR=`chroot $BUILD_ROOT su -c "debbuild --eval '%_topdir'" - $BUILD_USER`
if test -z "$TOPDIR"; then
cleanup_and_exit 1 "Error: TOPDIR empty"
fi
test "$DO_INIT_TOPDIR" = false || rm -rf "$BUILD_ROOT$TOPDIR"
mkdir -p "$BUILD_ROOT$TOPDIR"
mkdir -p "$BUILD_ROOT$TOPDIR/OTHER"
mkdir -p "$BUILD_ROOT$TOPDIR/SOURCES"
mkdir -p "$BUILD_ROOT$TOPDIR/DEBS"
mkdir -p "$BUILD_ROOT$TOPDIR/SDEBS"
mkdir -p "$BUILD_ROOT$TOPDIR/BUILD"
test -e "$BUILD_ROOT$TOPDIR/SPECS" || ln -s SOURCES "$BUILD_ROOT$TOPDIR/SPECS"
chown -R "$ABUILD_UID:$ABUILD_GID" "$BUILD_ROOT$TOPDIR"
cp -p "$MYSRCDIR"/* $BUILD_ROOT$TOPDIR/SOURCES/
}
recipe_prepare_debbuild() {
recipe_prepare_spec "$@"
}
recipe_build_debbuild() {
recipe_build_spec "$@"
}
recipe_resultdirs_debbuild() {
echo DEBS SDEBS
}
recipe_cleanup_debbuild() {
:
}
obs-build-20180831/Build/ 0000755 0001750 0001750 00000000000 13350372713 013303 5 ustar alee alee obs-build-20180831/Build/Collax.pm 0000644 0001750 0001750 00000003105 13350372713 015062 0 ustar alee alee #
# Copyright 2015 Zarafa B.V. and its licensors
#
# 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 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.
#
package Build::Collax;
use strict;
sub parse {
my($buildconf, $fn) = @_;
my @bscript;
if (ref($fn) eq "ARRAY") {
@bscript = @$fn;
$fn = undef;
} elsif (ref($fn) ne "") {
die "Unhandled ref type in collax";
} else {
local *FH;
if (!open(FH, "<", $fn)) {
return {"error" => "$fn: $!"};
}
@bscript = ;
chomp(@bscript);
close(FH);
}
my $ret = {"deps" => []};
for (my $i = 0; $i <= $#bscript; ++$i) {
next unless $bscript[$i] =~ m{^\w+=};
my $key = lc(substr($&, 0, -1));
my $value = $';
if ($value =~ m{^([\'\"])}) {
$value = substr($value, 1);
while ($value !~ m{[\'\"]}) {
my @cut = splice(@bscript, $i + 1, 1);
$value .= $cut[0];
}
$value =~ s{[\'\"]}{}s;
$value =~ s{\n}{ }gs;
}
if ($key eq "package") {
$ret->{"name"} = $value;
} elsif ($key eq "version") {
$ret->{$key} = $value;
} elsif ($key eq "builddepends" || $key eq "extradepends") {
$value =~ s{^\s+}{}gs;
$value =~ s{\s+$}{}gs;
$value =~ s{,}{ }gs;
push(@{$ret->{"deps"}}, split(/\s+/, $value));
}
}
return $ret;
}
1;
obs-build-20180831/Build/Appimage.pm 0000644 0001750 0001750 00000003475 13350372713 015375 0 ustar alee alee ################################################################
#
# Copyright (c) 2017 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Appimage;
use strict;
use Build::Deb;
use Build::Rpm;
eval { require YAML::XS; };
*YAML::XS::LoadFile = sub {die("YAML::XS is not available\n")} unless defined &YAML::XS::LoadFile;
sub parse {
my ($cf, $fn) = @_;
my $yml;
eval { $yml = YAML::XS::LoadFile($fn); };
return {'error' => "Failed to parse yml file"} unless $yml;
my $ret = {};
$ret->{'name'} = $yml->{'app'};
$ret->{'version'} = $yml->{'version'} || "0";
my @packdeps;
if ($yml->{'ingredients'}) {
for my $pkg (@{$yml->{'ingredients'}->{'packages'} || {}}) {
push @packdeps, $pkg;
}
}
if ($yml->{'build'} && $yml->{'build'}->{'packages'}) {
for my $pkg (@{$yml->{'build'}->{'packages'}}) {
push @packdeps, $pkg;
}
}
$ret->{'deps'} = \@packdeps;
my @sources;
if ($yml->{'build'} && $yml->{'build'}->{'files'}) {
for my $source (@{$yml->{'build'}->{'files'}}) {
push @sources, $source;
}
}
$ret->{'sources'} = \@sources;
return $ret;
}
1;
obs-build-20180831/Build/Rpm.pm 0000644 0001750 0001750 00000114444 13350372713 014407 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Rpm;
our $unfilteredprereqs = 0;
our $conflictdeps = 0;
use strict;
use Digest::MD5;
sub expr {
my $expr = shift;
my $lev = shift;
$lev ||= 0;
my ($v, $v2);
$expr =~ s/^\s+//;
my $t = substr($expr, 0, 1);
if ($t eq '(') {
($v, $expr) = expr(substr($expr, 1), 0);
return undef unless defined $v;
return undef unless $expr =~ s/^\)//;
} elsif ($t eq '!') {
($v, $expr) = expr(substr($expr, 1), 5);
return undef unless defined $v;
$v = 0 if $v && $v eq '\"\"';
$v =~ s/^0+/0/ if $v;
$v = !$v;
} elsif ($t eq '-') {
($v, $expr) = expr(substr($expr, 1), 5);
return undef unless defined $v;
$v = -$v;
} elsif ($expr =~ /^([0-9]+)(.*?)$/) {
$v = $1;
$expr = $2;
} elsif ($expr =~ /^([a-zA-Z_0-9]+)(.*)$/) {
$v = "\"$1\"";
$expr = $2;
} elsif ($expr =~ /^(\".*?\")(.*)$/) {
$v = $1;
$expr = $2;
} else {
return;
}
return ($v, $expr) if $lev >= 5;
while (1) {
$expr =~ s/^\s+//;
if ($expr =~ /^&&/) {
return ($v, $expr) if $lev > 1;
($v2, $expr) = expr(substr($expr, 2), 1);
return undef unless defined $v2;
$v = 0 if $v && $v eq '\"\"';
$v =~ s/^0+/0/;
$v2 = 0 if $v2 && $v2 eq '\"\"';
$v2 =~ s/^0+/0/;
$v &&= $v2;
} elsif ($expr =~ /^\|\|/) {
return ($v, $expr) if $lev > 1;
($v2, $expr) = expr(substr($expr, 2), 1);
return undef unless defined $v2;
$v = 0 if $v && $v eq '\"\"';
$v =~ s/^0+/0/;
$v2 = 0 if $v2 && $v2 eq '\"\"';
$v2 =~ s/^0+/0/;
$v ||= $v2;
} elsif ($expr =~ /^>=/) {
return ($v, $expr) if $lev > 2;
($v2, $expr) = expr(substr($expr, 2), 2);
return undef unless defined $v2;
$v = (($v =~ /^\"/) ? $v ge $v2 : $v >= $v2) ? 1 : 0;
} elsif ($expr =~ /^>/) {
return ($v, $expr) if $lev > 2;
($v2, $expr) = expr(substr($expr, 1), 2);
return undef unless defined $v2;
$v = (($v =~ /^\"/) ? $v gt $v2 : $v > $v2) ? 1 : 0;
} elsif ($expr =~ /^<=/) {
return ($v, $expr) if $lev > 2;
($v2, $expr) = expr(substr($expr, 2), 2);
return undef unless defined $v2;
$v = (($v =~ /^\"/) ? $v le $v2 : $v <= $v2) ? 1 : 0;
} elsif ($expr =~ /^) {
return ($v, $expr) if $lev > 2;
($v2, $expr) = expr(substr($expr, 1), 2);
return undef unless defined $v2;
$v = (($v =~ /^\"/) ? $v lt $v2 : $v < $v2) ? 1 : 0;
} elsif ($expr =~ /^==/) {
return ($v, $expr) if $lev > 2;
($v2, $expr) = expr(substr($expr, 2), 2);
return undef unless defined $v2;
$v = (($v =~ /^\"/) ? $v eq $v2 : $v == $v2) ? 1 : 0;
} elsif ($expr =~ /^!=/) {
return ($v, $expr) if $lev > 2;
($v2, $expr) = expr(substr($expr, 2), 2);
return undef unless defined $v2;
$v = (($v =~ /^\"/) ? $v ne $v2 : $v != $v2) ? 1 : 0;
} elsif ($expr =~ /^\+/) {
return ($v, $expr) if $lev > 3;
($v2, $expr) = expr(substr($expr, 1), 3);
return undef unless defined $v2;
$v += $v2;
} elsif ($expr =~ /^-/) {
return ($v, $expr) if $lev > 3;
($v2, $expr) = expr(substr($expr, 1), 3);
return undef unless defined $v2;
$v -= $v2;
} elsif ($expr =~ /^\*/) {
($v2, $expr) = expr(substr($expr, 1), 4);
return undef unless defined $v2;
$v *= $v2;
} elsif ($expr =~ /^\//) {
($v2, $expr) = expr(substr($expr, 1), 4);
return undef unless defined $v2 && 0 + $v2;
$v /= $v2;
} elsif ($expr =~ /^([=&|])/) {
warn("syntax error while parsing $1$1\n");
return ($v, $expr);
} else {
return ($v, $expr);
}
}
}
sub adaptmacros {
my ($macros, $optold, $optnew) = @_;
for (keys %$optold) {
delete $macros->{$_};
}
for (keys %$optnew) {
$macros->{$_} = $optnew->{$_};
}
return $optnew;
}
sub grabargs {
my ($macname, $getopt, @args) = @_;
my %m;
$m{'0'} = $macname;
$m{'**'} = join(' ', @args);
my %go;
%go = ($getopt =~ /(.)(:*)/sg) if defined $getopt;
while (@args && $args[0] =~ s/^-//) {
my $o = shift @args;
last if $o eq '-';
while ($o =~ /^(.)(.*)$/) {
if ($go{$1}) {
my $arg = $2;
$arg = shift(@args) if @args && $arg eq '';
$m{"-$1"} = "-$1 $arg";
$m{"-$1*"} = $arg;
last;
}
$m{"-$1"} = "-$1";
$o = $2;
}
}
$m{'#'} = scalar(@args);
my $i = 1;
for (@args) {
$m{$i} = $_;
$i++;
}
$m{'*'} = join(' ', @args);
return \%m;
}
# xspec may be passed as array ref to return the parsed spec files
# an entry in the returned array can be
# - a string: verbatim line from the original file
# - a two element array ref:
# - [0] original line
# - [1] undef: line unused due to %if
# - [1] scalar: line after macro expansion. Only set if it's a build deps
# line and build deps got modified or 'save_expanded' is set in
# config
sub parse {
my ($config, $specfile, $xspec) = @_;
my $packname;
my $exclarch;
my $badarch;
my @subpacks;
my @packdeps;
my @prereqs;
my $hasnfb;
my $nfbline;
my %macros;
my %macros_args;
my $ret = {};
my $ifdeps;
my $specdata;
local *SPEC;
if (ref($specfile) eq 'GLOB') {
*SPEC = *$specfile;
} elsif (ref($specfile) eq 'ARRAY') {
$specdata = [ @$specfile ];
} elsif (!open(SPEC, '<', $specfile)) {
warn("$specfile: $!\n");
$ret->{'error'} = "open $specfile: $!";
return $ret;
}
my @macros = @{$config->{'macros'} || []};
my $skip = 0;
my $main_preamble = 1;
my $preamble = 1;
my $inspec = 0;
my $hasif = 0;
my $lineno = 0;
my $obspackage = defined($config->{'obspackage'}) ? $config->{'obspackage'} : '@OBS_PACKAGE@';
my $buildflavor = defined($config->{'buildflavor'}) ? $config->{'buildflavor'} : '';
while (1) {
my $line;
if (@macros) {
$line = shift @macros;
$hasif = 0 unless @macros;
} elsif ($specdata) {
$inspec = 1;
last unless @$specdata;
$line = shift @$specdata;
++$lineno;
if (ref $line) {
$line = $line->[0]; # verbatim line
push @$xspec, $line if $xspec;
$xspec->[-1] = [ $line, undef ] if $xspec && $skip;
next;
}
} else {
$inspec = 1;
$line = ;
last unless defined $line;
chomp $line;
++$lineno;
}
push @$xspec, $line if $inspec && $xspec;
if ($line =~ /^#\s*neededforbuild\s*(\S.*)$/) {
if (defined $hasnfb) {
$xspec->[-1] = [ $xspec->[-1], undef ] if $inspec && $xspec;
next;
}
$hasnfb = $1;
$nfbline = \$xspec->[-1] if $inspec && $xspec;
next;
}
if ($line =~ /^\s*#/) {
next unless $line =~ /^#!Build(?:Ignore|Conflicts)\s*:/i;
}
my $expandedline = '';
if (!$skip && ($line =~ /%/)) {
my $tries = 0;
my @expandstack;
my $optmacros = {};
# newer perls: \{((?:(?>[^{}]+)|(?2))*)\}
reexpand:
while ($line =~ /^(.*?)%(\{([^\}]+)\}|[\?\!]*[0-9a-zA-Z_]+|%|\*\*?|#|\()(.*?)$/) {
if ($tries++ > 1000) {
print STDERR "Warning: spec file parser ",($lineno?" line $lineno":''),": macro too deeply nested\n" if $config->{'warnings'};
$line = 'MACRO';
last;
}
$expandedline .= $1;
$line = $4;
my $macname = defined($3) ? $3 : $2;
my $macorig = $2;
my $macdata;
my $macalt;
if (defined($3)) {
if ($macname =~ /{/) { # {
while (($macname =~ y/{/{/) > ($macname =~ y/}/}/)) {
last unless $line =~ /^([^}]*)}(.*)$/;
$macname .= "}$1";
$macorig .= "$1}";
$line = $2;
}
}
$macdata = '';
if ($macname =~ /^([^\s:]+)([\s:])(.*)$/) {
$macname = $1;
if ($2 eq ':') {
$macalt = $3;
} else {
$macdata = $3;
}
}
}
my $mactest = 0;
if ($macname =~ /^\!\?/ || $macname =~ /^\?\!/) {
$mactest = -1;
} elsif ($macname =~ /^\?/) {
$mactest = 1;
}
$macname =~ s/^[\!\?]+//;
if ($macname eq '%') {
$expandedline .= '%';
next;
} elsif ($macname eq '(') {
print STDERR "Warning: spec file parser",($lineno?" line $lineno":''),": can't expand %(...)\n" if $config->{'warnings'};
$line = 'MACRO';
last;
} elsif ($macname eq 'define' || $macname eq 'global') {
if ($line =~ /^\s*([0-9a-zA-Z_]+)(?:\(([^\)]*)\))?\s*(.*?)$/) {
my $macname = $1;
my $macargs = $2;
my $macbody = $3;
if (defined $macargs) {
$macros_args{$macname} = $macargs;
} else {
delete $macros_args{$macname};
}
$macros{$macname} = $macbody;
}
$line = '';
last;
} elsif ($macname eq 'defined' || $macname eq 'with' || $macname eq 'undefined' || $macname eq 'without' || $macname eq 'bcond_with' || $macname eq 'bcond_without') {
my @args;
if ($macorig =~ /^\{(.*)\}$/) {
@args = split(' ', $1);
shift @args;
} else {
@args = split(' ', $line);
$line = '';
}
next unless @args;
if ($macname eq 'bcond_with') {
$macros{"with_$args[0]"} = 1 if exists $macros{"_with_$args[0]"};
next;
}
if ($macname eq 'bcond_without') {
$macros{"with_$args[0]"} = 1 unless exists $macros{"_without_$args[0]"};
next;
}
$args[0] = "with_$args[0]" if $macname eq 'with' || $macname eq 'without';
$line = ((exists($macros{$args[0]}) ? 1 : 0) ^ ($macname eq 'undefined' || $macname eq 'without' ? 1 : 0)).$line;
} elsif ($macname eq 'expand') {
$macalt = $macros{$macname} unless defined $macalt;
$macalt = '' if $mactest == -1;
push @expandstack, ($expandedline, $line, undef);
$line = $macalt;
$expandedline = '';
} elsif (exists($macros{$macname})) {
if (!defined($macros{$macname})) {
print STDERR "Warning: spec file parser",($lineno?" line $lineno":''),": can't expand '$macname'\n" if $config->{'warnings'};
$line = 'MACRO';
last;
}
if (defined($macros_args{$macname})) {
# macro with args!
if (!defined($macdata)) {
$line =~ /^\s*([^\n]*).*$/;
$macdata = $1;
$line = '';
}
push @expandstack, ($expandedline, $line, $optmacros);
$optmacros = adaptmacros(\%macros, $optmacros, grabargs($macname, $macros_args{$macname}, split(' ', $macdata)));
$line = $macros{$macname};
$expandedline = '';
next;
}
$macalt = $macros{$macname} unless defined $macalt;
$macalt = '' if $mactest == -1;
if ($macalt =~ /%/) {
push @expandstack, ('', $line, 1) if $line ne '';
$line = $macalt;
} else {
$expandedline .= $macalt;
}
} elsif ($mactest) {
$macalt = '' if !defined($macalt) || $mactest == 1;
if ($macalt =~ /%/) {
push @expandstack, ('', $line, 1) if $line ne '';
$line = $macalt;
} else {
$expandedline .= $macalt;
}
} else {
$expandedline .= "%$macorig" unless $macname =~ /^-/;
}
}
$line = $expandedline . $line;
if (@expandstack) {
my $m = pop(@expandstack);
if ($m) {
$optmacros = adaptmacros(\%macros, $optmacros, $m) if ref $m;
$expandstack[-2] .= $line;
$line = pop(@expandstack);
$expandedline = pop(@expandstack);
} else {
my $todo = pop(@expandstack);
$expandedline = pop(@expandstack);
push @expandstack, ('', $todo, 1) if $todo ne '';
}
goto reexpand;
}
}
if ($line =~ /^\s*%else\b/) {
$skip = 1 - $skip if $skip < 2;
next;
}
if ($line =~ /^\s*%endif\b/) {
$skip-- if $skip;
next;
}
$skip++ if $skip && $line =~ /^\s*%if/;
if ($skip) {
$xspec->[-1] = [ $xspec->[-1], undef ] if $xspec;
$ifdeps = 1 if $line =~ /^(BuildRequires|BuildPrereq|BuildConflicts|\#\!BuildIgnore|\#\!BuildConflicts)\s*:\s*(\S.*)$/i;
next;
}
if ($line =~ /\@/) {
$line =~ s/\@BUILD_FLAVOR\@/$buildflavor/g;
$line =~ s/\@OBS_PACKAGE\@/$obspackage/g;
}
if ($line =~ /^\s*%ifarch(.*)$/) {
my $arch = $macros{'_target_cpu'} || 'unknown';
my @archs = grep {$_ eq $arch} split(/\s+/, $1);
$skip = 1 if !@archs;
$hasif = 1;
next;
}
if ($line =~ /^\s*%ifnarch(.*)$/) {
my $arch = $macros{'_target_cpu'} || 'unknown';
my @archs = grep {$_ eq $arch} split(/\s+/, $1);
$skip = 1 if @archs;
$hasif = 1;
next;
}
if ($line =~ /^\s*%ifos(.*)$/) {
my $os = $macros{'_target_os'} || 'unknown';
my @oss = grep {$_ eq $os} split(/\s+/, $1);
$skip = 1 if !@oss;
$hasif = 1;
next;
}
if ($line =~ /^\s*%ifnos(.*)$/) {
my $os = $macros{'_target_os'} || 'unknown';
my @oss = grep {$_ eq $os} split(/\s+/, $1);
$skip = 1 if @oss;
$hasif = 1;
next;
}
if ($line =~ /^\s*%if(.*)$/) {
my ($v, $r) = expr($1);
$v = 0 if $v && $v eq '\"\"';
$v =~ s/^0+/0/ if $v;
$skip = 1 unless $v;
$hasif = 1;
next;
}
if ($main_preamble) {
if ($line =~ /^(Name|Version|Disttag|Release)\s*:\s*(\S+)/i) {
$ret->{lc $1} = $2;
$macros{lc $1} = $2;
} elsif ($line =~ /^ExclusiveArch\s*:\s*(.*)/i) {
$exclarch ||= [];
push @$exclarch, split(' ', $1);
} elsif ($line =~ /^ExcludeArch\s*:\s*(.*)/i) {
$badarch ||= [];
push @$badarch, split(' ', $1);
}
}
if (@subpacks && $preamble && exists($ret->{'version'}) && $line =~ /^Version\s*:\s*(\S+)/i) {
$ret->{'multiversion'} = 1 if $ret->{'version'} ne $1;
}
if ($line =~ /^(?:Requires\(pre\)|Requires\(post\)|PreReq)\s*:\s*(\S.*)$/i) {
my $deps = $1;
my @deps = $deps =~ /([^\s\[,]+)(\s+[<=>]+\s+[^\s\[,]+)?(\s+\[[^\]]+\])?[\s,]*/g;
while (@deps) {
my ($pack, $vers, $qual) = splice(@deps, 0, 3);
if (!$unfilteredprereqs && $pack =~ /^\//) {
$ifdeps = 1;
next unless $config->{'fileprovides'}->{$pack};
}
push @prereqs, $pack unless grep {$_ eq $pack} @prereqs;
}
next;
}
if ($preamble && ($line =~ /^(BuildRequires|BuildPrereq|BuildConflicts|\#\!BuildIgnore|\#\!BuildConflicts)\s*:\s*(\S.*)$/i)) {
my $what = $1;
my $deps = $2;
$ifdeps = 1 if $hasif;
# XXX: weird syntax addition. can append arch or project to dependency
# BuildRequire: foo > 17 [i586,x86_64]
# BuildRequire: foo [home:bar]
# BuildRequire: foo [!home:bar]
my @deps;
if (" $deps" =~ /[\s,]\(/) {
# we need to be careful, there could be a rich dep
my $d = $deps;
while ($d ne '') {
if ($d =~ /^\(/) {
my @s = split(' ', $d);
push @deps, shiftrich(\@s), undef, undef;
$d = join(' ', @s);
} else {
last unless $d =~ s/([^\s\[,]+)(\s+[<=>]+\s+[^\s\[,]+)?(\s+\[[^\]]+\])?[\s,]*//;
push @deps, $1, $2, $3;
}
}
} else {
@deps = $deps =~ /([^\s\[,]+)(\s+[<=>]+\s+[^\s\[,]+)?(\s+\[[^\]]+\])?[\s,]*/g;
}
my $replace = 0;
my @ndeps = ();
while (@deps) {
my ($pack, $vers, $qual) = splice(@deps, 0, 3);
if (defined($qual)) {
$replace = 1;
my $arch = $macros{'_target_cpu'} || '';
my $proj = $macros{'_target_project'} || '';
$qual =~ s/^\s*\[//;
$qual =~ s/\]$//;
my $isneg = 0;
my $bad;
for my $q (split('[\s,]', $qual)) {
$isneg = 1 if $q =~ s/^\!//;
$bad = 1 if !defined($bad) && !$isneg;
if ($isneg) {
if ($q eq $arch || $q eq $proj) {
$bad = 1;
last;
}
} elsif ($q eq $arch || $q eq $proj) {
$bad = 0;
}
}
next if $bad;
}
$vers = '' unless defined $vers;
$vers =~ s/=(>|<)/$1=/;
push @ndeps, "$pack$vers";
}
$replace = 1 if grep {/^-/} @ndeps;
if (lc($what) ne 'buildrequires' && lc($what) ne 'buildprereq') {
if ($conflictdeps && $what =~ /conflict/i) {
push @packdeps, map {"!$_"} @ndeps;
next;
}
push @packdeps, map {"-$_"} @ndeps;
next;
}
if (defined($hasnfb)) {
if ((grep {$_ eq 'glibc' || $_ eq 'rpm' || $_ eq 'gcc' || $_ eq 'bash'} @ndeps) > 2) {
# ignore old generated BuildRequire lines.
$xspec->[-1] = [ $xspec->[-1], undef ] if $xspec;
next;
}
}
push @packdeps, @ndeps;
next unless $xspec && $inspec;
if ($replace) {
my @cndeps = grep {!/^-/} @ndeps;
if (@cndeps) {
$xspec->[-1] = [ $xspec->[-1], "$what: ".join(' ', @cndeps) ];
} else {
$xspec->[-1] = [ $xspec->[-1], ''];
}
}
next;
} elsif ($preamble && $line =~ /^(Source\d*|Patch\d*|Url|Icon)\s*:\s*(\S+)/i) {
my ($tag, $val) = (lc($1), $2);
$macros{$tag} = $val if $tag eq 'url';
# associate url and icon tags with the corresponding subpackage
$tag .= scalar @subpacks if ($tag eq 'url' || $tag eq 'icon') && @subpacks;
if ($tag =~ /icon/) {
# there can be a gif and xpm icon
push @{$ret->{$tag}}, $val;
} else {
$ret->{$tag} = $val;
}
if ($tag =~ /^(source|patch)(\d+)?$/) {
my $num = defined($2) ? $2 : ($1 eq 'source' ? 0 : -1);
$macros{uc($1) . "URL$num"} = $val if $num >= 0;
}
} elsif (!$preamble && ($line =~ /^(Source\d*|Patch\d*|Url|Icon|BuildRequires|BuildPrereq|BuildConflicts|\#\!BuildIgnore)\s*:\s*(\S.*)$/i)) {
print STDERR "Warning: spec file parser ".($lineno ? " line $lineno" : '').": Ignoring $1 used beyond the preamble.\n" if $config->{'warnings'};
}
if ($line =~ /^\s*%package\s+(-n\s+)?(\S+)/) {
if ($1) {
push @subpacks, $2;
} else {
push @subpacks, $ret->{'name'}.'-'.$2 if defined $ret->{'name'};
}
$preamble = 1;
$main_preamble = 0;
}
if ($line =~ /^\s*%(prep|build|install|check|clean|preun|postun|pretrans|posttrans|pre|post|files|changelog|description|triggerpostun|triggerun|triggerin|trigger|verifyscript)/) {
$main_preamble = 0;
$preamble = 0;
}
# do this always?
if ($xspec && @$xspec && $config->{'save_expanded'}) {
$xspec->[-1] = [ $xspec->[-1], $line ];
}
}
close SPEC unless ref $specfile;
if (defined($hasnfb)) {
if (!@packdeps) {
@packdeps = split(' ', $hasnfb);
} elsif ($nfbline) {
$$nfbline = [$$nfbline, undef ];
}
}
unshift @subpacks, $ret->{'name'} if defined $ret->{'name'};
$ret->{'subpacks'} = \@subpacks;
$ret->{'exclarch'} = $exclarch if defined $exclarch;
$ret->{'badarch'} = $badarch if defined $badarch;
$ret->{'deps'} = \@packdeps;
$ret->{'prereqs'} = \@prereqs if @prereqs;
$ret->{'configdependent'} = 1 if $ifdeps;
return $ret;
}
###########################################################################
my %rpmstag = (
"SIGTAG_SIZE" => 1000, # Header+Payload size in bytes. */
"SIGTAG_PGP" => 1002, # RSA signature over Header+Payload
"SIGTAG_MD5" => 1004, # MD5 hash over Header+Payload
"SIGTAG_GPG" => 1005, # DSA signature over Header+Payload
"NAME" => 1000,
"VERSION" => 1001,
"RELEASE" => 1002,
"EPOCH" => 1003,
"SUMMARY" => 1004,
"DESCRIPTION" => 1005,
"BUILDTIME" => 1006,
"ARCH" => 1022,
"OLDFILENAMES" => 1027,
"SOURCERPM" => 1044,
"PROVIDENAME" => 1047,
"REQUIREFLAGS" => 1048,
"REQUIRENAME" => 1049,
"REQUIREVERSION" => 1050,
"NOSOURCE" => 1051,
"NOPATCH" => 1052,
"SOURCEPACKAGE" => 1106,
"PROVIDEFLAGS" => 1112,
"PROVIDEVERSION" => 1113,
"DIRINDEXES" => 1116,
"BASENAMES" => 1117,
"DIRNAMES" => 1118,
"DISTURL" => 1123,
"CONFLICTFLAGS" => 1053,
"CONFLICTNAME" => 1054,
"CONFLICTVERSION" => 1055,
"OBSOLETENAME" => 1090,
"OBSOLETEFLAGS" => 1114,
"OBSOLETEVERSION" => 1115,
"OLDSUGGESTSNAME" => 1156,
"OLDSUGGESTSVERSION" => 1157,
"OLDSUGGESTSFLAGS" => 1158,
"OLDENHANCESNAME" => 1159,
"OLDENHANCESVERSION" => 1160,
"OLDENHANCESFLAGS" => 1161,
"RECOMMENDNAME" => 5046,
"RECOMMENDVERSION" => 5047,
"RECOMMENDFLAGS" => 5048,
"SUGGESTNAME" => 5049,
"SUGGESTVERSION" => 5050,
"SUGGESTFLAGS" => 5051,
"SUPPLEMENTNAME" => 5052,
"SUPPLEMENTVERSION" => 5053,
"SUPPLEMENTFLAGS" => 5054,
"ENHANCENAME" => 5055,
"ENHANCEVERSION" => 5056,
"ENHANCEFLAGS" => 5057,
);
sub rpmq {
my ($rpm, @stags) = @_;
my @sigtags = grep {/^SIGTAG_/} @stags;
@stags = grep {!/^SIGTAG_/} @stags;
my $dosigs = @sigtags && !@stags;
@stags = @sigtags if $dosigs;
my $need_filenames = grep { $_ eq 'FILENAMES' } @stags;
push @stags, 'BASENAMES', 'DIRNAMES', 'DIRINDEXES', 'OLDFILENAMES' if $need_filenames;
@stags = grep { $_ ne 'FILENAMES' } @stags if $need_filenames;
my %stags = map {0 + ($rpmstag{$_} || $_) => $_} @stags;
my ($magic, $sigtype, $headmagic, $cnt, $cntdata, $lead, $head, $index, $data, $tag, $type, $offset, $count);
local *RPM;
my $forcebinary;
if (ref($rpm) eq 'ARRAY') {
($headmagic, $cnt, $cntdata) = unpack('N@8NN', $rpm->[0]);
if ($headmagic != 0x8eade801) {
warn("Bad rpm\n");
return ();
}
if (length($rpm->[0]) < 16 + $cnt * 16 + $cntdata) {
warn("Bad rpm\n");
return ();
}
$index = substr($rpm->[0], 16, $cnt * 16);
$data = substr($rpm->[0], 16 + $cnt * 16, $cntdata);
} else {
if (ref($rpm) eq 'GLOB') {
*RPM = *$rpm;
} elsif (!open(RPM, '<', $rpm)) {
warn("$rpm: $!\n");
return ();
}
if (read(RPM, $lead, 96) != 96) {
warn("Bad rpm $rpm\n");
close RPM unless ref($rpm);
return ();
}
($magic, $sigtype) = unpack('N@78n', $lead);
if ($magic != 0xedabeedb || $sigtype != 5) {
warn("Bad rpm $rpm\n");
close RPM unless ref($rpm);
return ();
}
$forcebinary = 1 if unpack('@6n', $lead) != 1;
if (read(RPM, $head, 16) != 16) {
warn("Bad rpm $rpm\n");
close RPM unless ref($rpm);
return ();
}
($headmagic, $cnt, $cntdata) = unpack('N@8NN', $head);
if ($headmagic != 0x8eade801) {
warn("Bad rpm $rpm\n");
close RPM unless ref($rpm);
return ();
}
if (read(RPM, $index, $cnt * 16) != $cnt * 16) {
warn("Bad rpm $rpm\n");
close RPM unless ref($rpm);
return ();
}
$cntdata = ($cntdata + 7) & ~7;
if (read(RPM, $data, $cntdata) != $cntdata) {
warn("Bad rpm $rpm\n");
close RPM unless ref($rpm);
return ();
}
}
my %res = ();
if (@sigtags && !$dosigs) {
%res = &rpmq(["$head$index$data"], @sigtags);
}
if (ref($rpm) eq 'ARRAY' && !$dosigs && @$rpm > 1) {
my %res2 = &rpmq([ $rpm->[1] ], @stags);
%res = (%res, %res2);
return %res;
}
if (ref($rpm) ne 'ARRAY' && !$dosigs) {
if (read(RPM, $head, 16) != 16) {
warn("Bad rpm $rpm\n");
close RPM unless ref($rpm);
return ();
}
($headmagic, $cnt, $cntdata) = unpack('N@8NN', $head);
if ($headmagic != 0x8eade801) {
warn("Bad rpm $rpm\n");
close RPM unless ref($rpm);
return ();
}
if (read(RPM, $index, $cnt * 16) != $cnt * 16) {
warn("Bad rpm $rpm\n");
close RPM unless ref($rpm);
return ();
}
if (read(RPM, $data, $cntdata) != $cntdata) {
warn("Bad rpm $rpm\n");
close RPM unless ref($rpm);
return ();
}
}
close RPM unless ref($rpm);
# return %res unless @stags;
while($cnt-- > 0) {
($tag, $type, $offset, $count, $index) = unpack('N4a*', $index);
$tag = 0+$tag;
if ($stags{$tag} || !@stags) {
eval {
my $otag = $stags{$tag} || $tag;
if ($type == 0) {
$res{$otag} = [ '' ];
} elsif ($type == 1) {
$res{$otag} = [ unpack("\@${offset}c$count", $data) ];
} elsif ($type == 2) {
$res{$otag} = [ unpack("\@${offset}c$count", $data) ];
} elsif ($type == 3) {
$res{$otag} = [ unpack("\@${offset}n$count", $data) ];
} elsif ($type == 4) {
$res{$otag} = [ unpack("\@${offset}N$count", $data) ];
} elsif ($type == 5) {
$res{$otag} = [ undef ];
} elsif ($type == 6) {
$res{$otag} = [ unpack("\@${offset}Z*", $data) ];
} elsif ($type == 7) {
$res{$otag} = [ unpack("\@${offset}a$count", $data) ];
} elsif ($type == 8 || $type == 9) {
my $d = unpack("\@${offset}a*", $data);
my @res = split("\0", $d, $count + 1);
$res{$otag} = [ splice @res, 0, $count ];
} else {
$res{$otag} = [ undef ];
}
};
if ($@) {
warn("Bad rpm $rpm: $@\n");
return ();
}
}
}
if ($forcebinary && $stags{1044} && !$res{$stags{1044}} && !($stags{1106} && $res{$stags{1106}})) {
$res{$stags{1044}} = [ '(none)' ]; # like rpm does...
}
if ($need_filenames) {
if ($res{'OLDFILENAMES'}) {
$res{'FILENAMES'} = [ @{$res{'OLDFILENAMES'}} ];
} else {
my $i = 0;
$res{'FILENAMES'} = [ map {"$res{'DIRNAMES'}->[$res{'DIRINDEXES'}->[$i++]]$_"} @{$res{'BASENAMES'}} ];
}
}
return %res;
}
sub add_flagsvers {
my ($res, $name, $flags, $vers) = @_;
return unless $res && $res->{$name};
my @flags = @{$res->{$flags} || []};
my @vers = @{$res->{$vers} || []};
for (@{$res->{$name}}) {
if (@flags && ($flags[0] & 0xe) && @vers) {
$_ .= ' ';
$_ .= '<' if $flags[0] & 2;
$_ .= '>' if $flags[0] & 4;
$_ .= '=' if $flags[0] & 8;
$_ .= " $vers[0]";
}
shift @flags;
shift @vers;
}
}
sub filteroldweak {
my ($res, $name, $flags, $data, $strong, $weak) = @_;
return unless $res && $res->{$name};
my @flags = @{$res->{$flags} || []};
my @strong;
my @weak;
for (@{$res->{$name}}) {
if (@flags && ($flags[0] & 0x8000000)) {
push @strong, $_;
} else {
push @weak, $_;
}
shift @flags;
}
$data->{$strong} = \@strong if @strong;
$data->{$weak} = \@weak if @weak;
}
sub verscmp_part {
my ($s1, $s2) = @_;
if (!defined($s1)) {
return defined($s2) ? -1 : 0;
}
return 1 if !defined $s2;
return 0 if $s1 eq $s2;
while (1) {
$s1 =~ s/^[^a-zA-Z0-9~]+//;
$s2 =~ s/^[^a-zA-Z0-9~]+//;
if ($s1 =~ s/^~//) {
next if $s2 =~ s/^~//;
return -1;
}
return 1 if $s2 =~ /^~/;
if ($s1 eq '') {
return $s2 eq '' ? 0 : -1;
}
return 1 if $s2 eq '';
my ($x1, $x2, $r);
if ($s1 =~ /^([0-9]+)(.*?)$/) {
$x1 = $1;
$s1 = $2;
$s2 =~ /^([0-9]*)(.*?)$/;
$x2 = $1;
$s2 = $2;
return 1 if $x2 eq '';
$x1 =~ s/^0+//;
$x2 =~ s/^0+//;
$r = length($x1) - length($x2) || $x1 cmp $x2;
} elsif ($s1 ne '' && $s2 ne '') {
$s1 =~ /^([a-zA-Z]*)(.*?)$/;
$x1 = $1;
$s1 = $2;
$s2 =~ /^([a-zA-Z]*)(.*?)$/;
$x2 = $1;
$s2 = $2;
return -1 if $x1 eq '' || $x2 eq '';
$r = $x1 cmp $x2;
}
return $r > 0 ? 1 : -1 if $r;
}
}
sub verscmp {
my ($s1, $s2, $dtest) = @_;
return 0 if $s1 eq $s2;
my ($e1, $v1, $r1) = $s1 =~ /^(?:(\d+):)?(.*?)(?:-([^-]*))?$/s;
$e1 = 0 unless defined $e1;
my ($e2, $v2, $r2) = $s2 =~ /^(?:(\d+):)?(.*?)(?:-([^-]*))?$/s;
$e2 = 0 unless defined $e2;
if ($e1 ne $e2) {
my $r = verscmp_part($e1, $e2);
return $r if $r;
}
return 0 if $dtest && ($v1 eq '' || $v2 eq '');
if ($v1 ne $v2) {
my $r = verscmp_part($v1, $v2);
return $r if $r;
}
$r1 = '' unless defined $r1;
$r2 = '' unless defined $r2;
return 0 if $dtest && ($r1 eq '' || $r2 eq '');
if ($r1 ne $r2) {
return verscmp_part($r1, $r2);
}
return 0;
}
sub query {
my ($handle, %opts) = @_;
my @tags = qw{NAME SOURCERPM NOSOURCE NOPATCH SIGTAG_MD5 PROVIDENAME PROVIDEFLAGS PROVIDEVERSION REQUIRENAME REQUIREFLAGS REQUIREVERSION SOURCEPACKAGE};
push @tags, qw{EPOCH VERSION RELEASE ARCH};
push @tags, qw{FILENAMES} if $opts{'filelist'};
push @tags, qw{SUMMARY DESCRIPTION} if $opts{'description'};
push @tags, qw{DISTURL} if $opts{'disturl'};
push @tags, qw{BUILDTIME} if $opts{'buildtime'};
push @tags, qw{CONFLICTNAME CONFLICTVERSION CONFLICTFLAGS OBSOLETENAME OBSOLETEVERSION OBSOLETEFLAGS} if $opts{'conflicts'};
push @tags, qw{RECOMMENDNAME RECOMMENDVERSION RECOMMENDFLAGS SUGGESTNAME SUGGESTVERSION SUGGESTFLAGS SUPPLEMENTNAME SUPPLEMENTVERSION SUPPLEMENTFLAGS ENHANCENAME ENHANCEVERSION ENHANCEFLAGS OLDSUGGESTSNAME OLDSUGGESTSVERSION OLDSUGGESTSFLAGS OLDENHANCESNAME OLDENHANCESVERSION OLDENHANCESFLAGS} if $opts{'weakdeps'};
my %res = rpmq($handle, @tags);
return undef unless %res;
my $src = $res{'SOURCERPM'}->[0];
$src = '' unless defined $src;
$src =~ s/-[^-]*-[^-]*\.[^\.]*\.rpm//;
add_flagsvers(\%res, 'PROVIDENAME', 'PROVIDEFLAGS', 'PROVIDEVERSION');
add_flagsvers(\%res, 'REQUIRENAME', 'REQUIREFLAGS', 'REQUIREVERSION');
my $data = {
name => $res{'NAME'}->[0],
hdrmd5 => unpack('H32', $res{'SIGTAG_MD5'}->[0]),
};
if ($opts{'alldeps'}) {
$data->{'provides'} = [ @{$res{'PROVIDENAME'} || []} ];
$data->{'requires'} = [ @{$res{'REQUIRENAME'} || []} ];
} else {
$data->{'provides'} = [ grep {!/^rpmlib\(/ && !/^\//} @{$res{'PROVIDENAME'} || []} ];
$data->{'requires'} = [ grep {!/^rpmlib\(/ && !/^\//} @{$res{'REQUIRENAME'} || []} ];
}
if ($opts{'conflicts'}) {
add_flagsvers(\%res, 'CONFLICTNAME', 'CONFLICTFLAGS', 'CONFLICTVERSION');
add_flagsvers(\%res, 'OBSOLETENAME', 'OBSOLETEFLAGS', 'OBSOLETEVERSION');
$data->{'conflicts'} = [ @{$res{'CONFLICTNAME'}} ] if $res{'CONFLICTNAME'};
$data->{'obsoletes'} = [ @{$res{'OBSOLETENAME'}} ] if $res{'OBSOLETENAME'};
}
if ($opts{'weakdeps'}) {
for (qw{RECOMMEND SUGGEST SUPPLEMENT ENHANCE}) {
next unless $res{"${_}NAME"};
add_flagsvers(\%res, "${_}NAME", "${_}FLAGS", "${_}VERSION");
$data->{lc($_)."s"} = [ @{$res{"${_}NAME"}} ];
}
if ($res{'OLDSUGGESTSNAME'}) {
add_flagsvers(\%res, 'OLDSUGGESTSNAME', 'OLDSUGGESTSFLAGS', 'OLDSUGGESTSVERSION');
filteroldweak(\%res, 'OLDSUGGESTSNAME', 'OLDSUGGESTSFLAGS', $data, 'recommends', 'suggests');
}
if ($res{'OLDENHANCESNAME'}) {
add_flagsvers(\%res, 'OLDENHANCESNAME', 'OLDENHANCESFLAGS', 'OLDENHANCESVERSION');
filteroldweak(\%res, 'OLDENHANCESNAME', 'OLDENHANCESFLAGS', $data, 'supplements', 'enhances');
}
}
# rpm3 compatibility: retrofit missing self provides
if ($src ne '') {
my $haveselfprovides;
if (@{$data->{'provides'}}) {
if ($data->{'provides'}->[-1] =~ /^\Q$res{'NAME'}->[0]\E =/) {
$haveselfprovides = 1;
} elsif (@{$data->{'provides'}} > 1 && $data->{'provides'}->[-2] =~ /^\Q$res{'NAME'}->[0]\E =/) {
$haveselfprovides = 1;
}
}
if (!$haveselfprovides) {
my $evr = "$res{'VERSION'}->[0]-$res{'RELEASE'}->[0]";
$evr = "$res{'EPOCH'}->[0]:$evr" if $res{'EPOCH'} && $res{'EPOCH'}->[0];
push @{$data->{'provides'}}, "$res{'NAME'}->[0] = $evr";
}
}
$data->{'source'} = $src eq '(none)' ? $data->{'name'} : $src if $src ne '';
if ($opts{'evra'}) {
my $arch = $res{'ARCH'}->[0];
$arch = $res{'NOSOURCE'} || $res{'NOPATCH'} ? 'nosrc' : 'src' unless $src ne '';
$data->{'version'} = $res{'VERSION'}->[0];
$data->{'release'} = $res{'RELEASE'}->[0];
$data->{'arch'} = $arch;
$data->{'epoch'} = $res{'EPOCH'}->[0] if exists $res{'EPOCH'};
}
if ($opts{'filelist'}) {
$data->{'filelist'} = $res{'FILENAMES'};
}
if ($opts{'description'}) {
$data->{'summary'} = $res{'SUMMARY'}->[0];
$data->{'description'} = $res{'DESCRIPTION'}->[0];
}
$data->{'buildtime'} = $res{'BUILDTIME'}->[0] if $opts{'buildtime'};
$data->{'disturl'} = $res{'DISTURL'}->[0] if $opts{'disturl'} && $res{'DISTURL'};
return $data;
}
sub queryhdrmd5 {
my ($bin, $leadsigp) = @_;
local *F;
open(F, '<', $bin) || die("$bin: $!\n");
my $buf = '';
my $l;
while (length($buf) < 96 + 16) {
$l = sysread(F, $buf, 4096, length($buf));
if (!$l) {
warn("$bin: read error\n");
close(F);
return undef;
}
}
my ($magic, $sigtype) = unpack('N@78n', $buf);
if ($magic != 0xedabeedb || $sigtype != 5) {
warn("$bin: not a rpm (bad magic of header type)\n");
close(F);
return undef;
}
my ($headmagic, $cnt, $cntdata) = unpack('@96N@104NN', $buf);
if ($headmagic != 0x8eade801) {
warn("$bin: not a rpm (bad sig header magic)\n");
close(F);
return undef;
}
my $hlen = 96 + 16 + $cnt * 16 + $cntdata;
$hlen = ($hlen + 7) & ~7;
while (length($buf) < $hlen) {
$l = sysread(F, $buf, 4096, length($buf));
if (!$l) {
warn("$bin: read error\n");
close(F);
return undef;
}
}
close F;
$$leadsigp = Digest::MD5::md5_hex(substr($buf, 0, $hlen)) if $leadsigp;
my $idxarea = substr($buf, 96 + 16, $cnt * 16);
if ($idxarea !~ /\A(?:.{16})*\000\000\003\354\000\000\000\007(....)\000\000\000\020/s) {
warn("$bin: no md5 signature header\n");
return undef;
}
my $md5off = unpack('N', $1);
if ($md5off >= $cntdata) {
warn("$bin: bad md5 offset\n");
return undef;
}
$md5off += 96 + 16 + $cnt * 16;
return unpack("\@${md5off}H32", $buf);
}
sub queryinstalled {
my ($root, %opts) = @_;
$root = '' if !defined($root) || $root eq '/';
local *F;
my $dochroot = $root ne '' && !$opts{'nochroot'} && !$< && (-x "$root/usr/bin/rpm" || -x "$root/bin/rpm") ? 1 : 0;
my $pid = open(F, '-|');
die("fork: $!\n") unless defined $pid;
if (!$pid) {
if ($dochroot && chroot($root)) {
chdir('/') || die("chdir: $!\n");
$root = '';
}
my @args;
unshift @args, '--nodigest', '--nosignature' if -e "$root/usr/bin/rpmquery ";
unshift @args, '--dbpath', "$root/var/lib/rpm" if $root ne '';
push @args, '--qf', '%{NAME}/%{ARCH}/%|EPOCH?{%{EPOCH}}:{0}|/%{VERSION}/%{RELEASE}/%{BUILDTIME}\n';
if (-x "$root/usr/bin/rpm") {
exec("$root/usr/bin/rpm", '-qa', @args);
die("$root/usr/bin/rpm: $!\n");
}
if (-x "$root/bin/rpm") {
exec("$root/bin/rpm", '-qa', @args);
die("$root/bin/rpm: $!\n");
}
die("rpm: command not found\n");
}
my @pkgs;
while () {
chomp;
my @s = split('/', $_);
next unless @s >= 5;
my $q = {'name' => $s[0], 'arch' => $s[1], 'version' => $s[3], 'release' => $s[4]};
$q->{'epoch'} = $s[2] if $s[2];
$q->{'buildtime'} = $s[5] if $s[5];
push @pkgs, $q;
}
if (!close(F)) {
return queryinstalled($root, %opts, 'nochroot' => 1) if !@pkgs && $dochroot;
die("rpm: exit status $?\n");
}
return \@pkgs;
}
# return (lead, sighdr, hdr [, hdrmd5]) of a rpm
sub getrpmheaders {
my ($path, $withhdrmd5) = @_;
my $hdrmd5;
local *F;
open(F, '<', $path) || die("$path: $!\n");
my $buf = '';
my $l;
while (length($buf) < 96 + 16) {
$l = sysread(F, $buf, 4096, length($buf));
die("$path: read error\n") unless $l;
}
die("$path: not a rpm\n") unless unpack('N', $buf) == 0xedabeedb && unpack('@78n', $buf) == 5;
my ($headmagic, $cnt, $cntdata) = unpack('@96N@104NN', $buf);
die("$path: not a rpm (bad sig header)\n") unless $headmagic == 0x8eade801 && $cnt < 16384 && $cntdata < 1048576;
my $hlen = 96 + 16 + $cnt * 16 + $cntdata;
$hlen = ($hlen + 7) & ~7;
while (length($buf) < $hlen + 16) {
$l = sysread(F, $buf, 4096, length($buf));
die("$path: read error\n") unless $l;
}
if ($withhdrmd5) {
my $idxarea = substr($buf, 96 + 16, $cnt * 16);
die("$path: no md5 signature header\n") unless $idxarea =~ /\A(?:.{16})*\000\000\003\354\000\000\000\007(....)\000\000\000\020/s;
my $md5off = unpack('N', $1);
die("$path: bad md5 offset\n") unless $md5off;
$md5off += 96 + 16 + $cnt * 16;
$hdrmd5 = unpack("\@${md5off}H32", $buf);
}
($headmagic, $cnt, $cntdata) = unpack('N@8NN', substr($buf, $hlen));
die("$path: not a rpm (bad header)\n") unless $headmagic == 0x8eade801 && $cnt < 1048576 && $cntdata < 33554432;
my $hlen2 = $hlen + 16 + $cnt * 16 + $cntdata;
while (length($buf) < $hlen2) {
$l = sysread(F, $buf, 4096, length($buf));
die("$path: read error\n") unless $l;
}
close F;
return (substr($buf, 0, 96), substr($buf, 96, $hlen - 96), substr($buf, $hlen, $hlen2 - $hlen), $hdrmd5);
}
sub getnevr_rich {
my ($d) = @_;
my $n = '';
my $bl = 0;
while ($d =~ /^([^ ,\(\)]*)/) {
$n .= $1;
$d = substr($d, length($1));
last unless $d =~ /^([\(\)])/;
$bl += $1 eq '(' ? 1 : -1;
last if $bl < 0;
$n .= $1;
$d = substr($d, 1);
}
return $n;
}
my %richops = (
'and' => 1,
'or' => 2,
'if' => 3,
'unless' => 4,
'else' => 5,
'with' => 6,
'without' => 7,
);
sub parse_rich_rec {
my ($dep, $chainop) = @_;
my $d = $dep;
$chainop ||= 0;
return ($d, undef) unless $d =~ s/^\(\s*//;
my ($r, $r2);
if ($d =~ /^\(/) {
($d, $r) = parse_rich_rec($d);
return ($d, undef) unless $r;
} else {
return ($d, undef) if $d =~ /^\)/;
my $n = getnevr_rich($d);
$d = substr($d, length($n));
$d =~ s/^ +//;
if ($d =~ /^([<=>]+)/) {
$n .= " $1 ";
$d =~ s/^[<=>]+ +//;
my $evr = getnevr_rich($d);
$d = substr($d, length($evr));
$n .= $evr;
}
$r = [0, $n];
}
$d =~ s/^\s+//;
return ($d, undef) unless $d ne '';
return ($d, $r) if $d =~ s/^\)//;
return ($d, undef) unless $d =~ s/([a-z]+)\s+//;
my $op = $richops {$1};
return ($d, undef) unless $op;
return ($d, undef) if $op == 5 && $chainop != 3 && $chainop != 4;
$chainop = 0 if $op == 5;
return ($d, undef) if $chainop && (($chainop != 1 && $chainop != 2 && $chainop != 6) || $op != $chainop);
($d, $r2) = parse_rich_rec("($d", $op);
return ($d, undef) unless $r2;
if (($op == 3 || $op == 4) && $r2->[0] == 5) {
$r = [$op, $r, $r2->[1], $r2->[2]];
} else {
$r = [$op, $r, $r2];
}
return ($d, $r);
}
sub parse_rich_dep {
my ($dep) = @_;
my ($d, $r) = parse_rich_rec($dep);
return undef if !$r || $d ne '';
return $r;
}
my @testcaseops = ('', '&', '|', '', '', '', '+', '-');
sub testcaseformat_rec {
my ($r, $addparens) = @_;
my $op = $r->[0];
return $r->[1] unless $op;
my $top = $testcaseops[$op];
my $r1 = testcaseformat_rec($r->[1], 1);
if (($op == 3 || $op == 4) && @$r == 4) {
$r1 = "$r1 $top " . testcaseformat_rec($r->[2], 1);
$top = '';
}
my $addparens2 = 1;
$addparens2 = 0 if $r->[2]->[0] == $op && ($op == 1 || $op == 2 || $op == 6);
my $r2 = testcaseformat_rec($r->[-1], $addparens2);
return $addparens ? "($r1 $top $r2)" : "$r1 $top $r2";
}
sub testcaseformat {
my ($dep) = @_;
my $r = parse_rich_dep($dep);
return $dep unless $r;
return testcaseformat_rec($r);
}
sub shiftrich {
my ($s) = @_;
# FIXME: do this right!
my $dep = shift @$s;
while (@$s && ($dep =~ y/\(/\(/) > ($dep =~ y/\)/\)/)) {
$dep .= ' ' . shift(@$s);
}
return $dep;
}
1;
obs-build-20180831/Build/Rpmmd.pm 0000644 0001750 0001750 00000016545 13350372713 014733 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Rpmmd;
use strict;
use Build::Rpm;
use XML::Parser;
sub generic_parse {
my ($how, $in, $res, %options) = @_;
$res ||= [];
my @cursor = ([undef, $how, undef, $res, undef, \%options]);
my $p = new XML::Parser(Handlers => {
Start => sub {
my ($p, $el) = @_;
my $h = $cursor[-1]->[1];
return unless exists $h->{$el};
$h = $h->{$el};
push @cursor, [$el, $h];
$cursor[-1]->[2] = '' if $h->{'_text'};
$h->{'_start'}->($h, \@cursor, @_) if exists $h->{'_start'};
},
End => sub {
my ($p, $el) = @_;
if ($cursor[-1]->[0] eq $el) {
my $h = $cursor[-1]->[1];
$h->{'_end'}->($h, \@cursor, @_) if exists $h->{'_end'};
pop @cursor;
}
},
Char => sub {
my ($p, $text) = @_;
$cursor[-1]->[2] .= $text if defined $cursor[-1]->[2];
},
}, ErrorContext => 2);
if (ref($in)) {
$p->parse($in);
} else {
$p->parsefile($in);
}
return $res;
}
sub generic_store_text {
my ($h, $c, $p, $el) = @_;
my $data = $c->[0]->[4];
$data->{$h->{'_tag'}} = $c->[-1]->[2] if defined $c->[-1]->[2];
}
sub generic_store_attr {
my ($h, $c, $p, $el, %attr) = @_;
my $data = $c->[0]->[4];
$data->{$h->{'_tag'}} = $attr{$h->{'_attr'}} if defined $attr{$h->{'_attr'}};
}
sub generic_new_data {
my ($h, $c, $p, $el, %attr) = @_;
$c->[0]->[4] = {};
generic_store_attr(@_) if $h->{'_attr'};
}
sub generic_add_result {
my ($h, $c, $p, $el) = @_;
my $data = $c->[0]->[4];
return unless $data;
my $res = $c->[0]->[3];
if (ref($res) eq 'CODE') {
$res->($data);
} else {
push @$res, $data;
}
undef $c->[0]->[4];
}
my $repomdparser = {
repomd => {
data => {
_start => \&generic_new_data,
_attr => 'type',
_tag => 'type',
_end => \&generic_add_result,
location => { _start => \&generic_store_attr, _attr => 'href', _tag => 'location'},
checksum => { _start => \&generic_store_attr, _attr => 'type', _tag => 'checksum', _text => 1, _end => \&primary_handle_checksum },
size => { _text => 1, _end => \&generic_store_text, _tag => 'size'},
},
},
};
my $primaryparser = {
metadata => {
'package' => {
_start => \&generic_new_data,
_attr => 'type',
_tag => 'type',
_end => \&primary_add_result,
name => { _text => 1, _end => \&generic_store_text, _tag => 'name' },
arch => { _text => 1, _end => \&generic_store_text, _tag => 'arch' },
version => { _start => \&primary_handle_version },
checksum => { _start => \&generic_store_attr, _attr => 'type', _tag => 'checksum', _text => 1, _end => \&primary_handle_checksum },
'time' => { _start => \&primary_handle_time },
format => {
'rpm:provides' => { 'rpm:entry' => { _start => \&primary_handle_dep , _tag => 'provides' }, },
'rpm:requires' => { 'rpm:entry' => { _start => \&primary_handle_dep , _tag => 'requires' }, },
'rpm:conflicts' => { 'rpm:entry' => { _start => \&primary_handle_dep , _tag => 'conflicts' }, },
'rpm:recommends' => { 'rpm:entry' => { _start => \&primary_handle_dep , _tag => 'recommends' }, },
'rpm:suggests' => { 'rpm:entry' => { _start => \&primary_handle_dep , _tag => 'suggests' }, },
'rpm:supplements' => { 'rpm:entry' => { _start => \&primary_handle_dep , _tag => 'supplements' }, },
'rpm:enhances' => { 'rpm:entry' => { _start => \&primary_handle_dep , _tag => 'enhances' }, },
'rpm:obsoletes' => { 'rpm:entry' => { _start => \&primary_handle_dep , _tag => 'obsoletes' }, },
'rpm:buildhost' => { _text => 1, _end => \&generic_store_text, _tag => 'buildhost' },
'rpm:sourcerpm' => { _text => 1, _end => \&primary_handle_sourcerpm , _tag => 'source' },
### currently commented out, as we ignore file provides in expanddeps
# file => { _text => 1, _end => \&primary_handle_file_end, _tag => 'provides' },
},
location => { _start => \&generic_store_attr, _attr => 'href', _tag => 'location'},
},
},
};
sub primary_handle_sourcerpm {
my ($h, $c, $p, $el, %attr) = @_;
my $data = $c->[0]->[4];
return unless defined $c->[-1]->[2];
$c->[-1]->[2] =~ s/-[^-]*-[^-]*\.[^\.]*\.rpm$//;
$data->{$h->{'_tag'}} = $c->[-1]->[2];
}
sub primary_handle_version {
my ($h, $c, $p, $el, %attr) = @_;
my $data = $c->[0]->[4];
$data->{'epoch'} = $attr{'epoch'} if $attr{'epoch'};
$data->{'version'} = $attr{'ver'};
$data->{'release'} = $attr{'rel'};
}
sub primary_handle_time {
my ($h, $c, $p, $el, %attr) = @_;
my $data = $c->[0]->[4];
$data->{'filetime'} = $attr{'file'} if $attr{'file'};
$data->{'buildtime'} = $attr{'build'} if $attr{'build'};
}
sub primary_handle_checksum {
my ($h, $c, $p, $el) = @_;
my $data = $c->[0]->[4];
my $type = lc(delete($data->{$h->{'_tag'}}) || '');
$type = 'sha1' if $type eq 'sha';
if ($type eq 'md5' || $type eq 'sha1' || $type eq 'sha256' || $type eq 'sha512') {
$data->{$h->{'_tag'}} = "$type:$c->[-1]->[2]" if defined $c->[-1]->[2];
}
}
sub primary_handle_file_end {
my ($h, $c, $p, $el) = @_;
primary_handle_dep($h, $c, $p, $el, 'name', $c->[-1]->[2]);
}
my %flagmap = ( EQ => '=', LE => '<=', GE => '>=', GT => '>', LT => '<', NE => '!=' );
sub primary_handle_dep {
my ($h, $c, $p, $el, %attr) = @_;
my $dep = $attr{'name'};
return if $dep =~ /^rpmlib\(/;
if(exists $attr{'flags'}) {
my $evr = $attr{'ver'};
return unless defined($evr) && exists($flagmap{$attr{'flags'}});
$evr = "$attr{'epoch'}:$evr" if $attr{'epoch'};
$evr .= "-$attr{'rel'}" if defined $attr{'rel'};
$dep .= " $flagmap{$attr{'flags'}} $evr";
}
$dep = Build::Rpm::testcaseformat($dep) if ($dep =~ /^\(/) && ($c->[0]->[5] || {})->{'testcaseformat'};
my $data = $c->[0]->[4];
push @{$data->{$h->{'_tag'}}}, $dep;
}
sub primary_add_result {
my ($h, $c, $p, $el) = @_;
my $options = $c->[0]->[5] || {};
my $data = $c->[0]->[4];
if ($options->{'addselfprovides'} && defined($data->{'name'}) && defined($data->{'version'})) {
if (($data->{'arch'} || '') ne 'src' && ($data->{'arch'} || '') ne 'nosrc') {
my $evr = $data->{'version'};
$evr = "$data->{'epoch'}:$evr" if $data->{'epoch'};
$evr = "$evr-$data->{'release'}" if defined $data->{'release'};
my $s = "$data->{'name'} = $evr";
push @{$data->{'provides'}}, $s unless grep {$_ eq $s} @{$data->{'provides'} || []};
}
}
delete $data->{'checksum'} unless $options->{'withchecksum'};
return generic_add_result(@_);
}
sub parse_repomd {
return generic_parse($repomdparser, @_);
}
sub parse {
return generic_parse($primaryparser, @_);
}
1;
obs-build-20180831/Build/Docker.pm 0000644 0001750 0001750 00000016705 13350372713 015061 0 ustar alee alee ################################################################
#
# Copyright (c) 2017 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Docker;
use Build::SimpleXML;
use strict;
sub slurp {
my ($fn) = @_;
local *F;
return undef unless open(F, '<', $fn);
local $/ = undef; # Perl slurp mode
my $content = ;
close F;
return $content;
}
sub quote {
my ($str, $q, $vars) = @_;
if ($q ne "'" && $str =~ /\$/) {
$str =~ s/\$([a-zA-Z0-9_]+|\{([^\}]+)\})/join(' ', @{$vars->{$2 || $1} || []})/ge;
}
$str =~ s/([ \t\"\'\$\(\)])/sprintf("%%%02X", ord($1))/ge;
return $str;
}
sub addrepo {
my ($ret, $url) = @_;
unshift @{$ret->{'repo_urls'}}, $url;
if ($Build::Kiwi::urlmapper) {
my $prp = $Build::Kiwi::urlmapper->($url);
if (!$prp) {
$ret->{'error'} = "cannot map '$url' to obs";
return undef;
}
my ($projid, $repoid) = split('/', $prp, 2);
unshift @{$ret->{'path'}}, {'project' => $projid, 'repository' => $repoid};
return;
} else {
# this is just for testing purposes...
$url =~ s/^\/+$//;
$url =~ s/:\//:/g;
my @url = split('/', $url);
unshift @{$ret->{'path'}}, {'project' => $url[-2], 'repository' => $url[-1]} if @url >= 2;
}
return 1;
}
sub cmd_zypper {
my ($ret, @args) = @_;
# skip global options
shift @args while @args && $args[0] =~ /^-/;
return unless @args;
if ($args[0] eq 'in' || $args[0] eq 'install') {
shift @args;
while (@args && $args[0] =~ /^-/) {
shift @args if $args[0] =~ /^--(?:from|repo|type)$/ || $args[0] =~ /^-[tr]$/;
shift @args;
}
my @deps = grep {/^[a-zA-Z_0-9]/} @args;
s/^([^<=>]+)([<=>]+)/$1 $2 / for @deps;
push @{$ret->{'deps'}}, @deps;
} elsif ($args[0] eq 'ar' || $args[0] eq 'addrepo') {
shift @args;
while (@args && $args[0] =~ /^-/) {
shift @args if $args[0] =~ /^--(?:repo|type)$/ || $args[0] =~ /^-[rt]$/;
shift @args;
}
if (@args) {
my $path = $args[0];
$path =~ s/\/[^\/]*\.repo$//;
addrepo($ret, $path);
}
}
}
sub cmd_obs_pkg_mgr {
my ($ret, @args) = @_;
return unless @args;
if ($args[0] eq 'add_repo') {
shift @args;
addrepo($ret, $args[0]) if @args;
} elsif ($args[0] eq 'install') {
shift @args;
push @{$ret->{'deps'}}, @args;
}
}
sub cmd_dnf {
my ($ret, @args) = @_;
# skip global options
shift @args while @args && $args[0] =~ /^-/;
return unless @args;
if ($args[0] eq 'in' || $args[0] eq 'install') {
shift @args;
while (@args && $args[0] =~ /^-/) {
shift @args;
}
push @{$ret->{'deps'}}, grep {/^[a-zA-Z_0-9]/} @args;
}
}
sub cmd_apt_get {
my ($ret, @args) = @_;
shift @args while @args && $args[0] =~ /^-/;
return unless @args;
if ($args[0] eq 'install') {
shift @args;
push @{$ret->{'deps'}}, grep {/^[a-zA-Z_0-9]/} @args;
}
}
sub parse {
my ($cf, $fn) = @_;
my $basecontainer;
my $dockerfile_data = slurp($fn);
return { 'error' => 'could not open Dockerfile' } unless defined $dockerfile_data;
my @lines = split(/\r?\n/, $dockerfile_data);
my $ret = {
'name' => 'docker',
'deps' => [],
'path' => [],
'repo_urls' => [],
};
while (@lines) {
my $line = shift @lines;
$line =~ s/^\s+//;
if ($line =~ /^#/) {
if ($line =~ /^#!BuildTag:\s*(.*?)$/) {
my @tags = split(' ', $1);
push @{$ret->{'containertags'}}, @tags if @tags;
}
next;
}
# add continuation lines
while (@lines && $line =~ s/\\[ \t]*$//) {
shift @lines while @lines && $lines[0] =~ /^\s*#/;
$line .= shift(@lines) if @lines;
}
$line =~ s/^\s+//;
$line =~ s/\s+$//;
next unless $line;
my ($cmd, @args);
($cmd, $line) = split(' ', $line, 2);
$cmd = uc($cmd);
my $vars = {};
# split line into args
$line =~ s/%/%25/g;
$line =~ s/\\(.)/sprintf("%%%02X", ord($1))/ge;
while ($line =~ /([\"\'])/) {
my $q = $1;
last unless $line =~ s/$q(.*?)$q/quote($1, $q, $vars)/e;
}
if ($line =~ /\$/) {
$line =~ s/\$([a-zA-Z0-9_]+|\{([^\}]+)\})/join(' ', @{$vars->{$2 || $1} || []})/ge;
}
@args = split(/[ \t]+/, $line);
s/%([a-fA-F0-9]{2})/chr(hex($1))/ge for @args;
if ($cmd eq 'FROM') {
if (@args && !$basecontainer) {
$basecontainer = $args[0];
$basecontainer .= ':latest' unless $basecontainer =~ /:[^:\/]+$/;
}
} elsif ($cmd eq 'RUN') {
$line =~ s/#.*//; # get rid of comments
for my $l (split(/(?:\||\|\||\&|\&\&|;|\)|\()/, $line)) {
$l =~ s/^\s+//;
$l =~ s/\s+$//;
@args = split(/[ \t]+/, $l);
s/%([a-fA-F0-9]{2})/chr(hex($1))/ge for @args;
next unless @args;
my $rcmd = shift @args;
if ($rcmd eq 'zypper') {
cmd_zypper($ret, @args);
} elsif ($rcmd eq 'yum' || $rcmd eq 'dnf') {
cmd_dnf($ret, @args);
} elsif ($rcmd eq 'apt-get') {
cmd_apt_get($ret, @args);
} elsif ($rcmd eq 'obs_pkg_mgr') {
cmd_obs_pkg_mgr($ret, @args);
}
}
}
}
push @{$ret->{'deps'}}, "container:$basecontainer" if $basecontainer;
return $ret;
}
sub showcontainerinfo {
my $disturl;
(undef, $disturl) = splice(@ARGV, 0, 2) if @ARGV > 2 && $ARGV[0] eq '--disturl';
my ($fn, $image, $taglist, $annotationfile) = @ARGV;
local $Build::Kiwi::urlmapper = sub { return $_[0] };
my $d = {};
$d = parse({}, $fn) if $fn;
die("$d->{'error'}\n") if $d->{'error'};
$image =~ s/.*\/// if defined $image;
my @tags = split(' ', $taglist);
for (@tags) {
$_ .= ':latest' unless /:[^:\/]+$/;
}
@tags = map {"\"$_\""} @tags;
my @repos = map {"{ \"url\": \"$_\" }"} @{$d->{'repo_urls'} || []};
if ($annotationfile) {
my $annotation = slurp($annotationfile);
$annotation = Build::SimpleXML::parse($annotation) if $annotation;
$annotation = $annotation && ref($annotation) eq 'HASH' ? $annotation->{'annotation'} : undef;
$annotation = $annotation && ref($annotation) eq 'ARRAY' ? $annotation->[0] : undef;
my $annorepos = $annotation && ref($annotation) eq 'HASH' ? $annotation->{'repo'} : undef;
$annorepos = undef unless $annorepos && ref($annorepos) eq 'ARRAY';
for my $annorepo (@{$annorepos || []}) {
next unless $annorepo && ref($annorepo) eq 'HASH' && $annorepo->{'url'};
push @repos, "{ \"url\": \"$annorepo->{'url'}\" }";
}
}
my $buildtime = time();
print "{\n";
print " \"tags\": [ ".join(', ', @tags)." ]";
print ",\n \"repos\": [ ".join(', ', @repos)." ]" if @repos;
print ",\n \"file\": \"$image\"" if defined $image;
print ",\n \"disturl\": \"$disturl\"" if defined $disturl;
print ",\n \"buildtime\": $buildtime";
print "\n}\n";
}
sub showtags {
my ($fn) = @ARGV;
local $Build::Kiwi::urlmapper = sub { return $_[0] };
my $d = {};
$d = parse({}, $fn) if $fn;
die("$d->{'error'}\n") if $d->{'error'};
print "$_\n" for @{$d->{'containertags'} || []};
}
1;
obs-build-20180831/Build/LiveBuild.pm 0000644 0001750 0001750 00000005521 13350372713 015523 0 ustar alee alee ################################################################
#
# Copyright (c) 2014 Brocade Communications Systems, Inc.
# Author: Jan Blunck
#
# This file is part of build.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
#################################################################
package Build::LiveBuild;
use strict;
eval { require Archive::Tar; };
*Archive::Tar::new = sub {die("Archive::Tar is not available\n")} unless defined &Archive::Tar::new;
sub filter {
my ($content) = @_;
return '' unless defined $content;
$content =~ s/^#.*$//mg;
$content =~ s/^!.*$//mg;
$content =~ s/^\s*//mg;
return $content;
}
sub parse_package_list {
my ($content) = @_;
my @packages = split /\n/, filter($content);
return @packages;
};
sub parse_archive {
my ($content) = @_;
my @repos;
my @lines = split /\n/, filter($content);
for (@lines) {
next if /^deb-src /;
die("bad path using not obs:/ URL: $_\n") unless $_ =~ /^deb\s+obs:\/\/\/?([^\s\/]+)\/([^\s\/]+)\/?\s+.*$/;
push @repos, "$1/$2";
}
return @repos;
}
sub unify {
my %h = map {$_ => 1} @_;
return grep(delete($h{$_}), @_);
}
sub parse {
my ($config, $filename, @args) = @_;
my $ret = {};
# check that filename is a tar
my $tar = Archive::Tar->new;
unless($tar->read($filename)) {
warn("$filename: " . $tar->error . "\n");
$ret->{'error'} = "$filename: " . $tar->error;
return $ret;
}
# check that directory layout matches live-build directory structure
for my $file ($tar->list_files('')) {
next unless $file =~ /^(.*\/)?config\/archives\/.*\.list.*/;
warn("$filename: config/archives/*.list* files not allowed!\n");
$ret->{'error'} = "$filename: config/archives/*.list* files not allowed!";
return $ret;
}
# always require the list of packages required by live-boot for
# bootstrapping the target distribution image (e.g. with debootstrap)
my @packages = ( 'live-build-desc' );
for my $file ($tar->list_files('')) {
next unless $file =~ /^(.*\/)?config\/package-lists\/.*\.list.*/;
push @packages, parse_package_list($tar->get_content($file));
}
($ret->{'name'} = $filename) =~ s/\.[^.]+$//;
$ret->{'deps'} = [ unify(@packages) ];
return $ret;
}
1;
obs-build-20180831/Build/SimpleXML.pm 0000644 0001750 0001750 00000011154 13350372713 015455 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2016 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::SimpleXML;
use strict;
# very simple xml parser, just good enough to parse kiwi and _service files...
# can't use standard XML parsers, unfortunatelly, as the build script
# must not rely on external libraries
#
sub parse {
my ($xml, %opts) = @_;
my $record = $opts{'record'};
my $order = $opts{'order'};
my @nodestack;
my $node = {};
my $c = '';
my $xmllen = length($xml);
$xml =~ s/^\s*\<\?.*?\?\>//s;
while ($xml =~ /^(.*?)\//s;
next;
}
my $elstart = length($xml);
die("bad xml\n") unless $xml =~ /(.*?\>)/s;
my $tag = $1;
$xml = substr($xml, length($tag));
my $mode = 0;
if ($tag =~ s/^\<\///s) {
chop $tag;
$mode = 1; # end
} elsif ($tag =~ s/\/\>$//s) {
$mode = 2; # start & end
$tag = substr($tag, 1);
} else {
$tag = substr($tag, 1);
chop $tag;
}
my @tag = split(/(=(?:\"[^\"]*\"|\'[^\']*\'|[^\"\s]*))?\s+/, "$tag ");
$tag = shift @tag;
shift @tag;
push @tag, undef if @tag & 1;
my %atts = @tag;
for (values %atts) {
next unless defined $_;
s/^=\"([^\"]*)\"$/=$1/s or s/^=\'([^\']*)\'$/=$1/s;
s/^=//s;
s/<//g;
s/&/&/g;
s/'/\'/g;
s/"/\"/g;
}
if ($mode == 0 || $mode == 2) {
my $n = {};
if ($record) {
$n->{'_start'} = $xmllen - $elstart;
$n->{'_end'} = $xmllen - length($xml) if $mode == 2;
}
if ($order) {
push @{$node->{'_order'}}, $tag;
push @{$n->{'_order'}}, (splice(@tag, 0, 2))[0] while @tag;
}
push @{$node->{$tag}}, $n;
$n->{$_} = $atts{$_} for sort keys %atts;
if ($mode == 0) {
push @nodestack, [ $tag, $node, $c ];
$c = '';
$node = $n;
}
} else {
die("element '$tag' closes without open\n") unless @nodestack;
die("element '$tag' closes, but I expected '$nodestack[-1]->[0]'\n") unless $nodestack[-1]->[0] eq $tag;
$c =~ s/^\s*//s;
$c =~ s/\s*$//s;
$node->{'_content'} = $c if $c ne '';
$node->{'_end'} = $xmllen - length($xml) if $record;
$node = $nodestack[-1]->[1];
$c = $nodestack[-1]->[2];
pop @nodestack;
}
}
$c .= $xml;
$c =~ s/^\s*//s;
$c =~ s/\s*$//s;
$node->{'_content'} = $c if $c ne '';
return $node;
}
sub unparse_keys {
my ($d) = @_;
my @k = grep {$_ ne '_start' && $_ ne '_end' && $_ ne '_order' && $_ ne '_content'} sort keys %$d;
return @k unless $d->{'_order'};
my %k = map {$_ => 1} @k;
my @ko;
for (@{$d->{'_order'}}) {
push @ko, $_ if delete $k{$_};
}
return (@ko, grep {$k{$_}} @k);
}
sub unparse_escape {
my ($d) = @_;
$d =~ s/&/&/sg;
$d =~ s/</sg;
$d =~ s/>/>/sg;
$d =~ s/"/"/sg;
return $d;
}
sub unparse {
my ($d, %opts) = @_;
my $r = '';
my $indent = $opts{'ugly'} ? '' : $opts{'indent'} || '';
my $nl = $opts{'ugly'} ? '' : "\n";
my @k = unparse_keys($d);
my @e = grep {ref($d->{$_}) ne ''} @k;
for my $e (@e) {
my $en = unparse_escape($e);
my $de = $d->{$e};
$de = [ $de ] unless ref($de) eq 'ARRAY';
for my $se (@$de) {
my @sk = unparse_keys($se);
my @sa = grep {ref($se->{$_}) eq ''} @sk;
my @se = grep {ref($se->{$_}) ne ''} @sk;
$r .= "$indent<$en";
for my $sa (@sa) {
$r .= " ".unparse_escape($sa);
$r .= '="'.unparse_escape($se->{$sa}).'"' if defined $se->{$sa};
}
$r .= ">";
$r .= unparse_escape($se->{'_content'}) if defined $se->{'_content'};
$r .= $nl . unparse($se, %opts, 'indent' => " $indent") . "$indent" if @se;
$r .= "$en>$nl";
}
}
return $r;
}
1;
obs-build-20180831/Build/Zypp.pm 0000644 0001750 0001750 00000004650 13350372713 014610 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Zypp;
use strict;
our $root = '';
sub parsecfg {
my ($repocfg, $reponame, $allrepos) = @_;
local *REPO;
open(REPO, '<', "$root/etc/zypp/repos.d/$repocfg") or return undef;
my $name;
my $repo = {};
while () {
chomp;
next if /^\s*#/;
s/\s+$//;
if (/^\[(.+)\]/) {
if ($allrepos && defined($name)) {
$repo->{'description'} = $repo->{'name'} if defined $repo->{'name'};
$repo->{'name'} = $name;
push @$allrepos, $repo;
undef $name;
$repo = {};
}
last if defined $name;
$name = $1 if !defined($reponame) || $reponame eq $1;
} elsif (defined($name)) {
my ($key, $value) = split(/=/, $_, 2);
$repo->{$key} = $value if defined $key;
}
}
close(REPO);
return undef unless defined $name;
$repo->{'description'} = $repo->{'name'} if defined $repo->{'name'};
$repo->{'name'} = $name;
push @$allrepos, $repo if $allrepos;
return $repo;
}
sub repofiles {
local *D;
return () unless opendir(D, "/etc/zypp/repos.d");
my @r = grep {!/^\./ && /.repo$/} readdir(D);
closedir D;
return sort(@r);
}
sub parseallrepos {
my @r;
for my $r (repofiles()) {
parsecfg($r, undef, \@r);
}
return @r;
}
sub parserepo($) {
my ($reponame) = @_;
# first try matching .repo file
if (-e "$root/etc/zypp/repos.d/$reponame.repo") {
my $repo = parsecfg("$reponame.repo", $reponame);
return $repo if $repo;
}
# then try all repo files
for my $r (repofiles()) {
my $repo = parsecfg($r, $reponame);
return $repo if $repo;
}
die("could not find repo '$reponame'\n");
}
1;
# vim: sw=2
obs-build-20180831/Build/Mdkrepo.pm 0000644 0001750 0001750 00000007125 13350372713 015247 0 ustar alee alee ################################################################
#
# Copyright (c) 2015 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Mdkrepo;
use strict;
#use Data::Dumper;
sub addpkg {
my ($res, $data, $options) = @_;
if ($options->{'addselfprovides'} && defined($data->{'name'}) && defined($data->{'version'})) {
if (($data->{'arch'} || '') ne 'src' && ($data->{'arch'} || '') ne 'nosrc') {
my $evr = $data->{'version'};
$evr = "$data->{'epoch'}:$evr" if $data->{'epoch'};
$evr = "$evr-$data->{'release'}" if defined $data->{'release'};
my $s = "$data->{'name'} = $evr";
push @{$data->{'provides'}}, $s unless grep {$_ eq $s} @{$data->{'provides'} || []};
}
}
if (ref($res) eq 'CODE') {
$res->($data);
} else {
push @$res, $data;
}
}
sub parsedeps {
my ($d) = @_;
my @d = split('@', $d);
for (@d) {
s/\[\*\]//s;
s/\[(.*)\]$/ $1/s;
s/ == / = /;
}
return \@d;
}
sub parse {
my ($in, $res, %options) = @_;
$res ||= [];
my $fd;
if (ref($in)) {
$fd = $in;
} else {
if ($in =~ /\.[gc]z$/) {
# we need to probe, as mageia uses xz for compression
open($fd, '<', $in) || die("$in: $!\n");
my $probe;
sysread($fd, $probe, 5);
close($fd);
if ($probe && $probe eq "\xFD7zXZ") {
open($fd, '-|', "xzdec", "-dc", $in) || die("$in: $!\n");
} else {
open($fd, '-|', "gzip", "-dc", $in) || die("$in: $!\n");
}
} else {
open($fd, '<', $in) || die("$in: $!\n");
}
}
my $s = {};
while (<$fd>) {
chomp;
if (/^\@summary\@/) {
$s->{'summary'} = substr($_, 9);
} elsif (/^\@provides\@/) {
$s->{'provides'} = parsedeps(substr($_, 10));
} elsif (/^\@requires\@/) {
$s->{'requires'} = parsedeps(substr($_, 10));
} elsif (/^\@suggests\@/) {
$s->{'suggests'} = parsedeps(substr($_, 10));
} elsif (/^\@recommends\@/) {
$s->{'recommends'} = parsedeps(substr($_, 12));
} elsif (/^\@obsoletes\@/) {
$s->{'obsoletes'} = parsedeps(substr($_, 11));
} elsif (/^\@conflicts\@/) {
$s->{'conflicts'} = parsedeps(substr($_, 11));
} elsif (/^\@info\@/) {
$s ||= {};
my @s = split('@', substr($_, 6));
$s->{'location'} = "$s[0].rpm";
my $arch;
if ($s[0] =~ /\.([^\.]+)$/) {
$arch = $1;
$s[0] =~ s/\.[^\.]+$//;
}
$s->{'epoch'} = $s[1] if $s[1];
$s[0] =~ s/-\Q$s[4]\E[^-]*$//s if defined($s[4]) && $s[4] ne ''; # strip disttag
$s[0] .= ":$s[5]" if defined($s[5]) && $s[5] ne ''; # add distepoch
$s->{'arch'} = $arch || 'noarch';
if ($s[0] =~ /^(.*)-([^-]+)-([^-]+)$/s) {
($s->{'name'}, $s->{'version'}, $s->{'release'}) = ($1, $2, $3);
# fake source entry for now...
$s->{'source'} = $s->{'name'} if $s->{'arch'} ne 'src' && $s->{'arch'} ne 'nosrc';
addpkg($res, $s, \%options);
}
$s = {};
}
}
return $res;
}
1;
obs-build-20180831/Build/Kiwi.pm 0000644 0001750 0001750 00000050555 13350372713 014556 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Kiwi;
use strict;
use Build::SimpleXML;
our $bootcallback;
our $urlmapper;
our $repoextras = 0; # priority, flags, ...
sub unify {
my %h = map {$_ => 1} @_;
return grep(delete($h{$_}), @_);
}
sub expandFallBackArchs {
my ($fallbackArchXML, @archs) = @_;
my %fallbacks;
for (@{$fallbackArchXML->{'arch'} || []}) {
$fallbacks{$_->{'id'}} = $_->{'fallback'} if $_->{id} && $_->{'fallback'};
}
my @out;
while (@archs) {
push @out, shift @archs;
push @archs, delete $fallbacks{$out[-1]} if $fallbacks{$out[-1]};
}
return unify(@out);
}
# sles10 perl does not have the version.pm
# implement own hack
sub versionstring {
my ($str) = @_;
my $result = 0;
$result = $result * 100 + $_ for split (/\./, $str, 2);
return $result;
}
my $schemaversion56 = versionstring('5.6');
sub kiwiparse_product {
my ($kiwi, $xml, $arch, $buildflavor) = @_;
my $ret = {};
my @repos;
my %repoprio; # XXX: unused
my @packages;
my @requiredarch;
my @badarch;
my $obsexclusivearch;
my $obsexcludearch;
$obsexclusivearch = $1 if $xml =~ /^\s*\s*$/im;
$obsexcludearch = $1 if $xml =~ /^\s*\s*$/im;
$ret->{'name'} = $kiwi->{'name'} if $kiwi->{'name'};
$ret->{'filename'} = $kiwi->{'name'} if $kiwi->{'name'};
my $description = (($kiwi->{'description'} || [])->[0]) || {};
if (!$ret->{'name'} && $description->{'specification'}) {
$ret->{'name'} = $description->{'specification'}->[0]->{'_content'};
}
# parse the preferences section
my $preferences = $kiwi->{'preferences'} || [];
die("products must have exactly one preferences element\n") unless @$preferences == 1;
# take default version setting
if ($preferences->[0]->{'version'}) {
$ret->{'version'} = $preferences->[0]->{'version'}->[0]->{'_content'};
}
die("products must have exactly one type element in the preferences\n") unless @{$preferences->[0]->{'type'} || []} == 1;
my $preftype = $preferences->[0]->{'type'}->[0];
if (defined $preftype->{'image'}) {
# for kiwi 4.1 and 5.x
die("products must use type 'product'\n") unless $preftype->{'image'} eq 'product';
} else {
# for kiwi 3.8 and before
die("products must use type 'product'\n") unless $preftype->{'_content'} eq 'product';
}
push @packages, "kiwi-filesystem:$preftype->{'filesystem'}" if $preftype->{'filesystem'};
die("boot type not supported in products\n") if defined $preftype->{'boot'};
my $instsource = ($kiwi->{'instsource'} || [])->[0];
die("products must have an instsource element\n") unless $instsource;
# get repositories
for my $repository (sort {$a->{priority} <=> $b->{priority}} @{$instsource->{'instrepo'} || []}) {
my $kiwisource = ($repository->{'source'} || [])->[0];
if ($kiwisource->{'path'} eq 'obsrepositories:/') {
# special case, OBS will expand it.
push @repos, '_obsrepositories';
next;
}
if ($kiwisource->{'path'} =~ /^obs:\/\/\/?([^\/]+)\/([^\/]+)\/?$/) {
push @repos, "$1/$2";
} else {
my $prp;
$prp = $urlmapper->($kiwisource->{'path'}) if $urlmapper;
die("instsource repo url not using obs:/ scheme: $kiwisource->{'path'}\n") unless $prp;
push @repos, $prp;
}
}
$ret->{'sourcemedium'} = -1;
$ret->{'debugmedium'} = -1;
if ($instsource->{'productoptions'}) {
my $productoptions = $instsource->{'productoptions'}->[0] || {};
for my $po (@{$productoptions->{'productvar'} || []}) {
$ret->{'drop_repository'} = $po->{'_content'} if $po->{'name'} eq 'DROP_REPOSITORY';
$ret->{'version'} = $po->{'_content'} if $po->{'name'} eq 'VERSION';
}
for my $po (@{$productoptions->{'productoption'} || []}) {
$ret->{'sourcemedium'} = $po->{'_content'} if $po->{'name'} eq 'SOURCEMEDIUM';
$ret->{'debugmedium'} = $po->{'_content'} if $po->{'name'} eq 'DEBUGMEDIUM';
}
}
if ($instsource->{'architectures'}) {
my $architectures = $instsource->{'architectures'}->[0] || {};
for my $ra (@{$architectures->{'requiredarch'} || []}) {
push @requiredarch, $ra->{'ref'} if defined $ra->{'ref'};
}
}
# Find packages and possible additional required architectures
my @additionalarchs;
my @pkgs;
push @pkgs, @{$instsource->{'metadata'}->[0]->{'repopackage'} || []} if $instsource->{'metadata'};
push @pkgs, @{$instsource->{'repopackages'}->[0]->{'repopackage'} || []} if $instsource->{'repopackages'};
@pkgs = unify(@pkgs);
for my $package (@pkgs) {
# filter packages, which are not targeted for the wanted plattform
if ($package->{'arch'}) {
my $valid;
for my $ma (@requiredarch) {
for my $pa (split(',', $package->{'arch'})) {
$valid = 1 if $ma eq $pa;
}
}
next unless $valid;
}
# not nice, but optimizes our build dependencies
# FIXME: design a real blacklist option in kiwi
if ($package->{'onlyarch'} && $package->{'onlyarch'} eq 'skipit') {
push @packages, "-$package->{'name'}";
next;
}
push @packages, "-$package->{'replaces'}" if $package->{'replaces'};
# we need this package
push @packages, $package->{'name'};
# find the maximal superset of possible required architectures
push @additionalarchs, split(',', $package->{'addarch'}) if $package->{'addarch'};
push @additionalarchs, split(',', $package->{'onlyarch'}) if $package->{'onlyarch'};
}
@requiredarch = unify(@requiredarch, @additionalarchs);
#### FIXME: kiwi files have no informations where to get -32bit packages from
push @requiredarch, "i586" if grep {/^ia64/} @requiredarch;
push @requiredarch, "i586" if grep {/^x86_64/} @requiredarch;
push @requiredarch, "ppc" if grep {/^ppc64/} @requiredarch;
push @requiredarch, "s390" if grep {/^s390x/} @requiredarch;
@requiredarch = expandFallBackArchs($instsource->{'architectures'}->[0], @requiredarch);
push @packages, "kiwi-packagemanager:instsource";
push @requiredarch, split(' ', $obsexclusivearch) if $obsexclusivearch;
push @badarch , split(' ', $obsexcludearch) if $obsexcludearch;
$ret->{'exclarch'} = [ unify(@requiredarch) ] if @requiredarch;
$ret->{'badarch'} = [ unify(@badarch) ] if @badarch;
$ret->{'deps'} = [ unify(@packages) ];
$ret->{'path'} = [ unify(@repos) ];
$ret->{'imagetype'} = [ 'product' ];
for (@{$ret->{'path'} || []}) {
my @s = split('/', $_, 2);
$_ = {'project' => $s[0], 'repository' => $s[1]};
$_->{'priority'} = $repoprio{"$s[0]/$s[1]"} if $repoextras && defined $repoprio{"$s[0]/$s[1]"};
}
return $ret;
}
sub kiwiparse {
my ($xml, $arch, $buildflavor, $count) = @_;
$count ||= 0;
die("kiwi config inclusion depth limit reached\n") if $count++ > 10;
my $kiwi = Build::SimpleXML::parse($xml);
die("not a kiwi config\n") unless $kiwi && $kiwi->{'image'};
$kiwi = $kiwi->{'image'}->[0];
# check if this is a product, we currently test for the 'instsource' element
return kiwiparse_product($kiwi, $xml, $arch, $buildflavor) if $kiwi->{'instsource'};
my $ret = {};
my @types;
my @repos;
my @imagerepos;
my @bootrepos;
my @containerrepos;
my @packages;
my @extrasources;
my $obsexclusivearch;
my $obsexcludearch;
my $obsprofiles;
$obsexclusivearch = $1 if $xml =~ /^\s*\s*$/im;
$obsexcludearch = $1 if $xml =~ /^\s*\s*$/im;
$obsprofiles = $1 if $xml =~ /^\s*\s*$/im;
if ($obsprofiles) {
$obsprofiles = [ grep {defined($_)} map {$_ eq '@BUILD_FLAVOR@' ? $buildflavor : $_} split(' ', $obsprofiles) ];
}
my $schemaversion = $kiwi->{'schemaversion'} ? versionstring($kiwi->{'schemaversion'}) : 0;
$ret->{'name'} = $kiwi->{'name'} if $kiwi->{'name'};
$ret->{'filename'} = $kiwi->{'name'} if $kiwi->{'name'};
my $description = (($kiwi->{'description'} || [])->[0]) || {};
if (!$ret->{'name'} && $description->{'specification'}) {
$ret->{'name'} = $description->{'specification'}->[0]->{'_content'};
}
# usedprofiles also include direct wanted profile targets and indirect required profiles
my %usedprofiles;
# obsprofiles arch filtering
if ($obsprofiles && $arch && $kiwi->{'profiles'} && $kiwi->{'profiles'}->[0]->{'profile'}) {
my %obsprofiles = map {$_ => 1} @$obsprofiles;
for my $prof (@{$kiwi->{'profiles'}[0]->{'profile'}}) {
next unless $prof->{'name'} && exists $obsprofiles{$prof->{'name'}};
my $valid;
if ($prof->{'arch'}) {
my $ma = $arch;
$ma =~ s/i[456]86/i386/;
for my $pa (split(",", $prof->{'arch'})) {
$pa =~ s/i[456]86/i386/;
$valid = 1 if $ma eq $pa;
}
} else {
$valid = 1;
}
if ($valid) {
$obsprofiles{$prof->{'name'}} = 2;
} elsif ($obsprofiles{$prof->{'name'}} == 1) {
$obsprofiles{$prof->{'name'}} = 0;
}
}
$obsprofiles = [ grep {$obsprofiles{$_}} @$obsprofiles ];
for my $prof (@{$kiwi->{'profiles'}[0]->{'profile'}}) {
next unless $obsprofiles{$prof->{'name'}};
$usedprofiles{$prof->{'name'}} = 1;
for my $req (@{$prof->{'requires'}}) {
$usedprofiles{$req->{'profile'}} = 1;
}
}
}
# take default version setting
my $preferences = ($kiwi->{'preferences'} || []);
if ($preferences->[0]->{'version'}) {
$ret->{'version'} = $preferences->[0]->{'version'}->[0]->{'_content'};
}
my $containerconfig;
for my $pref (@{$preferences || []}) {
if ($obsprofiles && $pref->{'profiles'}) {
next unless grep {$usedprofiles{$_}} split(",", $pref->{'profiles'});
}
for my $type (@{$pref->{'type'} || []}) {
next unless @{$pref->{'type'}} == 1 || !$type->{'optional'};
if (defined $type->{'image'}) {
# for kiwi 4.1 and 5.x
push @types, $type->{'image'};
push @packages, "kiwi-image:$type->{'image'}" if $schemaversion >= $schemaversion56;
} else {
# for kiwi 3.8 and before
push @types, $type->{'_content'};
}
# save containerconfig so that we can retrievethe tag
$containerconfig = $type->{'containerconfig'}->[0] if $type->{'containerconfig'};
# add derived container dependency
if ($type->{'derived_from'}) {
my $derived = $type->{'derived_from'};
my ($name, $prp);
if ($derived =~ /^obs:\/{1,3}([^\/]+)\/([^\/]+)\/(.*?)(?:#([^\#\/]+))?$/) {
$name = defined($4) ? "$3:$4" : "$3:latest";
$prp = "$1/$2";
} elsif ($derived =~ /^obsrepositories:\/{1,3}([^\/].*?)(?:#([^\#\/]+))?$/) {
$name = defined($2) ? "$1:$2" : "$1:latest";
} elsif ($derived =~ /^file:/) {
next; # just ignore and hope
} elsif ($derived =~ /^(.*)\/([^\/]+?)(?:#([^\#\/]+))?$/) {
my $url = $1;
$name = defined($3) ? "$2:$3" : "$2:latest";
$prp = $urlmapper->($url) if $urlmapper;
# try again with one element moved from url to name
if (!$prp && $derived =~ /^(.*)\/([^\/]+\/[^\/]+?)(?:#([^\#\/]+))?$/) {
$url = $1;
$name = defined($3) ? "$2:$3" : "$2:latest";
$prp = $urlmapper->($url) if $urlmapper;
}
undef $name unless $prp;
}
die("derived_from url not using obs:/ scheme: $derived\n") unless defined $name;
push @packages, "container:$name";
push @containerrepos, $prp if $prp;
}
push @packages, "kiwi-filesystem:$type->{'filesystem'}" if $type->{'filesystem'};
if (defined $type->{'boot'}) {
if ($type->{'boot'} =~ /^obs:\/\/\/?([^\/]+)\/([^\/]+)\/?$/) {
next unless $bootcallback;
my ($bootxml, $xsrc) = $bootcallback->($1, $2);
next unless $bootxml;
push @extrasources, $xsrc if $xsrc;
my $bret = kiwiparse($bootxml, $arch, $buildflavor, $count);
push @bootrepos, map {"$_->{'project'}/$_->{'repository'}"} @{$bret->{'path'} || []};
push @packages, @{$bret->{'deps'} || []};
push @extrasources, @{$bret->{'extrasource'} || []};
} else {
die("bad boot reference: $type->{'boot'}\n") unless $type->{'boot'} =~ /^([^\/]+)\/([^\/]+)$/;
push @packages, "kiwi-boot:$1";
}
}
}
}
die("image contains 'product' type\n") if grep {$_ eq 'product'} @types;
my $packman = $preferences->[0]->{'packagemanager'}->[0]->{'_content'} || '';
# calculate priority for sorting
for (@{$kiwi->{'repository'} || []}) {
$_->{'sortprio'} = 0;
if (defined($_->{'priority'})) {
$_->{'sortprio'} = $packman eq 'smart' ? $_->{'priority'} : 99 - $_->{'priority'};
}
}
my @repositories = sort {$b->{'sortprio'} <=> $a->{'sortprio'}} @{$kiwi->{'repository'} || []};
my %repoprio;
for my $repository (@repositories) {
my $kiwisource = ($repository->{'source'} || [])->[0];
next unless $kiwisource; # huh?
next if $kiwisource->{'path'} eq '/var/lib/empty'; # grr
if ($repository->{'imageonly'} || $repository->{'imageinclude'}) {
# this repo will be configured in the image. Save so that we can write it into the containerinfo
my $imagerepo = { 'url' => $kiwisource->{'path'} };
$imagerepo->{'priority'} = $repository->{'sortprio'} if defined $repository->{'priority'};
push @imagerepos, $imagerepo;
}
next if $repository->{'imageonly'};
if ($kiwisource->{'path'} eq 'obsrepositories:/') {
push @repos, '_obsrepositories/';
next;
}
my $prp;
if ($kiwisource->{'path'} =~ /^obs:\/{1,3}([^\/]+)\/([^\/]+)\/?$/) {
$prp = "$1/$2";
} else {
$prp = $urlmapper->($kiwisource->{'path'}) if $urlmapper;
die("repo url not using obs:/ scheme: $kiwisource->{'path'}\n") unless $prp;
}
push @repos, $prp;
$repoprio{$prp} = $repository->{'sortprio'} if defined $repository->{'priority'};
}
# Find packages for the image
my @pkgs;
my $patterntype;
for my $packages (@{$kiwi->{'packages'}}) {
next if $packages->{'type'} && $packages->{'type'} ne 'image' && $packages->{'type'} ne 'bootstrap';
# we could skip the sections also when no profile is used,
# but don't to stay backward compatible
if ($obsprofiles && $packages->{'profiles'}) {
my @section_profiles = split(",", $packages->{'profiles'});
next unless grep {$usedprofiles{$_}} @section_profiles;
}
$patterntype ||= $packages->{'patternType'};
push @pkgs, @{$packages->{'package'}} if $packages->{'package'};
for my $pattern (@{$kiwi->{'namedCollection'} || []}) {
push @pkgs, { %$pattern, 'name' => "pattern()=$pattern->{'name'}" } if $pattern->{'name'};
}
for my $product (@{$kiwi->{'product'} || []}) {
push @pkgs, { %$product, 'name' => "product()=$product->{'name'}" } if $product->{'name'};
}
for my $pattern (@{$kiwi->{'opensusePatterns'} || []}) {
push @pkgs, { %$pattern, 'name' => "pattern()=$pattern->{'name'}" } if $pattern->{'name'};
}
for my $product (@{$kiwi->{'opensuseProduct'} || []}) {
push @pkgs, { %$product, 'name' => "product()=$product->{'name'}" } if $product->{'name'};
}
}
$patterntype ||= 'onlyRequired';
@pkgs = unify(@pkgs);
for my $package (@pkgs) {
# filter packages which are not targeted for the wanted plattform
if ($package->{'arch'}) {
my $valid;
my $ma = $arch;
$ma =~ s/i[456]86/i386/;
for my $pa (split(",", $package->{'arch'})) {
$pa =~ s/i[456]86/i386/;
$valid = 1 if $ma eq $pa;
}
next unless $valid;
}
# handle replaces as buildignore
push @packages, "-$package->{'replaces'}" if $package->{'replaces'};
# we need this package
push @packages, $package->{'name'};
}
push @packages, "kiwi-packagemanager:$packman";
push @packages, "--dorecommends--", "--dosupplements--" if $patterntype && $patterntype eq 'plusRecommended';
$ret->{'exclarch'} = [ unify(split(' ', $obsexclusivearch)) ] if $obsexclusivearch;
$ret->{'badarch'} = [ unify(split(' ', $obsexcludearch)) ] if $obsexcludearch;
$ret->{'deps'} = [ unify(@packages) ];
$ret->{'path'} = [ unify(@repos, @bootrepos) ];
$ret->{'containerpath'} = [ unify(@containerrepos) ] if @containerrepos;
$ret->{'imagetype'} = [ unify(@types) ];
$ret->{'extrasource'} = \@extrasources if @extrasources;
for (@{$ret->{'path'} || []}) {
my @s = split('/', $_, 2);
$_ = {'project' => $s[0], 'repository' => $s[1]};
$_->{'priority'} = $repoprio{"$s[0]/$s[1]"} if $repoextras && defined $repoprio{"$s[0]/$s[1]"};
}
for (@{$ret->{'containerpath'} || []}) {
my @s = split('/', $_, 2);
$_ = {'project' => $s[0], 'repository' => $s[1]};
}
$ret->{'imagerepos'} = \@imagerepos if @imagerepos;
if ($containerconfig) {
my $containername = $containerconfig->{'name'};
my $containertags = $containerconfig->{'tag'};
$containertags = [ $containertags ] if defined($containertags) && !ref($containertags);
if ($containertags && defined($containername)) {
for (@$containertags) {
$_ = "$containername:$_" unless /:/;
}
}
$containertags = undef if $containertags && !@$containertags;
$containertags = [ "$containername:latest" ] if defined($containername) && !$containertags;
$ret->{'container_tags'} = $containertags if $containertags;
}
if ($obsprofiles) {
if (@$obsprofiles) {
$ret->{'profiles'} = [ unify(@$obsprofiles) ];
} else {
$ret->{'exclarch'} = []; # all profiles excluded
}
}
return $ret;
}
sub parse {
my ($cf, $fn) = @_;
local *F;
open(F, '<', $fn) || die("$fn: $!\n");
my $xml = '';
1 while sysread(F, $xml, 4096, length($xml)) > 0;
close F;
$cf ||= {};
my $d;
eval { $d = kiwiparse($xml, ($cf->{'arch'} || ''), $cf->{'buildflavor'}, 0) };
if ($@) {
my $err = $@;
chomp $err;
return {'error' => $err};
}
return $d;
}
sub show {
my ($fn, $field, $arch, $buildflavor) = @ARGV;
local $urlmapper = sub { return $_[0] };
my $cf = {'arch' => $arch};
$cf->{'buildflavor'} = $buildflavor if defined $buildflavor;
my $d = parse($cf, $fn);
die("$d->{'error'}\n") if $d->{'error'};
if ($field eq 'profiles' && $d->{'exclarch'} && !@{$d->{'exclarch'}}) {
print "__excluded\n";
return;
}
my $x = $d->{$field};
$x = [ $x ] unless ref $x;
print "@$x\n";
}
sub showcontainerinfo {
my ($disturl, $arch, $buildflavor);
(undef, $disturl) = splice(@ARGV, 0, 2) if @ARGV > 2 && $ARGV[0] eq '--disturl';
(undef, $arch) = splice(@ARGV, 0, 2) if @ARGV > 2 && $ARGV[0] eq '--arch';
(undef, $buildflavor) = splice(@ARGV, 0, 2) if @ARGV > 2 && $ARGV[0] eq '--buildflavor';
my ($fn, $image) = @ARGV;
local $urlmapper = sub { return $_[0] };
my $cf = {};
$cf->{'arch'} = $arch if defined $arch;
$cf->{'buildflavor'} = $buildflavor if defined $buildflavor;
my $d = parse($cf, $fn);
die("$d->{'error'}\n") if $d->{'error'};
$image =~ s/.*\/// if defined $image;
my $release;
$release = $1 if $image =~ /.*-Build(\d+\.\d+).*/;
my @tags = map {"\"$_\""} @{$d->{'container_tags'} || []};
my @repos;
for my $repo (@{$d->{'imagerepos'} || []}) {
if (defined $repo->{'priority'}) {
push @repos, "{ \"url\": \"$repo->{'url'}\", \"priority\": $repo->{'priority'} }";
} else {
push @repos, "{ \"url\": \"$repo->{'url'}\" }";
}
}
my $buildtime = time();
print "{\n";
print " \"name\": \"$d->{'name'}\"";
print ",\n \"version\": \"$d->{'version'}\"" if defined $d->{'version'};
print ",\n \"release\": \"$release\"" if defined $release;
print ",\n \"tags\": [ ".join(', ', @tags)." ]" if @tags;
print ",\n \"repos\": [ ".join(', ', @repos)." ]" if @repos;
print ",\n \"file\": \"$image\"" if defined $image;
print ",\n \"disturl\": \"$disturl\"" if defined $disturl;
print ",\n \"buildtime\": $buildtime";
print "\n}\n";
}
# not implemented yet.
sub queryiso {
my ($handle, %opts) = @_;
return {};
}
sub queryhdrmd5 {
my ($bin) = @_;
die("Build::Kiwi::queryhdrmd5 unimplemented.\n");
}
1;
obs-build-20180831/Build/Deb.pm 0000644 0001750 0001750 00000032706 13350372713 014343 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Deb;
use strict;
use Digest::MD5;
my $have_zlib;
eval {
require Compress::Zlib;
$have_zlib = 1;
};
my %obs2debian = (
"i486" => "i386",
"i586" => "i386",
"i686" => "i386",
"ppc" => "powerpc",
"ppc64le" => "ppc64el",
"x86_64" => "amd64",
"armv4l" => "armel",
"armv5l" => "armel",
"armv6l" => "armel",
"armv7el" => "armel",
"armv7l" => "armhf",
"armv7hl" => "armhf",
"aarch64" => "arm64",
);
sub basearch {
my ($arch) = @_;
return 'all' if !defined($arch) || $arch eq 'noarch';
return $obs2debian{$arch} || $arch;
}
sub obsarch {
my ($arch) = @_;
return grep {$obs2debian{$_} eq $arch} sort keys %obs2debian;
}
sub parse {
my ($bconf, $fn) = @_;
my $ret;
my @control;
# get arch and os from macros
my ($arch, $os);
for (@{$bconf->{'macros'} || []}) {
$arch = $1 if /^%define _target_cpu (\S+)/;
$os = $1 if /^%define _target_os (\S+)/;
}
# map to debian names
$os = 'linux' if !defined($os);
$arch = basearch($arch);
if (ref($fn) eq 'ARRAY') {
@control = @$fn;
} else {
local *F;
if (!open(F, '<', $fn)) {
$ret->{'error'} = "$fn: $!";
return $ret;
}
@control = ;
close F;
chomp @control;
}
splice(@control, 0, 3) if @control > 3 && $control[0] =~ /^-----BEGIN/;
my $name;
my $version;
my @deps;
my @exclarch;
while (@control) {
my $c = shift @control;
last if $c eq ''; # new paragraph
my ($tag, $data) = split(':', $c, 2);
next unless defined $data;
$tag = uc($tag);
while (@control && $control[0] =~ /^\s/) {
$data .= "\n".substr(shift @control, 1);
}
$data =~ s/^\s+//s;
$data =~ s/\s+$//s;
if ($tag eq 'VERSION') {
$version = $data;
$version =~ s/-[^-]+$//;
} elsif ($tag eq 'ARCHITECTURE') {
my @archs = split('\s+', $data);
map { s/\Q$os\E-//; s/any-// } @archs;
next if grep { $_ eq "any" || $_ eq "all" } @archs;
@exclarch = map { obsarch($_) } @archs;
# unify
my %exclarch = map {$_ => 1} @exclarch;
@exclarch = sort keys %exclarch;
} elsif ($tag eq 'SOURCE') {
$name = $data;
} elsif ($tag eq 'BUILD-DEPENDS' || $tag eq 'BUILD-CONFLICTS' || $tag eq 'BUILD-IGNORE' ||
$tag eq 'BUILD-DEPENDS-INDEP' || $tag eq 'BUILD-DEPENDS-ARCH' || $tag eq 'BUILD-CONFLICTS-ARCH' ) {
my @d = split(/\s*,\s*/, $data);
for my $d (@d) {
my @alts = split('\s*\|\s*', $d);
my @needed;
for my $c (@alts) {
if ($c =~ /\s+<[^>]+>$/) {
my @build_profiles; # Empty for now
my $bad = 1;
while ($c =~ s/\s+<([^>]+)>$//) {
next if (!$bad);
my $list_valid = 1;
for my $term (split(/\s+/, $1)) {
my $isneg = ($term =~ s/^\!//);
my $profile_match = grep(/^$term$/, @build_profiles);
if (( $profile_match && $isneg) ||
(!$profile_match && !$isneg)) {
$list_valid = 0;
last;
}
}
$bad = 0 if ($list_valid);
}
next if ($bad);
}
if ($c =~ /^(.*?)\s*\[(.*)\]$/) {
$c = $1;
my $isneg = 0;
my $bad;
for my $q (split('[\s,]', $2)) {
$isneg = 1 if $q =~ s/^\!//;
$bad = 1 if !defined($bad) && !$isneg;
if ($isneg) {
if ($q eq $arch || $q eq 'any' || $q eq "$os-$arch" || $q eq "$os-any" || $q eq "any-$arch") {
$bad = 1;
last;
}
} elsif ($q eq $arch || $q eq 'any' || $q eq "$os-$arch" || $q eq "$os-any" || $q eq "any-$arch") {
$bad = 0;
}
}
next if ($bad);
}
$c =~ s/^([^:\s]*):(any|native)(.*)$/$1$3/;
push @needed, $c;
}
next unless @needed;
$d = join(' | ', @needed);
$d =~ s/ \(([^\)]*)\)/ $1/g;
$d =~ s/>>/>/g;
$d =~ s/<{'name'} = $name;
$ret->{'version'} = $version;
$ret->{'deps'} = \@deps;
$ret->{'exclarch'} = \@exclarch if @exclarch;
return $ret;
}
sub uncompress {
my ($data, $tool) = @_;
return $data if $tool eq 'cat';
return Compress::Zlib::memGunzip($data) if $have_zlib && $tool eq 'gunzip';
local (*TMP, *TMP2);
open(TMP, "+>", undef) or die("could not open tmpfile\n");
syswrite TMP, $data;
my $pid = open(TMP2, "-|");
die("fork: $!\n") unless defined $pid;
if (!$pid) {
open(STDIN, "<&TMP");
seek(STDIN, 0, 0); # these two lines are a workaround for a perl bug mixing up FD
sysseek(STDIN, 0, 0);
exec($tool);
die("$tool: $!\n");
}
close(TMP);
$data = '';
1 while sysread(TMP2, $data, 1024, length($data)) > 0;
if (!close(TMP2)) {
warn("$tool error: $?\n");
return undef;
}
return $data;
}
sub control2res {
my ($control) = @_;
my %res;
my @control = split("\n", $control);
while (@control) {
my $c = shift @control;
last if $c eq ''; # new paragraph
my ($tag, $data) = split(':', $c, 2);
next unless defined $data;
$tag = uc($tag);
while (@control && $control[0] =~ /^\s/) {
$data .= "\n".substr(shift @control, 1);
}
$data =~ s/^\s+//s;
$data =~ s/\s+$//s;
$res{$tag} = $data;
}
return %res;
}
sub debq {
my ($fn) = @_;
local *DEBF;
if (ref($fn) eq 'GLOB') {
*DEBF = *$fn;
} elsif (!open(DEBF, '<', $fn)) {
warn("$fn: $!\n");
return ();
}
my $data = '';
sysread(DEBF, $data, 4096);
if (length($data) < 8+60) {
warn("$fn: not a debian package - header too short\n");
close DEBF unless ref $fn;
return ();
}
if (substr($data, 0, 8+16) ne "!\ndebian-binary " &&
substr($data, 0, 8+16) ne "!\ndebian-binary/ ") {
close DEBF unless ref $fn;
return ();
}
my $len = substr($data, 8+48, 10);
$len += $len & 1;
if (length($data) < 8+60+$len+60) {
my $r = 8+60+$len+60 - length($data);
$r -= length($data);
if ((sysread(DEBF, $data, $r < 4096 ? 4096 : $r, length($data)) || 0) < $r) {
warn("$fn: unexpected EOF\n");
close DEBF unless ref $fn;
return ();
}
}
$data = substr($data, 8 + 60 + $len);
my $controlname = substr($data, 0, 16);
my $decompressor;
if ($controlname eq 'control.tar.gz ' || $controlname eq 'control.tar.gz/ ') {
$decompressor = 'gunzip';
} elsif ($controlname eq 'control.tar.xz ' || $controlname eq 'control.tar.xz/ ') {
$decompressor = 'unxz';
} elsif ($controlname eq 'control.tar ' || $controlname eq 'control.tar/ ') {
$decompressor = 'cat';
} else {
warn("$fn: control.tar is not second ar entry\n");
close DEBF unless ref $fn;
return ();
}
$len = substr($data, 48, 10);
if (length($data) < 60+$len) {
my $r = 60+$len - length($data);
if ((sysread(DEBF, $data, $r, length($data)) || 0) < $r) {
warn("$fn: unexpected EOF\n");
close DEBF unless ref $fn;
return ();
}
}
close DEBF unless ref($fn);
$data = substr($data, 60, $len);
my $controlmd5 = Digest::MD5::md5_hex($data); # our header signature
$data = uncompress($data, $decompressor);
if (!$data) {
warn("$fn: corrupt control.tar file\n");
return ();
}
my $control;
while (length($data) >= 512) {
my $n = substr($data, 0, 100);
$n =~ s/\0.*//s;
my $len = oct('00'.substr($data, 124,12));
my $blen = ($len + 1023) & ~511;
if (length($data) < $blen) {
warn("$fn: corrupt control.tar file\n");
return ();
}
if ($n eq './control' || $n eq "control") {
$control = substr($data, 512, $len);
last;
}
$data = substr($data, $blen);
}
my %res = control2res($control);
$res{'CONTROL_MD5'} = $controlmd5;
return %res;
}
sub query {
my ($handle, %opts) = @_;
my %res = debq($handle);
return undef unless %res;
my $name = $res{'PACKAGE'};
my $src = $name;
if ($res{'SOURCE'}) {
$src = $res{'SOURCE'};
$src =~ s/\s.*$//;
}
my @provides = split(',\s*', $res{'PROVIDES'} || '');
if ($opts{'addselfprovides'}) {
push @provides, "$name (= $res{'VERSION'})";
}
my @depends = split(',\s*', $res{'DEPENDS'} || '');
push @depends, split(',\s*', $res{'PRE-DEPENDS'} || '');
my $data = {
name => $name,
hdrmd5 => $res{'CONTROL_MD5'},
provides => \@provides,
requires => \@depends,
};
if ($opts{'conflicts'}) {
my @conflicts = split(',\s*', $res{'CONFLICTS'} || '');
push @conflicts, split(',\s*', $res{'BREAKS'} || '');
$data->{'conflicts'} = \@conflicts if @conflicts;
}
if ($opts{'weakdeps'}) {
for my $dep ('SUGGESTS', 'RECOMMENDS', 'ENHANCES') {
$data->{lc($dep)} = [ split(',\s*', $res{$dep} || '') ] if defined $res{$dep};
}
}
$data->{'source'} = $src if $src ne '';
if ($opts{'evra'}) {
$res{'VERSION'} =~ /^(?:(\d+):)?(.*?)(?:-([^-]*))?$/s;
$data->{'epoch'} = $1 if defined $1;
$data->{'version'} = $2;
$data->{'release'} = $3 if defined $3;
$data->{'arch'} = $res{'ARCHITECTURE'};
}
if ($opts{'description'}) {
$data->{'description'} = $res{'DESCRIPTION'};
}
if ($opts{'normalizedeps'}) {
for my $dep (qw{provides requires conflicts suggests enhances recommends}) {
next unless $data->{$dep};
for (@{$data->{$dep}}) {
s/ \(([^\)]*)\)/ $1/g;
s/<>/>/g;
}
}
}
return $data;
}
sub queryhdrmd5 {
my ($bin) = @_;
local *F;
open(F, '<', $bin) || die("$bin: $!\n");
my $data = '';
sysread(F, $data, 4096);
if (length($data) < 8+60) {
warn("$bin: not a debian package - header too short\n");
close F;
return undef;
}
if (substr($data, 0, 8+16) ne "!\ndebian-binary " &&
substr($data, 0, 8+16) ne "!\ndebian-binary/ ") {
warn("$bin: not a debian package - no \"debian-binary\" entry\n");
close F;
return undef;
}
my $len = substr($data, 8+48, 10);
$len += $len & 1;
if (length($data) < 8+60+$len+60) {
my $r = 8+60+$len+60 - length($data);
$r -= length($data);
if ((sysread(F, $data, $r < 4096 ? 4096 : $r, length($data)) || 0) < $r) {
warn("$bin: unexpected EOF\n");
close F;
return undef;
}
}
$data = substr($data, 8 + 60 + $len);
my $controlname = substr($data, 0, 16);
if ($controlname ne 'control.tar.gz ' && $controlname ne 'control.tar.gz/ ' &&
$controlname ne 'control.tar.xz ' && $controlname ne 'control.tar.xz/ ' &&
$controlname ne 'control.tar ' && $controlname ne 'control.tar/ ') {
warn("$bin: control.tar is not second ar entry\n");
close F;
return undef;
}
$len = substr($data, 48, 10);
if (length($data) < 60+$len) {
my $r = 60+$len - length($data);
if ((sysread(F, $data, $r, length($data)) || 0) < $r) {
warn("$bin: unexpected EOF\n");
close F;
return undef;
}
}
close F;
$data = substr($data, 60, $len);
return Digest::MD5::md5_hex($data);
}
sub verscmp_part {
my ($s1, $s2) = @_;
return 0 if $s1 eq $s2;
$s1 =~ s/([0-9]+)/substr("00000000000000000000000000000000$1", -32, 32)/ge;
$s2 =~ s/([0-9]+)/substr("00000000000000000000000000000000$1", -32, 32)/ge;
$s1 .= "\0";
$s2 .= "\0";
$s1 =~ tr[\176\000-\037\060-\071\101-\132\141-\172\040-\057\072-\100\133-\140\173-\175][\000-\176];
$s2 =~ tr[\176\000-\037\060-\071\101-\132\141-\172\040-\057\072-\100\133-\140\173-\175][\000-\176];
return $s1 cmp $s2;
}
sub verscmp {
my ($s1, $s2) = @_;
my ($e1, $v1, $r1) = $s1 =~ /^(?:(\d+):)?(.*?)(?:-([^-]*))?$/s;
$e1 = 0 unless defined $e1;
my ($e2, $v2, $r2) = $s2 =~ /^(?:(\d+):)?(.*?)(?:-([^-]*))?$/s;
$e2 = 0 unless defined $e2;
if ($e1 ne $e2) {
my $r = verscmp_part($e1, $e2);
return $r if $r;
}
my $r = verscmp_part($v1, $v2);
return $r if $r;
$r1 = '' unless defined $r1;
$r2 = '' unless defined $r2;
return verscmp_part($r1, $r2);
}
sub queryinstalled {
my ($root, %opts) = @_;
$root = '' if !defined($root) || $root eq '/';
my @pkgs;
local *F;
if (open(F, '<', "$root/var/lib/dpkg/status")) {
my $ctrl = '';
while() {
if ($_ eq "\n") {
my %res = control2res($ctrl);
if (defined($res{'PACKAGE'})) {
my $data = {'name' => $res{'PACKAGE'}};
$res{'VERSION'} =~ /^(?:(\d+):)?(.*?)(?:-([^-]*))?$/s;
$data->{'epoch'} = $1 if defined $1;
$data->{'version'} = $2;
$data->{'release'} = $3 if defined $3;
$data->{'arch'} = $res{'ARCHITECTURE'};
push @pkgs, $data;
}
$ctrl = '';
next;
}
$ctrl .= $_;
}
close F;
}
return \@pkgs;
}
1;
obs-build-20180831/Build/Snapcraft.pm 0000644 0001750 0001750 00000005056 13350372713 015570 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Snapcraft;
use strict;
use Build::Deb;
eval { require YAML::XS; };
*YAML::XS::LoadFile = sub {die("YAML::XS is not available\n")} unless defined &YAML::XS::LoadFile;
sub parse {
my ($cf, $fn) = @_;
my $yaml;
eval {$yaml = YAML::XS::LoadFile($fn);};
return {'error' => "Failed to parse yaml file"} unless $yaml;
my $ret = {};
$ret->{'name'} = $yaml->{'name'};
$ret->{'version'} = $yaml->{'version'};
$ret->{'epoch'} = $yaml->{'epoch'} if $yaml->{'epoch'};
# how should we report the built apps?
my @packdeps;
for my $p (@{$yaml->{'stage-packages'} || []}) {
push @packdeps, $p;
}
for my $p (@{$yaml->{'build-packages'} || []}) {
push @packdeps, $p;
}
for my $p (@{$yaml->{'after'} || []}) {
push @packdeps, "snapcraft-part:$p";
}
for my $key (sort keys(%{$yaml->{'parts'} || {}})) {
my $part = $yaml->{'parts'}->{$key};
push @packdeps, "snapcraft-plugin:$part->{plugin}" if defined $part->{plugin};
for my $p (@{$part->{'stage-packages'} || []}) {
push @packdeps, $p;
}
for my $p (@{$part->{'build-packages'} || []}) {
push @packdeps, $p;
}
for my $p (@{$part->{'after'} || []}) {
next if $yaml->{'parts'}->{$p};
push @packdeps, "build-snapcraft-part-$p";
}
}
my %exclarchs;
for my $arch (@{$yaml->{architectures} || []}) {
my @obsarchs = Build::Deb::obsarch($arch);
push @obsarchs, $arch unless @obsarchs;
$exclarchs{$_} = 1 for @obsarchs;
}
$ret->{'exclarch'} = [ sort keys %exclarchs ] if %exclarchs;
# $ret->{'badarch'} = $badarch if defined $badarch;
$ret->{'deps'} = \@packdeps;
# $ret->{'prereqs'} = \@prereqs if @prereqs;
# $ret->{'configdependent'} = 1 if $ifdeps;
return $ret;
}
1;
obs-build-20180831/Build/Susetags.pm 0000644 0001750 0001750 00000010423 13350372713 015437 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Susetags;
use strict;
use Build::Rpm;
# compatibility to old OBS code
sub parse_obs_compat {
my ($file, undef, undef, @arches) = @_;
$file = "$file.gz" if ! -e $file && -e "$file.gz";
my $pkgs = {};
parse($file, sub {
my ($data) = @_;
my $medium = delete($data->{'medium'});
my $loc = delete($data->{'location'});
if (defined($medium) && defined($loc)) {
$loc =~ s/^\Q$data->{'arch'}\E\///;
$data->{'path'} = "$medium $loc";
}
return unless !@arches || grep { /$data->{'arch'}/ } @arches;
$pkgs->{"$data->{'name'}-$data->{'version'}-$data->{'release'}-$data->{'arch'}"} = $data;
}, 'addselfprovides' => 1);
return $pkgs;
}
my %tmap = (
'Pkg' => '',
'Loc' => 'location',
'Src' => 'source',
'Prv' => 'provides',
'Req' => 'requires',
'Con' => 'conflicts',
'Obs' => 'obsoletes',
'Rec' => 'recommends',
'Sug' => 'suggests',
'Sup' => 'supplements',
'Enh' => 'enhances',
'Tim' => 'buildtime',
'Cks' => 'checksum',
);
sub addpkg {
my ($res, $data, $options) = @_;
# fixup location and source
if (exists($data->{'location'})) {
my ($medium, $dir, $loc) = split(' ', $data->{'location'}, 3);
$data->{'medium'} = $medium;
$data->{'location'} = defined($loc) ? "$dir/$loc" : "$data->{'arch'}/$dir";
}
$data->{'source'} =~ s/\s.*// if exists $data->{'source'};
if ($options->{'addselfprovides'} && defined($data->{'name'}) && defined($data->{'version'})) {
if (($data->{'arch'} || '') ne 'src' && ($data->{'arch'} || '') ne 'nosrc') {
my $evr = $data->{'version'};
$evr = "$data->{'epoch'}:$evr" if $data->{'epoch'};
$evr = "$evr-$data->{'release'}" if defined $data->{'release'};
my $s = "$data->{'name'} = $evr";
push @{$data->{'provides'}}, $s unless grep {$_ eq $s} @{$data->{'provides'} || []};
}
}
if ($options->{'withchecksum'} && $data->{'checksum'}) {
my ($ctype, $csum) = split(' ', delete($data->{'checksum'}));
$ctype = lc($ctype || '');
$data->{'checksum'} = "$ctype:$csum" if $csum && ($ctype eq 'md5' || $ctype eq 'sha1' || $ctype eq 'sha256' || $ctype eq 'sha512');
}
if (ref($res) eq 'CODE') {
$res->($data);
} else {
push @$res, $data;
}
}
sub parse {
return parse_obs_compat(@_) if @_ > 2 && !defined $_[2];
my ($in, $res, %options) = @_;
$res ||= [];
my $fd;
if (ref($in)) {
$fd = $in;
} else {
if ($in =~ /\.gz$/) {
open($fd, '-|', "gzip", "-dc", $in) || die("$in: $!\n");
} else {
open($fd, '<', $in) || die("$in: $!\n");
}
}
my $cur;
my @tmap = sort keys %tmap;
@tmap = grep {$_ ne 'Cks'} @tmap unless $options{'withchecksum'};
my $r = join('|', @tmap);
$r = qr/^([\+=])($r):\s*(.*)/;
while (<$fd>) {
chomp;
next unless /$r/;
my ($multi, $tag, $data) = ($1, $2, $3);
if ($multi eq '+') {
while (<$fd>) {
chomp;
last if /^-\Q$tag\E/;
next if $tag eq 'Req' && /^rpmlib\(/;
$_ = Build::Rpm::testcaseformat($_) if /^\(/ && $options{'testcaseformat'};
push @{$cur->{$tmap{$tag}}}, $_;
}
} elsif ($tag eq 'Pkg') {
addpkg($res, $cur, \%options) if $cur;
$cur = {};
($cur->{'name'}, $cur->{'version'}, $cur->{'release'}, $cur->{'arch'}) = split(' ', $data);
$cur->{'epoch'} = $1 if $cur->{'version'} =~ s/^(\d+)://;
} else {
$cur->{$tmap{$tag}} = $data;
}
}
addpkg($res, $cur, \%options) if $cur;
if (!ref($in)) {
close($fd) || die("close $in: $!\n");
}
return $res;
}
1;
obs-build-20180831/Build/Debrepo.pm 0000644 0001750 0001750 00000007275 13350372713 015234 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Debrepo;
use strict;
sub addpkg {
my ($res, $data, $options) = @_;
return unless defined $data->{'version'};
my $selfprovides;
$selfprovides = "= $data->{'version'}" if $options->{'addselfprovides'};
# split version into evr
$data->{'epoch'} = $1 if $data->{'version'} =~ s/^(\d+)://s;
$data->{'release'} = $1 if $data->{'version'} =~ s/-([^-]*)$//s;
for my $d (qw{provides requires conflicts recommends suggests enhances breaks prerequires}) {
next unless $data->{$d};
if ($options->{'normalizedeps'}) {
$data->{$d} =~ s/\(([^\)]*)\)/$1/g;
$data->{$d} =~ s/<{$d} =~ s/>>/>/g;
}
$data->{$d} = [ split(/\s*,\s*/, $data->{$d}) ];
}
push @{$data->{'requires'}}, @{$data->{'prerequires'}} if $data->{'prerequires'};
delete $data->{'prerequires'};
push @{$data->{'conflicts'}}, @{$data->{'breaks'}} if $data->{'breaks'};
delete $data->{'breaks'};
if (defined($selfprovides)) {
$selfprovides = "($selfprovides)" unless $options->{'normalizedeps'};
$selfprovides = "$data->{'name'} $selfprovides";
push @{$data->{'provides'}}, $selfprovides unless @{$data->{'provides'} || []} && $data->{'provides'}->[-1] eq $selfprovides;
}
if ($options->{'withchecksum'}) {
for (qw {md5 sha1 sha256}) {
my $c = delete($data->{"checksum_$_"});
$data->{'checksum'} = "$_:$c" if $c;
}
}
if (ref($res) eq 'CODE') {
$res->($data);
} else {
push @$res, $data;
}
}
my %tmap = (
'package' => 'name',
'version' => 'version',
'architecture' => 'arch',
'provides' => 'provides',
'depends' => 'requires',
'pre-depends' => 'prerequires',
'conflicts' => 'conflicts',
'breaks' => 'breaks',
'recommends' => 'recommends',
'suggests' => 'suggests',
'enhances' => 'enhances',
'filename' => 'location',
'source' => 'source',
);
my %tmap_checksums = (
'md5sum' => 'checksum_md5',
'sha1' => 'checksum_sha1',
'sha256' => 'checksum_sha256',
);
sub parse {
my ($in, $res, %options) = @_;
$res ||= [];
my $fd;
if (ref($in)) {
$fd = $in;
} else {
if ($in =~ /\.gz$/) {
open($fd, '-|', "gzip", "-dc", $in) || die("$in: $!\n");
} else {
open($fd, '<', $in) || die("$in: $!\n");
}
}
my $pkg = {};
my $tag;
my %ltmap = %tmap;
%ltmap = (%ltmap, %tmap_checksums) if $options{'withchecksum'};
while (<$fd>) {
chomp;
if ($_ eq '') {
addpkg($res, $pkg, \%options) if %$pkg;
$pkg = {};
next;
}
if (/^\s/) {
next unless $tag;
$pkg->{$tag} .= "\n".substr($_, 1);
next;
}
my $data;
($tag, $data) = split(':', $_, 2);
next unless defined $data;
$tag = $tmap{lc($tag)};
next unless $tag;
$data =~ s/^\s*//;
$pkg->{$tag} = $data;
}
addpkg($res, $pkg, \%options) if %$pkg;
if (!ref($in)) {
close($fd) || die("close $in: $!\n");
}
return $res;
}
1;
obs-build-20180831/Build/Arch.pm 0000644 0001750 0001750 00000022546 13350372713 014527 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Arch;
use strict;
use Digest::MD5;
eval { require Archive::Tar; };
*Archive::Tar::new = sub {die("Archive::Tar is not available\n")} unless defined &Archive::Tar::new;
# Archlinux support, based on the GSoC work of Nikolay Rysev
# parse a PKGBUILD file
sub quote {
my ($str, $q, $vars) = @_;
if ($q ne "'" && $str =~ /\$/) {
$str =~ s/\$([a-zA-Z0-9_]+|\{([^\}]+)\})/join(' ', @{$vars->{$2 || $1} || []})/ge;
}
$str =~ s/([ \t\"\'\$])/sprintf("%%%02X", ord($1))/ge;
return $str;
}
sub unquotesplit {
my ($str, $vars) = @_;
$str =~ s/%/%25/g;
$str =~ s/^[ \t]+//;
while ($str =~ /([\"\'])/) {
my $q = $1;
last unless $str =~ s/$q(.*?)$q/quote($1, $q, $vars)/e;
}
if ($str =~ /\$/) {
$str =~ s/\$([a-zA-Z0-9_]+|\{([^\}]+)\})/join(' ', @{$vars->{$2 || $1} || []})/ge;
}
my @args = split(/[ \t]+/, $str);
for (@args) {
s/%([a-fA-F0-9]{2})/chr(hex($1))/ge
}
return @args;
}
sub parse {
my ($config, $pkgbuild) = @_;
my $ret;
local *PKG;
if (!open(PKG, '<', $pkgbuild)) {
$ret->{'error'} = "$pkgbuild: $!";
return $ret;
}
my %vars;
my @ifs;
while () {
chomp;
next if /^\s*$/;
next if /^\s*#/;
s/^\s+//;
if (/^(el)?if\s+(?:(?:test|\[)\s+(-n|-z)\s+)?(.*?)\s*\]?\s*;\s*then\s*$/) {
if ($1) {
$ifs[-1] += 1;
next if $ifs[-1] != 1;
pop @ifs;
}
my $flag = $2 || '-n';
my $t = join('', unquotesplit($3, \%vars));
$t = $t eq '' ? 'true' : '' if $flag eq '-z';
push @ifs, $t ne '' ? 1 : 0;
next;
}
if (@ifs) {
if (/^fi\s*$/) {
pop @ifs;
next;
} elsif (/^else\s*$/) {
$ifs[-1] += 1;
next;
}
next if grep {$_ != 1} @ifs;
}
last unless /^([a-zA-Z0-9_]*)(\+?)=(\(?)(.*?)$/;
my $var = $1;
my $app = $2;
my $val = $4;
if ($3) {
while ($val !~ s/\)\s*(?:#.*)?$//s) {
my $nextline = ;
last unless defined $nextline;
chomp $nextline;
$val .= ' ' . $nextline;
}
}
if ($app) {
push @{$vars{$var}}, unquotesplit($val, \%vars);
} else {
$vars{$var} = [ unquotesplit($val, \%vars) ];
}
}
close PKG;
$ret->{'name'} = $vars{'pkgname'}->[0] if $vars{'pkgname'};
$ret->{'version'} = $vars{'pkgver'}->[0] if $vars{'pkgver'};
$ret->{'deps'} = [];
push @{$ret->{'deps'}}, @{$vars{$_} || []} for qw{makedepends checkdepends depends};
# get arch from macros
my $arch;
for (@{$config->{'macros'} || []}) {
$arch = $1 if /^%define _target_cpu (\S+)/;
}
# map to arch linux name and add arch dependent
$arch = 'i686' if $arch =~ /^i[345]86$/;
push @{$ret->{'deps'}}, @{$vars{"${_}_$arch"} || []} for qw{makedepends checkdepends depends};
# Maintain architecture-specific sources for officially supported architectures
for my $asuf ('', '_i686', '_x86_64') {
$ret->{"source$asuf"} = $vars{"source$asuf"} if $vars{"source$asuf"};
}
return $ret;
}
sub islzma {
my ($fn) = @_;
local *F;
return 0 unless open(F, '<', $fn);
my $h;
return 0 unless read(F, $h, 5) == 5;
close F;
return $h eq "\3757zXZ";
}
sub lzmadec {
my ($fn) = @_;
my $nh;
my $pid = open($nh, '-|');
return undef unless defined $pid;
if (!$pid) {
$SIG{'PIPE'} = 'DEFAULT';
exec('xzdec', '-dc', $fn);
die("xzdec: $!\n");
}
return $nh;
}
sub queryvars {
my ($handle) = @_;
if (ref($handle)) {
die("arch pkg query not implemented for file handles\n");
}
if ($handle =~ /\.xz$/ || islzma($handle)) {
$handle = lzmadec($handle);
}
my $tar = Archive::Tar->new;
my @read = $tar->read($handle, 1, {'filter' => '^\.PKGINFO$', 'limit' => 1});
die("$handle: not an arch package file\n") unless @read == 1;
my $pkginfo = $read[0]->get_content;
die("$handle: not an arch package file\n") unless $pkginfo;
my %vars;
$vars{'_pkginfo'} = $pkginfo;
for my $l (split('\n', $pkginfo)) {
next unless $l =~ /^(.*?) = (.*)$/;
push @{$vars{$1}}, $2;
}
return \%vars;
}
sub queryfiles {
my ($handle) = @_;
if (ref($handle)) {
die("arch pkg query not implemented for file handles\n");
}
if ($handle =~ /\.xz$/ || islzma($handle)) {
$handle = lzmadec($handle);
}
my @files;
my $tar = Archive::Tar->new;
# we use filter_cb here so that Archive::Tar skips the file contents
$tar->read($handle, 1, {'filter_cb' => sub {
my ($entry) = @_;
push @files, $entry->name unless $entry->is_longlink || (@files && $files[-1] eq $entry->name);
return 0;
}});
shift @files if @files && $files[0] eq '.PKGINFO';
return \@files;
}
sub query {
my ($handle, %opts) = @_;
my $vars = queryvars($handle);
my $ret = {};
$ret->{'name'} = $vars->{'pkgname'}->[0] if $vars->{'pkgname'};
$ret->{'hdrmd5'} = Digest::MD5::md5_hex($vars->{'_pkginfo'});
$ret->{'provides'} = $vars->{'provides'} || [];
$ret->{'requires'} = $vars->{'depend'} || [];
if ($vars->{'pkgname'} && $opts{'addselfprovides'}) {
my $selfprovides = $vars->{'pkgname'}->[0];
$selfprovides .= "=$vars->{'pkgver'}->[0]" if $vars->{'pkgver'};
push @{$ret->{'provides'}}, $selfprovides unless @{$ret->{'provides'} || []} && $ret->{'provides'}->[-1] eq $selfprovides;
}
if ($opts{'evra'}) {
if ($vars->{'pkgver'}) {
my $evr = $vars->{'pkgver'}->[0];
if ($evr =~ /^([0-9]+):(.*)$/) {
$ret->{'epoch'} = $1;
$evr = $2;
}
$ret->{'version'} = $evr;
if ($evr =~ /^(.*)-(.*?)$/) {
$ret->{'version'} = $1;
$ret->{'release'} = $2;
}
}
$ret->{'arch'} = $vars->{'arch'}->[0] if $vars->{'arch'};
}
if ($opts{'description'}) {
$ret->{'description'} = $vars->{'pkgdesc'}->[0] if $vars->{'pkgdesc'};
}
if ($opts{'conflicts'}) {
$ret->{'conflicts'} = $vars->{'conflict'} if $vars->{'conflict'};
$ret->{'obsoletes'} = $vars->{'replaces'} if $vars->{'replaces'};
}
if ($opts{'weakdeps'}) {
my @suggests = @{$vars->{'optdepend'} || []};
s/:.*// for @suggests;
$ret->{'suggests'} = \@suggests if @suggests;
}
# arch packages don't seem to have a source :(
# fake it so that the package isn't confused with a src package
$ret->{'source'} = $ret->{'name'} if defined $ret->{'name'};
$ret->{'buildtime'} = $vars->{'builddate'}->[0] if $opts{'buildtime'} && $vars->{'builddate'};
return $ret;
}
sub queryhdrmd5 {
my ($handle) = @_;
if (ref($handle)) {
die("arch pkg query not implemented for file handles\n");
}
if ($handle =~ /\.xz$/ || islzma($handle)) {
$handle = lzmadec($handle);
}
my $tar = Archive::Tar->new;
my @read = $tar->read($handle, 1, {'filter' => '^\.PKGINFO$', 'limit' => 1});
die("$handle: not an arch package file\n") unless @read == 1;
my $pkginfo = $read[0]->get_content;
die("$handle: not an arch package file\n") unless $pkginfo;
return Digest::MD5::md5_hex($pkginfo);
}
sub parserepodata {
my ($d, $data) = @_;
$d ||= {};
$data =~ s/^\n+//s;
my @parts = split(/\n\n+/s, $data);
for my $part (@parts) {
my @p = split("\n", $part);
my $p = shift @p;
if ($p eq '%NAME%') {
$d->{'name'} = $p[0];
} elsif ($p eq '%VERSION%') {
$d->{'version'} = $p[0];
} elsif ($p eq '%ARCH%') {
$d->{'arch'} = $p[0];
} elsif ($p eq '%BUILDDATE%') {
$d->{'buildtime'} = $p[0];
} elsif ($p eq '%FILENAME%') {
$d->{'filename'} = $p[0];
} elsif ($p eq '%PROVIDES%') {
push @{$d->{'provides'}}, @p;
} elsif ($p eq '%DEPENDS%') {
push @{$d->{'requires'}}, @p;
} elsif ($p eq '%OPTDEPENDS%') {
push @{$d->{'suggests'}}, @p;
} elsif ($p eq '%CONFLICTS%') {
push @{$d->{'conflicts'}}, @p;
} elsif ($p eq '%REPLACES%') {
push @{$d->{'obsoletes'}}, @p;
} elsif ($p eq '%MD5SUM%') {
$d->{'checksum_md5'} = $p[0];
} elsif ($p eq '%SHA256SUM%') {
$d->{'checksum_sha256'} = $p[0];
}
}
return $d;
}
sub queryinstalled {
my ($root, %opts) = @_;
$root = '' if !defined($root) || $root eq '/';
local *D;
local *F;
opendir(D, "$root/var/lib/pacman/local") || return [];
my @pn = sort(grep {!/^\./} readdir(D));
closedir(D);
my @pkgs;
for my $pn (@pn) {
next unless open(F, '<', "$root/var/lib/pacman/local/$pn/desc");
my $data = '';
1 while sysread(F, $data, 8192, length($data));
close F;
my $d = parserepodata(undef, $data);
next unless defined $d->{'name'};
my $q = {};
for (qw{name arch buildtime version}) {
$q->{$_} = $d->{$_} if defined $d->{$_};
}
$q->{'epoch'} = $1 if $q->{'version'} =~ s/^(\d+)://s;
$q->{'release'} = $1 if $q->{'version'} =~ s/-([^-]*)$//s;
push @pkgs, $q;
}
return \@pkgs;
}
1;
obs-build-20180831/Build/Archrepo.pm 0000644 0001750 0001750 00000006607 13350372713 015415 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Archrepo;
use strict;
use Build::Arch;
eval { require Archive::Tar; };
if (!defined &Archive::Tar::iter) {
*Archive::Tar::iter = sub {
my ($class, $filename) = @_;
die("Archive::Tar is not available\n") unless defined &Archive::Tar::new;
Archive::Tar->new();
my $handle = $class->_get_handle($filename, 1, 'rb') or return undef;
my @data;
return sub {
return shift(@data) if !$handle || @data;
my $files = $class->_read_tar($handle, { limit => 1 });
@data = @$files if (ref($files) || '') eq 'ARRAY';
undef $handle unless @data;
return shift @data;
};
};
}
sub addpkg {
my ($res, $data, $options) = @_;
return unless defined $data->{'version'};
if ($options->{'addselfprovides'}) {
my $selfprovides = $data->{'name'};
$selfprovides .= "=$data->{'version'}" if defined $data->{'version'};
push @{$data->{'provides'}}, $selfprovides unless @{$data->{'provides'} || []} && $data->{'provides'}->[-1] eq $selfprovides;
}
if ($options->{'normalizedeps'}) {
# our normalized dependencies have spaces around the op
for my $dep (qw {provides requires conflicts obsoletes suggests}) {
next unless $data->{$dep};
s/ ?([<=>]+) ?/ $1 / for @{$data->{$dep}};
}
}
if (defined($data->{'version'})) {
# split version into evr
$data->{'epoch'} = $1 if $data->{'version'} =~ s/^(\d+)://s;
$data->{'release'} = $1 if $data->{'version'} =~ s/-([^-]*)$//s;
}
$data->{'location'} = delete($data->{'filename'}) if exists $data->{'filename'};
if ($options->{'withchecksum'}) {
for (qw {md5 sha1 sha256}) {
my $c = delete($data->{"checksum_$_"});
$data->{'checksum'} = "$_:$c" if $c;
}
} else {
delete $data->{"checksum_$_"} for qw {md5 sha1 sha256};
}
if (ref($res) eq 'CODE') {
$res->($data);
} else {
push @$res, $data;
}
}
sub parse {
my ($in, $res, %options) = @_;
$res ||= [];
die("Build::Archrepo::parse needs a filename\n") if ref($in);
die("$in: $!\n") unless -e $in;
my $repodb = Archive::Tar->iter($in, 1);
die("$in is not a tar archive\n") unless $repodb;
my $e;
my $lastfn = '';
my $d;
while ($e = $repodb->()) {
next unless $e->type() == Archive::Tar::Constant::FILE();
my $fn = $e->name();
next unless $fn =~ s/\/(?:depends|desc|files)$//s;
if ($lastfn ne $fn) {
addpkg($res, $d, \%options) if $d->{'name'};
$d = {};
$lastfn = $fn;
}
Build::Arch::parserepodata($d, $e->get_content());
}
addpkg($res, $d, \%options) if $d->{'name'};
return $res;
}
1;
obs-build-20180831/Build/Repo.pm 0000644 0001750 0001750 00000003732 13350372713 014553 0 ustar alee alee ################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Repo;
use strict;
our $do_rpmmd;
our $do_deb;
our $do_arch;
our $do_susetags;
our $do_mdk;
sub import {
for (@_) {
$do_rpmmd = 1 if $_ eq ':rpmmd';
$do_deb = 1 if $_ eq ':deb';
$do_arch = 1 if $_ eq ':arch';
$do_susetags = 1 if $_ eq ':susetags';
$do_mdk = 1 if $_ eq ':mdk';
}
$do_rpmmd = $do_deb = $do_arch = $do_susetags = $do_mdk = 1 unless $do_rpmmd || $do_deb || $do_arch || $do_susetags || $do_mdk;
if ($do_rpmmd) {
require Build::Rpmmd;
}
if ($do_susetags) {
require Build::Susetags;
}
if ($do_deb) {
require Build::Debrepo;
}
if ($do_arch) {
require Build::Archrepo;
}
if ($do_mdk) {
require Build::Mdkrepo;
}
}
sub parse {
my ($type, @args) = @_;
return Build::Rpmmd::parse(@args) if $do_rpmmd && $type eq 'rpmmd';
return Build::Susetags::parse(@args) if $do_susetags && $type eq 'susetags';
return Build::Debrepo::parse(@args) if $do_deb && $type eq 'deb';
return Build::Archrepo::parse(@args) if $do_arch && $type eq 'arch';
return Build::Mdkrepo::parse(@args) if $do_arch && $type eq 'mdk';
die("parse repo: unknown type '$type'\n");
}
1;
obs-build-20180831/Build/Fissile.pm 0000644 0001750 0001750 00000002753 13350372713 015246 0 ustar alee alee ################################################################
#
# Copyright (c) 2017 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
package Build::Fissile;
use strict;
eval { require YAML::XS; };
*YAML::XS::LoadFile = sub {die("YAML::XS is not available\n")} unless defined &YAML::XS::LoadFile;
sub parse {
my ($cf, $fn) = @_;
my $yml;
eval { $yml = YAML::XS::LoadFile($fn); };
return {'error' => "Failed to parse yml file"} unless $yml;
my $ret = {};
$ret->{'name'} = $yml->{'Name'} || 'fissile';
$ret->{'version'} = $yml->{'Version'} if $yml->{'Version'};
my @deps;
for (@{$yml->{'DockerImageDeps'} || []}) {
# This generates something like: "container:fissile-dev:201707081450"
push @deps, "container:$_";
}
$ret->{'deps'} = \@deps;
return $ret;
}
1;
obs-build-20180831/substitutedeps 0000755 0001750 0001750 00000022262 13350372713 015265 0 ustar alee alee #!/usr/bin/perl -w
################################################################
#
# Copyright (c) 1995-2014 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# 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 (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################
BEGIN {
unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
}
use strict;
use Build;
sub expand {
my ($config, $str) = @_;
my @xspec;
my %cf = %$config;
$cf{'save_expanded'} = 1;
Build::Rpm::parse(\%cf, [ "$str" ], \@xspec);
return @xspec && ref($xspec[0]) ? $xspec[0]->[1] : '';
}
my ($dist, $buildroot, $rpmdeps, $archs, $configdir, $release, $changelog, $buildflavor, $obspackage);
$buildflavor = ''; # default to empty
$configdir = ($::ENV{'BUILD_DIR'} || '/usr/lib/build') . '/configs';
while (@ARGV) {
if ($ARGV[0] eq '--root') {
shift @ARGV;
$buildroot = shift @ARGV;
next;
}
if ($ARGV[0] eq '--dist') {
shift @ARGV;
$dist = shift @ARGV;
next;
}
if ($ARGV[0] eq '--archpath') {
shift @ARGV;
$archs = shift @ARGV;
next;
}
if ($ARGV[0] eq '--configdir') {
shift @ARGV;
$configdir = shift @ARGV;
next;
}
if ($ARGV[0] eq '--release') {
shift @ARGV;
$release = shift @ARGV;
next;
}
if ($ARGV[0] eq '--changelog') {
shift @ARGV;
$changelog = shift @ARGV;
next;
}
if ($ARGV[0] eq '--buildflavor') {
shift @ARGV;
$buildflavor = shift @ARGV;
next;
}
if ($ARGV[0] eq '--obspackage') {
shift @ARGV;
$obspackage = shift @ARGV;
next;
}
last;
}
die("Usage: substitutedeps --dist --archpath [--configdir ] \n") unless @ARGV == 2;
my $spec = $ARGV[0];
my $specdir = $spec;
$specdir =~ s/[^\/]*$//;
$specdir = "./" if $specdir eq '';
my $newspec = $ARGV[1];
my $cf = Build::read_config_dist($dist, $archs, $configdir);
$cf->{'warnings'} = 1;
#######################################################################
my $xspec = [];
my $d = Build::parse($cf, $spec, $xspec) || {};
my @sdeps = @{$d->{'deps'} || []};
my @neg = map {substr($_, 1)} grep {/^-/} @{$d->{'deps'} || []};
my %neg = map {$_ => 1} @neg;
@sdeps = grep {!$neg{$_}} @sdeps;
@sdeps = Build::do_subst($cf, @sdeps);
@sdeps = grep {!$neg{$_}} @sdeps;
my %sdeps = map {$_ => 1} @sdeps;
open(F, '>', $newspec) || die("$newspec: $!\n");
my $used;
my $inchangelog = 0;
my $mainpkg = '';
my $pkg;
for my $line (@$xspec) {
$line =~ s/\@BUILD_FLAVOR\@/$buildflavor/g if defined $buildflavor;
if (defined($obspackage)) {
$line =~ s/\@OBS_PACKAGE\@/$obspackage/g;
} else {
die("recipe contains \@OBS_PACKAGE\@, but no package is set\n") if $line =~ /\@OBS_PACKAGE\@/;
}
$used = 1;
if (ref($line)) {
if (!defined($line->[1])) {
$used = 0;
$line = $line->[0];
} else {
$line = $line->[1];
}
}
if ($inchangelog) {
$inchangelog = 0 if $line =~ /^\s*%[^%]/;
next if $inchangelog;
}
if ($changelog && ($line =~ /\s*\%changelog\b/)) {
$inchangelog = 1;
next;
}
if ($line =~ /^Name\s*:\s*(\S+)/i) {
$pkg = $mainpkg = $1 unless $mainpkg;
}
if ($line =~ /^\s*%package\s+(-n\s+)?(\S+)/) {
if ($1) {
$pkg = $2;
} else {
$pkg = "$mainpkg-$2";
}
}
if ($line =~ /^Release\s*:\s*(.*?)\s*$/i) {
my $spec_rel = $1; # User-provided value
my $oldl = $line;
if (defined $release) {
if (!($line =~ s//$release/g)) {
if ($line =~ /<(?:CI_CNT|B_CNT)>/) {
# XXX: should pass ci_cnt/b_cnt instead
if ($release =~ /(\d+)\.(\d+)$/) {
my ($ci, $b) = ($1, $2);
$line =~ s//$ci/;
$line =~ s//$b/;
} elsif ($release =~ /(\d+)$/) {
my $b = $1;
$b = '0' if $line =~ s//$b/;
$line =~ s//$b/;
}
} else {
# no special replacement rules in the line, simply replace
$line =~ s/^(Release\s*:\s*).*/$1$release/i;
$line =~ s//$spec_rel/g;
}
}
$line =~ s///g; # no recursion please
} else {
# remove macros, as rpm doesn't like them
$line =~ s//0/;
$line =~ s//0/;
$line =~ s//0/;
}
if ($cf->{'releasesuffix'}) {
my $suffix = $cf->{'releasesuffix'};
if ($suffix =~ /^file:(.+)$/) {
my $file = $1;
if ($file =~ /\//s || $file =~ /^\./) {
$suffix = "error:illegal release suffix";
} else {
if (open(RP, '<', "$specdir$file")) {
$suffix = "error:no suffix in $file";
for (