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