# HG changeset patch # User Bernhard Herzog # Date 1189518498 0 # Node ID 3caf4a5ecbf080e63596b21ede0d274dd7a50ad0 # Parent 3ae54f99db26fda26eb8f4802f708aa3f8d413df Add scripts that help publish the packages produced by the tree packager diff -r 3ae54f99db26 -r 3caf4a5ecbf0 bin/listpackages.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/listpackages.py Tue Sep 11 13:48:18 2007 +0000 @@ -0,0 +1,73 @@ +#! /usr/bin/python2.4 +# Copyright (C) 2007 by Intevation GmbH +# Authors: +# Bernhard Herzog +# +# This program is free software under the GPL (>=v2) +# Read the file COPYING coming with the software for details. + +"""List the absolute filenames of packages created by treepkg""" + +import sys + +import treepkgcmd +from treepkg.options import create_parser +from treepkg.report import get_packager_group + +def parse_commandline(): + parser = create_parser() + parser.set_defaults(binary=False, source=False) + parser.add_option("--revision", type="int", + help=("The revision whose files are to be listed." + " If not given, the latest revision is used")) + parser.add_option("--track", + help=("The package track whose files are to be listed")) + parser.add_option("--source", action="store_true", + help=("List source packages")) + parser.add_option("--binary", action="store_true", + help=("List binary packages")) + return parser.parse_args() + + +def list_track_packages(track, revision, source, binary): + revisions = track.get_revisions() + if not revisions: + print >>sys.stderr, "No revisions have been packaged" + sys.exit(1) + + if revision is None: + revpkg = revisions[-1] + else: + for revpkg in revisions: + if revpkg.revision == revision: + break + else: + revpkg = None + + if revpkg is not None: + if source: + for filename in revpkg.list_source_files(): + print filename + if binary: + for filename in revpkg.list_binary_files(): + print filename + else: + print >>sys.stderr, "No revision", repr(revision) + sys.exit(1) + +def list_packages(config_file, trackname, revision, source, binary): + group = get_packager_group(config_file) + for track in group.get_package_tracks(): + if track.name == trackname: + list_track_packages(track, revision, source, binary) + break + else: + print >>sys.stderr, "no track named", trackname + sys.exit(1) + +def main(): + options, args = parse_commandline() + list_packages(options.config_file, options.track, options.revision, + source=options.source, binary=options.binary) + +main() diff -r 3ae54f99db26 -r 3caf4a5ecbf0 bin/publishpackages.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/publishpackages.py Tue Sep 11 13:48:18 2007 +0000 @@ -0,0 +1,123 @@ +#! /usr/bin/python2.4 +# Copyright (C) 2007 by Intevation GmbH +# Authors: +# Bernhard Herzog +# +# This program is free software under the GPL (>=v2) +# Read the file COPYING coming with the software for details. + +"""Publishes selected packages created by treepkg""" + +import sys +import os +import shutil +from optparse import OptionParser +from ConfigParser import SafeConfigParser + +import treepkgcmd +from treepkg.readconfig import read_config_section +from treepkg.run import call, capture_output +from treepkg.cmdexpand import cmdexpand +from treepkg.util import ensure_directory, listdir_abs + + +def remove_trailing_slashes(s): + return s.rstrip("/") + +def expand_filename(filename): + """ + Applies os.path.expanduser and os.path.expandvars to filename + """ + return os.path.expandvars(os.path.expanduser(filename)) + +config_desc = ["build_user", "build_host", "build_listpackages", + "publish_user", "publish_host", "publish_apt_archive_update", + ("publish_dir", remove_trailing_slashes), + ("cachedir", + lambda s: expand_filename(remove_trailing_slashes(s)))] + +def read_config(filename): + parser = SafeConfigParser() + parser.read([filename]) + return read_config_section(parser, "publishpackages", config_desc) + +def parse_commandline(): + parser = OptionParser() + parser.set_defaults(config_file=os.path.join(treepkgcmd.topdir, + "publishpackages.cfg")) + parser.add_option("--config-file", + help=("The configuration file." + " Default is publishpackages.cfg")) + parser.add_option("--revision", + help=("The revision whose files are to be published." + " If not given, the latest revision is used")) + parser.add_option("--dist", + help=("The debian distribution name to use on" + " the publishing system")) + parser.add_option("--section", + help=("The debian distribution section name to use on" + " the publishing system")) + parser.add_option("--track", + help=("The package track whose files are to be" + " published")) + return parser.parse_args() + + +def publish_packages_arch(variables, track, revision, dist, section, arch): + # create web-page on build host + if arch == "source": + variables["pkgtype"] = "--source" + else: + variables["pkgtype"] = "--binary" + + files = capture_output(cmdexpand("ssh $build_user$@$build_host" + " $build_listpackages" + " --track $track @revision $pkgtype", + **variables)).strip().split("\n") + # scp the packages to the cache dir + cachedir = variables["cachedir"] + shutil.rmtree(cachedir, ignore_errors=True) + ensure_directory(cachedir) + userhost = "%(build_user)s@%(build_host)s:" % variables + call(cmdexpand("scp @files $cachedir/", + files = [userhost + filename for filename in files], + **variables)) + + # copy the packages to the remote publishing host. Create the + # destination directory if it doesn't exist yet. + destdir = os.path.join(variables["publish_dir"], dist, section, arch) + call(cmdexpand("ssh $publish_user$@$publish_host mkdir --parents $destdir", + destdir=destdir, **variables)) + call(cmdexpand("scp @files $publish_user$@$publish_host:$destdir", + files=listdir_abs(cachedir), destdir=destdir, + **variables)) + + +def publish_packages(config_filename, track, revision, dist, section): + config = read_config(config_filename) + + variables = config.copy() + variables["track"] = track + if revision: + variables["revision"] = ["--revision", revision] + else: + variables["revision"] = [] + + for arch in ["binary-i386", "source"]: + publish_packages_arch(variables, track, revision, dist, section, arch) + + # update apt archive + call(cmdexpand("ssh $publish_user$@$publish_host" + " $publish_apt_archive_update", + **variables)) + +def main(): + options, args = parse_commandline() + for required_opt in ["track", "dist", "section"]: + if getattr(options, required_opt) is None: + print >>sys.stderr, "The --%s option must be given" % required_opt + sys.exit(1) + publish_packages(options.config_file, options.track, options.revision, + options.dist, options.section) + +main() diff -r 3ae54f99db26 -r 3caf4a5ecbf0 demopublishpackages.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demopublishpackages.cfg Tue Sep 11 13:48:18 2007 +0000 @@ -0,0 +1,37 @@ +# Demo configuration file for publishpackages.py. The default config +# file used by publishpackages.py is publishpackages.cfg, so to use this +# file as the basis for your configuration, copy or rename this file and +# adapt it to your needs. + +[publishpackages] +# Username and host on which the treepackager runs. publishpackages.py +# has to be able to connect to that host as the builduser via ssh +# without knowning the password. This is best achieved with the +# ssh-agent. +build_user: builder +build_host: localhost + +# the program to run on build_host to list the filenames of the packages +# in question. Currently publishpackages.py assumes that the default +# configuration for that program works. +build_listpackages: ~/treepkg/bin/bin/listpackages.py + +# Username and host on which to publish the packages. +# publishpackages.py uses ssh to execute commands on the publish_host to +# create directories and scp to copy the files from the local cache to +# the publish_host. +publish_user: builder +publish_host: localhost + +# the directory on the publish_host where the apt directories reside. +publish_dir: /home/ftp/apt/dists/ + +# Command to execute on the build host to update the apt archive +publish_apt_archive_update: /home/ftp/apt/update + +# local cache directory. publishpackages.py may delete it and its +# contents. The value is passed through the python functions +# os.expanduser and os.expandvars, so references to home directories of +# the form ~ or ~user at the beginning of the value and environment +# variable references of the form $VAR or ${VAR} are expanded. +cachedir: /tmp/${LOGNAME}/treepkg-package-cache