]> git.ipfire.org Git - people/stevee/pakfire.git/blame - python/pakfire/cli.py
py-compile: Make script more robust for errors.
[people/stevee/pakfire.git] / python / pakfire / cli.py
CommitLineData
47a4cb89 1#!/usr/bin/python
b792d887
MT
2###############################################################################
3# #
4# Pakfire - The IPFire package management system #
5# Copyright (C) 2011 Pakfire development team #
6# #
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. #
11# #
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. #
16# #
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/>. #
19# #
20###############################################################################
47a4cb89
MT
21
22import argparse
68c0e769 23import datetime
936f6b37 24import os
b913e798 25import shutil
47a4cb89 26import sys
b913e798 27import tempfile
47a4cb89 28
c62d93f1
MT
29import pakfire.api as pakfire
30
31import client
32import config
60845a36 33import logger
47a4cb89 34import packages
fa6d335b 35import repository
677ff42a 36import server
e9c20259 37import util
47a4cb89 38
c62d93f1 39from system import system
47a4cb89
MT
40from constants import *
41from i18n import _
42
60845a36
MT
43# Initialize a very simple logging that is removed when a Pakfire instance
44# is started.
45logger.setup_logging()
46
47a4cb89 47class Cli(object):
47a4cb89
MT
48 def __init__(self):
49 self.parser = argparse.ArgumentParser(
50 description = _("Pakfire command line interface."),
51 )
52
53 self.parse_common_arguments()
54
2ba449f0 55 self.parser.add_argument("--root", metavar="PATH",
d2e26956 56 default="/",
47a4cb89
MT
57 help=_("The path where pakfire should operate in."))
58
59 # Add sub-commands.
60 self.sub_commands = self.parser.add_subparsers()
61
62 self.parse_command_install()
0ca71090 63 self.parse_command_reinstall()
a39fd08b 64 self.parse_command_remove()
47a4cb89
MT
65 self.parse_command_info()
66 self.parse_command_search()
e38914be 67 self.parse_command_check_update()
47a4cb89 68 self.parse_command_update()
67d1ddbd 69 self.parse_command_downgrade()
fa6d335b 70 self.parse_command_provides()
c1962d40 71 self.parse_command_grouplist()
ce2764c1 72 self.parse_command_groupinstall()
67bc4528 73 self.parse_command_repolist()
31267a64 74 self.parse_command_clean()
35d89fd7 75 self.parse_command_check()
b25a3d84 76 self.parse_command_resolvdep()
47a4cb89
MT
77
78 # Finally parse all arguments from the command line and save them.
79 self.args = self.parser.parse_args()
80
47a4cb89 81 self.action2func = {
5e87fa4f 82 "install" : self.handle_install,
0ca71090 83 "reinstall" : self.handle_reinstall,
a39fd08b 84 "remove" : self.handle_remove,
e38914be 85 "check_update" : self.handle_check_update,
5e87fa4f 86 "update" : self.handle_update,
67d1ddbd 87 "downgrade" : self.handle_downgrade,
5e87fa4f
MT
88 "info" : self.handle_info,
89 "search" : self.handle_search,
fa6d335b 90 "provides" : self.handle_provides,
c1962d40 91 "grouplist" : self.handle_grouplist,
ce2764c1 92 "groupinstall" : self.handle_groupinstall,
67bc4528 93 "repolist" : self.handle_repolist,
31267a64 94 "clean_all" : self.handle_clean_all,
35d89fd7 95 "check" : self.handle_check,
b25a3d84 96 "resolvdep" : self.handle_resolvdep,
47a4cb89
MT
97 }
98
7c8f2953
MT
99 @property
100 def pakfire_args(self):
6557ff4c
MT
101 ret = { "mode" : "normal" }
102
2ba449f0
MT
103 if hasattr(self.args, "root"):
104 ret["path"] = self.args.root
f9a012a8
MT
105
106 if hasattr(self.args, "disable_repo"):
107 ret["disable_repos"] = self.args.disable_repo
108
109 if hasattr(self.args, "enable_repo"):
110 ret["enable_repos"] = self.args.enable_repo
111
98733451
MT
112 if hasattr(self.args, "offline") and self.args.offline:
113 ret["downloader"] = {
114 "offline" : self.args.offline,
115 }
6a509182 116
854d8ccf
MT
117 if hasattr(self.args, "config"):
118 ret["configs"] = self.args.config
119 else:
120 ret["configs"] = None
121
f9a012a8 122 return ret
7c8f2953 123
c62d93f1 124 def parse_common_arguments(self, repo_manage_switches=True, offline_switch=True):
50381f5c
MT
125 self.parser.add_argument("--version", action="version",
126 version="%(prog)s " + PAKFIRE_VERSION)
127
47a4cb89
MT
128 self.parser.add_argument("-v", "--verbose", action="store_true",
129 help=_("Enable verbose output."))
130
131 self.parser.add_argument("-c", "--config", nargs="?",
132 help=_("Path to a configuration file to load."))
133
c62d93f1
MT
134 if repo_manage_switches:
135 self.parser.add_argument("--disable-repo", nargs="*", metavar="REPO",
136 help=_("Disable a repository temporarily."))
f781b1ab 137
c62d93f1
MT
138 self.parser.add_argument("--enabled-repo", nargs="*", metavar="REPO",
139 help=_("Enable a repository temporarily."))
f9a012a8 140
c62d93f1
MT
141 if offline_switch:
142 self.parser.add_argument("--offline", action="store_true",
143 help=_("Run pakfire in offline mode."))
6a509182 144
47a4cb89
MT
145 def parse_command_install(self):
146 # Implement the "install" command.
147 sub_install = self.sub_commands.add_parser("install",
148 help=_("Install one or more packages to the system."))
149 sub_install.add_argument("package", nargs="+",
150 help=_("Give name of at least one package to install."))
151 sub_install.add_argument("action", action="store_const", const="install")
152
0ca71090
MT
153 def parse_command_reinstall(self):
154 # Implement the "reinstall" command.
155 sub_install = self.sub_commands.add_parser("reinstall",
156 help=_("Reinstall one or more packages."))
157 sub_install.add_argument("package", nargs="+",
158 help=_("Give name of at least one package to reinstall."))
159 sub_install.add_argument("action", action="store_const", const="reinstall")
160
a39fd08b
MT
161 def parse_command_remove(self):
162 # Implement the "remove" command.
163 sub_remove = self.sub_commands.add_parser("remove",
164 help=_("Remove one or more packages from the system."))
165 sub_remove.add_argument("package", nargs="+",
166 help=_("Give name of at least one package to remove."))
167 sub_remove.add_argument("action", action="store_const", const="remove")
168
05fb1da0
MT
169 @staticmethod
170 def _parse_command_update(parser):
171 parser.add_argument("package", nargs="*",
172 help=_("Give a name of a package to update or leave emtpy for all."))
173 parser.add_argument("--exclude", "-x", nargs="+",
174 help=_("Exclude package from update."))
175 parser.add_argument("--allow-vendorchange", action="store_true",
176 help=_("Allow changing the vendor of packages."))
177 parser.add_argument("--allow-archchange", action="store_true",
178 help=_("Allow changing the architecture of packages."))
179
47a4cb89
MT
180 def parse_command_update(self):
181 # Implement the "update" command.
182 sub_update = self.sub_commands.add_parser("update",
183 help=_("Update the whole system or one specific package."))
47a4cb89 184 sub_update.add_argument("action", action="store_const", const="update")
05fb1da0 185 self._parse_command_update(sub_update)
47a4cb89 186
e38914be
MT
187 def parse_command_check_update(self):
188 # Implement the "check-update" command.
189 sub_check_update = self.sub_commands.add_parser("check-update",
190 help=_("Check, if there are any updates available."))
e38914be 191 sub_check_update.add_argument("action", action="store_const", const="check_update")
05fb1da0 192 self._parse_command_update(sub_check_update)
e38914be 193
67d1ddbd
MT
194 def parse_command_downgrade(self):
195 # Implement the "downgrade" command.
196 sub_downgrade = self.sub_commands.add_parser("downgrade",
197 help=_("Downgrade one or more packages."))
198 sub_downgrade.add_argument("package", nargs="*",
199 help=_("Give a name of a package to downgrade."))
200 sub_downgrade.add_argument("--allow-vendorchange", action="store_true",
201 help=_("Allow changing the vendor of packages."))
202 sub_downgrade.add_argument("--allow-archchange", action="store_true",
203 help=_("Allow changing the architecture of packages."))
204 sub_downgrade.add_argument("action", action="store_const", const="downgrade")
205
47a4cb89
MT
206 def parse_command_info(self):
207 # Implement the "info" command.
208 sub_info = self.sub_commands.add_parser("info",
209 help=_("Print some information about the given package(s)."))
210 sub_info.add_argument("package", nargs="+",
211 help=_("Give at least the name of one package."))
212 sub_info.add_argument("action", action="store_const", const="info")
213
214 def parse_command_search(self):
215 # Implement the "search" command.
216 sub_search = self.sub_commands.add_parser("search",
217 help=_("Search for a given pattern."))
218 sub_search.add_argument("pattern",
219 help=_("A pattern to search for."))
220 sub_search.add_argument("action", action="store_const", const="search")
221
fa6d335b
MT
222 def parse_command_provides(self):
223 # Implement the "provides" command
224 sub_provides = self.sub_commands.add_parser("provides",
225 help=_("Get a list of packages that provide a given file or feature."))
226 sub_provides.add_argument("pattern", nargs="+",
227 help=_("File or feature to search for."))
228 sub_provides.add_argument("action", action="store_const", const="provides")
229
c1962d40
MT
230 def parse_command_grouplist(self):
231 # Implement the "grouplist" command
232 sub_grouplist = self.sub_commands.add_parser("grouplist",
233 help=_("Get list of packages that belong to the given group."))
234 sub_grouplist.add_argument("group", nargs=1,
235 help=_("Group name to search for."))
236 sub_grouplist.add_argument("action", action="store_const", const="grouplist")
237
ce2764c1
MT
238 def parse_command_groupinstall(self):
239 # Implement the "grouplist" command
240 sub_groupinstall = self.sub_commands.add_parser("groupinstall",
241 help=_("Install all packages that belong to the given group."))
242 sub_groupinstall.add_argument("group", nargs=1,
243 help=_("Group name."))
244 sub_groupinstall.add_argument("action", action="store_const", const="groupinstall")
245
67bc4528
MT
246 def parse_command_repolist(self):
247 # Implement the "repolist" command
248 sub_repolist = self.sub_commands.add_parser("repolist",
249 help=_("List all currently enabled repositories."))
250 sub_repolist.add_argument("action", action="store_const", const="repolist")
ce2764c1 251
31267a64
MT
252 def parse_command_clean(self):
253 sub_clean = self.sub_commands.add_parser("clean", help=_("Cleanup commands."))
254
255 sub_clean_commands = sub_clean.add_subparsers()
256
257 self.parse_command_clean_all(sub_clean_commands)
258
259 def parse_command_clean_all(self, sub_commands):
260 sub_create = sub_commands.add_parser("all",
261 help=_("Cleanup all temporary files."))
262 sub_create.add_argument("action", action="store_const", const="clean_all")
263
35d89fd7
MT
264 def parse_command_check(self):
265 # Implement the "check" command
266 sub_check = self.sub_commands.add_parser("check",
267 help=_("Check the system for any errors."))
268 sub_check.add_argument("action", action="store_const", const="check")
269
b25a3d84
MT
270 def parse_command_resolvdep(self):
271 # Implement the "resolvdep" command.
272 sub_resolvdep = self.sub_commands.add_parser("resolvdep",
273 help=_("Check the dependencies for a particular package."))
c901e1f8 274 sub_resolvdep.add_argument("package", nargs=1,
b25a3d84
MT
275 help=_("Give name of at least one package to check."))
276 sub_resolvdep.add_argument("action", action="store_const", const="resolvdep")
277
47a4cb89
MT
278 def run(self):
279 action = self.args.action
280
47a4cb89
MT
281 try:
282 func = self.action2func[action]
283 except KeyError:
c62d93f1 284 raise Exception, "Unhandled action: %s" % action
47a4cb89
MT
285
286 return func()
287
9afa5620 288 def handle_info(self, long=False):
7c8f2953 289 pkgs = pakfire.info(self.args.package, **self.pakfire_args)
47a4cb89 290
7c8f2953
MT
291 for pkg in pkgs:
292 print pkg.dump(long=long)
47a4cb89
MT
293
294 def handle_search(self):
7c8f2953 295 pkgs = pakfire.search(self.args.pattern, **self.pakfire_args)
47a4cb89
MT
296
297 for pkg in pkgs:
298 print pkg.dump(short=True)
299
05fb1da0
MT
300 def handle_update(self, **args):
301 args.update(self.pakfire_args)
302
303 pakfire.update(self.args.package, excludes=self.args.exclude,
304 allow_vendorchange=self.args.allow_vendorchange,
305 allow_archchange=self.args.allow_archchange,
306 **args)
47a4cb89 307
e38914be 308 def handle_check_update(self):
05fb1da0 309 self.handle_update(check=True)
e38914be 310
67d1ddbd
MT
311 def handle_downgrade(self, **args):
312 args.update(self.pakfire_args)
313
314 pakfire.downgrade(self.args.package,
315 allow_vendorchange=self.args.allow_vendorchange,
316 allow_archchange=self.args.allow_archchange,
317 **args)
318
e0b99370
MT
319 def handle_install(self):
320 pakfire.install(self.args.package, **self.pakfire_args)
5e87fa4f 321
0ca71090
MT
322 def handle_reinstall(self):
323 pakfire.reinstall(self.args.package, **self.pakfire_args)
324
a39fd08b
MT
325 def handle_remove(self):
326 pakfire.remove(self.args.package, **self.pakfire_args)
327
fa6d335b 328 def handle_provides(self):
7c8f2953 329 pkgs = pakfire.provides(self.args.pattern, **self.pakfire_args)
fa6d335b
MT
330
331 for pkg in pkgs:
332 print pkg.dump()
333
c1962d40 334 def handle_grouplist(self):
7c8f2953 335 pkgs = pakfire.grouplist(self.args.group[0], **self.pakfire_args)
c1962d40
MT
336
337 for pkg in pkgs:
338 print " * %s" % pkg
339
ce2764c1 340 def handle_groupinstall(self):
7c8f2953 341 pakfire.groupinstall(self.args.group[0], **self.pakfire_args)
ce2764c1 342
67bc4528 343 def handle_repolist(self):
7c8f2953 344 repos = pakfire.repo_list(**self.pakfire_args)
67bc4528 345
c605d735 346 FORMAT = " %-20s %8s %12s %12s "
67bc4528 347
c605d735 348 title = FORMAT % (_("Repository"), _("Enabled"), _("Priority"), _("Packages"))
67bc4528
MT
349 print title
350 print "=" * len(title) # spacing line
351
352 for repo in repos:
353 # Skip the installed repository.
354 if repo.name == "installed":
355 continue
356
c605d735 357 print FORMAT % (repo.name, repo.enabled, repo.priority, len(repo))
67bc4528 358
31267a64
MT
359 def handle_clean_all(self):
360 print _("Cleaning up everything...")
361
362 pakfire.clean_all(**self.pakfire_args)
363
35d89fd7
MT
364 def handle_check(self):
365 pakfire.check(**self.pakfire_args)
366
b25a3d84 367 def handle_resolvdep(self):
c901e1f8
MT
368 (pkg,) = self.args.package
369
370 solver = pakfire.resolvdep(pkg, **self.pakfire_args)
371
372 assert solver.status
373 solver.transaction.dump()
b25a3d84 374
47a4cb89
MT
375
376class CliBuilder(Cli):
377 def __init__(self):
936f6b37
MT
378 # Check if we are already running in a pakfire container. In that
379 # case, we cannot start another pakfire-builder.
380 if os.environ.get("container", None) == "pakfire-builder":
381 raise PakfireContainerError, _("You cannot run pakfire-builder in a pakfire chroot.")
382
47a4cb89
MT
383 self.parser = argparse.ArgumentParser(
384 description = _("Pakfire builder command line interface."),
385 )
386
387 self.parse_common_arguments()
388
389 # Add sub-commands.
390 self.sub_commands = self.parser.add_subparsers()
391
392 self.parse_command_build()
393 self.parse_command_dist()
394 self.parse_command_info()
395 self.parse_command_search()
396 self.parse_command_shell()
397 self.parse_command_update()
4fbd4216 398 self.parse_command_provides()
2c84aceb 399 self.parse_command_grouplist()
67bc4528 400 self.parse_command_repolist()
31267a64 401 self.parse_command_clean()
b25a3d84 402 self.parse_command_resolvdep()
3817ae8e 403 self.parse_command_cache()
47a4cb89
MT
404
405 # Finally parse all arguments from the command line and save them.
406 self.args = self.parser.parse_args()
407
47a4cb89 408 self.action2func = {
fa6d335b
MT
409 "build" : self.handle_build,
410 "dist" : self.handle_dist,
411 "update" : self.handle_update,
412 "info" : self.handle_info,
413 "search" : self.handle_search,
414 "shell" : self.handle_shell,
4fbd4216 415 "provides" : self.handle_provides,
2c84aceb 416 "grouplist" : self.handle_grouplist,
67bc4528 417 "repolist" : self.handle_repolist,
31267a64 418 "clean_all" : self.handle_clean_all,
b25a3d84 419 "resolvdep" : self.handle_resolvdep,
3817ae8e
MT
420 "cache_create": self.handle_cache_create,
421 "cache_cleanup": self.handle_cache_cleanup,
47a4cb89
MT
422 }
423
7c8f2953
MT
424 @property
425 def pakfire_args(self):
6557ff4c 426 ret = { "mode" : "builder" }
f9a012a8
MT
427
428 if hasattr(self.args, "disable_repo"):
429 ret["disable_repos"] = self.args.disable_repo
430
431 if hasattr(self.args, "enable_repo"):
432 ret["enable_repos"] = self.args.enable_repo
433
98733451
MT
434 if hasattr(self.args, "offline") and self.args.offline:
435 ret["downloader"] = {
436 "offline" : self.args.offline,
437 }
6a509182 438
f9a012a8 439 return ret
7c8f2953 440
47a4cb89
MT
441 def parse_command_update(self):
442 # Implement the "update" command.
443 sub_update = self.sub_commands.add_parser("update",
444 help=_("Update the package indexes."))
445 sub_update.add_argument("action", action="store_const", const="update")
446
447 def parse_command_build(self):
448 # Implement the "build" command.
449 sub_build = self.sub_commands.add_parser("build",
450 help=_("Build one or more packages."))
451 sub_build.add_argument("package", nargs=1,
452 help=_("Give name of at least one package to build."))
453 sub_build.add_argument("action", action="store_const", const="build")
454
455 sub_build.add_argument("-a", "--arch",
456 help=_("Build the package for the given architecture."))
457 sub_build.add_argument("--resultdir", nargs="?",
458 help=_("Path were the output files should be copied to."))
f22069bb
MT
459 sub_build.add_argument("-m", "--mode", nargs="?", default="development",
460 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
1710ccec
MT
461 sub_build.add_argument("--after-shell", action="store_true",
462 help=_("Run a shell after a successful build."))
4fffe3c4
MT
463 sub_build.add_argument("--no-install-test", action="store_true",
464 help=_("Do not perform the install test."))
47a4cb89
MT
465
466 def parse_command_shell(self):
467 # Implement the "shell" command.
468 sub_shell = self.sub_commands.add_parser("shell",
469 help=_("Go into a shell."))
042266f3 470 sub_shell.add_argument("package", nargs="?",
47a4cb89
MT
471 help=_("Give name of a package."))
472 sub_shell.add_argument("action", action="store_const", const="shell")
473
474 sub_shell.add_argument("-a", "--arch",
475 help=_("Emulated architecture in the shell."))
6ee3d6b9
MT
476 sub_shell.add_argument("-m", "--mode", nargs="?", default="development",
477 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
47a4cb89
MT
478
479 def parse_command_dist(self):
480 # Implement the "dist" command.
481 sub_dist = self.sub_commands.add_parser("dist",
482 help=_("Generate a source package."))
e412b8dc
MT
483 sub_dist.add_argument("package", nargs="+",
484 help=_("Give name(s) of a package(s)."))
47a4cb89
MT
485 sub_dist.add_argument("action", action="store_const", const="dist")
486
487 sub_dist.add_argument("--resultdir", nargs="?",
488 help=_("Path were the output files should be copied to."))
489
3817ae8e
MT
490 def parse_command_cache(self):
491 # Implement the "cache" command.
492 sub_cache = self.sub_commands.add_parser("cache",
493 help=_("Create a build environment cache."))
494
495 # Implement subcommands.
496 sub_cache_commands = sub_cache.add_subparsers()
497
498 self.parse_command_cache_create(sub_cache_commands)
499 self.parse_command_cache_cleanup(sub_cache_commands)
500
501 def parse_command_cache_create(self, sub_commands):
502 sub_create = sub_commands.add_parser("create",
503 help=_("Create a new build environment cache."))
504 sub_create.add_argument("action", action="store_const", const="cache_create")
505
506 def parse_command_cache_cleanup(self, sub_commands):
507 sub_cleanup = sub_commands.add_parser("cleanup",
508 help=_("Remove all cached build environments."))
509 sub_cleanup.add_argument("action", action="store_const", const="cache_cleanup")
510
9afa5620
MT
511 def handle_info(self):
512 Cli.handle_info(self, long=True)
513
47a4cb89 514 def handle_build(self):
47a4cb89
MT
515 # Get the package descriptor from the command line options
516 pkg = self.args.package[0]
517
518 # Check, if we got a regular file
519 if os.path.exists(pkg):
520 pkg = os.path.abspath(pkg)
521
47a4cb89 522 else:
7c8f2953 523 raise FileNotFoundError, pkg
47a4cb89 524
4fffe3c4
MT
525 # Check whether to enable the install test.
526 install_test = not self.args.no_install_test
527
528 pakfire.build(pkg, builder_mode=self.args.mode, install_test=install_test,
a6bd96bc 529 arch=self.args.arch, resultdirs=[self.args.resultdir,],
1710ccec 530 shell=True, after_shell=self.args.after_shell, **self.pakfire_args)
47a4cb89
MT
531
532 def handle_shell(self):
042266f3
MT
533 pkg = None
534
47a4cb89 535 # Get the package descriptor from the command line options
042266f3 536 if self.args.package:
ad1b844f 537 pkg = self.args.package
47a4cb89 538
7c8f2953
MT
539 # Check, if we got a regular file
540 if os.path.exists(pkg):
541 pkg = os.path.abspath(pkg)
47a4cb89 542
7c8f2953
MT
543 else:
544 raise FileNotFoundError, pkg
47a4cb89 545
6ee3d6b9 546 pakfire.shell(pkg, builder_mode=self.args.mode,
a6bd96bc 547 arch=self.args.arch, **self.pakfire_args)
47a4cb89
MT
548
549 def handle_dist(self):
e412b8dc
MT
550 # Get the packages from the command line options
551 pkgs = []
47a4cb89 552
e412b8dc
MT
553 for pkg in self.args.package:
554 # Check, if we got a regular file
555 if os.path.exists(pkg):
556 pkg = os.path.abspath(pkg)
7c8f2953 557 pkgs.append(pkg)
47a4cb89 558
e412b8dc 559 else:
7c8f2953
MT
560 raise FileNotFoundError, pkg
561
7d40ac70
MT
562 # Put packages to where the user said or our
563 # current working directory.
564 resultdir = self.args.resultdir or os.getcwd()
565
566 # Change the default pakfire configuration, because
567 # packaging source packages can be done in server mode.
568 pakfire_args = self.pakfire_args
569 pakfire_args["mode"] = "server"
570
571 for pkg in pkgs:
572 pakfire.dist(pkg, resultdir=resultdir, **pakfire_args)
47a4cb89 573
c605d735
MT
574 def handle_provides(self):
575 pkgs = pakfire.provides(self.args.pattern, **self.pakfire_args)
576
577 for pkg in pkgs:
578 print pkg.dump(long=True)
579
3817ae8e
MT
580 def handle_cache_create(self):
581 pakfire.cache_create(**self.pakfire_args)
582
583 def handle_cache_cleanup(self):
584 for env in os.listdir(CACHE_ENVIRON_DIR):
585 if not env.endswith(".cache"):
586 continue
587
588 print _("Removing environment cache file: %s..." % env)
589 env = os.path.join(CACHE_ENVIRON_DIR, env)
590
591 try:
592 os.unlink(env)
593 except OSError:
594 print _("Could not remove file: %s") % env
595
47a4cb89 596
3ad4bb5a 597class CliServer(Cli):
677ff42a
MT
598 def __init__(self):
599 self.parser = argparse.ArgumentParser(
3ad4bb5a 600 description = _("Pakfire server command line interface."),
677ff42a
MT
601 )
602
603 self.parse_common_arguments()
604
605 # Add sub-commands.
606 self.sub_commands = self.parser.add_subparsers()
607
a52f536c 608 self.parse_command_build()
677ff42a 609 self.parse_command_keepalive()
8276111d 610 self.parse_command_repoupdate()
df9c4f62 611 self.parse_command_repo()
aad6f600 612 self.parse_command_info()
677ff42a
MT
613
614 # Finally parse all arguments from the command line and save them.
615 self.args = self.parser.parse_args()
616
269c59f3 617 self.server = server.Server(**self.pakfire_args)
677ff42a
MT
618
619 self.action2func = {
8276111d 620 "build" : self.handle_build,
aad6f600 621 "info" : self.handle_info,
8276111d
MT
622 "keepalive" : self.handle_keepalive,
623 "repoupdate" : self.handle_repoupdate,
df9c4f62 624 "repo_create": self.handle_repo_create,
677ff42a
MT
625 }
626
6557ff4c
MT
627 @property
628 def pakfire_args(self):
629 ret = { "mode" : "server" }
630
98733451
MT
631 if hasattr(self.args, "offline") and self.args.offline:
632 ret["downloader"] = {
633 "offline" : self.args.offline,
634 }
6a509182 635
6557ff4c
MT
636 return ret
637
a52f536c
MT
638 def parse_command_build(self):
639 # Implement the "build" command.
c62d93f1
MT
640 sub_build = self.sub_commands.add_parser("build",
641 help=_("Send a scrach build job to the server."))
642 sub_build.add_argument("package", nargs=1,
643 help=_("Give name of at least one package to build."))
644 sub_build.add_argument("--arch", "-a",
645 help=_("Limit build to only these architecture(s)."))
646 sub_build.add_argument("action", action="store_const", const="build")
a52f536c 647
677ff42a
MT
648 def parse_command_keepalive(self):
649 # Implement the "keepalive" command.
650 sub_keepalive = self.sub_commands.add_parser("keepalive",
651 help=_("Send a keepalive to the server."))
652 sub_keepalive.add_argument("action", action="store_const",
653 const="keepalive")
654
8276111d
MT
655 def parse_command_repoupdate(self):
656 # Implement the "repoupdate" command.
657 sub_repoupdate = self.sub_commands.add_parser("repoupdate",
658 help=_("Update all repositories."))
659 sub_repoupdate.add_argument("action", action="store_const",
660 const="repoupdate")
661
df9c4f62
MT
662 def parse_command_repo(self):
663 sub_repo = self.sub_commands.add_parser("repo",
664 help=_("Repository management commands."))
665
666 sub_repo_commands = sub_repo.add_subparsers()
667
668 self.parse_command_repo_create(sub_repo_commands)
669
670 def parse_command_repo_create(self, sub_commands):
671 sub_create = sub_commands.add_parser("create",
672 help=_("Create a new repository index."))
68c0e769
MT
673 sub_create.add_argument("path", nargs=1,
674 help=_("Path to the packages."))
675 sub_create.add_argument("inputs", nargs="+",
676 help=_("Path to input packages."))
677 sub_create.add_argument("--key", "-k", nargs="?",
678 help=_("Key to sign the repository with."))
df9c4f62
MT
679 sub_create.add_argument("action", action="store_const", const="repo_create")
680
aad6f600
MT
681 def parse_command_info(self):
682 sub_info = self.sub_commands.add_parser("info",
683 help=_("Dump some information about this machine."))
684 sub_info.add_argument("action", action="store_const", const="info")
685
677ff42a 686 def handle_keepalive(self):
3ad4bb5a 687 self.server.update_info()
9613a111 688
a52f536c 689 def handle_build(self):
c62d93f1
MT
690 # Arch.
691 if self.args.arch:
692 arches = self.args.arch.split()
693
694 (package,) = self.args.package
695
696 self.server.create_scratch_build({})
697 return
698
699 # Temporary folter for source package.
700 tmpdir = "/tmp/pakfire-%s" % util.random_string()
701
702 try:
703 os.makedirs(tmpdir)
704
705 pakfire.dist(package, resultdir=[tmpdir,])
706
707 for file in os.listdir(tmpdir):
708 file = os.path.join(tmpdir, file)
709
710 print file
711
712 finally:
713 if os.path.exists(tmpdir):
714 util.rm(tmpdir)
8276111d
MT
715
716 def handle_repoupdate(self):
717 self.server.update_repositories()
df9c4f62
MT
718
719 def handle_repo_create(self):
720 path = self.args.path[0]
721
68c0e769
MT
722 pakfire.repo_create(path, self.args.inputs, key_id=self.args.key,
723 **self.pakfire_args)
c07a3ca7 724
aad6f600
MT
725 def handle_info(self):
726 info = self.server.info()
727
728 print "\n".join(info)
729
c07a3ca7 730
9b875540 731class CliBuilderIntern(Cli):
c07a3ca7
MT
732 def __init__(self):
733 self.parser = argparse.ArgumentParser(
734 description = _("Pakfire builder command line interface."),
735 )
736
737 self.parse_common_arguments()
738
739 # Add sub-commands.
740 self.sub_commands = self.parser.add_subparsers()
741
742 self.parse_command_build()
743
744 # Finally parse all arguments from the command line and save them.
745 self.args = self.parser.parse_args()
746
747 self.action2func = {
748 "build" : self.handle_build,
749 }
750
751 def parse_command_build(self):
752 # Implement the "build" command.
753 sub_build = self.sub_commands.add_parser("build",
754 help=_("Build one or more packages."))
755 sub_build.add_argument("package", nargs=1,
756 help=_("Give name of at least one package to build."))
757 sub_build.add_argument("action", action="store_const", const="build")
758
759 sub_build.add_argument("-a", "--arch",
760 help=_("Build the package for the given architecture."))
761 sub_build.add_argument("--resultdir", nargs="?",
762 help=_("Path were the output files should be copied to."))
763 sub_build.add_argument("-m", "--mode", nargs="?", default="development",
764 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
765 sub_build.add_argument("--nodeps", action="store_true",
766 help=_("Do not verify build dependencies."))
767
768 def handle_build(self):
769 # Get the package descriptor from the command line options
770 pkg = self.args.package[0]
771
772 # Check, if we got a regular file
773 if os.path.exists(pkg):
774 pkg = os.path.abspath(pkg)
775 else:
776 raise FileNotFoundError, pkg
777
854d8ccf
MT
778 conf = config.ConfigBuilder()
779
8fe602a7
MT
780 if self.args.nodeps:
781 disable_repos = ["*"]
782 else:
783 disable_repos = None
784
4fffe3c4
MT
785 kwargs = {
786 "arch" : self.args.arch,
787 "builder_mode" : self.args.mode,
788 "config" : conf,
789 "disable_repos" : disable_repos,
790 "resultdir" : self.args.resultdir,
791 }
792
793 pakfire._build(pkg, **kwargs)
c62d93f1
MT
794
795
796class CliClient(Cli):
797 def __init__(self):
798 self.parser = argparse.ArgumentParser(
799 description = _("Pakfire client command line interface."),
800 )
801
802 self.parse_common_arguments(repo_manage_switches=True, offline_switch=True)
803
804 # Add sub-commands.
805 self.sub_commands = self.parser.add_subparsers()
806
807 self.parse_command_build()
808 self.parse_command_connection_check()
809 self.parse_command_info()
25a98632
MT
810 self.parse_command_jobs()
811 self.parse_command_builds()
37ff3f8f 812 self.parse_command_test()
c62d93f1
MT
813
814 # Finally parse all arguments from the command line and save them.
815 self.args = self.parser.parse_args()
816
817 self.action2func = {
818 "build" : self.handle_build,
819 "conn-check" : self.handle_connection_check,
820 "info" : self.handle_info,
25a98632
MT
821 "jobs_show" : self.handle_jobs_show,
822 "jobs_active" : self.handle_jobs_active,
823 "jobs_latest" : self.handle_jobs_latest,
824 "builds_show" : self.handle_builds_show,
37ff3f8f 825 "test" : self.handle_test,
c62d93f1
MT
826 }
827
828 # Read configuration for the pakfire client.
829 self.conf = conf = config.ConfigClient()
830
831 # Create connection to pakfire hub.
832 self.client = client.PakfireUserClient(
833 conf.get("client", "server"),
834 conf.get("client", "username"),
835 conf.get("client", "password"),
836 )
837
838 def parse_command_build(self):
839 # Parse "build" command.
840 sub_build = self.sub_commands.add_parser("build",
841 help=_("Build a package remotely."))
842 sub_build.add_argument("package", nargs=1,
843 help=_("Give name of a package to build."))
844 sub_build.add_argument("action", action="store_const", const="build")
845
846 sub_build.add_argument("-a", "--arch",
847 help=_("Build the package for the given architecture."))
848
849 def parse_command_info(self):
850 # Implement the "info" command.
851 sub_info = self.sub_commands.add_parser("info",
852 help=_("Print some information about this host."))
853 sub_info.add_argument("action", action="store_const", const="info")
854
855 def parse_command_connection_check(self):
856 # Implement the "conn-check" command.
857 sub_conn_check = self.sub_commands.add_parser("conn-check",
858 help=_("Check the connection to the hub."))
859 sub_conn_check.add_argument("action", action="store_const", const="conn-check")
860
25a98632
MT
861 def parse_command_jobs(self):
862 sub_jobs = self.sub_commands.add_parser("jobs",
863 help=_("Show information about build jobs."))
864
865 sub_jobs_commands = sub_jobs.add_subparsers()
866
867 self.parse_command_jobs_active(sub_jobs_commands)
868 self.parse_command_jobs_latest(sub_jobs_commands)
869 self.parse_command_jobs_show(sub_jobs_commands)
870
871 def parse_command_jobs_active(self, sub_commands):
872 sub_active = sub_commands.add_parser("active",
873 help=_("Show a list of all active jobs."))
874 sub_active.add_argument("action", action="store_const", const="jobs_active")
875
876 def parse_command_jobs_latest(self, sub_commands):
877 sub_latest = sub_commands.add_parser("latest",
878 help=_("Show a list of all recently finished of failed build jobs."))
879 sub_latest.add_argument("action", action="store_const", const="jobs_latest")
880
881 def parse_command_jobs_show(self, sub_commands):
882 sub_show = sub_commands.add_parser("show",
883 help=_("Show details about given build job."))
884 sub_show.add_argument("job_id", nargs=1, help=_("The ID of the build job."))
885 sub_show.add_argument("action", action="store_const", const="jobs_show")
886
887 def parse_command_builds(self):
888 sub_builds = self.sub_commands.add_parser("builds",
889 help=_("Show information about builds."))
890
891 sub_builds_commands = sub_builds.add_subparsers()
892
893 self.parse_command_builds_show(sub_builds_commands)
894
895 def parse_command_builds_show(self, sub_commands):
896 sub_show = sub_commands.add_parser("show",
897 help=_("Show details about the given build."))
898 sub_show.add_argument("build_id", nargs=1, help=_("The ID of the build."))
899 sub_show.add_argument("action", action="store_const", const="builds_show")
900
37ff3f8f
MT
901 def parse_command_test(self):
902 sub_test = self.sub_commands.add_parser("test",
903 help=_("Test the connection to the hub."))
904 sub_test.add_argument("error_code", nargs=1, help=_("Error code to test."))
905 sub_test.add_argument("action", action="store_const", const="test")
906
c62d93f1
MT
907 def handle_build(self):
908 (package,) = self.args.package
909
910 # XXX just for now, we do only upload source pfm files.
911 assert os.path.exists(package)
912
b913e798
MT
913 # Create a temporary directory.
914 temp_dir = tempfile.mkdtemp()
915
916 try:
917 if package.endswith(".%s" % MAKEFILE_EXTENSION):
918 pakfire_args = { "mode" : "server" }
919
920 # Create a source package from the makefile.
921 package = pakfire.dist(package, temp_dir, **pakfire_args)
922
923 elif package.endswith(".%s" % PACKAGE_EXTENSION):
924 pass
c62d93f1 925
b913e798
MT
926 else:
927 raise Exception, "Unknown filetype: %s" % package
928
929 # Format arches.
930 if self.args.arch:
931 arches = self.args.arch.replace(",", " ")
932 else:
933 arches = None
c62d93f1 934
b913e798
MT
935 # Create a new build on the server.
936 build = self.client.build_create(package, arches=arches)
937
938 # XXX Print the resulting build.
939 print build
940
941 finally:
942 # Cleanup the temporary directory and all files.
943 if os.path.exists(temp_dir):
944 shutil.rmtree(temp_dir, ignore_errors=True)
c62d93f1
MT
945
946 def handle_info(self):
947 ret = []
948
949 ret.append("")
950 ret.append(" PAKFIRE %s" % PAKFIRE_VERSION)
951 ret.append("")
952 ret.append(" %-20s: %s" % (_("Hostname"), system.hostname))
953 ret.append(" %-20s: %s" % (_("Pakfire hub"), self.conf.get("client", "server")))
954 if self.conf.get("client", "username") and self.conf.get("client", "password"):
955 ret.append(" %-20s: %s" % \
956 (_("Username"), self.conf.get("client", "username")))
957 ret.append("")
958
959 # Hardware information
960 ret.append(" %s:" % _("Hardware information"))
961 ret.append(" %-16s: %s" % (_("CPU model"), system.cpu_model))
962 ret.append(" %-16s: %s" % (_("Memory"), util.format_size(system.memory)))
cae35096 963 ret.append(" %-16s: %s" % (_("Parallelism"), system.parallelism))
c62d93f1 964 ret.append("")
790a44cc
MT
965 ret.append(" %-16s: %s" % (_("Native arch"), system.native_arch))
966 if not system.arch == system.native_arch:
967 ret.append(" %-16s: %s" % (_("Default arch"), system.arch))
c62d93f1
MT
968
969 header = _("Supported arches")
970 for arch in system.supported_arches:
971 ret.append(" %-16s: %s" % (header, arch))
972 header = ""
973 ret.append("")
974
975 for line in ret:
976 print line
977
978 def handle_connection_check(self):
979 ret = []
980
981 address = self.client.get_my_address()
982 ret.append(" %-20s: %s" % (_("Your IP address"), address))
983 ret.append("")
984
985 authenticated = self.client.check_auth()
986 if authenticated:
987 ret.append(" %s" % _("You are authenticated to the build service:"))
988
989 user = self.client.get_user_profile()
990 assert user, "Could not fetch user infomation"
991
992 keys = [
993 ("name", _("User name")),
994 ("realname", _("Real name")),
995 ("email", _("Email address")),
996 ("registered", _("Registered")),
997 ]
998
999 for key, desc in keys:
1000 ret.append(" %-18s: %s" % (desc, user.get(key)))
1001
1002 else:
1003 ret.append(_("You could not be authenticated to the build service."))
1004
1005 for line in ret:
1006 print line
1007
25a98632
MT
1008 def _print_jobs(self, jobs, heading=None):
1009 if heading:
1010 print "%s:" % heading
1011 print
1012
1013 for job in jobs:
1014 line = " [%(type)8s] %(name)-30s: %(state)s"
1015
1016 print line % job
1017
1018 print # Empty line at the end.
1019
1020 def handle_jobs_active(self):
1021 jobs = self.client.get_active_jobs()
1022
1023 if not jobs:
1024 print _("No ongoing jobs found.")
1025 return
1026
1027 self._print_jobs(jobs, _("Active build jobs"))
1028
1029 def handle_jobs_latest(self):
1030 jobs = self.client.get_latest_jobs()
1031
1032 if not jobs:
1033 print _("No jobs found.")
1034 return
1035
1036 self._print_jobs(jobs, _("Recently processed build jobs"))
1037
1038 def handle_builds_show(self):
1039 (build_id,) = self.args.build_id
1040
1041 build = self.client.get_build(build_id)
1042 if not build:
1043 print _("A build with ID %s could not be found.") % build_id
1044 return
1045
1046 print _("Build: %(name)s") % build
1047
1048 fmt = "%-14s: %s"
1049 lines = [
1050 fmt % (_("State"), build["state"]),
1051 fmt % (_("Priority"), build["priority"]),
1052 ]
1053
1054 lines.append("%s:" % _("Jobs"))
1055 for job in build["jobs"]:
1056 lines.append(" * [%(uuid)s] %(name)-30s: %(state)s" % job)
1057
1058 for line in lines:
1059 print " ", line
1060 print
1061
1062 def handle_jobs_show(self):
1063 (job_id,) = self.args.job_id
1064
1065 job = self.client.get_job(job_id)
1066 if not job:
1067 print _("A job with ID %s could not be found.") % job_id
1068 return
1069
1070 builder = None
1071 if job["builder_id"]:
1072 builder = self.client.get_builder(job["builder_id"])
1073
1074 print _("Job: %(name)s") % job
1075
1076 fmt = "%-14s: %s"
1077 lines = [
1078 fmt % (_("State"), job["state"]),
1079 fmt % (_("Arch"), job["arch"]),
1080 ]
1081
1082 if builder:
1083 lines += [
1084 fmt % (_("Build host"), builder["name"]),
1085 "",
1086 ]
1087
1088 lines += [
1089 fmt % (_("Time created"), job["time_created"]),
1090 fmt % (_("Time started"), job["time_started"]),
1091 fmt % (_("Time finished"), job["time_finished"]),
1092 fmt % (_("Duration"), job["duration"]),
1093 ]
1094
1095 if job["packages"]:
1096 lines += ["", "%s:" % _("Packages")]
1097
1098 for pkg in job["packages"]:
1099 pkg_lines = [
1100 "* %(friendly_name)s" % pkg,
1101 " %(uuid)s" % pkg,
1102 "",
1103 ]
1104
1105 lines += [" %s" % line for line in pkg_lines]
1106
1107 for line in lines:
1108 print " ", line
1109 print # New line.
1110
37ff3f8f
MT
1111 def handle_test(self):
1112 error_code = self.args.error_code[0]
1113
1114 try:
1115 error_code = int(error_code)
1116 except ValueError:
1117 error_code = 0
1118
1119 if error_code < 100 or error_code > 999:
1120 raise Error, _("Invalid error code given.")
1121
1122 res = self.client.test_code(error_code)
1123 print _("Reponse from the server: %s") % res
1124
c62d93f1
MT
1125
1126class CliDaemon(Cli):
1127 def __init__(self):
1128 self.parser = argparse.ArgumentParser(
1129 description = _("Pakfire daemon command line interface."),
1130 )
1131
1132 self.parse_common_arguments(repo_manage_switches=True, offline_switch=True)
1133
1134 # Finally parse all arguments from the command line and save them.
1135 self.args = self.parser.parse_args()
1136
1137 def run(self):
1138 """
1139 Runs the pakfire daemon with provided settings.
1140 """
1141 # Read the configuration file for the daemon.
1142 conf = config.ConfigDaemon()
1143
1144 # Create daemon instance.
2dbaea05 1145 d = pakfire.client.PakfireDaemon()
c62d93f1
MT
1146 try:
1147 d.run()
1148
1149 # We cannot just kill the daemon, it needs a smooth shutdown.
1150 except (SystemExit, KeyboardInterrupt):
1151 d.shutdown()
68c0e769
MT
1152
1153
1154class CliKey(Cli):
1155 def __init__(self):
1156 self.parser = argparse.ArgumentParser(
1157 description = _("Pakfire key command line interface."),
1158 )
1159
1160 self.parse_common_arguments(repo_manage_switches=False,
1161 offline_switch=True)
1162
1163 # Add sub-commands.
1164 self.sub_commands = self.parser.add_subparsers()
1165
68c0e769
MT
1166 self.parse_command_generate()
1167 self.parse_command_import()
1168 self.parse_command_export()
eaf999ef 1169 self.parse_command_delete()
68c0e769
MT
1170 self.parse_command_list()
1171 self.parse_command_sign()
1172 self.parse_command_verify()
1173
1174 # Finally parse all arguments from the command line and save them.
1175 self.args = self.parser.parse_args()
1176
1177 # Create a pakfire instance.
1178 self.pakfire = pakfire.Pakfire(**self.pakfire_args)
1179
1180 self.action2func = {
68c0e769
MT
1181 "generate" : self.handle_generate,
1182 "import" : self.handle_import,
1183 "export" : self.handle_export,
eaf999ef 1184 "delete" : self.handle_delete,
68c0e769
MT
1185 "list" : self.handle_list,
1186 "sign" : self.handle_sign,
1187 "verify" : self.handle_verify,
1188 }
1189
1190 @property
1191 def pakfire_args(self):
1192 ret = {
1193 "mode" : "server",
1194 }
1195
1196 return ret
1197
68c0e769
MT
1198 def parse_command_generate(self):
1199 # Parse "generate" command.
1200 sub_gen = self.sub_commands.add_parser("generate",
1201 help=_("Import a key from file."))
1202 sub_gen.add_argument("--realname", nargs=1,
1203 help=_("The real name of the owner of this key."))
1204 sub_gen.add_argument("--email", nargs=1,
1205 help=_("The email address of the owner of this key."))
1206 sub_gen.add_argument("action", action="store_const", const="generate")
1207
1208 def parse_command_import(self):
1209 # Parse "import" command.
1210 sub_import = self.sub_commands.add_parser("import",
1211 help=_("Import a key from file."))
1212 sub_import.add_argument("filename", nargs=1,
1213 help=_("Filename of that key to import."))
1214 sub_import.add_argument("action", action="store_const", const="import")
1215
1216 def parse_command_export(self):
1217 # Parse "export" command.
1218 sub_export = self.sub_commands.add_parser("export",
1219 help=_("Export a key to a file."))
1220 sub_export.add_argument("keyid", nargs=1,
1221 help=_("The ID of the key to export."))
1222 sub_export.add_argument("filename", nargs=1,
1223 help=_("Write the key to this file."))
a78770d3
MT
1224 sub_export.add_argument("--secret", action="store_true",
1225 help=_("Export the secret key, too."))
68c0e769
MT
1226 sub_export.add_argument("action", action="store_const", const="export")
1227
eaf999ef
MT
1228 def parse_command_delete(self):
1229 # Parse "delete" command.
1230 sub_del = self.sub_commands.add_parser("delete",
1231 help=_("Delete a key from the local keyring."))
1232 sub_del.add_argument("keyid", nargs=1,
1233 help=_("The ID of the key to delete."))
1234 sub_del.add_argument("action", action="store_const", const="delete")
1235
68c0e769
MT
1236 def parse_command_list(self):
1237 # Parse "list" command.
1238 sub_list = self.sub_commands.add_parser("list",
1239 help=_("List all imported keys."))
1240 sub_list.add_argument("action", action="store_const", const="list")
1241
1242 def parse_command_sign(self):
1243 # Implement the "sign" command.
1244 sub_sign = self.sub_commands.add_parser("sign",
1245 help=_("Sign one or more packages."))
1246 sub_sign.add_argument("--key", "-k", nargs=1,
1247 help=_("Key that is used sign the package(s)."))
1248 sub_sign.add_argument("package", nargs="+",
1249 help=_("Package(s) to sign."))
1250 sub_sign.add_argument("action", action="store_const", const="sign")
1251
1252 def parse_command_verify(self):
1253 # Implement the "verify" command.
1254 sub_verify = self.sub_commands.add_parser("verify",
1255 help=_("Verify one or more packages."))
1256 #sub_verify.add_argument("--key", "-k", nargs=1,
1257 # help=_("Key that is used verify the package(s)."))
1258 sub_verify.add_argument("package", nargs="+",
1259 help=_("Package(s) to verify."))
1260 sub_verify.add_argument("action", action="store_const", const="verify")
1261
68c0e769
MT
1262 def handle_generate(self):
1263 realname = self.args.realname[0]
1264 email = self.args.email[0]
1265
1266 print _("Generating the key may take a moment...")
1267 print
1268
1269 # Generate the key.
1389d9d5 1270 pakfire.key_generate(realname, email, **self.pakfire_args)
68c0e769
MT
1271
1272 def handle_import(self):
1273 filename = self.args.filename[0]
1274
1275 # Simply import the file.
1276 pakfire.key_import(filename, **self.pakfire_args)
1277
1278 def handle_export(self):
1279 keyid = self.args.keyid[0]
1280 filename = self.args.filename[0]
a78770d3 1281 secret = self.args.secret
68c0e769 1282
a78770d3 1283 pakfire.key_export(keyid, filename, secret=secret, **self.pakfire_args)
68c0e769 1284
eaf999ef
MT
1285 def handle_delete(self):
1286 keyid = self.args.keyid[0]
1287
1288 pakfire.key_delete(keyid, **self.pakfire_args)
1289
68c0e769
MT
1290 def handle_list(self):
1291 lines = pakfire.key_list(**self.pakfire_args)
1292
1293 for line in lines:
1294 print line
1295
1296 def handle_sign(self):
1297 # Get the files from the command line options
1298 files = []
1299
1300 for file in self.args.package:
1301 # Check, if we got a regular file
1302 if os.path.exists(file):
1303 file = os.path.abspath(file)
1304 files.append(file)
1305
1306 else:
1307 raise FileNotFoundError, file
1308
1309 key = self.args.key[0]
1310
1311 for file in files:
1312 # Open the package.
1313 pkg = packages.open(self.pakfire, None, file)
1314
1315 print _("Signing %s...") % pkg.friendly_name
1316 pkg.sign(key)
1317
1318 def handle_verify(self):
1319 # Get the files from the command line options
1320 files = []
1321
1322 for file in self.args.package:
1323 # Check, if we got a regular file
1324 if os.path.exists(file) and not os.path.isdir(file):
1325 file = os.path.abspath(file)
1326 files.append(file)
1327
1328 for file in files:
1329 # Open the package.
1330 pkg = packages.open(self.pakfire, None, file)
1331
1332 print _("Verifying %s...") % pkg.friendly_name
1333 sigs = pkg.verify()
1334
1335 for sig in sigs:
1336 key = self.pakfire.keyring.get_key(sig.fpr)
1337 if key:
1338 subkey = key.subkeys[0]
1339
1340 print " %s %s" % (subkey.fpr[-16:], key.uids[0].uid)
1341 if sig.validity:
1342 print " %s" % _("This signature is valid.")
1343
1344 else:
1345 print " %s <%s>" % (sig.fpr, _("Unknown key"))
1346 print " %s" % _("Could not check if this signature is valid.")
1347
1348 created = datetime.datetime.fromtimestamp(sig.timestamp)
1349 print " %s" % _("Created: %s") % created
1350
1351 if sig.exp_timestamp:
1352 expires = datetime.datetime.fromtimestamp(sig.exp_timestamp)
1353 print " %s" % _("Expires: %s") % expires
1354
1355 print # Empty line