]>
git.ipfire.org Git - people/stevee/pakfire.git/blob - python/pakfire/cli.py
2 ###############################################################################
4 # Pakfire - The IPFire package management system #
5 # Copyright (C) 2011 Pakfire development team #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
39 from system
import system
40 from constants
import *
43 # Initialize a very simple logging that is removed when a Pakfire instance
45 logger
.setup_logging()
48 pakfire
= base
.Pakfire
51 self
.parser
= argparse
.ArgumentParser(
52 description
= _("Pakfire command line interface."),
55 self
.parse_common_arguments()
57 self
.parser
.add_argument("--root", metavar
="PATH",
59 help=_("The path where pakfire should operate in."))
62 self
.sub_commands
= self
.parser
.add_subparsers()
64 self
.parse_command_install()
65 self
.parse_command_reinstall()
66 self
.parse_command_remove()
67 self
.parse_command_info()
68 self
.parse_command_search()
69 self
.parse_command_check_update()
70 self
.parse_command_update()
71 self
.parse_command_downgrade()
72 self
.parse_command_provides()
73 self
.parse_command_grouplist()
74 self
.parse_command_groupinstall()
75 self
.parse_command_repolist()
76 self
.parse_command_clean()
77 self
.parse_command_check()
78 self
.parse_command_resolvdep()
79 self
.parse_command_extract()
81 # Finally parse all arguments from the command line and save them.
82 self
.args
= self
.parser
.parse_args()
85 "install" : self
.handle_install
,
86 "reinstall" : self
.handle_reinstall
,
87 "remove" : self
.handle_remove
,
88 "check_update" : self
.handle_check_update
,
89 "update" : self
.handle_update
,
90 "downgrade" : self
.handle_downgrade
,
91 "info" : self
.handle_info
,
92 "search" : self
.handle_search
,
93 "provides" : self
.handle_provides
,
94 "grouplist" : self
.handle_grouplist
,
95 "groupinstall" : self
.handle_groupinstall
,
96 "repolist" : self
.handle_repolist
,
97 "clean_all" : self
.handle_clean_all
,
98 "check" : self
.handle_check
,
99 "resolvdep" : self
.handle_resolvdep
,
100 "extract" : self
.handle_extract
,
104 def pakfire_args(self
):
107 if hasattr(self
.args
, "root"):
108 ret
["path"] = self
.args
.root
110 if hasattr(self
.args
, "offline") and self
.args
.offline
:
111 ret
["downloader"] = {
112 "offline" : self
.args
.offline
,
115 if hasattr(self
.args
, "config"):
116 ret
["configs"] = self
.args
.config
118 ret
["configs"] = None
122 def create_pakfire(self
, cls
=None, **kwargs
):
126 args
= self
.pakfire_args
131 # Disable repositories.
132 for repo
in self
.args
.disable_repo
:
133 p
.repos
.disable_repo(repo
)
135 # Enable repositories.
136 for repo
in self
.args
.enable_repo
:
137 p
.repos
.enable_repo(repo
)
141 def parse_common_arguments(self
, offline_switch
=True):
142 self
.parser
.add_argument("--version", action
="version",
143 version
="%(prog)s " + PAKFIRE_VERSION
)
145 self
.parser
.add_argument("-v", "--verbose", action
="store_true",
146 help=_("Enable verbose output."))
148 self
.parser
.add_argument("-c", "--config", nargs
="?",
149 help=_("Path to a configuration file to load."))
151 self
.parser
.add_argument("--disable-repo", nargs
="*", metavar
="REPO",
152 help=_("Disable a repository temporarily."), default
=[])
154 self
.parser
.add_argument("--enable-repo", nargs
="*", metavar
="REPO",
155 help=_("Enable a repository temporarily."), default
=[])
158 self
.parser
.add_argument("--offline", action
="store_true",
159 help=_("Run pakfire in offline mode."))
161 def parse_command_install(self
):
162 # Implement the "install" command.
163 sub_install
= self
.sub_commands
.add_parser("install",
164 help=_("Install one or more packages to the system."))
165 sub_install
.add_argument("package", nargs
="+",
166 help=_("Give name of at least one package to install."))
167 sub_install
.add_argument("--without-recommends", action
="store_true",
168 help=_("Don't install recommended packages."))
169 sub_install
.add_argument("action", action
="store_const", const
="install")
171 def parse_command_reinstall(self
):
172 # Implement the "reinstall" command.
173 sub_install
= self
.sub_commands
.add_parser("reinstall",
174 help=_("Reinstall one or more packages."))
175 sub_install
.add_argument("package", nargs
="+",
176 help=_("Give name of at least one package to reinstall."))
177 sub_install
.add_argument("action", action
="store_const", const
="reinstall")
179 def parse_command_remove(self
):
180 # Implement the "remove" command.
181 sub_remove
= self
.sub_commands
.add_parser("remove",
182 help=_("Remove one or more packages from the system."))
183 sub_remove
.add_argument("package", nargs
="+",
184 help=_("Give name of at least one package to remove."))
185 sub_remove
.add_argument("action", action
="store_const", const
="remove")
188 def _parse_command_update(parser
):
189 parser
.add_argument("package", nargs
="*",
190 help=_("Give a name of a package to update or leave emtpy for all."))
191 parser
.add_argument("--exclude", "-x", nargs
="+",
192 help=_("Exclude package from update."))
193 parser
.add_argument("--allow-vendorchange", action
="store_true",
194 help=_("Allow changing the vendor of packages."))
195 parser
.add_argument("--disallow-archchange", action
="store_true",
196 help=_("Disallow changing the architecture of packages."))
198 def parse_command_update(self
):
199 # Implement the "update" command.
200 sub_update
= self
.sub_commands
.add_parser("update",
201 help=_("Update the whole system or one specific package."))
202 sub_update
.add_argument("action", action
="store_const", const
="update")
203 self
._parse
_command
_update
(sub_update
)
205 def parse_command_check_update(self
):
206 # Implement the "check-update" command.
207 sub_check_update
= self
.sub_commands
.add_parser("check-update",
208 help=_("Check, if there are any updates available."))
209 sub_check_update
.add_argument("action", action
="store_const", const
="check_update")
210 self
._parse
_command
_update
(sub_check_update
)
212 def parse_command_downgrade(self
):
213 # Implement the "downgrade" command.
214 sub_downgrade
= self
.sub_commands
.add_parser("downgrade",
215 help=_("Downgrade one or more packages."))
216 sub_downgrade
.add_argument("package", nargs
="*",
217 help=_("Give a name of a package to downgrade."))
218 sub_downgrade
.add_argument("--allow-vendorchange", action
="store_true",
219 help=_("Allow changing the vendor of packages."))
220 sub_downgrade
.add_argument("--disallow-archchange", action
="store_true",
221 help=_("Disallow changing the architecture of packages."))
222 sub_downgrade
.add_argument("action", action
="store_const", const
="downgrade")
224 def parse_command_info(self
):
225 # Implement the "info" command.
226 sub_info
= self
.sub_commands
.add_parser("info",
227 help=_("Print some information about the given package(s)."))
228 sub_info
.add_argument("package", nargs
="+",
229 help=_("Give at least the name of one package."))
230 sub_info
.add_argument("action", action
="store_const", const
="info")
232 def parse_command_search(self
):
233 # Implement the "search" command.
234 sub_search
= self
.sub_commands
.add_parser("search",
235 help=_("Search for a given pattern."))
236 sub_search
.add_argument("pattern",
237 help=_("A pattern to search for."))
238 sub_search
.add_argument("action", action
="store_const", const
="search")
240 def parse_command_provides(self
):
241 # Implement the "provides" command
242 sub_provides
= self
.sub_commands
.add_parser("provides",
243 help=_("Get a list of packages that provide a given file or feature."))
244 sub_provides
.add_argument("pattern", nargs
="+",
245 help=_("File or feature to search for."))
246 sub_provides
.add_argument("action", action
="store_const", const
="provides")
248 def parse_command_grouplist(self
):
249 # Implement the "grouplist" command
250 sub_grouplist
= self
.sub_commands
.add_parser("grouplist",
251 help=_("Get list of packages that belong to the given group."))
252 sub_grouplist
.add_argument("group", nargs
=1,
253 help=_("Group name to search for."))
254 sub_grouplist
.add_argument("action", action
="store_const", const
="grouplist")
256 def parse_command_groupinstall(self
):
257 # Implement the "grouplist" command
258 sub_groupinstall
= self
.sub_commands
.add_parser("groupinstall",
259 help=_("Install all packages that belong to the given group."))
260 sub_groupinstall
.add_argument("group", nargs
=1,
261 help=_("Group name."))
262 sub_groupinstall
.add_argument("action", action
="store_const", const
="groupinstall")
264 def parse_command_repolist(self
):
265 # Implement the "repolist" command
266 sub_repolist
= self
.sub_commands
.add_parser("repolist",
267 help=_("List all currently enabled repositories."))
268 sub_repolist
.add_argument("action", action
="store_const", const
="repolist")
270 def parse_command_clean(self
):
271 sub_clean
= self
.sub_commands
.add_parser("clean", help=_("Cleanup commands."))
273 sub_clean_commands
= sub_clean
.add_subparsers()
275 self
.parse_command_clean_all(sub_clean_commands
)
277 def parse_command_clean_all(self
, sub_commands
):
278 sub_create
= sub_commands
.add_parser("all",
279 help=_("Cleanup all temporary files."))
280 sub_create
.add_argument("action", action
="store_const", const
="clean_all")
282 def parse_command_check(self
):
283 # Implement the "check" command
284 sub_check
= self
.sub_commands
.add_parser("check",
285 help=_("Check the system for any errors."))
286 sub_check
.add_argument("action", action
="store_const", const
="check")
288 def parse_command_resolvdep(self
):
289 # Implement the "resolvdep" command.
290 sub_resolvdep
= self
.sub_commands
.add_parser("resolvdep",
291 help=_("Check the dependencies for a particular package."))
292 sub_resolvdep
.add_argument("package", nargs
=1,
293 help=_("Give name of at least one package to check."))
294 sub_resolvdep
.add_argument("action", action
="store_const", const
="resolvdep")
296 def parse_command_extract(self
):
297 # Implement the "extract" command.
298 sub_extract
= self
.sub_commands
.add_parser("extract",
299 help=_("Extract a package to a directory."))
300 sub_extract
.add_argument("package", nargs
="+",
301 help=_("Give name of the file to extract."))
302 sub_extract
.add_argument("--target", nargs
="?",
303 help=_("Target directory where to extract to."))
304 sub_extract
.add_argument("action", action
="store_const", const
="extract")
307 action
= self
.args
.action
310 func
= self
.action2func
[action
]
312 raise Exception, "Unhandled action: %s" % action
316 def handle_info(self
, long=False):
317 p
= self
.create_pakfire()
319 for pkg
in p
.info(self
.args
.package
):
320 print pkg
.dump(long=long)
322 def handle_search(self
):
323 p
= self
.create_pakfire()
325 for pkg
in p
.search(self
.args
.pattern
):
326 print pkg
.dump(short
=True)
328 def handle_update(self
, **args
):
329 p
= self
.create_pakfire()
332 excludes
=self
.args
.exclude
,
333 allow_vendorchange
=self
.args
.allow_vendorchange
,
334 allow_archchange
=not self
.args
.disallow_archchange
,
338 def handle_check_update(self
):
339 self
.handle_update(check
=True)
341 def handle_downgrade(self
, **args
):
342 p
= self
.create_pakfire()
345 allow_vendorchange
=self
.args
.allow_vendorchange
,
346 allow_archchange
=not self
.args
.disallow_archchange
,
350 def handle_install(self
):
351 p
= self
.create_pakfire()
352 p
.install(self
.args
.package
, ignore_recommended
=self
.args
.without_recommends
)
354 def handle_reinstall(self
):
355 p
= self
.create_pakfire()
356 p
.reinstall(self
.args
.package
)
358 def handle_remove(self
):
359 p
= self
.create_pakfire()
360 p
.remove(self
.args
.package
)
362 def handle_provides(self
, long=False):
363 p
= self
.create_pakfire()
365 for pkg
in p
.provides(self
.args
.pattern
):
366 print pkg
.dump(long=long)
368 def handle_grouplist(self
):
369 p
= self
.create_pakfire()
371 for pkg
in p
.grouplist(self
.args
.group
[0]):
374 def handle_groupinstall(self
):
375 p
= self
.create_pakfire()
376 p
.groupinstall(self
.args
.group
[0])
378 def handle_repolist(self
):
379 p
= self
.create_pakfire()
381 # Get a list of all repositories.
382 repos
= p
.repo_list()
384 FORMAT
= " %-20s %8s %12s %12s "
385 title
= FORMAT
% (_("Repository"), _("Enabled"), _("Priority"), _("Packages"))
387 print "=" * len(title
) # spacing line
390 print FORMAT
% (repo
.name
, repo
.enabled
, repo
.priority
, len(repo
))
392 def handle_clean_all(self
):
393 print _("Cleaning up everything...")
395 p
= self
.create_pakfire()
398 def handle_check(self
):
399 p
= self
.create_pakfire()
402 def handle_resolvdep(self
):
403 p
= self
.create_pakfire()
405 (pkg
,) = self
.args
.package
407 solver
= p
.resolvdep(pkg
)
410 t
= transaction
.Transaction
.from_solver(p
, solver
)
413 def handle_extract(self
):
414 p
= self
.create_pakfire()
418 for pkg
in self
.args
.package
:
419 pkg
= packages
.open(self
, None, pkg
)
422 target_prefix
= self
.args
.target
424 # Search for binary packages.
425 binary_packages
= any([p
.type == "binary" for p
in pkgs
])
426 source_packages
= any([p
.type == "source" for p
in pkgs
])
428 if binary_packages
and source_packages
:
429 raise Error
, _("Cannot extract mixed package types")
431 if binary_packages
and not target_prefix
:
432 raise Error
, _("You must provide an install directory with --target=...")
434 elif source_packages
and not target_prefix
:
435 target_prefix
= "/usr/src/packages/"
437 if target_prefix
== "/":
438 raise Error
, _("Cannot extract to /.")
441 if pkg
.type == "binary":
442 target_dir
= target_prefix
443 elif pkg
.type == "source":
444 target_dir
= os
.path
.join(target_prefix
, pkg
.friendly_name
)
446 pkg
.extract(message
=_("Extracting"), prefix
=target_dir
)
449 class CliBuilder(Cli
):
450 pakfire
= base
.PakfireBuilder
453 # Check if we are already running in a pakfire container. In that
454 # case, we cannot start another pakfire-builder.
455 if os
.environ
.get("container", None) == "pakfire-builder":
456 raise PakfireContainerError
, _("You cannot run pakfire-builder in a pakfire chroot.")
458 self
.parser
= argparse
.ArgumentParser(
459 description
= _("Pakfire builder command line interface."),
462 self
.parse_common_arguments()
465 self
.sub_commands
= self
.parser
.add_subparsers()
467 self
.parse_command_build()
468 self
.parse_command_dist()
469 self
.parse_command_info()
470 self
.parse_command_search()
471 self
.parse_command_shell()
472 self
.parse_command_update()
473 self
.parse_command_provides()
474 self
.parse_command_grouplist()
475 self
.parse_command_repolist()
476 self
.parse_command_clean()
477 self
.parse_command_resolvdep()
478 self
.parse_command_extract()
480 # Finally parse all arguments from the command line and save them.
481 self
.args
= self
.parser
.parse_args()
484 "build" : self
.handle_build
,
485 "dist" : self
.handle_dist
,
486 "update" : self
.handle_update
,
487 "info" : self
.handle_info
,
488 "search" : self
.handle_search
,
489 "shell" : self
.handle_shell
,
490 "provides" : self
.handle_provides
,
491 "grouplist" : self
.handle_grouplist
,
492 "repolist" : self
.handle_repolist
,
493 "clean_all" : self
.handle_clean_all
,
494 "resolvdep" : self
.handle_resolvdep
,
495 "extract" : self
.handle_extract
,
499 def pakfire_args(self
):
501 "arch" : self
.args
.arch
,
504 if hasattr(self
.args
, "offline") and self
.args
.offline
:
505 ret
["downloader"] = {
506 "offline" : self
.args
.offline
,
509 if hasattr(self
.args
, "distro"):
510 ret
["distro_name"] = self
.args
.distro
514 def parse_common_arguments(self
, *args
, **kwargs
):
515 Cli
.parse_common_arguments(self
, *args
, **kwargs
)
517 self
.parser
.add_argument("--distro", nargs
="?",
518 help=_("Choose the distribution configuration to use for build"))
520 self
.parser
.add_argument("--arch", "-a", nargs
="?",
521 help=_("Run pakfire for the given architecture."))
523 def parse_command_update(self
):
524 # Implement the "update" command.
525 sub_update
= self
.sub_commands
.add_parser("update",
526 help=_("Update the package indexes."))
527 sub_update
.add_argument("action", action
="store_const", const
="update")
529 def parse_command_build(self
):
530 # Implement the "build" command.
531 sub_build
= self
.sub_commands
.add_parser("build",
532 help=_("Build one or more packages."))
533 sub_build
.add_argument("package", nargs
=1,
534 help=_("Give name of at least one package to build."))
535 sub_build
.add_argument("action", action
="store_const", const
="build")
537 sub_build
.add_argument("--resultdir", nargs
="?",
538 help=_("Path were the output files should be copied to."))
539 sub_build
.add_argument("-m", "--mode", nargs
="?", default
="development",
540 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
541 sub_build
.add_argument("--after-shell", action
="store_true",
542 help=_("Run a shell after a successful build."))
543 sub_build
.add_argument("--no-install-test", action
="store_true",
544 help=_("Do not perform the install test."))
546 def parse_command_shell(self
):
547 # Implement the "shell" command.
548 sub_shell
= self
.sub_commands
.add_parser("shell",
549 help=_("Go into a shell."))
550 sub_shell
.add_argument("package", nargs
="?",
551 help=_("Give name of a package."))
552 sub_shell
.add_argument("action", action
="store_const", const
="shell")
554 sub_shell
.add_argument("-m", "--mode", nargs
="?", default
="development",
555 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
557 def parse_command_dist(self
):
558 # Implement the "dist" command.
559 sub_dist
= self
.sub_commands
.add_parser("dist",
560 help=_("Generate a source package."))
561 sub_dist
.add_argument("package", nargs
="+",
562 help=_("Give name(s) of a package(s)."))
563 sub_dist
.add_argument("action", action
="store_const", const
="dist")
565 sub_dist
.add_argument("--resultdir", nargs
="?",
566 help=_("Path were the output files should be copied to."))
568 def handle_info(self
):
569 Cli
.handle_info(self
, long=True)
571 def handle_build(self
):
572 # Get the package descriptor from the command line options
573 pkg
= self
.args
.package
[0]
575 # Check, if we got a regular file
576 if os
.path
.exists(pkg
):
577 pkg
= os
.path
.abspath(pkg
)
580 raise FileNotFoundError
, pkg
582 # Check whether to enable the install test.
583 install_test
= not self
.args
.no_install_test
585 if self
.args
.mode
== "release":
588 release_build
= False
590 p
= self
.create_pakfire()
592 install_test
=install_test
,
593 resultdirs
=[self
.args
.resultdir
,],
595 after_shell
=self
.args
.after_shell
,
596 release_build
=release_build
,
599 def handle_shell(self
):
602 # Get the package descriptor from the command line options
603 if self
.args
.package
:
604 pkg
= self
.args
.package
606 # Check, if we got a regular file
607 if os
.path
.exists(pkg
):
608 pkg
= os
.path
.abspath(pkg
)
611 raise FileNotFoundError
, pkg
613 if self
.args
.mode
== "release":
616 release_build
= False
618 p
= self
.create_pakfire()
619 p
.shell(pkg
, release_build
=release_build
)
621 def handle_dist(self
):
622 # Get the packages from the command line options
625 for pkg
in self
.args
.package
:
626 # Check, if we got a regular file
627 if os
.path
.exists(pkg
):
628 pkg
= os
.path
.abspath(pkg
)
632 raise FileNotFoundError
, pkg
634 # Put packages to where the user said or our
635 # current working directory.
636 resultdir
= self
.args
.resultdir
or os
.getcwd()
638 p
= self
.create_pakfire()
640 p
.dist(pkg
, resultdir
=resultdir
)
642 def handle_provides(self
):
643 Cli
.handle_provides(self
, long=True)
646 class CliServer(Cli
):
647 pakfire
= base
.PakfireServer
650 self
.parser
= argparse
.ArgumentParser(
651 description
= _("Pakfire server command line interface."),
654 self
.parse_common_arguments()
657 self
.sub_commands
= self
.parser
.add_subparsers()
659 self
.parse_command_build()
660 self
.parse_command_keepalive()
661 self
.parse_command_repoupdate()
662 self
.parse_command_repo()
663 self
.parse_command_info()
665 # Finally parse all arguments from the command line and save them.
666 self
.args
= self
.parser
.parse_args()
668 self
.server
= server
.Server(**self
.pakfire_args
)
671 "build" : self
.handle_build
,
672 "info" : self
.handle_info
,
673 "keepalive" : self
.handle_keepalive
,
674 "repoupdate" : self
.handle_repoupdate
,
675 "repo_create": self
.handle_repo_create
,
679 def pakfire_args(self
):
682 if hasattr(self
.args
, "offline") and self
.args
.offline
:
683 ret
["downloader"] = {
684 "offline" : self
.args
.offline
,
689 def parse_command_build(self
):
690 # Implement the "build" command.
691 sub_build
= self
.sub_commands
.add_parser("build",
692 help=_("Send a scrach build job to the server."))
693 sub_build
.add_argument("package", nargs
=1,
694 help=_("Give name of at least one package to build."))
695 sub_build
.add_argument("--arch", "-a",
696 help=_("Limit build to only these architecture(s)."))
697 sub_build
.add_argument("action", action
="store_const", const
="build")
699 def parse_command_keepalive(self
):
700 # Implement the "keepalive" command.
701 sub_keepalive
= self
.sub_commands
.add_parser("keepalive",
702 help=_("Send a keepalive to the server."))
703 sub_keepalive
.add_argument("action", action
="store_const",
706 def parse_command_repoupdate(self
):
707 # Implement the "repoupdate" command.
708 sub_repoupdate
= self
.sub_commands
.add_parser("repoupdate",
709 help=_("Update all repositories."))
710 sub_repoupdate
.add_argument("action", action
="store_const",
713 def parse_command_repo(self
):
714 sub_repo
= self
.sub_commands
.add_parser("repo",
715 help=_("Repository management commands."))
717 sub_repo_commands
= sub_repo
.add_subparsers()
719 self
.parse_command_repo_create(sub_repo_commands
)
721 def parse_command_repo_create(self
, sub_commands
):
722 sub_create
= sub_commands
.add_parser("create",
723 help=_("Create a new repository index."))
724 sub_create
.add_argument("path", nargs
=1,
725 help=_("Path to the packages."))
726 sub_create
.add_argument("inputs", nargs
="+",
727 help=_("Path to input packages."))
728 sub_create
.add_argument("--key", "-k", nargs
="?",
729 help=_("Key to sign the repository with."))
730 sub_create
.add_argument("action", action
="store_const", const
="repo_create")
732 def parse_command_info(self
):
733 sub_info
= self
.sub_commands
.add_parser("info",
734 help=_("Dump some information about this machine."))
735 sub_info
.add_argument("action", action
="store_const", const
="info")
737 def handle_keepalive(self
):
738 self
.server
.update_info()
740 def handle_build(self
):
743 arches
= self
.args
.arch
.split()
745 (package
,) = self
.args
.package
747 self
.server
.create_scratch_build({})
750 # Temporary folter for source package.
751 tmpdir
= "/tmp/pakfire-%s" % util
.random_string()
756 pakfire
.dist(package
, resultdir
=[tmpdir
,])
758 for file in os
.listdir(tmpdir
):
759 file = os
.path
.join(tmpdir
, file)
764 if os
.path
.exists(tmpdir
):
767 def handle_repoupdate(self
):
768 self
.server
.update_repositories()
770 def handle_repo_create(self
):
771 path
= self
.args
.path
[0]
773 p
= self
.pakfire(**self
.pakfire_args
)
774 p
.repo_create(path
, self
.args
.inputs
, key_id
=self
.args
.key
)
776 def handle_info(self
):
777 info
= self
.server
.info()
779 print "\n".join(info
)
782 class CliBuilderIntern(Cli
):
784 self
.parser
= argparse
.ArgumentParser(
785 description
= _("Pakfire builder command line interface."),
788 self
.parse_common_arguments()
791 self
.sub_commands
= self
.parser
.add_subparsers()
793 self
.parse_command_build()
795 # Finally parse all arguments from the command line and save them.
796 self
.args
= self
.parser
.parse_args()
799 "build" : self
.handle_build
,
802 def parse_command_build(self
):
803 # Implement the "build" command.
804 sub_build
= self
.sub_commands
.add_parser("build",
805 help=_("Build one or more packages."))
806 sub_build
.add_argument("package", nargs
=1,
807 help=_("Give name of at least one package to build."))
808 sub_build
.add_argument("action", action
="store_const", const
="build")
810 sub_build
.add_argument("-a", "--arch",
811 help=_("Build the package for the given architecture."))
812 sub_build
.add_argument("--resultdir", nargs
="?",
813 help=_("Path were the output files should be copied to."))
814 sub_build
.add_argument("-m", "--mode", nargs
="?", default
="development",
815 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
816 sub_build
.add_argument("--nodeps", action
="store_true",
817 help=_("Do not verify build dependencies."))
818 sub_build
.add_argument("--prepare", action
="store_true",
819 help=_("Only run the prepare stage."))
821 def handle_build(self
):
822 # Get the package descriptor from the command line options
823 pkg
= self
.args
.package
[0]
825 # Check, if we got a regular file
826 if os
.path
.exists(pkg
):
827 pkg
= os
.path
.abspath(pkg
)
829 raise FileNotFoundError
, pkg
831 # Create pakfire instance.
832 c
= config
.ConfigBuilder()
833 p
= base
.Pakfire(arch
= self
.args
.arch
, config
= c
)
835 # Disable all repositories.
837 p
.repos
.disable_repo("*")
839 # Limit stages that are to be run.
840 if self
.args
.prepare
:
845 p
.build(pkg
, resultdir
=self
.args
.resultdir
, stages
=stages
)
848 class CliClient(Cli
):
849 pakfire
= base
.PakfireClient
852 self
.parser
= argparse
.ArgumentParser(
853 description
= _("Pakfire client command line interface."),
856 self
.parse_common_arguments(offline_switch
=True)
859 self
.sub_commands
= self
.parser
.add_subparsers()
861 self
.parse_command_build()
862 self
.parse_command_connection_check()
863 self
.parse_command_info()
864 self
.parse_command_jobs()
865 self
.parse_command_builds()
866 self
.parse_command_test()
868 # Finally parse all arguments from the command line and save them.
869 self
.args
= self
.parser
.parse_args()
872 "build" : self
.handle_build
,
873 "conn-check" : self
.handle_connection_check
,
874 "info" : self
.handle_info
,
875 "jobs_show" : self
.handle_jobs_show
,
876 "jobs_active" : self
.handle_jobs_active
,
877 "jobs_latest" : self
.handle_jobs_latest
,
878 "builds_show" : self
.handle_builds_show
,
879 "test" : self
.handle_test
,
882 # Read configuration for the pakfire client.
883 self
.config
= config
.ConfigClient()
885 # Create connection to pakfire hub.
886 self
.client
= client
.PakfireUserClient(
887 self
.config
.get("client", "server"),
888 self
.config
.get("client", "username"),
889 self
.config
.get("client", "password"),
893 def pakfire_args(self
):
895 "config" : self
.config
,
898 def parse_command_build(self
):
899 # Parse "build" command.
900 sub_build
= self
.sub_commands
.add_parser("build",
901 help=_("Build a package remotely."))
902 sub_build
.add_argument("package", nargs
=1,
903 help=_("Give name of a package to build."))
904 sub_build
.add_argument("action", action
="store_const", const
="build")
906 sub_build
.add_argument("-a", "--arch",
907 help=_("Build the package for the given architecture."))
909 def parse_command_info(self
):
910 # Implement the "info" command.
911 sub_info
= self
.sub_commands
.add_parser("info",
912 help=_("Print some information about this host."))
913 sub_info
.add_argument("action", action
="store_const", const
="info")
915 def parse_command_connection_check(self
):
916 # Implement the "conn-check" command.
917 sub_conn_check
= self
.sub_commands
.add_parser("conn-check",
918 help=_("Check the connection to the hub."))
919 sub_conn_check
.add_argument("action", action
="store_const", const
="conn-check")
921 def parse_command_jobs(self
):
922 sub_jobs
= self
.sub_commands
.add_parser("jobs",
923 help=_("Show information about build jobs."))
925 sub_jobs_commands
= sub_jobs
.add_subparsers()
927 self
.parse_command_jobs_active(sub_jobs_commands
)
928 self
.parse_command_jobs_latest(sub_jobs_commands
)
929 self
.parse_command_jobs_show(sub_jobs_commands
)
931 def parse_command_jobs_active(self
, sub_commands
):
932 sub_active
= sub_commands
.add_parser("active",
933 help=_("Show a list of all active jobs."))
934 sub_active
.add_argument("action", action
="store_const", const
="jobs_active")
936 def parse_command_jobs_latest(self
, sub_commands
):
937 sub_latest
= sub_commands
.add_parser("latest",
938 help=_("Show a list of all recently finished of failed build jobs."))
939 sub_latest
.add_argument("action", action
="store_const", const
="jobs_latest")
941 def parse_command_jobs_show(self
, sub_commands
):
942 sub_show
= sub_commands
.add_parser("show",
943 help=_("Show details about given build job."))
944 sub_show
.add_argument("job_id", nargs
=1, help=_("The ID of the build job."))
945 sub_show
.add_argument("action", action
="store_const", const
="jobs_show")
947 def parse_command_builds(self
):
948 sub_builds
= self
.sub_commands
.add_parser("builds",
949 help=_("Show information about builds."))
951 sub_builds_commands
= sub_builds
.add_subparsers()
953 self
.parse_command_builds_show(sub_builds_commands
)
955 def parse_command_builds_show(self
, sub_commands
):
956 sub_show
= sub_commands
.add_parser("show",
957 help=_("Show details about the given build."))
958 sub_show
.add_argument("build_id", nargs
=1, help=_("The ID of the build."))
959 sub_show
.add_argument("action", action
="store_const", const
="builds_show")
961 def parse_command_test(self
):
962 sub_test
= self
.sub_commands
.add_parser("test",
963 help=_("Test the connection to the hub."))
964 sub_test
.add_argument("error_code", nargs
=1, help=_("Error code to test."))
965 sub_test
.add_argument("action", action
="store_const", const
="test")
967 def handle_build(self
):
968 (package
,) = self
.args
.package
970 # XXX just for now, we do only upload source pfm files.
971 assert os
.path
.exists(package
)
973 # Create a temporary directory.
974 temp_dir
= tempfile
.mkdtemp()
977 if package
.endswith(".%s" % MAKEFILE_EXTENSION
):
980 # Create a source package from the makefile.
981 p
= self
.pakfire(**self
.pakfire_args
)
982 package
= p
.dist(package
, temp_dir
)
984 elif package
.endswith(".%s" % PACKAGE_EXTENSION
):
988 raise Exception, "Unknown filetype: %s" % package
992 arches
= self
.args
.arch
.replace(",", " ")
996 # Create a new build on the server.
997 build
= self
.client
.build_create(package
, arches
=arches
)
999 # XXX Print the resulting build.
1003 # Cleanup the temporary directory and all files.
1004 if os
.path
.exists(temp_dir
):
1005 shutil
.rmtree(temp_dir
, ignore_errors
=True)
1007 def handle_info(self
):
1011 ret
.append(" PAKFIRE %s" % PAKFIRE_VERSION
)
1013 ret
.append(" %-20s: %s" % (_("Hostname"), system
.hostname
))
1014 ret
.append(" %-20s: %s" % (_("Pakfire hub"), self
.config
.get("client", "server")))
1015 if self
.config
.get("client", "username") and self
.config
.get("client", "password"):
1016 ret
.append(" %-20s: %s" % \
1017 (_("Username"), self
.config
.get("client", "username")))
1020 # Hardware information
1021 ret
.append(" %s:" % _("Hardware information"))
1022 ret
.append(" %-16s: %s" % (_("CPU model"), system
.cpu_model
))
1023 ret
.append(" %-16s: %s" % (_("Memory"), util
.format_size(system
.memory
)))
1024 ret
.append(" %-16s: %s" % (_("Parallelism"), system
.parallelism
))
1026 ret
.append(" %-16s: %s" % (_("Native arch"), system
.native_arch
))
1027 if not system
.arch
== system
.native_arch
:
1028 ret
.append(" %-16s: %s" % (_("Default arch"), system
.arch
))
1030 header
= _("Supported arches")
1031 for arch
in system
.supported_arches
:
1032 ret
.append(" %-16s: %s" % (header
, arch
))
1039 def handle_connection_check(self
):
1042 address
= self
.client
.get_my_address()
1043 ret
.append(" %-20s: %s" % (_("Your IP address"), address
))
1046 authenticated
= self
.client
.check_auth()
1048 ret
.append(" %s" % _("You are authenticated to the build service:"))
1050 user
= self
.client
.get_user_profile()
1051 assert user
, "Could not fetch user infomation"
1054 ("name", _("User name")),
1055 ("realname", _("Real name")),
1056 ("email", _("Email address")),
1057 ("registered", _("Registered")),
1060 for key
, desc
in keys
:
1061 ret
.append(" %-18s: %s" % (desc
, user
.get(key
)))
1064 ret
.append(_("You could not be authenticated to the build service."))
1069 def _print_jobs(self
, jobs
, heading
=None):
1071 print "%s:" % heading
1075 line
= " [%(type)8s] %(name)-30s: %(state)s"
1079 print # Empty line at the end.
1081 def handle_jobs_active(self
):
1082 jobs
= self
.client
.get_active_jobs()
1085 print _("No ongoing jobs found.")
1088 self
._print
_jobs
(jobs
, _("Active build jobs"))
1090 def handle_jobs_latest(self
):
1091 jobs
= self
.client
.get_latest_jobs()
1094 print _("No jobs found.")
1097 self
._print
_jobs
(jobs
, _("Recently processed build jobs"))
1099 def handle_builds_show(self
):
1100 (build_id
,) = self
.args
.build_id
1102 build
= self
.client
.get_build(build_id
)
1104 print _("A build with ID %s could not be found.") % build_id
1107 print _("Build: %(name)s") % build
1111 fmt
% (_("State"), build
["state"]),
1112 fmt
% (_("Priority"), build
["priority"]),
1115 lines
.append("%s:" % _("Jobs"))
1116 for job
in build
["jobs"]:
1117 lines
.append(" * [%(uuid)s] %(name)-30s: %(state)s" % job
)
1123 def handle_jobs_show(self
):
1124 (job_id
,) = self
.args
.job_id
1126 job
= self
.client
.get_job(job_id
)
1128 print _("A job with ID %s could not be found.") % job_id
1132 if job
["builder_id"]:
1133 builder
= self
.client
.get_builder(job
["builder_id"])
1135 print _("Job: %(name)s") % job
1139 fmt
% (_("State"), job
["state"]),
1140 fmt
% (_("Arch"), job
["arch"]),
1145 fmt
% (_("Build host"), builder
["name"]),
1150 fmt
% (_("Time created"), job
["time_created"]),
1151 fmt
% (_("Time started"), job
["time_started"]),
1152 fmt
% (_("Time finished"), job
["time_finished"]),
1153 fmt
% (_("Duration"), job
["duration"]),
1157 lines
+= ["", "%s:" % _("Packages")]
1159 for pkg
in job
["packages"]:
1161 "* %(friendly_name)s" % pkg
,
1166 lines
+= [" %s" % line
for line
in pkg_lines
]
1172 def handle_test(self
):
1173 error_code
= self
.args
.error_code
[0]
1176 error_code
= int(error_code
)
1180 if error_code
< 100 or error_code
> 999:
1181 raise Error
, _("Invalid error code given.")
1183 res
= self
.client
.test_code(error_code
)
1184 print _("Reponse from the server: %s") % res
1187 class CliDaemon(Cli
):
1189 self
.parser
= argparse
.ArgumentParser(
1190 description
= _("Pakfire daemon command line interface."),
1193 self
.parse_common_arguments(offline_switch
=True)
1195 # Finally parse all arguments from the command line and save them.
1196 self
.args
= self
.parser
.parse_args()
1200 Runs the pakfire daemon with provided settings.
1202 # Read the configuration file for the daemon.
1203 conf
= config
.ConfigDaemon()
1205 # Create daemon instance.
1206 d
= pakfire
.client
.PakfireDaemon()
1210 # We cannot just kill the daemon, it needs a smooth shutdown.
1211 except (SystemExit, KeyboardInterrupt):
1216 pakfire
= base
.PakfireKey
1219 self
.parser
= argparse
.ArgumentParser(
1220 description
= _("Pakfire key command line interface."),
1223 self
.parse_common_arguments(offline_switch
=True)
1226 self
.sub_commands
= self
.parser
.add_subparsers()
1228 self
.parse_command_generate()
1229 self
.parse_command_import()
1230 self
.parse_command_export()
1231 self
.parse_command_delete()
1232 self
.parse_command_list()
1233 self
.parse_command_sign()
1234 self
.parse_command_verify()
1236 # Finally parse all arguments from the command line and save them.
1237 self
.args
= self
.parser
.parse_args()
1239 self
.action2func
= {
1240 "generate" : self
.handle_generate
,
1241 "import" : self
.handle_import
,
1242 "export" : self
.handle_export
,
1243 "delete" : self
.handle_delete
,
1244 "list" : self
.handle_list
,
1245 "sign" : self
.handle_sign
,
1246 "verify" : self
.handle_verify
,
1250 def pakfire_args(self
):
1253 def parse_command_generate(self
):
1254 # Parse "generate" command.
1255 sub_gen
= self
.sub_commands
.add_parser("generate",
1256 help=_("Import a key from file."))
1257 sub_gen
.add_argument("--realname", nargs
=1,
1258 help=_("The real name of the owner of this key."))
1259 sub_gen
.add_argument("--email", nargs
=1,
1260 help=_("The email address of the owner of this key."))
1261 sub_gen
.add_argument("action", action
="store_const", const
="generate")
1263 def parse_command_import(self
):
1264 # Parse "import" command.
1265 sub_import
= self
.sub_commands
.add_parser("import",
1266 help=_("Import a key from file."))
1267 sub_import
.add_argument("filename", nargs
=1,
1268 help=_("Filename of that key to import."))
1269 sub_import
.add_argument("action", action
="store_const", const
="import")
1271 def parse_command_export(self
):
1272 # Parse "export" command.
1273 sub_export
= self
.sub_commands
.add_parser("export",
1274 help=_("Export a key to a file."))
1275 sub_export
.add_argument("keyid", nargs
=1,
1276 help=_("The ID of the key to export."))
1277 sub_export
.add_argument("filename", nargs
=1,
1278 help=_("Write the key to this file."))
1279 sub_export
.add_argument("action", action
="store_const", const
="export")
1281 def parse_command_delete(self
):
1282 # Parse "delete" command.
1283 sub_del
= self
.sub_commands
.add_parser("delete",
1284 help=_("Delete a key from the local keyring."))
1285 sub_del
.add_argument("keyid", nargs
=1,
1286 help=_("The ID of the key to delete."))
1287 sub_del
.add_argument("action", action
="store_const", const
="delete")
1289 def parse_command_list(self
):
1290 # Parse "list" command.
1291 sub_list
= self
.sub_commands
.add_parser("list",
1292 help=_("List all imported keys."))
1293 sub_list
.add_argument("action", action
="store_const", const
="list")
1295 def parse_command_sign(self
):
1296 # Implement the "sign" command.
1297 sub_sign
= self
.sub_commands
.add_parser("sign",
1298 help=_("Sign one or more packages."))
1299 sub_sign
.add_argument("--key", "-k", nargs
=1,
1300 help=_("Key that is used sign the package(s)."))
1301 sub_sign
.add_argument("package", nargs
="+",
1302 help=_("Package(s) to sign."))
1303 sub_sign
.add_argument("action", action
="store_const", const
="sign")
1305 def parse_command_verify(self
):
1306 # Implement the "verify" command.
1307 sub_verify
= self
.sub_commands
.add_parser("verify",
1308 help=_("Verify one or more packages."))
1309 #sub_verify.add_argument("--key", "-k", nargs=1,
1310 # help=_("Key that is used verify the package(s)."))
1311 sub_verify
.add_argument("package", nargs
="+",
1312 help=_("Package(s) to verify."))
1313 sub_verify
.add_argument("action", action
="store_const", const
="verify")
1315 def handle_generate(self
):
1316 realname
= self
.args
.realname
[0]
1317 email
= self
.args
.email
[0]
1319 print _("Generating the key may take a moment...")
1323 p
= self
.pakfire(**self
.pakfire_args
)
1324 p
.keyring
.gen_key(realname
, email
)
1326 def handle_import(self
):
1327 filename
= self
.args
.filename
[0]
1329 # Simply import the file.
1330 p
= self
.pakfire(**self
.pakfire_args
)
1331 p
.keyring
.import_key(filename
)
1333 def handle_export(self
):
1334 keyid
= self
.args
.keyid
[0]
1335 filename
= self
.args
.filename
[0]
1337 p
= self
.pakfire(**self
.pakfire_args
)
1338 p
.keyring
.export_key(keyid
, filename
)
1340 def handle_delete(self
):
1341 keyid
= self
.args
.keyid
[0]
1343 p
= self
.pakfire(**self
.pakfire_args
)
1344 p
.keyring
.delete_key(keyid
)
1346 def handle_list(self
):
1347 p
= self
.pakfire(**self
.pakfire_args
)
1348 for line
in p
.keyring
.list_keys():
1351 def handle_sign(self
):
1352 # Get the files from the command line options
1355 for file in self
.args
.package
:
1356 # Check, if we got a regular file
1357 if os
.path
.exists(file):
1358 file = os
.path
.abspath(file)
1362 raise FileNotFoundError
, file
1364 key
= self
.args
.key
[0]
1366 # Create pakfire instance.
1367 p
= self
.pakfire(**self
.pakfire_args
)
1371 pkg
= packages
.open(p
, None, file)
1373 print _("Signing %s...") % pkg
.friendly_name
1376 def handle_verify(self
):
1377 # Get the files from the command line options
1380 for file in self
.args
.package
:
1381 # Check, if we got a regular file
1382 if os
.path
.exists(file) and not os
.path
.isdir(file):
1383 file = os
.path
.abspath(file)
1386 # Create pakfire instance.
1387 p
= self
.pakfire(**self
.pakfire_args
)
1391 pkg
= packages
.open(p
, None, file)
1393 print _("Verifying %s...") % pkg
.friendly_name
1397 key
= self
.pakfire
.keyring
.get_key(sig
.fpr
)
1399 subkey
= key
.subkeys
[0]
1401 print " %s %s" % (subkey
.fpr
[-16:], key
.uids
[0].uid
)
1403 print " %s" % _("This signature is valid.")
1406 print " %s <%s>" % (sig
.fpr
, _("Unknown key"))
1407 print " %s" % _("Could not check if this signature is valid.")
1409 created
= datetime
.datetime
.fromtimestamp(sig
.timestamp
)
1410 print " %s" % _("Created: %s") % created
1412 if sig
.exp_timestamp
:
1413 expires
= datetime
.datetime
.fromtimestamp(sig
.exp_timestamp
)
1414 print " %s" % _("Expires: %s") % expires