bh@287: #! /usr/bin/python
bh@243: # Copyright (C) 2007, 2008, 2009 by Intevation GmbH
bh@177: # Authors:
bh@177: # Bernhard Herzog <bh@intevation.de>
bh@177: #
bh@177: # This program is free software under the GPL (>=v2)
bh@177: # Read the file COPYING coming with the software for details.
bh@177: 
bh@177: """Usage: treepkgbuilder COMMAND [options]
bh@177: 
bh@177: Manage the pbuilder environment for a tree packager installation.  The
bh@177: pbuilder settings are taken from the configuration file, either the
bh@177: default treepkg.cfg or the one given with the --config-file option.
bh@177: Also, this script assumes that there is only one pbuilder setting for
bh@177: all packagers.  Use treepkgbuilder COMMAND --help for more details about
bh@177: the commands.
bh@177: """
bh@177: 
bh@177: import sys
bh@177: 
bh@177: import treepkgcmd
bh@177: from treepkg.options import create_parser
bh@177: from treepkg.packager import create_package_track, PackagerGroup
bh@177: from treepkg.readconfig import read_config
bh@177: 
bh@177: 
bh@177: class Command(object):
bh@177: 
bh@177:     names = ()
bh@177: 
bh@177:     def __init__(self, arguments):
bh@177:         parser = self.create_parser()
bh@177:         self.opts, self.rest = parser.parse_args(arguments)
bh@177: 
bh@177:     def create_parser(self):
bh@177:         return create_parser()
bh@177: 
bh@177:     def read_config(self):
bh@177:         self.treepkg_opts, self.packager_opts \
bh@177:                            = read_config(self.opts.config_file)
bh@177: 
bh@177:     def get_builder(self):
bh@177:         self.read_config()
bh@177:         group = PackagerGroup([create_package_track(**opts)
bh@177:                                for opts in self.packager_opts],
bh@177:                               **self.treepkg_opts)
bh@177:         track = group.get_package_tracks()[0]
bh@177:         return track.builder
bh@177: 
bh@177: 
bh@177: 
bh@177: class InitCommand(Command):
bh@177: 
bh@177:     names = ("init",)
bh@177: 
bh@177:     def __init__(self, arguments):
bh@177:         super(InitCommand, self).__init__(arguments)
bh@177:         if self.opts.mirrorsite is None:
bh@177:             print >>sys.stderr, "Missing required option --mirrorsite"
bh@177:             sys.exit(1)
bh@177: 
bh@177:     def create_parser(self):
bh@177:         parser = super(InitCommand, self).create_parser()
bh@177:         parser.set_defaults(distribution="etch")
bh@177:         parser.add_option("--mirrorsite",
bh@177:                           help=("The debian mirror site"
bh@177:                                 " (pbuilder MIRRORSITE setting).  Required."))
bh@177:         parser.add_option("--othermirror",
bh@177:                           help=("Extra contents of the OTHERMIRROR setting."
bh@177:                                 " See the pbuilder documentation for the"
bh@177:                                 " format."))
bh@177:         parser.add_option("--distribution",
bh@177:                           help=("The debian distribution for the pbuilder"
bh@177:                                 " chroot. Default is etch."))
bh@177:         return parser
bh@177: 
bh@177:     def run(self):
bh@177:         builder = self.get_builder()
bricks@344:         builder.init_builder(distribution=self.opts.distribution,
bh@177:                               mirrorsite=self.opts.mirrorsite,
bh@177:                               extramirrors=self.opts.othermirror)
bh@177: 
bh@177: 
bh@192: class AddBinariesCommand(Command):
bh@192: 
bh@192:     names = ("add-binaries",)
bh@192: 
bh@296:     def create_parser(self):
bh@296:         parser = super(AddBinariesCommand, self).create_parser()
bh@296:         parser.set_defaults(subdir="manual")
bh@296:         parser.add_option("--subdir",
bh@296:                           help=("The subdirectory of extra-pkg into which"
bh@296:                                 " the packages are to be copied"
bh@296:                                 " (default 'manual')."))
bh@296:         return parser
bh@296: 
bh@296: 
bh@192:     def run(self):
bh@192:         builder = self.get_builder()
bh@296:         builder.add_binaries_to_extra_pkg(self.rest,
bh@296:                                           subdirectory=self.opts.subdir)
bh@192: 
bh@192: 
bh@177: class UpdateCommand(Command):
bh@177: 
bh@177:     names = ("update",)
bh@177: 
bh@177:     def run(self):
bh@177:         builder = self.get_builder()
bh@177:         builder.update(suppress_output=False, log_info=False)
bh@177: 
bh@177: 
bh@184: class AddKeyCommand(Command):
bh@184: 
bh@184:     names = ("addkey", "add-key")
bh@184: 
bh@184:     def __init__(self, arguments):
bh@184:         super(AddKeyCommand, self).__init__(arguments)
bh@184:         if not self.opts.key_id:
bh@184:             print >>sys.stderr, "No key id given"
bh@184:             sys.exit(1)
bh@184: 
bh@184:     def create_parser(self):
bh@184:         parser = super(AddKeyCommand, self).create_parser()
bh@184:         parser.add_option("--key-id",
bh@184:                           help=("The id of the key to add.  Required."))
bh@184:         return parser
bh@184: 
bh@184:     def run(self):
bh@184:         builder = self.get_builder()
bh@184:         builder.add_apt_key(self.opts.key_id)
bh@184: 
bh@184: 
bh@201: class LoginCommand(Command):
bh@201: 
bh@201:     names = ("login",)
bh@201: 
bh@213:     def create_parser(self):
bh@213:         parser = super(LoginCommand, self).create_parser()
bh@213:         parser.set_defaults(bind_mount=[])
bh@213:         parser.add_option("--bind-mount", action="append",
bh@213:                           help=("Directories to bind-mount in the chroot"
bh@213:                                 " environment."))
bh@245:         parser.add_option("--save-after-login", action="store_true",
bh@245:                           help="Copy changes back to the tarball.")
bh@213:         return parser
bh@213: 
bh@213: 
bh@201:     def run(self):
bh@245:         self.get_builder().login(bindmounts=self.opts.bind_mount,
bh@245:                                  save_after_login=self.opts.save_after_login)
bh@201: 
bh@201: 
bh@210: class BuildCommand(Command):
bh@210: 
bh@210:     names = ("build",)
bh@210: 
bh@210:     def create_parser(self):
bh@210:         parser = super(BuildCommand, self).create_parser()
bh@210:         parser.add_option("--logfile", help=("The file for the build log."))
bh@210:         parser.add_option("--binary-dir",
bh@210:                           help=("Directory for the binary packages."))
bh@210:         return parser
bh@210: 
bh@210:     def run(self):
bh@210:         if len(self.rest) != 1:
bh@210:             print >>sys.stderr, "Exactly one .dsc file must be specified"
bh@210:             sys.exit(1)
bh@210:         dsc_file = self.rest[0]
bh@210:         self.get_builder().build(dsc_file, binary_dir=self.opts.binary_dir,
bh@210:                                  logfile=self.opts.logfile)
bh@210: 
bh@210: 
bh@243: class ExecuteCommand(Command):
bh@243: 
bh@243:     names = ("execute",)
bh@243: 
bh@243:     def create_parser(self):
bh@243:         parser = super(ExecuteCommand, self).create_parser()
bh@243:         parser.add_option("--logfile", help=("Log file."))
bh@243:         parser.add_option("--bind-mount", action="append",
bh@243:                           help=("Directories to bind-mount in the chroot"
bh@243:                                 " environment."))
bh@243:         return parser
bh@243: 
bh@243:     def run(self):
bh@243:         if not self.rest:
bh@243:             print >>sys.stderr, "At least the script file must be specified"
bh@243:             sys.exit(1)
bh@243:         script = self.rest
bh@243:         self.get_builder().run_script(script, bindmounts=self.opts.bind_mount,
bh@243:                                       logfile=self.opts.logfile)
bh@243: 
bh@243: 
bh@177: class HelpCommand(Command):
bh@177: 
bh@177:     names = ("help", "--help", "-h")
bh@177: 
bh@177:     def run(self):
bh@177:         print __doc__.rstrip()
bh@177:         print "Supported commands:"
bh@177:         commands = sorted((cmd for cmd in iter_commands() if cmd.names),
bh@177:                           key=lambda cmd: cmd.names[0])
bh@177:         for cmd in commands:
bh@177:             print "   ", " ".join(cmd.names)
bh@177: 
bh@177: 
bh@177: def iter_commands():
bh@177:     for key, obj in globals().items():
bh@177:         if key.endswith("Command"):
bh@177:             yield obj
bh@177: 
bh@177: def get_command_class(name):
bh@177:     for obj in iter_commands():
bh@177:         if name in obj.names:
bh@177:             return obj
bh@177:     return None
bh@177: 
bh@177: 
bh@177: def main():
bh@177:     arguments = sys.argv[1:]
bh@177: 
bh@177:     if len(arguments) < 1:
bh@177:         print >>sys.stderr, "Missing command"
bh@177:         sys.exit(1)
bh@177: 
bh@177:     command_name = arguments[0]
bh@177:     arguments = arguments[1:]
bh@177: 
bh@177:     command_class = get_command_class(command_name)
bh@177:     if command_class is None:
bh@177:         print >>sys.stderr, "Unknown command %r" % command_name
bh@177:         sys.exit(1)
bh@177: 
bh@177:     command = command_class(arguments)
bh@177:     command.run()
bh@177: 
bh@177: 
bh@177: main()