diff options
author | Joshua Harlow <harlowja@yahoo-inc.com> | 2012-06-25 16:59:39 -0700 |
---|---|---|
committer | Joshua Harlow <harlowja@yahoo-inc.com> | 2012-06-25 16:59:39 -0700 |
commit | c36c782d3c3913611b86edeb7d371c54ced4b8bd (patch) | |
tree | 1ecbfc9de0ea710155e4b51f3558ee740a3d3773 /packages/brpm | |
parent | 3b05473d57f5aaadf4cd0b57b7138d9ff2141808 (diff) | |
download | vyos-cloud-init-c36c782d3c3913611b86edeb7d371c54ced4b8bd.tar.gz vyos-cloud-init-c36c782d3c3913611b86edeb7d371c54ced4b8bd.zip |
Get rpm building working with a template.
Diffstat (limited to 'packages/brpm')
-rwxr-xr-x | packages/brpm | 270 |
1 files changed, 260 insertions, 10 deletions
diff --git a/packages/brpm b/packages/brpm index f2c3dac4..5feade24 100755 --- a/packages/brpm +++ b/packages/brpm @@ -6,9 +6,19 @@ import subprocess import sys import tempfile import re +import textwrap +import shutil +import zipfile + +import glob import tempita +from datetime import datetime +from datetime import date + +from distutils import version as ver + # This is more just for running from the bin folder so that # cloud-init binary can find the cloudinit module possible_topdir = os.path.normpath(os.path.join(os.path.abspath( @@ -16,28 +26,268 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath( if os.path.exists(os.path.join(possible_topdir, "cloudinit", "__init__.py")): sys.path.insert(0, possible_topdir) +from cloudinit import util +from cloudinit import version + +import contextlib + +# Mapping of expected packages to there full name... +PKG_MP = { + 'boto': 'python-boto', + 'tempita': 'python-tempita', + 'prettytable': 'python-prettytable', + 'oauth': 'python-oauth', + 'configobj': 'python-configobj', + 'yaml': 'PyYAML', + 'argparse': 'python-argparse' +} + + +@contextlib.contextmanager +def chdir(where_to): + cur_cwd = os.path.abspath(os.getcwd()) + where_to = os.path.abspath(where_to) + os.chdir(where_to) + yield where_to + os.chdir(cur_cwd) + + PWD = os.getcwd() def info(msg): - sys.stderr.write("INFO: %s\n" % (msg)) + print("INFO: %s" % (msg)) def warn(msg): - sys.stderr.write("WARNING: %s\n" % (msg)) + print("WARNING: %s" % (msg)) -def main(): - if not os.path.isfile(os.path.join(PWD, 'brpm.tmpl')): - warn("Can not find required template file 'brpm.tmpl'") - return 1 - if not os.path.isfile(os.path.join(os.pardir, 'setup.py')): - warn("Can not find required root 'setup.py' file") - return 1 +def cut_up(entry, maxline=80): + if len(entry) < maxline: + return entry + else: + c = entry[0:maxline] + return "%s..." % (c) + + +def extract_entry(collecting): + a_entry = {} + for t in ['tags', 'revno', 'author', 'timestamp', 'committer']: + look_for = "%s:" % (t) + for v in collecting: + if v.startswith(look_for): + a_entry[t] = v[len(look_for):].strip() + break + i = -1 + for a, v in enumerate(collecting): + if v.startswith("message:"): + i = a + break + if i != -1: + msg_lines = collecting[i + 1:] + n_lines = [] + for m in msg_lines: + m = m.strip() + if not m: + continue + m = m.replace("\n", " ") + n_lines.append("" + m.lstrip()) + message = " ".join(n_lines).lstrip() + a_entry['message'] = message + return a_entry + + +def build_changelog(history=-1): + cmd = ['bzr', 'log', '--timezone=utc'] + (stdout, _stderr) = util.subp(cmd) + # Clean the format up + entries = stdout.splitlines() + all_entries = [] + collecting = [] + for e in entries: + if e.startswith("---"): + if collecting: + a_entry = extract_entry(collecting) + if a_entry: + all_entries.append(a_entry) + collecting = [] + else: + collecting.append(e) + a_entry = extract_entry(collecting) + if a_entry: + all_entries.append(a_entry) + + if history > 0: + take_entries = list(all_entries[0:history]) + else: + take_entries = list(all_entries) + + # Merge those with same date + date_entries = {} + for e in take_entries: + author = e.get('author') + if not author: + author = e.get('committer') + if not author: + continue + timestamp = e.get('timestamp') + if not timestamp: + continue + msg = e.get('message') + if not msg: + continue + revno = e.get('revno') + if not revno: + continue + # http://bugs.python.org/issue6641 + timestamp = timestamp.replace("+0000", '').strip() + ds = datetime.strptime(timestamp, '%a %Y-%m-%d %H:%M:%S') + c_ds = ds.date() + if c_ds not in date_entries: + ap_entry = {} + ap_entry['messages'] = [] + ap_entry['authors'] = [] + ap_entry['revnos'] = [] + date_entries[c_ds] = ap_entry + ap_entry = date_entries[c_ds] + ap_entry['messages'].append(msg) + ap_entry['authors'].append(author) + ap_entry['revnos'].append(revno) + + dates = sorted(date_entries.keys()) + chglog = [] + for ds in reversed(dates): + e = date_entries[ds] + authors = ", ".join(set(e['authors'])) + revnos = ", ".join(list(sorted(e['revnos']))) + top_line = "%s %s - %s" % (ds.strftime("%a %b %d %Y"), + authors, revnos) + chglog.append("* %s" % (top_line)) + for msg in e['messages']: + chglog.append("- %s" % (cut_up(msg))) + return "\n".join(chglog) + + +def generate_spec_contents(tmpl_fn): + # Version junk cmd = [os.path.join(os.pardir, 'tools', 'read-version')] - version = subprocess.check_Call(cmd) + (stdout, _stderr) = util.subp(cmd) + i_version = stdout.strip() + + # Ensure ok match! + if ver.StrictVersion(i_version) != version.version(): + raise RuntimeError("Version found does not match the code version") + + # Tmpl params + subs = {} + subs['version'] = i_version + (stdout, _stderr) = util.subp(['bzr', 'revno']) + subs['revno'] = "%s" % (stdout.strip()) + subs['release'] = "%s" % (subs['revno']) + subs['archive_name'] = '%{name}-%{version}-' + subs['revno'] + '.tar.gz' + subs['bd_requires'] = ['python-devel', 'python-setuptools'] + + requires = [] + cmd = [os.path.join(os.pardir, 'tools', 'read-dependencies')] + (stdout, _stderr) = util.subp(cmd) + pkgs = stdout.splitlines() + + # Map to known packages + for e in pkgs: + e = e.lower().strip() + tgt_pkg = None + for n in PKG_MP.keys(): + if e.find(n) != -1: + tgt_pkg = PKG_MP.get(n) + if not tgt_pkg: + raise RuntimeError(("Do not know how to translate %s to " + " a known package") % (e)) + else: + requires.append(tgt_pkg) + + base_name = 'cloud-init-%s-%s' % (i_version, subs['revno']) + subs['requires'] = requires + subs['changelog'] = build_changelog() + + # See: http://www.zarb.org/~jasonc/macros.php + # Pickup any special files + docs = [ + 'TODO', + 'LICENSE', + 'ChangeLog', + 'Requires', + '%{_defaultdocdir}/cloud-init/*', + ] + subs['docs'] = docs + configs = [ + 'cloud/cloud.cfg', + 'cloud/cloud.cfg.d/*.cfg', + 'cloud/cloud.cfg.d/README', + 'cloud/templates/*', + ] + subs['configs'] = configs + other_files = [ + '%{_bindir}/*', + '/usr/lib/cloud-init/*', + ] + subs['files'] = other_files + with open(tmpl_fn, 'r') as fh: + tmpl = tempita.Template(fh.read()) + contents = tmpl.substitute(**subs) + return (base_name, '%s.tar.gz' % (base_name), contents) + + +def main(): + root_dir = os.path.expanduser("~/rpmbuild") + info("Cleaning %s" % (root_dir)) + util.delete_dir_contents(root_dir) + arc_dir = os.path.join(root_dir, 'SOURCES') + util.ensure_dirs([root_dir, arc_dir]) + tmpl_fn = os.path.join(os.getcwd(), 'brpm.tmpl') + info("Generated spec file from template %s" % (tmpl_fn)) + (base_name, arc_name, contents) = generate_spec_contents(tmpl_fn) + spec_fn = os.path.join(root_dir, 'cloud-init.spec') + util.write_file(spec_fn, contents) + info("Wrote spec file to %s" % (spec_fn)) + with util.tempdir() as td: + src_dir = os.path.join(td, base_name) + os.makedirs(src_dir) + for fn in os.listdir(os.pardir): + if fn.startswith("."): + continue + full_fn = os.path.abspath(os.path.join(os.pardir, fn)) + if os.path.isfile(full_fn): + shutil.copy(full_fn, os.path.join(src_dir, fn)) + else: + shutil.copytree(full_fn, os.path.join(src_dir, fn), + ignore=shutil.ignore_patterns('*.pyc', + '.bzr', + 'tmp*', + '*bzr*')) + arc_fn = os.path.join(arc_dir, arc_name) + cmd = ['tar', '-zcvf', arc_fn, '-C', td] + cmd.extend(os.listdir(td)) + util.subp(cmd) + info("Archived code at %s" % (arc_fn)) + cmd = ['rpmbuild', '-ba', spec_fn] + info("Running rpmbuild %s" % (cmd)) + util.subp(cmd) + info("Rpmbuild completed!") + globs = [] + globs.extend(glob.glob("%s/*.rpm" % + (os.path.join(root_dir, 'RPMS', 'noarch')))) + globs.extend(glob.glob("%s/*.rpm" % + (os.path.join(root_dir, 'RPMS')))) + globs.extend(glob.glob("%s/*.rpm" % + (os.path.join(root_dir, 'SRPMS')))) + for fn in globs: + n = os.path.basename(fn) + tgt_fn = os.path.join(os.getcwd(), n) + util.copy(fn, tgt_fn) + info("Copied %s to %s" % (n, tgt_fn)) return 0 |