code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.operations.check as check
import inary.cli.command as command
import inary.context as ctx
import inary.util as util
import inary.db

class Check(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Verify installation

    Usage: check [<package1> <package2> ... <packagen>]
           check -c <component>

    <packagei>: package name

    A cryptographic checksum is stored for each installed
    file. Check command uses the checksums to verify a package.
    Just give the names of packages.

    If no packages are given, checks all installed packages.
    """)

    def __init__(self, args):
        super(Check, self).__init__(args)
        self.installdb = inary.db.installdb.InstallDB()
        self.componentdb = inary.db.componentdb.ComponentDB()

    name = ("check", None)

    def options(self):
        group = optparse.OptionGroup(self.parser, _("check options"))

        group.add_option("-c", "--component",
                         action="store",
                         default=None,
                         help=_("Check installed packages under "
                                "given component."))

        group.add_option("--config",
                         action="store_true",
                         default=False,
                         help=_("Checks only changed config files of "
                                "the packages."))

        self.parser.add_option_group(group)

    def run(self):
        self.init(database=True, write=False)

        component = ctx.get_option('component')
        if component:
            installed = inary.db.installdb.InstallDB().list_installed()
            component_pkgs = self.componentdb.get_union_packages(component,
                                                                 walk=True)
            pkgs = list(set(installed) & set(component_pkgs))
        elif self.args:
            pkgs = self.args
        else:
            ctx.ui.info(_('Checking all installed packages.'), color='blue')
            pkgs = inary.db.installdb.InstallDB().list_installed()
        if not pkgs:
            ctx.ui.error(_("No package has been installed yet. :("))
            exit()

        necessary_permissions = True

        # True if we should also check the configuration files
        check_config = ctx.get_option('config')

        # Line prefix
        prefix = _('Checking integrity of \"{}\".')

        # Determine maximum length of messages for proper formatting
        maxpkglen = max([len(_p) for _p in pkgs])

        for pkg in pkgs:
            if self.installdb.has_package(pkg):
                check_results = check.check(pkg, check_config)
                ctx.ui.info("{0}    {1}".format(prefix.format(pkg), (' ' * (maxpkglen - len(pkg)))), noln=True)

                if check_results['missing'] or check_results['corrupted'] \
                        or check_results['config']:
                    ctx.ui.info(_("Broken"), color='brightred')
                elif check_results['denied']:
                    # We can't deduce a result when some files
                    # can't be accessed
                    necessary_permissions = False
                    ctx.ui.info(_("Unknown"), color='yellow')
                else:
                    ctx.ui.info(_("OK"), color='green')
                    continue

                # Dump per file stuff
                for fpath in check_results['missing']:
                    ctx.ui.info(_("Missing file: \"/{}\"").format(fpath), color='brightred')

                for fpath in check_results['denied']:
                    ctx.ui.info(_("Access denied: \"/{}\"").format(fpath), color='yellow')

                for fpath in check_results['corrupted']:
                    ctx.ui.info(_("Corrupted file: \"/{}\"").format(fpath), color='brightyellow')

                for fpath in check_results['config']:
                    ctx.ui.info(_("Modified configuration file: \"/{}\"").format(fpath),
                                color='brightyellow')

            else:
                # Package is not installed
                ctx.ui.info(_('Package \"{}\" not installed.').format(pkg))

        if not necessary_permissions:
            ctx.ui.info("")
            ctx.ui.warning(_("Inary was unable to check the integrity of "
                             "packages which contain files that you don't "
                             "have read access.\n"
                             "Running the check under a privileged user "
                             "may help fixing this problem."))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import os
import sys
import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.api
import inary.util as util
import inary.context as ctx

class autocommand(type):
    def __init__(cls, name, bases, dict):
        super(autocommand, cls).__init__(name, bases, dict)
        Command.cmd.append(cls)
        name = getattr(cls, 'name', None)
        if name is None:
            raise inary.cli.Error(_('Command lacks name.'))
        longname, shortname = name

        def add_cmd(cmd):
            if cmd in Command.cmd_dict:
                raise inary.cli.Error(_('Duplicate command \'{}\'').format(cmd))
            else:
                Command.cmd_dict[cmd] = cls

        add_cmd(longname)
        if shortname:
            add_cmd(shortname)

class Command(object):
    """generic help string for any command"""

    # class variables

    cmd = []
    cmd_dict = {}

    @staticmethod
    def commands_string():
        s = ''
        l = [x.name[0] for x in Command.cmd]
        l.sort()
        for name in l:
            commandcls = Command.cmd_dict[name]
            trans = gettext.translation('inary', fallback=True)
            summary = trans.gettext(commandcls.__doc__).split('\n')[0]
            name = commandcls.name[0]
            if commandcls.name[1]:
                name += ' ({})'.format(commandcls.name[1])
            s += util.colorize(' %23s ' % name, 'blue') + '- %s\n' % summary
        return s

    @staticmethod
    def get_command(cmd, fail=False, args=None):

        if cmd in Command.cmd_dict:
            return Command.cmd_dict[cmd](args)

        if fail:
            raise inary.cli.Error(_("Unrecognized command: \'{}\'").format(cmd))
        else:
            return None

    # instance variabes

    def __init__(self, args=None):
        # now for the real parser
        import inary
        self.scom = False
        self.parser = optparse.OptionParser(usage=getattr(self, "__doc__"),
                                            version="%prog " + inary.__version__,
                                            formatter=InaryHelpFormatter())
        self.options()
        self.commonopts()
        (self.options, self.args) = self.parser.parse_args(args)
        if self.args:
            self.args.pop(0)  # exclude command arg

        self.process_opts()

    def commonopts(self):
        """common options"""
        p = self.parser

        group = optparse.OptionGroup(self.parser, _("general options"))

        group.add_option("-D", "--destdir", action="store", default=None,
                         help=_("Change the system root for INARY commands."))
        group.add_option("-y", "--yes-all", action="store_true",
                         default=False, help=_("Assume yes in all yes/no queries."))
        group.add_option("-u", "--username", action="store")
        group.add_option("-p", "--password", action="store")
        group.add_option("-L", "--bandwidth-limit", action="store", default=0,
                         help=_("Keep bandwidth usage under specified KB's."))
        group.add_option("-v", "--verbose", action="store_true",
                         dest="verbose", default=False,
                         help=_("Detailed output"))
        group.add_option("-d", "--debug", action="store_true",
                         default=False, help=_("Show debugging information."))
        group.add_option("-N", "--no-color", action="store_true", default=False,
                         help=_("Suppresses all coloring of INARY's output."))

        p.add_option_group(group)

        return p

    def options(self):
        """This is a fall back function. If the implementer module provides an
        options function it will be called"""
        pass

    def process_opts(self):
        self.check_auth_info()

        # make destdir absolute
        if self.options.destdir:
            d = str(self.options.destdir)
            if not os.path.exists(d):
                inary.cli.printu(_('Destination directory \"{}\" does not exist. Creating directory.\n').format(d))
                os.makedirs(d)
            self.options.destdir = os.path.realpath(d)

    def check_auth_info(self):
        username = self.options.username
        password = self.options.password

        # TODO: We'll get the username, password pair from a configuration
        # file from users home directory. Currently we need user to
        # give it from the user interface.
        #         if not username and not password:
        #             if someauthconfig.username and someauthconfig.password:
        #                 self.authInfo = (someauthconfig.username,
        #                                  someauthconfig.password)
        #                 return
        if username and password:
            self.options.authinfo = (username, password)
            return

        if username and not password:
            from getpass import getpass
            password = getpass(_("Password: "))
            self.options.authinfo = (username, password)
        else:
            self.options.authinfo = None

    def init(self, database=True, write=True, locked=False):
        """initialize INARY components"""

        if self.options:
            ui = inary.cli.CLI(self.options.debug, self.options.verbose)
        else:
            ui = inary.cli.CLI()

        if (write and not os.access(inary.context.config.packages_dir(), os.W_OK) or
                ('sf' == self.get_name() or 'cp' == self.get_name() and not os.access(
                    os.path.join(ctx.config.info_dir(), ctx.const.files_db), os.W_OK))):
            raise inary.cli.Error(_("You have to be root for this operation."))

        inary.api.set_scom(self.scom and not ctx.get_option('ignore_scom'))
        inary.api.set_userinterface(ui)
        inary.api.set_options(self.options)

    def get_name(self):
        return self.__class__.name

    def format_name(self):
        (name, shortname) = self.get_name()
        if shortname:
            return "{0} ({1})".format(name, shortname)
        else:
            return name

    def help(self):
        """print help for the command"""
        trans = gettext.translation('inary', fallback=True)
        print("{0}: {1}".format(self.format_name(), trans.gettext(self.__doc__)))
        print(self.parser.format_option_help())

    @staticmethod
    def die():
        """exit program"""
        ctx.ui.error(_('Command terminated abnormally.'))
        util.noecho(False)
        sys.exit(-1)

class PackageOp(Command):
    """Abstract package operation command"""

    def __init__(self, args):
        super(PackageOp, self).__init__(args)
        self.scom = True

    def options(self, group):
        group.add_option("--ignore-dependency", action="store_true",
                         default=False,
                         help=_("Do not take dependency information into account."))
        group.add_option("--ignore-safety", action="store_true",
                         default=False, help=_("Bypass safety switch."))
        group.add_option("--ignore-scom", action="store_true",
                         default=False, help=_("Bypass scom configuration agent."))
        group.add_option("-n", "--dry-run", action="store_true", default=False,
                         help=_("Do not perform any action, just show what would be done."))

    def init(self, database=True, write=True):
        super(PackageOp, self).init(database, write)

class InaryHelpFormatter(optparse.HelpFormatter):
    def __init__(self,
                 indent_increment=1,
                 max_help_position=32,
                 width=None,
                 short_first=1):
        optparse.HelpFormatter.__init__(
            self, indent_increment, max_help_position, width, short_first)

        self._short_opt_fmt = "{}"
        self._long_opt_fmt = "{}"

    def format_usage(self, usage):
        return _("usage: {}\n").format(usage)

    def format_heading(self, heading):
        return "%*s%s:\n" % (self.current_indent, "", heading)

    def format_option_strings(self, option):
        """Return a comma-separated list of option strings & metavariables."""
        if option.takes_value():
            short_opts = [self._short_opt_fmt.format(sopt)
                          for sopt in option._short_opts]
            long_opts = [self._long_opt_fmt.format(lopt)
                         for lopt in option._long_opts]
        else:
            short_opts = option._short_opts
            long_opts = option._long_opts

        if long_opts and short_opts:
            opt = "{0} [{1}]".format(short_opts[0], long_opts[0])
        else:
            opt = long_opts[0] or short_opts[0]

        if option.takes_value():
            opt += " arg"

        return opt

    def format_option(self, option):
        import textwrap
        result = []
        opts = self.option_strings[option]
        opt_width = self.help_position - self.current_indent - 2
        if len(opts) > opt_width:
            opts = "%*s%s\n" % (self.current_indent, "", opts)
            indent_first = self.help_position
        else:  # start help on same line as opts
            opts = "%*s%-*s  " % (self.current_indent, "", opt_width, opts)
            indent_first = 0
        result.append(opts)
        if option.help:
            help_text = self.expand_default(option)
            help_lines = textwrap.wrap(help_text, self.help_width)
            result.append(": %*s%s\n" % (indent_first, "", help_lines[0]))
            result.extend(["  %*s%s\n" % (self.help_position, "", line)
                           for line in help_lines[1:]])
        elif opts[-1] != "\n":
            result.append("\n")
        return "".join(result)

repo_name: SulinOS/inary

license: mit


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.util as util
import inary.cli.command as command
import inary.ui
import inary.data
import inary.errors
import inary.context as ctx
import inary.reactor

def configure_pending(packages=None):
    # Import SCOM

    # start with pending packages
    # configure them in reverse topological order of dependency
    installdb = inary.db.installdb.InstallDB()
    if not packages:
        packages = installdb.list_pending()
    else:
        packages = set(packages).intersection(installdb.list_pending())

    order = inary.data.pgraph.generate_pending_order(packages)
    try:
        for x in order:
            if installdb.has_package(x):
                pkginfo = installdb.get_package(x)
                pkg_path = installdb.package_path(x)
                m = inary.data.metadata.MetaData()
                metadata_path = util.join_path(pkg_path, ctx.const.metadata_xml)
                m.read(metadata_path)
                # FIXME: we need a full package info here!
                pkginfo.name = x
                ctx.ui.notify(inary.ui.configuring, package=pkginfo, files=None)
                inary.reactor.post_install(
                    pkginfo.name,
                    m.package.providesScom,
                    util.join_path(pkg_path, ctx.const.scom_dir),
                    util.join_path(pkg_path, ctx.const.metadata_xml),
                    util.join_path(pkg_path, ctx.const.files_xml),
                    None,
                    None,
                    m.package.version,
                    m.package.release
                )
                ctx.ui.notify(inary.ui.configured, package=pkginfo, files=None)
            installdb.clear_pending(x)
    except ImportError:
        raise inary.errors.Error(_("scom package is not fully installed."))

class ConfigurePending(command.PackageOp, metaclass=command.autocommand):
    __doc__ = _("""Configure pending packages

If SCOM configuration of some packages were not
done at installation time, they are added to a list
of packages waiting to be configured. This command
configures those packages.
""")

    def __init__(self, args):
        super(ConfigurePending, self).__init__(args)

    name = ("configure-pending", "cp")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("configure-pending options"))
        super(ConfigurePending, self).options(group)
        self.parser.add_option_group(group)

    def run(self):
        self.init(database=True, write=False)
        configure_pending(self.args)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import os
import inary.util as util
import inary.context as ctx
import inary.cli.command as command

class DeleteCache(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Delete cache files

Usage: delete-cache

Sources, packages and temporary files are stored
under /var directory. Since these accumulate they can
consume a lot of disk space.""")

    def __init__(self, args=None):
        super(DeleteCache, self).__init__(args)

    name = ("delete-cache", "dc")

    def run(self):
        self.init(database=False, write=True)
        self.delete_cache()

    @staticmethod
    def delete_cache():
        """
        Deletes cached packages, cached archives, build dirs, db caches
        """
        ctx.ui.info(_("Cleaning package cache \"{}\"...").format(ctx.config.cached_packages_dir()))
        util.clean_dir(ctx.config.cached_packages_dir())
        ctx.ui.info(_("Cleaning source archive cache \"{}\"...").format(ctx.config.archives_dir()))
        util.clean_dir(ctx.config.archives_dir())
        ctx.ui.info(_("Cleaning temporary directory \"{}\"...").format(ctx.config.tmp_dir()))
        util.clean_dir(ctx.config.tmp_dir())
        for cache in [x for x in os.listdir(ctx.config.cache_root_dir()) if x.endswith(".cache")]:
            cache_file = util.join_path(ctx.config.cache_root_dir(), cache)
            ctx.ui.info(_("Removing cache file \"{}\"...").format(cache_file))
            os.unlink(cache_file)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.package
import inary.operations

usage = _("""Creates delta packages

Usages: delta oldpackage1 oldpackage2 ...  newpackage
        delta -t newpackage oldpackage1 oldpackage2 ...

Delta command finds the changed files between the given
packages by comparing the sha1sum of files and creates
a delta package with the changed files.
""")

class Delta(command.Command, metaclass=command.autocommand):
    __doc__ = usage

    def __init__(self, args):
        super(Delta, self).__init__(args)

    name = ("delta", "dt")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("delta options"))

        group.add_option("-t", "--newest-package",
                         action="store",
                         default=None,
                         help=_("Use arg as the new package and treat "
                                "other arguments as old packages."))

        group.add_option("-O", "--output-dir",
                         action="store",
                         default=None,
                         help=_("Output directory for produced packages."))

        group.add_option("-F", "--package-format",
                         action="store",
                         help=_("Create the binary package using the given "
                                "format. Use '-F help' to see a list of "
                                "supported formats."))
        self.parser.add_option_group(group)

    def run(self):
        self.init(database=False, write=False)

        if self.options.package_format == "help":
            ctx.ui.info(_("Supported package formats:"))
            for format in inary.package.Package.formats:
                if format == inary.package.Package.default_format:
                    ctx.ui.info(_("  {} (default)").format(format))
                else:
                    ctx.ui.info("  {}".format(format))
            return

        new_package = ctx.get_option("newest_package")
        if new_package:
            old_packages = self.args
        else:
            if len(self.args) < 2:
                self.help()
                return

            new_package = self.args[-1]
            old_packages = self.args[:-1]

        if not ctx.get_option('output_dir'):
            ctx.config.options.output_dir = '.'

        from inary.operations.delta import create_delta_packages
        create_delta_packages(old_packages, new_package)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C)  2017 - 2018,  Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.db
import inary.cli.command as command
import inary.operations.repository as repository

class DisableRepo(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Disable repository

Usage: disable-repo [<repo1> <repo2> ... <repon>]

<repoi>: repository name

Disabled repositories are not taken into account in operations
""")

    def __init__(self, args):
        super(DisableRepo, self).__init__(args)
        self.repodb = inary.db.repodb.RepoDB()

    name = ("disable-repo", "dr")

    def run(self):
        self.init(database=True)

        if not self.args:
            self.help()
            return

        for repo in self.args:
            if self.repodb.has_repo(repo):
                repository.set_repo_activity(repo, False)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.db
import inary.cli.command as command
import inary.cli.build as build
import inary.context as ctx
import inary.operations.emerge as emerge

class Emerge(build.Build, metaclass=command.autocommand):
    __doc__ = _("""Build and install INARY source packages from repository

Usage: emerge <sourcename> ...

You should give the name of a source package to be
downloaded from a repository containing sources.

You can also give the name of a component.
""")

    def __init__(self, args):
        super(Emerge, self).__init__(args)
        self.scom = True

    name = ("emerge", "em")

    def options(self):

        group = optparse.OptionGroup(self.parser, _("emerge options"))
        group.add_option("-c", "--component", action="store",
                         default=None, help=_("Emerge available packages under given component"))
        group.add_option("--ignore-file-conflicts", action="store_true",
                         default=False, help=_("Ignore file conflicts."))
        group.add_option("--ignore-package-conflicts", action="store_true",
                         default=False, help=_("Ignore package conflicts."))
        group.add_option("--ignore-scom", action="store_true",
                         default=False, help=_("Bypass scom configuration agent."))
        self.parser.add_option_group(group)

    def run(self):
        self.init(database=True)

        component = ctx.get_option('component')
        if not self.args and not component:
            self.help()
            return

        if component:
            componentdb = inary.db.componentdb.ComponentDB()
            sources = componentdb.get_union_sources(component, walk=True)
        else:
            sources = self.args

        if ctx.get_option('output_dir'):
            ctx.ui.info(_('Output directory: {}').format(ctx.config.options.output_dir))
        else:
            ctx.ui.info(_('Outputting binary packages in the package cache.'))
            ctx.config.options.output_dir = ctx.config.cached_packages_dir()

        emerge.emerge(sources)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.cli.build as build
import inary.context as ctx
import inary.db
from inary.operations import repository, emerge

class EmergeUp(build.Build, metaclass=command.autocommand):
    __doc__ = _("""Build and upgrade INARY source packages from repository

Usage: emergeup ...

You should give the name of a source package to be
downloaded from a repository containing sources.

You can also give the name of a component.
""")

    def __init__(self, args):
        super(EmergeUp, self).__init__(args)
        self.scom = True

    name = ("emergeup", "emup")

    def options(self):

        group = optparse.OptionGroup(self.parser, _("emergeup options"))
        group.add_option("-c", "--component", action="store",
                         default=None, help=_("Emerge available packages under given component"))
        group.add_option("--ignore-file-conflicts", action="store_true",
                         default=False, help=_("Ignore file conflicts."))
        group.add_option("--ignore-package-conflicts", action="store_true",
                         default=False, help=_("Ignore package conflicts."))
        group.add_option("--ignore-scom", action="store_true",
                         default=False, help=_("Bypass scom configuration agent."))
        self.parser.add_option_group(group)

    def run(self):
        self.init(database=True)

        source = inary.db.sourcedb.SourceDB()

        imdb = inary.db.installdb.InstallDB()

        installed_emerge_packages = imdb.list_installed_with_build_host("localhost")

        emerge_up_list = []

        for package in installed_emerge_packages:
            if source.has_spec(package):
                spec = source.get_spec(package)
                if spec.getSourceRelease() > imdb.get_version(package)[1]:
                    emerge_up_list.append(package)

        if ctx.get_option('output_dir'):
            ctx.ui.info(_('Output directory: {}').format(ctx.config.options.output_dir))
        else:
            ctx.ui.info(_('Outputting binary packages in the package cache.'))
            ctx.config.options.output_dir = ctx.config.cached_packages_dir()

        repos = inary.db.repodb.RepoDB().list_repos(only_active=True)
        repository.update_repos(repos, ctx.get_option('force'))

        emerge.emerge(emerge_up_list)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C)  2017 - 2018,  Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.db
import inary.cli.command as command
from inary.operations import repository

class EnableRepo(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Enable repository

Usage: enable-repo [<repo1> <repo2> ... <repon>]

<repoi>: repository name

Disabled repositories are not taken into account in operations
""")

    def __init__(self, args):
        super(EnableRepo, self).__init__(args)
        self.repodb = inary.db.repodb.RepoDB()

    name = ("enable-repo", "er")

    def run(self):
        self.init(database=True)

        if not self.args:
            self.help()
            return

        for repo in self.args:
            if self.repodb.has_repo(repo):
                repository.set_repo_activity(repo, True)


code:
# -*- coding:utf-8 -*-
#
# Copyright (C)  2017 - 2018,  Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse
import os

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.db
import inary.fetcher as fetcher

class Fetch(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Fetch a package

Usage: fetch [<package1> <package2> ... <packagen>]

<packagei>: package name

Downloads the given inary packages to working directory
""")

    def __init__(self, args):
        super(Fetch, self).__init__(args)

    name = ("fetch", "fc")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("fetch options"))

        group.add_option("-o", "--output-dir", action="store", default=os.path.curdir,
                         help=_("Output directory for the fetched packages"))
        group.add_option("--runtime-deps", action="store_true", default=None,
                         help=_("Download with runtime dependencies."))

        self.parser.add_option_group(group)

    def run(self):
        packages = inary.db.packagedb.PackageDB()
        self.init(database=False, write=False)

        if not self.args:
            self.help()
            return

        full_packages = []

        for inary_package in self.args:
            package = packages.get_package(inary_package)
            full_packages.append(inary_package)
            if ctx.config.options.runtime_deps:
                for dep in package.runtimeDependencies():
                    full_packages.append(dep.name())

        fetcher.fetch(full_packages, ctx.config.options.output_dir)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.db
import inary.data.pgraph as pgraph

class Graph(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Graph package relations

Usage: graph [<package1> <package2> ...]

Write a graph of package relations, tracking dependency and
conflicts relations starting from given packages. By default
shows the package relations among repository packages, and writes
the package in graphviz format to 'pgraph.dot'.
""")

    def __init__(self, args=None):
        super(Graph, self).__init__(args)

    def options(self):

        group = optparse.OptionGroup(self.parser, _("graph options"))

        group.add_option("-r", "--repository", action="store",
                         default=None,
                         help=_("Specify a particular repository."))
        group.add_option("-i", "--installed", action="store_true",
                         default=False,
                         help=_("Graph of installed packages"))
        group.add_option("--ignore-installed", action="store_true",
                         default=False,
                         help=_("Do not show installed packages."))
        group.add_option("-R", "--reverse", action="store_true",
                         default=False,
                         help=_("Draw reverse dependency graph."))
        group.add_option("-o", "--output", action="store",
                         default='pgraph.dot',
                         help=_("Dot output file"))

        self.parser.add_option_group(group)

    name = ("graph", None)

    def run(self):
        self.init(write=False)
        if not ctx.get_option('installed'):
            # Graph from package database
            packagedb = inary.db.packagedb.PackageDB()

            if ctx.get_option('repository'):
                repo = ctx.get_option('repository')
                ctx.ui.info(_('Plotting packages in repository \"{}\"').format(repo))
            else:
                repo = None
                ctx.ui.info(_('Plotting a graph of relations among all repository packages.'))

            if self.args:
                a = self.args
            else:
                a = packagedb.list_packages(repo)

        else:
            # Graph from installed packages database
            packagedb = inary.db.installdb.InstallDB()

            if self.args:
                a = self.args
            else:
                # if A is empty, then graph all packages
                ctx.ui.info(_('Plotting a graph of relations among all installed packages.'))
                a = inary.db.installdb.InstallDB().list_installed()

        g = pgraph.package_graph(a, packagedb,
                                 ignore_installed=ctx.get_option('ignore_installed'), reverse=ctx.get_option('reverse'))
        g.write_graphviz(open(ctx.get_option('output'), 'w'))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli
import inary.cli.command as command
import inary.context as ctx

class Help(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Prints help for given commands

Usage: help [ <command1> <command2> ... <commandn> ]

If run without parameters, it prints the general help.""")

    def __init__(self, args=None):
        super(Help, self).__init__(args)

    name = ("help", "?")

    def run(self):

        if not self.args:
            self.parser.set_usage(usage_text)
            inary.cli.printu(self.parser.format_help())
            return

        self.init(database=False, write=False)

        for arg in self.args:
            obj = command.Command.get_command(arg, True)
            obj.help()
            ctx.ui.info('')

usage_text1 = _("""%prog [options] <command> [arguments]

where <command> is one of:

""")

usage_text2 = _("""
Use \"%prog help <command>\" for help on a specific command.
""")

usage_text = (usage_text1 + command.Command.commands_string() + usage_text2)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse
import os
import sys

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

from inary.operations import history
import inary.db
import inary.context as ctx
import inary.util as util
import inary.cli.command as command

# Operation names for translation
opttrans = {"upgrade": _("upgrade"), "remove": _("remove"), "emerge": _("emerge"), "install": _("install"),
            "snapshot": _("snapshot"), "takeback": _("takeback"), "repoupdate": _("repository update")}

class History(command.PackageOp, metaclass=command.autocommand):
    __doc__ = _("""History of inary operations

Usage: history

Lists previous operations.""")

    def __init__(self, args=None):
        super(History, self).__init__(args)
        self.historydb = inary.db.historydb.HistoryDB()

    name = ("history", "hs")

    def options(self):

        group = optparse.OptionGroup(self.parser, _("history options"))

        group.add_option("-l", "--last", action="store", type="int", default=0,
                         help=_("Output only the last \'n\' operations."))
        group.add_option("-s", "--snapshot", action="store_true", default=False,
                         help=_("Take snapshot of the current system."))
        group.add_option("-t", "--takeback", action="store", type="int", default=-1,
                         help=_("Takeback to the state after the given operation finished."))

        self.parser.add_option_group(group)

    @staticmethod
    def take_snapshot():
        history.snapshot()

    @staticmethod
    def takeback(operation):
        history.takeback(operation)

    def print_history(self):
        ordered_history = []
        ordered_history.append(_("Inary Transaction History: "))
        for operation in self.historydb.get_last(ctx.get_option('last')):

            msg_oprt = util.colorize(_("Operation "), 'yellow') \
                       + util.colorize("#{}: ".format(operation.no), "blue") \
                       + util.colorize("{}:".format(opttrans[operation.type]), "white")

            date_and_time = util.colorize(_("Date: "), "cyan") + "{0.date} {0.time}".format(operation)
            ordered_history.append(msg_oprt)
            ordered_history.append(date_and_time)

            if operation.type == "snapshot":
                msg_snap = util.colorize(
                    _("    * There are {} packages in this snapshot.").format(len(operation.packages)),
                    "purple")

                ordered_history.append(msg_snap)
            elif operation.type == "repoupdate":
                for repo in operation.repos:
                    ordered_history.append("    * " + repo.name)
            else:
                for pkg in operation.packages:
                    ordered_history.append("    * " + pkg.name)
        return ordered_history

    def redirect_output(self, order):
    #    if os.isatty(sys.stdout.fileno()):
        class LessException(Exception):
            pass

        class LessPipe():
            def __init__(self):
                import subprocess
                self.less = subprocess.Popen(["less", "-K", "-R", "-"],
                                             stdin=subprocess.PIPE)

            def close(self):
                self.less.stdin.close()
                self.less.wait()
                self.less.kill()

            def flush(self):
                self.less.stdin.flush()

            def write(self, s):
                try:
                    self.less.stdin.write(bytes(s.encode("utf-8")))
                except IOError:
                    raise LessException

        pipe=LessPipe()

        try:
            for i in order:
                pipe.write(i)
                pipe.write("\n")
            pipe.close()
        except LessException:
            pass

    def run(self):
        self.init(database=False, write=False)
        if ctx.get_option('snapshot'):
            self.take_snapshot()
            return
        elif ctx.get_option('takeback'):
            opno = ctx.get_option('takeback')
            if opno != -1:
                self.takeback(opno)
                return

        self.redirect_output(self.print_history())


code:
# -*- coding: utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import sys
import optparse
import sys

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary
import inary.errors

import inary.cli
import inary.cli.command as command
import inary.cli.addrepo
import inary.cli.blame
import inary.cli.build
import inary.cli.check
import inary.cli.configurepending
import inary.cli.deletecache
import inary.cli.delta
import inary.cli.emerge
import inary.cli.emergeup
import inary.cli.fetch
import inary.cli.graph
import inary.cli.index
import inary.cli.info
import inary.cli.install
import inary.cli.history
import inary.cli.listnewest
import inary.cli.listavailable
import inary.cli.listcomponents
import inary.cli.listinstalled
import inary.cli.listorphaned
import inary.cli.listpending
import inary.cli.listrepo
import inary.cli.listsources
import inary.cli.listupgrades
import inary.cli.rebuilddb
import inary.cli.reconfigure
import inary.cli.remove
import inary.cli.removerepo
import inary.cli.removeorphaned
import inary.cli.enablerepo
import inary.cli.disablerepo
import inary.cli.searchfile
import inary.cli.search
import inary.cli.updaterepo
import inary.cli.upgrade

# FIXME: why does this has to be imported last
import inary.cli.help

class ParserError(inary.errors.Exception):
    pass

class PreParser(optparse.OptionParser):
    """consumes any options, and finds arguments from command line"""

    def __init__(self, version):
        optparse.OptionParser.__init__(self, usage=inary.cli.help.usage_text, version=version)

    def error(self, msg):
        raise ParserError(msg)

    def parse_args(self, args=None):
        self.opts = []
        self.rargs = self._get_args(args)
        self._process_args()
        return self.opts, self.args

    def _process_args(self):
        args = []
        rargs = self.rargs
        if not self.allow_interspersed_args:
            first_arg = False
        while rargs:
            arg = rargs[0]

            def option():
                if not self.allow_interspersed_args and first_arg:
                    self.error(_('Options must precede non-option arguments.'))
                arg = rargs[0]
                if arg.startswith('--'):
                    self.opts.append(arg[2:])
                else:
                    self.opts.append(arg[1:])
                del rargs[0]
                return

            # We handle bare "--" explicitly, and bare "-" is handled by the
            # standard arg handler since the short arg case ensures that the
            # len of the opt string is greater than 1.
            if arg == "--":
                del rargs[0]
                break
            elif arg[0:2] == "--":
                # process a single long option (possibly with value(s))
                option()
            elif arg[:1] == "-" and len(arg) > 1:
                # process a cluster of short options (possibly with
                # value(s) for the last one only)
                option()
            else:  # then it must be an argument
                args.append(arg)
                del rargs[0]
        self.args = args

class InaryCLI(object):

    def __init__(self, orig_args=None):
        # first construct a parser for common options
        # this is really dummy

        self.parser = PreParser(version="%prog " + inary.__version__)
        try:
            opts, args = self.parser.parse_args(args=orig_args)
            if len(args) == 0:  # more explicit than using IndexError
                if 'version' in opts:
                    self.parser.print_version()
                    sys.exit(0)
                elif 'help' in opts or 'h' in opts:
                    self.die()
                raise inary.cli.Error(_('No command given.'))
            cmd_name = args[0]
        except ParserError:
            raise inary.cli.Error(_('Command line parsing error.'))

        self.command = command.Command.get_command(cmd_name, args=orig_args)
        if not self.command:
            raise inary.cli.Error(_("Unrecognized command: {}").format(cmd_name))

    def die(self):
        inary.cli.printu('\n' + self.parser.format_help())
        sys.exit(1)

    def run_command(self):
        self.command.run()


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.data.index as index
import inary.util as util

usage = _("""Index INARY files in a given directory

Usage: index <directory> ...

This command searches for all INARY files in a directory, collects INARY
tags from them and accumulates the information in an output XML file,
named by default 'inary-index.xml'. In particular, it indexes both
source and binary packages.

If you give multiple directories, the command still works, but puts
everything in a single index file.
""")

class Index(command.Command, metaclass=command.autocommand):
    __doc__ = usage

    def __init__(self, args):
        super(Index, self).__init__(args)

    name = ("index", "ix")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("index options"))

        group.add_option("-a", "--absolute-urls",
                         action="store_true",
                         default=False,
                         help=_("Store absolute links for indexed files."))

        group.add_option("-o", "--output",
                         action="store",
                         default='inary-index.xml',
                         help=_("Index output file"))

        group.add_option("--compression-types",
                         action="store",
                         default="xz",
                         help=_("Comma-separated compression types "
                                "for index file"))

        group.add_option("--skip-sources",
                         action="store_true",
                         default=False,
                         help=_("Do not index INARY spec files."))

        group.add_option("--skip-signing",
                         action="store_true",
                         default=False,
                         help=_("Do not sign index."))

        self.parser.add_option_group(group)

    def run(self):
        self.init(database=True, write=False)

        from inary.file import File

        ctypes = {"bz2": File.COMPRESSION_TYPE_BZ2,
                  "xz": File.COMPRESSION_TYPE_XZ}
        compression = 0
        for type_str in ctx.get_option("compression_types").split(","):
            compression |= ctypes.get(type_str, 0)

        util.xterm_title(_("Taking inary repo index."))
        index.index(self.args or ["."], ctx.get_option('output'),
                    skip_sources=ctx.get_option('skip_sources'),
                    skip_signing=ctx.get_option('skip_signing'),
                    compression=compression)
        util.xterm_title_reset()


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.util as util
import inary.db
import inary.operations.info as info_operation

class Info(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Display package information

Usage: info <package1> <package2> ... <packagen>

<packagei> is either a package name or a .inary file,
""")

    def __init__(self, args):
        super(Info, self).__init__(args)
        self.installdb = inary.db.installdb.InstallDB()
        self.componentdb = inary.db.componentdb.ComponentDB()
        self.packagedb = inary.db.packagedb.PackageDB()
        self.sourcedb = inary.db.sourcedb.SourceDB()

    name = ("info", None)

    def options(self):

        group = optparse.OptionGroup(self.parser, _("info options"))

        group.add_option("-f", "--files", action="store_true",
                         default=False,
                         help=_("Show a list of package files."))
        group.add_option("-c", "--component", action="append",
                         default=None, help=_("Info about the given component."))
        group.add_option("-F", "--files-path", action="store_true",
                         default=False,
                         help=_("Show only paths."))
        group.add_option("-s", "--short", action="store_true",
                         default=False, help=_("Do not show details."))
        group.add_option("--xml", action="store_true",
                         default=False, help=_("Output in xml format."))
        self.parser.add_option_group(group)

    def run(self):

        self.init(database=True, write=False)

        components = ctx.get_option('component')
        if not components and not self.args:
            self.help()
            return

        index = inary.data.index.Index()
        index.distribution = None

        # info of components
        if components:
            for name in components:
                if self.componentdb.has_component(name):
                    component = self.componentdb.get_union_component(name)
                    if self.options.xml:
                        index.add_component(component)
                    else:
                        if not self.options.short:
                            ctx.ui.info(str(component))
                        else:
                            ctx.ui.info("{0.name} - {0.summary}".format(component))

        # info of packages
        for arg in self.args:
            if self.options.xml:
                index.packages.append(info_operation.info(arg)[0].package)
            else:
                self.info_package(arg)

        if self.options.xml:
            import sys
            errs = []
            index.newDocument()
            index.encode(index.rootNode(), errs)
            index.writexmlfile(sys.stdout)
            sys.stdout.write('\n')

    def info_package(self, arg):

        if arg.endswith(ctx.const.package_suffix):
            self.inaryfile_info(arg)
            return

        self.installdb_info(arg)
        self.packagedb_info(arg)
        self.sourcedb_info(arg)

    def print_files(self, files):
        files.list.sort(key=lambda x: x.path)
        for fileinfo in files.list:
            if self.options.files:
                print(fileinfo)
            else:
                print("/" + fileinfo.path)

    @staticmethod
    def print_metadata(metadata, packagedb=None):
        if ctx.get_option('short'):
            pkg = metadata.package
            ctx.ui.formatted_output(" - ".join((pkg.name, str(pkg.summary))))
        else:
            ctx.ui.formatted_output(str(metadata.package))
            if packagedb:
                revdeps = [name for name, dep in packagedb.get_rev_deps(metadata.package.name)]
                ctx.ui.formatted_output(" ".join((_("Reverse Dependencies:"), util.strlist(revdeps))))
                print()

    @staticmethod
    def print_specdata(spec, sourcedb=None):
        src = spec.source
        if ctx.get_option('short'):
            ctx.ui.formatted_output(" - ".join((src.name, str(src.summary))))
        else:
            ctx.ui.formatted_output(str(spec))
            if sourcedb:
                revdeps = [name for name, dep in sourcedb.get_rev_deps(spec.source.name)]
                print(_('Reverse Build Dependencies:'), util.strlist(revdeps))
                print()

    def inaryfile_info(self, package):
        metadata, files = info_operation.info_file(package)
        ctx.ui.formatted_output(_("Package file: \"{}\"").format(package))

        self.print_metadata(metadata)
        if self.options.files or self.options.files_path:
            self.print_files(files)

    def installdb_info(self, package):
        if self.installdb.has_package(package):
            metadata, files, repo = info_operation.info_name(package, True)

            if self.options.files or self.options.files_path:
                self.print_files(files)
                return

            if self.options.short:
                ctx.ui.formatted_output(_("[inst] "), noln=True, column=" ")
            else:
                ctx.ui.info(_('Installed package:'))

            self.print_metadata(metadata, self.installdb)
        else:
            ctx.ui.info(_("\"{}\" package is not installed.").format(package))

    def packagedb_info(self, package):
        if self.packagedb.has_package(package):
            metadata, files, repo = info_operation.info_name(package, False)
            if self.options.short:
                ctx.ui.formatted_output(_("[binary] "), noln=True, column=" ")
            else:
                ctx.ui.info(_('Package found in \"{}\" repository:').format(repo))
            self.print_metadata(metadata, self.packagedb)
        else:
            ctx.ui.info(_("\"{}\" package is not found in binary repositories.").format(package))

    def sourcedb_info(self, package):
        if self.sourcedb.has_spec(package):
            repo = self.sourcedb.which_repo(package)
            spec = self.sourcedb.get_spec(package)
            if self.options.short:
                ctx.ui.formatted_output(_("[source] "), noln=True, column=" ")
            else:
                ctx.ui.info(_('Package found in \"{}\" repository:').format(repo))
            self.print_specdata(spec, self.sourcedb)
        else:
            ctx.ui.info(_("\"{}\" package is not found in source repositories.").format(package))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
from inary.operations import install, helper
import inary.db
import inary.util as util

class Install(command.PackageOp, metaclass=command.autocommand):
    __doc__ = _("""Install INARY packages

Usage: install <package1> <package2> ... <packagen>

You may use filenames, URI's or package names for packages. If you have
specified a package name, it should exist in a specified repository.

You can also specify components instead of package names, which will be
expanded to package names.
""")

    def __init__(self, args):
        super(Install, self).__init__(args)
        self.componentdb = inary.db.componentdb.ComponentDB()

    name = "install", "it"

    def options(self):
        group = optparse.OptionGroup(self.parser, _("install options"))

        super(Install, self).options(group)

        group.add_option("--reinstall", action="store_true",
                         default=False, help=_("Reinstall already installed packages."))
        group.add_option("--ignore-check", action="store_true",
                         default=False, help=_("Skip distribution release and architecture check."))
        group.add_option("--ignore-file-conflicts", action="store_true",
                         default=False, help=_("Ignore file conflicts."))
        group.add_option("--ignore-package-conflicts", action="store_true",
                         default=False, help=_("Ignore package conflicts."))
        group.add_option("-c", "--component", action="append",
                         default=None, help=_("Install component's and recursive components' packages."))
        group.add_option("-r", "--repository", action="store",
                         type="string", default=None, help=_('Name of the component\'s repository.'))
        group.add_option("-f", "--fetch-only", action="store_true",
                         default=False, help=_("Fetch upgrades but do not install."))
        group.add_option("-x", "--exclude", action="append",
                         default=None, help=_(
                "When installing packages, ignore packages and components whose basenames match pattern."))
        group.add_option("--exclude-from", action="store",
                         default=None,
                         help=_("When installing packages, ignore packages "
                                "and components whose basenames match "
                                "any pattern contained in file."))
        group.add_option("-s", "--store-lib-info", action="store_true",
                         default=False,
                         help=_("Store previous libraries info when package is updating to newer version."))
        self.parser.add_option_group(group)

    def run(self):

        if self.options.fetch_only:
            self.init(database=True, write=False)
        else:
            self.init()

        components = ctx.get_option('component')
        if not components and not self.args:
            self.help()
            return

        packages = []
        if components:
            for name in components:
                if self.componentdb.has_component(name):
                    repository = ctx.get_option('repository')
                    if repository:
                        packages.extend(self.componentdb.get_packages(name, walk=True, repo=repository))
                    else:
                        packages.extend(self.componentdb.get_union_packages(name, walk=True))
                else:
                    ctx.ui.info(_('There is no component named  as \"{}\"').format(name))

        packages.extend(self.args)

        if ctx.get_option('exclude_from'):
            packages = inary.blacklist.exclude_from(packages, ctx.get_option('exclude_from'))

        if ctx.get_option('exclude'):
            packages = inary.blacklist.exclude(packages, ctx.get_option('exclude'))

        reinstall = bool(packages) and packages[0].endswith(ctx.const.package_suffix)
        install.install(packages, ctx.get_option('reinstall') or reinstall)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.util as util
import inary.db

class ListAvailable(command.Command, metaclass=command.autocommand):
    __doc__ = _("""List available packages in the repositories

Usage: list-available [ <repo1> <repo2> ... repon ]

Gives a brief list of INARY packages published in the specified
repositories. If no repository is specified, we list packages in
all repositories.
""")

    def __init__(self, args):
        super(ListAvailable, self).__init__(args)
        self.componentdb = inary.db.componentdb.ComponentDB()
        self.packagedb = inary.db.packagedb.PackageDB()

    name = ("list-available", "la")

    def options(self):

        group = optparse.OptionGroup(self.parser, _("list-available options"))
        group.add_option("-l", "--long", action="store_true",
                         default=False, help=_("Show in long format"))
        group.add_option("-c", "--component", action="store",
                         default=None, help=_("List available packages under given component"))
        group.add_option("-U", "--uninstalled", action="store_true",
                         default=False, help=_("Show uninstalled packages only"))
        self.parser.add_option_group(group)

    def run(self):

        self.init(database=True, write=False)

        if not (ctx.get_option('no_color') or ctx.config.get_option('uninstalled')):
            ctx.ui.info(_('Installed packages are shown in this color.'), color='green')

        if self.args:
            for arg in self.args:
                self.print_packages(arg)
        else:
            # print for all repos
            for repo in inary.db.repodb.RepoDB().list_repos(only_active=True):
                ctx.ui.info(_("\n Repository : \"{}\"\n").format(str(repo)), color="blue")
                self.print_packages(repo)

    def print_packages(self, repo):

        component = ctx.get_option('component')
        if component:
            try:
                l = self.componentdb.get_packages(component, repo=repo, walk=True)
            except:
                return
        else:
            l = self.packagedb.list_packages(repo)

        installed_list = inary.db.installdb.InstallDB().list_installed()

        # maxlen is defined dynamically from the longest package name (#9021)
        if l:
            maxlen = max([len(_p) for _p in l])

        l.sort()
        for p in l:
            if ctx.config.get_option('uninstalled') and p in installed_list:
                continue

            package = self.packagedb.get_package(p, repo)

            if p in installed_list:
                package.name = util.colorize(package.name, 'green')
            else:
                package.name = util.colorize(package.name, 'brightwhite')

            if self.options.long:
                ctx.ui.info(str(package) + '\n')
            else:
                package.name += ' ' * max(0, maxlen - len(p))
                ctx.ui.info('{0} - {1} '.format(package.name, str(package.summary)))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.db

class ListComponents(command.Command, metaclass=command.autocommand):
    __doc__ = _("""List available components

Usage: list-components

Gives a brief list of INARY components published in the
repositories.
""")

    def __init__(self, args):
        super(ListComponents, self).__init__(args)
        self.componentdb = inary.db.componentdb.ComponentDB()

    name = ("list-components", "lc")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("list-components options"))
        group.add_option("-l", "--long", action="store_true",
                         default=False, help=_("Show in long format"))
        group.add_option("-r", "--repository", action="store",
                         type="string", default=None, help=_('Name of the source or package repository'))
        self.parser.add_option_group(group)

    def run(self):

        self.init(database=True, write=False)

        l = self.componentdb.list_components(ctx.get_option('repository'))
        if l:
            maxlen = max([len(_p) for _p in l])
        l.sort()
        for p in l:
            component = self.componentdb.get_component(p)
            if self.options.long:
                ctx.ui.info(str(component))
            else:
                component.name += ' ' * max(0, maxlen - len(p))
                ctx.ui.info('{0} - {1} '.format(component.name, str(component.summary)))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.db
import sys

class ListInstalled(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Print the list of all installed packages

Usage: list-installed
""")

    def __init__(self, args):
        super(ListInstalled, self).__init__(args)
        self.installdb = inary.db.installdb.InstallDB()
        self.componentdb = inary.db.componentdb.ComponentDB()

    name = ("list-installed", "li")

    def options(self):

        group = optparse.OptionGroup(self.parser, _("list-installed options"))

        group.add_option("-b", "--with-build-host",
                         action="store",
                         default=None,
                         help=_("Only list the installed packages built "
                                "by the given host."))
        group.add_option("-l", "--long", action="store_true",
                         default=False, help=_("Show in long format"))
        group.add_option("-c", "--component", action="store",
                         default=None, help=_("List installed packages under given component."))
        group.add_option("-i", "--install-info", action="store_true",
                         default=False, help=_("Show detailed install info."))

        self.parser.add_option_group(group)

    def run(self):
        self.init(database=True, write=False)

        build_host = ctx.get_option("with_build_host")
        if build_host is None:
            installed = self.installdb.list_installed()
        else:
            installed = self.installdb.list_installed_with_build_host(build_host)

        component = ctx.get_option('component')
        if component:
            component_pkgs = self.componentdb.get_union_packages(component, walk=True)
            installed = list(set(installed) & set(component_pkgs))

        installed.sort()

        # Resize the first column according to the longest package name
        if installed:
            maxlen = max([len(_p) for _p in installed])

        if self.options.install_info:
            ctx.ui.info(_('Package Name          |St|        Version|  Rel.|  Distro|             Date'))
            sys.stdout.write('===========================================================================\n')
        for pkg in installed:
            package = self.installdb.get_package(pkg)
            inst_info = self.installdb.get_info(pkg)
            if self.options.long:
                ctx.ui.info(str(package))
                ctx.ui.info(str(inst_info))
            elif self.options.install_info:
                ctx.ui.info('%-20s  ' % package.name, color='white', noln=True)
                ctx.ui.info('|%s' % inst_info.one_liner())
            else:
                package.name += ' ' * (maxlen - len(package.name))
                ctx.ui.info('{} '.format(package.name), color='white', noln=True)
                ctx.ui.info('- {}'.format(str(package.summary)))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C)  2017 - 2018,  Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.db

class ListNewest(command.Command, metaclass=command.autocommand):
    __doc__ = _("""List newest packages in the repositories

Usage: list-newest [ <repo1> <repo2> ... repon ]

Gives a list of INARY newly published packages in the specified
repositories. If no repository is specified, we list the new
packages from all repositories.
""")

    def __init__(self, args):
        super(ListNewest, self).__init__(args)
        self.componentdb = inary.db.componentdb.ComponentDB()
        self.packagedb = inary.db.packagedb.PackageDB()

    name = ("list-newest", "ln")

    def options(self):

        group = optparse.OptionGroup(self.parser, _("list-newest options"))
        group.add_option("-s", "--since", action="store",
                         default=None,
                         help=_("List new packages added to repository after this given date formatted as yyyy-mm-dd."))
        group.add_option("-l", "--last", action="store",
                         default=None,
                         help=_("List new packages added to repository after last nth previous repository update."))
        self.parser.add_option_group(group)

    def run(self):

        self.init(database=True, write=False)

        if self.args:
            for arg in self.args:
                self.print_packages(arg)
        else:
            # print for all repos
            for repo in inary.db.repodb.RepoDB().list_repos(only_active=True):
                self.print_packages(repo)

    def print_packages(self, repo):
        if ctx.config.get_option('since'):
            since = ctx.config.get_option('since')
        elif ctx.config.get_option('last'):
            since = inary.db.historydb.HistoryDB().get_last_repo_update(int(ctx.config.get_option('last')))
        else:
            since = None

        l = self.packagedb.list_newest(repo, since)
        if not l:
            return

        if since:
            ctx.ui.info(_("Packages added to \'{0}\' since \"{1}\":\n").format(repo, since))
        else:
            ctx.ui.info(_("Packages added to \'{}\':").format(repo))

        # maxlen is defined dynamically from the longest package name (#9021)
        maxlen = max([len(_p) for _p in l])

        l.sort()
        for p in l:
            package = self.packagedb.get_package(p, repo)
            lenp = len(p)
            p += ' ' * max(0, maxlen - lenp)
            ctx.ui.info('{0} - {1} '.format(p, str(package.summary)))

        print()


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.db
import inary.util as util

class ListOrphaned(command.Command, metaclass=command.autocommand):
    __doc__ = _("""List orphaned packages

Usage: list-orphaned

Lists packages installed as dependency, but no longer needed by any other installed package.
""")

    def __init__(self, args):
        super(ListOrphaned, self).__init__(args)
        self.installdb = inary.db.installdb.InstallDB()

    name = ("list-orphaned", "lo")

    def options(self):

        group = optparse.OptionGroup(self.parser, _("list-orphaned options"))
        group.add_option("-a", "--all", action="store_true",
                         default=False, help=_("Show all packages without reverse dependencies."))
        group.add_option("-x", "--exclude", action="append",
                         default=None, help=_("Ignore packages and components whose basenames match pattern."))
        self.parser.add_option_group(group)

    def run(self):

        self.init(database=True, write=False)
        orphaned = self.installdb.get_no_rev_deps() if self.options.all else self.installdb.get_orphaned()

        if self.options.exclude:
            orphaned = inary.blacklist.exclude(orphaned, ctx.get_option('exclude'))

        if orphaned:
            ctx.ui.info(_("Orphaned packages:"))
            ctx.ui.info(util.format_by_columns(sorted(orphaned)))
        else:
            ctx.ui.info(_("No orphaned packages."))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.data.pgraph
import inary.db

class ListPending(command.Command, metaclass=command.autocommand):
    __doc__ = _("""List pending packages

Lists packages waiting to be configured.
""")

    def __init__(self, args):
        super(ListPending, self).__init__(args)

    name = ("list-pending", "lp")

    def run(self):
        self.init(database=True, write=False)

        A = inary.db.installdb.InstallDB().list_pending()
        if len(A):
            ctx.ui.info(_('Listing pending orders:'), color='blue')
            for p in inary.data.pgraph.generate_pending_order(A):
                ctx.ui.info(p)
        else:
            ctx.ui.info(_('There are no packages waiting to be configured.'))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.db

class ListRepo(command.Command, metaclass=command.autocommand):
    __doc__ = _("""List repositories

Usage: list-repo

Lists currently tracked repositories.
""")

    def __init__(self, args):
        super(ListRepo, self).__init__(args)
        self.repodb = inary.db.repodb.RepoDB()

    name = ("list-repo", "lr")

    def run(self):

        self.init(database=True, write=False)
        for repo in self.repodb.list_repos(only_active=False):
            active = _("active") if self.repodb.repo_active(repo) else _("inactive")
            if active == _("active"):
                ctx.ui.info(_("{0} [{1}]").format(repo, active), color='green')
            else:
                ctx.ui.info(_("{0} [{1}]").format(repo, active), color='red')
            print('  ', self.repodb.get_repo_url(repo))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.db
import inary.util as util

class ListSources(command.Command, metaclass=command.autocommand):
    __doc__ = _("""List available sources

Usage: list-sources

Gives a brief list of sources published in the repositories.
""")

    def __init__(self, args):
        super(ListSources, self).__init__(args)
        self.sourcedb = inary.db.sourcedb.SourceDB()

    name = ("list-sources", "ls")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("list-sources options"))
        group.add_option("-l", "--long", action="store_true",
                         default=False, help=_("Show in long format"))
        self.parser.add_option_group(group)

    def run(self):

        self.init(database=True, write=False)

        l = self.sourcedb.list_sources()

        if l:
            maxlen = max([len(_p) for _p in l])

        installed_list = inary.db.sourcedb.SourceDB().list_sources()
        l.sort()

        for p in l:
            sf, repo = self.sourcedb.get_spec_repo(p)
            if self.options.long:
                ctx.ui.info(_('[Repository: ') + repo + ']')
                ctx.ui.info(str(sf.source))
            else:
                if p in installed_list:
                    sf.source.name = util.colorize(sf.source.name, 'cyan')
                sf.source.name += ' ' * max(0, maxlen - len(p))
                ctx.ui.info('{0} - {1}'.format(sf.source.name, str(sf.source.summary)))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse
import sys

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.blacklist
import inary.context as ctx
import inary.db
import inary.operations as operations

class ListUpgrades(command.Command, metaclass=command.autocommand):
    __doc__ = _("""List packages to be upgraded

Usage: list-upgrades

Lists the packages that will be upgraded.
""")

    def __init__(self, args):
        super(ListUpgrades, self).__init__(args)
        self.componentdb = inary.db.componentdb.ComponentDB()
        self.installdb = inary.db.installdb.InstallDB()

    name = ("list-upgrades", "lu")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("list-upgrades options"))
        group.add_option("-l", "--long", action="store_true",
                         default=False, help=_("Show in long format."))
        group.add_option("-c", "--component", action="store",
                         default=None, help=_("List upgradable packages under given component."))
        group.add_option("-i", "--install-info", action="store_true",
                         default=False, help=_("Show detailed install info."))
        self.parser.add_option_group(group)

    def run(self):
        self.init(database=True, write=False)
        installdb = inary.db.installdb.InstallDB()
        is_upgradable = operations.upgrade.is_upgradable

        upgradable_pkgs = list(filter(is_upgradable, installdb.list_installed()))
        # replaced packages can not pass is_upgradable test, so we add them manually
        # upgradable_pkgs.extend(list_replaces())

        # consider also blacklist filtering
        upgradable_pkgs = inary.blacklist.exclude_from(upgradable_pkgs, ctx.const.blacklist)

        component = ctx.get_option('component')
        if component:
            component_pkgs = self.componentdb.get_union_packages(component, walk=True)
            upgradable_pkgs = list(set(upgradable_pkgs) & set(component_pkgs))

        upgradable_pkgs = inary.blacklist.exclude_from(upgradable_pkgs, ctx.const.blacklist)

        if not upgradable_pkgs:
            ctx.ui.info(_('No packages to upgrade.'))
            return

        upgradable_pkgs.sort()

        # Resize the first column according to the longest package name
        maxlen = max([len(_p) for _p in upgradable_pkgs])

        if self.options.install_info:
            ctx.ui.info(_('Package Name          |St|        Version|  Rel.|  Distro|             Date'))
            sys.stdout.write('===========================================================================')

        for pkg in upgradable_pkgs:
            package = self.installdb.get_package(pkg)
            inst_info = self.installdb.get_info(pkg)
            if self.options.long:
                ctx.ui.info(package)
                sys.stdout.write(inst_info)
            elif self.options.install_info:
                ctx.ui.info('%-20s |%s ' % (package.name, inst_info.one_liner()))
            else:
                package.name += ' ' * max(0, maxlen - len(package.name))
                ctx.ui.info('{0} - {1}'.format(package.name, str(package.summary)))


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.db.filesdb

class RebuildDb(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Rebuild Databases

Usage: rebuilddb [ <package1> <package2> ... <packagen> ]

Rebuilds the INARY databases

If package specs are given, they should be the names of package
dirs under /var/lib/inary
""")

    def __init__(self, args):
        super(RebuildDb, self).__init__(args)

    name = ("rebuild-db", "rdb")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("rebuild-db options"))

        group.add_option("-f", "--files", action="store_true",
                         default=False, help=_("Rebuild files database"))

        self.parser.add_option_group(group)

    def run(self):
        self.init(database=True)
        if ctx.ui.confirm(_('Rebuild INARY databases?')):
            inary.db.filesdb.rebuild_db()


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext
__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.util as util
import inary.cli.command as command
import inary.ui
import inary.data
import inary.errors
import inary.context as ctx
import inary.reactor

def configure_pending(packages=None):

    # start with pending packages
    # configure them in reverse topological order of dependency
    installdb = inary.db.installdb.InstallDB()
    order=packages
    if True:
        for x in order:
            if installdb.has_package(x):
                pkginfo = installdb.get_package(x)
                pkg_path = installdb.package_path(x)
                m = inary.data.metadata.MetaData()
                metadata_path = util.join_path(pkg_path, ctx.const.metadata_xml)
                m.read(metadata_path)
                # FIXME: we need a full package info here!
                pkginfo.name = x
                ctx.ui.notify(inary.ui.configuring, package=pkginfo, files=None)
                inary.reactor.post_install(
                    pkginfo.name,
                    m.package.providesScom,
                    util.join_path(pkg_path, ctx.const.scom_dir),
                    util.join_path(pkg_path, ctx.const.metadata_xml),
                    util.join_path(pkg_path, ctx.const.files_xml),
                    None,
                    None,
                    m.package.version,
                    m.package.release
                )
                ctx.ui.notify(inary.ui.configured, package=pkginfo, files=None)
            installdb.clear_pending(x)

class ConfigurePending(command.PackageOp, metaclass=command.autocommand):
    __doc__ = _("""Reconfigure pending packages

If SCOM configuration of some packages were not
done at installation time, they are added to a list
of packages waiting to be configured. This command
configures those packages.
""")

    def __init__(self, args):
        super(ConfigurePending, self).__init__(args)

    name = (_("reconfigure"), "rp")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("configure-pending options"))
        super(ConfigurePending, self).options(group)
        self.parser.add_option_group(group)

    def run(self):
        self.init(database=True, write=False)
        configure_pending(self.args)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
from inary.operations import remove
import inary.db

class Remove(command.PackageOp, metaclass=command.autocommand):
    __doc__ = _("""Remove INARY packages

Usage: remove <package1> <package2> ... <packagen>

Remove package(s) from your system. Just give the package names to remove.

You can also specify components instead of package names, which will be
expanded to package names.
""")

    def __init__(self, args):
        super(Remove, self).__init__(args)
        self.componentdb = inary.db.componentdb.ComponentDB()

    name = ("remove", "rm")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("remove options"))
        super(Remove, self).options(group)
        group.add_option("--purge", action="store_true",
                         default=False, help=_("Removes everything including changed config files of the package."))
        group.add_option("-c", "--component", action="append",
                         default=None, help=_("Remove component's and recursive components' packages."))
        self.parser.add_option_group(group)

    def run(self):
        self.init()

        components = ctx.get_option('component')
        if not components and not self.args:
            self.help()
            return

        packages = []
        if components:
            for name in components:
                if self.componentdb.has_component(name):
                    packages.extend(self.componentdb.get_union_packages(name, walk=True))
        packages.extend(self.args)

        remove.remove(packages)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
from inary.operations import remove
import inary.db
import inary.blacklist

class RemoveOrphaned(command.PackageOp, metaclass=command.autocommand):
    __doc__ = _("""Remove orphaned packages

Usage: remove-orphaned

Remove all orphaned packages from the system.
""")

    def __init__(self, args):
        super(RemoveOrphaned, self).__init__(args)
        self.installdb = inary.db.installdb.InstallDB()

    name = ("remove-orphaned", "ro")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("remove-orphaned options"))

        super(RemoveOrphaned, self).options(group)
        group.add_option("-x", "--exclude", action="append",
                         default=None, help=_(
                "When removing orphaned, ignore packages and components whose basenames match pattern."))

        self.parser.add_option_group(group)

    def run(self):
        self.init()
        orphaned = self.installdb.get_orphaned()
        if ctx.get_option('exclude'):
            orphaned = inary.blacklist.exclude(orphaned, ctx.get_option('exclude'))

        remove.remove(orphaned)


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
from inary.operations import repository

class RemoveRepo(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Remove repositories

Usage: remove-repo <repo1> <repo2> ... <repon>

Remove all repository information from the system.
""")

    def __init__(self, args):
        super(RemoveRepo, self).__init__(args)

    name = ("remove-repo", "rr")

    def run(self):

        if len(self.args) >= 1:
            self.init()
            for repo in self.args:
                repository.remove_repo(repo)
        else:
            self.help()
            return


code:
# -*- coding:utf-8 -*-
#
# Main fork Pisi: Copyright (C) 2005 - 2011, Tubitak/UEKAE
#
# Copyright (C) 2016 - 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#

import optparse
import re

import gettext

__trans = gettext.translation('inary', fallback=True)
_ = __trans.gettext

import inary.cli.command as command
import inary.context as ctx
import inary.db

class Search(command.Command, metaclass=command.autocommand):
    __doc__ = _("""Search packages

Usage: search <term1> <term2> ... <termn>

Finds a package containing specified search terms
in summary, description, and package name fields.
Default search is done in package database. Use
options to search in install database or source
database.
""")

    def __init__(self, args):
        super(Search, self).__init__(args)

    name = ("search", "sr")

    def options(self):
        group = optparse.OptionGroup(self.parser, _("search options"))
        group.add_option("-l", "--language", action="store",
                         type="string", default=None, help=_('Summary and description language.'))
        group.add_option("-r", "--repository", action="store",
                         type="string", default=None, help=_('Name of the source or package repository.'))
        group.add_option("-i", "--installdb", action="store_true",
                         default=False, help=_("Search in installdb."))
        group.add_option("-s", "--sourcedb", action="store_true",
                         default=False, help=_("Search in sourcedb."))
        group.add_option("-c", "--case-sensitive", action="store_true",
                         default=False, help=_("Case sensitive search."))
        group.add_option("--name", action="store_true",
                         default=False, help=_('Search in the package name.'))
        group.add_option("--summary", action="store_true",
                         default=False, help=_('Search in the package summary.'))
        group.add_option("--description", action="store_true",
                         default=False, help=_('Search in the package description.'))
        self.parser.add_option_group(group)

    def run(self):

        self.init(database=True, write=False)

        if not self.args:
            self.help()
            return

        cs = ctx.get_option("case_sensitive")
        replace = re.compile("({})".format("|".join(self.args)), 0 if cs else re.I)
        lang = ctx.get_option('language')
        repo = ctx.get_option('repository')
        name = ctx.get_option('name')
        summary = ctx.get_option('summary')
        desc = ctx.get_option('description')
        fields = None
        if name or summary or desc:
            fields = {'name': name, 'summary': summary, 'desc': desc}

        installdb = inary.db.installdb.InstallDB()
        if ctx.get_option('installdb'):
            pkgs = installdb.search_package(self.args, lang, fields, cs)
            get_info = db.get_package
            get_name_sum = lambda pkg: (pkg.name, pkg.summary)
        elif ctx.get_option('sourcedb'):
            db = inary.db.sourcedb.SourceDB()
            pkgs = db.search_spec(self.args, lang, repo, fields, cs)
            get_info = db.get_spec
            get_name_sum = lambda pkg: (pkg.source.name, pkg.source.summary)
        else:
            db = inary.db.packagedb.PackageDB()
            pkgs = db.search_package(self.args, lang, repo, fields, cs)
            get_info = db.get_package
            get_name_sum = lambda pkg: (pkg.name, pkg.summary)

        if pkgs:
            maxlen = max([len(_pkg) for _pkg in pkgs])+2

        for pkg in pkgs:
            pkg_info = get_info(pkg)

            name, summary = get_name_sum(pkg_info)
            lenp = len(name)
            version=""
            if installdb.has_package(pkg):
                  color="brightgreen"
            else:
                  color="brightred"
            name = replace.sub(inary.util.colorize(r"\1", color), str(name))
            summary = replace.sub(inary.util.colorize(r"\1", color), str(summary))
            name += ' ' * max(0, maxlen - lenp)

            ctx.ui.info('{} {} {}'.format(name,inary.util.colorize("=",color), summary))