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