#!/bin/sh # # Copyright (C) 2017-2018, 2020 Etersoft # Copyright (C) 2017-2018, 2020 Vitaly Lipatov <lav@etersoft.ru> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # load_helper epm-sh-altlinux load_helper epm-assure # arg: rpm or deb # fills split_replaced_pkgs with packages of that type __epm_split_by_pkg_type() { local type="$1" shift split_replaced_pkgs='' for pkg in "$@" ; do [ "$(get_package_type "$pkg")" = "$type" ] || return 1 [ -e "$pkg" ] || fatal "Can't read $pkg" split_replaced_pkgs="$split_replaced_pkgs $pkg" done [ -n "$split_replaced_pkgs" ] } # fills repacked_pkgs __epm_repack_to_deb() { local pkg local pkgs="$@" assure_exists alien assure_exists fakeroot assure_exists rpm repacked_pkgs='' local TDIR=$(mktemp -d) for pkg in $pkgs ; do abspkg="$(realpath "$pkg")" info "Repacking $abspkg to local deb format ..." alpkg=$(basename $pkg) # don't use abs package path: copy package to temp dir and use there cp $verbose $pkg $TDIR/$alpkg cd $TDIR || fatal __prepare_source_package "$pkg" showcmd_store_output fakeroot alien -d -k $scripts "$alpkg" local DEBCONVERTED=$(grep "deb generated" $RC_STDOUT | sed -e "s| generated||g") if [ -n "$DEBCONVERTED" ] ; then repacked_pkgs="$repacked_pkgs $(realpath $DEBCONVERTED)" to_remove_pkg_files="$to_remove_pkg_files $(realpath $DEBCONVERTED)" fi to_remove_pkg_dirs="$to_remove_pkg_files $TDIR" clean_store_output cd - >/dev/null done # TODO: move it to exit handler #if [ -z "$DEBUG" ] ; then # # TODO: reinvent # [ -n "$to_remove_pkg_files" ] && rm -f $to_remove_pkg_files # [ -n "$to_remove_pkg_files" ] && rmdir $(dirname $to_remove_pkg_files | head -n1) 2>/dev/null # [ -n "$to_remove_pkg_dirs" ] && rmdir $to_remove_pkg_dirs #fi #cd - >/dev/null return 0 } # $spec $PKGNAME $VERSION __set_name_version() { SPEC="$1" PKGNAME="$2" VERSION="$3" [ -n "$PKGNAME" ] && subst "s|^Name:.*|Name: $PKGNAME|" $SPEC [ -n "$VERSION" ] && subst "s|^Version:.*|Version: $VERSION|" $SPEC } # args: pkgname buildroot spec __fix_spec() { local pkgname="$1" local buildroot="$2" local spec="$3" local i # drop forbidded paths # https://bugzilla.altlinux.org/show_bug.cgi?id=38842 for i in / /etc /etc/init.d /etc/systemd /bin /opt /usr /usr/bin /usr/share /usr/share/doc /var /var/log /var/run \ /etc/cron.daily /usr/share/icons /usr/share/pixmaps /usr/share/man /usr/share/man/man1 /usr/share/appdata /usr/share/applications /usr/share/menu ; do sed -i -e "s|^%dir \"$i/*\"$||" \ -e "s|^\"$i/*\"$||" \ -e "s|^$i/*$||" \ $spec done # commented out: conflicts with already installed package # drop %dir for existed system dirs #for i in $(grep '^%dir "' $spec | sed -e 's|^%dir *"\(.*\)".*|\1|' ) ; do #" # echo "$i" | grep -q '^/opt/' && continue # [ -d "$i" ] && [ -n "$verbose" ] && echo "drop dir $i from packing, it exists in the system" #done # replace dir "/path/dir" -> %dir /path/dir grep '^"/' $spec | sed -e 's|^"\(/.*\)"$|\1|' | while read i ; do # add dir as %dir in the filelist if [ -d "$buildroot$i" ] ; then subst 's|^\("'$i'"\)$|%dir \1|' $spec #else # subst 's|^\("'$i'"\)$|\1|' $spec fi done # FIXME: where is a source of the bug with empty Summary? subst "s|Summary: *$|Summary: $pkgname (was empty Summary after alien)|" $spec subst "s|^\(Version: .*\)~.*|\1|" $spec subst "s|^Release: |Release: alt1.repacked.with.epm.|" $spec subst "s|^Distribution:.*||" $SPEC subst "s|^\((Converted from a\) \(.*\) \(package.*\)|(Repacked from binary \2 package with epm $EPMVERSION)\n\1 \2 \3|" $spec #" hack for highlight } # TODO: move this list from external file __check_stoplist() { cat <<EOF | grep -q "^$1$" kesl kesl-astra klnagent klnagent64 klnagent64-astra EOF } # args: pkgname buildroot spec __apply_fix_code() { local repackcode="$(realpath $CONFIGDIR/repack.d/$1.sh)" [ -x "$repackcode" ] || return shift export PATH=$PROGDIR:$PATH local bashopt='' [ -n "$verbose" ] && bashopt='-x' docmd bash $bashopt $repackcode "$1" "$2" || fatal "There is an error from $repackcode script" } __create_rpmmacros() { # FIXME: [ -n "$TMPDIR" ] || TMPDIR=/tmp cat <<EOF >$HOME/.rpmmacros %_topdir $HOME/RPM %_tmppath $TMPDIR %packager EPM <support@etersoft.ru> %_gpg_name support@etersoft.ru %_allow_root_build 1 EOF to_remove_pkg_files="$to_remove_pkg_files $HOME/.rpmmacros" } __set_version_pkgname() { local alpkg="$1" VERSION="$(echo "$alpkg" | grep -o -P "[-_.]([0-9])([0-9])*(\.[0-9])*" | head -n1 | sed -e 's|^[-_.]||')" #" [ -n "$VERSION" ] && PKGNAME="$(echo "$alpkg" | sed -e "s|[-_.]$VERSION.*||")" } # arg: <package file> # sets: # alpkg - package file name without path # PKGNAME - package name # VERSION - version of the package # SUBGENERIC - name of generic file's extension __prepare_source_package() { local pkg="$1" alpkg=$(basename $pkg) # TODO: use func for get name from deb pkg # TODO: epm print name from deb package # TODO: use stoplist only for deb? [ -z "$force" ] && __check_stoplist $(echo $alpkg | sed -e "s|_.*||") && fatal "Please use official package instead of $alpkg repacking (It is not recommended to use --force to skip this checking." PKGNAME='' VERSION='' SUBGENERIC='' # convert tarballs to tar (for alien) if rhas "$alpkg" "\.(rpm|deb)$" ; then return fi if rhas "$alpkg" "\.AppImage$" ; then __set_version_pkgname $alpkg [ -n "$VERSION" ] || fatal "Can't get version from $alpkg." SUBGENERIC='appimage' # TODO: move repack archive to erc? [ -x "$alpkg" ] || docmd chmod u+x -v "$alpkg" ./$alpkg --appimage-extract || fatal alpkg=$PKGNAME-$VERSION.tar assure_exists erc || fatal # make a tar for alien a= erc a $alpkg squashfs-root return fi __set_version_pkgname $alpkg if [ -n "$VERSION" ] ; then assure_exists erc || fatal pkgtype="$(a= erc type $alpkg)" [ -n "$PKGNAME" ] || PKGNAME=$(basename $alpkg .$pkgtype) if [ "$pkgtype" = "tar" ] || [ "$pkgtype" = "tar.gz" ] || [ "$pkgtype" = "tgz" ] ; then : else newalpkg=$(basename $alpkg .$pkgtype).tar assure_exists erc || fatal a= erc repack $alpkg $newalpkg || fatal rm -f $verbose $alpkg alpkg=$newalpkg fi fi } # will fill repacked_pkgs var __epm_repack_to_rpm() { local pkgs="$*" case $DISTRNAME in ALTLinux|ALTServer) ;; *) assure_distr ALTLinux "install --repack for rpm target" ;; esac # install epm-repack for static (package based) dependencies assure_exists alien || fatal assure_exists /usr/bin/rpmbuild rpm-build || fatal # TODO: improve if echo "$pkgs" | grep -q "\.deb" ; then assure_exists dpkg || fatal # TODO: Для установки требует: /usr/share/debconf/confmodule но пакет не может быть установлен # assure_exists debconf fi local pkg export HOME=$(mktemp -d) __create_rpmmacros local alpkg local abspkg local tmpbuilddir repacked_pkgs='' for pkg in $pkgs ; do tmpbuilddir=$HOME/$(basename $pkg).tmpdir mkdir $tmpbuilddir abspkg="$(realpath $pkg)" info "" info "Repacking $abspkg to local rpm format ..." alpkg=$(basename $pkg) # don't use abs package path: copy package to temp dir and use there cp $verbose $pkg $tmpbuilddir/../$alpkg cd $tmpbuilddir/../ || fatal __prepare_source_package "$pkg" cd $tmpbuilddir/ || fatal if [ -n "$verbose" ] ; then docmd alien --generate --to-rpm $verbose $scripts "../$alpkg" || fatal else showcmd alien --generate --to-rpm $scripts "../$alpkg" a='' alien --generate --to-rpm $scripts "../$alpkg" >/dev/null || fatal fi local subdir="$(echo *)" [ -d "$subdir" ] || fatal "can't find subdir" # detect spec and move to prev dir local spec="$(echo $tmpbuilddir/$subdir/*.spec)" [ -s "$spec" ] || fatal "can't find spec" mv $spec $tmpbuilddir || fatal spec="$tmpbuilddir/$(basename "$spec")" __set_name_version $spec $PKGNAME $VERSION local pkgname="$(grep "^Name: " $spec | sed -e "s|Name: ||g" | head -n1)" # for tarballs fix permissions [ -n "$VERSION" ] && chmod -R a+rX $tmpbuilddir/$subdir/* __fix_spec $pkgname $tmpbuilddir/$subdir $spec __apply_fix_code "generic" $tmpbuilddir/$subdir $spec [ -n "$SUBGENERIC" ] && __apply_fix_code "generic-$SUBGENERIC" $tmpbuilddir/$subdir $spec __apply_fix_code $pkgname $tmpbuilddir/$subdir $spec # TODO: we need these dirs to be created to_remove_pkg_dirs="$to_remove_pkg_dirs $HOME/RPM/BUILD $HOME/RPM" showcmd rpmbuild --buildroot $tmpbuilddir/$subdir -bb $spec if [ -n "$verbose" ] ; then a='' rpmbuild --buildroot $tmpbuilddir/$subdir -bb $spec || fatal else a='' rpmbuild --buildroot $tmpbuilddir/$subdir -bb $spec >/dev/null || fatal fi # remove copy of source binary package (don't mix with generated) rm -f $tmpbuilddir/../$alpkg local repacked_rpm="$(realpath $tmpbuilddir/../*.rpm)" if [ -s "$repacked_rpm" ] ; then repacked_pkgs="$repacked_pkgs $repacked_rpm" to_remove_pkg_files="$to_remove_pkg_files $repacked_rpm" else warning "Can't find converted rpm for source binary package '$pkg'" fi cd - >/dev/null rm -rf $tmpbuilddir/$subdir/ rm -rf $spec done to_remove_pkg_dirs="$to_remove_pkg_dirs $HOME" rmdir $tmpbuilddir #rmdir $tmpbuilddir/.. true } __epm_remove_tmp_files() { # TODO: move it to exit handler if [ -z "$DEBUG" ] ; then # TODO: reinvent [ -n "$to_remove_pkg_files" ] && rm -f $to_remove_pkg_files # hack?? [ -n "$to_remove_pkg_files" ] && rmdir $(dirname $to_remove_pkg_files | head -n1) 2>/dev/null [ -n "$to_remove_pkg_dirs" ] && rmdir $to_remove_pkg_dirs 2>/dev/null fi return 0 } # FIXME: Нужно как-то обеспечить непродолжение выполнения. # used in epm install # fill repacked_pkgs __epm_repack() { repacked_pkgs='' case $PKGFORMAT in rpm) __epm_repack_to_rpm "$@" || return ;; deb) __epm_repack_to_deb "$@" || return ;; *) fatal "$PKGFORMAT is not supported for repack yet" ;; esac return 0 } __epm_repack_if_needed() { # return 1 if there is a package in host package format __epm_split_by_pkg_type $PKGFORMAT "$@" && return 1 __epm_repack "$@" return 0 } epm_repack() { local CURDIR="$(pwd)" # if possible, it will put pkg_urls into pkg_files and reconstruct pkg_filenames if [ -n "$pkg_urls" ] ; then load_helper epm-download __handle_pkg_urls_to_install fi [ -n "$pkg_names" ] && warning "Can't find $pkg_names" [ -z "$pkg_files" ] && info "Skip empty repack list" && return 22 if __epm_repack $pkg_files && [ -n "$repacked_pkgs" ] ; then cp $repacked_pkgs "$CURDIR" if [ -z "$quiet" ] ; then echo echo "Adapted packages:" for i in $repacked_pkgs ; do echo " $CURDIR/$(basename "$i")" done fi fi __epm_remove_tmp_files }