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