]>
git.ipfire.org Git - people/stevee/pakfire.git/blob - src/pakfire/cli.py
2 ###############################################################################
4 # Pakfire - The IPFire package management system #
5 # Copyright (C) 2011 Pakfire development team #
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. #
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. #
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/>. #
20 ###############################################################################
40 from .system
import system
41 from .constants
import *
48 self
.ui
= ui
.cli
.CliUI()
51 parser
= argparse
.ArgumentParser(
52 description
= _("Pakfire command line interface"),
54 subparsers
= parser
.add_subparsers()
56 # Add common arguments
57 self
._add
_common
_arguments
(parser
)
59 parser
.add_argument("--arch", "-a", nargs
="?",
60 help=_("Run pakfire for the given architecture"))
61 parser
.add_argument("--root", metavar
="PATH", default
="/",
62 help=_("The path where pakfire should operate in"))
65 check
= subparsers
.add_parser("check", help=_("Check the system for any errors"))
66 check
.set_defaults(func
=self
.handle_check
)
69 check_update
= subparsers
.add_parser("check-update",
70 help=_("Check, if there are any updates available"))
71 check_update
.set_defaults(func
=self
.handle_check_update
)
72 check_update
.add_argument("--exclude", "-x", nargs
="+",
73 help=_("Exclude package from update"))
74 check_update
.add_argument("--allow-archchange", action
="store_true",
75 help=_("Allow changing the architecture of packages"))
76 check_update
.add_argument("--allow-downgrade", action
="store_true",
77 help=_("Allow downgrading of packages"))
78 check_update
.add_argument("--allow-vendorchange", action
="store_true",
79 help=_("Allow changing the vendor of packages"))
82 clean
= subparsers
.add_parser("clean", help=_("Cleanup all temporary files"))
83 clean
.set_defaults(func
=self
.handle_clean
)
86 downgrade
= subparsers
.add_parser("downgrade", help=_("Downgrade one or more packages"))
87 downgrade
.add_argument("package", nargs
="*",
88 help=_("Give a name of a package to downgrade"))
89 downgrade
.add_argument("--allow-vendorchange", action
="store_true",
90 help=_("Allow changing the vendor of packages"))
91 downgrade
.add_argument("--disallow-archchange", action
="store_true",
92 help=_("Disallow changing the architecture of packages"))
93 downgrade
.set_defaults(func
=self
.handle_downgrade
)
96 execute
= subparsers
.add_parser("execute",
97 help=_("Executes a command in the pakfire environment (useful for development)"))
98 execute
.add_argument("--bind", action
="append", default
=[], dest
="binds",
99 help=_("Bind-mounts the given directory"))
100 execute
.add_argument("command", nargs
=argparse
.REMAINDER
)
101 execute
.set_defaults(func
=self
.handle_execute
)
104 extract
= subparsers
.add_parser("extract",
105 help=_("Extract a package to a directory"))
106 extract
.add_argument("package", nargs
="+",
107 help=_("Give name of the file to extract"))
108 extract
.add_argument("--target", nargs
="?",
109 help=_("Target directory where to extract to"))
110 extract
.set_defaults(func
=self
.handle_extract
)
113 info
= subparsers
.add_parser("info",
114 help=_("Print some information about the given package(s)"))
115 info
.add_argument("--long", action
="store_true",
116 help=_("Show more information"))
117 info
.add_argument("package", nargs
="+",
118 help=_("Give at least the name of one package"))
119 info
.set_defaults(func
=self
.handle_info
)
122 install
= subparsers
.add_parser("install",
123 help=_("Install one or more packages to the system"))
124 install
.add_argument("package", nargs
="+",
125 help=_("Give name of at least one package to install"))
126 install
.add_argument("--without-recommends", action
="store_true",
127 help=_("Don't install recommended packages"))
128 install
.set_defaults(func
=self
.handle_install
)
131 provides
= subparsers
.add_parser("provides",
132 help=_("Get a list of packages that provide a given file or feature"))
133 provides
.add_argument("pattern", nargs
="+", help=_("File or feature to search for"))
134 provides
.set_defaults(func
=self
.handle_provides
)
137 reinstall
= subparsers
.add_parser("reinstall",
138 help=_("Reinstall one or more packages"))
139 reinstall
.add_argument("package", nargs
="+",
140 help=_("Give name of at least one package to reinstall"))
141 reinstall
.set_defaults(func
=self
.handle_reinstall
)
144 remove
= subparsers
.add_parser("remove",
145 help=_("Remove one or more packages from the system"))
146 remove
.add_argument("package", nargs
="+",
147 help=_("Give name of at least one package to remove"))
148 remove
.set_defaults(func
=self
.handle_remove
)
151 repolist
= subparsers
.add_parser("repolist",
152 help=_("List all currently enabled repositories"))
153 repolist
.set_defaults(func
=self
.handle_repolist
)
156 search
= subparsers
.add_parser("search", help=_("Search for a given pattern"))
157 search
.add_argument("pattern", help=_("A pattern to search for"))
158 search
.set_defaults(func
=self
.handle_search
)
161 sync
= subparsers
.add_parser("sync",
162 help=_("Sync all installed with the latest one in the distribution"))
163 sync
.set_defaults(func
=self
.handle_sync
)
166 update
= subparsers
.add_parser("update",
167 help=_("Update the whole system or one specific package"))
168 update
.add_argument("package", nargs
="*",
169 help=_("Give a name of a package to update or leave emtpy for all"))
170 update
.add_argument("--exclude", "-x", nargs
="+",
171 help=_("Exclude package from update"))
172 update
.add_argument("--allow-archchange", action
="store_true",
173 help=_("Allow changing the architecture of packages"))
174 update
.add_argument("--allow-downgrade", action
="store_true",
175 help=_("Allow downgrading of packages"))
176 update
.add_argument("--allow-vendorchange", action
="store_true",
177 help=_("Allow changing the vendor of packages"))
178 update
.set_defaults(func
=self
.handle_update
)
180 return parser
.parse_args()
182 def _add_common_arguments(self
, parser
, offline_switch
=True):
183 parser
.add_argument("--version", action
="version",
184 version
="%(prog)s " + PAKFIRE_VERSION
)
186 parser
.add_argument("-v", "--verbose", action
="store_true",
187 help=_("Enable verbose output."))
189 parser
.add_argument("-c", "--config", nargs
="?",
190 help=_("Path to a configuration file to load."))
192 parser
.add_argument("--disable-repo", nargs
="*", metavar
="REPO",
193 help=_("Disable a repository temporarily."), default
=[])
195 parser
.add_argument("--enable-repo", nargs
="*", metavar
="REPO",
196 help=_("Enable a repository temporarily."), default
=[])
199 parser
.add_argument("--offline", action
="store_true",
200 help=_("Run pakfire in offline mode."))
202 def pakfire(self
, ns
):
206 path
=ns
.root
if "root" in ns
else self
.default_path
,
210 # Disable repositories.
211 for repo_name
in ns
.disable_repo
:
212 repo
= p
.get_repo(repo_name
)
215 # Enable repositories.
216 for repo_name
in ns
.enable_repo
:
217 repo
= p
.get_repo(repo_name
)
222 def handle_execute(self
, ns
):
223 pakfire
= self
.pakfire(ns
)
225 # Bind-mount everything
226 for bind
in ns
.binds
:
229 # Log everything to the console
230 def logging_callback(level
, line
):
231 if level
>= logging
.ERROR
:
232 sys
.stderr
.write("%s\n" % line
)
234 sys
.stdout
.write("%s\n" % line
)
236 return pakfire
.execute(ns
.command
, logging_callback
=logging_callback
)
239 args
= self
.parse_cli()
240 assert args
.func
, "Argument function not defined"
243 return args
.func(args
)
245 except KeyboardInterrupt:
246 self
.ui
.message(_("Received keyboard interupt (Ctrl-C). Exiting."),
247 level
=logging
.CRITICAL
)
249 return 128 + signal
.SIGINT
251 except DependencyError
as e
:
252 self
.ui
.message(_("One or more dependencies could not been resolved"))
253 self
.ui
.message("") # empty line
255 # This exception provides a list of all problems
259 for problem
in problems
:
260 self
.ui
.message(" * %s" % problem
)
262 self
.ui
.message(" %s" % _("Possible solutions are:"))
263 for solution
in problem
.solutions
:
264 self
.ui
.message(" * %s" % solution
)
266 # Add another empty line
271 # Catch all errors and show a user-friendly error message.
273 self
.ui
.message(_("An error has occured when running Pakfire"), level
=logging
.CRITICAL
)
275 self
.ui
.message(_("%s: %s") % (e
.__class
__.__name
__, e
.message
),
280 def _dump_transaction(self
, transaction
):
282 Dumps the transaction
284 t
= transaction
.dump()
286 for line
in t
.splitlines():
287 self
.ui
.message(line
)
289 def _execute_transaction(self
, transaction
):
292 def handle_info(self
, ns
):
293 with self
.pakfire(ns
) as p
:
294 for pkg
in p
.info(ns
.package
):
295 s
= pkg
.dump(long=ns
.long)
298 def handle_search(self
, ns
):
299 with self
.pakfire(ns
) as p
:
300 for pkg
in p
.search(ns
.pattern
):
301 # Skip any -debuginfo packages
302 if pkg
.name
.endswith("-debuginfo"):
305 self
.ui
.message("%-24s: %s" % (pkg
.name
, pkg
.summary
))
307 def handle_update(self
, ns
, check
=False):
308 with self
.pakfire(ns
) as p
:
309 transaction
= p
.update(
310 ns
.package
, excludes
=ns
.exclude
,
311 allow_archchange
=ns
.allow_archchange
,
312 allow_vendorchange
=ns
.allow_vendorchange
,
315 # If we are only checking for updates,
316 # we dump the transaction and exit here.
318 self
._dump
_transaction
(transaction
)
321 # Otherwise we execute the transaction
322 self
._execute
_transaction
(transaction
)
324 def handle_sync(self
, ns
):
325 with self
.pakfire(ns
) as p
:
326 transaction
= p
.update(
327 allow_archchange
=True,
328 allow_vendorchange
=True,
331 self
._execute
_transaction
(transaction
)
333 def handle_check_update(self
, ns
):
334 self
.handle_update(ns
, check
=True)
336 def handle_downgrade(self
, ns
, **args
):
337 with self
.pakfire(ns
) as p
:
340 allow_vendorchange
=self
.args
.allow_vendorchange
,
341 allow_archchange
=not self
.args
.disallow_archchange
,
345 def handle_install(self
, ns
):
346 with self
.pakfire(ns
) as p
:
347 transaction
= p
.install(ns
.package
, without_recommends
=ns
.without_recommends
)
349 # Execute the transaction
350 self
._execute
_transaction
(transaction
)
352 def handle_reinstall(self
, ns
):
353 with self
.pakfire(ns
) as p
:
354 transaction
= p
.reinstall(ns
.package
)
356 # Execute the transaction
357 self
._execute
_transaction
(transaction
)
359 def handle_remove(self
, ns
):
360 with self
.pakfire(ns
) as p
:
361 transaction
= p
.erase(ns
.package
)
363 self
._execute
_transaction
(transaction
)
365 def handle_provides(self
, ns
, long=False):
366 with self
.pakfire(ns
) as p
:
367 for pkg
in p
.provides(ns
.pattern
):
368 s
= pkg
.dump(long=long)
371 def handle_repolist(self
, ns
):
372 with self
.pakfire(ns
) as p
:
373 FORMAT
= " %-20s %8s %12s %12s "
374 title
= FORMAT
% (_("Repository"), _("Enabled"), _("Priority"), _("Packages"))
376 print("=" * len(title
)) # spacing line
379 print(FORMAT
% (repo
.name
, repo
.enabled
, repo
.priority
, len(repo
)))
381 def handle_clean(self
, ns
):
382 self
.ui
.message(_("Cleaning up everything..."))
387 def handle_check(self
, ns
):
388 with self
.pakfire(ns
) as p
:
389 # This will throw an exception when there are errors
390 transaction
= p
.check()
392 self
.ui
.message(_("Everything okay"))
394 def handle_extract(self
, ns
):
395 with self
.pakfire(ns
) as p
:
396 p
.extract(ns
.package
, target
=ns
.target
)
399 class CliBuilder(Cli
):
403 parser
= argparse
.ArgumentParser(
404 description
= _("Pakfire builder command line interface"),
406 subparsers
= parser
.add_subparsers()
408 # Add common arguments
409 self
._add
_common
_arguments
(parser
)
411 # Add additional arguments
412 parser
.add_argument("--arch", "-a", nargs
="?",
413 help=_("Run pakfire for the given architecture"))
414 parser
.add_argument("--distro", nargs
="?", default
="ipfire3", # XXX for now
415 help=_("Choose the distribution configuration to use for build"))
416 parser
.add_argument("--disable-snapshot", action
="store_true",
417 help=_("Disable using snapshots"))
420 build
= subparsers
.add_parser("build", help=_("Build one or more packages"))
421 build
.add_argument("package", nargs
=1,
422 help=_("Give name of at least one package to build"))
423 build
.set_defaults(func
=self
.handle_build
)
425 build
.add_argument("--resultdir", nargs
="?",
426 help=_("Path were the output files should be copied to"))
427 build
.add_argument("-m", "--mode", nargs
="?", default
="development",
428 help=_("Mode to run in. Is either 'release' or 'development' (default)"))
429 build
.add_argument("--after-shell", action
="store_true",
430 help=_("Run a shell after a successful build"))
431 build
.add_argument("--skip-install-test", action
="store_true",
432 help=_("Do not perform the install test"))
433 build
.add_argument("--private-network", action
="store_true",
434 help=_("Disable network in container"))
437 clean
= subparsers
.add_parser("clean", help=_("Cleanup all temporary files"))
438 clean
.set_defaults(func
=self
.handle_clean
)
441 dist
= subparsers
.add_parser("dist", help=_("Generate a source package"))
442 dist
.add_argument("package", nargs
="+", help=_("Give name(s) of a package(s)"))
443 dist
.set_defaults(func
=self
.handle_dist
)
445 dist
.add_argument("--resultdir", nargs
="?",
446 help=_("Path were the output files should be copied to"))
449 extract
= subparsers
.add_parser("extract", help=_("Extract a package to a directory"))
450 extract
.add_argument("package", nargs
="+",
451 help=_("Give name of the file to extract"))
452 extract
.add_argument("--target", nargs
="?",
453 help=_("Target directory where to extract to"))
454 extract
.set_defaults(func
=self
.handle_extract
)
457 info
= subparsers
.add_parser("info",
458 help=_("Print some information about the given package(s)"))
459 info
.add_argument("--filelist", action
="store_true",
460 help=_("Show filelist"))
461 info
.add_argument("package", nargs
="+",
462 help=_("Give at least the name of one package."))
463 info
.set_defaults(func
=self
.handle_info
)
466 provides
= subparsers
.add_parser("provides",
467 help=_("Get a list of packages that provide a given file or feature"))
468 provides
.add_argument("pattern", nargs
="+",
469 help=_("File or feature to search for"))
470 provides
.set_defaults(func
=self
.handle_provides
)
473 repolist
= subparsers
.add_parser("repolist",
474 help=_("List all currently enabled repositories"))
475 repolist
.set_defaults(func
=self
.handle_repolist
)
478 search
= subparsers
.add_parser("search", help=_("Search for a given pattern"))
479 search
.add_argument("pattern", help=_("A pattern to search for"))
480 search
.set_defaults(func
=self
.handle_search
)
483 shell
= subparsers
.add_parser("shell", help=_("Go into a build shell"))
484 shell
.add_argument("package", nargs
="*", help=_("Give name of a package"))
485 shell
.add_argument("--install", nargs
="*",
486 help=_("Packages that should be installed in the shell"))
487 shell
.set_defaults(func
=self
.handle_shell
)
489 shell
.add_argument("-m", "--mode", nargs
="?", default
="development",
490 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
491 shell
.add_argument("--private-network", action
="store_true",
492 help=_("Disable network in container"))
495 update
= subparsers
.add_parser("update", help=_("Update the package indexes"))
496 update
.set_defaults(func
=self
.handle_update
)
498 return parser
.parse_args()
500 def builder(self
, ns
):
501 # Find distro configuration file
502 conf
= os
.path
.join(CONFIG_DISTRO_DIR
, "%s.conf" % ns
.distro
)
504 return builder
.Builder(
507 enable_snapshot
=not ns
.disable_snapshot
510 def handle_build(self
, ns
):
511 package
, = ns
.package
513 # Initialise a builder instance and build this package
514 with self
.builder(ns
) as b
:
517 def handle_info(self
, ns
):
518 with self
.builder(ns
) as b
:
520 for pkg
in p
.info(ns
.package
):
521 s
= pkg
.dump(long=True, filelist
=ns
.filelist
)
524 def handle_repolist(self
, ns
):
525 with self
.builder(ns
) as b
:
527 FORMAT
= " %-20s %8s %12s %12s "
528 title
= FORMAT
% (_("Repository"), _("Enabled"), _("Priority"), _("Packages"))
530 print("=" * len(title
)) # spacing line
533 print(FORMAT
% (repo
.name
, repo
.enabled
, repo
.priority
, len(repo
)))
535 def handle_shell(self
, ns
):
536 with self
.builder(ns
) as b
:
537 b
.shell(packages
=ns
.package
, install
=ns
.install
)
539 def handle_dist(self
, ns
):
540 # Get the packages from the command line options
543 for pkg
in ns
.package
:
544 # Check, if we got a regular file
545 if os
.path
.exists(pkg
):
546 pkg
= os
.path
.abspath(pkg
)
550 raise FileNotFoundError(pkg
)
552 # Put packages to where the user said or our
553 # current working directory.
554 resultdir
= ns
.resultdir
or os
.getcwd()
558 p
.dist(pkg
, resultdir
)
561 class CliClient(Cli
):
563 # Create connection to pakfire hub
564 self
.client
= client
.Client()
567 parser
= argparse
.ArgumentParser(
568 description
= _("Pakfire client command line interface"),
570 subparsers
= parser
.add_subparsers(help=_("sub-command help"))
572 # Add common arguments
573 self
._add
_common
_arguments
(parser
, offline_switch
=False)
576 build
= subparsers
.add_parser("build", help=_("Build a package remote"))
577 build
.add_argument("packages", nargs
="+", help=_("Package(s) to build"))
578 build
.set_defaults(func
=self
.handle_build
)
580 build
.add_argument("-a", "--arch",
581 help=_("Build the package(s) for the given architecture only"))
584 check_connection
= subparsers
.add_parser("check-connection",
585 help=_("Check the connection to the hub"))
586 check_connection
.set_defaults(func
=self
.handle_check_connection
)
589 upload
= subparsers
.add_parser("upload", help=_("Upload a file to the build service"))
590 upload
.add_argument("file", nargs
=1, help=_("Filename"))
591 upload
.set_defaults(func
=self
.handle_upload
)
594 watch_build
= subparsers
.add_parser("watch-build", help=_("Watch the status of a build"))
595 watch_build
.add_argument("id", nargs
=1, help=_("Build ID"))
596 watch_build
.set_defaults(func
=self
.handle_watch_build
)
599 watch_job
= subparsers
.add_parser("watch-job", help=_("Watch the status of a job"))
600 watch_job
.add_argument("id", nargs
=1, help=_("Job ID"))
601 watch_job
.set_defaults(func
=self
.handle_watch_job
)
603 return parser
.parse_args()
605 def handle_build(self
, ns
):
606 # Create a temporary directory.
607 temp_dir
= tempfile
.mkdtemp()
611 arches
= self
.args
.arch
.split(",")
616 # Package all packages first and save the actual filenames
619 for package
in ns
.packages
:
620 if package
.endswith(".%s" % MAKEFILE_EXTENSION
):
621 # Create a source package from the makefile.
623 package
= p
.dist(package
, temp_dir
)
624 packages
.append(package
)
626 elif package
.endswith(".%s" % PACKAGE_EXTENSION
):
627 packages
.append(package
)
630 raise Exception("Unknown filetype: %s" % package
)
634 # Upload the packages to the build service
635 for package
in packages
:
636 build
= self
.client
.create_build(package
, type="scratch", arches
=arches
)
638 # Show information about the uploaded build
639 summary
= build
.dump()
640 for line
in summary
.splitlines():
644 # Cleanup the temporary directory and all files.
645 if os
.path
.exists(temp_dir
):
646 shutil
.rmtree(temp_dir
, ignore_errors
=True)
648 def handle_check_connection(self
, ns
):
649 success
= self
.client
.check_connection()
652 print("%s: %s" % (_("Connection OK"), success
))
654 def handle_upload(self
, ns
):
656 self
.client
.upload_file(path
)
658 def handle_watch_build(self
, ns
):
659 build
= self
.client
.get_build(ns
.id[0])
661 return self
._watch
_something
(build
)
663 def handle_watch_job(self
, ns
):
664 job
= self
.client
.get_job(ns
.id[0])
666 return self
._watch
_something
(job
)
668 def _watch_something(self
, o
):
673 # Break the loop if the build/job is not active any more
674 # (since we don't expect any changes)
675 if not o
.is_active():
680 # Update data before the next loop is shown
684 class CliDaemon(Cli
):
686 parser
= argparse
.ArgumentParser(
687 description
= _("Pakfire daemon command line interface"),
689 self
._add
_common
_arguments
(parser
, offline_switch
=False)
691 # There is only one default action
692 parser
.set_defaults(func
=self
.handle_run
)
694 return parser
.parse_args()
696 def handle_run(self
, ns
):
698 Runs the pakfire daemon
700 d
= daemon
.PakfireDaemon()
705 # We cannot just kill the daemon, it needs a smooth shutdown
706 except (SystemExit, KeyboardInterrupt):
712 parser
= argparse
.ArgumentParser(
713 description
= _("Pakfire key command line interface"),
715 subparsers
= parser
.add_subparsers()
717 # Add common arguments
718 self
._add
_common
_arguments
(parser
)
721 delete
= subparsers
.add_parser("delete", help=_("Delete a key from the local keyring"))
722 delete
.add_argument("fingerprint", nargs
="+", help=_("The fingerprint of the key to delete"))
723 delete
.set_defaults(func
=self
.handle_delete
)
726 export
= subparsers
.add_parser("export", help=_("Export a key to a file"))
727 export
.add_argument("fingerprint", nargs
=1,
728 help=_("The fingerprint of the key to export"))
729 export
.add_argument("--filename", nargs
="*", help=_("Write the key to this file"))
730 export
.add_argument("--secret", action
="store_true",
731 help=_("Export the secret key"))
732 export
.set_defaults(func
=self
.handle_export
)
735 _import
= subparsers
.add_parser("import", help=_("Import a key from file"))
736 _import
.add_argument("filename", nargs
="+", help=_("Filename of that key to import"))
737 _import
.set_defaults(func
=self
.handle_import
)
740 generate
= subparsers
.add_parser("generate", help=_("Import a key from file"))
741 generate
.add_argument("--realname", nargs
=1,
742 help=_("The real name of the owner of this key"))
743 generate
.add_argument("--email", nargs
=1,
744 help=_("The email address of the owner of this key"))
745 generate
.set_defaults(func
=self
.handle_generate
)
748 list = subparsers
.add_parser("list", help=_("List all imported keys"))
749 list.set_defaults(func
=self
.handle_list
)
751 return parser
.parse_args()
753 def parse_command_sign(self
):
754 # Implement the "sign" command.
755 sub_sign
= self
.sub_commands
.add_parser("sign",
756 help=_("Sign one or more packages."))
757 sub_sign
.add_argument("--key", "-k", nargs
=1,
758 help=_("Key that is used sign the package(s)."))
759 sub_sign
.add_argument("package", nargs
="+",
760 help=_("Package(s) to sign."))
761 sub_sign
.add_argument("action", action
="store_const", const
="sign")
763 def parse_command_verify(self
):
764 # Implement the "verify" command.
765 sub_verify
= self
.sub_commands
.add_parser("verify",
766 help=_("Verify one or more packages."))
767 #sub_verify.add_argument("--key", "-k", nargs=1,
768 # help=_("Key that is used verify the package(s)."))
769 sub_verify
.add_argument("package", nargs
="+",
770 help=_("Package(s) to verify."))
771 sub_verify
.add_argument("action", action
="store_const", const
="verify")
773 def handle_generate(self
, ns
):
776 print(_("Generating the key may take a moment..."))
779 key
= p
.generate_key("%s <%s>" % (ns
.realname
.pop(), ns
.email
.pop()))
781 def handle_list(self
, ns
):
787 def handle_export(self
, ns
):
790 for fingerprint
in ns
.fingerprint
:
791 key
= p
.get_key(fingerprint
)
793 print(_("Could not find key with fingerprint %s") % fingerprint
)
796 data
= key
.export(ns
.secret
)
798 for file in ns
.filename
:
799 with
open(file, "w") as f
:
804 def handle_import(self
, ns
):
807 for filename
in ns
.filename
:
808 with
open(filename
) as f
:
811 keys
= p
.import_key(data
)
815 def handle_delete(self
, ns
):
818 for fingerprint
in ns
.fingerprint
:
819 key
= p
.get_key(fingerprint
)
823 def handle_sign(self
):
824 # Get the files from the command line options
827 for file in self
.args
.package
:
828 # Check, if we got a regular file
829 if os
.path
.exists(file):
830 file = os
.path
.abspath(file)
834 raise FileNotFoundError(file)
836 key
= self
.args
.key
[0]
838 # Create pakfire instance.
839 p
= self
.create_pakfire()
843 pkg
= packages
.open(p
, None, file)
845 print(_("Signing %s...") % pkg
.friendly_name
)
848 def handle_verify(self
):
849 # TODO needs to use new key code from libpakfire
851 # Get the files from the command line options
854 for file in self
.args
.package
:
855 # Check, if we got a regular file
856 if os
.path
.exists(file) and not os
.path
.isdir(file):
857 file = os
.path
.abspath(file)
860 # Create pakfire instance.
861 p
= self
.create_pakfire()
865 pkg
= packages
.open(p
, None, file)
867 print(_("Verifying %s...") % pkg
.friendly_name
)
871 key
= p
.keyring
.get_key(sig
.fpr
)
873 subkey
= key
.subkeys
[0]
875 print(" %s %s" % (subkey
.fpr
[-16:], key
.uids
[0].uid
))
877 print(" %s" % _("This signature is valid."))
880 print(" %s <%s>" % (sig
.fpr
, _("Unknown key")))
881 print(" %s" % _("Could not check if this signature is valid."))
883 created
= datetime
.datetime
.fromtimestamp(sig
.timestamp
)
884 print(" %s" % _("Created: %s") % created
)
886 if sig
.exp_timestamp
:
887 expires
= datetime
.datetime
.fromtimestamp(sig
.exp_timestamp
)
888 print(" %s" % _("Expires: %s") % expires
)