diff --git a/bin/pungi b/bin/pungi deleted file mode 100755 index 0a45d178..00000000 --- a/bin/pungi +++ /dev/null @@ -1,362 +0,0 @@ -#!/usr/bin/env python -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Library General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . - -from __future__ import print_function - -import os -import selinux -import sys - -here = sys.path[0] -if here != '/usr/bin': - # Git checkout - sys.path.insert(1, os.path.dirname(here)) - -from pungi import get_full_version -import pungi.gather -import pungi.config -import pungi.ks - - -def main(): - - config = pungi.config.Config() - opts = get_arguments(config) - - # Read the config to create "new" defaults - # reparse command line options so they take precedence - config = pungi.config.Config(pungirc=opts.pungirc) - opts = get_arguments(config) - - # You must be this high to ride if you're going to do root tasks - if os.geteuid() != 0 and (opts.do_all or opts.do_buildinstall): - print("You must run pungi as root", file=sys.stderr) - return 1 - - if opts.do_all or opts.do_buildinstall: - try: - enforcing = selinux.security_getenforce() - except: - print("INFO: selinux disabled") - enforcing = False - if enforcing: - print("WARNING: SELinux is enforcing. This may lead to a compose with selinux disabled.") - print("Consider running with setenforce 0.") - - # Set up the kickstart parser and pass in the kickstart file we were handed - ksparser = pungi.ks.get_ksparser(ks_path=opts.config) - - if opts.sourceisos: - config.set('pungi', 'arch', 'source') - - for part in ksparser.handler.partition.partitions: - if part.mountpoint == 'iso': - config.set('pungi', 'cdsize', str(part.size)) - - config.set('pungi', 'force', str(opts.force)) - - if config.get('pungi', 'workdirbase') == '/work': - config.set('pungi', 'workdirbase', "%s/work" % config.get('pungi', 'destdir')) - # Set up our directories - if not os.path.exists(config.get('pungi', 'destdir')): - try: - os.makedirs(config.get('pungi', 'destdir')) - except OSError: - print("Error: Cannot create destination dir %s" % config.get('pungi', 'destdir'), - file=sys.stderr) - sys.exit(1) - else: - print("Warning: Reusing existing destination directory.") - - if not os.path.exists(config.get('pungi', 'workdirbase')): - try: - os.makedirs(config.get('pungi', 'workdirbase')) - except OSError: - print("Error: Cannot create working base dir %s" % config.get('pungi', 'workdirbase'), - file=sys.stderr) - sys.exit(1) - else: - print("Warning: Reusing existing working base directory.") - - cachedir = config.get('pungi', 'cachedir') - - if not os.path.exists(cachedir): - try: - os.makedirs(cachedir) - except OSError: - print("Error: Cannot create cache dir %s" % cachedir, file=sys.stderr) - sys.exit(1) - - # Set debuginfo flag - if opts.nodebuginfo: - config.set('pungi', 'debuginfo', "False") - if opts.greedy: - config.set('pungi', 'greedy', opts.greedy) - else: - # XXX: compatibility - if opts.nogreedy: - config.set('pungi', 'greedy', "none") - else: - config.set('pungi', 'greedy', "all") - config.set('pungi', 'resolve_deps', str(bool(opts.resolve_deps))) - if opts.isfinal: - config.set('pungi', 'isfinal', "True") - if opts.nohash: - config.set('pungi', 'nohash', "True") - if opts.full_archlist: - config.set('pungi', 'full_archlist', "True") - if opts.arch: - config.set('pungi', 'arch', opts.arch) - if opts.multilib: - config.set('pungi', 'multilib', " ".join(opts.multilib)) - if opts.lookaside_repos: - config.set('pungi', 'lookaside_repos', " ".join(opts.lookaside_repos)) - if opts.no_dvd: - config.set('pungi', 'no_dvd', "True") - if opts.nomacboot: - config.set('pungi', 'nomacboot', "True") - config.set("pungi", "fulltree", str(bool(opts.fulltree))) - config.set("pungi", "selfhosting", str(bool(opts.selfhosting))) - config.set("pungi", "nosource", str(bool(opts.nosource))) - config.set("pungi", "nodebuginfo", str(bool(opts.nodebuginfo))) - - if opts.lorax_conf: - config.set("lorax", "conf_file", opts.lorax_conf) - if opts.installpkgs: - config.set("lorax", "installpkgs", " ".join(opts.installpkgs)) - - # Actually do work. - mypungi = pungi.gather.Pungi(config, ksparser) - - with mypungi.yumlock: - if not opts.sourceisos: - if opts.do_all or opts.do_gather or opts.do_buildinstall: - mypungi._inityum() # initialize the yum object for things that need it - if opts.do_all or opts.do_gather: - mypungi.gather() - if opts.nodownload: - for line in mypungi.list_packages(): - flags_str = ",".join(line["flags"]) - if flags_str: - flags_str = "(%s)" % flags_str - sys.stdout.write("RPM%s: %s\n" % (flags_str, line["path"])) - sys.stdout.flush() - else: - mypungi.downloadPackages() - mypungi.makeCompsFile() - if not opts.nodebuginfo: - mypungi.getDebuginfoList() - if opts.nodownload: - for line in mypungi.list_debuginfo(): - flags_str = ",".join(line["flags"]) - if flags_str: - flags_str = "(%s)" % flags_str - sys.stdout.write("DEBUGINFO%s: %s\n" % (flags_str, line["path"])) - sys.stdout.flush() - else: - mypungi.downloadDebuginfo() - if not opts.nosource: - if opts.nodownload: - for line in mypungi.list_srpms(): - flags_str = ",".join(line["flags"]) - if flags_str: - flags_str = "(%s)" % flags_str - sys.stdout.write("SRPM%s: %s\n" % (flags_str, line["path"])) - sys.stdout.flush() - else: - mypungi.downloadSRPMs() - - print("RPM size: %s MiB" % (mypungi.size_packages() / 1024 ** 2)) - if not opts.nodebuginfo: - print("DEBUGINFO size: %s MiB" % (mypungi.size_debuginfo() / 1024 ** 2)) - if not opts.nosource: - print("SRPM size: %s MiB" % (mypungi.size_srpms() / 1024 ** 2)) - - # Furthermore (but without the yumlock...) - if not opts.sourceisos: - if opts.do_all or opts.do_createrepo: - mypungi.doCreaterepo() - - if opts.do_all or opts.do_buildinstall: - if not opts.norelnotes: - mypungi.doGetRelnotes() - mypungi.doBuildinstall() - - if opts.do_all or opts.do_createiso: - mypungi.doCreateIsos() - - # Do things slightly different for src. - if opts.sourceisos: - # we already have all the content gathered - mypungi.topdir = os.path.join(config.get('pungi', 'destdir'), - config.get('pungi', 'version'), - config.get('pungi', 'variant'), - 'source', 'SRPMS') - mypungi.doCreaterepo(comps=False) - if opts.do_all or opts.do_createiso: - mypungi.doCreateIsos() - - print("All done!") - -if __name__ == '__main__': - from argparse import ArgumentParser, Action - import sys - import time - - today = time.strftime('%Y%m%d', time.localtime()) - - def get_arguments(config): - parser = ArgumentParser() - - class SetConfig(Action): - def __call__(self, parser, namespace, value, option_string=None): - config.set('pungi', self.dest, value) - - parser.add_argument('--version', action='version', version=get_full_version()) - - # Pulled in from config file to be cli options as part of pykickstart conversion - parser.add_argument( - "--name", dest="family", type=str, action=SetConfig, - help='the name for your distribution (defaults to "Fedora"), DEPRECATED') - parser.add_argument( - "--family", dest="family", action=SetConfig, - help='the family name for your distribution (defaults to "Fedora")') - parser.add_argument( - "--ver", dest="version", action=SetConfig, - help='the version of your distribution (defaults to datestamp)') - parser.add_argument( - "--flavor", dest="variant", action=SetConfig, - help='the flavor of your distribution spin (optional), DEPRECATED') - parser.add_argument( - "--variant", dest="variant", action=SetConfig, - help='the variant of your distribution spin (optional)') - parser.add_argument( - "--destdir", dest="destdir", action=SetConfig, - help='destination directory (defaults to current directory)') - parser.add_argument( - "--cachedir", dest="cachedir", action=SetConfig, - help='package cache directory (defaults to /var/cache/pungi)') - parser.add_argument( - "--bugurl", dest="bugurl", action=SetConfig, - help='the url for your bug system (defaults to http://bugzilla.redhat.com)') - parser.add_argument( - "--selfhosting", action="store_true", dest="selfhosting", - help='build a self-hosting tree by following build dependencies (optional)') - parser.add_argument( - "--fulltree", action="store_true", dest="fulltree", - help='build a tree that includes all packages built from corresponding source rpms (optional)') - parser.add_argument( - "--nosource", action="store_true", dest="nosource", - help='disable gathering of source packages (optional)') - parser.add_argument( - "--nodebuginfo", action="store_true", dest="nodebuginfo", - help='disable gathering of debuginfo packages (optional)') - parser.add_argument( - "--nodownload", action="store_true", dest="nodownload", - help='disable downloading of packages. instead, print the package URLs (optional)') - parser.add_argument( - "--norelnotes", action="store_true", dest="norelnotes", - help='disable gathering of release notes (optional); DEPRECATED') - parser.add_argument( - "--nogreedy", action="store_true", dest="nogreedy", - help='disable pulling of all providers of package dependencies (optional)') - parser.add_argument( - "--nodeps", action="store_false", dest="resolve_deps", default=True, - help='disable resolving dependencies') - parser.add_argument( - "--sourceisos", default=False, action="store_true", dest="sourceisos", - help='Create the source isos (other arch runs must be done)') - parser.add_argument( - "--force", default=False, action="store_true", - help='Force reuse of an existing destination directory (will overwrite files)') - parser.add_argument( - "--isfinal", default=False, action="store_true", - help='Specify this is a GA tree, which causes betanag to be turned off during install') - parser.add_argument( - "--nohash", default=False, action="store_true", - help='disable hashing the Packages trees') - parser.add_argument( - "--full-archlist", action="store_true", - help='Use the full arch list for x86_64 (include i686, i386, etc.)') - parser.add_argument("--arch", help='Override default (uname based) arch') - parser.add_argument( - "--greedy", metavar="METHOD", - help='Greedy method; none, all, build') - parser.add_argument( - "--multilib", action="append", metavar="METHOD", - help='Multilib method; can be specified multiple times; recommended: devel, runtime') - parser.add_argument( - "--lookaside-repo", action="append", dest="lookaside_repos", metavar="NAME", - help='Specify lookaside repo name(s) (packages will used for depsolving but not be included in the output)') - parser.add_argument( - "--workdirbase", dest="workdirbase", action=SetConfig, - help='base working directory (defaults to destdir + /work)') - parser.add_argument("--no-dvd", default=False, action="store_true", dest="no_dvd", - help='Do not make a install DVD/CD only the netinstall image and the tree') - parser.add_argument("--lorax-conf", - help='Path to lorax.conf file (optional)') - parser.add_argument( - "-i", "--installpkgs", default=[], action="append", metavar="STRING", - help="Package glob for lorax to install before runtime-install.tmpl runs. (may be listed multiple times)") - parser.add_argument( - "--multilibconf", default=None, action=SetConfig, - help="Path to multilib conf files. Default is /usr/share/pungi/multilib/") - - parser.add_argument("-c", "--config", dest="config", required=True, - help='Path to kickstart config file') - parser.add_argument("--all-stages", action="store_true", default=True, dest="do_all", - help="Enable ALL stages") - parser.add_argument("-G", action="store_true", default=False, dest="do_gather", - help="Flag to enable processing the Gather stage") - parser.add_argument("-C", action="store_true", default=False, dest="do_createrepo", - help="Flag to enable processing the Createrepo stage") - parser.add_argument("-B", action="store_true", default=False, dest="do_buildinstall", - help="Flag to enable processing the BuildInstall stage") - parser.add_argument("-I", action="store_true", default=False, dest="do_createiso", - help="Flag to enable processing the CreateISO stage") - parser.add_argument("--relnotepkgs", dest="relnotepkgs", action=SetConfig, - help='Rpms which contain the release notes') - parser.add_argument( - "--relnotefilere", dest="relnotefilere", action=SetConfig, - help='Which files are the release notes -- GPL EULA') - parser.add_argument("--nomacboot", action="store_true", dest="nomacboot", - help='disable setting up macboot as no hfs support ') - - parser.add_argument( - "--rootfs-size", dest="rootfs_size", action=SetConfig, default=False, - help='Size of root filesystem in GiB. If not specified, use lorax default value') - - parser.add_argument( - "--pungirc", dest="pungirc", default='~/.pungirc', action=SetConfig, - help='Read pungi options from config file ') - - opts = parser.parse_args() - - if not config.get('pungi', 'variant').isalnum() and not config.get('pungi', 'variant') == '': - parser.error("Variant must be alphanumeric") - - if opts.do_gather or opts.do_createrepo or opts.do_buildinstall or opts.do_createiso: - opts.do_all = False - - if opts.arch and (opts.do_all or opts.do_buildinstall): - parser.error("Cannot override arch while the BuildInstall stage is enabled") - - # set the iso_basename. - if not config.get('pungi', 'variant') == '': - config.set('pungi', 'iso_basename', '%s-%s' % (config.get('pungi', 'family'), config.get('pungi', 'variant'))) - else: - config.set('pungi', 'iso_basename', config.get('pungi', 'family')) - - return opts - - main() diff --git a/bin/pungi-make-ostree b/bin/pungi-make-ostree deleted file mode 100755 index 28005884..00000000 --- a/bin/pungi-make-ostree +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import os -import sys - -here = sys.path[0] -if here != '/usr/bin': - sys.path.insert(0, os.path.dirname(here)) - -from pungi import ostree - - -if __name__ == '__main__': - ostree.main() diff --git a/bin/pungi-orchestrate b/bin/pungi-orchestrate deleted file mode 100755 index 0cb4348d..00000000 --- a/bin/pungi-orchestrate +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import os -import sys - -here = sys.path[0] -if here != '/usr/bin': - # Git checkout - sys.path[0] = os.path.dirname(here) - -from pungi_utils import orchestrator - - -if __name__ == '__main__': - orchestrator.main() diff --git a/doc/contributing.rst b/doc/contributing.rst index 02ae13ae..fb8217f2 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -158,6 +158,7 @@ In the ``tests/`` directory there is a shell script ``test_compose.sh`` that you can use to try and create a miniature compose on dummy data. The actual data will be created by running ``make test-data`` in project root. :: + $ python setup.py develop $ make test-data $ make test-compose diff --git a/pungi/scripts/__init__.py b/pungi/scripts/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bin/comps_filter b/pungi/scripts/comps_filter.py old mode 100755 new mode 100644 similarity index 97% rename from bin/comps_filter rename to pungi/scripts/comps_filter.py index f2e6f1e7..21262dba --- a/bin/comps_filter +++ b/pungi/scripts/comps_filter.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- +from __future__ import absolute_import import sys import argparse @@ -68,7 +68,3 @@ def main(): f.remove_environments() f.write(open(opts.output, 'wb') if opts.output else sys.stdout) - - -if __name__ == "__main__": - main() diff --git a/bin/pungi-config-dump b/pungi/scripts/config_dump.py old mode 100755 new mode 100644 similarity index 99% rename from bin/pungi-config-dump rename to pungi/scripts/config_dump.py index 39caf4b0..cafd66cf --- a/bin/pungi-config-dump +++ b/pungi/scripts/config_dump.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- +from __future__ import absolute_import from __future__ import print_function import argparse @@ -206,7 +206,7 @@ def main(): ) -if __name__ == "__main__": +def cli_main(): try: if not main(): sys.exit(1) diff --git a/bin/pungi-config-validate b/pungi/scripts/config_validate.py old mode 100755 new mode 100644 similarity index 97% rename from bin/pungi-config-validate rename to pungi/scripts/config_validate.py index ba7a045c..68800981 --- a/bin/pungi-config-validate +++ b/pungi/scripts/config_validate.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- +from __future__ import absolute_import from __future__ import print_function import argparse @@ -10,11 +10,6 @@ import sys import six -here = sys.path[0] -if here != '/usr/bin': - # Git checkout - sys.path[0] = os.path.dirname(here) - import pungi.checks import pungi.compose import pungi.paths @@ -187,6 +182,6 @@ def main(args=None): return bool(errors) -if __name__ == '__main__': +def cli_main(): if main(): sys.exit(1) diff --git a/bin/pungi-create-unified-isos b/pungi/scripts/create_unified_isos.py old mode 100755 new mode 100644 similarity index 78% rename from bin/pungi-create-unified-isos rename to pungi/scripts/create_unified_isos.py index 84953173..48dc93d1 --- a/bin/pungi-create-unified-isos +++ b/pungi/scripts/create_unified_isos.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ @@ -11,10 +10,6 @@ import argparse import os import sys -here = sys.path[0] -if here != '/usr/bin': - # Git checkout - sys.path[0] = os.path.dirname(here) from pungi_utils.unified_isos import UnifiedISO @@ -36,7 +31,3 @@ def main(): args = parse_args() iso = UnifiedISO(args.compose[0]) iso.create(delete_temp=True) - - -if __name__ == '__main__': - main() diff --git a/bin/pungi-fedmsg-notification b/pungi/scripts/fedmsg_notification.py old mode 100755 new mode 100644 similarity index 92% rename from bin/pungi-fedmsg-notification rename to pungi/scripts/fedmsg_notification.py index 32514518..ff8278cf --- a/bin/pungi-fedmsg-notification +++ b/pungi/scripts/fedmsg_notification.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- import argparse @@ -12,7 +11,8 @@ def send(cmd, data): topic = 'compose.%s' % cmd.replace('-', '.').lower() fedmsg.publish(topic=topic, modname='pungi', msg=data) -if __name__ == '__main__': + +def main(): parser = argparse.ArgumentParser() parser.add_argument('cmd') opts = parser.parse_args() diff --git a/bin/pungi-patch-iso b/pungi/scripts/patch_iso.py old mode 100755 new mode 100644 similarity index 92% rename from bin/pungi-patch-iso rename to pungi/scripts/patch_iso.py index e7150c0f..0c9e68b5 --- a/bin/pungi-patch-iso +++ b/pungi/scripts/patch_iso.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- # This program is free software; you can redistribute it and/or modify @@ -18,11 +17,6 @@ import logging import os import sys -here = sys.path[0] -if here != '/usr/bin': - # Git checkout - sys.path[0] = os.path.dirname(here) - from pungi_utils import patch_iso @@ -52,6 +46,6 @@ def main(args=None): patch_iso.run(log, opts) -if __name__ == '__main__': +def cli_main(): if main(): sys.exit(1) diff --git a/pungi/scripts/pungi.py b/pungi/scripts/pungi.py new file mode 100644 index 00000000..281abe69 --- /dev/null +++ b/pungi/scripts/pungi.py @@ -0,0 +1,351 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + +from __future__ import absolute_import +from __future__ import print_function + +import os +import selinux +import sys + +from argparse import ArgumentParser, Action + +from pungi import get_full_version +import pungi.gather +import pungi.config +import pungi.ks + + +def get_arguments(config): + parser = ArgumentParser() + + class SetConfig(Action): + def __call__(self, parser, namespace, value, option_string=None): + config.set('pungi', self.dest, value) + + parser.add_argument('--version', action='version', version=get_full_version()) + + # Pulled in from config file to be cli options as part of pykickstart conversion + parser.add_argument( + "--name", dest="family", type=str, action=SetConfig, + help='the name for your distribution (defaults to "Fedora"), DEPRECATED') + parser.add_argument( + "--family", dest="family", action=SetConfig, + help='the family name for your distribution (defaults to "Fedora")') + parser.add_argument( + "--ver", dest="version", action=SetConfig, + help='the version of your distribution (defaults to datestamp)') + parser.add_argument( + "--flavor", dest="variant", action=SetConfig, + help='the flavor of your distribution spin (optional), DEPRECATED') + parser.add_argument( + "--variant", dest="variant", action=SetConfig, + help='the variant of your distribution spin (optional)') + parser.add_argument( + "--destdir", dest="destdir", action=SetConfig, + help='destination directory (defaults to current directory)') + parser.add_argument( + "--cachedir", dest="cachedir", action=SetConfig, + help='package cache directory (defaults to /var/cache/pungi)') + parser.add_argument( + "--bugurl", dest="bugurl", action=SetConfig, + help='the url for your bug system (defaults to http://bugzilla.redhat.com)') + parser.add_argument( + "--selfhosting", action="store_true", dest="selfhosting", + help='build a self-hosting tree by following build dependencies (optional)') + parser.add_argument( + "--fulltree", action="store_true", dest="fulltree", + help='build a tree that includes all packages built from corresponding source rpms (optional)') + parser.add_argument( + "--nosource", action="store_true", dest="nosource", + help='disable gathering of source packages (optional)') + parser.add_argument( + "--nodebuginfo", action="store_true", dest="nodebuginfo", + help='disable gathering of debuginfo packages (optional)') + parser.add_argument( + "--nodownload", action="store_true", dest="nodownload", + help='disable downloading of packages. instead, print the package URLs (optional)') + parser.add_argument( + "--norelnotes", action="store_true", dest="norelnotes", + help='disable gathering of release notes (optional); DEPRECATED') + parser.add_argument( + "--nogreedy", action="store_true", dest="nogreedy", + help='disable pulling of all providers of package dependencies (optional)') + parser.add_argument( + "--nodeps", action="store_false", dest="resolve_deps", default=True, + help='disable resolving dependencies') + parser.add_argument( + "--sourceisos", default=False, action="store_true", dest="sourceisos", + help='Create the source isos (other arch runs must be done)') + parser.add_argument( + "--force", default=False, action="store_true", + help='Force reuse of an existing destination directory (will overwrite files)') + parser.add_argument( + "--isfinal", default=False, action="store_true", + help='Specify this is a GA tree, which causes betanag to be turned off during install') + parser.add_argument( + "--nohash", default=False, action="store_true", + help='disable hashing the Packages trees') + parser.add_argument( + "--full-archlist", action="store_true", + help='Use the full arch list for x86_64 (include i686, i386, etc.)') + parser.add_argument("--arch", help='Override default (uname based) arch') + parser.add_argument( + "--greedy", metavar="METHOD", + help='Greedy method; none, all, build') + parser.add_argument( + "--multilib", action="append", metavar="METHOD", + help='Multilib method; can be specified multiple times; recommended: devel, runtime') + parser.add_argument( + "--lookaside-repo", action="append", dest="lookaside_repos", metavar="NAME", + help='Specify lookaside repo name(s) (packages will used for depsolving but not be included in the output)') + parser.add_argument( + "--workdirbase", dest="workdirbase", action=SetConfig, + help='base working directory (defaults to destdir + /work)') + parser.add_argument("--no-dvd", default=False, action="store_true", dest="no_dvd", + help='Do not make a install DVD/CD only the netinstall image and the tree') + parser.add_argument("--lorax-conf", + help='Path to lorax.conf file (optional)') + parser.add_argument( + "-i", "--installpkgs", default=[], action="append", metavar="STRING", + help="Package glob for lorax to install before runtime-install.tmpl runs. (may be listed multiple times)") + parser.add_argument( + "--multilibconf", default=None, action=SetConfig, + help="Path to multilib conf files. Default is /usr/share/pungi/multilib/") + + parser.add_argument("-c", "--config", dest="config", required=True, + help='Path to kickstart config file') + parser.add_argument("--all-stages", action="store_true", default=True, dest="do_all", + help="Enable ALL stages") + parser.add_argument("-G", action="store_true", default=False, dest="do_gather", + help="Flag to enable processing the Gather stage") + parser.add_argument("-C", action="store_true", default=False, dest="do_createrepo", + help="Flag to enable processing the Createrepo stage") + parser.add_argument("-B", action="store_true", default=False, dest="do_buildinstall", + help="Flag to enable processing the BuildInstall stage") + parser.add_argument("-I", action="store_true", default=False, dest="do_createiso", + help="Flag to enable processing the CreateISO stage") + parser.add_argument("--relnotepkgs", dest="relnotepkgs", action=SetConfig, + help='Rpms which contain the release notes') + parser.add_argument( + "--relnotefilere", dest="relnotefilere", action=SetConfig, + help='Which files are the release notes -- GPL EULA') + parser.add_argument("--nomacboot", action="store_true", dest="nomacboot", + help='disable setting up macboot as no hfs support ') + + parser.add_argument( + "--rootfs-size", dest="rootfs_size", action=SetConfig, default=False, + help='Size of root filesystem in GiB. If not specified, use lorax default value') + + parser.add_argument( + "--pungirc", dest="pungirc", default='~/.pungirc', action=SetConfig, + help='Read pungi options from config file ') + + opts = parser.parse_args() + + if not config.get('pungi', 'variant').isalnum() and not config.get('pungi', 'variant') == '': + parser.error("Variant must be alphanumeric") + + if opts.do_gather or opts.do_createrepo or opts.do_buildinstall or opts.do_createiso: + opts.do_all = False + + if opts.arch and (opts.do_all or opts.do_buildinstall): + parser.error("Cannot override arch while the BuildInstall stage is enabled") + + # set the iso_basename. + if not config.get('pungi', 'variant') == '': + config.set('pungi', 'iso_basename', '%s-%s' % (config.get('pungi', 'family'), config.get('pungi', 'variant'))) + else: + config.set('pungi', 'iso_basename', config.get('pungi', 'family')) + + return opts + + +def main(): + + config = pungi.config.Config() + opts = get_arguments(config) + + # Read the config to create "new" defaults + # reparse command line options so they take precedence + config = pungi.config.Config(pungirc=opts.pungirc) + opts = get_arguments(config) + + # You must be this high to ride if you're going to do root tasks + if os.geteuid() != 0 and (opts.do_all or opts.do_buildinstall): + print("You must run pungi as root", file=sys.stderr) + return 1 + + if opts.do_all or opts.do_buildinstall: + try: + enforcing = selinux.security_getenforce() + except: + print("INFO: selinux disabled") + enforcing = False + if enforcing: + print("WARNING: SELinux is enforcing. This may lead to a compose with selinux disabled.") + print("Consider running with setenforce 0.") + + # Set up the kickstart parser and pass in the kickstart file we were handed + ksparser = pungi.ks.get_ksparser(ks_path=opts.config) + + if opts.sourceisos: + config.set('pungi', 'arch', 'source') + + for part in ksparser.handler.partition.partitions: + if part.mountpoint == 'iso': + config.set('pungi', 'cdsize', str(part.size)) + + config.set('pungi', 'force', str(opts.force)) + + if config.get('pungi', 'workdirbase') == '/work': + config.set('pungi', 'workdirbase', "%s/work" % config.get('pungi', 'destdir')) + # Set up our directories + if not os.path.exists(config.get('pungi', 'destdir')): + try: + os.makedirs(config.get('pungi', 'destdir')) + except OSError: + print("Error: Cannot create destination dir %s" % config.get('pungi', 'destdir'), + file=sys.stderr) + sys.exit(1) + else: + print("Warning: Reusing existing destination directory.") + + if not os.path.exists(config.get('pungi', 'workdirbase')): + try: + os.makedirs(config.get('pungi', 'workdirbase')) + except OSError: + print("Error: Cannot create working base dir %s" % config.get('pungi', 'workdirbase'), + file=sys.stderr) + sys.exit(1) + else: + print("Warning: Reusing existing working base directory.") + + cachedir = config.get('pungi', 'cachedir') + + if not os.path.exists(cachedir): + try: + os.makedirs(cachedir) + except OSError: + print("Error: Cannot create cache dir %s" % cachedir, file=sys.stderr) + sys.exit(1) + + # Set debuginfo flag + if opts.nodebuginfo: + config.set('pungi', 'debuginfo', "False") + if opts.greedy: + config.set('pungi', 'greedy', opts.greedy) + else: + # XXX: compatibility + if opts.nogreedy: + config.set('pungi', 'greedy', "none") + else: + config.set('pungi', 'greedy', "all") + config.set('pungi', 'resolve_deps', str(bool(opts.resolve_deps))) + if opts.isfinal: + config.set('pungi', 'isfinal', "True") + if opts.nohash: + config.set('pungi', 'nohash', "True") + if opts.full_archlist: + config.set('pungi', 'full_archlist', "True") + if opts.arch: + config.set('pungi', 'arch', opts.arch) + if opts.multilib: + config.set('pungi', 'multilib', " ".join(opts.multilib)) + if opts.lookaside_repos: + config.set('pungi', 'lookaside_repos', " ".join(opts.lookaside_repos)) + if opts.no_dvd: + config.set('pungi', 'no_dvd', "True") + if opts.nomacboot: + config.set('pungi', 'nomacboot', "True") + config.set("pungi", "fulltree", str(bool(opts.fulltree))) + config.set("pungi", "selfhosting", str(bool(opts.selfhosting))) + config.set("pungi", "nosource", str(bool(opts.nosource))) + config.set("pungi", "nodebuginfo", str(bool(opts.nodebuginfo))) + + if opts.lorax_conf: + config.set("lorax", "conf_file", opts.lorax_conf) + if opts.installpkgs: + config.set("lorax", "installpkgs", " ".join(opts.installpkgs)) + + # Actually do work. + mypungi = pungi.gather.Pungi(config, ksparser) + + with mypungi.yumlock: + if not opts.sourceisos: + if opts.do_all or opts.do_gather or opts.do_buildinstall: + mypungi._inityum() # initialize the yum object for things that need it + if opts.do_all or opts.do_gather: + mypungi.gather() + if opts.nodownload: + for line in mypungi.list_packages(): + flags_str = ",".join(line["flags"]) + if flags_str: + flags_str = "(%s)" % flags_str + sys.stdout.write("RPM%s: %s\n" % (flags_str, line["path"])) + sys.stdout.flush() + else: + mypungi.downloadPackages() + mypungi.makeCompsFile() + if not opts.nodebuginfo: + mypungi.getDebuginfoList() + if opts.nodownload: + for line in mypungi.list_debuginfo(): + flags_str = ",".join(line["flags"]) + if flags_str: + flags_str = "(%s)" % flags_str + sys.stdout.write("DEBUGINFO%s: %s\n" % (flags_str, line["path"])) + sys.stdout.flush() + else: + mypungi.downloadDebuginfo() + if not opts.nosource: + if opts.nodownload: + for line in mypungi.list_srpms(): + flags_str = ",".join(line["flags"]) + if flags_str: + flags_str = "(%s)" % flags_str + sys.stdout.write("SRPM%s: %s\n" % (flags_str, line["path"])) + sys.stdout.flush() + else: + mypungi.downloadSRPMs() + + print("RPM size: %s MiB" % (mypungi.size_packages() / 1024 ** 2)) + if not opts.nodebuginfo: + print("DEBUGINFO size: %s MiB" % (mypungi.size_debuginfo() / 1024 ** 2)) + if not opts.nosource: + print("SRPM size: %s MiB" % (mypungi.size_srpms() / 1024 ** 2)) + + # Furthermore (but without the yumlock...) + if not opts.sourceisos: + if opts.do_all or opts.do_createrepo: + mypungi.doCreaterepo() + + if opts.do_all or opts.do_buildinstall: + if not opts.norelnotes: + mypungi.doGetRelnotes() + mypungi.doBuildinstall() + + if opts.do_all or opts.do_createiso: + mypungi.doCreateIsos() + + # Do things slightly different for src. + if opts.sourceisos: + # we already have all the content gathered + mypungi.topdir = os.path.join(config.get('pungi', 'destdir'), + config.get('pungi', 'version'), + config.get('pungi', 'variant'), + 'source', 'SRPMS') + mypungi.doCreaterepo(comps=False) + if opts.do_all or opts.do_createiso: + mypungi.doCreateIsos() + + print("All done!") diff --git a/bin/pungi-gather b/pungi/scripts/pungi_gather.py old mode 100755 new mode 100644 similarity index 98% rename from bin/pungi-gather rename to pungi/scripts/pungi_gather.py index e4f4ee5a..2f02b0a7 --- a/bin/pungi-gather +++ b/pungi/scripts/pungi_gather.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- +from __future__ import absolute_import from __future__ import print_function import argparse @@ -176,7 +176,7 @@ def print_rpms(gather_obj): print("SRPM%s: %s" % (_get_flags(gather_obj, pkg), _get_url(pkg))) -if __name__ == "__main__": +def cli_main(): parser = get_parser() ns = parser.parse_args() diff --git a/bin/pungi-koji b/pungi/scripts/pungi_koji.py old mode 100755 new mode 100644 similarity index 99% rename from bin/pungi-koji rename to pungi/scripts/pungi_koji.py index 17a6e87e..48cbc25c --- a/bin/pungi-koji +++ b/pungi/scripts/pungi_koji.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- +from __future__ import absolute_import from __future__ import print_function import argparse @@ -17,11 +17,6 @@ import shutil from six.moves import shlex_quote -here = sys.path[0] -if here != '/usr/bin': - # Git checkout - sys.path[0] = os.path.dirname(here) - from pungi.phases import PHASES_NAMES from pungi import get_full_version, util @@ -479,7 +474,7 @@ def sigterm_handler(signum, frame): sys.exit(1) -if __name__ == "__main__": +def cli_main(): signal.signal(signal.SIGTERM, sigterm_handler) try: diff --git a/bin/pungi-notification-report-progress b/pungi/scripts/report_progress.py old mode 100755 new mode 100644 similarity index 92% rename from bin/pungi-notification-report-progress rename to pungi/scripts/report_progress.py index 5de39045..0d96b260 --- a/bin/pungi-notification-report-progress +++ b/pungi/scripts/report_progress.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - from __future__ import print_function import argparse @@ -8,7 +6,7 @@ import os import sys -if __name__ == '__main__': +def main(): parser = argparse.ArgumentParser() parser.add_argument('cmd') opts = parser.parse_args() diff --git a/bin/pungi-wait-for-signed-ostree-handler b/pungi/scripts/wait_for_signed_ostree_handler.py old mode 100755 new mode 100644 similarity index 98% rename from bin/pungi-wait-for-signed-ostree-handler rename to pungi/scripts/wait_for_signed_ostree_handler.py index eddda647..c4848445 --- a/bin/pungi-wait-for-signed-ostree-handler +++ b/pungi/scripts/wait_for_signed_ostree_handler.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ @@ -38,7 +37,7 @@ def ts_log(msg): print("%s: %s" % (datetime.datetime.utcnow(), msg)) -if __name__ == '__main__': +def main(): parser = argparse.ArgumentParser() parser.add_argument('cmd') opts = parser.parse_args() diff --git a/setup.py b/setup.py index bbabc406..d0d5a2f6 100755 --- a/setup.py +++ b/setup.py @@ -33,21 +33,24 @@ setup( license = "GPLv2", packages = packages, + entry_points = { + 'console_scripts': [ + 'comps_filter = pungi.scripts.comps_filter:main', + 'pungi = pungi.scripts.pungi:main', + 'pungi-create-unified-isos = pungi.scripts.create_unified_isos:main', + 'pungi-fedmsg-notification = pungi.scripts.fedmsg_notification:main', + 'pungi-patch-iso = pungi.scripts.patch_iso:cli_main', + 'pungi-make-ostree = pungi.ostree:main', + 'pungi-notification-report-progress = pungi.scripts.report_progress:main', + 'pungi-orchestrate = pungi_utils.orchestrator:main', + 'pungi-wait-for-signed-ostree-handler = pungi.scripts.wait_for_signed_ostree_handler:main', + 'pungi-koji = pungi.scripts.pungi_koji:cli_main', + 'pungi-gather = pungi.scripts.pungi_gather:cli_main', + 'pungi-config-dump = pungi.scripts.config_dump:cli_main', + 'pungi-config-validate = pungi.scripts.config_validate:cli_main', + ] + }, scripts = [ - 'bin/comps_filter', - 'bin/pungi', - 'bin/pungi-config-dump', - 'bin/pungi-config-validate', - 'bin/pungi-create-unified-isos', - 'bin/pungi-fedmsg-notification', - 'bin/pungi-gather', - 'bin/pungi-koji', - 'bin/pungi-make-ostree', - 'bin/pungi-notification-report-progress', - 'bin/pungi-orchestrate', - 'bin/pungi-patch-iso', - 'bin/pungi-wait-for-signed-ostree-handler', - 'contrib/yum-dnf-compare/pungi-compare-depsolving', ], data_files = [ diff --git a/tests/helpers.py b/tests/helpers.py index 9650d401..bdf51c11 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -275,10 +275,6 @@ def load_config(data={}, **kwargs): return conf -def load_bin(name): - return imp.load_source('pungi_cli_fake_' + name, os.path.dirname(__file__) + "/../bin/" + name) - - def fake_run_in_threads(func, params, threads=None): """Like run_in_threads from Kobo, but actually runs tasks serially.""" for num, param in enumerate(params): diff --git a/tests/test_arguments.py b/tests/test_arguments.py index 6438b2a0..8817859b 100644 --- a/tests/test_arguments.py +++ b/tests/test_arguments.py @@ -5,9 +5,7 @@ except ImportError: import unittest import six -from tests.helpers import load_bin - -cli = load_bin("pungi-koji") +from pungi.scripts.pungi_koji import cli_main class PungiKojiTestCase(unittest.TestCase): @@ -15,10 +13,11 @@ class PungiKojiTestCase(unittest.TestCase): @mock.patch('sys.argv', new=['prog', '--version']) @mock.patch('sys.stderr', new_callable=six.StringIO) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('pungi_cli_fake_pungi-koji.get_full_version', return_value='a-b-c.111') + @mock.patch('pungi.scripts.pungi_koji.get_full_version', return_value='a-b-c.111') def test_version(self, get_full_version, stdout, stderr): - with self.assertRaises(SystemExit): - cli.main() + with self.assertRaises(SystemExit) as cm: + cli_main() + self.assertEqual(cm.exception.code, 0) # Python 2.7 prints the version to stderr, 3.4+ to stdout. if six.PY3: self.assertMultiLineEqual(stdout.getvalue(), 'a-b-c.111\n') diff --git a/tests/test_config_validate_script.py b/tests/test_config_validate_script.py index bd6cfc9f..961e8701 100644 --- a/tests/test_config_validate_script.py +++ b/tests/test_config_validate_script.py @@ -1,30 +1,26 @@ # -*- coding: utf-8 -*- +import mock import os import subprocess import sys +import six + +from pungi.scripts.config_validate import cli_main +from tests import helpers HERE = os.path.abspath(os.path.dirname(__file__)) -BINDIR = os.path.join(HERE, '../bin') -PUNGI_CONFIG_VALIDATE = os.path.join(BINDIR, 'pungi-config-validate') - -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) - -from tests import helpers +DUMMY_CONFIG = os.path.join(HERE, 'data/dummy-pungi.conf') class ConfigValidateScriptTest(helpers.PungiTestCase): - def test_validate_dummy_config(self): - DUMMY_CONFIG = os.path.join(HERE, 'data/dummy-pungi.conf') - p = subprocess.Popen( - [sys.executable, "-W", "ignore", PUNGI_CONFIG_VALIDATE, DUMMY_CONFIG], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - (stdout, stderr) = p.communicate() - self.assertEqual(b'', stdout) - self.assertEqual(b'', stderr) - self.assertEqual(0, p.returncode) + @mock.patch('sys.argv', new=['pungi-config-validate', DUMMY_CONFIG]) + @mock.patch('sys.stderr', new_callable=six.StringIO) + @mock.patch('sys.stdout', new_callable=six.StringIO) + def test_validate_dummy_config(self, stdout, stderr): + cli_main() + self.assertEqual('', stdout.getvalue()) + self.assertEqual('', stderr.getvalue())