#!/bin/sh # # Copyright (C) 2012-2021 Etersoft # Copyright (C) 2012-2021 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/>. # PROGDIR=$(dirname "$0") PROGNAME=$(basename "$0") [ "$PROGDIR" = "." ] && PROGDIR=$(pwd) if [ "$0" = "/dev/stdin" ] || [ "$0" = "sh" ] ; then PROGDIR="" PROGNAME="" fi # will replaced to /usr/share/eepm during install SHAREDIR=$PROGDIR CONFIGDIR=$PROGDIR/.. load_helper() { local CMD="$SHAREDIR/$1" # do not use fatal() here, it can be initial state [ -r "$CMD" ] || { echo "FATAL: Have no $CMD helper file" ; exit 1; } # shellcheck disable=SC1090 . $CMD } # File bin/epm-sh-functions: inputisatty() { # check stdin #tty -s 2>/dev/null test -t 0 } isatty() { # check stdout test -t 1 } isatty2() { # check stderr test -t 2 } check_tty() { isatty2 || return # Set a sane TERM required for tput [ -n "$TERM" ] || TERM=dumb export TERM # egrep from busybox may not --color # egrep from MacOS print help to stderr if grep -E --help 2>&1 | grep -q -- "--color" ; then export EGREPCOLOR="--color" fi which tput >/dev/null 2>/dev/null || return # FreeBSD does not support tput -S echo | tput -S >/dev/null 2>/dev/null || return [ -z "$USETTY" ] || return export USETTY=1 } : ${BLACK:=0} ${RED:=1} ${GREEN:=2} ${YELLOW:=3} ${BLUE:=4} ${MAGENTA:=5} ${CYAN:=6} ${WHITE:=7} set_boldcolor() { [ "$USETTY" = "1" ] || return { echo bold echo setaf $1 } |tput -S } restore_color() { [ "$USETTY" = "1" ] || return { echo op; # set Original color Pair. echo sgr0; # turn off all special graphics mode (bold in our case). } |tput -S } echover() { [ -z "$verbose" ] && return echo "$*" >&2 } echon() { # default /bin/sh on MacOS does not recognize -n /bin/echo -n "$*" } set_target_pkg_env() { [ -n "$DISTRNAME" ] || fatal "Missing DISTRNAME in set_target_pkg_env." local ver="$DISTRVERSION" [ -n "$ver" ] && ver="/$ver" PKGFORMAT=$($DISTRVENDOR -p "$DISTRNAME$ver") PKGVENDOR=$($DISTRVENDOR -s "$DISTRNAME$ver") RPMVENDOR=$($DISTRVENDOR -n "$DISTRNAME$ver") } showcmd() { if [ -z "$quiet" ] ; then set_boldcolor $GREEN local PROMTSIG="\$" is_root && PROMTSIG="#" echo " $PROMTSIG $*" restore_color fi >&2 } docmd() { showcmd "$*$EXTRA_SHOWDOCMD" $@ } docmd_foreach() { local cmd pkg cmd="$1" #showcmd "$@" shift for pkg in "$@" ; do docmd "$cmd" $pkg done } sudorun() { set_sudo if [ -z "$SUDO" ] ; then "$@" return fi $SUDO "$@" } sudocmd() { set_sudo [ -n "$SUDO" ] && showcmd "$SUDO $*" || showcmd "$*" sudorun "$@" } sudocmd_foreach() { local cmd pkg cmd="$1" #showcmd "$@" shift for pkg in "$@" ; do # don't quote $cmd here: it can be a command with an args sudocmd $cmd $pkg || return done } if ! which realpath 2>/dev/null >/dev/null ; then realpath() { readlink -f "$@" } fi get_firstarg() { echon "$1" } get_lastarg() { local lastarg eval "lastarg=\${$#}" echon "$lastarg" } isnumber() { echo "$*" | filter_strip_spaces | grep -q "^[0-9]\+$" } rhas() { echo "$1" | grep -E -q -- "$2" } is_dirpath() { [ "$1" = "." ] && return $? rhas "$1" "/" } filter_strip_spaces() { # possible use just #xargs echo sed -e "s| \+| |g" | \ sed -e "s|^ ||" | sed -e "s| \$||" } strip_spaces() { echo "$*" | filter_strip_spaces } subst_option() { eval "[ -n \"\$$1\" ]" && echo "$2" || echo "$3" } store_output() { # use make_temp_file from etersoft-build-utils RC_STDOUT=$(mktemp) local CMDSTATUS=$RC_STDOUT.pipestatus echo 1 >$CMDSTATUS #RC_STDERR=$(mktemp) ( LANG=C $@ 2>&1 ; echo $? >$CMDSTATUS ) | tee $RC_STDOUT return "$(cat $CMDSTATUS)" # bashism # http://tldp.org/LDP/abs/html/bashver3.html#PIPEFAILREF #return $PIPESTATUS } showcmd_store_output() { showcmd "$@" store_output "$@" } clean_store_output() { rm -f $RC_STDOUT $RC_STDOUT.pipestatus } epm() { [ -n "$PROGNAME" ] || fatal "Can't use epm call from the piped script" $PROGDIR/$PROGNAME --inscript "$@" } sudoepm() { [ -n "$PROGNAME" ] || fatal "Can't use epm call from the piped script" sudorun $PROGDIR/$PROGNAME --inscript "$@" } fatal() { if [ -z "$TEXTDOMAIN" ] ; then echo "Error: $*" >&2 fi exit 1 } warning() { if [ -z "$TEXTDOMAIN" ] ; then echo "Warning: $*" >&2 fi } info() { [ -n "$quiet" ] && return # print message to stderr if stderr forwarded to (a file) if isatty2 ; then isatty || return 0 echo "$*" else echo "$*" >&2 fi } SUDO_TESTED='' SUDO_CMD='sudo' set_sudo() { local nofail="$1" # cache the result [ -n "$SUDO_TESTED" ] && return "$SUDO_TESTED" SUDO_TESTED="0" SUDO="" # skip SUDO if disabled [ -n "$EPMNOSUDO" ] && return if [ "$DISTRNAME" = "Cygwin" ] || [ "$DISTRNAME" = "Windows" ] ; then # skip sudo using on Windows return fi # if we are root, do not need sudo is_root && return # start error section SUDO_TESTED="1" if ! which $SUDO_CMD >/dev/null 2>/dev/null ; then [ "$nofail" = "nofail" ] || SUDO="fatal 'Can't find sudo. Please install and tune sudo ('# epm install sudo') or run epm under root.'" return "$SUDO_TESTED" fi # if input is a console if inputisatty && isatty && isatty2 ; then if ! $SUDO_CMD -l >/dev/null ; then [ "$nofail" = "nofail" ] || SUDO="fatal 'Can't use sudo (only without password sudo is supported in non interactive using). Please run epm under root.'" return "$SUDO_TESTED" fi else # use sudo if one is tuned and tuned without password if ! $SUDO_CMD -l -n >/dev/null 2>/dev/null ; then [ "$nofail" = "nofail" ] || SUDO="fatal 'Can't use sudo (only without password sudo is supported). Please run epm under root.'" return "$SUDO_TESTED" fi fi SUDO_TESTED="0" SUDO="$SUDO_CMD --" # check for < 1.7 version which do not support -- (and --help possible too) $SUDO_CMD -h 2>/dev/null | grep -q " --" || SUDO="$SUDO_CMD" } withtimeout() { local TO=$(which timeout 2>/dev/null || which gtimeout 2>/dev/null) if [ -x "$TO" ] ; then $TO "$@" return fi # fallback: drop time arg and run without timeout shift "$@" } set_eatmydata() { # skip if disabled [ -n "$EPMNOEATMYDATA" ] && return # use if possible which eatmydata >/dev/null 2>/dev/null || return set_sudo [ -n "$SUDO" ] && SUDO="$SUDO eatmydata" || SUDO="eatmydata" [ -n "$verbose" ] && info "Uwaga! eatmydata is installed, we will use it for disable all sync operations." return 0 } __get_package_for_command() { case "$1" in equery|revdep-rebuild) echo 'gentoolkit' ;; update-kernel|remove-old-kernels) echo 'update-kernel' ;; esac } confirm() { local response # call with a prompt string or use a default read -r -p "${1:-Are you sure? [y/N]} " response case $response in [yY][eE][sS]|[yY]) true ;; *) false ;; esac } confirm_info() { info "$*" if [ -z "$non_interactive" ] ; then confirm "Are you sure? [y/N]" || fatal "Exiting" fi } is_root() { local EFFUID="$(id -u)" [ "$EFFUID" = "0" ] } assure_root() { is_root || fatal "run me only under root" } regexp_subst() { local expression="$1" shift sed -i -r -e "$expression" "$@" } assure_exists() { local package="$2" local textpackage= [ -n "$package" ] || package="$(__get_package_for_command "$1")" [ -n "$3" ] && textpackage=" >= $3" ( direct='' epm_assure "$1" $package $3 ) || fatal "Can't assure in '$1' command from $package$textpackage package" } __set_EGET() { # use internal eget only if exists if [ -s $SHAREDIR/tools_eget ] ; then export EGET="$SHAREDIR/tools_eget" return fi fatal "Internal error: missed tools_eget" # FIXME: we need disable output here, eget can be used for get output assure_exists eget eget 3.3 >/dev/null # use external command, not the function export EGET="$(which eget)" || fatal "Missed command eget from installed package eget" } disabled_eget() { local EGET # use internal eget only if exists if [ -s $SHAREDIR/tools_eget ] ; then $SHAREDIR/tools_eget "$@" return fi fatal "Internal error: missed tools_eget" # FIXME: we need disable output here, eget can be used for get output assure_exists eget eget 3.3 >/dev/null # run external command, not the function EGET=$(which eget) || fatal "Missed command eget from installed package eget" $EGET "$@" } disabled_estrlist() { if [ -s $SHAREDIR/tools_estrlist ] ; then $SHAREDIR/tools_estrlist "$@" return fi fatal "missed tools_estrlist" } estrlist() { internal_tools_estrlist "$@" } eget() { assure_exists wget internal_tools_eget "$@" } get_package_type() { local i case $1 in *.deb) echo "deb" return ;; *.rpm) echo "rpm" return ;; *.txz) echo "txz" return ;; *.tbz) echo "tbz" return ;; *.exe) echo "exe" return ;; *.msi) echo "msi" return ;; *) #fatal "Don't know type of $1" # return package name for info echo "$1" return 1 ;; esac } get_help() { if [ "$0" = "/dev/stdin" ] || [ "$0" = "sh" ] ; then return fi local F="$0" if [ -n "$2" ] ; then is_dirpath "$2" && F="$2" || F="$(dirname $0)/$2" fi cat "$F" | grep -- "# $1" | while read -r n ; do if echo "$n" | grep -q "# $1: PART: " ; then echo echo "$n" | sed -e "s|# $1: PART: ||" continue fi echo "$n" | grep -q "^ *#" && continue opt=`echo $n | sed -e "s|) # $1:.*||g" -e 's|"||g' -e 's@^|@@'` desc=`echo $n | sed -e "s|.*) # $1:||g"` printf " %-20s %s\n" "$opt" "$desc" done } set_distro_info() { # use external distro_info if internal one is missed DISTRVENDOR=internal_distr_info [ -x $DISTRVENDOR ] || DISTRVENDOR=internal_distr_info export DISTRVENDOR [ -n "$DISTRNAME" ] || DISTRNAME=$($DISTRVENDOR -d) || fatal "Can't get distro name." [ -n "$DISTRVERSION" ] || DISTRVERSION=$($DISTRVENDOR -v) if [ -z "$DISTRARCH" ] ; then DISTRARCH=$($DISTRVENDOR --distro-arch) fi DISTRCONTROL="$($DISTRVENDOR -y)" } set_pm_type() { local CMD set_distro_info set_target_pkg_env if [ -n "$FORCEPM" ] ; then PMTYPE=$FORCEPM return fi PMTYPE="$($DISTRVENDOR -g $DISTRNAME/$DISTRVERSION)" } is_active_systemd() { [ "$DISTRCONTROL" = "systemd" ] } assure_distr() { local TEXT="this option" [ -n "$2" ] && TEXT="$2" [ "$DISTRNAME" = "$1" ] || fatal "$TEXT supported only for $1 distro" } get_pkg_name_delimiter() { local pkgtype="$1" [ -n "$pkgtype" ] || pkgtype="$($DISTRVENDOR -p)" [ "$pkgtype" = "deb" ] && echo "_" && return echo "-" } has_space() { estrlist -- has_space "$@" } # File bin/epm-addrepo: ETERSOFTPUBURL=http://download.etersoft.ru/pub ALTLINUXPUBURL=http://ftp.altlinux.org/pub/distributions __epm_addrepo_rhel() { local repo="$@" if [ -z "$repo" ] ; then echo "Add repo." echo "1. Use with repository URL, f.i. http://www.example.com/example.repo" echo "2. Use with epel to add EPEL repository" return 1 fi case "$1" in epel) epm install epel-release return 1 ;; esac return 0 } __epm_addrepo_etersoft_addon() { epm install --skip-installed apt-conf-etersoft-common apt-conf-etersoft-hold || fatal # TODO: ignore only error code 22 (skipped) || fatal local pb="$DISTRVERSION/branch" [ "$DISTRVERSION" = "Sisyphus" ] && pb="$DISTRVERSION" # FIXME [ -n "$DISTRVERSION" ] || fatal "Empty DISTRVERSION" # TODO: use apt-repo add ? echo "" | sudocmd tee -a /etc/apt/sources.list echo "# added with eepm addrepo etersoft" | sudocmd tee -a /etc/apt/sources.list echo "rpm [etersoft] $ETERSOFTPUBURL/Etersoft LINUX@Etersoft/$pb/$DISTRARCH addon" | sudocmd tee -a /etc/apt/sources.list if [ "$DISTRARCH" = "x86_64" ] ; then echo "rpm [etersoft] $ETERSOFTPUBURL/Etersoft LINUX@Etersoft/$pb/x86_64-i586 addon" | sudocmd tee -a /etc/apt/sources.list fi echo "rpm [etersoft] $ETERSOFTPUBURL/Etersoft LINUX@Etersoft/$pb/noarch addon" | sudocmd tee -a /etc/apt/sources.list } __epm_addrepo_altlinux() { local repo="$*" local branch="$(echo "$DISTRVERSION" | tr "[:upper:]" "[:lower:]")" [ -n "$branch" ] || fatal "Empty DISTRVERSION" if [ -z "$repo" ] || [ "$repo" == "--help" ] ; then info "Add branch repo. Use follow params:" sudocmd apt-repo $dryrun add branch echo "etersoft - for LINUX@Etersoft repo" echo "basealt - for BaseALT repo" echo "yandex - for BaseALT repo mirror on yandex (recommended)" echo "<task number> - add task repo" echo "archive 2018/02/09 - for archive from that date" echo "autoimports - for BaseALT autoimports repo" return fi case "$1" in etersoft) info "add Etersoft's addon repo" assure_exists apt-repo __epm_addrepo_etersoft_addon sudocmd apt-repo add $branch epm repofix etersoft return 0 ;; basealt|altlinux) # TODO: setrepo? assure_exists apt-repo sudocmd apt-repo add $branch return 0 ;; yandex) assure_exists apt-repo sudocmd apt-repo add $branch epm repofix yandex return 0 ;; autoimports) repo="autoimports.$branch" ;; archive) datestr="$2" echo "$datestr" | grep -Eq "^20[0-2][0-9]/[01][0-9]/[0-3][0-9]$" || fatal "use follow date format: 2017/12/31" echo "" | sudocmd tee -a /etc/apt/sources.list local distrversion="$(echo "$DISTRVERSION" | tr "[:upper:]" "[:lower:]")" local rpmsign='[alt]' [ "$distrversion" != "sisyphus" ] && rpmsign="[$distrversion]" echo "rpm $rpmsign $ALTLINUXPUBURL archive/$distrversion/date/$datestr/$DISTRARCH classic" | sudocmd tee -a /etc/apt/sources.list if [ "$DISTRARCH" = "x86_64" ] ; then echo "rpm $rpmsign $ALTLINUXPUBURL archive/$distrversion/date/$datestr/x86_64-i586 classic" | sudocmd tee -a /etc/apt/sources.list fi echo "rpm $rpmsign $ALTLINUXPUBURL archive/$distrversion/date/$datestr/noarch classic" | sudocmd tee -a /etc/apt/sources.list return 0 ;; esac assure_exists apt-repo if tasknumber "$repo" >/dev/null ; then sudocmd_foreach "apt-repo $dryrun add" $(tasknumber "$repo") return fi sudocmd apt-repo $dryrun add "$repo" } __epm_addkey_deb() { local url="$1" local fingerprint="$2" if [ -z "$fingerprint" ] ; then assure_exists curl set_sudo showcmd "curl -fsSL '$url' | $SUDO apt-key add -" a= curl -fsSL "$url" | sudorun apt-key add - return fi sudocmd apt-key adv --keyserver "$url" --recv "$fingerprint" } __epm_addrepo_deb() { assure_exists apt-add-repository software-properties-common local ad="$($DISTRVENDOR --distro-arch)" # TODO: move to distro_info local nd="$(lsb_release -cs)" local repo="$*" if [ -z "$repo" ] || [ "$repo" = "--help" ]; then info "Add repo. You can use follow params:" echo " docker - add official docker repo" echo " ppa:<user>/<ppa-name> - add PPA repo" echo " distribution component name" echo " full sources list line" echo " URL version component" return fi if [ "$DISTRNAME" = "AstraLinux" ] ; then echo "Use workaround for AstraLinux" # aptsources.distro.NoDistroTemplateException: Error: could not find a distribution template for AstraLinuxCE/orel echo "" | sudocmd tee -a /etc/apt/sources.list echo "$repo" | sudocmd tee -a /etc/apt/sources.list exit fi # keywords case "$1" in docker) __epm_addkey_deb https://download.docker.com/linux/$PKGVENDOR/gpg "9DC858229FC7DD38854AE2D88D81803C0EBFCD88" repo="https://download.docker.com/linux/$PKGVENDOR $nd stable" ;; esac # if started from url, use heroistic if echo "$repo" | egrep -q "^https?://" ; then repo="deb [arch=$ad] $repo" fi if echo "$repo" | grep -q "https://" ; then assure_exists /usr/share/doc/apt-transport-https apt-transport-https assure_exists /usr/sbin/update-ca-certificates ca-certificates fi # FIXME: quotes in showcmd/sudocmd showcmd apt-add-repository "$repo" sudorun apt-add-repository "$repo" info "Check file /etc/apt/sources.list if needed" } epm_addrepo() { local repo="$*" case $DISTRNAME in ALTLinux) # Note! Don't use quotes here __epm_addrepo_altlinux $repo return ;; esac case $PMTYPE in apt-dpkg) # Note! Don't use quotes here __epm_addrepo_deb $repo ;; aptitude-dpkg) info "You need manually add repo to /etc/apt/sources.list (TODO)" ;; yum-rpm) assure_exists yum-utils __epm_addrepo_rhel "$repo" || return sudocmd yum-config-manager --add-repo "$repo" ;; dnf-rpm) __epm_addrepo_rhel "$repo" || return sudocmd dnf config-manager --add-repo "$repo" ;; urpm-rpm) sudocmd urpmi.addmedia "$repo" ;; zypper-rpm) sudocmd zypper ar "$repo" ;; emerge) sudocmd layman -a "$repo" ;; pacman) info "You need manually add repo to /etc/pacman.conf" # Only for alone packages: #sudocmd repo-add $pkg_filenames ;; npackd) sudocmd npackdcl add-repo --url="$repo" ;; winget) sudocmd winget source add "$repo" ;; slackpkg) info "You need manually add repo to /etc/slackpkg/mirrors" ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-assure: __check_command_in_path() { PATH=$PATH:/sbin:/usr/sbin which "$1" 2>/dev/null } __epm_need_update() { local PACKAGE="$1" local PACKAGEVERSION="$2" [ -n "$PACKAGEVERSION" ] || return 0 is_installed "$PACKAGE" || return 0 # epm print version for package N local INSTALLEDVERSION=$(query_package_field "version" "$PACKAGE") # if needed >= installed, return 0 [ "$(compare_version "$PACKAGEVERSION" "$INSTALLEDVERSION")" -gt 0 ] && return 0 return 1 } __epm_assure_checking() { local CMD="$1" local PACKAGE="$2" local PACKAGEVERSION="$3" [ -n "$PACKAGEVERSION" ] && return 1 if is_dirpath "$CMD" ; then # TODO: check for /usr/bin, /bin, /usr/sbin, /sbin if [ -e "$CMD" ] ; then if [ -n "$verbose" ] ; then info "File or directory $CMD is already exists." epm qf "$CMD" fi return 0 fi [ -n "$PACKAGE" ] || fatal "You need run with package name param when use with absolute path to non executable file" return 1 fi if __check_command_in_path "$CMD" >/dev/null ; then if [ -n "$verbose" ] ; then local compath="$(__check_command_in_path "$1")" info "Command $CMD is exists: $compath" epm qf "$compath" fi return 0 fi return 1 } epm_assure() { local CMD="$1" local PACKAGE="$2" local PACKAGEVERSION="$3" [ -n "$PACKAGE" ] || PACKAGE="$1" __epm_assure_checking $CMD $PACKAGE $PACKAGEVERSION && return 0 info "Installing appropriate package for $CMD command..." __epm_need_update $PACKAGE $PACKAGEVERSION || return 0 # can't be used in epm ei case #docmd epm --auto install $PACKAGE || return # TODO: HACK: DEBUG=1 for skip to_remove_pkg handling (DEBUG=1 repack='' non_interactive=1 pkg_names="$PACKAGE" pkg_files='' pkg_urls='' epm_install ) || return # no check if we don't need a version [ -n "$PACKAGEVERSION" ] || return 0 # check if we couldn't update and still need update __epm_need_update $PACKAGE $PACKAGEVERSION && return 1 return 0 } # File bin/epm-audit: epm_audit() { [ -z "$pkg_filenames" ] || fatal "No arguments are allowed here" case $PMTYPE in pkgng) sudocmd pkg audit -F ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-autoorphans: __epm_orphan_altrpm() { docmd "apt-cache list-extras" } epm_autoorphans() { [ -z "$*" ] || fatal "No arguments are allowed here" case $PMTYPE in apt-rpm) # ALT Linux only assure_exists /usr/share/apt/scripts/list-extras.lua apt-scripts if [ -z "$dryrun" ] ; then echo "We will try remove all installed packages which are missed in repositories" warning "Use with caution!" fi epm Upgrade || fatal local PKGLIST=$(__epm_orphan_altrpm \ | sed -e "s/\.32bit//g" \ | grep -v -- "^eepm$" \ | grep -v -- "^distro_info$" \ | grep -v -- "^kernel") if [ -z "$dryrun" ] && [ -n "$PKGLIST" ] ; then showcmd epm remove $dryrun $force $PKGLIST confirm_info "We will remove packages above." fi docmd epm remove $dryrun $force $(subst_option non_interactive --auto) $PKGLIST ;; apt-dpkg|aptitude-dpkg) assure_exists deborphan showcmd deborphan a='' deborphan | docmd epm remove $dryrun ;; #aura) # sudocmd aura -Oj # ;; yum-rpm) docmd epm upgrade assure_exists package-cleanup yum-utils showcmd package-cleanup --orphans local PKGLIST=$(package-cleanup -q --orphans | grep -v "^eepm-") docmd epm remove $dryrun $PKGLIST ;; dnf-rpm) # TODO: dnf list extras docmd epm upgrade assure_exists package-cleanup dnf-utils showcmd package-cleanup --orphans local PKGLIST=$(package-cleanup -q --orphans | grep -v "^eepm-") docmd epm remove $dryrun $PKGLIST ;; urpm-rpm) if [ -n "$dryrun" ] ; then fatal "--dry-run is not supported yet" else showcmd urpme --report-orphans sudocmd urpme --auto-orphans fi ;; #emerge) # sudocmd emerge --depclean # assure_exists revdep-rebuild # sudocmd revdep-rebuild # ;; pacman) if [ -n "$dryrun" ] ; then info "Autoorphans packages list:" sudocmd pacman -Qdtq else sudocmd pacman -Qdtq | sudocmd pacman -Rs - fi ;; slackpkg) # clean-system removes non official packages sudocmd slackpkg clean-system ;; #guix) # sudocmd guix gc # ;; #pkgng) # sudocmd pkg autoremove # ;; zypper-rpm) # https://www.linux.org.ru/forum/desktop/11931830 assure_exists zypper zypper 1.9.2 # For zypper < 1.9.2: zypper se -si | grep 'System Packages' sudocmd zypper packages --orphaned # FIXME: x86_64/i586 are duplicated local PKGLIST=$(zypper packages --orphaned | tail -n +5 | cut -d \| -f 3 | sort -u) docmd epm remove $dryrun --clean-deps $PKGLIST ;; xbps) if [ -n "$dryrun" ] ; then fatal "--dry-run is not supported yet" else sudocmd xbps-remove -o fi ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-autoremove: __epm_print_excluded() { local pkgs="$1" local fullpkgs="$2" local excluded excluded="$(estrlist exclude "$pkgs" "$fullpkgs")" if [ -n "$excluded" ] ; then echo "Skipped manually installed:" estrlist union $excluded fi } __epm_autoremove_altrpm_pp() { local pkgs fullpkgs info "Removing unused python/perl modules..." local libexclude="$1" local flag= showcmd "apt-cache list-nodeps | grep -E -- \"$libexclude\"" fullpkgs=$(apt-cache list-nodeps | grep -E -- "$libexclude" ) pkgs=$(skip_manually_installed $fullpkgs) if [ -n "$dryrun" ] ; then info "Packages for autoremoving:" echo "$pkgs" __epm_print_excluded "$pkgs" "$fullpkgs" return 0 fi if [ -n "$pkgs" ] ; then info "The command we will run:" showcmd rpm -v -e $pkgs __epm_print_excluded "$pkgs" "$fullpkgs" confirm_info "We will remove unused (without dependencies) packages above." sudocmd rpm -v -e $pkgs && flag=1 fi if [ -n "$flag" ] ; then info "" info "call again for next cycle until all modules will be removed" __epm_autoremove_altrpm_pp "$libexclude" fi return 0 } __epm_autoremove_altrpm_package_group() { if epmqp "$*" ; then confirm_info "We will remove unused (without dependencies) packages above." docmd epm remove $(epmqp --short "$*") fi } __epm_autoremove_altrpm_lib() { local pkgs fullpkgs local flag='' local opt="$1" local libgrep='' info case "$opt" in libs) info "Removing all non -devel/-debuginfo libs packages not need by anything..." local develrule='-(devel|devel-static)$' libgrep='^(lib|bzlib|zlib)' ;; i586-libs) info "Removing all non -devel/-debuginfo i586-libs packages not need by anything..." local develrule='-(devel|devel-static)$' libgrep='^(i586-lib|i586-bzlib|i586-zlib)' ;; devel) info "Removing all non -debuginfo libs packages (-devel too) not need by anything..." local develrule='-(NONONO)$' libgrep='^(lib|bzlib|zlib)' ;; *) fatal "Internal error: unsupported opt $opt" esac # https://www.altlinux.org/APT_в_ALT_Linux/Советы_по_использованию#apt-cache_list-nodeps showcmd "apt-cache list-nodeps | grep -E -- \"$libgrep\"" fullpkgs=$(apt-cache list-nodeps | grep -E -- "$libgrep" \ | sed -e "s/[-\.]32bit$//g" \ | grep -E -v -- "$develrule" \ | grep -E -v -- "-(debuginfo)$" \ | grep -E -v -- "-(util|utils|tool|tools|plugin|daemon|help)$" \ | grep -E -v -- "^(libsystemd|libreoffice|libnss|libvirt-client|libvirt-daemon|libsasl2-plugin|eepm|distro_info)" ) pkgs=$(skip_manually_installed $fullpkgs) if [ -n "$dryrun" ] ; then info "Packages for autoremoving:" echo "$pkgs" __epm_print_excluded "$pkgs" "$fullpkgs" return 0 fi if [ -n "$pkgs" ] ; then info "The command we will run:" showcmd rpm -v -e $pkgs __epm_print_excluded "$pkgs" "$fullpkgs" confirm_info "We will remove unused (without dependencies) packages above." sudocmd rpm -v -e $pkgs && flag=1 fi if [ -n "$flag" ] ; then info "" info "call again for next cycle until all libs will be removed" __epm_autoremove_altrpm_lib $opt fi return 0 } epm_autoremove_default_groups="python2 python3 perl gem ruby libs" __epm_autoremove_altrpm() { local i assure_exists /usr/share/apt/scripts/list-nodeps.lua apt-scripts if [ -z "$pkg_names" ] ; then pkg_names="$epm_autoremove_default_groups" elif [ "$pkg_names" = "python" ] ; then pkg_names="python2 python3" fi for i in $pkg_names ; do case $i in libs) __epm_autoremove_altrpm_lib libs ;; i586-libs) __epm_autoremove_altrpm_lib i586-libs ;; debuginfo) __epm_autoremove_altrpm_package_group '-debuginfo-' ;; devel) __epm_autoremove_altrpm_package_group '^(rpm-build-|gcc-|glibc-devel-)' ;; python2) __epm_autoremove_altrpm_pp '^(python-module-|python-modules-)' ;; python3) __epm_autoremove_altrpm_pp '^(python3-module-|python3-modules-)' ;; php) __epm_autoremove_altrpm_pp '^(php7-|php5-|php8-)' ;; gem) __epm_autoremove_altrpm_pp '^(gem-)' ;; ruby) __epm_autoremove_altrpm_pp '^(ruby-)' ;; perl) __epm_autoremove_altrpm_pp '^(perl-)' ;; libs-devel) __epm_autoremove_altrpm_lib devel ;; *) fatal "autoremove: unsupported '$i'. Use epm autoremove --help to list supported ones" ;; esac done return 0 } epm_autoremove_print_help() { echo "epm autoremove removes unneeded packages from the system" echo "run 'epm autoremove' to use apt-get autoremove" echo "or run 'epm autoremove --direct [group1] [group2] ...' to use epm implementation" echo "Default groups: $epm_autoremove_default_groups" cat <<EOF Supported package groups: libs - unused libraries libs-devel - unused -devel packages i586-libs - unused i586-libs libraries debuginfo - all debuginfo packages devel - all packages used for build/developing python - all python modules python2 - python2 modules python3 - python3 modules perl - perl modules gem - gem modules ruby - ruby modules Use --auto|--assumeyes|--non-interactive for non interactive mode EOF } epm_autoremove() { case $DISTRNAME in ALTLinux) if [ "$1" = "-h" ] || [ "$1" = "--help" ] || [ "$1" = "help" ] ; then epm_autoremove_print_help return 0 fi if [ -z "$direct" ] ; then [ -n "$1" ] && fatal "Run autoremove without args or with --direct. Check epm autoremove --help to available commands." sudocmd apt-get $(subst_option non_interactive -y) autoremove $dryrun local RET=$? if [ "$RET" != 0 ] ; then echo info "Also you can run 'epm autoremove --direct' to use epm implementation of autoremove (see --help)" return fi else __epm_autoremove_altrpm "$@" fi [ -n "$dryrun" ] && return # remove old kernels only by a default way [ -n "$1" ] && return docmd epm remove-old-kernels $(subst_option non_interactive --auto) if [ -z "$direct" ] ; then echo info "Also you can run 'epm autoremove --direct' to use epm implementation of autoremove (see --help)" fi return ;; *) ;; esac [ -z "$pkg_filenames" ] || fatal "No arguments are allowed here" case $PMTYPE in apt-dpkg|aptitude-dpkg) sudocmd apt-get autoremove $dryrun ;; aura) if [ -n "$dryrun" ] ; then fatal "--dry-run is not supported yet" fi sudocmd aura -Oj ;; packagekit) docmd pkcon repair --autoremove ;; yum-rpm) # cleanup orphanes? while true ; do # shellcheck disable=SC2046 docmd package-cleanup --leaves $(subst_option non_interactive --assumeyes) # FIXME: package-cleanup have to use stderr for errors local PKGLIST=$(package-cleanup -q --leaves | grep -v "^eepm-") [ -n "$PKGLIST" ] || break showcmd epm remove $PKGLIST done ;; dnf-rpm) if [ -n "$dryrun" ] ; then fatal "--dry-run is not supported yet" fi sudocmd dnf autoremove ;; # see autoorhans #urpm-rpm) # sudocmd urpme --auto-orphans # ;; emerge) if [ -n "$dryrun" ] ; then fatal "--dry-run is not supported yet" fi sudocmd emerge --depclean assure_exists revdep-rebuild sudocmd revdep-rebuild ;; # see autoorhans #pacman) # sudocmd pacman -Qdtq | sudocmd pacman -Rs - # ;; slackpkg) # clean-system removes non official packages #sudocmd slackpkg clean-system ;; guix) sudocmd guix gc ;; pkgng) sudocmd pkg autoremove ;; zypper-rpm) # https://www.linux.org.ru/forum/desktop/11931830 assure_exists zypper zypper 1.9.3 sudocmd zypper packages --unneeded # FIXME: x86_64/i586 are duplicated local PKGLIST=$(zypper packages --unneeded | tail -n +5 | cut -d \| -f 3 | sort -u) showcmd epm remove --clean-deps $PKGLIST ;; xbps) if [ -n "$dryrun" ] ; then fatal "--dry-run is not supported yet" fi sudocmd xbps-remove -O ;; opkg) if [ -n "$dryrun" ] ; then sudocmd opkg --noaction --autoremove else sudocmd opkg --autoremove fi ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-changelog: __epm_changelog_apt() { local i for i in $@ ; do docmd apt-cache show $i | grep -A 1000 "^Changelog:" done } __epm_changelog_files() { [ -z "$*" ] && return # TODO: detect every file case $(get_package_type $1) in rpm) assure_exists rpm docmd_foreach "rpm -q -p --changelog" $@ | less ;; *) fatal "Have no suitable command for $1" ;; esac } __epm_changelog_local_names() { [ -z "$*" ] && return case $PMTYPE in apt-rpm|yum-rpm|dnf-rpm|urpm-rpm|zypper-rpm) docmd_foreach "rpm -q --changelog" $@ | less ;; apt-dpkg|aptitude-dpkg) docmd zcat /usr/share/doc/$1/changelog.Debian.gz | less ;; emerge) assure_exists equery docmd equery changes -f $1 | less ;; pacman) docmd pacman -Qc $1 | less ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } __epm_changelog_unlocal_names() { [ -z "$*" ] && return case $PMTYPE in apt-rpm) __epm_changelog_apt $@ | less ;; #apt-dpkg) # # FIXME: only first pkg # docmd zcat /usr/share/doc/$1/changelog.Debian.gz | less # ;; #yum-rpm) # sudocmd yum clean all # ;; urpm-rpm) docmd urpmq --changelog $@ | less ;; #zypper-rpm) # sudocmd zypper clean # ;; emerge) assure_exists equery docmd equery changes -f $1 | less ;; *) fatal "Have no suitable command for $PMTYPE. Try install the package firstly." ;; esac } epm_changelog() { [ -n "$pkg_filenames" ] || fatal "Changelog: Missing package(s) name" __epm_changelog_files $pkg_files local pkg for pkg in $pkg_names ; do if is_installed $pkg ; then __epm_changelog_local_names $pkg else __epm_changelog_unlocal_names $pkg fi done } # File bin/epm-check: epm_check() { case $PMTYPE in apt-rpm) #sudocmd apt-get check || exit #sudocmd apt-get update || exit sudocmd apt-get -f install || return info "You can use epm dedup also" ;; apt-dpkg) #sudocmd apt-get check || exit #sudocmd apt-get update || exit sudocmd apt-get -f install || return ;; apt-dpkg) #sudocmd apt-get update || exit #sudocmd apt-get check || exit sudocmd apt-get -f install || return #sudocmd apt-get autoremove ;; packagekit) docmd pkcon repair ;; aptitude-dpkg) sudocmd aptitude -f install || return #sudocmd apt-get autoremove ;; yum-rpm) docmd yum check docmd package-cleanup --problems #docmd package-cleanup --dupes sudocmd package-cleanup --cleandupes docmd rpm -Va --nofiles --nodigest ;; dnf-rpm) sudocmd dnf check ;; emerge) sudocmd revdep-rebuild ;; #urpm-rpm) # sudocmd urpme --auto-orphans # ;; zypper-rpm) sudocmd zypper verify ;; conary) sudocmd conary verify ;; pkgng) sudocmd pkg check -d -a ;; homebrew) docmd brew doctor ;; xbps) sudocmd xbps-pkgdb -a ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-checkpkg: __rpm_allows_nosignature() { a= rpm --help | grep -q -- "--nosignature" } check_pkg_integrity() { local PKG="$1" local RET local NOSIGNATURE case $(get_package_type $PKG) in rpm) assure_exists rpm __rpm_allows_nosignature && NOSIGNATURE="--nosignature" || NOSIGNATURE="--nogpg" docmd rpm --checksig $NOSIGNATURE $PKG ;; deb) assure_exists dpkg # FIXME: debsums -ca package ? docmd dpkg --contents $PKG >/dev/null && echo "Package $PKG is correct." ;; exe) file $PKG | grep -q "executable for MS Windows" ;; msi) # TODO: add to patool via cabextract assure_exists cabextract #file $PKG | grep -q "Microsoft Office Document" docmd cabextract -t $PKG ;; ebuild) true ;; *) assure_exists erc docmd erc test "$PKG" && return ;; esac } __epm_check_installed_pkg() { case $PMTYPE in *-rpm) docmd rpm -V $@ ;; *-dpkg) assure_exists debsums docmd debsums $@ ;; emerge) assure_exists equery docmd equery check $@ ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } epm_checkpkg() { if [ -n "$pkg_names" ] ; then # TODO: если есть / или расширение, это отсутствующий файл info "Suggest $pkg_names are name(s) of installed package(s)" __epm_check_installed_pkg $pkg_names return fi # if possible, it will put pkg_urls into pkg_files or pkg_names if [ -n "$pkg_urls" ] ; then __handle_pkg_urls_to_checking fi [ -n "$pkg_files" ] || fatal "Checkpkg: filename(s) is missed" local RETVAL=0 local pkg for pkg in $pkg_files ; do check_pkg_integrity $pkg || RETVAL=1 done # TODO: reinvent [ -n "$to_remove_pkg_files" ] && rm -fv $to_remove_pkg_files [ -n "$to_remove_pkg_files" ] && rmdir -v $(dirname $to_remove_pkg_files | head -n1) 2>/dev/null #fatal "Broken package $pkg" return $RETVAL } # File bin/epm-checksystem: epm_checksystem_ALTLinux() { local TDIR=$(mktemp -d) assure_exists time touch $TDIR/added for ft in $(ls /usr/lib/rpm/*.filetrigger | sort) ; do echo "Try run $ft ..." echo $TDIR/added $TDIR/removed | a='' time $ft done rm -f $TDIR/added fatal rmdir $TDIR || fatal echo "Count lines:" wc -l /var/lib/rpm/files-awaiting-filetriggers } epm_checksystem() { is_root && fatal "Do not use checksystem under root" case $PMTYPE in homebrew) sudocmd brew doctor return ;; esac case $DISTRNAME in ALTLinux) epm_checksystem_$DISTRNAME ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } if [ "$1" = "--debug" ] ; then shift SUDO=sudo DISTRNAME=ALTLinux epm_checksystem fi # File bin/epm-check_updated_repo: __is_repo_info_downloaded() { case $PMTYPE in apt-*) #if [ -r /var/cache/apt ] ; then # sudorun test -r /var/cache/apt/pkgcache.bin || return #fi ;; *) ;; esac return 0 } __is_repo_info_uptodate() { case $PMTYPE in apt-*) # apt-deb do not update lock file date #if $SUDO test -r /var/lib/apt/lists ; then local LOCKFILE=/var/lib/apt/lists sudorun test -r $LOCKFILE || return # if repo older than 1 day, return false # find print string if file is obsoleted test -z "$(find $LOCKFILE -maxdepth 0 -mtime +1)" || return #fi ;; *) ;; esac return 0 } update_repo_if_needed() { # check if we need skip update checking if [ "$1" = "soft" ] && ! set_sudo nofail ; then # if sudo requires a password, skip autoupdate info "can't use sudo, so skip repo status checking" return 1 fi cd / || fatal if ! __is_repo_info_downloaded || ! __is_repo_info_uptodate ; then # FIXME: cleans!!! epm_update fi cd - >/dev/null || fatal } save_installed_packages() { [ -d /var/lib/rpm ] || return 0 estrlist list "$@" | sudorun tee /var/lib/rpm/EPM-installed >/dev/null } check_manually_installed() { [ -r /var/lib/rpm/EPM-installed ] || return 1 grep -q -- "^$1\$" /var/lib/rpm/EPM-installed } skip_manually_installed() { local i for i in "$@" ; do check_manually_installed "$i" && continue echo "$i" done } # File bin/epm-clean: __remove_alt_apt_cache_file() { sudocmd rm -vf /var/cache/apt/*.bin sudocmd rm -vf /var/cache/apt/partial/* sudocmd rm -vf /var/lib/apt/lists/*pkglist* sudocmd rm -vf /var/lib/apt/lists/*release* } __remove_deb_apt_cache_file() { sudocmd rm -vf /var/cache/apt/*.bin sudocmd rm -vf /var/cache/apt/archives/partial/* sudocmd rm -vf /var/lib/apt/lists/*Packages* sudocmd rm -vf /var/lib/apt/lists/*Release* sudocmd rm -vf /var/lib/apt/lists/*Translation* } epm_clean() { [ -z "$*" ] || fatal "No arguments are allowed here" case $PMTYPE in apt-rpm) sudocmd apt-get clean [ -n "$force" ] && __remove_alt_apt_cache_file ;; apt-dpkg) sudocmd apt-get clean [ -n "$force" ] && __remove_deb_apt_cache_file ;; aptitude-dpkg) sudocmd aptitude clean [ -n "$force" ] && __remove_deb_apt_cache_file ;; yum-rpm) sudocmd yum clean all #sudocmd yum makecache ;; dnf-rpm) sudocmd dnf clean all ;; urpm-rpm) sudocmd urpmi --clean ;; homebrew) sudocmd brew cleanup -s ;; pacman) sudocmd pacman -Sc --noconfirm ;; zypper-rpm) sudocmd zypper clean ;; nix) sudocmd nix-collect-garbage ;; slackpkg) ;; pkgng) sudocmd pkg clean -a ;; appget|winget) sudocmd $PMTYPE clean ;; xbps) sudocmd xbps-remove -O ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac info "It is recommend to run 'epm autoremove' also" } # File bin/epm-conflicts: epm_conflicts_files() { [ -n "$pkg_files" ] || return case $(get_package_type $pkg_files) in rpm) assure_exists rpm docmd "rpm -q --conflicts -p" $pkg_files ;; #deb) # a= docmd dpkg -I $pkg_files | grep "^ *Depends:" | sed "s|^ *Depends:||g" # ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } epm_conflicts_names() { local CMD [ -n "$pkg_names" ] || return case $PMTYPE in apt-rpm) # FIXME: need fix for a few names case # FIXME: too low level of requires name (libSOME.so) if is_installed $pkg_names ; then CMD="rpm -q --conflicts" else EXTRA_SHOWDOCMD=' | grep "Conflicts:"' docmd apt-cache show $pkg_names | grep "Conflicts:" return fi ;; urpm-rpm|zypper-rpm) # FIXME: use hi level commands CMD="rpm -q --conflicts" ;; #yum-rpm) # CMD="yum deplist" # ;; #pacman) # CMD="pactree" # ;; apt-dpkg) # FIXME: need fix for a few names case if is_installed $pkg_names ; then showcmd dpkg -s $pkg_names a='' dpkg -s $pkg_names | grep "^Conflicts:" | sed "s|^Conflicts:||g" return else EXTRA_SHOWDOCMD=' | grep "Conflicts:"' docmd apt-cache show $pkg_names | grep "Conflicts:" return fi ;; # TODO: why-not show who conflicts with us #aptitude-dpkg) # docmd aptitude why-not $pkg_names # ;; #emerge) # assure_exists equery # CMD="equery depgraph" # ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac docmd $CMD $pkg_names } epm_conflicts() { [ -n "$pkg_filenames" ] || fatal "Conflicts: Missing package(s) name" epm_conflicts_files epm_conflicts_names } # File bin/epm-dedup: try_fix_apt_rpm_dupls() { info "Check for duplicates (internal implementation) ..." local TESTPKG="ignoreflock" local has_testpkg="" if epm --quiet installed $TESTPKG ; then has_testpkg=1 sudocmd epm remove --auto $TESTPKG || return fi local PKGLIST PKGLIST=$(LANG=C sudorun apt-get install $TESTPKG 2>&1 | grep "W: There are multiple versions of" | \ sed -e 's|W: There are multiple versions of "\(.*\)" in your system.|\1|') local TODEL for i in $PKGLIST ; do local pkg=${i/.32bit/} local todel="$(rpm -q $pkg | head -n1)" local todel2="$(rpm -q $pkg | head -n2 | tail -n1)" if [ "$todel" = "$todel2" ] ; then echo "Fix the same name duplicates for $pkg..." sudocmd rpm -e "$todel" --allmatches --nodeps --justdb && epm install $pkg && continue fi # first use older package [ "$(rpmevrcmp "$todel" "$todel2")" = "1" ] && todel="$todel2" sudocmd rpm -e "$todel" || TODEL="$TODEL $todel" done [ -n "$TODEL" ] && sudocmd rpm -e $TODEL [ -n "$has_testpkg" ] && epm install $TESTPKG } epm_dedup() { case "$DISTRNAME" in "ALTLinux") assure_exists /usr/share/apt/scripts/dedup.lua apt-scripts if [ -z "$direct" ] && [ -f /usr/share/apt/scripts/dedup.lua ] ; then info "Check for duplicates via apt-get dedup from apt-scripts (also you can use internal EPM dedup implementation with --direct option)" sudocmd apt-get dedup else info "You can use dedup from apt-scripts package" try_fix_apt_rpm_dupls fi ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-downgrade: __epm_add_alt_apt_downgrade_preferences() { [ -r /etc/apt/preferences ] && fatal "/etc/apt/preferences already exists" cat <<EOF | sudocmd tee /etc/apt/preferences Package: * Pin: release c=classic Pin-Priority: 1001 Package: * Pin: release c=addon Pin-Priority: 1101 Package: * Pin: release c=task Pin-Priority: 1201 EOF } __epm_add_deb_apt_downgrade_preferences() { [ -r /etc/apt/preferences ] && fatal "/etc/apt/preferences already exists" info "Running with /etc/apt/preferences:" cat <<EOF | sudorun tee /etc/apt/preferences Package: * Pin: release a=stable Pin-Priority: 1001 Package: * Pin: release a=testing Pin-Priority: 900 Package: * Pin: release a=unstable Pin-Priority: 800 EOF } __epm_remove_apt_downgrade_preferences() { sudocmd rm -f /etc/apt/preferences } epm_downgrade() { local CMD # it is useful for first time running update_repo_if_needed info "Running command for downgrade packages" case $PMTYPE in apt-rpm) # pass pkg_filenames too if [ -n "$pkg_names" ] ; then __epm_add_alt_apt_downgrade_preferences || return (pkg_names=$(get_only_installed_packages $pkg_names) epm_install) __epm_remove_apt_downgrade_preferences elif [ -n "$pkg_files" ] ; then (pkg_files=$pkg_files force="$force -F --oldpackage" epm_install) else __epm_add_alt_apt_downgrade_preferences || return epm_upgrade "$@" __epm_remove_apt_downgrade_preferences fi ;; apt-dpkg) local APTOPTIONS="$(subst_option non_interactive -y) $force_yes" __epm_add_deb_apt_downgrade_preferences || return if [ -n "$pkg_filenames" ] ; then sudocmd apt-get $APTOPTIONS install $pkg_filenames else sudocmd apt-get $APTOPTIONS dist-upgrade fi __epm_remove_apt_downgrade_preferences ;; yum-rpm) # can do update repobase automagically if [ -n "$pkg_filenames" ] ; then sudocmd yum downgrade $pkg_filenames else sudocmd yum distro-sync fi ;; dnf-rpm) if [ -n "$pkg_filenames" ] ; then sudocmd dnf downgrade $pkg_filenames else sudocmd dnf distro-sync fi ;; urpm-rpm) assure_exists urpm-reposync urpm-tools sudocmd urpm-reposync -v ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-download: alt_base_dist_url="http://ftp.basealt.ru/pub/distributions" __use_url_install() { # force download if wildcard is used echo "$pkg_urls" | grep -q "[?*]" && return 1 # install of remote files has a side affect # (more fresh package from a repo can be installed instead of the file) #case $DISTRNAME in # "ALTLinux") # # do not support https yet # echo "$pkg_urls" | grep -q "https://" && return 1 # pkg_names="$pkg_names $pkg_urls" # return 0 # ;; #esac case $PMTYPE in #apt-rpm) # pkg_names="$pkg_names $pkg_urls" # ;; #deepsolver-rpm) # pkg_names="$pkg_names $pkg_urls" # ;; #urpm-rpm) # pkg_names="$pkg_names $pkg_urls" # ;; pacman) pkg_names="$pkg_names $pkg_urls" ;; yum-rpm|dnf-rpm) pkg_names="$pkg_names $pkg_urls" ;; #zypper-rpm) # pkg_names="$pkg_names $pkg_urls" # ;; *) return 1 ;; esac return 0 } __download_pkg_urls() { local url [ -z "$pkg_urls" ] && return for url in $pkg_urls ; do local tmppkg=$(mktemp -d) || fatal "failed mktemp -d" showcmd cd $tmppkg cd $tmppkg || fatal if docmd eget --latest "$url" ; then local i for i in $(basename $url) ; do [ -s "$tmppkg/$i" ] || continue pkg_files="$pkg_files $tmppkg/$i" to_remove_pkg_files="$to_remove_pkg_files $tmppkg/$i" done else warning "Failed to download $url, ignoring" fi cd - >/dev/null done # reconstruct pkg_filenames=$(strip_spaces "$pkg_files $pkg_names") } __handle_pkg_urls_to_install() { #[ -n "$pkg_urls" ] || return # TODO: do it correctly to_remove_pkg_files= # FIXME: check type of pkg_urls separately? if [ "$(get_package_type "$pkg_urls")" != $PKGFORMAT ] || ! __use_url_install ; then # use workaround with eget: download and put in pkg_files __download_pkg_urls fi pkg_urls= } __handle_pkg_urls_to_checking() { #[ -n "$pkg_urls" ] || return # TODO: do it correctly to_remove_pkg_files= # use workaround with eget: download and put in pkg_files __download_pkg_urls pkg_urls= } __epm_get_altpkg_url() { info "TODO: https://packages.altlinux.org/api/branches" local arch=$(paoapi packages/$1 | get_pao_var arch) # FIXME: arch can be list [ "$arch" = "noarch" ] || arch=$(arch) # HACK: filename can be list local filename=$(paoapi packages/$1 | get_pao_var filename | grep $arch) [ -n "$filename" ] || fatal "Can't get filename" # fixme: get from /branches local dv=$DISTRNAME/$DISTRVERSION/branch [ "$DISTRVERSION" = "Sisyphus" ] && dv=$DISTRNAME/$DISTRVERSION echo "$alt_base_dist_url/$dv/$arch/RPMS.classic/$filename" } __epm_print_url_alt() { local url="$1" echo "$url" echo "$url" | sed -e "s|$alt_base_dist_url/$DISTRNAME|http://mirror.yandex.ru/altlinux|g" echo "$url" | sed -e "s|$alt_base_dist_url/$DISTRNAME|http://download.etersoft.ru/pub/ALTLinux|g" } __epm_print_url_alt_check() { local pkg=$1 shift local tm=$(mktemp) assure_exists curl quiet=1 local buildtime=$(paoapi packages/$pkg | get_pao_var buildtime) echo echo "Latest release: $(paoapi packages/$pkg | get_pao_var sourcepackage) $buildtime" __epm_print_url_alt "$1" | while read url ; do a='' curl -s --head $url >$tm || { echo "$url: missed" ; continue ; } local http=$(cat $tm | grep "^HTTP" | sed -e "s|\r||g") local lastdate=$(cat $tm | grep "^Last-Modified:" | sed -e "s|\r||g") local size=$(cat $tm | grep "^Content-Length:" | sed -e "s|^Content-Length: ||g" | sed -e "s|\r||g") echo "$url ($http $lastdate) Size: $size" done rm -f $tm } __epm_download_alt() { local pkg if [ "$1" = "--check" ] ; then local checkflag="$1" shift fi for pkg in "$@" ; do local url=$(__epm_get_altpkg_url $pkg) [ -n "$url" ] || warning "Can't get URL for $pkg" if [ -n "$checkflag" ] ; then __epm_print_url_alt_check "$pkg" "$url" else docmd eget $url || return fi done } epm_download() { local CMD case $DISTRNAME-$PMTYPE in ALTLinux-apt-rpm) __epm_download_alt $* return ;; esac case $PMTYPE in dnf-rpm) sudocmd dnf download $* ;; aptcyg) sudocmd apt-cyg download $* ;; packagekit) docmd pkcon download $* ;; yum-rpm) # TODO: check yum install --downloadonly --downloaddir=/tmp <package-name> assure_exists yumdownloader yum-utils sudocmd yumdownloader $* ;; dnf-rpm) sudocmd dnf download $* ;; urpm-rpm) sudocmd urpmi --no-install $URPMOPTIONS $@ ;; tce) sudocmd tce-load -w $* ;; opkg) docmd opkg $* ;; homebrew) docmd brew fetch $* ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-epm_install: __epm_korinf_site_mask() { local MASK="$1" local archprefix="" # short hack to install needed package rhas "$MASK" "[-_]" || MASK="$MASK[-_][0-9]" # set arch for Korinf compatibility [ "$($DISTRVENDOR -a)" = "x86_64" ] && archprefix="x86_64/" echo "http://updates.etersoft.ru/pub/Korinf/$archprefix$($DISTRVENDOR -e)/$MASK*.$($DISTRVENDOR -p)" } __epm_korinf_list() { local MASK="$1" MASK="$(__epm_korinf_site_mask "$MASK")" showcmd eget --list "$MASK" eget --list "$MASK" | sort } __epm_korinf_install() { local PACKAGE="$1" # due Error: Can't use epm call from the piped script #epm install $(__epm_korinf_site_mask "$PACKAGE") pkg_names='' pkg_files='' pkg_urls="$(__epm_korinf_site_mask "$PACKAGE")" epm_install } epm_epm_install() { local i local pkglist="$*" # install epm by default if [ -z "$pkglist" ] || [ "$pkglist" = "epm" ] || [ "$pkglist" = "eepm" ]; then pkglist="eepm" fi case "$pkglist" in --list*) shift __epm_korinf_list "$1" return ;; esac for i in $pkglist ; do __epm_korinf_install $i done } # File bin/epm-filelist: __alt_local_content_filelist() { update_alt_contents_index local CI="$(cat $ALT_CONTENTS_INDEX_LIST)" # TODO: safe way to use less #local OUTCMD="less" #[ -n "$USETTY" ] || OUTCMD="cat" OUTCMD="cat" { [ -n "$USETTY" ] && info "Search in $CI for $1..." __local_ercat $CI | grep -h -P -- ".*\t$1$" | sed -e "s|\(.*\)\t\(.*\)|\1|g" } | $OUTCMD } __deb_local_content_filelist() { showcmd "apt-file list $1 | grep '^$1: ' | sed -e 's|$1: ||g'" a='' apt-file list "$1" | grep "^$1: " | sed -e "s|$1: ||g" } __epm_filelist_remote() { [ -z "$*" ] && return case $PMTYPE in apt-rpm) # TODO: use RESTful interface to prometeus? See ALT bug #29496 docmd_foreach __alt_local_content_filelist "$@" ;; apt-dpkg) assure_exists apt-file || return # TODO: improve me if sudorun -n true 2>/dev/null ; then sudocmd apt-file update else info "sudo requires a password, skip apt-file update" fi docmd_foreach __deb_local_content_filelist "$@" ;; packagekit) docmd pkcon get-files "$@" ;; yum-rpm) assure_exists yum-utils || return docmd repoquery -q -l "$@" ;; dnf-rpm) assure_exists dnf-plugins-core || return docmd dnf repoquery -l "$@" ;; *) fatal "Query filelist for non installed packages is not implemented yet." ;; esac } __epm_filelist_file() { local CMD [ -z "$*" ] && return # TODO: allow a new packages case $(get_package_type $1) in rpm) assure_exists rpm CMD="rpm -qlp" ;; deb) assure_exists dpkg CMD="dpkg --contents" ;; *) fatal "Have no suitable query command for $PMTYPE" ;; esac docmd $CMD $@ | less } __epm_filelist_name() { local CMD [ -z "$*" ] && return warmup_lowbase case $PMTYPE in *-rpm) CMD="rpm -ql" ;; *-dpkg) CMD="dpkg -L" ;; packagekit) CMD="pkcon get-files" ;; android) CMD="pm list packages -f" ;; conary) CMD="conary query --ls" ;; pacman) docmd pacman -Ql $@ | sed -e "s|.* ||g" | less return ;; emerge) assure_exists equery CMD="equery files" ;; homebrew) CMD="brew list" ;; pkgng) CMD="pkg info -l" ;; opkg) CMD="opkg files" ;; xbps) CMD="xbps-query -f" ;; aptcyg) docmd apt-cyg listfiles $@ | sed -e "s|^|/|g" return ;; slackpkg) is_installed $@ || fatal "Query filelist for non installed packages is not implemented yet" docmd awk 'BEGIN{desk=1}{if(/^FILE LIST:$/){desk=0} else if (desk==0) {print}}' /var/log/packages/${pkg_filenames}* | less return ;; *) fatal "Have no suitable query command for $PMTYPE" ;; esac # TODO: add less docmd $CMD $@ && return # TODO: may be we need check is installed before prev. line? is_installed $@ || __epm_filelist_remote $@ } epm_filelist() { [ -n "$pkg_filenames" ] || fatal "Filelist: package name is missed" __epm_filelist_file $pkg_files || return # shellcheck disable=SC2046 __epm_filelist_name $(print_name $pkg_names) || return } # File bin/epm-full_upgrade: epm_full_upgrade() { epm_update || return epm_upgrade || return epm_kernel_update || return epm play --update all || return } # File bin/epm-info: __epm_info_rpm_low() { if [ -n "$pkg_files" ] ; then docmd rpm -qip $pkg_files fi [ -z "$pkg_names" ] && return is_installed $pkg_names && docmd rpm -qi $pkg_names && return } __epm_info_by_pkgtype() { [ -n "$pkg_files" ] || return 1 case $(get_package_type $pkg_files) in rpm) __epm_info_rpm_low && return ;; deb) docmd dpkg -I $pkg_files ;; *) return 1 ;; esac } __epm_info_by_pmtype() { case $PMTYPE in apt-dpkg) if [ -n "$pkg_files" ] ; then docmd dpkg -I $pkg_files fi [ -z "$pkg_names" ] && return is_installed $pkg_names && docmd dpkg -p $pkg_names && return docmd apt-cache show $pkg_names ;; aptitude-dpkg) if [ -n "$pkg_files" ] ; then docmd dpkg -I $pkg_files fi [ -z "$pkg_names" ] && return docmd aptitude show $pkg_names ;; *-rpm) __epm_info_rpm_low && return case $PMTYPE in apt-rpm) docmd apt-cache show $pkg_names ;; packagekit) docmd pkcon get-details $pkg_names ;; yum-rpm) docmd yum info $pkg_names ;; urpmi-rpm) docmd urpmq -i $pkg_names ;; dnf-rpm) docmd dnf info $pkg_names ;; zypper-rpm) docmd zypper info $pkg_names ;; *) warning "Unknown command for $PMTYPE" ;; esac ;; packagekit) # TODO: get-details-local docmd pkcon get-details $pkg_names ;; pacman) is_installed $pkg_names && docmd pacman -Qi $pkg_names && return docmd pacman -Si $pkg_names ;; aura) is_installed $pkg_names && docmd pacman -Qi $pkg_names && return docmd aura -Ai $pkg_names ;; npackd) # FIXME: --version= docmd npackdcl info --package=$pkg_names ;; conary) is_installed $pkg_names && docmd conary query $pkg_names --info && return docmd conary repquery $pkg_names --info ;; emerge) assure_exists equery docmd equery meta $pkg_names docmd equery which $pkg_names docmd equery uses $pkg_names docmd equery size $pkg_names ;; slackpkg) docmd /usr/sbin/slackpkg info $pkg_names ;; opkg) docmd opkg info $pkg_names ;; pkgng) docmd pkg info $pkg_names ;; xbps) docmd xbps-query --show $pkg_names ;; homebrew) docmd brew info $pkg_names ;; aptcyg) docmd apt-cyg show $pkg_names ;; winget) docmd winget show $pkg_names ;; appget) docmd appget view $pkg_names ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } epm_info() { if [ -n "$pkg_urls" ] ; then __handle_pkg_urls_to_checking fi [ -n "$pkg_filenames" ] || fatal "Info: package name is missed" __epm_info_by_pkgtype || __epm_info_by_pmtype local RETVAL=$? [ -n "$to_remove_pkg_files" ] && rm -fv $to_remove_pkg_files [ -n "$to_remove_pkg_files" ] && rmdir -v $(dirname $to_remove_pkg_files | head -n1) 2>/dev/null return $RETVAL } # File bin/epm-install: __use_zypper_no_gpg_checks() { a='' zypper install --help 2>&1 | grep -q -- "--no-gpg-checks" && echo "--no-gpg-checks" } __separate_sudocmd_foreach() { local cmd_re=$1 local cmd_in=$2 shift 2 separate_installed $@ if [ -n "$pkg_noninstalled" ] ; then sudocmd_foreach "$cmd_re" $pkg_noninstalled || return fi if [ -n "$pkg_installed" ] ; then sudocmd_foreach "$cmd_in" $pkg_installed || return fi return 0 } __separate_sudocmd() { local cmd_re=$1 local cmd_in=$2 shift 2 separate_installed $@ if [ -n "$pkg_noninstalled" ] ; then sudocmd $cmd_re $pkg_noninstalled || return fi if [ -n "$pkg_installed" ] ; then sudocmd $cmd_in $pkg_installed || return fi return 0 } epm_install_names() { [ -z "$1" ] && return warmup_hibase if [ -n "$non_interactive" ] ; then epm_ni_install_names "$@" return fi case $PMTYPE in apt-rpm|apt-dpkg) APTOPTIONS="$APTOPTIONS $(subst_option verbose "-o Debug::pkgMarkInstall=1 -o Debug::pkgProblemResolver=1")" sudocmd apt-get $APTOPTIONS $noremove install $@ && save_installed_packages $@ return ;; aptitude-dpkg) sudocmd aptitude install $@ return ;; deepsolver-rpm) sudocmd ds-install $@ return ;; urpm-rpm) sudocmd urpmi $URPMOPTIONS $@ return ;; packagekit) docmd pkcon install $@ return ;; pkgsrc) sudocmd pkg_add -r $@ return ;; pkgng) sudocmd pkg install $@ return ;; emerge) sudocmd emerge -uD $@ return ;; pacman) sudocmd pacman -S $nodeps $@ return ;; aura) sudocmd aura -A $force $nodeps $@ return ;; yum-rpm) sudocmd yum $YUMOPTIONS install $(echo "$*" | exp_with_arch_suffix) return ;; dnf-rpm) sudocmd dnf install $(echo "$*" | exp_with_arch_suffix) return ;; snappy) sudocmd snappy install $@ return ;; zypper-rpm) sudocmd zypper install $ZYPPEROPTIONS $@ return ;; mpkg) sudocmd mpkg install $@ return ;; conary) sudocmd conary update $@ return ;; npackd) # FIXME: correct arg __separate_sudocmd_foreach "npackdcl add --package=" "npackdcl update --package=" $@ return ;; slackpkg) __separate_sudocmd_foreach "/usr/sbin/slackpkg install" "/usr/sbin/slackpkg upgrade" $@ return ;; homebrew) # FIXME: sudo and quote SUDO='' __separate_sudocmd "brew install" "brew upgrade" "$@" return ;; opkg) [ -n "$force" ] && force=-force-depends sudocmd opkg $force install $@ return ;; nix) __separate_sudocmd "nix-env --install" "nix-env --upgrade" "$@" return ;; apk) sudocmd apk add $@ return ;; tce) sudocmd tce-load -wi $@ return ;; guix) __separate_sudocmd "guix package -i" "guix package -i" $@ return ;; android) fatal "We still have no idea how to use package repository, ever if it is F-Droid." return ;; aptcyg) sudocmd apt-cyg install $@ return ;; xbps) sudocmd xbps-install $@ return ;; appget|winget) sudocmd $PMTYPE install $@ return ;; *) fatal "Have no suitable install command for $PMTYPE" ;; esac } epm_ni_install_names() { [ -z "$1" ] && return case $PMTYPE in apt-rpm|apt-dpkg) export DEBIAN_FRONTEND=noninteractive sudocmd apt-get -y $noremove --force-yes -o APT::Install::VirtualVersion=true -o APT::Install::Virtual=true -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" $APTOPTIONS install $@ return ;; aptitude-dpkg) sudocmd aptitude -y install $@ return ;; yum-rpm) sudocmd yum -y $YUMOPTIONS install $(echo "$*" | exp_with_arch_suffix) return ;; dnf-rpm) sudocmd dnf -y $YUMOPTIONS install $(echo "$*" | exp_with_arch_suffix) return ;; urpm-rpm) sudocmd urpmi --auto $URPMOPTIONS $@ return ;; zypper-rpm) # FIXME: returns true ever no package found, need check for "no found", "Nothing to do." yes | sudocmd zypper --non-interactive $ZYPPEROPTIONS install $@ return ;; packagekit) docmd pkcon install --noninteractive $@ return ;; pkgsrc) sudocmd pkg_add -r $@ return ;; pkgng) sudocmd pkg install -y $@ return ;; emerge) sudocmd emerge -uD $@ return ;; pacman) sudocmd pacman -S --noconfirm $nodeps $@ return ;; aura) sudocmd aura -A $force $nodeps $@ return ;; npackd) # npackdcl update --package=<package> (remove old and install new) sudocmd npackdcl add --package="$*" return ;; chocolatey) docmd chocolatey install $@ return ;; opkg) sudocmd opkg -force-defaults install $@ return ;; nix) sudocmd nix-env --install $@ return ;; apk) sudocmd apk add $@ return ;; tce) sudocmd tce-load -wi $@ return ;; xbps) sudocmd xbps-install -y $@ return ;; appget|winget) sudocmd $PMTYPE -s install $@ return ;; homebrew) # FIXME: sudo and quote SUDO='' __separate_sudocmd "brew install" "brew upgrade" $@ return ;; #android) # sudocmd pm install $@ # return ;; slackpkg) # FIXME: broken status when use batch and default answer __separate_sudocmd_foreach "/usr/sbin/slackpkg -batch=on -default_answer=yes install" "/usr/sbin/slackpkg -batch=on -default_answer=yes upgrade" $@ return ;; *) fatal "Have no suitable appropriate install command for $PMTYPE" ;; esac } __epm_check_if_rpm_already_installed() { # Not: we can make optimize if just check version? LANG=C sudorun rpm -Uvh $force $nodeps $@ 2>&1 | grep -q "is already installed" } __handle_direct_install() { case "$DISTRNAME" in "ALTLinux") local pkg url for pkg in $pkg_names ; do url=$(__epm_get_altpkg_url $pkg) [ -n "$url" ] || continue # TODO: use estrlist pkg_urls="$pkg_urls $url" done # FIXME: need remove pkg_names="" ;; esac } __epm_check_if_src_rpm() { local pkg for pkg in $@ ; do echo "$pkg" | grep -q "\.src.\rpm" && fatal "Installation of a source packages (like '$pkg') is not supported." done } __epm_check_if_needed_repack() { local pkgname="$(epm print name from "$1")" local repackcode="$CONFIGDIR/repack.d/$pkgname.sh" [ -x "$repackcode" ] || return warning "There is exists repack rules for $pkgname package. It is better install this package via epm --repack install or epm play." } epm_install_files() { [ -z "$1" ] && return # TODO: check read permissions # sudo test -r FILE # do not fallback to install_names if we have no permissions case "$DISTRNAME" in "ALTLinux") # TODO: replace with name changed function __epm_check_if_try_install_deb $@ && return __epm_check_if_src_rpm $@ # do not using low-level for install by file path (FIXME: reasons?) if ! is_dirpath "$@" || [ "$(get_package_type "$@")" = "rpm" ] ; then __epm_check_vendor $@ __epm_check_if_needed_repack $@ sudocmd rpm -Uvh $force $noscripts $nodeps $@ && save_installed_packages $@ && return local RES=$? # TODO: check rpm result code and convert it to compatible format if possible __epm_check_if_rpm_already_installed $@ && return # if run with --nodeps, do not fallback on hi level [ -n "$nodeps" ] && return $RES fi epm_install_names "$@" return ;; esac case $PMTYPE in apt-dpkg|aptitude-dpkg) # the new version of the conf. file is installed with a .dpkg-dist suffix if [ -n "$non_interactive" ] ; then DPKGOPTIONS="--force-confdef --force-confold" fi __epm_check_if_try_install_rpm $@ && return # FIXME: return false in case no install and in case install with broken deps sudocmd dpkg $DPKGOPTIONS -i $@ local RES=$? # if run with --nodeps, do not fallback on hi level [ -n "$nodeps" ] && return $RES # fall to apt-get -f install for fix deps # can't use APTOPTIONS with empty install args epm_install_names -f # repeat install for get correct status sudocmd dpkg $DPKGOPTIONS -i $@ return ;; *-rpm) __epm_check_if_try_install_deb $@ && return __epm_check_if_src_rpm $@ sudocmd rpm -Uvh $force $noscripts $nodeps $@ && return local RES=$? __epm_check_if_rpm_already_installed $@ && return # if run with --nodeps, do not fallback on hi level [ -n "$nodeps" ] && return $RES case $PMTYPE in yum-rpm|dnf-rpm) YUMOPTIONS=--nogpgcheck # use install_names ;; zypper-rpm) ZYPPEROPTIONS=$(__use_zypper_no_gpg_checks) # use install_names ;; urpm-rpm) URPMOPTIONS=--no-verify-rpm # use install_names ;; *) # use install_names ;; esac ;; packagekit) docmd pkcon install-local $@ return ;; pkgsrc) sudocmd pkg_add $@ return ;; pkgng) local PKGTYPE="$(get_package_type $@)" case "$PKGTYPE" in tbz) sudocmd pkg_add $@ ;; *) sudocmd pkg add $@ ;; esac return ;; android) sudocmd pm install $@ return ;; emerge) sudocmd epm_install_emerge $@ return ;; pacman) sudocmd pacman -U --noconfirm $nodeps $@ && return local RES=$? [ -n "$nodeps" ] && return $RES sudocmd pacman -U $@ return ;; slackpkg) # FIXME: check for full package name # FIXME: broken status when use batch and default answer __separate_sudocmd_foreach "/sbin/installpkg" "/sbin/upgradepkg" $@ return ;; esac # other systems can install file package via ordinary command epm_install_names "$@" } epm_print_install_command() { # print out low level command by default (wait --low-level for control it) #[ -z "$1" ] && return [ -z "$1" ] && [ -n "$pkg_names" ] && return case $PMTYPE in *-rpm) echo "rpm -Uvh --force $nodeps $*" ;; *-dpkg) echo "dpkg -i $*" ;; pkgsrc) echo "pkg_add $*" ;; pkgng) echo "pkg add $*" ;; emerge) # need be placed in /usr/portage/packages/somewhere echo "emerge --usepkg $*" ;; pacman) echo "pacman -U --noconfirm $nodeps $*" ;; slackpkg) echo "/sbin/installpkg $*" ;; npackd) echo "npackdcl add --package=$*" ;; opkg) echo "opkg install $*" ;; android) echo "pm install $*" ;; aptcyg) echo "apt-cyg install $*" ;; tce) echo "tce-load -wi $*" ;; xbps) echo "xbps-install -y $*" ;; appget|winget) echo "$PMTYPE install -s $*" ;; homebrew) # FIXME: sudo and quote echo "brew install $*" ;; *) fatal "Have no suitable appropriate install command for $PMTYPE" ;; esac } epm_print_install_names_command() { # check for pkg_files to support print out command without pkg names in args #[ -z "$1" ] && [ -n "$pkg_files" ] && return [ -z "$1" ] && return case $PMTYPE in apt-rpm|apt-dpkg) echo "apt-get -y --force-yes -o APT::Install::VirtualVersion=true -o APT::Install::Virtual=true $APTOPTIONS install $*" return ;; aptitude-dpkg) echo "aptitude -y install $*" return ;; yum-rpm) echo "yum -y $YUMOPTIONS install $*" return ;; dnf-rpm) echo "dnf -y $YUMOPTIONS install $*" return ;; urpm-rpm) echo "urpmi --auto $URPMOPTIONS $*" return ;; zypper-rpm) echo "zypper --non-interactive $ZYPPEROPTIONS install $*" return ;; packagekit) echo "pkcon --noninteractive $*" return ;; pacman) echo "pacman -S --noconfirm $*" return ;; chocolatey) echo "chocolatey install $*" return ;; nix) echo "nix-env --install $*" return ;; appget|winget) echo "$PMTYPE install $*" return ;; *) fatal "Have no suitable appropriate install command for $PMTYPE" ;; esac } epm_install() { if [ "$DISTRNAME" = "ALTLinux" ] ; then if tasknumber "$pkg_names" >/dev/null ; then assure_exists apt-repo # TODO: add --auto support sudocmd_foreach "apt-repo test" $(tasknumber $pkg_names) return fi fi if [ -n "$show_command_only" ] ; then epm_print_install_command $pkg_files epm_print_install_names_command $pkg_names return fi if [ -n "$direct" ] && [ -z "$repack" ] ; then __handle_direct_install fi # if possible, it will put pkg_urls into pkg_files and reconstruct pkg_filenames if [ -n "$pkg_urls" ] ; then __handle_pkg_urls_to_install fi [ -z "$pkg_files$pkg_names" ] && info "Skip empty install list" && return 22 # to be filter happy warmup_lowbase # Note: filter_out_installed_packages depends on skip_installed flag local names="$(echo $pkg_names | filter_out_installed_packages)" #local names="$(echo $pkg_names | exp_with_arch_suffix | filter_out_installed_packages)" local files="$(echo $pkg_files | filter_out_installed_packages)" # can be empty only after skip installed if [ -z "$files$names" ] ; then # TODO: assert $skip_installed [ -n "$verbose" ] && info "Skip empty install list (filtered out)" # FIXME: see to_remove below return 0 fi if [ -z "$files" ] && [ -z "$direct" ] ; then # it is useful for first time running update_repo_if_needed fi # FIXME: see to_remove below epm_install_names $names || return # repack binary files if [ -n "$repack" ] ; then # FIXME: see to_remove below __epm_repack_to_rpm $files || fatal files="$repacked_rpms" fi epm_install_files $files local RETVAL=$? # TODO: move it to exit handler if [ -z "$DEBUG" ] ; then # TODO: reinvent [ -n "$to_remove_pkg_files" ] && rm -fv $to_remove_pkg_files [ -n "$to_remove_pkg_files" ] && rmdir -v $(dirname $to_remove_pkg_files | head -n1) 2>/dev/null fi return $RETVAL } # File bin/epm-Install: epm_Install() { # copied from epm_install local names="$(echo $pkg_names | filter_out_installed_packages)" local files="$(echo $pkg_files | filter_out_installed_packages)" [ -z "$files$names" ] && info "Install: Skip empty install list." && return 22 epm_update || { [ -n "$force" ] || return ; } epm_install_names $names || return epm_install_files $files } # File bin/epm-installed: separate_installed() { pkg_installed= pkg_noninstalled= for i in "$@" ; do is_installed $i && pkg_installed="$pkg_installed $i" || pkg_noninstalled="$pkg_noninstalled $i" done } epm_installed() { [ -n "$pkg_names" ] || fatal "is_installed: package name is missed" is_installed "$pkg_names" } # File bin/epm-install-emerge: __emerge_install_ebuild() { local EBUILD="$1" [ -s "$EBUILD" ] || fatal ".ebuild file '$EBUILD' is missed" # load ebuild and get vars . $(pwd)/$EBUILD [ -n "$SRC_URI" ] || fatal "Can't load SRC_URI from $EBUILD" # try to detect tarballs local TARBALLS= local BASEDIR=$(dirname $EBUILD) for i in $SRC_URI ; do [ -s "$BASEDIR/$(basename $i)" ] || continue TARBALLS="$TARBALLS $BASEDIR/$(basename $i)" done local PORTAGENAME=epm local LP=/usr/local/portage/$PORTAGENAME docmd mkdir -p $LP/ MAKECONF=/etc/portage/make.conf [ -r "$MAKECONF" ] || MAKECONF=/etc/make.conf if ! grep -v "^#" $MAKECONF | grep -q $LP ; then echo "PORTDIR_OVERLAY=\"$LP \${PORTDIR_OVERLAY}\"" >>$MAKECONF # Overlay name mkdir -p $LP/profiles/ echo "$PORTAGENAME" > $LP/profiles/repo_name fi # copy tarballs local DDIR=/usr/portage/distfiles # FIXME: use independent dir [ -d /var/calculate/remote/distfiles ] && DDIR=/var/calculate/remote/distfiles docmd cp -f $TARBALLS $DDIR/ || return # copy ebuild docmd cp -f $EBUILD $LP/ || return cd $LP docmd ebuild $(basename $EBUILD) digest cd - # FIXME: more correcty get name local PKGNAME=$(echo $EBUILD | sed -e "s|-[0-9].*||g") docmd emerge -av $PKGNAME || return } __emerge_install_tbz2() { local TGDIR=/usr/portage/packages/app-arch mkdir -p $TGDIR cp $i $TGDIR || return docmd emerge --usepkg $TGDIR/$(basename $i) || return } epm_install_emerge() { local EBUILD= #local TARBALLS= local i # search ebuild in the args for i in $* ; do if echo $i | grep -q ebuild ; then __emerge_install_ebuild $i || return elif echo $i | grep -q "\.tbz2$" ; then __emerge_install_tbz2 $i || return # else # TARBALLS="$TARBALLS $i" fi done } # File bin/epm-kernel_update: epm_kernel_update() { warmup_bases info "Updating system kernel to the latest version..." case $DISTRNAME in ALTLinux) if ! __epm_query_package kernel-image >/dev/null ; then info "No installed kernel packages, skipping update" return fi assure_exists update-kernel update-kernel 0.9.9 update_repo_if_needed sudocmd update-kernel $(subst_option non_interactive -y) "$@" || return docmd epm remove-old-kernels $(subst_option non_interactive -y) "$@" || fatal return ;; esac case $PMTYPE in dnf-rpm) docmd epm install kernel ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-mark: epm_mark() { case $PMTYPE in apt-rpm|apt-dpkg) sudocmd apt-mark "$@" ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-optimize: __repack_rpm_base() { assure_exists db_dump || fatal assure_exists db_load || fatal cd /var/lib/rpm || fatal mv Packages Packages.BACKUP || fatal # mask dependencies with a= a='' db_dump Packages.BACKUP | a='' db_load Packages || fatal rm Packages.BACKUP } epm_optimize() { [ -z "$*" ] || fatal "No arguments are allowed here" case $PMTYPE in *-rpm) #__repack_rpm_base #rm -f /var/lib/rpm/__db* a= rpm --rebuilddb ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-packages: __epm_packages_sort() { case $PMTYPE in *-rpm) # FIXME: space with quotes problems, use point instead warmup_rpmbase docmd rpm -qa --queryformat "%{size}@%{name}-%{version}-%{release}\n" $pkg_filenames | sed -e "s|@| |g" | sort -n -k1 ;; *-dpkg) warmup_dpkgbase docmd dpkg-query -W --showformat="\${Installed-Size}@\${Package}-\${Version}:\${Architecture}\n" $pkg_filenames | sed -e "s|@| |g" | sort -n -k1 ;; *) fatal "Sorted package list function is not implemented for $PMTYPE" ;; esac } __aptcyg_print_full() { #showcmd apt-cyg show local VERSION=$(apt-cyg show "$1" | grep -m1 "^version: " | sed -e "s|^version: ||g") echo "$1-$VERSION" } __fo_pfn() { grep -v "^$" | grep -- "$pkg_filenames" } epm_packages() { local CMD [ -n "$sort" ] && __epm_packages_sort && return case $PMTYPE in *-dpkg) warmup_dpkgbase # FIXME: strong equal #CMD="dpkg -l $pkg_filenames" CMD="dpkg-query -W --showformat=\${db:Status-Abbrev}\${Package}-\${Version}:\${Architecture}\n $pkg_filenames" # TODO: ${Architecture} [ -n "$short" ] && CMD="dpkg-query -W --showformat=\${db:Status-Abbrev}\${Package}\n $pkg_filenames" showcmd $CMD $CMD | grep "^i" | sed -e "s|.* ||g" | __fo_pfn return ;; *-rpm) warmup_rpmbase # FIXME: strong equal CMD="rpm -qa $pkg_filenames" [ -n "$short" ] && CMD="rpm -qa --queryformat %{name}\n $pkg_filenames" docmd $CMD return ;; packagekit) docmd pkcon get-packages --filter installed ;; snappy) CMD="snappy info" ;; emerge) CMD="qlist -I -C" # print with colors for console output isatty && CMD="qlist -I" ;; pkgsrc) CMD="pkg_info" showcmd $CMD $CMD | sed -e "s| .*||g" | __fo_pfn return ;; pkgng) if [ -n "$pkg_filenames" ] ; then CMD="pkg info -E $pkg_filenames" else CMD="pkg info" fi showcmd $CMD if [ -n "$short" ] ; then $CMD | sed -e "s| .*||g" | sed -e "s|-[0-9].*||g" | __fo_pfn else $CMD | sed -e "s| .*||g" | __fo_pfn fi return ;; pacman) CMD="pacman -Qs $pkg_filenames" showcmd $CMD if [ -n "$short" ] ; then $CMD | sed -e "s| .*||g" -e "s|.*/||g" | __fo_pfn return fi ;; npackd) CMD="npackdcl list --status=installed" # TODO: use search if pkg_filenames is not empty ;; conary) CMD="conary query" ;; chocolatey) CMD="chocolatey list" ;; slackpkg) CMD="ls -1 /var/log/packages/" if [ -n "$short" ] ; then # FIXME: does not work for libjpeg-v8a # TODO: remove last 3 elements (if arch is second from the last?) # FIXME this hack docmd ls -1 /var/log/packages/ | sed -e "s|-[0-9].*||g" | sed -e "s|libjpeg-v8a.*|libjpeg|g" | __fo_pfn return fi ;; homebrew) docmd brew list | xargs -n1 echo ;; opkg) CMD="opkg list-installed" ;; apk) CMD="apk info" ;; tce) CMD="ls -1 /usr/local/tce.installed" ;; guix) CMD="guix package -I" ;; appget) CMD="appget list" ;; winget) info "Use appget instead of winget" return 0 ;; xbps) CMD="xbps-query -l" showcmd $CMD if [ -n "$short" ] ; then $CMD | sed -e "s|^ii ||g" -e "s| .*||g" -e "s|\(.*\)-.*|\1|g" | __fo_pfn else $CMD | sed -e "s|^ii ||g" -e "s| .*||g" | __fo_pfn fi return 0 ;; android) CMD="pm list packages" showcmd $CMD $CMD | sed -e "s|^package:||g" | __fo_pfn return ;; aptcyg) CMD="apt-cyg list $pkg_filenames" if [ -z "$short" ] ; then showcmd $CMD # TODO: fix this slow way for i in $($CMD) ; do __aptcyg_print_full $i done return fi ;; *) fatal "Have no suitable query command for $PMTYPE" ;; esac docmd $CMD | __fo_pfn } # File bin/epm-play: epm_vardir=/var/lib/eepm __save_installed_app() { [ -d "$epm_vardir" ] || return 0 __check_installed_app "$1" && return 0 echo "$1" | sudorun tee -a $epm_vardir/installed-app >/dev/null } __remove_installed_app() { [ -d "$epm_vardir" ] || return 0 local i for i in $* ; do sudorun sed -i "/^$i$/d" $epm_vardir/installed-app done return 0 } __check_installed_app() { [ -s $epm_vardir/installed-app ] || return 1 grep -q -- "^$1\$" $epm_vardir/installed-app } __list_installed_app() { cat $epm_vardir/installed-app 2>/dev/null } __get_app_description() { [ -x "$1" ] || return $1 --description 2>/dev/null } __epm_play_run() { local script="$psdir/$1.sh" shift if [ ! -x "$script" ] ; then fatal "Can't find executable play script $script." fi # allow use EGET in the scripts __set_EGET # also we will have DISTRVENDOR there export PATH=$PROGDIR:$PATH set_sudo export SUDO local bashopt='' [ -n "$verbose" ] && bashopt='-x' && export EPM_VERBOSE="$verbose" #info "Running $($script --description 2>/dev/null) ..." docmd bash $bashopt $script "$@" } epm_play() { local psdir="$CONFIGDIR/play.d" if [ "$1" = "-h" ] || [ "$1" = "--help" ] ; then cat <<EOF Options: APP - install APP --remove APP - remove APP --list - list all installed apps --list-all - list all available apps --short - print only names --update [APP|all] - update APP (or all installed apps) if there is new version EOF exit fi if [ "$1" = "--remove" ] ; then shift #__check_installed_app "$1" || warning "$1 is not installed" prescription="$1" shift __epm_play_run $prescription --remove "$@" __remove_installed_app "$prescription" exit fi if [ "$1" = "--update" ] ; then shift if [ "$1" = "all" ] ; then shift for i in $(__list_installed_app) ; do echo "$i" prescription="$i" __epm_play_run $prescription --run "$@" done exit fi if [ -z "$1" ] ; then fatal "run --update with 'all' or a project name" fi __check_installed_app "$1" || fatal "$1 is not installed" prescription="$1" shift __epm_play_run $prescription --run "$@" exit fi if [ "$1" = "--list" ] || [ "$1" = "--installed" ] ; then shift local i if [ -n "$short" ] ; then for i in $(__list_installed_app) ; do echo "$i" done exit fi echo "Installed:" for i in $(__list_installed_app) ; do local desc="$(__get_app_description $psdir/$i.sh)" [ -n "$desc" ] || continue printf " %-20s - %s\n" "$i" "$desc" done exit fi [ "$($DISTRVENDOR -a)" = "x86_64" ] && IGNOREi586='' || IGNOREi586=1 if [ "$1" = "--list-all" ] || [ -z "$*" ] ; then local i if [ -n "$short" ] ; then for i in $psdir/*.sh ; do local name=$(basename $i .sh) [ -n "$IGNOREi586" ] && rhas "$name" "^i586-" && continue rhas "$name" "^common" && continue echo "$name" done exit fi echo "Run with a name of a play script to run:" for i in $psdir/*.sh ; do local desc="$(__get_app_description $i)" [ -n "$desc" ] || continue local name=$(basename $i .sh) [ -n "$IGNOREi586" ] && rhas "$name" "^i586-" && continue rhas "$name" "^common" && continue printf " %-20s - %s\n" "$name" "$desc" done echo echo "run epm play" echo " --list - to list installed only" echo " --list-all (default) - to list all app" echo " --remove <app> - to remove app" echo " --update <app|all> - to update app or all installed apps" echo " --short (with --list) - list names only" exit fi prescription="$1" shift __epm_play_run "$prescription" --run "$@" && __save_installed_app "$prescription" || fatal "There was some error during install the application." } # File bin/epm-policy: epm_policy() { [ -n "$pkg_names" ] || fatal "Info: package name is missed" warmup_bases pkg_names=$(__epm_get_hilevel_name $pkg_names) case $PMTYPE in apt-*) docmd apt-cache policy $pkg_names ;; packagekit) docmd pkcon resolve $pkg_names ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-prescription: epm_vardir=/var/lib/eepm __epm_prescription_run() { local script="$psdir/$1.sh" shift local option="$1" if [ ! -x "$script" ] ; then fatal "Can't find $script prescription." fi # allow use EGET in the scripts __set_EGET # also we will have DISTRVENDOR there export PATH=$PROGDIR:$PATH #info "Running $($script --description 2>/dev/null) ..." docmd $script $option } epm_prescription() { local psdir="$CONFIGDIR/prescription.d" if [ "$1" = "-h" ] || [ "$1" = "--help" ] ; then cat <<EOF Options: <receipt> - run receipt --list-all - list all available receipts EOF exit fi [ "$($DISTRVENDOR -a)" = "x86_64" ] && IGNOREi586='' || IGNOREi586=1 if [ "$1" == "--list-all" ] || [ -z "$*" ] ; then if [ -n "$short" ] ; then for i in $psdir/*.sh ; do local name=$(basename $i .sh) [ -n "$IGNOREi586" ] && rhas "$name" "^i586-" && continue rhas "$name" "^common" && continue echo "$name" done exit fi echo "Run with a name of a prescription to run:" for i in $psdir/*.sh ; do local name=$(basename $i .sh) [ -n "$IGNOREi586" ] && rhas "$name" "^i586-" && continue rhas "$name" "^common" && continue printf " %-20s - %s\n" "$name" "$($i --description 2>/dev/null)" done echo exit fi __epm_prescription_run "$1" --run } # File bin/epm-print: query_package_field() { local FORMAT="%{$1}\n" shift local INSTALLED="" # if a file, ad -p for get from rpm base if [ -f "$1" ] && [ "$(get_package_type "$1")" = "rpm" ] ; then INSTALLED="-p" fi a= rpmquery $INSTALLED --queryformat "$FORMAT" "$@" } print_binpkgfilelist() { local PKGDIR=$1 local PKGNAME=$(basename $2) find "$PKGDIR" ! -name '*\.src\.rpm' -name '*\.rpm' -execdir \ rpmquery -p --qf='%{sourcerpm}\t%{name}-%{version}-%{release}.%{arch}.rpm\n' "{}" \; \ | grep "^$PKGNAME[[:space:]].*" \ | cut -f2 \ | xargs -n1 -I "{}" echo -n "$PKGDIR/{} " } PKGNAMEMASK="\(.*\)-\([0-9].*\)-\(.*[0-9].*\)\.\(.*\)\.\(.*\)" print_name() { echo "$@" | xargs -n1 echo | sed -e "s|$PKGNAMEMASK|\1|g" } print_version() { echo "$1" | xargs -n1 echo | sed -e "s|$PKGNAMEMASK|\2|g" } print_release() { echo "$1" | xargs -n1 echo | sed -e "s|$PKGNAMEMASK|\3|g" } print_version_release() { echo "$1" | xargs -n1 echo | sed -e "s|$PKGNAMEMASK|\2-\3|g" } print_pkgname() { local i for i in $@ ; do # TODO: deb and other, arch string echo "$(basename "$i") " | sed -e "s|\.[a-z_0-9]*\.rpm||g" -e "s|\(.*\)_\(.*\)_[a-z_0-9]*\.deb|\1-\2|g" done } print_srcname() { print_name "$(print_srcpkgname "$@")" } print_specname() { # CHECKME: it is possible to have two or more specs in one package? a= rpm -qlp "$@" | grep "\.spec\$" } print_srcpkgname() { if [ -n "$FNFLAG" ] ; then query_package_field sourcerpm "$@" return fi # if PKFLAG case $PMTYPE in apt-dpkg) fatal "Unknown command for get source package name via dpkg" ;; urpm-rpm) docmd urpmq --sourcerpm "$@" return ;; dnf-rpm) showcmd dnf repoquery --qf '%{SOURCERPM}' "$@" a= dnf repoquery --qf '%{SOURCERPM}' "$@" return ;; esac # FIXME: only for installed rpm packages query_package_field sourcerpm "$@" } compare_version() { which rpmevrcmp 2>/dev/null >/dev/null || fatal "rpmevrcmp exists in ALT Linux only" a= rpmevrcmp "$@" } construct_name() { local name="$1" local version="$2" local arch="$3" local pkgtype="$4" local ds="$5" local pds [ -n "$arch" ] || arch="$($DISTRVENDOR --distro-arch)" [ -n "$pkgtype" ] || pkgtype="$($DISTRVENDOR -p)" [ -n "$ds" ] || ds=$(get_pkg_name_delimiter $pkgtype) pds="$ds" [ "$pds" = "-" ] && pds="." [ -n "$version" ] && version="$ds$version" echo "${name}${version}${pds}$arch.$pkgtype" } epm_print() { local WHAT="$1" shift local FNFLAG= local PKFLAG= [ "$1" = "from" ] && shift [ "$1" = "for" ] && shift [ "$1" = "in" ] && shift if [ "$1" = "filename" ] ; then FNFLAG="$1" shift fi if [ "$1" = "package" ] ; then PKFLAG="$1" shift fi case "$WHAT" in "") fatal "Use epm print help to get help." ;; "-h"|"--help"|"help") cat <<EOF Examples: epm print info [args] print system and distro info (via distro_info command) epm print name [from filename|for package] NN print only name of package name or package file epm print version [from filename|for package] NN print only version of package name or package file epm print release [from filename|for package] NN print only release of package name or package file epm print version-release [from filename|for package] NN print only release-release of package name or package file epm print field FF for package NN print field of the package epm print pkgname from filename NN print package name for the package file epm print srcname from filename NN print source name for the package file epm print srcpkgname from [filename|package] NN print source package name for the binary package file epm print specname from filename NN print spec filename for the source package file epm print binpkgfilelist in DIR for NN list binary package(s) filename(s) from DIR for the source package file epm print compare [package] version N1 N2 compare (package) versions and print -1, 0, 1 epm print constructname <name> <version> [arch] [ pkgtype] print distro dependend package filename from args name version arch pkgtype EOF ;; "name") [ -n "$1" ] || fatal "Arg is missed" if [ -n "$FNFLAG" ] ; then print_name "$(print_pkgname "$@")" elif [ -n "$PKFLAG" ] ; then query_package_field "name" "$@" else print_name "$@" fi ;; "version") [ -n "$1" ] || fatal "Arg is missed" if [ -n "$FNFLAG" ] ; then print_version "$(print_pkgname "$@")" elif [ -n "$PKFLAG" ] ; then query_package_field "version" "$@" else print_version "$@" fi ;; "release") [ -n "$1" ] || fatal "Arg is missed" if [ -n "$FNFLAG" ] ; then print_release "$(print_pkgname "$@")" elif [ -n "$PKFLAG" ] ; then query_package_field "release" "$@" else print_release "$@" fi ;; "version-release") [ -n "$1" ] || fatal "Arg is missed" if [ -n "$FNFLAG" ] ; then print_version_release "$(print_pkgname "$@")" elif [ -n "$PKFLAG" ] ; then echo "$(query_package_field "version" "$@")-$(query_package_field "release" "$@")" else print_version_release "$@" fi ;; "field") [ -n "$1" ] || fatal "Arg is missed" local FIELD="$1" shift [ "$1" = "for" ] && shift query_package_field "$FIELD" "$@" ;; "pkgname") [ -n "$FNFLAG" ] || fatal "print $WHAT works only for filename(s)" [ -n "$1" ] || fatal "Arg is missed" # TODO: drop_pkg_extensions print_pkgname "$@" ;; "srcname") [ -n "$FNFLAG" ] || fatal "print $WHAT works only for filename(s)" [ -n "$1" ] || fatal "Arg is missed" print_srcname "$@" ;; "srcpkgname") [ -n "$FNFLAG" ] || [ -n "$PKFLAG" ] || fatal "print $WHAT works only for filename(s)" [ -n "$1" ] || fatal "Arg is missed" print_srcpkgname "$@" ;; "specname") [ -n "$FNFLAG" ] || [ -n "$PKFLAG" ] || fatal "print $WHAT works only for filename(s)" [ -n "$1" ] || fatal "Arg is missed" print_specname "$@" ;; "binpkgfilelist") # TODO: rpm only # TODO: replace get_binpkg_list local DIR="$1" shift [ "$1" = "for" ] && shift [ -n "$DIR" ] || fatal "DIR arg is missed" [ -n "$1" ] || fatal "source package filename is missed" print_binpkgfilelist "$DIR" "$1" ;; "compare") [ "$1" = "version" ] && shift [ -n "$1" ] || fatal "Arg is missed" #if [ -n "$PKFLAG" ] ; then # query_package_field "name" "$@" #else compare_version "$1" "$2" #fi ;; "constructname") construct_name "$@" ;; "info") $DISTRVENDOR "$@" ;; *) fatal "Unknown command $ epm print $WHAT. Use epm print help for get help." ;; esac } # File bin/epm-programs: epm_programs() { case $DISTRNAME in FreeBSD|NetBSD|OpenBSD|Solaris) local DESKTOPDIR=/usr/local/share/applications ;; *) local DESKTOPDIR=/usr/share/applications ;; esac [ -d "$DESKTOPDIR" ] || fatal "There is no $DESKTOPDIR dir on the system." #find /usr/share/applications -type f -name "*.desktop" | while read f; do pkg_files="$f" quiet=1 short=1 epm_query_file ; done | sort -u showcmd "find $DESKTOPDIR -type f -print0 -name "*.desktop" | xargs -0 $0 -qf --quiet --short | sort -u" find $DESKTOPDIR -type f -print0 -name "*.desktop" | \ xargs -0 $0 -qf --quiet --short | sort -u } # File bin/epm-provides: epm_provides_files() { local pkg_files="$*" [ -n "$pkg_files" ] || return local PKGTYPE="$(get_package_type $pkg_files)" case $PKGTYPE in rpm) assure_exists rpm docmd rpm -q --provides -p $pkg_files ;; deb) assure_exists dpkg # FIXME: will we provide ourself? docmd dpkg -I $pkg_files | grep "^ *Provides:" | sed "s|^ *Provides:||g" ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } epm_provides_names() { local pkg_names="$*" local CMD [ -n "$pkg_names" ] || return case $PMTYPE in apt-rpm) # FIXME: need fix for a few names case # TODO: separate this function to two section if is_installed $pkg_names ; then CMD="rpm -q --provides" else EXTRA_SHOWDOCMD=' | grep "Provides:"' docmd apt-cache show $pkg_names | grep "Provides:" return fi ;; urpm-rpm|zypper-rpm|yum-rpm|dnf-rpm) if is_installed $pkg_names ; then CMD="rpm -q --provides" else fatal "FIXME: use hi level commands" fi ;; emerge) assure_exists equery CMD="equery files" ;; pkgng) CMD="pkg info -b" ;; apt-dpkg) # FIXME: need fix for a few names case if is_installed $pkg_names ; then info "Please inform the author how to get provides from dpkg" fi # CMD="rpm -q --provides" #else EXTRA_SHOWDOCMD=' | grep "Provides:"' docmd apt-cache show $pkg_names | grep "Provides:" return #fi ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac docmd $CMD $pkg_names } epm_provides() { [ -n "$pkg_filenames" ] || fatal "Provides: package name is missed" epm_provides_files $pkg_files # shellcheck disable=SC2046 epm_provides_names $(print_name $pkg_names) } # File bin/epm-query: __print_with_arch_suffix() { local pkg="$1" local suffix="$2" [ -n "$pkg" ] || return 1 # do not change if some suffix already exists echo "$pkg" | grep -q "(x86-32)$" && echo "$pkg" | sed -e "s|(x86-32)$|.i686|" && return 1 echo "$pkg" | grep "\.x86_64$" && return 1 echo "$pkg" | grep "\.noarch$" && return 1 echo "$pkg" | grep "\.i[56]86$" && return 1 echo "$pkg$suffix" } exp_with_arch_suffix() { local suffix [ "$($DISTRVENDOR -a)" = "x86_64" ] || { cat ; return ; } # TODO: it is ok for ALT rpm to remove with this suffix # TODO: separate install and remove? case $PMTYPE in yum-rpm|dnf-rpm) suffix=".x86_64" ;; *) cat return ;; esac # TODO: use estrlist or some function to do it local pkg for pkg in $(cat) ; do local p # check only packages without arch p="$(__print_with_arch_suffix "$pkg" .i686)" || { echo "$pkg" ; continue ; } # add arch suffix only if arch package already installed (otherwise we don't know package arch) is_installed "$p" || { echo "$pkg" ; continue ; } echo "$pkg.x86_64" done } _get_grep_exp() { local def="^$1$" [ "$PMTYPE" != "emerge" ] && echo "$def" && return # Gentoo hack: support for short package form echo "$1" | grep -q "/" && echo "$def" && return echo "/$1$" } _shortquery_via_packages_list() { local res=1 local grepexp local firstpkg=$1 shift grepexp=$(_get_grep_exp $firstpkg) # TODO: we miss status due grep # Note: double call due stderr redirect # Note: we use short=1 here due grep by ^name$ # separate first line for print out command (short=1 pkg_filenames=$firstpkg epm_packages | grep -- "$grepexp") && res=0 || res=1 local pkg for pkg in "$@" ; do grepexp=$(_get_grep_exp $pkg) (short=1 pkg_filenames=$pkg epm_packages 2>/dev/null) | grep -- "$grepexp" || res=1 done # TODO: print in query (for user): 'warning: package $pkg is not installed' return $res } _query_via_packages_list() { local res=1 local grepexp local firstpkg=$1 shift grepexp=$(_get_grep_exp $firstpkg) # TODO: we miss status due grep # TODO: grep correctly # Note: double call due stderr redirect # Note: we use short=1 here due grep by ^name$ # separate first line for print out command (short=1 pkg_filenames=$firstpkg epm_packages) | grep -q -- "$grepexp" && (quiet=1 pkg_filenames=$firstpkg epm_packages) && res=0 || res=1 local pkg for pkg in "$@" ; do grepexp=$(_get_grep_exp $pkg) (short=1 pkg_filenames=$pkg epm_packages 2>/dev/null) | grep -q -- "$grepexp" && (quiet=1 pkg_filenames=$pkg epm_packages) || res=1 done return $res } __epm_get_hilevel_nameform() { [ -n "$*" ] || return case $PMTYPE in apt-rpm) # use # as delimeter for apt local pkg pkg=$(rpm -q --queryformat "%{NAME}#%{SERIAL}:%{VERSION}-%{RELEASE}\n" $1) echo $pkg | grep -q "(none)" && pkg=$(rpm -q --queryformat "%{NAME}#%{VERSION}-%{RELEASE}\n" $1) # HACK: can use only for multiple install packages like kernel echo $pkg | grep -q kernel || return 1 echo $pkg return ;; yum-rpm|dnf-rpm) # just use strict version with Epoch and Serial local pkg pkg=$(rpm -q --queryformat "%{EPOCH}:%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n" $1) echo $pkg | grep -q "(none)" && pkg=$(rpm -q --queryformat "%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n" $1) echo $pkg return ;; *) return 1 ;; esac } __epm_get_hilevel_name() { local i for i in $@ ; do local pkg # get short form in pkg # FIXME: where we use it? continue or pkg=$i? quiet=1 pkg=$(__epm_query_shortname "$i") || pkg="$i" #continue # drop not installed packages # if already short form, skipped [ "$pkg" = "$i" ] && echo "$i" && continue # try get long form or use short form __epm_get_hilevel_nameform "$i" || echo $pkg done } __epm_query_file() { local CMD [ -z "$*" ] && return case $PMTYPE in *-rpm) CMD="rpm -qp" [ -n "$short" ] && CMD="rpm -qp --queryformat %{name}\n" ;; *-dpkg) CMD="dpkg-deb --show --showformat=\${Package}-\${Version}\n" [ -n "$short" ] && CMD="dpkg-query --show --showformat=\${Package}\n" ;; *) fatal "Do not know command for query file package" ;; esac docmd $CMD $@ } __epm_query_dpkg_check() { local i for i in $@ ; do a='' dpkg -s $i >/dev/null 2>/dev/null || return done return 0 } __epm_query_name() { local CMD [ -z "$*" ] && return case $PMTYPE in *-rpm) CMD="rpm -q" ;; *-dpkg) #docmd dpkg -l $@ | grep "^ii" #CMD="dpkg-query -W --showformat=\${Package}-\${Version}\n" docmd dpkg-query -W "--showformat=\${Package}-\${Version}\n" $@ || return __epm_query_dpkg_check $@ || return return ;; npackd) docmd "npackdcl path --package=$1" return ;; conary) CMD="conary query" ;; #homebrew) # showcmd "brew info $1" # local HBRESULT # HBRESULT="$(brew info "$1" 2>/dev/null)" || return # echo "$HBRESULT" | grep -q "Not installed" && return 1 # echo "$1" # return 0 # ;; pacman) docmd pacman -Q $@ return ;; # TODO: need to print name if exists #pkgng) # CMD="pkg info -e" # ;; # Note: slackpkg info pkgname *) # default slow workaround _query_via_packages_list $@ return ;; esac docmd $CMD $@ } __epm_query_shortname() { local CMD [ -z "$*" ] && return case $PMTYPE in *-rpm) CMD="rpm -q --queryformat %{name}\n" ;; *-dpkg) #CMD="dpkg-query -W --showformat=\${Package}\n" docmd dpkg-query -W "--showformat=\${Package}\n" $@ || return __epm_query_dpkg_check $@ || return return ;; npackd) docmd "npackdcl path --package=$1" return ;; conary) CMD="conary query" ;; homebrew) docmd brew info "$1" >/dev/null 2>/dev/null && echo "$1" && return return 1 ;; # TODO: check status #pacman) # docmd pacman -Q $@ | sed -e "s| .*||g" # return # ;; # TODO: need to print name if exists #pkgng) # CMD="pkg info -e" # ;; # Note: slackpkg info pkgname *) # default slow workaround _shortquery_via_packages_list $@ return ;; esac docmd $CMD $@ } is_installed() { (quiet=1 __epm_query_name "$@") >/dev/null 2>/dev/null } epm_query() { [ -n "$pkg_filenames" ] || fatal "Query: package name is missed" __epm_query_file $pkg_files || return if [ -n "$short" ] ; then # shellcheck disable=SC2046 __epm_query_shortname $(print_name $pkg_names) || return else # shellcheck disable=SC2046 __epm_query_name $(print_name $pkg_names) || return fi } # File bin/epm-query_file: __abs_filename() { if echo "$1" | grep -q "/" ; then echo "$1" return fi if [ -e "$1" ] ; then echo "$(pwd)/$1" return fi echo "$1" } __do_query_real_file() { local TOFILE # get canonical path if [ -e "$1" ] ; then TOFILE="$(__abs_filename "$1")" else TOFILE=$(which -- "$1" 2>/dev/null || echo "$1") if [ "$TOFILE" != "$1" ] ; then info " > $1 is placed as $TOFILE" fi fi if [ -n "$short" ] ; then __do_short_query "$TOFILE" || return else __do_query "$TOFILE" || return fi # get value of symbolic link if [ -n "$TOFILE" ] && [ -L "$TOFILE" ] ; then local LINKTO LINKTO=$(readlink -- "$TOFILE") info " > $TOFILE is link to $LINKTO" LINKTO=$(readlink -f -- "$TOFILE") __do_query_real_file "$LINKTO" return fi } dpkg_print_name_version() { local ver i for i in "$@" ; do [ -n "$i" ] || continue ver=$(dpkg -s "$i" 2>/dev/null | grep "Version:" | sed -e "s|Version: ||g") if [ -z "$ver" ] ; then echo "$i" else echo "$i-$ver" fi done } __do_query() { local CMD case $PMTYPE in *-dpkg) showcmd dpkg -S "$1" dpkg_print_name_version "$(dpkg -S "$1" | grep -v "^diversion by" | sed -e "s|:.*||")" return ;; *-rpm) CMD="rpm -qf" ;; emerge) assure_exists equery CMD="equery belongs" ;; pacman) CMD="pacman -Qo" ;; pkgng) CMD="pkg which" ;; conary) CMD="conary query --path" ;; slackpkg) # note: need remove leading slash for grep docmd grep -R -- "$(echo $@ | sed -e 's|^/\+||g')" /var/log/packages | sed -e "s|/var/log/packages/||g" return ;; opkg) CMD="opkg search" ;; xbps) # FIXME: maybe it is search file? CMD="xbps-query -o" ;; aptcyg) #CMD="apt-cyg packageof" # is not implemented locally return 1 ;; *) fatal "Have no suitable query command for $PMTYPE" ;; esac docmd $CMD $@ } __do_short_query() { local CMD case $PMTYPE in *-rpm) CMD="rpm -qf --queryformat %{NAME}\n" ;; NOapt-dpkg) showcmd dpkg -S "$1" dpkg_print_name_version "$(dpkg -S $1 | sed -e "s|:.*||" | grep -v "^diversion by")" return ;; NOemerge) assure_exists equery CMD="equery belongs" ;; NOpacman) CMD="pacman -Qo" ;; NOslackpkg) # note: need remove leading slash for grep docmd grep -R "$(echo $@ | sed -e 's|^/\+||g')" /var/log/packages | sed -e "s|/var/log/packages/||g" return ;; *) fatal "Have no suitable query command for $PMTYPE" ;; esac docmd $CMD $@ } epm_query_file() { # file can exists or not [ -n "$pkg_filenames" ] || fatal "Run query without file names" #load_helper epm-search_file res=0 for pkg in $pkg_filenames ; do __do_query_real_file "$pkg" || res=$? done [ "$res" = "0" ] || info "Try epm sf for search file in all packages of the repositories" #|| pkg_filenames="$FULLFILEPATH" epm_search_file return $res } # File bin/epm-query_package: __epm_query_package() { (pkg_filenames="$*" quoted_args="$*" quiet=1 epm_query_package) } epm_query_package() { [ -n "$pkg_filenames" ] || fatal "Please, use search with some argument or run epmqa for get all packages." # FIXME: do it better local MGS MGS=$(eval __epm_search_make_grep $quoted_args) EXTRA_SHOWDOCMD=$MGS # Note: get all packages list and do grep (eval "pkg_filenames='' epm_packages \"$(eval get_firstarg $quoted_args)\" $MGS") } # File bin/epm-reinstall: epm_reinstall_names() { [ -n "$1" ] || return case $PMTYPE in apt-rpm|apt-dpkg) local APTOPTIONS="$(subst_option non_interactive -y)" sudocmd apt-get --reinstall $APTOPTIONS install $@ return ;; aptitude-dpkg) sudocmd aptitude reinstall $@ return ;; packagekit) warning "Please send me the correct command form for it" docmd pkcon install --allow-reinstall $@ return ;; yum-rpm) sudocmd yum reinstall $@ return ;; dnf-rpm) sudocmd dnf reinstall $@ return ;; homebrew) sudocmd brew reinstall $@ return ;; pkgng) sudocmd pkg install -f $@ return ;; opkg) sudocmd opkg --force-reinstall install $@ return ;; slackpkg) sudocmd_foreach "/usr/sbin/slackpkg reinstall" $@ return ;; esac # fallback to generic install epm_install_names $@ } epm_reinstall_files() { [ -z "$1" ] && return case $PMTYPE in apt-rpm) sudocmd rpm -Uvh --force $@ && return sudocmd apt-get --reinstall install $@ return ;; apt-dpkg|aptitude-dpkg) sudocmd dpkg -i $@ return ;; slackpkg) sudocmd_foreach "/sbin/installpkg" $@ return ;; esac # other systems can install file package via ordinary command epm_reinstall_names $@ } epm_reinstall() { [ -n "$pkg_filenames" ] || fatal "Reinstall: package name is missed." warmup_lowbase # get package name for hi level package management command (with version if supported and if possible) pkg_names=$(__epm_get_hilevel_name $pkg_names) warmup_hibase epm_reinstall_names $pkg_names epm_reinstall_files $pkg_files } # File bin/epm-release_downgrade: get_prev_release() { local FROM="$1" case "$FROM" in "p8") echo "p7" ;; "p9") echo "p8" ;; "p10") echo "p9" ;; "c7") echo "c6" ;; "c8") echo "c7" ;; "c8.1") echo "c8" ;; "c8.2") echo "c8.1" ;; "c9") echo "c8.2" ;; *) echo "$FROM" ;; esac } epm_release_downgrade() { assure_root assure_safe_run info "Starting upgrade/switch whole system to other release" info "Check also http://wiki.etersoft.ru/Admin/UpdateLinux" cd /tmp || fatal # TODO: it is possible eatmydata does not do his work export EPMNOEATMYDATA=1 case $DISTRNAME in ALTLinux) __epm_ru_update || fatal # try to detect current release by repo if [ "$DISTRVERSION" = "Sisyphus" ] || [ -z "$DISTRVERSION" ] ; then local dv dv="$(__detect_alt_release_by_repo)" if [ -n "$dv" ] && [ "$dv" != "$DISTRVERSION" ] ; then DISTRVERSION="$dv" info "Detected running $DISTRNAME $DISTRVERSION (according to using repos)" fi fi TARGET="" [ -n "$3" ] && fatal "Too many args: $*" if [ -n "$2" ] ; then DISTRVERSION="$1" info "Force current distro version as $DISTRVERSION" TARGET="$2" elif [ -n "$1" ] ; then TARGET="$1" fi [ -n "$TARGET" ] || TARGET="$(get_prev_release $DISTRVERSION)" __alt_repofix __switch_alt_to_distro $DISTRVERSION $TARGET && info "Done. The system has been successfully downgraded to the previous release '$TARGET'." return 0 ;; *) ;; esac case $PMTYPE in apt-rpm) #docmd epm update info "Have no idea how to downgrade $DISTRNAME" ;; *-dpkg) assure_exists do-release-upgrade update-manager-core sudocmd do-release-upgrade ;; packagekit) docmd pkcon upgrade-system "$@" ;; yum-rpm) docmd epm install rpm yum sudocmd yum clean all # TODO showcmd rpm -Uvh http://mirror.yandex.ru/fedora/linux/releases/16/Fedora/x86_64/os/Packages/fedora-release-16-1.noarch.rpm showcmd epm Upgrade ;; dnf-rpm) info "Check https://fedoraproject.org/wiki/DNF_system_upgrade for an additional info" docmd epm install dnf #docmd epm install epel-release yum-utils sudocmd dnf --refresh upgrade sudocmd dnf clean all assure_exists dnf-plugin-system-upgrade sudocmd dnf upgrade --refresh local RELEASEVER="$1" [ -n "$RELEASEVER" ] || RELEASEVER=$(($DISTRVERSION + 1)) #[ -n "$RELEASEVER" ] || fatal "Run me with new version" confirm_info "Upgrade to $DISTRNAME/$RELEASEVER" sudocmd dnf system-upgrade download --refresh --releasever=$RELEASEVER # TODO: from docs: # dnf system-upgrade reboot # FIXME: download all packages again sudocmd dnf distro-sync --releasever=$RELEASEVER info "Run epm autoorphans to remove orphaned packages" ;; urpm-rpm) sudocmd urpmi.removemedia -av # TODO showcmd urpmi.addmedia --distrib http://mirror.yandex.ru/mandriva/devel/2010.2/i586/ sudocmd urpmi --auto-update --replacefiles ;; zypper-rpm) docmd epm repolist # TODO # sudocmd zypper rr <номер_репозитория> showcmd rr N showcmd epm ar http://mirror.yandex.ru/opensuse/distribution/11.1/repo/oss 11.1oss showcmd zypper ref docmd epm update docmd epm install rpm zypper docmd epm upgrade ;; pacman) epm Upgrade ;; conary) epm Upgrade ;; emerge) epm Upgrade ;; guix) sudocmd guix pull --verbose ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-release_upgrade: assure_safe_run() { if [ "$TERM" = "linux" ] ; then echo "You have the best choise to run the '# epm release-upgrade' from text console." return fi if [ "$TERM" != "screen" ] ; then if [ -n "$force" ] ; then echo "You force me running not under screen (TERM=$TERM now)! You can lost your system!" return else warning "It is very dangerous to upgrade to next release from a GUI (your TERM=$TERM)." if is_installed screen ; then warning "You have 'screen' already installed, just run upgrade via screen (check https://losst.ru/komanda-screen-linux if needed)." else warning "It is recommended install 'screen' and run upgrade via screen (check https://losst.ru/komanda-screen-linux if needed)." fi fatal "or run me with --force if you understand the risk." fi fi # run under screen, check if systemd will not kill our processes local res if ! is_active_systemd systemd ; then return fi res="$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager KillUserProcesses)" if [ "$res" = "b false" ] ; then echo "Good news: systemd-logind will not kill your screen processes (KillUserProcesses=false)" return else if [ -n "$force" ] ; then warning "You force runnning even if systemd-logind kills screen on disconnect" else if ! epm installed systemd-settings-disable-kill-user-processes ; then docmd epm install systemd-settings-disable-kill-user-processes || fatal "Can't install the package above. Fix it or run with --force." fi # commented, will kick off the user from the system (ALT issue 50580) #docmd serv systemd-logind restart || fatal "Can't restart systemd-logind service. Fix it or run with --force." fatal "Now you need relogin to the system. In this session your screen still will be killed." fi fi # check too: KillExcludeUsers # can continue return 0 } __wcount() { echo "$*" | wc -w } __detect_alt_release_by_repo() { local BRD=$(cat /etc/apt/sources.list /etc/apt/sources.list.d/*.list \ | grep -v "^#" \ | egrep "[tpc][5-9]\.?[0-9]?/branch/" \ | sed -e "s|.*\([tpc][5-9]\.\?[0-9]\?\)/branch.*|\1|g" \ | sort -u ) if [ "$(__wcount $BRD)" = "1" ] ; then echo "$BRD" return fi local BRD=$(cat /etc/apt/sources.list /etc/apt/sources.list.d/*.list \ | grep -v "^#" \ | grep "Sisyphus/" \ | sed -e "s|.*\(Sisyphus\).*|\1|g" \ | sort -u ) if [ "$(__wcount $BRD)" = "1" ] ; then echo "$BRD" return fi return 1 } __get_conflict_release_pkg() { epm qf --quiet --short /etc/fedora-release | head -n1 } get_fix_release_pkg() { local TOINSTALL='' local FORCE='' if [ "$1" == "--force" ] ; then FORCE="$1" shift fi local TO="$1" if [ "$TO" = "Sisyphus" ] ; then TO="sisyphus" echo "apt-conf-$TO" elif [ "$TO" = "p10" ] ; then true #echo "apt-conf-$TO" else epmqp apt-conf-branch >/dev/null 2>/dev/null || echo "apt-conf-branch" fi if [ "$FORCE" == "--force" ] ; then # assure we have set needed release TOINSTALL="altlinux-release-$TO" else # just assure we have /etc/altlinux-release and switched from sisyphus if [ ! -s /etc/altlinux-release ] || epm qf /etc/altlinux-release | grep -q sisyphus ; then TOINSTALL="altlinux-release-$TO" fi fi #local AR="$(epm --short qf /etc/altlinux-release)" #if [ -n "$AR" ] && [ "$AR" != "$TOINSTALL" ] ; then # echo "$AR-" #fi # TODO: add bug? # workaround against obsoleted altlinux-release-sisyphus package from 2008 year [ "$TOINSTALL" = "altlinux-release-sisyphus" ] && TOINSTALL="branding-alt-sisyphus-release" # update if installed (just print package name here to include in the install list) epm --quiet --short installed alt-gpgkeys 2>/dev/null if epm --quiet --short -q etersoft-gpgkeys 2>/dev/null >/dev/null ; then # leave etersoft-gpgkeys only if we have LINUX@Etersoft repo epm rl | grep -q "LINUX@Etersoft" && echo etersoft-gpgkeys || echo alt-gpgkeys fi if [ -n "$TOINSTALL" ] ; then echo "$TOINSTALL" # workaround against # file /etc/fedora-release from install of altlinux-release-p8-20160414-alt1 conflicts with file from package branding-simply-linux-release-8.2.0-alt1 # problem local AR="$(__get_conflict_release_pkg)" if [ -n "$AR" ] && [ "$TOINSTALL" != "$AR" ] ; then echo $AR- fi fi } __check_system() { local TO="$1" shift # sure we have systemd if systemd is running if is_active_systemd systemd ; then docmd epm --skip-installed install systemd || fatal fi if [ "$TO" != "Sisyphus" ] ; then # we could miss DISTRVENDOR script during downgrade, reread set_distro_info if [ "$($DISTRVENDOR -v)" != "$TO" ] || epm installed altlinux-release-sisyphus >/dev/null ; then warning "Current distro still is not $TO, or altlinux-release-sisyphus package is installed." warning "Trying to fix with altlinux-release-$TO" docmd epm install altlinux-release-$TO fi fi # switch from prefdm: https://bugzilla.altlinux.org/show_bug.cgi?id=26405#c47 if is_active_systemd systemd ; then if serv display-manager exists || serv prefdm exists ; then # don't stop running X server! # docmd serv dm off docmd serv disable prefdm docmd serv disable display-manager docmd serv enable display-manager # enable first available DM for i in lightdm sddm lxde-lxdm gdm ; do serv $i exists && docmd serv enable $i && break done fi fi } __epm_ru_update() { docmd epm update && return # TODO: there can be errors due obsoleted alt-gpgkeys epm update 2>&1 | grep "E: Unknown vendor ID" || return info "Drop vendor signs" __alt_replace_sign_name "" docmd epm update } __switch_repo_to() { epm_reposwitch "$@" __epm_ru_update || fatal } get_next_release() { local FROM="$1" case "$FROM" in "p6") echo "p7" ;; "p7") echo "p8" ;; "p8") echo "p9" ;; "p9") echo "p10" ;; "c6") echo "c7" ;; "c7") echo "c8" ;; "c8") echo "c8.1" ;; "c8.1") echo "c8.2" ;; "c8.2") echo "c9" ;; *) echo "$FROM" ;; esac } __do_upgrade() { docmd epm $non_interactive $force_yes upgrade || fatal "Check the errors and run '# $0' again" } __switch_alt_to_distro() { local TO="$2" local FROM="$1" info try_change_alt_repo case "$*" in "p6"|"p6 p7"|"t6 p7"|"c6 c7") confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..." docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal __switch_repo_to $TO docmd epm install rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" __do_upgrade end_change_alt_repo docmd epm update-kernel info "Run epm release-upgrade again for update to p8" ;; "p7"|"p7 p8"|"t7 p8"|"c7 c8") confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..." docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal __switch_repo_to $TO docmd epm install rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" __do_upgrade end_change_alt_repo __check_system "$TO" docmd epm update-kernel || fatal info "Run epm release-upgrade again for update to p9" ;; "c8"|"c8.1"|"c8.2"|"c8 c8.1"|"c8.1 c8.2"|"c8 c8.2") confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..." docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal __switch_repo_to $TO docmd epm install rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" __do_upgrade end_change_alt_repo __check_system "$TO" docmd epm update-kernel || fatal ;; "p8 c8"|"p8 c8.1"|"p8 c8.2") confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..." docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal __switch_repo_to $TO docmd epm install rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" if epm installed libcrypt ; then # glibc-core coflicts libcrypt docmd epm downgrade apt pam pam0_passwdqc glibc-core libcrypt- || fatal fi docmd epm $non_interactive $force_yes downgrade || fatal __do_upgrade end_change_alt_repo __check_system "$TO" docmd epm update-kernel || fatal ;; "p8"|"p8 p9"|"t8 p9"|"c8 c9"|"c8 p9"|"c8.1 p9"|"c8.2 p9"|"p9 p9") confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..." docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal info "Workaround for https://bugzilla.altlinux.org/show_bug.cgi?id=35492 ..." if epm installed gdb >/dev/null ; then docmd epm remove gdb || fatal fi __switch_repo_to $TO __do_upgrade end_change_alt_repo docmd epm install rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" __check_system "$TO" docmd epm update-kernel || fatal info "Run epm release-upgrade again for update to p10" ;; "p9"|"p9 p10"|"p10 p10") info "Upgrade all packages to current $FROM repository" __do_upgrade confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..." docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal __switch_repo_to $TO __do_upgrade end_change_alt_repo docmd epm install rpm apt "$(get_fix_release_pkg "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" __check_system "$TO" docmd epm update-kernel -t std-def || fatal ;; "p9 p8"|"c8.1 c8"|"c8.1 p8"|"p8 p8") confirm_info "Downgrade $DISTRNAME from $FROM to $TO ..." docmd epm install "$(get_fix_release_pkg "$FROM")" __switch_repo_to $TO docmd epm downgrade rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" if epm installed libcrypt >/dev/null ; then # glibc-core coflicts libcrypt docmd epm downgrade apt rpm pam pam0_passwdqc glibc-core libcrypt- || fatal fi docmd epm $force_yes $non_interactive downgrade || fatal "Check the error and run '# epm downgrade'" end_change_alt_repo __check_system "$TO" docmd epm upgrade || fatal ;; "p9 c8"|"p9 c8.1"|"p9 c8.2") confirm_info "Downgrade $DISTRNAME from $FROM to $TO ..." docmd epm install "$(get_fix_release_pkg "$FROM")" __switch_repo_to $TO docmd epm downgrade rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" #if epm installed libcrypt >/dev/null ; then # # glibc-core coflicts libcrypt # docmd epm downgrade apt rpm pam pam0_passwdqc glibc-core libcrypt- || fatal #fi docmd epm $force_yes $non_interactive downgrade || fatal "Check the error and run '# epm downgrade'" end_change_alt_repo __check_system "$TO" docmd epm upgrade || fatal ;; "p10 p9") confirm_info "Downgrade $DISTRNAME from $FROM to $TO ..." docmd epm install "$(get_fix_release_pkg "$FROM")" __switch_repo_to $TO docmd epm downgrade rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" docmd epm $force_yes $non_interactive downgrade || fatal "Check the error and run '# epm downgrade'" end_change_alt_repo __check_system "$TO" docmd epm upgrade || fatal ;; "Sisyphus p8"|"Sisyphus p9"|"Sisyphus p10"|"Sisyphus c8"|"Sisyphus c8.1") confirm_info "Downgrade $DISTRNAME from $FROM to $TO ..." docmd epm install "$(get_fix_release_pkg "$FROM")" __switch_repo_to $TO docmd epm install rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" docmd epm $force_yes $non_interactive downgrade || fatal "Check the error and run '# epm downgrade'" end_change_alt_repo __check_system "$TO" docmd epm upgrade || fatal ;; "p8 Sisyphus"|"p9 Sisyphus"|"p10 Sisyphus"|"Sisyphus Sisyphus") confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..." docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal docmd epm upgrade || fatal # TODO: epm_reposwitch?? __replace_alt_version_in_repo "$FROM/branch/" "$TO/" __alt_repofix "alt" [ -s /etc/rpm/macros.d/p10 ] && rm -fv /etc/rpm/macros.d/p10 __epm_ru_update || fatal docmd epm install rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check the errors and run '# epm release-upgrade' again" #local ADDPKG #ADDPKG=$(epm -q --short make-initrd sssd-ad 2>/dev/null) #docmd epm install librpm7 librpm rpm apt $ADDPKG "$(get_fix_release_pkg --force "$TO")" ConsoleKit2- || fatal "Check an error and run again" docmd epm $force_yes $non_interactive upgrade || fatal "Check the error and run '# epm release-upgrade' again or just '# epm upgrade'" docmd epm $force_yes $non_interactive downgrade || fatal "Check the error and run '# epm downgrade'" end_change_alt_repo __check_system "$TO" docmd epm update-kernel || fatal ;; *) if [ "$FROM" = "$TO" ] ; then info "It seems your system is already $DISTRNAME $TO" else warning "Unknown distro version. Have no idea how to switch from $DISTRNAME $FROM to $DISTRNAME $TO." fi end_change_alt_repo info "Try run f.i. '# epm release-upgrade p10' or '# epm release-downgrade p9' or '# epm release-upgrade Sisyphus'" info "Also possible you need install altlinux-release-p? package for correct distro version detecting" return 1 esac docmd epm clean docmd epm update info "Note: Also you can try '# epm autoremove' and '# epm autoorphans' commands to remove obsoleted and unused packages." } epm_release_upgrade() { assure_root assure_safe_run info "Starting upgrade/switch whole system to other release" info "Check also http://wiki.etersoft.ru/Admin/UpdateLinux" cd / || fatal # TODO: it is possible eatmydata does not do his work export EPMNOEATMYDATA=1 case $DISTRNAME in ALTLinux) __epm_ru_update || fatal # TODO: remove this hack (or move it to distro_info) # try to detect current release by repo if [ "$DISTRVERSION" = "Sisyphus" ] || [ -z "$DISTRVERSION" ] ; then local dv dv="$(__detect_alt_release_by_repo)" if [ -n "$dv" ] && [ "$dv" != "$DISTRVERSION" ] ; then DISTRVERSION="$dv" info "Detected running $DISTRNAME $DISTRVERSION (according to using repos)" fi fi TARGET="" [ -n "$3" ] && fatal "Too many args: $*" if [ -n "$2" ] ; then DISTRVERSION="$1" info "Force current distro version as $DISTRVERSION" TARGET="$2" elif [ -n "$1" ] ; then TARGET="$1" fi [ -n "$TARGET" ] || TARGET="$(get_next_release $DISTRVERSION)" __alt_repofix __switch_alt_to_distro $DISTRVERSION $TARGET && info "Done. The system has been successfully upgraded to the next release '$TO'." return 0 ;; *) ;; esac case $PMTYPE in apt-rpm) #docmd epm update info "Have no idea how to upgrade $DISTRNAME. It is possible you need use 'release-downgrade'" ;; *-dpkg) assure_exists do-release-upgrade update-manager-core sudocmd do-release-upgrade ;; packagekit) docmd pkcon upgrade-system "$@" ;; yum-rpm) docmd epm install rpm yum sudocmd yum clean all # TODO showcmd rpm -Uvh http://mirror.yandex.ru/fedora/linux/releases/16/Fedora/x86_64/os/Packages/fedora-release-16-1.noarch.rpm showcmd epm Upgrade ;; dnf-rpm) if [ "$DISTRNAME/$DISTRVERSION" = "CentOS/8" ] ; then if [ "$1" = "RockyLinux" ] ; then info "https://github.com/rocky-linux/rocky-tools/tree/main/migrate2rocky/" confirm_info "Switch to Rocky Linux 8.x" cd /tmp showcmd epm install git sudocmd git clone https://github.com/rocky-linux/rocky-tools.git || fatal sudocmd bash rocky-tools/migrate2rocky/migrate2rocky.sh -r exit fi if [ "$1" = "OracleLinux" ] ; then info "Check https://t.me/srv_admin/1630" confirm_info "Switch to Oracle Linux 8.x" cd /tmp showcmd epm install git sudocmd sed -i -r \ -e 's!^mirrorlist=!#mirrorlist=!' \ -e 's!^#?baseurl=http://(mirror|vault).centos.org/\$contentdir/\$releasever/!baseurl=https://dl.rockylinux.org/vault/centos/8.5.2111/!i' \ /etc/yum.repos.d/CentOS-*.repo sudocmd git clone https://github.com/oracle/centos2ol.git || fatal a= bash centos2ol/centos2ol.sh exit fi info "Check https://www.cyberciti.biz/howto/upgrade-migrate-from-centos-8-to-centos-stream-conversion/" confirm_info "Switch to CentOS Stream?" sudocmd sed -i -r \ -e 's!^mirrorlist=!#mirrorlist=!' \ -e 's!^#?baseurl=http://(mirror|vault).centos.org/\$contentdir/\$releasever/!baseurl=https://dl.rockylinux.org/vault/centos/8.5.2111/!i' \ /etc/yum.repos.d/CentOS-*.repo docmd epm install centos-release-stream sudocmd dnf swap centos-{linux,stream}-repos sudocmd dnf distro-sync info "You can run '# epm autoorphans' to remove orphaned packages" exit fi info "Check https://fedoraproject.org/wiki/DNF_system_upgrade for an additional info" #docmd epm install epel-release yum-utils sudocmd dnf --refresh upgrade || fatal sudocmd dnf clean all assure_exists dnf-plugin-system-upgrade sudocmd dnf upgrade --refresh local RELEASEVER="$1" [ -n "$RELEASEVER" ] || RELEASEVER=$(($DISTRVERSION + 1)) #[ -n "$RELEASEVER" ] || fatal "Run me with new version" confirm_info "Upgrade to $DISTRNAME/$RELEASEVER" sudocmd dnf system-upgrade download --refresh --releasever=$RELEASEVER # TODO: from docs: # dnf system-upgrade reboot # FIXME: download all packages again sudocmd dnf distro-sync --releasever=$RELEASEVER info "You can run '# epm autoorphans' to remove orphaned packages" ;; urpm-rpm) sudocmd urpmi.removemedia -av # TODO showcmd urpmi.addmedia --distrib http://mirror.yandex.ru/mandriva/devel/2010.2/i586/ sudocmd urpmi --auto-update --replacefiles ;; zypper-rpm) docmd epm repolist # TODO # sudocmd zypper rr <номер_репозитория> showcmd rr N showcmd epm ar http://mirror.yandex.ru/opensuse/distribution/11.1/repo/oss 11.1oss showcmd zypper ref docmd epm update docmd epm install rpm zypper docmd epm upgrade ;; pacman) epm Upgrade ;; conary) epm Upgrade ;; emerge) epm Upgrade ;; guix) sudocmd guix pull --verbose ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-remove: RPMISNOTINSTALLED=202 __check_rpm_e_result() { grep -q "is not installed" $1 && return $RPMISNOTINSTALLED return $2 } epm_remove_low() { [ -z "$1" ] && return warmup_lowbase case $PMTYPE in *-rpm) cd /tmp || fatal __epm_check_vendor $@ store_output sudocmd rpm -ev $noscripts $nodeps $@ # rpm returns number of packages if failed on removing __check_rpm_e_result $RC_STDOUT $? RES=$? clean_store_output cd - >/dev/null return $RES ;; *-dpkg|-dpkg) # shellcheck disable=SC2046 sudocmd dpkg -P $(subst_option nodeps --force-all) $(print_name "$@") return ;; pkgsrc) sudocmd pkg_delete -r $@ return ;; pkgng) sudocmd pkg delete -R $@ return ;; emerge) sudocmd emerge --unmerge $@ return ;; pacman) sudocmd pacman -R $@ return ;; appget|winget) sudocmd $PMTYPE uninstall $@ return ;; slackpkg) sudocmd /sbin/removepkg $@ return ;; esac return 1 } epm_remove_names() { [ -z "$1" ] && return warmup_bases case $PMTYPE in apt-dpkg) sudocmd apt-get remove --purge $APTOPTIONS $@ return ;; aptitude-dpkg) sudocmd aptitude purge $@ return ;; apt-rpm) sudocmd apt-get remove $APTOPTIONS $@ return ;; packagekit) docmd pkcon remove $@ return ;; deepsolver-rpm) sudocmd ds-remove $@ return ;; urpm-rpm) sudocmd urpme $@ return ;; pkgsrc) # without dependencies sudocmd pkg_delete $@ return ;; pkgng) sudocmd pkg delete -R $@ return ;; emerge) #sudocmd emerge --unmerge $@ sudocmd emerge -aC $@ return ;; pacman) sudocmd pacman -Rc $@ return ;; yum-rpm) sudocmd yum remove $@ return ;; dnf-rpm) sudocmd dnf remove $@ return ;; snappy) sudocmd snappy uninstall $@ return ;; zypper-rpm) sudocmd zypper remove --clean-deps $@ return ;; mpkg) sudocmd mpkg remove $@ return ;; conary) sudocmd conary erase $@ return ;; npackd) sudocmd npackdcl remove --package=$1 return ;; nix) sudocmd nix-env --uninstall $@ return ;; apk) sudocmd apk del $@ return ;; guix) sudocmd guix package -r $@ return ;; android) sudocmd pm uninstall $@ return ;; chocolatey) sudocmd chocolatey uninstall $@ return ;; slackpkg) sudocmd /usr/sbin/slackpkg remove $@ return ;; homebrew) docmd brew remove $@ return ;; aptcyg) sudocmd apt-cyg remove $@ return ;; xbps) sudocmd xbps remove -R $@ return ;; appget|winget) sudocmd $PMTYPE uninstall $@ return ;; opkg) # shellcheck disable=SC2046 sudocmd opkg $(subst_option force -force-depends) remove $@ return ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } epm_remove_nonint() { warmup_bases case $PMTYPE in apt-dpkg) sudocmd apt-get -y --force-yes remove --purge $@ return ;; aptitude-dpkg) sudocmd aptitude -y purge $@ return ;; apt-rpm) sudocmd apt-get -y --force-yes remove $@ return ;; packagekit) docmd pkcon remove --noninteractive $@ return ;; urpm-rpm) sudocmd urpme --auto $@ return ;; pacman) sudocmd pacman -Rc --noconfirm $@ return ;; yum-rpm) sudocmd yum -y remove $@ return ;; dnf-rpm) sudocmd dnf remove --assumeyes $@ return ;; zypper-rpm) sudocmd zypper --non-interactive remove --clean-deps $@ return ;; slackpkg) sudocmd /usr/sbin/slackpkg -batch=on -default_answer=yes remove $@ return ;; pkgng) sudocmd pkg delete -y -R $@ return ;; opkg) sudocmd opkg -force-defaults remove $@ return ;; appget|winget) sudocmd $PMTYPE uninstall -s $@ return ;; xbps) sudocmd xbps remove -y $@ return ;; esac return 5 } epm_print_remove_command() { case $PMTYPE in *-rpm) echo "rpm -ev $nodeps $*" ;; *-dpkg) echo "dpkg -P $*" ;; packagekit-*) echo "pkcon remove --noninteractive $*" ;; pkgsrc) echo "pkg_delete -r $*" ;; pkgng) echo "pkg delete -R $*" ;; pacman) echo "pacman -R $*" ;; emerge) echo "emerge --unmerge $*" ;; slackpkg) echo "/sbin/removepkg $*" ;; opkg) echo "opkg remove $*" ;; aptcyg) echo "apt-cyg remove $*" ;; xbps) echo "xbps remove -y $*" ;; appget|winget) echo "$PMTYPE uninstall -s $*" ;; *) fatal "Have no suitable appropriate remove command for $PMTYPE" ;; esac } epm_remove() { if [ -n "$show_command_only" ] ; then epm_print_remove_command $pkg_filenames return fi if [ "$DISTRNAME" = "ALTLinux" ] ; then if tasknumber "$pkg_names" >/dev/null ; then assure_exists apt-repo pkg_names="$(get_task_packages $pkg_names)" fi fi # TODO: fix pkg_names override # get full package name(s) from the package file(s) [ -n "$pkg_files" ] && pkg_names="$pkg_names $(epm query $pkg_files)" pkg_files='' if [ -z "$pkg_names" ] ; then warning "no package(s) to remove." exit 0 fi # remove according current arch (if x86_64) by default pkg_names="$(echo $pkg_names | exp_with_arch_suffix)" if [ -n "$dryrun" ] ; then info "Packages for removing:" echo "$pkg_names" case $PMTYPE in apt-rpm) nodeps="--test" APTOPTIONS="--simulate" ;; apt-deb) nodeps="--simulate" APTOPTIONS="--simulate" ;; *) return ;; esac fi if [ -n "$skip_missed" ] ; then pkg_names="$(get_only_installed_packages $pkg_names)" fi epm_remove_low $pkg_names && return local STATUS=$? if [ -n "$direct" ] || [ -n "$nodeps" ] || [ "$STATUS" = "$RPMISNOTINSTALLED" ]; then [ -n "$force" ] || return $STATUS fi # get package name for hi level package management command (with version if supported and if possible) pkg_names=$(__epm_get_hilevel_name $pkg_names) if [ -n "$non_interactive" ] ; then epm_remove_nonint $pkg_names local RET=$? # if not separate command, use usual command [ "$RET" = "5" ] || return $RET fi epm_remove_names $pkg_names } # File bin/epm-remove_old_kernels: epm_remove_old_kernels() { warmup_bases case $DISTRNAME in ALTLinux) if ! __epm_query_package kernel-image >/dev/null ; then info "No installed kernel packages, skipping cleaning" return fi assure_exists update-kernel update-kernel 0.9.9 sudocmd remove-old-kernels $(subst_option non_interactive -y) "$@" # remove unused nvidia drivers if which nvidia-clean-driver 2>/dev/null ; then if [ -n "$non_interactive" ] ; then yes | sudocmd nvidia-clean-driver else sudocmd nvidia-clean-driver fi fi return ;; Ubuntu) if ! __epm_query_package linux-image >/dev/null ; then info "No installed kernel packages, skipping cleaning" return fi info "Note: it is enough to use eepm autoremove for old kernel removing..." info "Check also http://ubuntuhandbook.org/index.php/2016/05/remove-old-kernels-ubuntu-16-04/" # http://www.opennet.ru/tips/2980_ubuntu_apt_clean_kernel_packet.shtml case $DISTRVERSION in 10.04|12.04|14.04|15.04|15.10) assure_exists purge-old-kernels bikeshed ;; *) # since Ubuntu 16.04 assure_exists purge-old-kernels byobu ;; esac sudocmd purge-old-kernels "$@" return ;; Gentoo) sudocmd emerge -P gentoo-sources return ;; VoidLinux) sudocmd vkpurge rm all return ;; esac case $PMTYPE in *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-removerepo: __epm_removerepo_alt_grepremove() { local rl # ^rpm means full string if [ "$1" = "all" ] || rhas "$1" "^rpm" ; then rl="$1" else rl="$( (epm --quiet repolist) 2>/dev/null | grep -E "$1")" [ -z "$rl" ] && warning "Can't find '$1' in the repos (see '# epm repolist' output)" && return 1 fi echo "$rl" | while read rp ; do # TODO: print removed lines if [ -n "$dryrun" ] ; then docmd apt-repo $dryrun rm "$rp" continue fi if [ -n "$verbose" ] ; then sudocmd apt-repo $dryrun rm "$rp" else sudorun apt-repo $dryrun rm "$rp" fi done } __epm_removerepo_alt() { local repo="$*" [ -n "$repo" ] || fatal "No such repo or task. Use epm repo remove <autoimports|archive|tasks|TASKNUMBER>" assure_exists apt-repo if tasknumber "$repo" >/dev/null ; then local tn for tn in $(tasknumber "$repo") ; do __epm_removerepo_alt_grepremove " repo/$tn/" done return fi case "$1" in autoimports) info "remove autoimports repo" [ -n "$DISTRVERSION" ] || fatal "Empty DISTRVERSION" repo="autoimports.$(echo "$DISTRVERSION" | tr "[:upper:]" "[:lower:]")" sudocmd apt-repo $dryrun rm "$repo" ;; archive) info "remove archive repos" __epm_removerepo_alt_grepremove "archive/" ;; tasks) info "remove task repos" __epm_removerepo_alt_grepremove " repo/[0-9]+/" ;; task) shift __epm_removerepo_alt_grepremove " repo/$1/" ;; -*) fatal "epm removerepo: no options are supported" ;; *) __epm_removerepo_alt_grepremove "$*" ;; esac } epm_removerepo() { case $DISTRNAME in ALTLinux) __epm_removerepo_alt "$@" return ;; esac; case $PMTYPE in apt-dpkg) assure_exists apt-add-repository software-properties-common set_sudo if [ "$DISTRNAME" = "AstraLinux" ] ; then echo "Use workaround for AstraLinux" [ -n "$*" ] || fatal "empty repo name" # aptsources.distro.NoDistroTemplateException: Error: could not find a distribution template for AstraLinuxCE/orel sudocmd sed -i -e "s|.*$*.*||" /etc/apt/sources.list if [ -d /etc/apt/sources.list.d ] && ls /etc/apt/sources.list.d/*.list >/dev/null 2>/dev/null ; then sudocmd sed -i -e "s|.*$*.*||" /etc/apt/sources.list.d/*.list fi exit fi # FIXME: it is possible there is troubles to pass the args sudocmd apt-add-repository --remove "$*" info "Check file /etc/apt/sources.list if needed" ;; aptitude-dpkg) info "You need remove repo from /etc/apt/sources.list" ;; yum-rpm) assure_exists yum-utils sudocmd yum-config-manager --disable "$@" ;; urpm-rpm) sudocmd urpmi.removemedia "$@" ;; zypper-rpm) sudocmd zypper removerepo "$@" ;; emerge) sudocmd layman "-d$@" ;; pacman) info "You need remove repo from /etc/pacman.conf" ;; npackd) sudocmd npackdcl remove-repo --url="$@" ;; winget) sudocmd winget source remove "$@" ;; slackpkg) info "You need remove repo from /etc/slackpkg/mirrors" ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-repack: __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_target_pkgs $(realpath "$pkg")" done [ -n "$split_replaced_pkgs" ] } __epm_repack_rpm_to_deb() { local pkg assure_exists alien assure_exists fakeroot assure_exists rpm repacked_debs='' local TDIR=$(mktemp -d) cd $TDIR || fatal for pkg in $rpmpkgs ; do showcmd_store_output fakeroot alien -d -k $scripts "$pkg" local DEBCONVERTED=$(grep "deb generated" $RC_STDOUT | sed -e "s| generated||g") repacked_debs="$repacked_rpms $(realpath $DEBCONVERTED)" to_remove_pkg_files="$to_remove_pkg_files $(realpath $DEBCONVERTED)" clean_store_output 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 } __epm_check_if_try_install_rpm() { __epm_split_by_pkg_type rpm "$@" || return 1 __epm_repack_rpm_to_deb $split_replaced_pkgs # TODO: move to install docmd epm install $repacked_debs return 0 } __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 } __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 # 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 } __check_stoplist() { cat <<EOF | grep -q "^$1$" kesl kesl-astra klnagent klnagent64 klnagent64-astra EOF } __apply_fix_code() { local repackcode="$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() { cat <<EOF >$HOME/.rpmmacros %_topdir $HOME/RPM %_tmppath $TMPDIR %packager EPM <support@etersoft.ru> %_gpg_name support@etersoft.ru EOF to_remove_pkg_files="$to_remove_pkg_files $HOME/.rpmmacros" } __epm_repack_to_rpm() { local pkgs="$*" assure_distr ALTLinux "install --repack" # install epm-repack for static (package based) dependencies assure_exists fakeroot || fatal assure_exists alien || fatal assure_exists /usr/bin/rpmbuild || 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_rpms='' for pkg in $pkgs ; do tmpbuilddir=$HOME/$(basename $pkg).tmpdir mkdir $tmpbuilddir abspkg="$(realpath $pkg)" info "" info "Repacking $abspkg to local rpm format ..." # alien failed with spaced names # alpkg=$abspkg 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 rpm package instead of $alpkg (It is not recommended to use --force to skip this checking." # don't use abs package path: copy package to temp dir and use there cp $verbose $pkg $tmpbuilddir/../$alpkg cd $tmpbuilddir/../ || fatal PKGNAME='' VERSION='' # convert tarballs to tar (for alien) if ! echo "$pkg" | grep -q "\.rpm" && ! echo "$pkg" | grep -q "\.deb" ; then VERSION="$(echo "$alpkg" | grep -o -P "[-_.]([0-9])([0-9])*(\.[0-9])*" | head -n1 | sed -e 's|^[-_.]||')" #" if [ -n "$VERSION" ] ; then PKGNAME="$(echo "$alpkg" | sed -e "s|[-_.]$VERSION.*||")" 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 -fv $alpkg alpkg=$newalpkg fi fi fi cd $tmpbuilddir/ || fatal if [ -n "$verbose" ] ; then docmd fakeroot alien --generate --to-rpm $verbose $scripts "../$alpkg" || fatal else showcmd fakeroot alien --generate --to-rpm $scripts "../$alpkg" a='' fakeroot 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 __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 fakeroot rpmbuild --buildroot $tmpbuilddir/$subdir --define='_allow_root_build 1' -bb $spec if [ -n "$verbose" ] ; then a='' fakeroot rpmbuild --buildroot $tmpbuilddir/$subdir --define='_allow_root_build 1' -bb $spec || fatal else a='' fakeroot rpmbuild --buildroot $tmpbuilddir/$subdir --define='_allow_root_build 1' -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_rpms="$repacked_rpms $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_check_if_try_install_deb() { __epm_split_by_pkg_type deb "$@" || return 1 __epm_repack_to_rpm $split_replaced_pkgs || fatal # TODO: move to install docmd epm install $repacked_rpms # 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 2>/dev/null fi 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 __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 case $PKGFORMAT in rpm) __epm_repack_to_rpm $pkg_files || fatal echo echo "Adapted packages:" cp $repacked_rpms "$CURDIR" for i in $repacked_rpms ; do echo " $(pwd)/$(basename "$i")" done ;; deb) if __epm_split_by_pkg_type rpm $pkg_files ; then __epm_repack_rpm_to_deb $split_replaced_pkgs cp -v $repacked_debs . pkg_files="$(estrlist exclude $split_replaced_pkgs $pkg_files)" [ -n "$pkg_files" ] && warning "There are left unconverted packages $pkg_files." fi ;; *) fatal "$PKGFORMAT is not supported for repack yet" ;; esac # 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 } # File bin/epm-repo: epm_repo() { local CMD="$1" [ -n "$CMD" ] && shift case $CMD in "-h"|"--help"|help) # HELPCMD: help get_help HELPCMD $SHAREDIR/epm-repo cat <<EOF Examples: epm repo set p9 epm repo add autoimports epm repo list epm repo change yandex EOF ;; ""|list) # HELPCMD: list packages epm_repolist "$@" ;; fix) # HELPCMD: fix paths in sources lists (ALT Linux only) epm_repofix "$@" ;; change) # HELPCMD: <mirror>: switch sources to the mirror (supports etersoft/yandex/basealt): rewrite URLs to the specified server epm_repofix "$@" ;; set) # HELPCMD: <mirror>: remove all existing sources and add mirror for the branch epm repo rm all epm addrepo "$@" ;; switch) # HELPCMD: switch repo to <repo>: rewrite URLs to the repo epm_reposwitch "$@" ;; clean) # HELPCMD: remove temp. repos (tasks and CD-ROMs) # TODO: check for ALT sudocmd apt-repo $dryrun clean ;; save) epm_reposave "$@" ;; restore) epm_reporestore "$@" ;; reset) epm_reporeset "$@" ;; add) # HELPCMD: add package repo (etersoft, autoimports, archive 2017/12/31); run with param to get list epm_addrepo "$@" ;; Add) # HELPCMD: like add, but do update after add epm_addrepo "$@" epm update ;; rm|remove) # HELPCMD: remove repository from sources list (epm repo remove all for all) epm_removerepo "$@" ;; *) fatal "Unknown command $ epm repo '$CMD'" ;; esac } # File bin/epm-repofix: __replace_text_in_alt_repo() { local i for i in /etc/apt/sources.list /etc/apt/sources.list.d/*.list ; do [ -s "$i" ] || continue regexp_subst "$1" "$i" done } __repofix_check_vendor() { local i for i in /etc/apt/vendors.list.d/*.list; do [ -e "$i" ] || continue grep -q "^simple-key \"$1\"" $i && return done return 1 } __repofix_filter_vendor() { local br="$1" br="$(echo "$br" | sed -e "s|\..*||")" case $br in c8) br="cert8" ;; c9) br="cert9" ;; esac echo "$br" } __replace_alt_version_in_repo() { local i assure_exists apt-repo #echo "Upgrading $DISTRNAME from $1 to $2 ..." a='' apt-repo list | sed -e "s|\($1\)|{\1}->{$2}|g" | grep -E --color -- "$1" # ask and replace only we will have changes if a='' apt-repo list | grep -E -q -- "$1" ; then __replace_text_in_alt_repo "/^ *#/! s!$1!$2!g" fi #docmd apt-repo list } __alt_replace_sign_name() { local TO="$1" __replace_text_in_alt_repo "/^ *#/! s!\[alt\]!$TO!g" __replace_text_in_alt_repo "/^ *#/! s!\[sisyphus\]!$TO!g" __replace_text_in_alt_repo "/^ *#/! s!\[updates\]!$TO!g" __replace_text_in_alt_repo "/^ *#/! s!\[cert[789]\]!$TO!g" __replace_text_in_alt_repo "/^ *#/! s!\[p10\.?[0-9]?\]!$TO!g" __replace_text_in_alt_repo "/^ *#/! s!\[[tpc][6-9]\.?[0-9]?\]!$TO!g" } __alt_repofix() { local TO="$1" epm --quiet repo fix >/dev/null if [ -n "$TO" ] ; then # TODO: switch it in repo code TO="$(__repofix_filter_vendor "$TO")" __alt_replace_sign_name "[$TO]" fi } epm_reposwitch() { local TO="$1" [ -n "$TO" ] || fatal "run repo switch with arg (p9, p10, Sisyphus)" __replace_alt_version_in_repo "Sisyphus/" "$TO/branch/" __replace_alt_version_in_repo "[tpc][5-9]\.?[0-9]?/branch/" "$TO/branch/" __replace_alt_version_in_repo "p10\.?[0-9]?/branch/" "$TO/branch/" __alt_repofix $TO if [ "$TO" = "p10" ] ; then echo '%_priority_distbranch p10' >/etc/rpm/macros.d/p10 else rm -fv /etc/rpm/macros.d/p10 fi #epm repo list } __try_fix_apt_source_list() { local list="$1" local br="$(__repofix_filter_vendor "$2")" local path="$3" if grep -q -e "^[^#].*$path" $list ; then if __repofix_check_vendor $br ; then regexp_subst "/$path/s/^rpm[[:space:]]*([fhr])/rpm [$br] \1/" $list else warning "Skip set $br vendor key (it is missed) for $list" regexp_subst "/$path/s/^rpm[[:space:]]*\[$br\][[:space:]]*([fhr])/rpm \1/" $list fi fi } __fix_alt_sources_list() { # for beauty spaces local SUBST_ALT_RULE1='s!^(.*)[/ ](ALTLinux|LINUX\@Etersoft)[/ ]*(Sisyphus)[/ ](x86_64|i586|x86_64-i586|noarch|aarch64) !\1 \2/\3/\4 !gi' local SUBST_ALT_RULE2='s!^(.*)[/ ](ALTLinux|LINUX\@Etersoft)[/ ]*([tcp][6-9]\.?[0-9]?[/ ]branch|[tcp]1[012][/ ]branch)[/ ](x86_64|i586|x86_64-i586|noarch|aarch64) !\1 \2/\3/\4 !gi' local i for i in "$@" ; do [ -s "$i" ] || continue #perl -i.bak -pe "$SUBST_ALT_RULE" $i # TODO: only for uncommented strings #sed -i -r -e "$SUBST_ALT_RULE" $i regexp_subst "/^ *#/! s| pub|/pub|" $i regexp_subst "/^ *#/! $SUBST_ALT_RULE1" $i regexp_subst "/^ *#/! $SUBST_ALT_RULE2" $i # Sisyphus uses 'alt' vendor key __try_fix_apt_source_list $i alt "ALTLinux\/Sisyphus" __try_fix_apt_source_list $i etersoft "Etersoft\/Sisyphus" # skip branch replacement for ALT Linux Sisyphus [ "$DISTRVERSION" = "Sisyphus" ] && continue # add signs for branches __try_fix_apt_source_list $i $DISTRVERSION "ALTLinux\/$DISTRVERSION\/branch" __try_fix_apt_source_list $i etersoft "Etersoft\/$DISTRVERSION\/branch" done } __subst_with_etersoft_url() { local NURL="http://download.etersoft.ru/pub ALTLinux" echo "$1" | sed \ -e "s|h\?f\?t\?tp://ftp.altlinux.org/pub/distributions/* ALTLinux|$NURL|" \ -e "s|h\?f\?t\?tp://ftp.basealt.ru/pub/distributions/* ALTLinux|$NURL|" \ -e "s|h\?f\?t\?tp://mirror.yandex.ru/* altlinux|$NURL|" } __subst_with_yandex_url() { local NURL="http://mirror.yandex.ru altlinux" echo "$1" | sed \ -e "s|h\?f\?t\?tp://ftp.altlinux.org/pub/distributions/* ALTLinux|$NURL|" \ -e "s|h\?f\?t\?tp://ftp.basealt.ru/pub/distributions/* ALTLinux|$NURL|" \ -e "s|h\?f\?t\?tp://ftp.etersoft.ru/pub/* ALTLinux|$NURL|" \ -e "s|h\?f\?t\?tp://download.etersoft.ru/pub/* ALTLinux|$NURL|" } __subst_with_basealt_url() { local NURL="http://ftp.basealt.ru/pub/distributions ALTLinux" echo "$1" | sed \ -e "s|h\?f\?t\?tp://mirror.yandex.ru/* altlinux|$NURL|" \ -e "s|h\?f\?t\?tp://ftp.etersoft.ru/pub/* ALTLinux|$NURL|" \ -e "s|h\?f\?t\?tp://download.etersoft.ru/pub/* ALTLinux|$NURL|" } __fix_repo_to_etersoft() { local NN a="" apt-repo list | grep -v debuginfo | grep -v etersoft | grep -v "file:/" | while read nn ; do NN="$(__subst_with_etersoft_url "$nn")" [ "$NN" = "$nn" ] && continue epm removerepo "$nn" epm addrepo "$NN" done } __fix_repo_to_yandex() { local NN a="" apt-repo list | grep -v debuginfo | grep -v mirror\.yandex | grep -v "file:/" | while read nn ; do NN="$(__subst_with_yandex_url "$nn")" [ "$NN" = "$nn" ] && continue epm removerepo "$nn" epm addrepo "$NN" done } __fix_repo_to_basealt() { local NN a="" apt-repo list | grep -v debuginfo | grep -v ftp.basealt | grep -v "file:/" | while read nn ; do NN="$(__subst_with_basealt_url "$nn")" [ "$NN" = "$nn" ] && continue epm removerepo "$nn" epm addrepo "$NN" done } epm_repofix() { case $DISTRNAME in ALTLinux) assure_exists apt-repo [ -n "$quiet" ] || docmd apt-repo list assure_root __fix_alt_sources_list /etc/apt/sources.list __fix_alt_sources_list /etc/apt/sources.list.d/*.list # TODO: move to repo change if [ "$1" = "etersoft" ] ; then __fix_repo_to_etersoft /etc/apt/sources.list __fix_repo_to_etersoft /etc/apt/sources.list.d/*.list fi if [ "$1" = "yandex" ] ; then __fix_repo_to_yandex /etc/apt/sources.list __fix_repo_to_yandex /etc/apt/sources.list.d/*.list fi if [ "$1" = "basealt" ] ; then __fix_repo_to_basealt /etc/apt/sources.list __fix_repo_to_basealt /etc/apt/sources.list.d/*.list fi docmd apt-repo list return ;; esac case $PMTYPE in *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-repolist: __print_apt_sources_list() { local i for i in $@ ; do test -r "$i" || continue grep -v -- "^.*#" $i done | grep -v -- "^ *\$" } __print_apt_sources_list_list() { local i for i in $@ ; do test -r "$i" || continue grep -v -- "^.*#" $i | grep -v -- "^ *\$" | grep -q . && echo "$i" done } __info_cyan() { set_boldcolor $CYAN echo "$*" >&2 restore_color } __print_apt_sources_list_verbose() { local i for i in $@ ; do test -r "$i" || continue grep -v -- "^.*#" $i | grep -v -- "^ *\$" | grep -q . && __info_cyan "$i:" || continue grep -v -- "^.*#" $i | grep -v -- "^ *\$" | sed -e 's|^| |' done } print_apt_sources_list() { local LISTS='/etc/apt/sources.list /etc/apt/sources.list.d/*.list' if [ -n "$quiet" ] ; then __print_apt_sources_list $LISTS else __print_apt_sources_list_verbose $LISTS fi } epm_repolist() { [ -z "$*" ] || [ "$PMTYPE" = "apt-rpm" ] || fatal "No arguments are allowed here" case $PMTYPE in apt-rpm) #assure_exists apt-repo if tasknumber "$1" >/dev/null ; then get_task_packages "$@" else print_apt_sources_list #docmd apt-repo list fi ;; deepsolver-rpm) docmd ds-conf ;; apt-dpkg|aptitude-dpkg) print_apt_sources_list ;; yum-rpm) docmd yum repolist -v ;; dnf-rpm) docmd dnf repolist -v ;; urpm-rpm) docmd urpmq --list-url ;; zypper-rpm) docmd zypper sl -d ;; packagekit) docmd pkcon repo-list ;; emerge) docmd eselect profile list docmd layman -L ;; xbps) docmd xbps-query -L ;; winget) docmd winget source list ;; pacman) docmd grep -v -- "^#\|^$" /etc/pacman.conf ;; slackpkg) docmd grep -v -- "^#\|^$" /etc/slackpkg/mirrors ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-reposave: SAVELISTDIR=/tmp/eepm-etc-save __save_alt_repo_lists() { assure_root info "Creating copy of all sources lists to $SAVELISTDIR ..." local i rm -rf $verbose $SAVELISTDIR 2>/dev/null mkdir -p $SAVELISTDIR/apt/ $SAVELISTDIR/apt/sources.list.d/ for i in /etc/apt/sources.list /etc/apt/sources.list.d/*.list ; do [ -s "$i" ] || continue local DD="$(echo "$i" | sed -e "s|/etc|$SAVELISTDIR|")" cp -af $verbose "$i" "$DD" || fatal "Can't save apt source list files to $SAVELISTDIR" done } __restore_alt_repo_lists() { assure_root info "Restoring copy of all sources lists from $SAVELISTDIR ..." local i [ -d "$SAVELISTDIR/apt" ] || return 0 mkdir -p $SAVELISTDIR/apt/ $SAVELISTDIR/apt/sources.list.d/ for i in /etc/apt/sources.list /etc/apt/sources.list.d/*.list ; do [ -s "$i" ] || continue local DD="$(echo "$i" | sed -e "s|/etc|$SAVELISTDIR|")" # restore only if there are differences if diff -q "$DD" "$i" >/dev/null ; then rm -f $verbose "$DD" else mv $verbose "$DD" "$i" || warning "Can't restore $i file" fi done } __on_error_restore_alt_repo_lists() { warning "An error occurred..." epm repo restore } try_change_alt_repo() { epm repo save trap __on_error_restore_alt_repo_lists EXIT } end_change_alt_repo() { trap - EXIT } epm_reposave() { case $PMTYPE in apt-*) if ! is_root ; then sudoepm repo save return fi __save_alt_repo_lists ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } epm_reporestore() { case $PMTYPE in apt-*) if ! is_root ; then sudoepm repo restore return fi __restore_alt_repo_lists ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } epm_reporeset() { case $PMTYPE in winget) sudocmd winget source reset ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac } # File bin/epm-requires: epm_requires_files() { local pkg_files="$*" [ -n "$pkg_files" ] || return local PKGTYPE="$(get_package_type $pkg_files)" case "$PKGTYPE" in rpm) assure_exists rpm docmd rpm -q --requires -p $pkg_files ;; deb) assure_exists dpkg a='' docmd dpkg -I $pkg_files | grep "^ *Depends:" | sed "s|^ *Depends:||g" ;; *) fatal "Have no suitable command for $PKGTYPE" ;; esac } epm_requires_names() { local pkg_names="$*" local CMD [ -n "$pkg_names" ] || return case $PMTYPE in apt-rpm) # FIXME: need fix for a few names case # FIXME: too low level of requires name (libSOME.so) if is_installed $pkg_names ; then CMD="rpm -q --requires" else #EXTRA_SHOWDOCMD=' | grep "Depends:"' #docmd apt-cache show $pkg_names | grep "Depends:" #return CMD="apt-cache depends" fi ;; packagekit) CMD="pkcon required-by" ;; #zypper-rpm) # # FIXME: use hi level commands # CMD="rpm -q --requires" # ;; urpm-rpm) CMD="urpmq --requires" ;; yum-rpm) if is_installed $pkg_names ; then CMD="rpm -q --requires" else CMD="yum deplist" fi ;; dnf-rpm) if is_installed $pkg_names ; then CMD="rpm -q --requires" else CMD="dnf repoquery --requires" fi ;; pacman) CMD="pactree" ;; apt-dpkg|aptitude-dpkg) # FIXME: need fix for a few names case if is_installed $pkg_names ; then showcmd dpkg -s $pkg_names a='' dpkg -s $pkg_names | grep "^Depends:" | sed "s|^Depends:||g" return else CMD="apt-cache depends" fi ;; emerge) assure_exists equery CMD="equery depgraph" ;; homebrew) #docmd brew info $pkg_names | grep "^Required: " | sed -s "|s|^Requires: ||" docmd brew deps $pkg_names return ;; pkgng) #CMD="pkg rquery '%dn-%dv'" CMD="pkg info -d" ;; opkg) CMD="opkg depends" ;; xbps) CMD="xbps-query -x" ;; aptcyg) #CMD="apt-cyg depends" # print show version docmd apt-cyg show $pkg_names | grep "^requires: " | sed "s|^requires: ||g" return ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac docmd $CMD $pkg_names } epm_requires() { [ -n "$pkg_filenames" ] || fatal "Requires: package name is missed" epm_requires_files $pkg_files # shellcheck disable=SC2046 epm_requires_names $(print_name $pkg_names) } # File bin/epm-restore: __epm_restore_print_comment() { echo "#$2 generated by 'epm restore --dry-run' from $(basename $(dirname $(realpath "$1")))/$(basename "$1")$3" } __epm_filter_pip_to_rpm() { tr "A-Z" "a-z" | sed -e "s|_|-|g" -e "s|^python[-_]||" -e "s|python$||" \ -e "s|bs4|beautifulsoup4|" \ -e "s|pillow|Pillow|" \ -e "s|sqlalchemy|SQLAlchemy|" \ -e "s|flask-SQLAlchemy|flask_sqlalchemy|" \ -e "s|redis|redis-py|" \ -e "s|pyjwt|jwt|" \ -e "s|pymonetdb|monetdb|" \ -e "s|pyyaml|yaml|" \ -e "s|flask-migrate|Flask-Migrate|" \ -e "s|twisted|twisted-core|" \ -e "s|pymacaroons|pymacaroons-pynacl|" \ -e "s|pygments|Pygments|" \ -e "s|memcached|memcache|" \ -e "s|pyinstaller||" \ -e "s|pyopenssl|OpenSSL|" } fill_sign() { local sign="$1" echo "$2" | grep -E -- "$sign[[:space:]]*[0-9.]+?" | sed -E -e "s|.*$sign[[:space:]]*([0-9.]+?).*|\1|" } __epm_pi_sign_to_rpm() { local t="$1" local l="$2" local equal="$3" [ -n "$equal" ] || equal=">=" local pi='' local sign ll for sign in "<=" "<" ">=" ">" "==" "!=" "~="; do ll=$(fill_sign "$sign" "$l") [ -n "$ll" ] || continue [ "$sign" = "==" ] && sign="$equal" [ "$sign" = "~=" ] && sign="$equal" [ "$sign" = "!=" ] && sign=">=" [ -n "$pi" ] && pi="$pi " pi="$pi$t $sign $ll" done [ -n "$pi" ] || pi="$t" echo "$pi" } __epm_get_array_name() { echo "$*" | grep "=" | head -n1 | sed -e 's| *=.*||' } __epm_lineprint_python_array() { local a="$*" [ -n "$a" ] || return local name="$(__epm_get_array_name "$a")" (echo "$a" | sed -E -e 's@(\]|\)).*@\1@' ; echo "print('\n'.join($name))" ) | ( a= python3 - || a= python - ) } __epm_restore_convert_to_rpm_notation() { local equal="$1" local l while read l ; do if echo "$l" | grep -q 'platform_python_implementation != "PyPy"' ; then [ -n "$verbose" ] && warning " $t is not PyPi requirement, skipped" continue fi if echo "$l" | grep -q 'sys_platform == "darwin"' ; then [ -n "$verbose" ] && warning " $t is darwin only requirement, skipped" continue fi if echo "$l" | grep -q 'sys_platform == "win32"' ; then [ -n "$verbose" ] && warning " $t is win32 only requirement, skipped" continue fi if echo "$l" | grep -q "; *python_version *< *['\"]3" ; then [ -n "$verbose" ] && warning " $t is python2 only requirement, skipped" continue fi if echo "$l" | grep -q "; *python_version *<= *['\"]2\." ; then [ -n "$verbose" ] && warning " $t is python2 only requirement, skipped" continue fi # drop various "python_version > '3.5'" l="$(echo "$l" | sed -e "s| *;.*||")" if echo "$l" | grep -qE "^ *#" || [ -z "$l" ] ; then continue fi local t="$(echo "$l" | sed -E -e "s|[[:space:]]*[<>!=~]+.*||" -e "s| *#.*||" | __epm_filter_pip_to_rpm)" [ -n "$t" ] || continue # until new section if echo "$l" | grep -qE "^\[" ; then break fi # if dependency_links URLs, use egg name if echo "$l" | grep -qE "://" ; then if echo "$l" | grep -q "#egg=" ; then t="$(echo "$l" | sed -e "s|.*#egg=||" -e "s|\[.*||" | __epm_filter_pip_to_rpm)" else warning " skipping URL $l ..." continue fi fi __epm_pi_sign_to_rpm "$t" "$l" "$equal" done } __epm_restore_pip() { local req_file="$1" local reqmacro local ilist if [ -n "$dryrun" ] ; then reqmacro="%py3_use" basename "$req_file" | egrep -q "(dev|test|coverage)" && reqmacro="%py3_buildrequires" echo __epm_restore_print_comment "$req_file" cat $req_file | __epm_restore_convert_to_rpm_notation | sed -e "s|^|$reqmacro |" return else info "Install requirements from $req_file ..." ilist="$(cat $req_file | __epm_restore_convert_to_rpm_notation | cut -d' ' -f 1 | sed -e "s|^|python3-module-|")" fi ilist="$(estrlist list $ilist)" docmd epm install $ilist } __eresection() { rhas "$1" "[[:space:]]*$2[[:space:]]*=[[:space:]]*[\[(]" } __epm_restore_setup_py() { local req_file="$1" if [ -z "$dryrun" ] ; then info "Install requirements from $req_file ..." fi local ar='' local ilist='' local reqmacro local section='' while read l ; do if rhas "$l" "^ *#" ; then continue fi # start of section if __eresection "$l" "REQUIREMENTS" ; then reqmacro="%py3_use" section="$l" fi if __eresection "$l" "install_requires" ; then reqmacro="%py3_use" section="$l" fi if __eresection "$l" "setup_requires" ; then reqmacro="%py3_buildrequires" section="$l" fi if __eresection "$l" "tests_require" ; then reqmacro="%py3_buildrequires" section="$l" fi if [ -n "$section" ] ; then ar="$ar $l" fi # not end of section if [ -z "$section" ] || ! rhas "$l" "(\]|\)),*" ; then continue fi if [ -n "$dryrun" ] ; then echo __epm_restore_print_comment "$req_file" "" " $(__epm_get_array_name "$section")" __epm_lineprint_python_array "$ar" | __epm_restore_convert_to_rpm_notation ">=" | sed -e "s|^|$reqmacro |" else ilist="$ilist $(__epm_lineprint_python_array "$ar" | __epm_restore_convert_to_rpm_notation ">=" | cut -d' ' -f 1 | sed -e "s|^|python3-module-|")" fi section='' ar='' done < $req_file if [ -n "$dryrun" ] ; then return fi ilist="$(estrlist list $ilist)" docmd epm install $ilist } __epm_print_npm_list() { local reqmacro="$1" local req_file="$2" local l while read l ; do # "tap": "^14.10.7" echo "$l" | grep -q '"\(.*\)": "\(.*\)"' || continue local name="$(echo "$l" | sed -e 's|.*"\(.*\)": ".*|\1|')" [ -z "$name" ] && continue local ver="$(echo "$l" | sed -e 's|.*"\(.*\)": "\(.*\)".*|\2|')" #' [ -z "$name" ] && continue if [ -n "$dryrun" ] ; then local pi='' local sign if echo "$ver" | grep -q "^\^" ; then sign=">=" else sign="=" fi ll=$(echo "$ver" | sed -e 's|^[^~]||') pi="$pi$reqmacro node-$name $sign $ll" echo "$pi" continue else local pi="node-$name" #echo " $l -> $name -> $pi" fi [ -n "$name" ] || continue ilist="$ilist $pi" done < $req_file [ -n "$dryrun" ] || echo "$ilist" } __epm_print_perl_list() { local reqmacro="$1" local req_file="$2" local l for l in $(cat) ; do # perl(Class::ErrorHandler)>=0 echo "$l" | grep -q '^perl(' || continue local name="$(echo "$l" | sed -e 's|>=.*||' -e 's|::|/|g' -e 's|)|.pm)|')" [ "$name" = "perl(perl.pm)" ] && continue [ -z "$name" ] && continue local ver="$(echo "$l" | sed -e 's|.*>=||')" [ -z "$name" ] && continue if [ -n "$dryrun" ] ; then local pi='' local sign='' [ "$ver" = "0" ] || sign=" >= $ver" pi="$pi$reqmacro $name$sign" echo "$pi" continue else local pi="$name" #echo " $l -> $name -> $pi" fi [ -n "$name" ] || continue ilist="$ilist $pi" done < $req_file [ -n "$dryrun" ] || echo "$ilist" } __epm_print_perl_list_shyaml() { local reqmacro="$1" local req_file="$2" local l while read l ; do # Convert::ASN1: 0.10 echo "$l" | grep -q '^ *\(.*\): \(.*\)' || continue local name="$(echo "$l" | sed -e 's| *\(.*\): \(.*\)|\1|' -e 's|::|/|g')".pm [ "$name" = "perl.pm" ] && continue [ -z "$name" ] && continue local ver="$(echo "$l" | sed -e 's| *\(.*\): \(.*\)|\2|')" [ -z "$name" ] && continue if [ -n "$dryrun" ] ; then local pi='' local sign='' [ "$ver" = "0" ] || sign=" >= $ver" pi="$pi$reqmacro perl($name)$sign" echo "$pi" continue else local pi="perl($name)" #echo " $l -> $name -> $pi" fi [ -n "$name" ] || continue ilist="$ilist $pi" done < $req_file [ -n "$dryrun" ] || echo "$ilist" } __epm_print_nupkg_list() { a= dotnet list $1 package | grep "^ > " | while read n name req other; do if [ -n "$dryrun" ] ; then echo "BuildRequires: nupkg($name) >= $req" else echo "nupkg($name)" fi done } __epm_restore_nupkg() { local req_file="$1" if [ -n "$dryrun" ] ; then echo "# generated via dotnet list $(basename $(dirname $(realpath "$req_file")))/$(basename "$req_file") package" __epm_print_nupkg_list $req_file return fi info "Install requirements from $req_file ..." ilist=$(__epm_print_nupkg_list $req_file) ilist="$(estrlist list $ilist)" docmd epm install $ilist } __epm_restore_npm() { local req_file="$1" assure_exists jq || fatal if [ -n "$dryrun" ] ; then local lt=$(mktemp) a= jq .dependencies <$req_file >$lt echo __epm_restore_print_comment "$req_file" __epm_print_npm_list "Requires:" $lt echo __epm_restore_print_comment "$req_file" " devDependencies" a= jq .devDependencies <$req_file >$lt __epm_print_npm_list "BuildRequires:" $lt rm -f $lt return fi info "Install requirements from $req_file ..." local lt=$(mktemp) a= jq .dependencies <$req_file >$lt ilist="$(__epm_print_npm_list "" $lt)" a= jq .devDependencies <$req_file >$lt ilist="$ilist $(__epm_print_npm_list "" $lt)" rm -f $lt docmd epm install $ilist } __epm_restore_perl() { local req_file="$1" if [ -n "$dryrun" ] ; then local lt=$(mktemp) a= /usr/bin/perl $req_file PRINT_PREREQ=1 >$lt # all requirements will autodetected during packing, put it to the buildreq echo __epm_restore_print_comment "$req_file" __epm_print_perl_list "BuildRequires:" $lt rm -f $lt return fi info "Install requirements from $req_file ..." local lt=$(mktemp) a= /usr/bin/perl $req_file PRINT_PREREQ=1 >$lt ilist="$(__epm_print_perl_list "" $lt)" rm -f $lt docmd epm install $ilist } __epm_restore_perl_shyaml() { local req_file="$1" assure_exists shyaml || fatal if [ -n "$dryrun" ] ; then local lt=$(mktemp) a= shyaml get-value requires <$req_file >$lt # all requirements will autodetected during packing, put it to the buildreq echo __epm_restore_print_comment "$req_file" __epm_print_perl_list "BuildRequires:" $lt echo __epm_restore_print_comment "$req_file" " build_requires" a= shyaml get-value build_requires <$req_file >$lt __epm_print_perl_list "BuildRequires:" $lt rm -f $lt return fi info "Install requirements from $req_file ..." local lt=$(mktemp) a= shyaml get-value requires <$req_file >$lt ilist="$(__epm_print_perl_list "" $lt)" a= shyaml get-value build_requires <$req_file >$lt ilist="$ilist $(__epm_print_perl_list "" $lt)" rm -f $lt docmd epm install $ilist } __epm_restore_by() { local req_file="$1" [ -s "$req_file" ] || return if file $req_file | grep -q "ELF [3264]*-bit LSB executable" ; then assure_exists ldd-requires showcmd ldd-requires $req_file local TOINSTALL="$(a= ldd-requires $req_file | grep "^apt-get install" | sed -e "s|^apt-get install ||")" if [ -n "$dryrun" ] ; then estrlist list $TOINSTALL return fi [ -n "$TOINSTALL" ] || { info "There are no missed packages is found for $req_file binary." ; return ; } docmd epm install $TOINSTALL return fi case $req_file in requirements/default.txt|requirements/dev.txt|requirements/test.txt|requirements/coverage.txt) [ -s "$req_file" ] && __epm_restore_pip "$req_file" && return ;; esac case $(basename $req_file) in requirements.txt|dev-requirements.txt|requirements-dev.txt|requirements_dev.txt|requirements_test.txt|requirements-test.txt|test-requirements.txt|requires.txt) [ -s "$req_file" ] && __epm_restore_pip "$req_file" ;; setup.py|python_dependencies.py) [ -s "$req_file" ] && __epm_restore_setup_py "$req_file" ;; package.json) [ -s "$req_file" ] && __epm_restore_npm "$req_file" ;; Makefile.PL) [ -s "$req_file" ] && __epm_restore_perl "$req_file" ;; *.sln|*.csproj) local PROJ="$(echo $req_file)" [ -s "$PROJ" ] && __epm_restore_nupkg "$PROJ" ;; Gemfile|package.json) info "$req_file support is not implemented yet" ;; esac } epm_restore() { req_file="$pkg_filenames" if [ -n "$pkg_urls" ] && echo "$pkg_urls" | grep -qE "^https?://" ; then req_file="$(basename "$pkg_urls")" #assure eget [ -r "$req_file" ] && fatal "File $req_file is already exists in $(pwd)" info "Downloading '$req_file' from '$pkg_urls' ..." eget "$pkg_urls" [ -s "$req_file" ] || fatal "Can't download $req_file from '$pkg_urls'" fi if [ -n "$req_file" ] ; then __epm_restore_by $req_file return fi # if run with empty args for i in requirements.txt requirements/default.txt requirements_dev.txt requirements-dev.txt requirements/dev.txt dev-requirements.txt \ requirements-test.txt requirements_test.txt requirements/test.txt test-requirements.txt requirements/coverage.txt \ Gemfile requires.txt package.json setup.py python_dependencies.py Makefile.PL \ *.sln *.csproj ; do __epm_restore_by $i done } # File bin/epm-search: __epm_search_output() { local CMD local string="$1" case $PMTYPE in apt-rpm|apt-dpkg) CMD="apt-cache search --" ;; aptitude-dpkg) CMD="aptitude search --" ;; deepsolver-rpm) CMD="ds-require --" ;; packagekit) CMD="pkcon search name" ;; urpm-rpm) # urpmq does not support -- CMD="urpmq -y" ;; pkgsrc) CMD="pkg_info -x --" ;; pkgng) CMD="pkg search -i --" ;; emerge) CMD="emerge --search --" ;; pacman) CMD="pacman -Ss --" ;; aura) CMD="aura -As --" ;; yum-rpm) CMD="yum search --" ;; dnf-rpm) CMD="dnf search --" ;; zypper-rpm) CMD="zypper search -d --" ;; mpkg) CMD="mpkg search" ;; apk) CMD="apk search" ;; tce) CMD="tce-ab" ;; conary) CMD="conary repquery" ;; npackd) docmd npackdcl search --query="$string" --status=all return ;; chocolatey) CMD="chocolatey list" ;; slackpkg) # FIXME echo "Note: case sensitive search" if [ -n "$verbose" ] ; then CMD="/usr/sbin/slackpkg search" else LANG=C docmd /usr/sbin/slackpkg search $string | grep " - " | sed -e 's|.* - ||g' return fi ;; opkg) CMD="opkg find" ;; homebrew) CMD="brew search" ;; guix) CMD="guix package -A" ;; android) CMD="pm list packages" ;; aptcyg) CMD="apt-cyg searchall" ;; xbps) CMD="xbps-query -s" ;; appget|winget) CMD="$PMTYPE search" ;; *) fatal "Have no suitable search command for $PMTYPE" ;; esac LANG=C docmd $CMD $string epm play $short --list-all | sed -e 's|^ *||g' -e 's|[[:space:]]\+| |g' -e "s|\$| (use \'epm play\' to install it)|" } __epm_search_make_grep() { local i [ -z "$*" ] && return local list= local listN= for i in $@ ; do case "$i" in ~*) # will clean from ~ later (and have the bug here with empty arg if run with one ~ only) listN="$listN $i" ;; *) list="$list $i" ;; esac done #list=$(strip_spaces $list | sed -e "s/ /|/g") listN=$(strip_spaces $listN | sed -e "s/ /|/g" | sed -e "s/~//g") if [ -n "$short" ] ; then echon " | sed -e \"s| .*||g\"" fi [ -n "$listN" ] && echon " | egrep -i -v -- \"$listN\"" # FIXME: The World has not idea how to do grep both string # http://stackoverflow.com/questions/10110051/grep-with-two-strings-logical-and-in-regex?rq=1 # Need only if we have more than one word (with one word we will grep for colorify) if [ "$(echo "$list" | wc -w)" -gt 1 ] ; then for i in $list ; do # FIXME -n on MacOS? echon " | egrep -i -- \"$i\"" done fi # FIXME: move from it #isatty || return # TODO: sorts word by length from large to short local COLO="" # rule for colorife for i in $list $listN; do [ -n "$COLO" ] && COLO="$COLO|" COLO="$COLO$i" done # TODO: use some colorifer instead grep (check grep adove too) if [ -n "$list" ] ; then echon " | egrep -i $EGREPCOLOR -- \"($COLO)\"" fi } __epm_search_internal() { [ -n "$pkg_filenames" ] || fatal "Search: search argument(s) is missed" # it is useful for first time running update_repo_if_needed soft warmup_bases __epm_search_output $(get_firstarg $pkg_filenames) | grep "$pkg_filenames" } epm_search() { [ -n "$pkg_filenames" ] || fatal "Search: search argument(s) is missed" # it is useful for first time running update_repo_if_needed soft warmup_bases # FIXME: do it better local MGS MGS=$(eval __epm_search_make_grep $quoted_args) EXTRA_SHOWDOCMD="$MGS" eval "__epm_search_output \"$(eval get_firstarg $quoted_args)\" $MGS" } # File bin/epm-search_file: __alt_search_file_output() { # grep only on left part (filename), then revert order and grep with color __local_ercat $1 | grep -h -- ".*$2.*[[:space:]]" | sed -e "s|\(.*\)\t\(.*\)|\2: \1|g" $3 } __alt_local_content_search() { update_alt_contents_index local CI="$(cat $ALT_CONTENTS_INDEX_LIST)" info "Searching for $1 ... " # FIXME: do it better local MGS MGS=$(eval __epm_search_make_grep $quoted_args) showcmd "$ cat contents_index $MGS" eval "__alt_search_file_output \"$CI\" \"$(eval get_firstarg $quoted_args)\" $MGS" } epm_search_file() { local CMD [ -n "$pkg_filenames" ] || fatal "Search file: file name is missed" case $PMTYPE in apt-rpm) __alt_local_content_search $pkg_filenames return ;; apt-dpkg|aptitude-dpkg) assure_exists apt-file sudocmd apt-file update docmd apt-file search $pkg_filenames return ;; packagekit) CMD="pkcon search file" ;; yum-rpm) # TODO info "Search by full packages list is not implemented yet" CMD="yum provides" ;; dnf-rpm) # TODO info "Search by full packages list is not implemented yet" CMD="dnf provides" ;; urpm-rpm) CMD="urpmf" ;; zypper-rpm) CMD="zypper search --file-list" ;; pacman) CMD="pacman -Qo" ;; slackpkg) CMD="/usr/sbin/slackpkg file-search" ;; opkg) CMD="opkg -A search" ;; xbps) CMD="xbps-query -Ro" ;; aptcyg) docmd apt-cyg searchall "$(echo " $pkg_filenames" | sed -e "s| /| |g")" return ;; *) fatal "Have no suitable search file command for $PMTYPE" ;; esac docmd $CMD $pkg_filenames } # File bin/epm-sh-altlinux: tasknumber() { local num="$(echo "$1" | sed -e "s| *#*||g")" isnumber "$num" && echo "$*" } get_task_arepo_packages() { local res assure_exists apt-repo assure_exists curl info "TODO: please, improve apt-repo to support arepo (i586-) packages for apt-repo list task" showcmd "curl -s -f http://git.altlinux.org/tasks/$tn/plan/arepo-add-x86_64-i586 | cut -f1" # TODO: retrieve one time res="$(a='' curl -s -f http://git.altlinux.org/tasks/$tn/plan/arepo-add-x86_64-i586 2>/dev/null)" || { warning "There is a download error for x86_64-i586 arepo." ; return ; } echo "$res" | cut -f1 } get_task_packages() { local arch="$($DISTRVENDOR -a)" local tn for tn in $(tasknumber "$@") ; do showcmd apt-repo list task "$tn" a='' apt-repo list task "$tn" >/dev/null || continue a='' apt-repo list task "$tn" [ "$arch" = "x86_64" ] && get_task_arepo_packages "$tn" done } # File bin/epm-sh-altlinux-contents-index: get_alt_repo_path() { local DN1=$(dirname "$1") local DN2=$(dirname $DN1) local DN3=$(dirname $DN2) local BN0=$(basename "$1") # arch local BN1=$(basename $DN1) # branch/Sisyphus local BN2=$(basename $DN2) # p8/ALTLinux local BN3=$(basename $DN3) # ALTLinux/ [ "$BN1" = "branch" ] && echo "$BN3/$BN2/$BN1/$BN0" || echo "$BN2/$BN1/$BN0" } get_local_alt_mirror_path() { # TODO: /var/cache/eepm echo "$TMPDIR/eepm/$(get_alt_repo_path "$1")" } ALT_CONTENTS_INDEX_LIST=$TMPDIR/eepm/contents_index_list __local_ercat() { local i for i in "$@" ; do case "$i" in *.xz) a='' xzcat $i ;; *.lz4) a='' lz4cat $i ;; *.gz) a='' zcat $i ;; *.failed) # just ignore ;; *) cat $i ;; esac done } rsync_alt_contents_index() { local URL="$1" local TD="$2" assure_exists rsync mkdir -p "$(dirname "$TD")" if [ -n "$verbose" ] ; then docmd rsync --partial --inplace $3 -a --progress "$URL" "$TD" else a= rsync --partial --inplace $3 -a --progress "$URL" "$TD" >/dev/null 2>/dev/null fi } get_url_to_etersoft_mirror() { local REPOPATH local ETERSOFT_MIRROR="rsync://download.etersoft.ru/pub" local ALTREPO=$(get_alt_repo_path "$1") echo "$ALTREPO" | grep -q "^ALTLinux" || return echo "$ETERSOFT_MIRROR/$(get_alt_repo_path "$1" | sed -e "s|^ALTLinux/|ALTLinux/contents_index/|")" } __init_contents_index_list() { mkdir -p "$(dirname $ALT_CONTENTS_INDEX_LIST)" truncate -s0 $ALT_CONTENTS_INDEX_LIST } __add_to_contents_index_list() { [ -n "$quiet" ] || echo " $1 -> $2" echo "$2" >>$ALT_CONTENTS_INDEX_LIST } __add_better_to_contents_index_list() { if [ -s "$2" ] && [ -s "$3" ] ; then [ "$2" -ot "$3" ] && __add_to_contents_index_list "$1" "$3" && return __add_to_contents_index_list "$1" "$2" && return fi [ -s "$2" ] && __add_to_contents_index_list "$1" "$2" && return [ -s "$3" ] && __add_to_contents_index_list "$1" "$3" && return } update_alt_contents_index() { __init_contents_index_list # TODO: fix for Etersoft/LINUX@Etersoft # TODO: fix for rsync info "Retrieving contents_index ..." (quiet=1 epm_repolist) | grep -v " task$" | grep -E "rpm.*(ftp://|http://|https://|rsync://|file:/)" | sed -e "s@^rpm.*\(ftp://\|http://\|https://\)@rsync://@g" | sed -e "s@^rpm.*\(file:\)@@g" | while read -r URL1 URL2 component ; do [ "$component" = "debuginfo" ] && continue URL="$URL1/$URL2" if echo "$URL" | grep -q "^/" ; then # first check for local mirror local LOCALPATH="$(echo "$URL/base")" local LOCALPATHGZIP="$(echo "$LOCALPATH" | sed -e "s|/ALTLinux/|/ALTLinux/contents_index/|")" __add_better_to_contents_index_list "$URL" "$LOCALPATHGZIP/contents_index.gz" "$LOCALPATH/contents_index" else local LOCALPATH="$(get_local_alt_mirror_path "$URL")" local REMOTEURL="$(get_url_to_etersoft_mirror "$URL")" if [ -n "$REMOTEURL" ] ; then rsync_alt_contents_index $REMOTEURL/base/contents_index.gz $LOCALPATH/contents_index.gz && __add_to_contents_index_list "$REMOTEURL" "$LOCALPATH/contents_index.gz" && continue [ -n "$verbose" ] && info "Note: Can't retrieve $REMOTEURL/base/contents_index.gz, fallback to $URL/base/contents_index" fi # fix rsync URL firstly local RSYNCURL="$(echo "$URL" | sed -e "s|rsync://\(ftp.basealt.ru\|basealt.org\|altlinux.ru\)/pub/distributions/ALTLinux|rsync://\1/ALTLinux|")" #" rsync_alt_contents_index $RSYNCURL/base/contents_index $LOCALPATH/contents_index -z && __add_to_contents_index_list "$RSYNCURL" "$LOCALPATH/contents_index" && continue __add_better_to_contents_index_list "(cached)" "$LOCALPATH/contents_index.gz" "$LOCALPATH/contents_index" fi done if [ ! -s "$ALT_CONTENTS_INDEX_LIST" ] ; then fatal "Have no local contents index. Check epm repo --help." fi } # File bin/epm-sh-install: __fast_hack_for_filter_out_installed_rpm() { LANG=C LC_ALL=C xargs -n1 rpm -q 2>&1 | grep 'is not installed' | sed -e 's|^.*package \(.*\) is not installed.*|\1|g' } filter_out_installed_packages() { [ -z "$skip_installed" ] && cat && return case $PMTYPE in yum-rpm|dnf-rpm) if [ "$($DISTRVENDOR -a)" = "x86_64" ] ; then # shellcheck disable=SC2013 for i in $(cat) ; do is_installed "$(__print_with_arch_suffix $i .x86_64)" && continue is_installed "$(__print_with_arch_suffix $i .noarch)" && continue echo $i done else __fast_hack_for_filter_out_installed_rpm fi ;; *-rpm) __fast_hack_for_filter_out_installed_rpm ;; # dpkg -l lists some non ii status (un, etc) #"deb") # LANG=C LC_ALL=C xargs -n1 dpkg -l 2>&1 | grep -i 'no packages found matching' | # sed -e 's|\.\+$||g' -e 's|^.*[Nn]o packages found matching \(.*\)|\1|g' # ;; *) # shellcheck disable=SC2013 for i in $(cat) ; do is_installed $i || echo $i done ;; esac | sed -e "s|rpm-build-altlinux-compat[^ ]*||g" | filter_strip_spaces } get_only_installed_packages() { local installlist="$*" estrlist exclude "$(echo "$installlist" | (skip_installed='yes' filter_out_installed_packages))" "$installlist" } __epm_check_vendor() { # don't check vendor if there are forced script options [ -n "$scripts$noscripts" ] && return # only ALT [ "$DISTRNAME" = "ALTLinux" ] || return local i for i in $* ; do local vendor rpmversion # skip checking if the package is unaccessible rpmversion="$(epm print field Version for "$i" 2>/dev/null)" [ -n "$rpmversion" ] || continue vendor="$(epm print field Vendor for "$i" 2>/dev/null)" # TODO: check GPG [ "$vendor" = "ALT Linux Team" ] && continue warning "Scripts are disabled for package $i from outside vendor '$vendor'. Use --scripts if you need run scripts from such packages." noscripts="--noscripts" done } # File bin/epm-sh-warmup: is_warmup_allowed() { local MEM # disable warming up until set EPM_WARNUP in /etc/eepm/eepm.conf [ -n "$EPM_WARMUP" ] || return 1 MEM="$($DISTRVENDOR -m)" # disable warm if have no enough memory [ "$MEM" -le 1024 ] && return 1 return 0 } __warmup_files() { local D="$1" shift #showcmd "$*" [ -n "$D" ] && info "Warming up $D ..." # TODO: use progress, calc files size before docmd cat $* >/dev/null 2>/dev/null } warmup_rpmbase() { is_warmup_allowed || return __warmup_files "rpm" "/var/lib/rpm/*" } warmup_dpkgbase() { is_warmup_allowed || { warning "Skipping warmup bases due low memory size" ; return ; } __warmup_files "dpkg" "/var/lib/dpkg/*" } warmup_lowbase() { case $PKGFORMAT in "rpm") warmup_rpmbase "$@" ;; "dpkg") warmup_dpkgbase "$@" ;; *) ;; esac } warmup_aptbase() { is_warmup_allowed || return __warmup_files "apt" "/var/lib/apt/lists/* /var/cache/apt/*.bin" } warmup_hibase() { case $PMTYPE in "apt-rpm"|"apt-dpkg") warmup_aptbase "$@" ;; *) ;; esac } warmup_bases() { DISquiet=1 warmup_lowbase DISquiet=1 warmup_hibase } # File bin/epm-simulate: __use_zypper_dry_run() { a='' zypper install --help 2>&1 | grep -q -- "--dry-run" && echo "--dry-run" } __use_yum_assumeno() { a='' yum --help 2>&1 | grep -q -- "--assumeno" } __check_yum_result() { grep -q "^No package" $1 && return 1 grep -q "^Complete!" $1 && return 0 grep -q "Exiting on user [Cc]ommand" $1 && return 0 # dnf issue grep -q "^Operation aborted." $1 && return 0 # return default result by default return $2 } __check_pacman_result() { grep -q "^error: target not found:" $1 && return 1 grep -q "^Total Installed Size:" $1 && return 0 grep -q "^Total Download Size:" $1 && return 0 # return default result by default return $2 } _epm_do_simulate() { local CMD local RES=0 local filenames="$*" case $PMTYPE in apt-rpm|apt-dpkg) CMD="apt-get --simulate install" ;; aptitude-dpkg) CMD="aptitude -s install" ;; yum-rpm) if __use_yum_assumeno ; then store_output sudocmd yum --assumeno install $filenames __check_yum_result $RC_STDOUT $? else store_output sudocmd yum install $filenames <<EOF n EOF __check_yum_result $RC_STDOUT $? fi RES=$? clean_store_output return $RES ;; dnf-rpm) store_output sudocmd dnf --assumeno install $filenames __check_yum_result $RC_STDOUT $? RES=$? clean_store_output return $RES ;; urpm-rpm) CMD="urpmi --test --auto" ;; zypper-rpm) if ! __use_zypper_dry_run >/dev/null ; then fatal "zypper is too old: does not support --dry-run" fi CMD="zypper --non-interactive install --dry-run" ;; emerge) local res=0 for pkg in $filenames ; do is_installed $pkg && continue docmd emerge --pretend $pkg && continue pkg=1 break done return $res ;; opkg) docmd --noaction install $filenames return $res ;; pacman) store_output sudocmd pacman -v -S $filenames <<EOF no EOF __check_pacman_result $RC_STDOUT $? RES=$? clean_store_output return $RES ;; slackpkg) #docmd /usr/sbin/slackpkg -batch=on -default_answer=yes download # just try search every package # FIXME: epm_search have to return false status code if the package does not found local pkg res res=0 for pkg in $filenames ; do # FIXME: -[0-0] does not work in search! # FIXME: we need strict search here (not find gst-plugins-base if search for gst-plugins # TODO: use short? # use verbose for get package status #pkg_filenames="$pkg-[0-9]" verbose=--verbose __epm_search_internal | egrep "(installed|upgrade)" && continue #pkg_filenames="$pkg" verbose=--verbose __epm_search_internal | egrep "(installed|upgrade)" && continue (pkg_filenames="$pkg" __epm_search_internal) | grep -q "^$pkg-[0-9]" && continue res=1 info "Package '$pkg' does not found in repository." done return $res ;; *) fatal "Have no suitable simulate command for $PMTYPE" ;; esac sudocmd $CMD $filenames } epm_simulate() { [ -z "$pkg_filenames" ] && info "Simulate: Skip empty list" && return 22 local filenames="$(echo $pkg_filenames | filter_out_installed_packages)" [ -z "$filenames" ] && info "Simulate: All packages are already installed" && return 0 _epm_do_simulate $filenames local RES=$? if [ -z "$quiet" ] ; then if [ "$RES" = 0 ] ; then info "Simulate result: $filenames package(s) CAN BE installed" else info "Simulate result: There are PROBLEMS with install some package(s)" fi fi return $RES } # File bin/epm-site: PAOURL="https://packages.altlinux.org" paoapi() { # http://petstore.swagger.io/?url=http://packages.altlinux.org/api/docs assure_exists curl || return 1 showcmd curl "$PAOURL/api/$1" a='' curl -s --header "Accept: application/json" "$PAOURL/api/$1" } get_pao_var() { local FIELD="$1" #grep '"$FIELD"' | sed -e 's|.*"$FIELD":"||g' | sed -e 's|".*||g' internal_tools_json -b | grep -E "\[.*\"$FIELD\"\]" | sed -e 's|.*[[:space:]]"\(.*\)"|\1|g' return 0 } run_command_if_exists() { local CMD="$1" shift if which "$CMD" 2>/dev/null >/dev/null ; then docmd "$CMD" "$@" return 0 fi return 1 } open_browser() { local i for i in xdg-open firefox chromium links ; do run_command_if_exists $i "$@" && return done } __query_package_hl_url() { case $DISTRNAME in ALTLinux) paoapi srpms/$1 | get_pao_var url ;; esac return 1 } query_package_url() { local URL case $PMTYPE in *-rpm) # TODO: for binary packages? query_package_field URL "$1" || __query_package_hl_url "$1" #LANG=C epm info "$1" return ;; homebrew) docmd brew "$1" | grep "^From: " | sed -e "s|^From: ||" return ;; esac fatal "rpm based distro supported only. TODO: Realize via web service?" } get_locale() { local loc loc=$(a='' natspec --locale 2>/dev/null) [ -n "$loc" ] || loc=$LANG echo $loc } get_pao_url() { local loc loc=$(get_locale | cut -c1-2) case $loc in en|ru|uk|br) loc=$loc ;; *) loc=en esac echo "$PAOURL/$loc/Sisyphus/srpms" } query_altlinux_url() { local URL case $PMTYPE in *-rpm) local srpm=$(print_srcname "$1") [ -n "$srpm" ] || fatal "Can't get source name for $1" echo "$(get_pao_url)/$srpm" return ;; esac fatal "rpm based distro supported only. TODO: Realize via web service?" } epm_site() { [ -n "$pkg_filenames" ] || fatal "Info: package name is missed" local PAO="" for f in $pkg_names $pkg_files ; do [ "$f" = "-p" ] && PAO="$f" && continue if [ -n "$PAO" ] ; then pkg_url=$(query_altlinux_url $f) else pkg_url=$(query_package_url $f) fi [ -n "$pkg_url" ] && open_browser "$pkg_url" && continue warning "Can't get URL for $f package" done } # File bin/epm-update: epm_update() { [ -z "$*" ] || fatal "No arguments are allowed here" info "Running command for update remote package repository database" warmup_hibase case $PMTYPE in apt-rpm) sudocmd apt-get update || return #sudocmd apt-get -f install || exit ;; apt-dpkg) sudocmd apt-get update || return #sudocmd apt-get -f install || exit #sudocmd apt-get autoremove ;; packagekit) docmd pkcon refresh ;; #snappy) # sudocmd snappy # ;; aptitude-dpkg) sudocmd aptitude update || return ;; yum-rpm) # just skipped [ -n "$verbose" ] && info "update command is stubbed for yum" ;; dnf-rpm) # just skipped [ -n "$verbose" ] && info "update command is stubbed for dnf" ;; urpm-rpm) sudocmd urpmi.update -a ;; pacman) sudocmd pacman -S -y ;; aura) sudocmd aura -A -y ;; zypper-rpm) sudocmd zypper refresh ;; emerge) sudocmd emerge --sync ;; slackpkg) sudocmd /usr/sbin/slackpkg -batch=on update ;; deepsolver-rpm) sudocmd ds-update ;; npackd) sudocmd packdcl detect # get packages from MSI database ;; homebrew) docmd brew update ;; opkg) sudocmd opkg update ;; apk) sudocmd apk update ;; pkgsrc) # portsnap extract for the first time? sudocmd portsnap fetch update ;; aptcyg) sudocmd apt-cyg update ;; xbps) sudocmd xbps-install -S ;; winget) sudocmd winget source update ;; *) fatal "Have no suitable update command for $PMTYPE" ;; esac } # File bin/epm-upgrade: epm_upgrade() { local CMD # it is useful for first time running update_repo_if_needed warmup_bases if [ "$DISTRNAME" = "ALTLinux" ] ; then if tasknumber "$@" >/dev/null ; then try_change_alt_repo epm_addrepo "$@" local installlist="$(get_task_packages $*)" # hack: drop -devel packages to avoid package provided by multiple packages installlist="$(estrlist reg_exclude ".*-devel .*-devel-static" "$installlist")" [ -n "$verbose" ] && info "Packages from task(s): $installlist" # install only installed packages (simulate upgrade packages) installlist="$(get_only_installed_packages "$installlist")" [ -n "$verbose" ] && info "Packages to upgrade: $installlist" (pkg_names="$installlist" epm_Install) || fatal "Can't update repo" epm_removerepo "$@" end_change_alt_repo return fi fi info "Running command for upgrade packages" case $PMTYPE in *-rpm) # upgrade only install files from the list if [ -n "$pkg_files" ] ; then #sudocmd rpm -Fvh $pkg_files (pkg_files=$pkg_files force="$force -F" epm_install) return elif [ -n "$pkg_names" ] ; then # hack for https://bugzilla.altlinux.org/41225 case "$pkg_names" in -*) fatal "Option $pkg_names is not allowed here" esac (pkg_names=$(get_only_installed_packages $pkg_names) epm_install) return fi ;; esac case $PMTYPE in apt-rpm|apt-dpkg) local APTOPTIONS="$(subst_option non_interactive -y) $(subst_option verbose "-o Debug::pkgMarkInstall=1 -o Debug::pkgProblemResolver=1")" CMD="apt-get $APTOPTIONS $noremove $force_yes dist-upgrade" ;; aptitude-dpkg) CMD="aptitude dist-upgrade" ;; packagekit) docmd pkcon update return ;; yum-rpm) local OPTIONS="$(subst_option non_interactive -y)" # can do update repobase automagically CMD="yum $OPTIONS update $*" ;; dnf-rpm) local OPTIONS="$(subst_option non_interactive -y)" CMD="dnf $OPTIONS distro-sync $*" ;; snappy) CMD="snappy update" ;; urpm-rpm) # or --auto-select --replace-files CMD="urpmi --update --auto-select $*" ;; zypper-rpm) CMD="zypper dist-upgrade" ;; pacman) CMD="pacman -S -u $force" ;; aura) CMD="aura -A -u" ;; emerge) CMD="emerge -NuDa world" ;; conary) CMD="conary updateall" ;; pkgsrc) CMD="freebsd-update fetch install" ;; pkgng) CMD="pkg upgrade" ;; chocolatey) CMD="chocolatey update all" ;; homebrew) #CMD="brew upgrade" docmd "brew upgrade $(brew outdated)" return ;; opkg) CMD="opkg upgrade" ;; slackpkg) CMD="/usr/sbin/slackpkg upgrade-all" ;; guix) CMD="guix package -u" ;; appget|winget) CMD="$PMTYPE update-all" ;; aptcyg) # shellcheck disable=SC2046 docmd_foreach "epm install" $(short=1 epm packages) return ;; xbps) CMD="xbps-install -Su" ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac sudocmd $CMD "$@" } # File bin/epm-Upgrade: epm_Upgrade() { epm_update epm_upgrade "$@" } # File bin/epm-whatdepends: epm_whatdepends() { local CMD [ -n "$pkg_files" ] && fatal "whatdepends does not handle files" [ -n "$pkg_names" ] || fatal "whatdepends: package name is missed" local pkg=$(print_name $pkg_names) case $PMTYPE in apt-rpm) if [ -z "$verbose" ] ; then showcmd apt-cache whatdepends $pkg if [ -n "$short" ] ; then a= apt-cache whatdepends $pkg | grep "^ [^ ]" | sed -e "s|[0-9]*:||" | grep -E -v "(i586-|-debuginfo)" | sed -e 's|[@:].*||' -e "s|-[0-9].*||g" -e 's|^ *||' -e 's/\.32bit//g' else a= apt-cache whatdepends $pkg | grep "^ [^ ]" | sed -e "s|[0-9]*:||" | grep -E -v "(i586-|-debuginfo)" fi return fi CMD="apt-cache whatdepends" ;; apt-dpkg|aptitude-dpkg) CMD="apt-cache rdepends" ;; aptitude-dpkg) CMD="aptitude why" ;; packagekit) CMD="pkcon depends-on" ;; yum-rpm) CMD="repoquery --whatrequires" ;; urpm-rpm) CMD="urpmq --whatrequires" ;; dnf-rpm) # check command: dnf repoquery --whatrequires CMD="repoquery --whatrequires" ;; emerge) assure_exists equery CMD="equery depends -a" ;; homebrew) CMD="brew uses" ;; pkgng) CMD="pkg info -r" ;; aptcyg) CMD="apt-cyg rdepends" ;; opkg) CMD="opkg whatdepends" ;; xbps) CMD="xbps-query -X" ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac docmd $CMD $pkg } # File bin/epm-whatprovides: epm_whatprovides() { local CMD [ -n "$pkg_files" ] && fatal "whatprovides does not handle files" [ -n "$pkg_names" ] || fatal "whatprovides: package name is missed" local pkg=$(print_name $pkg_names) case $PMTYPE in conary) CMD="conary repquery --what-provides" ;; apt-rpm|apt-dpkg|aptitude-dpkg) LANG=C docmd apt-get install --print-uris $pkg | grep "^Selecting" | cut -f2 -d" " return ;; yum-rpm) CMD="yum whatprovides" ;; urpm-rpm) CMD="urpmq --whatprovides" ;; dnf-rpm) CMD="yum provides" ;; zypper-rpm) CMD="zypper what-provides" ;; opkg) CMD="opkg whatprovides" ;; *) fatal "Have no suitable command for $PMTYPE" ;; esac docmd $CMD $pkg } ################# incorporate bin/distr_info ################# internal_distr_info() { # 2007-2022 (c) Vitaly Lipatov <lav@etersoft.ru> # 2007-2022 (c) Etersoft # 2007-2022 Public domain # You can set ROOTDIR to root system dir #ROOTDIR= PROGVERSION="20220323" # TODO: check /etc/system-release # Check for DISTRO specific file in /etc distro() { #[ -n "$ROOTDIR" ] || return # fill global DISTROFILE DISTROFILE="$ROOTDIR/etc/$1" [ -f "$DISTROFILE" ] } # Has a distro file the specified word? has() { [ -n "$DISTROFILE" ] || exit 1 grep "$*" "$DISTROFILE" >/dev/null 2>&1 } # Has a system the specified command? hascommand() { which "$1" 2>/dev/null >/dev/null } firstupper() { echo "$*" | sed 's/.*/\u&/' } tolower() { # tr is broken in busybox (checked with OpenWrt) #echo "$*" | tr "[:upper:]" "[:lower:]" echo "$*" | awk '{print tolower($0)}' } override_distrib() { [ -n "$1" ] || return VENDOR_ID='' DISTRIB_ID="$(echo "$1" | sed -e 's|/.*||')" DISTRIB_RELEASE="$(echo "$1" | sed -e 's|.*/||')" } # Translate DISTRIB_ID to vendor name (like %_vendor does), uses VENDOR_ID by default rpmvendor() { [ "$DISTRIB_ID" = "ALTLinux" ] && echo "alt" && return [ "$DISTRIB_ID" = "ALTServer" ] && echo "alt" && return [ "$DISTRIB_ID" = "AstraLinux" ] && echo "astra" && return [ "$DISTRIB_ID" = "LinuxXP" ] && echo "lxp" && return [ "$DISTRIB_ID" = "TinyCoreLinux" ] && echo "tcl" && return [ "$DISTRIB_ID" = "VoidLinux" ] && echo "void" && return [ "$DISTRIB_ID" = "OpenSUSE" ] && echo "suse" && return [ "$DISTRIB_ID" = "openSUSETumbleweed" ] && echo "suse" && return [ "$DISTRIB_ID" = "openSUSELeap" ] && echo "suse" && return [ -n "$VENDOR_ID" ] && echo "$VENDOR_ID" && return tolower "$DISTRIB_ID" } # Translate DISTRIB_ID name to package manner (like in the package release name) pkgvendor() { [ "$DISTRIB_ID" = "Mandriva" ] && echo "mdv" && return rpmvendor } # TODO: in more appropriate way #which pkcon 2>/dev/null >/dev/null && info "You can run $ PMTYPE=packagekit epm to use packagekit backend" # Print package manager (need DISTRIB_ID var) pkgmanager() { local CMD # FIXME: some problems with multibased distros (Server Edition on CentOS and Desktop Edition on Ubuntu) case $DISTRIB_ID in ALTLinux) #which ds-install 2>/dev/null >/dev/null && CMD=deepsolver-rpm #which pkcon 2>/dev/null >/dev/null && CMD=packagekit-rpm CMD="apt-rpm" ;; ALTServer) CMD="apt-rpm" ;; PCLinux) CMD="apt-rpm" ;; Ubuntu|Debian|Mint|AstraLinux|Elbrus) CMD="apt-dpkg" #which aptitude 2>/dev/null >/dev/null && CMD=aptitude-dpkg hascommand snappy && CMD=snappy ;; Mandriva|ROSA) CMD="urpm-rpm" ;; FreeBSD|NetBSD|OpenBSD|Solaris) CMD="pkgsrc" which pkg 2>/dev/null >/dev/null && CMD=pkgng ;; Gentoo) CMD="emerge" ;; ArchLinux) CMD="pacman" ;; Fedora|FedoraLinux|LinuxXP|ASPLinux|CentOS|OracleLinux|RockyLinux|AlmaLinux|RHEL|Scientific|GosLinux|Amzn|RedOS) CMD="dnf-rpm" hascommand dnf || CMD=yum-rpm [ "$DISTRIB_ID/$DISTRIB_RELEASE" = "CentOS/7" ] && CMD=yum-rpm ;; Slackware) CMD="slackpkg" ;; SUSE|SLED|SLES|openSUSETumbleweed|openSUSELeap) CMD="zypper-rpm" ;; ForesightLinux|rPathLinux) CMD="conary" ;; Windows) CMD="appget" hascommand $CMD || CMD="chocolatey" hascommand $CMD || CMD="winget" ;; MacOS) CMD="homebrew" ;; OpenWrt) CMD="opkg" ;; GNU/Linux/Guix) CMD="guix" ;; Android) CMD="android" ;; Cygwin) CMD="aptcyg" ;; alpine) CMD="apk" ;; TinyCoreLinux) CMD="tce" ;; VoidLinux) CMD="xbps" ;; *) # try detect firstly if hascommand "rpm" ; then hascommand "urpmi" && echo "urpmi-rpm" && return hascommand "zypper" && echo "zypper-rpm" && return hascommand "apt-get" && echo "apt-rpm" && return hascommand "dnf" && echo "dnf-rpm" && return fi if hascommand "dpkg" ; then hascommand "apt" && echo "apt-dpkg" && return hascommand "apt-get" && echo "apt-dpkg" && return fi echo "We don't support yet DISTRIB_ID $DISTRIB_ID" >&2 ;; esac echo "$CMD" } # Print pkgtype (need DISTRIB_ID var) pkgtype() { # TODO: try use generic names case $(pkgvendor) in freebsd) echo "tbz" ;; sunos) echo "pkg.gz" ;; slackware|mopslinux) echo "tgz" ;; archlinux|manjaro) echo "pkg.tar.xz" ;; gentoo) echo "tbz2" ;; windows) echo "exe" ;; android) echo "apk" ;; alpine) echo "apk" ;; tinycorelinux) echo "tcz" ;; voidlinux) echo "xbps" ;; openwrt) echo "ipk" ;; cygwin) echo "tar.xz" ;; *) case $(pkgmanager) in *-dpkg) echo "deb" ;; *-rpm) echo "rpm" ;; *) echo "rpm" ;; esac esac } get_var() { # get first variable and print it out, drop quotes if exists grep -i "^$1 *=" | head -n 1 | sed -e "s/^[^=]*[ \t]*=[ \t]*//" | sed -e "s/^[\'\"]\(.*\)[\'\"]/\1/" } # 2010.1 -> 2010 get_major_version() { echo "$1" | sed -e "s/\..*//g" } normalize_name() { [ "$1" = "RED OS" ] && echo "RedOS" && return [ "$1" = "CentOS Linux" ] && echo "CentOS" && return [ "$1" = "Rocky Linux" ] && echo "RockyLinux" && return [ "$1" = "Oracle Linux" ] && echo "OracleLinux" && return [ "$1" = "Alma Linux" ] && echo "AlmaLinux" && return #echo "${1// /}" echo "$1" | sed -e "s/ //g" } # Default values PRETTY_NAME="" DISTRIB_ID="" DISTRIB_RELEASE="" DISTRIB_CODENAME="" # Default with LSB if distro lsb-release ; then DISTRIB_ID=$(cat $DISTROFILE | get_var DISTRIB_ID) DISTRIB_RELEASE=$(cat $DISTROFILE | get_var DISTRIB_RELEASE) DISTRIB_CODENAME=$(cat $DISTROFILE | get_var DISTRIB_CODENAME) PRETTY_NAME=$(cat $DISTROFILE | get_var DISTRIB_DESCRIPTION) fi # Next default by /etc/os-release # https://www.freedesktop.org/software/systemd/man/os-release.html if distro os-release ; then # shellcheck disable=SC1090 . $DISTROFILE DISTRIB_ID="$(normalize_name "$NAME")" # DISTRIB_ID="$(firstupper "$ID")" DISTRIB_RELEASE="$VERSION_ID" [ -n "$DISTRIB_RELEASE" ] || DISTRIB_RELEASE="CUR" # set by os-release: #PRETTY_NAME VENDOR_ID="$ID" fi # ALT Linux based if distro altlinux-release ; then DISTRIB_ID="ALTLinux" # FIXME: fast hack for fallback: 10 -> p10 for /etc/os-release DISTRIB_RELEASE="$(echo p$DISTRIB_RELEASE | sed -e 's|\..*||')" if has Sisyphus ; then DISTRIB_RELEASE="Sisyphus" elif has "ALT p10.* p10 " ; then DISTRIB_RELEASE="p10" elif has "ALTServer 10." ; then DISTRIB_RELEASE="p10" elif has "ALTServer 9." ; then DISTRIB_RELEASE="p9" elif has "ALT c10.* c10 " ; then DISTRIB_RELEASE="c10" elif has "ALT p9.* p9 " ; then DISTRIB_RELEASE="p9" elif has "ALT 9 SP " ; then DISTRIB_RELEASE="c9" elif has "ALT c9f1" ; then DISTRIB_RELEASE="c9f1" elif has "ALT 8 SP " ; then DISTRIB_RELEASE="c8" elif has "ALT c8.2 " ; then DISTRIB_RELEASE="c8.2" elif has "ALT c8.1 " ; then DISTRIB_RELEASE="c8.1" elif has "ALT c8 " ; then DISTRIB_RELEASE="c8" elif has "ALT .*8.[0-9]" ; then DISTRIB_RELEASE="p8" elif has "Simply Linux 10." ; then DISTRIB_RELEASE="p10" elif has "Simply Linux 9." ; then DISTRIB_RELEASE="p9" elif has "Simply Linux 8." ; then DISTRIB_RELEASE="p8" elif has "Simply Linux 7." ; then DISTRIB_RELEASE="p7" elif has "Simply Linux 6." ; then DISTRIB_RELEASE="p6" elif has "ALT Linux p8" ; then DISTRIB_RELEASE="p8" elif has "ALT Linux 8." ; then DISTRIB_RELEASE="p8" elif has "ALT Linux p7" ; then DISTRIB_RELEASE="p7" elif has "ALT Linux 7." ; then DISTRIB_RELEASE="p7" elif has "ALT Linux t7." ; then DISTRIB_RELEASE="t7" elif has "ALT Linux 6." ; then DISTRIB_RELEASE="p6" elif has "ALT Linux p6" ; then DISTRIB_RELEASE="p6" elif has "ALT Linux p5" ; then DISTRIB_RELEASE="p5" elif has "ALT Linux 5.1" ; then DISTRIB_RELEASE="5.1" elif has "ALT Linux 5.0" ; then DISTRIB_RELEASE="5.0" elif has "ALT Linux 4.1" ; then DISTRIB_RELEASE="4.1" elif has "ALT Linux 4.0" ; then DISTRIB_RELEASE="4.0" elif has "starter kit" ; then DISTRIB_RELEASE="Sisyphus" elif has Citron ; then DISTRIB_RELEASE="2.4" fi PRETTY_NAME="$(cat /etc/altlinux-release)" elif distro gentoo-release ; then DISTRIB_ID="Gentoo" MAKEPROFILE=$(readlink $ROOTDIR/etc/portage/make.profile 2>/dev/null) || MAKEPROFILE=$(readlink $ROOTDIR/etc/make.profile) DISTRIB_RELEASE=$(basename $MAKEPROFILE) echo $DISTRIB_RELEASE | grep -q "[0-9]" || DISTRIB_RELEASE=$(basename "$(dirname $MAKEPROFILE)") #" elif distro slackware-version ; then DISTRIB_ID="Slackware" DISTRIB_RELEASE="$(grep -Eo '[0-9]+\.[0-9]+' $DISTROFILE)" elif distro os-release && hascommand apk ; then # shellcheck disable=SC1090 . $ROOTDIR/etc/os-release DISTRIB_ID="$(firstupper "$ID")" DISTRIB_RELEASE="$VERSION_ID" elif distro os-release && hascommand tce-ab ; then # shellcheck disable=SC1090 . $ROOTDIR/etc/os-release DISTRIB_ID="TinyCoreLinux" DISTRIB_RELEASE="$VERSION_ID" elif distro os-release && hascommand xbps-query ; then # shellcheck disable=SC1090 . $ROOTDIR/etc/os-release DISTRIB_ID="VoidLinux" DISTRIB_RELEASE="Live" # TODO: use standart /etc/os-release or lsb elif distro arch-release ; then DISTRIB_ID="ArchLinux" DISTRIB_RELEASE="rolling" # Elbrus elif distro mcst_version ; then DISTRIB_ID="MCST" DISTRIB_RELEASE=$(cat "$DISTROFILE" | grep "release" | sed -e "s|.*release \([0-9]*\).*|\1|g") #" # OpenWrt elif distro openwrt_release ; then . $DISTROFILE DISTRIB_RELEASE=$(cat $ROOTDIR/etc/openwrt_version) elif distro astra_version ; then #DISTRIB_ID=`cat $DISTROFILE | get_var DISTRIB_ID` DISTRIB_ID="AstraLinux" #DISTRIB_RELEASE=$(cat "$DISTROFILE" | head -n1 | sed -e "s|.* \([a-z]*\).*|\1|g") DISTRIB_RELEASE=$DISTRIB_CODENAME # for Ubuntu use standard LSB info elif [ "$DISTRIB_ID" = "Ubuntu" ] && [ -n "$DISTRIB_RELEASE" ]; then # use LSB version true # Debian based elif distro debian_version ; then DISTRIB_ID="Debian" DISTRIB_RELEASE=$(cat $DISTROFILE | sed -e "s/\..*//g") # Mandriva based elif distro pclinuxos-release ; then DISTRIB_ID="PCLinux" if has "2007" ; then DISTRIB_RELEASE="2007" elif has "2008" ; then DISTRIB_RELEASE="2008" elif has "2010" ; then DISTRIB_RELEASE="2010" fi elif distro mandriva-release || distro mandrake-release ; then DISTRIB_ID="Mandriva" if has 2005 ; then DISTRIB_RELEASE="2005" elif has 2006 ; then DISTRIB_RELEASE="2006" elif has 2007 ; then DISTRIB_RELEASE="2007" elif has 2008 ; then DISTRIB_RELEASE="2008" elif has 2009.0 ; then DISTRIB_RELEASE="2009.0" elif has 2009.1 ; then DISTRIB_RELEASE="2009.1" else # use /etc/lsb-release info by default if has ROSA ; then DISTRIB_ID="ROSA" fi fi # Fedora based elif distro MCBC-release ; then DISTRIB_ID="MCBC" if has 3.0 ; then DISTRIB_RELEASE="3.0" elif has 3.1 ; then DISTRIB_RELEASE="3.1" fi # TODO: drop in favour of /etc/os-release elif distro redhat-release && [ -z "$PRETTY_NAME" ] ; then # FIXME if need # actually in the original RHEL: Red Hat Enterprise Linux .. release N DISTRIB_ID="RHEL" if has CentOS ; then DISTRIB_ID="CentOS" elif has Scientific ; then DISTRIB_ID="Scientific" elif has GosLinux ; then DISTRIB_ID="GosLinux" fi if has Beryllium ; then DISTRIB_ID="Scientific" DISTRIB_RELEASE="4.1" elif has "release 4" ; then DISTRIB_RELEASE="4" elif has "release 5" ; then DISTRIB_RELEASE="5" elif has "release 6" ; then DISTRIB_RELEASE="6" elif has "release 7" ; then DISTRIB_RELEASE="7" elif has "release 8" ; then DISTRIB_RELEASE="8" fi # SUSE based elif distro SuSe-release || distro SuSE-release ; then DISTRIB_ID="SUSE" DISTRIB_RELEASE=$(cat "$DISTROFILE" | grep "VERSION" | sed -e "s|^VERSION = ||g") if has "SUSE Linux Enterprise Desktop" ; then DISTRIB_ID="SLED" elif has "SUSE Linux Enterprise Server" ; then DISTRIB_ID="SLES" fi # fixme: can we detect by some file? elif [ "$(uname)" = "FreeBSD" ] ; then DISTRIB_ID="FreeBSD" UNAME=$(uname -r) DISTRIB_RELEASE=$(echo "$UNAME" | grep RELEASE | sed -e "s|\([0-9]\.[0-9]\)-RELEASE|\1|g") #" # fixme: can we detect by some file? elif [ "$(uname)" = "SunOS" ] ; then DISTRIB_ID="SunOS" DISTRIB_RELEASE=$(uname -r) # fixme: can we detect by some file? elif [ "$(uname -s 2>/dev/null)" = "Darwin" ] ; then DISTRIB_ID="MacOS" DISTRIB_RELEASE=$(uname -r) # fixme: move to up elif [ "$(uname)" = "Linux" ] && hascommand guix ; then DISTRIB_ID="GNU/Linux/Guix" DISTRIB_RELEASE=$(uname -r) # fixme: move to up elif [ "$(uname)" = "Linux" ] && [ -x $ROOTDIR/system/bin/getprop ] ; then DISTRIB_ID="Android" DISTRIB_RELEASE=$(getprop | awk -F": " '/build.version.release/ { print $2 }' | tr -d '[]') elif [ "$(uname -o 2>/dev/null)" = "Cygwin" ] ; then DISTRIB_ID="Cygwin" DISTRIB_RELEASE="all" fi [ -n "$DISTRIB_ID" ] || DISTRIB_ID="Generic" if [ -z "$PRETTY_NAME" ] ; then PRETTY_NAME="$DISTRIB_ID $DISTRIB_RELEASE" fi get_uname() { tolower $(uname $1) | tr -d " \t\r\n" } get_base_os_name() { local DIST_OS # Resolve the os DIST_OS="$(get_uname -s)" case "$DIST_OS" in 'sunos') DIST_OS="solaris" ;; 'hp-ux' | 'hp-ux64') DIST_OS="hpux" ;; 'darwin' | 'oarwin') DIST_OS="macosx" ;; 'unix_sv') DIST_OS="unixware" ;; 'freebsd' | 'openbsd' | 'netbsd') DIST_OS="freebsd" ;; esac echo "$DIST_OS" } get_arch() { local DIST_ARCH # Resolve the architecture DIST_ARCH="$(get_uname -m)" case "$DIST_ARCH" in 'ia32' | 'i386' | 'i486' | 'i586' | 'i686') DIST_ARCH="x86" ;; 'amd64' | 'x86_64') DIST_ARCH="x86_64" ;; 'ia64' | 'ia-64') DIST_ARCH="ia64" ;; 'ip27' | 'mips') DIST_ARCH="mips" ;; 'powermacintosh' | 'power' | 'powerpc' | 'power_pc' | 'ppc64') DIST_ARCH="ppc" ;; 'pa_risc' | 'pa-risc') DIST_ARCH="parisc" ;; 'sun4u' | 'sparcv9') DIST_ARCH="sparc" ;; '9000/800') DIST_ARCH="parisc" ;; 'arm64' | 'aarch64') DIST_ARCH='aarch64' ;; armv7*) # TODO: use uname only # uses binutils package if which readelf >/dev/null 2>/dev/null && [ -z "$(readelf -A /proc/self/exe | grep Tag_ABI_VFP_args)" ] ; then DIST_ARCH="armel" else DIST_ARCH="armhf" fi ;; esac echo "$DIST_ARCH" } get_debian_arch() { local arch="$(get_arch)" case $arch in 'x86') arch='i386' ;; 'x86_64') arch='amd64' ;; esac echo "$arch" } get_distro_arch() { local arch="$(get_arch)" case "$(pkgtype)" in rpm) case $arch in 'x86') arch='i586' ;; esac ;; deb) get_debian_arch return ;; esac echo "$arch" } get_bit_size() { local DIST_BIT DIST_BIT="$(getconf LONG_BIT 2>/dev/null)" if [ -n "$DIST_BIT" ] ; then echo "$DIST_BIT" return fi # Try detect arch size by arch name case "$(get_uname -m)" in 'amd64' | 'ia64' | 'x86_64' | 'ppc64') DIST_BIT="64" ;; 'aarch64') DIST_BIT="64" ;; 'e2k') DIST_BIT="64" ;; # 'pa_risc' | 'pa-risc') # Are some of these 64bit? Least not all... # BIT="64" # ;; 'sun4u' | 'sparcv9') # Are all sparcs 64? DIST_BIT="64" ;; # '9000/800') # DIST_BIT="64" # ;; *) # In any other case default to 32 DIST_BIT="32" ;; esac echo "$DIST_BIT" } # TODO: check before calc get_memory_size() { local detected="" local DIST_OS="$(get_base_os_name)" case "$DIST_OS" in macosx) detected=$((`sysctl hw.memsize | sed s/"hw.memsize: "//`/1024/1024)) ;; freebsd) detected=$((`sysctl hw.physmem | sed s/"hw.physmem: "//`/1024/1024)) ;; linux) [ -r /proc/meminfo ] && detected=$((`cat /proc/meminfo | grep MemTotal | awk '{print $2}'`/1024)) ;; solaris) detected=$(prtconf | grep Memory | sed -e "s|Memory size: \([0-9][0-9]*\) Megabyte.*|\1|") ;; # *) # fatal "Unsupported OS $DIST_OS" esac [ -n "$detected" ] || detected=0 echo $detected } print_name_version() { [ -n "$DISTRIB_RELEASE" ] && echo $DISTRIB_ID/$DISTRIB_RELEASE || echo $DISTRIB_ID } get_core_count() { local detected="" local DIST_OS="$(get_base_os_name)" case "$DIST_OS" in macos|freebsd) detected=$(sysctl hw.ncpu | awk '{print $2}') ;; linux) detected=$(grep -c "^processor" /proc/cpuinfo) ;; solaris) detected=$(prtconf | grep -c 'cpu[^s]') ;; aix) detected=$(lsdev -Cc processor -S A | wc -l) ;; # *) # fatal "Unsupported OS $DIST_OS" esac [ -n "$detected" ] || detected=0 echo $detected } get_core_mhz() { cat /proc/cpuinfo | grep "cpu MHz" | head -n1 | cut -d':' -f2 | cut -d' ' -f2 | cut -d'.' -f1 } get_virt() { local VIRT local SDCMD SDCMD=$(which systemd-detect-virt 2>/dev/null) if [ -n "$SDCMD" ] ; then VIRT="$($SDCMD)" [ "$VIRT" = "none" ] && echo "(host system)" && return [ -z "$VIRT" ] && echo "(unknown)" && return echo "$VIRT" && return fi # TODO: use virt-what under root # inspired by virt_what if [ -d "/proc/vz" -a ! -d "/proc/bc" ]; then echo "openvz" && return fi if [ -r "/sys/bus/xen" ] ; then echo "xen" && return fi echo "(unknown)" # TODO: check for openvz } # https://unix.stackexchange.com/questions/196166/how-to-find-out-if-a-system-uses-sysv-upstart-or-systemd-initsystem get_service_manager() { [ -d /run/systemd/system ] && echo "systemd" && return # TODO #[ -d /usr/share/upstart ] && echo "upstart" && return [ -d /etc/init.d ] && echo "sysvinit" && return echo "(unknown)" } print_pretty_name() { echo "$PRETTY_NAME" } print_total_info() { cat <<EOF distro_info v$PROGVERSION : Copyright © 2007-2022 Etersoft ==== Total system information: Pretty distro name (--pretty): $(print_pretty_name) Distro name and version (-e): $(print_name_version) Package manager/type (-g/-p): $(pkgmanager) / $(pkgtype) Running service manager (-y): $(get_service_manager) Virtualization (-i): $(get_virt) CPU Cores/MHz (-c/-z): $(get_core_count) / $(get_core_mhz) MHz CPU Architecture (-a): $(get_arch) CPU norm register size (-b): $(get_bit_size) System memory size (MB) (-m): $(get_memory_size) Base OS name (-o): $(get_base_os_name) Build system distro name (-s): $(pkgvendor) Build system vendor name (-n): $(rpmvendor) (run with -h to get help) EOF } case $1 in -h|--help) echo "distro_info v$PROGVERSION - distro information retriever" echo "Usage: distro_info [options] [args]" echo "Options:" echo " -a - print hardware architecture (--distro-arch for distro depended name)" echo " -b - print size of arch bit (32/64)" echo " -c - print number of CPU cores" echo " -z - print current CPU MHz" echo " -d - print distro name" echo " -e - print full name of distro with version" echo " -i - print virtualization type" echo " -h - this help" echo " -m - print system memory size (in MB)" echo " -n [SystemName] - print vendor name (as _vendor macros in rpm)" echo " -o - print base OS name" echo " -p [SystemName] - print type of the packaging system" echo " -g [SystemName] - print name of the packaging system" echo " -s [SystemName] - print name of distro for build system (like in the package release name)" echo " -y - print running service manager" echo " --pretty - print pretty distro name" echo " -v - print version of distro" echo " -V - print the utility version" echo "Run without args to print all information." exit 0 ;; -p) override_distrib "$2" pkgtype exit 0 ;; -g) override_distrib "$2" pkgmanager exit 0 ;; --pretty) print_pretty_name ;; --distro-arch) override_distrib "$2" get_distro_arch exit 0 ;; --debian-arch) override_distrib "$2" get_debian_arch exit 0 ;; -d) echo $DISTRIB_ID ;; -a) get_arch ;; -b) get_bit_size ;; -c) get_core_count ;; -z) get_core_mhz ;; -i) get_virt ;; -m) get_memory_size ;; -o) get_base_os_name ;; -v) echo $DISTRIB_RELEASE ;; -s) override_distrib "$2" pkgvendor exit 0 ;; -n) override_distrib "$2" rpmvendor exit 0 ;; -y) get_service_manager ;; -V) echo "$PROGVERSION" exit 0 ;; -e) print_name_version ;; *) print_total_info ;; esac } ################# end of incorporated bin/distr_info ################# ################# incorporate bin/tools_eget ################# internal_tools_eget() { # eget - simply shell on wget for loading directories over http (wget does not support wildcard for http) # Example use: # eget http://ftp.altlinux.ru/pub/security/ssl/* # # Copyright (C) 2014-2014, 2016, 2020 Etersoft # Copyright (C) 2014 Daniil Mikhailov <danil@etersoft.ru> # Copyright (C) 2016-2017, 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/>. # fatal() { echo "FATAL: $*" >&2 exit 1 } WGETQ='' #-q CURLQ='' #-s set_quiet() { WGETQ='-q' CURLQ='-s' } # TODO: passthrou all wget options if [ "$1" = "-q" ] ; then set_quiet shift fi WGET="$(which wget 2>/dev/null)" if [ -n "$WGET" ] ; then # put remote content to stdout scat() { $WGET $WGETQ -O- "$1" } # download to default name of to $2 sget() { if [ -n "$2" ] ; then $WGET $WGETQ -O "$2" "$1" else $WGET $WGETQ "$1" fi } else CURL="$(which curl 2>/dev/null)" [ -n "$CURL" ] || fatal "There are no wget nor curl in the system. Install it with $ epm install curl" # put remote content to stdout scat() { $CURL -L $CURLQ "$1" } # download to default name of to $2 sget() { if [ -n "$2" ] ; then $CURL -L $CURLQ --output "$2" "$1" else $CURL -L $CURLQ -O "$1" fi } fi LISTONLY='' if [ "$1" = "--list" ] ; then LISTONLY="$1" set_quiet shift fi LATEST='' if [ "$1" = "--latest" ] ; then LATEST="$1" shift fi fatal() { echo "$*" >&2 exit 1 } # check man glob filter_glob() { [ -z "$1" ] && cat && return # translate glob to regexp grep "$(echo "$1" | sed -e "s|\*|.*|g" -e "s|?|.|g")$" } filter_order() { [ -z "$LATEST" ] && cat && return sort | tail -n1 } # download to this file TARGETFILE='' if [ "$1" = "-O" ] ; then TARGETFILE="$2" shift 2 fi # TODO: # -P support if [ -z "$1" ] ; then echo "eget - wget like downloader" >&2 fatal "Run $0 --help to get help" fi if [ "$1" = "-h" ] || [ "$1" = "--help" ] ; then echo "eget - wget like downloader with wildcard support in filename part of URL" echo "Usage: eget [-q] [-O target file] [--list] http://somesite.ru/dir/na*.log" echo echo "Options:" echo " -q - quiet mode" echo " -O file - download to this file (use filename from server if missed)" echo " --list - print files from url with mask" echo " --latest - print only latest version of file" echo echo "eget supports --list and download for https://github.com/owner/project urls" echo # echo "See $ wget --help for wget options you can use here" return fi get_github_urls() { # https://github.com/OWNER/PROJECT local owner="$(echo "$1" | sed -e "s|^https://github.com/||" -e "s|/.*||")" #" local project="$(echo "$1" | sed -e "s|^https://github.com/$owner/||" -e "s|/.*||")" #" [ -n "$owner" ] || fatal "Can't get owner from $1" [ -n "$project" ] || fatal "Can't get project from $1" local URL="https://api.github.com/repos/$owner/$project/releases" scat $URL | \ grep -i -o -E '"browser_download_url": "https://.*"' | cut -d'"' -f4 } if echo "$1" | grep -q "^https://github.com/" && \ echo "$1" | grep -q -v "/download/" && [ -n "$2" ] ; then MASK="$2" if [ -n "$LISTONLY" ] ; then get_github_urls "$1" | filter_glob "$MASK" | filter_order return fi for fn in $(get_github_urls "$1" | filter_glob "$MASK" | filter_order) ; do sget "$fn" || ERROR=1 done return fi # do not support / if echo "$1" | grep -q "/$" ; then fatal "Use http://example.com/e/* to download all files in dir" fi # If ftp protocol, just download if echo "$1" | grep -q "^ftp://" ; then [ -n "$LISTONLY" ] && fatal "TODO: list files for ftp:// do not supported yet" sget "$1" "$TARGETFILE" return fi # mask allowed only in the last part of path MASK=$(basename "$1") # if mask are second arg if [ -n "$2" ] ; then URL="$1" MASK="$2" else # drop mask part URL="$(dirname "$1")" fi if echo "$URL" | grep -q "[*?]" ; then fatal "Error: there are globbing symbols (*?) in $URL" fi # If have no wildcard symbol like asterisk, just download if echo "$MASK" | grep -qv "[*?]" || echo "$MASK" | grep -q "[?].*="; then sget "$1" "$TARGETFILE" return fi is_url() { echo "$1" | grep -q "://" } get_urls() { scat $URL/ | \ grep -i -o -E 'href="(.+)"' | cut -d'"' -f2 } if [ -n "$LISTONLY" ] ; then for fn in $(get_urls | filter_glob "$MASK" | filter_order) ; do is_url "$fn" && echo $fn && continue fn="$(echo "$fn" | sed -e 's|^./||' -e 's|^/+||')" echo "$URL/$fn" done return fi ERROR=0 for fn in $(get_urls | filter_glob "$MASK" | filter_order) ; do sget "$URL/$(basename "$fn")" || ERROR=1 done return $ERROR } ################# end of incorporated bin/tools_eget ################# ################# incorporate bin/tools_estrlist ################# internal_tools_estrlist() { #!/bin/bash # 2009-2010, 2012, 2017, 2020 Etersoft www.etersoft.ru # Author: Vitaly Lipatov <lav@etersoft.ru> # Public domain # TODO: rewrite with shell commands, perl or C # Python - http://www.linuxtopia.org/online_books/programming_books/python_programming/python_ch16s03.html # Shell - http://linux.byexamples.com/archives/127/uniq-and-basic-set-theory/ # - http://maiaco.com/articles/shellSetOperations.php # Perl - http://docstore.mik.ua/orelly/perl/cookbook/ch04_09.htm # - http://blogs.perl.org/users/polettix/2012/03/sets-operations.html # http://rosettacode.org/wiki/Symmetric_difference # TODO: add unit tests # http://ru.wikipedia.org/wiki/Операции_над_множествами # Base set operations: # * union # "1 2 3" "3 4 5" -> "1 2 3 4 5" # * intersection # "1 2 3" "3 4 5" -> "3" # * relative complement (substracted, difference) ( A ? B – members in A but not in B ) # http://en.wikipedia.org/wiki/Complement_%28set_theory%29 # "1 3" "1 2 3 4" -> "2 4" # * symmetric difference (симметричная разность) ( A ^ B – members in A or B but not both ) # http://en.wikipedia.org/wiki/Symmetric_difference # "1 2 3" "3 4 5" -> "1 2 4 5" fatal() { echo "FATAL: $*" >&2 exit 1 } filter_strip_spaces() { # possible use just #xargs echo sed -e "s| \+| |g" -e "s|^ ||" -e "s| \$||" } strip_spaces() { echo "$*" | filter_strip_spaces } is_empty() { [ "$(strip_spaces "$*")" = "" ] } isempty() { is_empty "$@" } has_space() { # not for dash: # [ "$1" != "${1/ //}" ] [ "$(echo "$*" | sed -e "s| ||")" != "$*" ] } list() { local i for i in $@ ; do echo "$i" done } count() { list $@ | wc -l } union() { strip_spaces $(list $@ | sort -u) } intersection() { local RES="" local i j for i in $2 ; do for j in $1 ; do [ "$i" = "$j" ] && RES="$RES $i" done done strip_spaces "$RES" } uniq() { union $@ } has() { local wd="$1" shift echo "$*" | grep -q -- "$wd" } # Note: used egrep! write '[0-9]+(first|two)', not '[0-9]\+...' match() { local wd="$1" shift echo "$*" | egrep -q -- "$wd" } # remove_from_list "1." "11 12 21 22" -> "21 22" reg_remove() { local i local RES= for i in $2 ; do echo "$i" | grep -q "^$1$" || RES="$RES $i" done strip_spaces "$RES" } # remove_from_list "1." "11 12 21 22" -> "21 22" reg_wordremove() { local i local RES="" for i in $2 ; do echo "$i" | grep -q -w "$1" || RES="$RES $i" done strip_spaces "$RES" } reg_rqremove() { local i local RES="" for i in $2 ; do [ "$i" = "$1" ] || RES="$RES $i" done strip_spaces "$RES" } # Args: LIST1 LIST2 # do_exclude_list print LIST2 list exclude fields contains also in LIST1 # Example: exclude "1 3" "1 2 3 4" -> "2 4" exclude() { local i local RES="$2" for i in $1 ; do RES="$(reg_rqremove "$i" "$RES")" done strip_spaces "$RES" } # regexclude_list "22 1." "11 12 21 22" -> "21" reg_exclude() { local i local RES="$2" for i in $1 ; do RES="$(reg_remove "$i" "$RES")" done strip_spaces "$RES" } # regexclude_list "22 1." "11 12 21 22" -> "21" reg_wordexclude() { local i local RES="$2" for i in $1 ; do RES=$(reg_wordremove "$i" "$RES") done strip_spaces "$RES" } if_contain() { local i for i in $2 ; do [ "$i" = "$1" ] && return done return 1 } difference() { local RES="" local i for i in $1 ; do if_contain $i "$2" || RES="$RES $i" done for i in $2 ; do if_contain $i "$1" || RES="$RES $i" done strip_spaces "$RES" } # FIXME: # reg_include "1." "11 12 21 22" -> "11 12" reg_include() { local i local RES="" for i in $2 ; do echo "$i" | grep -q -w "$1" && RES="$RES $i" done strip_spaces "$RES" } example() { local CMD="$1" local ARG1="$2" shift 2 echo "\$ $0 $CMD \"$ARG1\" \"$@\"" $0 $CMD "$ARG1" "$@" } example_res() { example "$@" && echo TRUE || echo FALSE } help() { echo "estrlist developed for string list operations. See also cut, join, paste..." echo "Usage: $0 <command> [args]" echo "Commands:" echo " strip_spaces [args] - remove extra spaces" # TODO: add filter # echo " filter_strip_spaces - remove extra spaces from words from standart input" # echo " reg_remove <PATTERN> [word list] - remove words containing a match to the given PATTERN (grep notation)" # echo " reg_wordremove <PATTERN> [word list] - remove words containing a match to the given PATTERN (grep -w notation)" echo " exclude <list1> <list2> - print list2 items exclude list1 items" echo " reg_exclude <list PATTERN> [word list] - print only words that do not match PATTERN" # echo " reg_wordexclude <list PATTERN> [word list] - print only words do not match PATTERN" echo " has <PATTERN> string - check the string for a match to the regular expression given in PATTERN (grep notation)" echo " match <PATTERN> string - check the string for a match to the regular expression given in PATTERN (egrep notation)" echo " isempty [string] (is_empty) - true if string has no any symbols (only zero or more spaces)" echo " has_space [string] - true if string has no spaces" echo " union [word list] - sort and remove duplicates" echo " intersection <list1> <list2> - print only intersected items (the same in both lists)" echo " difference <list1> <list2> - symmetric difference between lists items (not in both lists)" echo " uniq [word list] - alias for union" echo " list [word list] - just list words line by line" echo " count [word list] - print word count" echo echo "Examples:" # example reg_remove "1." "11 12 21 22" # example reg_wordremove "1." "11 12 21 22" example exclude "1 3" "1 2 3 4" example reg_exclude "22 1." "11 12 21 22" example reg_wordexclude "wo.* er" "work were more else" example union "1 2 2 3 3" example count "1 2 3 4 10" example_res isempty " " #example_res isempty " 1 " example_res has ex "exactly" example_res has exo "exactly" example_res match "M[0-9]+" "M250" example_res match "M[0-9]+" "MI" } COMMAND="$1" if [ -z "$COMMAND" ] ; then echo "Run with --help for get command description." exit 1 fi if [ "$COMMAND" = "-h" ] || [ "$COMMAND" = "--help" ] ; then COMMAND="help" fi # case "$COMMAND" in reg_remove|reg_wordremove) fatal "obsoleted command $COMMAND" ;; esac shift # FIXME: do to call function directly, use case instead? if [ "$COMMAND" = "--" ] ; then # ignore all options (-) COMMAND="$1" shift "$COMMAND" "$@" elif [ "$1" = "-" ] ; then shift "$COMMAND" "$(cat) $@" elif [ "$2" = "-" ] ; then "$COMMAND" "$1" "$(cat)" else "$COMMAND" "$@" fi } ################# end of incorporated bin/tools_estrlist ################# ################# incorporate bin/tools_json ################# internal_tools_json() { # License: MIT or Apache # Homepage: http://github.com/dominictarr/JSON.sh throw() { echo "$*" >&2 exit 1 } BRIEF=0 LEAFONLY=0 PRUNE=0 NO_HEAD=0 NORMALIZE_SOLIDUS=0 usage() { echo echo "Usage: JSON.sh [-b] [-l] [-p] [-s] [-h]" echo echo "-p - Prune empty. Exclude fields with empty values." echo "-l - Leaf only. Only show leaf nodes, which stops data duplication." echo "-b - Brief. Combines 'Leaf only' and 'Prune empty' options." echo "-n - No-head. Do not show nodes that have no path (lines that start with [])." echo "-s - Remove escaping of the solidus symbol (straight slash)." echo "-h - This help text." echo } parse_options() { set -- "$@" local ARGN=$# while [ "$ARGN" -ne 0 ] do case $1 in -h) usage exit 0 ;; -b) BRIEF=1 LEAFONLY=1 PRUNE=1 ;; -l) LEAFONLY=1 ;; -p) PRUNE=1 ;; -n) NO_HEAD=1 ;; -s) NORMALIZE_SOLIDUS=1 ;; ?*) echo "ERROR: Unknown option." usage exit 0 ;; esac shift 1 ARGN=$((ARGN-1)) done } # compatibility awk_egrep () { local pattern_string=$1 a='' gawk '{ while ($0) { start=match($0, pattern); token=substr($0, start, RLENGTH); print token; $0=substr($0, start+RLENGTH); } }' pattern="$pattern_string" } tokenize () { local GREP local ESCAPE local CHAR if echo "test string" | egrep -ao --color=never "test" >/dev/null 2>&1 then GREP='egrep -ao --color=never' else GREP='egrep -ao' fi if echo "test string" | egrep -o "test" >/dev/null 2>&1 then ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})' CHAR='[^[:cntrl:]"\\]' else GREP=awk_egrep ESCAPE='(\\\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})' CHAR='[^[:cntrl:]"\\\\]' fi local STRING="\"$CHAR*($ESCAPE$CHAR*)*\"" local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?' local KEYWORD='null|false|true' local SPACE='[[:space:]]+' # Force zsh to expand $A into multiple words local is_wordsplit_disabled=$(unsetopt 2>/dev/null | grep -c '^shwordsplit$') if [ $is_wordsplit_disabled != 0 ]; then setopt shwordsplit; fi $GREP "$STRING|$NUMBER|$KEYWORD|$SPACE|." | egrep -v "^$SPACE$" if [ $is_wordsplit_disabled != 0 ]; then unsetopt shwordsplit; fi } parse_array () { local index=0 local ary='' read -r token case "$token" in ']') ;; *) while : do parse_value "$1" "$index" index=$((index+1)) ary="$ary""$value" read -r token case "$token" in ']') break ;; ',') ary="$ary," ;; *) throw "EXPECTED , or ] GOT ${token:-EOF}" ;; esac read -r token done ;; esac [ "$BRIEF" -eq 0 ] && value=$(printf '[%s]' "$ary") || value= : } parse_object () { local key local obj='' read -r token case "$token" in '}') ;; *) while : do case "$token" in '"'*'"') key=$token ;; *) throw "EXPECTED string GOT ${token:-EOF}" ;; esac read -r token case "$token" in ':') ;; *) throw "EXPECTED : GOT ${token:-EOF}" ;; esac read -r token parse_value "$1" "$key" obj="$obj$key:$value" read -r token case "$token" in '}') break ;; ',') obj="$obj," ;; *) throw "EXPECTED , or } GOT ${token:-EOF}" ;; esac read -r token done ;; esac [ "$BRIEF" -eq 0 ] && value=$(printf '{%s}' "$obj") || value= : } parse_value () { local jpath="${1:+$1,}$2" isleaf=0 isempty=0 print=0 case "$token" in '{') parse_object "$jpath" ;; '[') parse_array "$jpath" ;; # At this point, the only valid single-character tokens are digits. ''|[!0-9]) throw "EXPECTED value GOT ${token:-EOF}" ;; *) value=$token # if asked, replace solidus ("\/") in json strings with normalized value: "/" [ "$NORMALIZE_SOLIDUS" -eq 1 ] && value=$(echo "$value" | sed 's#\\/#/#g') isleaf=1 [ "$value" = '""' ] && isempty=1 ;; esac [ "$value" = '' ] && return [ "$NO_HEAD" -eq 1 ] && [ -z "$jpath" ] && return [ "$LEAFONLY" -eq 0 ] && [ "$PRUNE" -eq 0 ] && print=1 [ "$LEAFONLY" -eq 1 ] && [ "$isleaf" -eq 1 ] && [ $PRUNE -eq 0 ] && print=1 [ "$LEAFONLY" -eq 0 ] && [ "$PRUNE" -eq 1 ] && [ "$isempty" -eq 0 ] && print=1 [ "$LEAFONLY" -eq 1 ] && [ "$isleaf" -eq 1 ] && \ [ $PRUNE -eq 1 ] && [ $isempty -eq 0 ] && print=1 [ "$print" -eq 1 ] && printf "[%s]\t%s\n" "$jpath" "$value" : } parse () { read -r token parse_value read -r token case "$token" in '') ;; *) throw "EXPECTED EOF GOT $token" ;; esac } if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]); then parse_options "$@" tokenize | parse fi # vi: expandtab sw=2 ts=2 } ################# end of incorporated bin/tools_json ################# #PATH=$PATH:/sbin:/usr/sbin set_pm_type check_tty ############################# phelp() { echo "$Descr $Usage Options: $(get_help HELPOPT) Short commands: $(get_help HELPSHORT) $(get_help HELPCMD) Examples: $ epmi etckeeper install etckeeper package $ epmqp lib print out all installed packages with 'lib' in a name $ epmqf ip print out a package the command 'ip' from is " } print_version() { echo "EPM package manager version 3.16.2 https://wiki.etersoft.ru/Epm" echo "Running on $($DISTRVENDOR -e) ('$PMTYPE' package manager uses '$PKGFORMAT' package format)" echo "Copyright (c) Etersoft 2012-2021" echo "This program may be freely redistributed under the terms of the GNU AGPLv3." } Usage="Usage: epm [options] <command> [package name(s), package files]..." Descr="epm - EPM package manager" EPMVERSION=3.16.2 verbose=$EPM_VERBOSE quiet= nodeps= noremove= dryrun= force= repack= inscript= scripts= noscripts= short= direct= sort= non_interactive= force_yes= skip_installed= skip_missed= show_command_only= epm_cmd= pkg_files= pkg_dirs= pkg_names= pkg_urls= quoted_args= direct_args= # load system wide config [ -f /etc/eepm/eepm.conf ] && . /etc/eepm/eepm.conf case $PROGNAME in epmi) # HELPSHORT: alias for epm install epm_cmd=install ;; epmI) # HELPSHORT: alias for epm Install epm_cmd=Install ;; epme) # HELPSHORT: alias for epm remove epm_cmd=remove ;; epmcl) # HELPSHORT: alias for epm changelog epm_cmd=changelog ;; epms) # HELPSHORT: alias for epm search epm_cmd=search ;; epmsf) # HELPSHORT: alias for epm search file epm_cmd=search_file ;; epmwd) # HELPSHORT: alias for epm wd epm_cmd=whatdepends ;; epmq) # HELPSHORT: alias for epm query epm_cmd=query ;; epmqi) # HELPSHORT: alias for epm info epm_cmd=info ;; epmqf) # HELPSHORT: alias for epm belongs epm_cmd=query_file ;; epmqa) # HELPSHORT: alias for epm packages epm_cmd=packages ;; epmqp) # HELPSHORT: alias for epm qp (epm query package) epm_cmd=query_package ;; epmql) # HELPSHORT: alias for epm filelist epm_cmd=filelist ;; epmrl) # HELPSHORT: alias for epm repo list epm_cmd=repolist direct_args=1 ;; epmu) # HELPSHORT: alias for epm update epm_cmd=update direct_args=1 ;; epm|upm|eepm) # HELPSHORT: other aliases for epm command ;; epm.sh) ;; *) # epm by default # fatal "Unknown command: $progname" ;; esac # was called with alias name [ -n "$epm_cmd" ] && PROGNAME="epm" check_command() { # do not override command [ -z "$epm_cmd" ] || return # HELPCMD: PART: Base commands: case $1 in -i|install|add|i) # HELPCMD: install package(s) from remote repositories or from local file epm_cmd=install ;; -e|-P|rm|del|remove|delete|uninstall|erase|purge|e) # HELPCMD: remove (delete) package(s) from the database and the system epm_cmd=remove ;; -s|search|s) # HELPCMD: search in remote package repositories epm_cmd=search ;; -qp|qp|query_package) # HELPCMD: search in the list of installed packages epm_cmd=query_package ;; -qf|qf|-S|wp|which|belongs) # HELPCMD: query package(s) owning file epm_cmd=query_file ;; # HELPCMD: PART: Useful commands: reinstall) # HELPCMD: reinstall package(s) from remote repositories or from local file epm_cmd=reinstall ;; Install) # HELPCMD: perform update package repo info and install package(s) via install command epm_cmd=Install ;; -q|q|query) # HELPCMD: check presence of package(s) and print this name (also --short is supported) epm_cmd=query ;; installed) # HELPCMD: check presence of package(s) (like -q with --quiet) epm_cmd=installed ;; -sf|sf|filesearch) # HELPCMD: search in which package a file is included epm_cmd=search_file ;; -ql|ql|filelist|get-files) # HELPCMD: print package file list epm_cmd=filelist ;; check|fix|verify) # HELPCMD: check local package base integrity and fix it epm_cmd=check direct_args=1 ;; dedup) # HELPCMD: remove unallowed duplicated pkgs (after upgrade crash) epm_cmd=dedup direct_args=1 ;; -cl|cl|changelog) # HELPCMD: show changelog for package epm_cmd=changelog ;; -qi|qi|info|show) # HELPCMD: print package detail info epm_cmd=info ;; requires|deplist|depends|req|depends-on) # HELPCMD: print package requires epm_cmd=requires ;; provides|prov) # HELPCMD: print package provides epm_cmd=provides ;; whatdepends|rdepends|whatrequires|wd|required-by) # HELPCMD: print packages dependences on that epm_cmd=whatdepends ;; whatprovides) # HELPCMD: print packages provides that target epm_cmd=whatprovides ;; conflicts) # HELPCMD: print package conflicts epm_cmd=conflicts ;; -qa|qa|-l|list|packages) # HELPCMD: print list of installed package(s) epm_cmd=packages ;; programs) # HELPCMD: print list of installed GUI program(s) (they have .desktop files) epm_cmd=programs direct_args=1 ;; assure) # HELPCMD: <command> [package] [version]: install package if command does not exist epm_cmd=assure ;; policy|resolve) # HELPCMD: print detailed information about the priority selection of package epm_cmd=policy ;; # HELPCMD: PART: Repository control: update) # HELPCMD: update remote package repository databases epm_cmd=update direct_args=1 ;; addrepo|ar) # HELPCMD: add package repo (etersoft, autoimports, archive 2017/12/31); run with param to get list epm_cmd=addrepo direct_args=1 ;; repolist|sl|rl|listrepo|repo-list) # HELPCMD: print repo list epm_cmd=repolist direct_args=1 ;; repofix) # HELPCMD: <mirror>: fix paths in sources lists (ALT Linux only). use repofix etersoft/yandex/basealt for rewrite URL to the specified server epm_cmd=repofix direct_args=1 ;; removerepo|rr) # HELPCMD: remove package repo (shortcut for epm repo remove) epm_cmd=removerepo direct_args=1 ;; repo) # HELPCMD: manipulate with repository list (run epm repo --help to help) epm_cmd=repo direct_args=1 ;; full-upgrade) # HELPCMD: update all system packages and kernel epm_cmd=full_upgrade direct_args=1 ;; release-upgrade|upgrade-release|upgrade-system|release-switch) # HELPCMD: upgrade/switch whole system to the release in arg (default: next (latest) release) epm_cmd=release_upgrade direct_args=1 ;; release-downgrade|downgrade-release|downgrade-system) # HELPCMD: downgrade whole system to the release in arg (default: previuos release) epm_cmd=release_downgrade direct_args=1 ;; kernel-update|kernel-upgrade|update-kernel|upgrade-kernel) # HELPCMD: update system kernel to the last repo version epm_cmd=kernel_update direct_args=1 ;; remove-old-kernels|remove-old-kernel) # HELPCMD: remove old system kernels (exclude current or last two kernels) epm_cmd=remove_old_kernels direct_args=1 ;; # HELPCMD: PART: Other commands: clean) # HELPCMD: clean local package cache epm_cmd=clean direct_args=1 ;; restore) # HELPCMD: install (restore) packages need for the project (f.i. by requirements.txt) epm_cmd=restore ;; autoremove|package-cleanup) # HELPCMD: auto remove unneeded package(s) Supports args for ALT: [--direct [libs|python|perl|libs-devel]] epm_cmd=autoremove direct_args=1 ;; mark) # HELPCMD: mark package as manually or automatically installed (see epm mark --help) epm_cmd=mark ;; autoorphans|--orphans) # HELPCMD: remove all packages not from the repository epm_cmd=autoorphans ;; upgrade|dist-upgrade) # HELPCMD: performs upgrades of package software distributions epm_cmd=upgrade ;; Upgrade) # HELPCMD: force update package base, then run upgrade epm_cmd=Upgrade direct_args=1 ;; downgrade) # HELPCMD: downgrade [all] packages to the repo state epm_cmd=downgrade ;; download) # HELPCMD: download package(s) file to the current dir epm_cmd=download ;; # TODO: replace with install --simulate simulate) # HELPCMD: simulate install with check requires epm_cmd=simulate ;; audit) # HELPCMD: audits installed packages against known vulnerabilities epm_cmd=audit direct_args=1 ;; #checksystem) # HELPCMD: check system for known errors (package management related) # epm_cmd=checksystem # direct_args=1 # ;; site|url) # HELPCMD: open package's site in a browser (use -p for open packages.altlinux.org site) epm_cmd=site ;; ei|ik|epminstall|epm-install|selfinstall) # HELPCMD: install package(s) from Korinf (eepm by default) epm_cmd=epm_install ;; print) # HELPCMD: print various info, run epm print help for details epm_cmd=print direct_args=1 ;; repack) # HELPCMD: repack rpm to local compatibility epm_cmd=repack ;; prescription|recipe) # HELPCMD: run prescription (a script to achieving the goal), run without args to get list epm_cmd=prescription direct_args=1 ;; play) # HELPCMD: install the application from the official site (run without args to get list) epm_cmd=play direct_args=1 ;; -V|checkpkg|integrity) # HELPCMD: check package file integrity (checksum) epm_cmd=checkpkg ;; -h|--help|help) # HELPOPT: print this help help=1 phelp exit 0 ;; *) return 1 ;; esac return 0 } check_option() { case $1 in -v|--version) # HELPOPT: print version print_version exit 0 ;; --verbose) # HELPOPT: verbose mode verbose="--verbose" ;; --skip-installed) # HELPOPT: skip already installed packages during install skip_installed=1 ;; --skip-missed) # HELPOPT: skip not installed packages during remove skip_missed=1 ;; --show-command-only) # HELPOPT: show command only, do not any action (supports install and remove ONLY) show_command_only=1 ;; --quiet|--silent) # HELPOPT: quiet mode (do not print commands before exec) quiet=1 ;; --nodeps) # HELPOPT: skip dependency check (during install/simulate and so on) nodeps="--nodeps" ;; --force) # HELPOPT: force install/remove package (f.i., override) force="--force" ;; --noremove|--no-remove) # HELPOPT: exit if any packages are to be removed during upgrade noremove="--no-remove" ;; --no-stdin|--inscript) # HELPOPT: don't read from stdin for epm args inscript=1 ;; --dry-run|--simulate|--just-print|--no-act) # HELPOPT: print only (autoremove/autoorphans/remove only) dryrun="--dry-run" ;; --short) # HELPOPT: short output (just 'package' instead 'package-version-release') short="--short" ;; --direct) # HELPOPT: direct install package file from ftp (not via hilevel repository manager) direct="--direct" ;; --repack) # HELPOPT: repack rpm package(s) before install repack="--repack" ;; --scripts) # HELPOPT: include scripts in repacked rpm package(s) (see --repack or repacking when foreign package is installed) scripts="--scripts" ;; --noscripts) # HELPOPT: disable scripts in install packages noscripts="--noscripts" ;; --sort) # HELPOPT: sort output, f.i. --sort=size (supported only for packages command) # TODO: how to read arg? sort="$1" ;; --auto|--assumeyes|--non-interactive) # HELPOPT: non interactive mode non_interactive="--auto" ;; --force-yes) # HELPOPT: force yes in a danger cases (f.i., during release upgrade) force_yes="--force-yes" ;; *) return 1 ;; esac return 0 } # TODO: skip for commands where we don't need parse args check_filenames() { local opt for opt in "$@" ; do # files can be with full path or have extension via . if [ -f "$opt" ] && echo "$opt" | grep -q "[/\.]" ; then has_space "$opt" && warning "There are space(s) in filename '$opt', it is not supported. Skipped" && continue pkg_files="$pkg_files $opt" elif [ -d "$opt" ] ; then has_space "$opt" && warning "There are space(s) in directory path '$opt', it is not supported. Skipped" && continue pkg_dirs="$pkg_dirs $opt" elif echo "$opt" | grep -q "^[fhtps]*://" ; then has_space "$opt" && warning "There are space(s) in URL '$opt', it is not supported. Skipped" && continue pkg_urls="$pkg_urls $opt" else has_space "$opt" && warning "There are space(s) in package name '$opt', it is not supported. Skipped." && continue # TODO: don't add unknown options (like -y, --unknown) to pkg_names pkg_names="$pkg_names $opt" fi quoted_args="$quoted_args \"$opt\"" done } # handle external EPM_OPTIONS for opt in $EPM_OPTIONS ; do check_option "$opt" done FLAGENDOPTS= # NOTE: can't use while read here: set vars inside for opt in "$@" ; do [ "$opt" = "--" ] && FLAGENDOPTS=1 && continue if [ -z "$FLAGENDOPTS" ] ; then check_command "$opt" && continue check_option "$opt" && continue fi if [ -n "$direct_args" ] ; then quoted_args="$quoted_args \"$opt\"" else # Note: will parse all params separately (no package names with spaces!) check_filenames "$opt" fi done # fill export EPM_OPTIONS="$nodeps $force $non_interactive" # if input is not console and run script from file, get pkgs from stdin too if [ ! -n "$inscript" ] && ! inputisatty && [ -n "$PROGDIR" ] ; then for opt in $(withtimeout 10 cat) ; do # FIXME: do not work # workaround against # yes | epme [ "$opt" = "y" ] && break; [ "$opt" = "yes" ] && break; check_filenames $opt done fi pkg_files=$(strip_spaces "$pkg_files") pkg_dirs=$(strip_spaces "$pkg_dirs") # in common case dirs equals to names only suddenly pkg_names=$(strip_spaces "$pkg_names $pkg_dirs") pkg_urls=$(strip_spaces "$pkg_urls") pkg_filenames=$(strip_spaces "$pkg_files $pkg_names") # Just debug #echover "command: $epm_cmd" #echover "pkg_files=$pkg_files" #echover "pkg_names=$pkg_names" # Just printout help if run without args if [ -z "$epm_cmd" ] ; then print_version echo fatstr="Unknown command in $* arg(s)" [ -n "$*" ] || fatstr="That program needs be running with some command" echo "Run $ $PROGNAME --help to get help." >&2 echo "Run $ epm print info to get some system and distro info." >&2 fatal "$fatstr." fi # Use eatmydata for write specific operations case $epm_cmd in update|upgrade|Upgrade|install|reinstall|Install|remove|autoremove|kernel_update|release_upgrade|release_downgrade|check) set_eatmydata ;; esac [ -n "$verbose$EPM_VERBOSE" ] && showcmd "$0 $*" # Run helper for command with natural args eval epm_$epm_cmd $quoted_args # return last error code (from subroutine)