]> git.ipfire.org Git - pakfire.git/commitdiff
CLI: Remove pakfire cli into an extra file
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 6 Jul 2021 16:03:55 +0000 (16:03 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 6 Jul 2021 16:03:55 +0000 (16:03 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
.gitignore
Makefile.am
src/pakfire/__init__.py
src/pakfire/cli.py
src/scripts/pakfire [deleted file]
src/scripts/pakfire.in [new file with mode: 0644]

index 6493cbfc3370fef6cdf545178818b29f98b31bd9..4079771e617d3e5d31921c7bb5d5fdf192034473 100644 (file)
@@ -7,6 +7,7 @@
 /missing
 /contrib/pakfire.nm
 /src/pakfire/__version__.py
+/src/scripts/pakfire
 /src/scripts/pakfire-builder
 /src/scripts/pakfire-client
 /src/scripts/pakfire-daemon
index 8cc0f01c95bebb13922451fedbd0a380bc95e835..6bfe1c83ebe00bdbd0d711e1920bd0ab43dde198 100644 (file)
@@ -100,30 +100,25 @@ dist_doc_DATA = \
        README
 
 # ------------------------------------------------------------------------------
-
-dist_bin_SCRIPTS = \
-       src/scripts/pakfire
        
 bin_SCRIPTS = \
+       src/scripts/pakfire \
        src/scripts/pakfire-builder \
        src/scripts/pakfire-client \
        src/scripts/pakfire-daemon
 
 EXTRA_DIST += \
+       src/scripts/pakfire.in \
        src/scripts/pakfire-builder.in \
        src/scripts/pakfire-client.in \
        src/scripts/pakfire-daemon.in
 
 CLEANFILES += \
+       src/scripts/pakfire \
        src/scripts/pakfire-builder \
        src/scripts/pakfire-client \
        src/scripts/pakfire-daemon
 
-install-exec-local:
-       $(MKDIR_P) $(DESTDIR)/$(bindir)
-       cd $(DESTDIR)/$(bindir) && \
-               $(LN_S) -vf pakfire pakfire-key
-
 # ------------------------------------------------------------------------------
 
 pakfire_PYTHON = \
index a9759336b3a28e3b4677fd297bf6f7aaf55f2f15..8b281b0fc548b7fbfc9beb46532b8a3482456f57 100644 (file)
@@ -21,5 +21,7 @@
 
 from ._pakfire import Pakfire
 
+from .__version__ import PAKFIRE_VERSION as __version__
+
 # Import Exceptions
 from ._pakfire import CommandExecutionError
index 98a9c224a0ab5fbfcdcb2d80c00d48e596f383e6..648f191fa874bd31c6214bb305895dd794c82862 100644 (file)
@@ -37,289 +37,6 @@ from .i18n import _
 class Cli(object):
        default_path = "/"
 
-       def parse_cli(self):
-               parser = argparse.ArgumentParser(
-                       description = _("Pakfire command line interface"),
-               )
-               subparsers = parser.add_subparsers()
-
-               # Add common arguments
-               self._add_common_arguments(parser)
-
-               parser.add_argument("--arch", "-a", nargs="?",
-                       help=_("Run pakfire for the given architecture"))
-               parser.add_argument("--root", metavar="PATH", default="/",
-                       help=_("The path where pakfire should operate in"))
-
-               # check
-               check = subparsers.add_parser("check", help=_("Check the system for any errors"))
-               check.set_defaults(func=self.handle_check)
-
-               # clean
-               clean = subparsers.add_parser("clean", help=_("Cleanup all temporary files"))
-               clean.set_defaults(func=self.handle_clean)
-
-               # execute
-               execute = subparsers.add_parser("execute",
-                       help=_("Executes a command in the pakfire environment (useful for development)"))
-               execute.add_argument("--bind", action="append", default=[], dest="binds",
-                       help=_("Bind-mounts the given directory"))
-               execute.add_argument("command", nargs=argparse.REMAINDER)
-               execute.set_defaults(func=self.handle_execute)
-
-               # info
-               info = subparsers.add_parser("info",
-                       help=_("Print some information about the given package(s)"))
-               info.add_argument("--long", action="store_true",
-                       help=_("Show more information"))
-               info.add_argument("package", help=_("Give at least the name of one package"))
-               info.set_defaults(func=self.handle_info)
-
-               # install
-               install = subparsers.add_parser("install",
-                       help=_("Install one or more packages to the system"))
-               install.add_argument("package", nargs="+",
-                       help=_("Give name of at least one package to install"))
-               install.add_argument("--without-recommended", action="store_true",
-                       help=_("Don't install recommended packages"))
-               install.add_argument("--allow-uninstall", action="store_true",
-                       help=_("Allow uninstalling packages"))
-               install.add_argument("--allow-downgrade", action="store_true",
-                       help=_("Allow downgrading packages"))
-               install.set_defaults(func=self.handle_install)
-
-               # provides
-               provides = subparsers.add_parser("provides",
-                       help=_("Get a list of packages that provide a given file or feature"))
-               provides.add_argument("pattern", help=_("File or feature to search for"))
-               provides.set_defaults(func=self.handle_provides)
-
-               # requires
-               requires = subparsers.add_parser("requires",
-                       help=_("Get a list of packages that require this dependency"))
-               requires.add_argument("pattern", help=_("File or feature to search for"))
-               requires.set_defaults(func=self.handle_requires)
-
-               # reinstall
-               reinstall = subparsers.add_parser("reinstall",
-                       help=_("Reinstall one or more packages"))
-               reinstall.add_argument("package", nargs="+",
-                       help=_("Give name of at least one package to reinstall"))
-               reinstall.set_defaults(func=self.handle_reinstall)
-
-               # remove
-               remove = subparsers.add_parser("remove",
-                       help=_("Remove one or more packages from the system"))
-               remove.add_argument("package", nargs="+",
-                       help=_("Give name of at least one package to remove"))
-               remove.add_argument("--keep-dependencies", action="store_true",
-                       help=_("Keep dependencies installed"))
-               remove.set_defaults(func=self.handle_remove)
-
-               # repolist
-               repolist = subparsers.add_parser("repolist",
-                       help=_("List all currently enabled repositories"))
-               repolist.set_defaults(func=self.handle_repolist)
-
-               # search
-               search = subparsers.add_parser("search", help=_("Search for a given pattern"))
-               search.add_argument("pattern", help=_("A pattern to search for"))
-               search.set_defaults(func=self.handle_search)
-
-               # sync
-               sync = subparsers.add_parser("sync",
-                       help=_("Sync all installed with the latest one in the distribution"))
-               sync.add_argument("--keep-orphaned", action="store_true",
-                       help=_("Keep orphaned packages"))
-               sync.set_defaults(func=self.handle_sync)
-
-               # update
-               update = subparsers.add_parser("update",
-                       help=_("Update the whole system or one specific package"))
-               update.add_argument("package", nargs="*",
-                       help=_("Give a name of a package to update or leave emtpy for all"))
-               update.add_argument("--exclude", "-x", nargs="+", default=[],
-                       help=_("Exclude package from update"))
-               update.add_argument("--allow-uninstall", action="store_true",
-                       help=_("Allow uninstalling packages"))
-               update.add_argument("--allow-downgrade", action="store_true",
-                       help=_("Allow downgrading packages"))
-               update.set_defaults(func=self.handle_update)
-
-               return parser.parse_args()
-
-       def _add_common_arguments(self, parser, offline_switch=True):
-               parser.add_argument("--version", action="version",
-                       version="%(prog)s " + PAKFIRE_VERSION)
-
-               parser.add_argument("-v", "--verbose", action="store_true",
-                       help=_("Enable verbose output."))
-
-               parser.add_argument("-c", "--config", nargs="?",
-                       help=_("Path to a configuration file to load."))
-
-               parser.add_argument("--disable-repo", nargs="*", metavar="REPO",
-                       help=_("Disable a repository temporarily."), default=[])
-
-               parser.add_argument("--enable-repo", nargs="*", metavar="REPO",
-                       help=_("Enable a repository temporarily."), default=[])
-
-               if offline_switch:
-                       parser.add_argument("--offline", action="store_true",
-                               help=_("Run pakfire in offline mode."))
-
-       def pakfire(self, ns):
-               p = _pakfire.Pakfire(
-                       arch=ns.arch,
-                       conf=ns.config,
-                       path=ns.root if "root" in ns else self.default_path,
-                       offline=ns.offline,
-               )
-
-               # Disable repositories.
-               for repo_name in ns.disable_repo:
-                       repo = p.get_repo(repo_name)
-                       repo.enabled = False
-
-               # Enable repositories.
-               for repo_name in ns.enable_repo:
-                       repo = p.get_repo(repo_name)
-                       repo.enabled = True
-
-               return p
-
-       def handle_execute(self, ns):
-               pakfire = self.pakfire(ns)
-
-               # Bind-mount everything
-               for bind in ns.binds:
-                       pakfire.bind(bind)
-
-               # Log everything to the console
-               def logging_callback(level, line):
-                       if level >= logging.ERROR:
-                               sys.stderr.write("%s\n" % line)
-                       else:
-                               sys.stdout.write("%s\n" % line)
-
-               return pakfire.execute(ns.command, logging_callback=logging_callback)
-
-       def run(self):
-               args = self.parse_cli()
-               assert args.func, "Argument function not defined"
-
-               try:
-                       return args.func(args)
-
-               except KeyboardInterrupt:
-                       return 128 + signal.SIGINT
-
-               except DependencyError as e:
-                       print(_("One or more dependencies could not been resolved"))
-                       print("") # empty line
-
-                       # This exception provides a list of all problems
-                       problems, = e.args
-
-                       # List all problems
-                       for problem in problems:
-                               print("  * %s" % problem)
-
-                               print("    %s" % _("Possible solutions are:"))
-                               for solution in problem.solutions:
-                                       print("    * %s" % solution)
-
-                               # Add another empty line
-                               print("")
-
-                       return 4
-
-               # Catch all errors and show a user-friendly error message.
-               except Error as e:
-                       print(_("An error has occured when running Pakfire"))
-                       print(_("%s: %s") % (e.__class__.__name__, e.message))
-
-                       return e.exit_code
-
-       def handle_info(self, ns):
-               p = self.pakfire(ns)
-
-               for pkg in p.search(ns.package, name_only=True):
-                       s = pkg.dump(long=ns.long)
-                       print(s)
-
-       def handle_search(self, ns):
-               p = self.pakfire(ns)
-
-               for pkg in p.search(ns.pattern):
-                       # Skip any -debuginfo packages
-                       if pkg.name.endswith("-debuginfo"):
-                               continue
-
-                       print("%-24s: %s" % (pkg.name, pkg.summary))
-
-       def handle_update(self, ns):
-               p = self.pakfire(ns)
-               p.update(
-                       ns.package,
-                       excludes=ns.exclude,
-                       allow_uninstall=ns.allow_uninstall,
-                       allow_downgrade=ns.allow_downgrade,
-               )
-
-       def handle_sync(self, ns):
-               self.pakfire(ns).sync(keep_orphaned=ns.keep_orphaned)
-
-       def handle_install(self, ns):
-               p = self.pakfire(ns)
-               p.install(
-                       ns.package,
-                       without_recommended=ns.without_recommended,
-                       allow_uninstall=ns.allow_uninstall,
-                       allow_downgrade=ns.allow_downgrade,
-               )
-
-       def handle_reinstall(self, ns):
-               with self.pakfire(ns) as p:
-                       transaction = p.reinstall(ns.package)
-
-                       # Execute the transaction
-                       self._execute_transaction(transaction)
-
-       def handle_remove(self, ns):
-               p = self.pakfire(ns)
-               p.erase(ns.package, keep_dependencies=ns.keep_dependencies)
-
-       def handle_provides(self, ns, long=False):
-               for pkg in self.pakfire(ns).whatprovides(ns.pattern):
-                       s = pkg.dump(long=long)
-                       print(s)
-
-       def handle_requires(self, ns):
-               for pkg in self.pakfire(ns).whatrequires(ns.pattern):
-                       s = pkg.dump(long=True)
-                       print(s)
-
-       def handle_repolist(self, ns):
-               p = self.pakfire(ns)
-
-               FORMAT = " %-20s %8s %12s %12s "
-               title = FORMAT % (_("Repository"), _("Enabled"), _("Priority"), _("Packages"))
-               print(title)
-               print("=" * len(title)) # spacing line
-
-               for repo in p.repos:
-                       print(FORMAT % (repo.name, repo.enabled, repo.priority, len(repo)))
-
-       def handle_clean(self, ns):
-               print(_("Cleaning up everything..."))
-
-               p = self.pakfire(ns)
-               p.clean()
-
-       def handle_check(self, ns):
-               self.pakfire(ns).check()
-
 
 class CliKey(Cli):
        def parse_cli(self):
diff --git a/src/scripts/pakfire b/src/scripts/pakfire
deleted file mode 100755 (executable)
index 7004ccc..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/python3
-###############################################################################
-#                                                                             #
-# Pakfire - The IPFire package management system                              #
-# Copyright (C) 2017 Pakfire development team                                 #
-#                                                                             #
-# 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.                                         #
-#                                                                             #
-# This program is distributed in the hope that it will be useful,             #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
-# GNU General Public License for more details.                                #
-#                                                                             #
-# You should have received a copy of the GNU General Public License           #
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
-#                                                                             #
-###############################################################################
-
-import os
-import sys
-
-# Catch ImportError and show a more user-friendly message about what went wrong
-try:
-       import pakfire.cli
-
-except ImportError as e:
-       # Try to load at least the i18n support, but when this fails as well we can
-       # go with an English error message.
-       try:
-               from pakfire.i18n import _
-       except ImportError:
-               _ = lambda x: x
-
-       print(_("There has been an error when trying to import one or more of the"
-               " modules, that are required to run Pakfire."))
-       print(_("Please check your installation of Pakfire."))
-       print()
-       print(_("The error that lead to this:"))
-       print("  ", e)
-       print()
-
-       # Exit immediately.
-       sys.exit(1)
-
-basename2cls = {
-       "pakfire"         : pakfire.cli.Cli,
-       "pakfire-client"  : pakfire.cli.CliClient,
-       "pakfire-key"     : pakfire.cli.CliKey,
-}
-
-# Get the basename of the program
-basename = os.path.basename(sys.argv[0])
-
-# Check if the program was called with a weird basename.
-# If so, we exit immediately.
-if basename not in basename2cls:
-       sys.exit(127)
-
-cli = basename2cls[basename]()
-ret = cli.run()
-
-sys.exit(ret)
diff --git a/src/scripts/pakfire.in b/src/scripts/pakfire.in
new file mode 100644 (file)
index 0000000..032b105
--- /dev/null
@@ -0,0 +1,278 @@
+#!/usr/bin/python3
+##############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2021 Pakfire development team                                 #
+#                                                                             #
+# 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.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+import argparse
+import sys
+
+import pakfire
+from pakfire.i18n import _
+
+class Cli(object):
+       def parse_cli(self):
+               parser = argparse.ArgumentParser(
+                       description = _("Pakfire command line interface"),
+               )
+
+               # Version
+               parser.add_argument("--version", action="version",
+                       version="%%(prog)s %s" % pakfire.__version__)
+
+               # Which configuration file to load?
+               parser.add_argument("--config", "-c", nargs="?",
+                       help=_("Configuration file"))
+
+               # Enable/disable repositories
+               parser.add_argument("--disable-repo", nargs="*", metavar="REPO",
+                       help=_("Disable a repository"), default=[])
+               parser.add_argument("--enable-repo", nargs="*", metavar="REPO",
+                       help=_("Enable a repository"), default=[])
+
+               # Offline mode
+               parser.add_argument("--offline", action="store_true",
+                       help=_("Run pakfire in offline mode"))
+
+               # Architecture
+               parser.add_argument("--arch", "-a", nargs="?",
+                       help=_("Run pakfire for the given architecture"))
+
+               # Root
+               parser.add_argument("--root", metavar="PATH", default="/",
+                       help=_("The path where pakfire should operate in"))
+
+               subparsers = parser.add_subparsers()
+
+               # check
+               check = subparsers.add_parser("check",
+                       help=_("Check the system for any errors"))
+               check.set_defaults(func=self._check)
+
+               # clean
+               clean = subparsers.add_parser("clean",
+                       help=_("Cleanup all temporary files"))
+               clean.set_defaults(func=self._clean)
+
+               # execute
+               execute = subparsers.add_parser("execute",
+                       help=_("Executes a command in the pakfire environment (useful for development)"))
+               execute.add_argument("--bind", action="append", default=[], dest="binds",
+                       help=_("Bind-mounts the given directory"))
+               execute.add_argument("command", nargs=argparse.REMAINDER)
+               execute.set_defaults(func=self._execute)
+
+               # info
+               info = subparsers.add_parser("info",
+                       help=_("Print some information about the given package(s)"))
+               info.add_argument("--long", action="store_true",
+                       help=_("Show more information"))
+               info.add_argument("package", help=_("Give at least the name of one package"))
+               info.set_defaults(func=self._info)
+
+               # install
+               install = subparsers.add_parser("install",
+                       help=_("Install one or more packages to the system"))
+               install.add_argument("package", nargs="+",
+                       help=_("Give name of at least one package to install"))
+               install.add_argument("--without-recommended", action="store_true",
+                       help=_("Don't install recommended packages"))
+               install.add_argument("--allow-uninstall", action="store_true",
+                       help=_("Allow uninstalling packages"))
+               install.add_argument("--allow-downgrade", action="store_true",
+                       help=_("Allow downgrading packages"))
+               install.set_defaults(func=self._install)
+
+               # provides
+               provides = subparsers.add_parser("provides",
+                       help=_("Get a list of packages that provide a given file or feature"))
+               provides.add_argument("pattern", help=_("File or feature to search for"))
+               provides.set_defaults(func=self._provides)
+
+               # requires
+               requires = subparsers.add_parser("requires",
+                       help=_("Get a list of packages that require this dependency"))
+               requires.add_argument("pattern", help=_("File or feature to search for"))
+               requires.set_defaults(func=self._requires)
+
+               # remove
+               remove = subparsers.add_parser("remove",
+                       help=_("Remove one or more packages from the system"))
+               remove.add_argument("package", nargs="+",
+                       help=_("Give name of at least one package to remove"))
+               remove.add_argument("--keep-dependencies", action="store_true",
+                       help=_("Keep dependencies installed"))
+               remove.set_defaults(func=self._remove)
+
+               # repolist
+               repolist = subparsers.add_parser("repolist",
+                       help=_("List all currently enabled repositories"))
+               repolist.set_defaults(func=self._repolist)
+
+               # search
+               search = subparsers.add_parser("search",
+                       help=_("Search for a given pattern"))
+               search.add_argument("pattern",
+                       help=_("A pattern to search for"))
+               search.set_defaults(func=self._search)
+
+               # sync
+               sync = subparsers.add_parser("sync",
+                       help=_("Sync all installed with the latest one in the distribution"))
+               sync.add_argument("--keep-orphaned", action="store_true",
+                       help=_("Keep orphaned packages"))
+               sync.set_defaults(func=self._sync)
+
+               # update
+               update = subparsers.add_parser("update",
+                       help=_("Update the whole system or one specific package"))
+               update.add_argument("package", nargs="*",
+                       help=_("Give a name of a package to update or leave emtpy for all"))
+               update.add_argument("--exclude", "-x", nargs="+", default=[],
+                       help=_("Exclude package from update"))
+               update.add_argument("--allow-uninstall", action="store_true",
+                       help=_("Allow uninstalling packages"))
+               update.add_argument("--allow-downgrade", action="store_true",
+                       help=_("Allow downgrading packages"))
+               update.set_defaults(func=self._update)
+
+               args = parser.parse_args()
+
+               # Print usage if no action was given
+               if not "func" in args:
+                       parser.print_usage()
+                       sys.exit(2)
+
+               return args
+
+       def __call__(self):
+               # Parse command line arguments
+               args = self.parse_cli()
+
+               # Create Pakfire instance
+               p = pakfire.Pakfire(
+                       conf=args.config,
+                       arch=args.arch,
+                       path=args.root,
+                       offline=args.offline,
+               )
+
+               # Disable repositories
+               for name in args.disable_repo:
+                       repo = p.get_repo(name)
+                       repo.enabled = False
+
+               # Enable repositories
+               for name in args.enable_repo:
+                       repo = p.get_repo(name)
+                       repo.enabled = True
+
+               # Call function
+               try:
+                       ret = args.func(p, args)
+
+               # Catch invalid inputs
+               except ValueError as e:
+                       sys.stderr.write("%s\n" % e)
+                       ret = 2
+
+               # Return with exit code
+               sys.exit(ret or 0)
+
+       def _check(self, p, args):
+               p.check()
+
+       def _clean(self, p, args):
+               print(_("Cleaning up everything..."))
+               p.clean()
+
+       def _execute(self, p, args):
+               """
+                       Executes a command
+               """
+               # Bind-mount everything
+               for bind in args.binds:
+                       p.bind(bind)
+
+               # Log everything to the console
+               def logging_callback(level, line):
+                       if level >= logging.ERROR:
+                               sys.stderr.write("%s\n" % line)
+                       else:
+                               sys.stdout.write("%s\n" % line)
+
+               return p.execute(args.command, logging_callback=logging_callback)
+
+       def _info(self, p, args):
+               for pkg in p.search(args.package, name_only=True):
+                       s = pkg.dump(long=args.long)
+                       print(s)
+
+       def _install(self, p, args):
+               p.install(
+                       args.package,
+                       without_recommended=args.without_recommended,
+                       allow_uninstall=args.allow_uninstall,
+                       allow_downgrade=args.allow_downgrade,
+               )
+
+       def _provides(self, p, args):
+               for pkg in p.whatprovides(args.pattern):
+                       s = pkg.dump(long=True)
+                       print(s)
+
+       def _remove(self, p, args):
+               p.erase(args.package, keep_dependencies=args.keep_dependencies)
+
+       def _repolist(self, p, args):
+               FORMAT = " %-20s %8s %12s %12s "
+               title = FORMAT % (_("Repository"), _("Enabled"), _("Priority"), _("Packages"))
+               print(title)
+               print("=" * len(title)) # spacing line
+
+               for repo in p.repos:
+                       print(FORMAT % (repo.name, repo.enabled, repo.priority, len(repo)))
+
+       def _requires(self, p, args):
+               for pkg in p.whatrequires(args.pattern):
+                       s = pkg.dump(long=True)
+                       print(s)
+
+       def _search(self, p, args):
+               for pkg in p.search(args.pattern):
+                       # Skip any -debuginfo packages
+                       if pkg.name.endswith("-debuginfo"):
+                               continue
+
+                       print("%-24s: %s" % (pkg.name, pkg.summary))
+
+       def _sync(self, p, args):
+               p.sync(keep_orphaned=args.keep_orphaned)
+
+       def _update(self, p, args):
+               p.update(
+                       args.package,
+                       excludes=args.exclude,
+                       allow_uninstall=args.allow_uninstall,
+                       allow_downgrade=args.allow_downgrade,
+               )
+
+
+if __name__ == "__main__":
+       c = Cli()
+       c()