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