Merge ~larsks/cloud-init:feature/move-to-git into cloud-init:master
- Git
- lp:~larsks/cloud-init
- feature/move-to-git
- Merge into master
Proposed by
Lars Kellogg-Stedman
on 2016-07-27
| Status: | Merged |
|---|---|
| Merged at revision: | 72d6adcb2e4cb5911f7809b89835965d4bf04476 |
| Proposed branch: | ~larsks/cloud-init:feature/move-to-git |
| Merge into: | cloud-init:master |
| Diff against target: |
746 lines (+228/-275) 9 files modified
.gitignore (+5/-0) HACKING.rst (+46/-22) MANIFEST.in (+2/-0) dev/null (+0/-21) packages/brpm (+123/-171) packages/redhat/cloud-init.spec.in (+6/-14) packages/suse/cloud-init.spec.in (+3/-11) tools/make-tarball (+22/-30) tools/read-dependencies (+21/-6) |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Joshua Harlow | 2016-07-27 | Pending | |
|
Review via email:
|
|||
Commit Message
Description of the Change
Update build tools to work with git
- Update HACKING.rst to include git instructions
- update MANIFEST.in and .gitignore to ignore git-related things
- replaced tarball generation scripts with git-based script
- have the spec files correctly identify themselves as cheetah templates
- make brpm work with git
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
| 1 | diff --git a/.gitignore b/.gitignore |
| 2 | new file mode 100644 |
| 3 | index 0000000..f8b0f3e |
| 4 | --- /dev/null |
| 5 | +++ b/.gitignore |
| 6 | @@ -0,0 +1,5 @@ |
| 7 | +.tox |
| 8 | +dist |
| 9 | +cloud_init.egg-info |
| 10 | +__pycache__ |
| 11 | +build |
| 12 | diff --git a/HACKING.rst b/HACKING.rst |
| 13 | index 6bfe4b4..63a5bde 100644 |
| 14 | --- a/HACKING.rst |
| 15 | +++ b/HACKING.rst |
| 16 | @@ -2,47 +2,71 @@ |
| 17 | Hacking on cloud-init |
| 18 | ===================== |
| 19 | |
| 20 | -To get changes into cloud-init, the process to follow is: |
| 21 | +This document describes how to contribute changes to cloud-init. |
| 22 | + |
| 23 | +Do these things once |
| 24 | +-------------------- |
| 25 | |
| 26 | * If you have not already, be sure to sign the CCA: |
| 27 | |
| 28 | - `Canonical Contributor Agreement`_ |
| 29 | |
| 30 | -* Get your changes into a local bzr branch. |
| 31 | - Initialize a repo, and checkout trunk (init repo is to share bzr info across multiple checkouts, its different than git): |
| 32 | +* Clone the `LaunchPad`_ repository: |
| 33 | + |
| 34 | + git clone YOUR_USERNAME@git.launchpad.net:cloud-init |
| 35 | + cd cloud-init |
| 36 | + |
| 37 | + If you would prefer a bzr style `git clone lp:cloud-init`, see |
| 38 | + the `Instructions on LaunchPad`_ for more information. |
| 39 | |
| 40 | - - ``bzr init-repo cloud-init`` |
| 41 | - - ``bzr branch lp:cloud-init trunk.dist`` |
| 42 | - - ``bzr branch trunk.dist my-topic-branch`` |
| 43 | +* Create a new remote pointing to your personal LaunchPad |
| 44 | + repository:: |
| 45 | + |
| 46 | + git remote add YOUR_USERNAME YOUR_USERNAME@git.launchpad.net:~YOUR_USERNAME/cloud-init |
| 47 | + |
| 48 | +.. _Canonical Contributor Agreement: http://www.canonical.com/contributors |
| 49 | |
| 50 | -* Commit your changes (note, you can make multiple commits, fixes, more commits.): |
| 51 | +Do these things for each feature or bug |
| 52 | +--------------------------------------- |
| 53 | |
| 54 | - - ``bzr commit`` |
| 55 | +* Create a new topic branch for your work:: |
| 56 | |
| 57 | -* Check pep8 and test, and address any issues: |
| 58 | + git checkout -b my-topic-branch |
| 59 | |
| 60 | - - ``make test pep8`` |
| 61 | +.. _Instructions on launchpad: https://help.launchpad.net/Code/Git |
| 62 | |
| 63 | -* Push to launchpad to a personal branch: |
| 64 | +* Make and commit your changes (note, you can make multiple commits, |
| 65 | + fixes, more commits.):: |
| 66 | |
| 67 | - - ``bzr push lp:~<YOUR_USERNAME>/cloud-init/<BRANCH_NAME>`` |
| 68 | + git commit |
| 69 | |
| 70 | -* Propose that for a merge into lp:cloud-init via web browser. |
| 71 | +* Check pep8 and test, and address any issues:: |
| 72 | |
| 73 | - - Open the branch in `Launchpad`_ |
| 74 | + make test pep8 |
| 75 | |
| 76 | - - It will typically be at ``https://code.launchpad.net/<YOUR_USERNAME>/<PROJECT>/<BRANCH_NAME>`` |
| 77 | - - ie. https://code.launchpad.net/~smoser/cloud-init/mybranch |
| 78 | +* Push your changes to your personal LaunchPad repository:: |
| 79 | |
| 80 | -* Click 'Propose for merging' |
| 81 | -* Select 'lp:cloud-init' as the target branch |
| 82 | + git push -u YOUR_USERNAME my-topic-branch |
| 83 | |
| 84 | -Then, someone on cloud-init-dev (currently `Scott Moser`_ and `Joshua Harlow`_) will |
| 85 | -review your changes and follow up in the merge request. |
| 86 | +* Use your browser to create a merge request: |
| 87 | |
| 88 | -Feel free to ping and/or join #cloud-init on freenode (irc) if you have any questions. |
| 89 | + - Open the branch on `LaunchPad`_ |
| 90 | + |
| 91 | + - It will typically be at |
| 92 | + ``https://code.launchpad.net/~YOUR_USERNAME/cloud-init/+git/cloud-init/+ref/BRANCHNAME`` |
| 93 | + for example |
| 94 | + https://code.launchpad.net/~larsks/cloud-init/+git/cloud-init/+ref/feature/move-to-git |
| 95 | + |
| 96 | + - Click 'Propose for merging` |
| 97 | + - Select ``cloud-init`` as the target repository |
| 98 | + - Select ``master`` as the target reference path |
| 99 | + |
| 100 | +Then, someone on cloud-init-dev (currently `Scott Moser`_ and `Joshua |
| 101 | +Harlow`_) will review your changes and follow up in the merge request. |
| 102 | + |
| 103 | +Feel free to ping and/or join ``#cloud-init`` on freenode (irc) if you |
| 104 | +have any questions. |
| 105 | |
| 106 | .. _Launchpad: https://launchpad.net |
| 107 | -.. _Canonical Contributor Agreement: http://www.canonical.com/contributors |
| 108 | .. _Scott Moser: https://launchpad.net/~smoser |
| 109 | .. _Joshua Harlow: https://launchpad.net/~harlowja |
| 110 | diff --git a/MANIFEST.in b/MANIFEST.in |
| 111 | index 90f6c7d..9426464 100644 |
| 112 | --- a/MANIFEST.in |
| 113 | +++ b/MANIFEST.in |
| 114 | @@ -4,5 +4,7 @@ graft tools |
| 115 | prune build |
| 116 | prune dist |
| 117 | prune .tox |
| 118 | +prune .git |
| 119 | prune .bzr |
| 120 | +exclude .gitignore |
| 121 | exclude .bzrignore |
| 122 | diff --git a/packages/brpm b/packages/brpm |
| 123 | index 45e4761..5d16eb7 100755 |
| 124 | --- a/packages/brpm |
| 125 | +++ b/packages/brpm |
| 126 | @@ -1,27 +1,24 @@ |
| 127 | -#!/usr/bin/python |
| 128 | +#!/usr/bin/env python |
| 129 | |
| 130 | import argparse |
| 131 | -import contextlib |
| 132 | import glob |
| 133 | import os |
| 134 | import shutil |
| 135 | -import subprocess |
| 136 | import sys |
| 137 | import tempfile |
| 138 | -import re |
| 139 | - |
| 140 | -from datetime import datetime |
| 141 | +import time |
| 142 | |
| 143 | |
| 144 | def find_root(): |
| 145 | # expected path is in <top_dir>/packages/ |
| 146 | top_dir = os.environ.get("CLOUD_INIT_TOP_D", None) |
| 147 | if top_dir is None: |
| 148 | - top_dir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))) |
| 149 | + top_dir = os.path.dirname( |
| 150 | + os.path.dirname(os.path.abspath(sys.argv[0]))) |
| 151 | if os.path.isfile(os.path.join(top_dir, 'setup.py')): |
| 152 | return os.path.abspath(top_dir) |
| 153 | raise OSError(("Unable to determine where your cloud-init topdir is." |
| 154 | - " set CLOUD_INIT_TOP_D?")) |
| 155 | + " set CLOUD_INIT_TOP_D?")) |
| 156 | |
| 157 | |
| 158 | # Use the util functions from cloudinit |
| 159 | @@ -30,34 +27,15 @@ sys.path.insert(0, find_root()) |
| 160 | from cloudinit import templater |
| 161 | from cloudinit import util |
| 162 | |
| 163 | -# Mapping of expected packages to there full name... |
| 164 | -# this is a translation of the 'requires' |
| 165 | -# file pypi package name to a redhat/fedora package name. |
| 166 | -PKG_MP = { |
| 167 | +# Map python requirements to package names. If a match isn't found |
| 168 | +# here, we assume 'python-<pypi_name>'. |
| 169 | +PACKAGE_MAP = { |
| 170 | 'redhat': { |
| 171 | - 'argparse': 'python-argparse', |
| 172 | - 'cheetah': 'python-cheetah', |
| 173 | - 'jinja2': 'python-jinja2', |
| 174 | - 'configobj': 'python-configobj', |
| 175 | - 'jsonpatch': 'python-jsonpatch', |
| 176 | - 'oauthlib': 'python-oauthlib', |
| 177 | - 'prettytable': 'python-prettytable', |
| 178 | 'pyserial': 'pyserial', |
| 179 | 'pyyaml': 'PyYAML', |
| 180 | - 'requests': 'python-requests', |
| 181 | - 'six': 'python-six', |
| 182 | }, |
| 183 | 'suse': { |
| 184 | - 'argparse': 'python-argparse', |
| 185 | - 'cheetah': 'python-cheetah', |
| 186 | - 'configobj': 'python-configobj', |
| 187 | - 'jsonpatch': 'python-jsonpatch', |
| 188 | - 'oauthlib': 'python-oauthlib', |
| 189 | - 'prettytable': 'python-prettytable', |
| 190 | - 'pyserial': 'python-pyserial', |
| 191 | 'pyyaml': 'python-yaml', |
| 192 | - 'requests': 'python-requests', |
| 193 | - 'six': 'python-six', |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | @@ -65,113 +43,79 @@ PKG_MP = { |
| 198 | RPM_BUILD_SUBDIRS = ['BUILD', 'RPMS', 'SOURCES', 'SPECS', 'SRPMS'] |
| 199 | |
| 200 | |
| 201 | -def get_log_header(version): |
| 202 | - # Try to find the version in the tags output |
| 203 | - cmd = ['bzr', 'tags'] |
| 204 | - (stdout, _stderr) = util.subp(cmd) |
| 205 | - a_rev = None |
| 206 | - for t in stdout.splitlines(): |
| 207 | - ver, rev = t.split(None) |
| 208 | - if ver == version: |
| 209 | - a_rev = rev |
| 210 | - break |
| 211 | - if not a_rev: |
| 212 | - return None |
| 213 | - |
| 214 | - # Extract who made that tag as the header |
| 215 | - cmd = ['bzr', 'log', '-r%s' % (a_rev), '--timezone=utc'] |
| 216 | +def read_dependencies(): |
| 217 | + '''Returns the Python depedencies from requirements.txt. This explicitly |
| 218 | + removes 'argparse' from the list of requirements for python >= 2.7, |
| 219 | + because with 2.7 argparse became part of the standard library.''' |
| 220 | + cmd = [util.abs_join(find_root(), 'tools', 'read-dependencies')] |
| 221 | (stdout, _stderr) = util.subp(cmd) |
| 222 | - kvs = { |
| 223 | - 'comment': version, |
| 224 | - } |
| 225 | + return [p.lower().strip() for p in stdout.splitlines() |
| 226 | + if p != 'argparse' or (p == 'argparse' |
| 227 | + and sys.version_info[0:2] < (2, 7))] |
| 228 | |
| 229 | - for line in stdout.splitlines(): |
| 230 | - if line.startswith('committer:'): |
| 231 | - kvs['who'] = line[len('committer:'):].strip() |
| 232 | - if line.startswith('timestamp:'): |
| 233 | - ts = line[len('timestamp:'):] |
| 234 | - ts = ts.strip() |
| 235 | - # http://bugs.python.org/issue6641 |
| 236 | - ts = ts.replace("+0000", '').strip() |
| 237 | - ds = datetime.strptime(ts, '%a %Y-%m-%d %H:%M:%S') |
| 238 | - kvs['ds'] = ds |
| 239 | |
| 240 | - return format_change_line(**kvs) |
| 241 | +def translate_dependencies(deps, distro): |
| 242 | + '''Maps python requirements into package names. We assume |
| 243 | + python-<pypi_name> for packages not listed explicitly in |
| 244 | + PACKAGE_MAP.''' |
| 245 | + return [PACKAGE_MAP[distro][req] |
| 246 | + if req in PACKAGE_MAP[distro] else 'python-%s' % req |
| 247 | + for req in deps] |
| 248 | |
| 249 | |
| 250 | -def format_change_line(ds, who, comment=None): |
| 251 | - # Rpmbuild seems to be pretty strict about the date format |
| 252 | - d = ds.strftime("%a %b %d %Y") |
| 253 | - d += " - %s" % (who) |
| 254 | - if comment: |
| 255 | - d += " - %s" % (comment) |
| 256 | - return "* %s" % (d) |
| 257 | - |
| 258 | - |
| 259 | -def generate_spec_contents(args, tmpl_fn, top_dir, arc_fn): |
| 260 | - |
| 261 | +def read_version(): |
| 262 | + '''Read version information. We parse the version itself from |
| 263 | + the changelog, and then ask git for the commit id and distance |
| 264 | + from the last tag.''' |
| 265 | # Figure out the version and revno |
| 266 | cmd = [util.abs_join(find_root(), 'tools', 'read-version')] |
| 267 | (stdout, _stderr) = util.subp(cmd) |
| 268 | version = stdout.strip() |
| 269 | - |
| 270 | - cmd = ['bzr', 'revno'] |
| 271 | + |
| 272 | + cmd = ['git', 'describe', '--tags'] |
| 273 | (stdout, _stderr) = util.subp(cmd) |
| 274 | - revno = stdout.strip() |
| 275 | + git_version = stdout.strip() |
| 276 | + |
| 277 | + try: |
| 278 | + _version, distance, revno = git_version.split('-') |
| 279 | + except ValueError: |
| 280 | + distance = None |
| 281 | + revno = None |
| 282 | + |
| 283 | + return (version, distance, revno) |
| 284 | + |
| 285 | + |
| 286 | +def generate_spec_contents(args, tmpl_fn, top_dir, arc_fn): |
| 287 | + |
| 288 | + # This will get us something like ('0.7.6', None, None) for a |
| 289 | + # tagged commit, and something like ('0.7.6', '1026', 'gd1d5796') |
| 290 | + # for an untagged commited. |
| 291 | + version, distance, revno = read_version() |
| 292 | |
| 293 | # Tmpl params |
| 294 | subs = {} |
| 295 | subs['version'] = version |
| 296 | subs['revno'] = revno |
| 297 | - subs['release'] = "bzr%s" % (revno) |
| 298 | + subs['distance'] = distance |
| 299 | + |
| 300 | + if distance is not None: |
| 301 | + now = time.strftime('%Y%m%d', time.localtime()) |
| 302 | + release = '.%sgit%s' % (now, revno) |
| 303 | + else: |
| 304 | + release = '' |
| 305 | + |
| 306 | if args.sub_release is not None: |
| 307 | - subs['subrelease'] = "." + str(args.sub_release) |
| 308 | + subs['subrelease'] = release + "." + str(args.sub_release) |
| 309 | else: |
| 310 | - subs['subrelease'] = '' |
| 311 | - subs['archive_name'] = arc_fn |
| 312 | + subs['subrelease'] = release |
| 313 | |
| 314 | - cmd = [util.abs_join(find_root(), 'tools', 'read-dependencies')] |
| 315 | - (stdout, _stderr) = util.subp(cmd) |
| 316 | - pkgs = [p.lower().strip() for p in stdout.splitlines()] |
| 317 | + subs['archive_name'] = arc_fn |
| 318 | + subs['source_name'] = os.path.basename(arc_fn).replace('.tar.gz', '') |
| 319 | |
| 320 | # Map to known packages |
| 321 | - requires = [] |
| 322 | - for p in pkgs: |
| 323 | - if p == 'argparse' and sys.version_info[0:2] >= (2, 7): |
| 324 | - # Not needed on anything but 2.6 or older. |
| 325 | - continue |
| 326 | - tgt_pkg = PKG_MP[args.distro].get(p) |
| 327 | - if not tgt_pkg: |
| 328 | - raise RuntimeError(("Do not know how to translate pypi dependency" |
| 329 | - " %r to a known package") % (p)) |
| 330 | - else: |
| 331 | - requires.append(tgt_pkg) |
| 332 | - subs['requires'] = requires |
| 333 | - |
| 334 | - # Format a nice changelog (as best as we can) |
| 335 | - changelog = util.load_file(util.abs_join(find_root(), 'ChangeLog')) |
| 336 | - changelog_lines = [] |
| 337 | - missing_versions = 0 |
| 338 | - for line in changelog.splitlines(): |
| 339 | - if not line.strip(): |
| 340 | - continue |
| 341 | - if re.match(r"^\s*[\d][.][\d][.][\d]:\s*", line): |
| 342 | - line = line.strip(":") |
| 343 | - header = get_log_header(line) |
| 344 | - if not header: |
| 345 | - missing_versions += 1 |
| 346 | - if missing_versions == 1: |
| 347 | - # Must be using a new 'dev'/'trunk' release |
| 348 | - changelog_lines.append(format_change_line(datetime.now(), |
| 349 | - '??')) |
| 350 | - else: |
| 351 | - sys.stderr.write(("Changelog version line %s does not " |
| 352 | - "have a corresponding tag!\n") % (line)) |
| 353 | - else: |
| 354 | - changelog_lines.append(header) |
| 355 | - else: |
| 356 | - changelog_lines.append(line) |
| 357 | - subs['changelog'] = "\n".join(changelog_lines) |
| 358 | + python_deps = read_dependencies() |
| 359 | + package_deps = translate_dependencies(python_deps, args.distro) |
| 360 | + subs['requires'] = package_deps |
| 361 | |
| 362 | if args.boot == 'sysvinit': |
| 363 | subs['sysvinit'] = True |
| 364 | @@ -183,21 +127,23 @@ def generate_spec_contents(args, tmpl_fn, top_dir, arc_fn): |
| 365 | else: |
| 366 | subs['systemd'] = False |
| 367 | |
| 368 | - subs['defines'] = ["_topdir %s" % (top_dir)] |
| 369 | subs['init_sys'] = args.boot |
| 370 | subs['patches'] = [os.path.basename(p) for p in args.patches] |
| 371 | return templater.render_from_file(tmpl_fn, params=subs) |
| 372 | |
| 373 | |
| 374 | def main(): |
| 375 | - |
| 376 | + |
| 377 | parser = argparse.ArgumentParser() |
| 378 | parser.add_argument("-d", "--distro", dest="distro", |
| 379 | help="select distro (default: %(default)s)", |
| 380 | metavar="DISTRO", default='redhat', |
| 381 | choices=('redhat', 'suse')) |
| 382 | + parser.add_argument('--srpm', |
| 383 | + help='Produce a source rpm', |
| 384 | + action='store_true') |
| 385 | parser.add_argument("-b", "--boot", dest="boot", |
| 386 | - help="select boot type (default: %(default)s)", |
| 387 | + help="select boot type (default: %(default)s)", |
| 388 | metavar="TYPE", default='sysvinit', |
| 389 | choices=('sysvinit', 'systemd')) |
| 390 | parser.add_argument("-v", "--verbose", dest="verbose", |
| 391 | @@ -221,57 +167,63 @@ def main(): |
| 392 | if args.verbose: |
| 393 | capture = False |
| 394 | |
| 395 | - # Clean out the root dir and make sure the dirs we want are in place |
| 396 | - root_dir = os.path.expanduser("~/rpmbuild") |
| 397 | - if os.path.isdir(root_dir): |
| 398 | - shutil.rmtree(root_dir) |
| 399 | - |
| 400 | - arc_dir = util.abs_join(root_dir, 'SOURCES') |
| 401 | - build_dirs = [root_dir, arc_dir] |
| 402 | - for dname in RPM_BUILD_SUBDIRS: |
| 403 | - build_dirs.append(util.abs_join(root_dir, dname)) |
| 404 | - build_dirs.sort() |
| 405 | - util.ensure_dirs(build_dirs) |
| 406 | - |
| 407 | - # Archive the code |
| 408 | - cmd = [util.abs_join(find_root(), 'tools', 'make-tarball')] |
| 409 | - (stdout, _stderr) = util.subp(cmd) |
| 410 | - archive_fn = stdout.strip() |
| 411 | - real_archive_fn = os.path.join(arc_dir, os.path.basename(archive_fn)) |
| 412 | - shutil.move(archive_fn, real_archive_fn) |
| 413 | - print("Archived the code in %r" % (real_archive_fn)) |
| 414 | - |
| 415 | - # Form the spec file to be used |
| 416 | - tmpl_fn = util.abs_join(find_root(), 'packages', |
| 417 | - args.distro, 'cloud-init.spec.in') |
| 418 | - contents = generate_spec_contents(args, tmpl_fn, root_dir, |
| 419 | - os.path.basename(archive_fn)) |
| 420 | - spec_fn = util.abs_join(root_dir, 'cloud-init.spec') |
| 421 | - util.write_file(spec_fn, contents) |
| 422 | - print("Created spec file at %r" % (spec_fn)) |
| 423 | - print(contents) |
| 424 | - for p in args.patches: |
| 425 | - util.copy(p, util.abs_join(arc_dir, os.path.basename(p))) |
| 426 | - |
| 427 | - # Now build it! |
| 428 | - print("Running 'rpmbuild' in %r" % (root_dir)) |
| 429 | - cmd = ['rpmbuild', '-ba', spec_fn] |
| 430 | - util.subp(cmd, capture=capture) |
| 431 | - |
| 432 | - # Copy the items built to our local dir |
| 433 | - globs = [] |
| 434 | - globs.extend(glob.glob("%s/*.rpm" % |
| 435 | - (util.abs_join(root_dir, 'RPMS', 'noarch')))) |
| 436 | - globs.extend(glob.glob("%s/*.rpm" % |
| 437 | - (util.abs_join(root_dir, 'RPMS', 'x86_64')))) |
| 438 | - globs.extend(glob.glob("%s/*.rpm" % |
| 439 | - (util.abs_join(root_dir, 'RPMS')))) |
| 440 | - globs.extend(glob.glob("%s/*.rpm" % |
| 441 | - (util.abs_join(root_dir, 'SRPMS')))) |
| 442 | - for rpm_fn in globs: |
| 443 | - tgt_fn = util.abs_join(os.getcwd(), os.path.basename(rpm_fn)) |
| 444 | - shutil.move(rpm_fn, tgt_fn) |
| 445 | - print("Wrote out %s package %r" % (args.distro, tgt_fn)) |
| 446 | + workdir = None |
| 447 | + try: |
| 448 | + workdir = tempfile.mkdtemp(prefix='rpmbuild') |
| 449 | + os.environ['HOME'] = workdir |
| 450 | + topdir = os.path.join(workdir, 'rpmbuild') |
| 451 | + build_dirs = [os.path.join(topdir, dir) |
| 452 | + for dir in RPM_BUILD_SUBDIRS] |
| 453 | + util.ensure_dirs(build_dirs) |
| 454 | + |
| 455 | + # Archive the code |
| 456 | + cmd = [util.abs_join(find_root(), 'tools', 'make-tarball')] |
| 457 | + (stdout, _stderr) = util.subp(cmd) |
| 458 | + archive_fn = stdout.strip() |
| 459 | + print "Archived source as %s" % archive_fn |
| 460 | + real_archive_fn = os.path.join(topdir, 'SOURCES', |
| 461 | + os.path.basename(archive_fn)) |
| 462 | + shutil.move(archive_fn, real_archive_fn) |
| 463 | + print("Archived the code in %r" % (real_archive_fn)) |
| 464 | + |
| 465 | + # Form the spec file to be used |
| 466 | + tmpl_fn = util.abs_join(find_root(), 'packages', |
| 467 | + args.distro, 'cloud-init.spec.in') |
| 468 | + contents = generate_spec_contents(args, tmpl_fn, topdir, |
| 469 | + os.path.basename(archive_fn)) |
| 470 | + spec_fn = util.abs_join(topdir, 'SPECS', 'cloud-init.spec') |
| 471 | + util.write_file(spec_fn, contents) |
| 472 | + print("Created spec file at %r" % (spec_fn)) |
| 473 | + for p in args.patches: |
| 474 | + util.copy(p, util.abs_join(topdir, 'SOURCES', os.path.basename(p))) |
| 475 | + |
| 476 | + # Now build it! |
| 477 | + print("Running 'rpmbuild' in %r" % (topdir)) |
| 478 | + |
| 479 | + if args.srpm: |
| 480 | + cmd = ['rpmbuild', '-bs', '--nodeps', spec_fn] |
| 481 | + else: |
| 482 | + cmd = ['rpmbuild', '-ba', spec_fn] |
| 483 | + |
| 484 | + util.subp(cmd, capture=capture) |
| 485 | + |
| 486 | + # Copy the items built to our local dir |
| 487 | + globs = [] |
| 488 | + globs.extend(glob.glob("%s/*.rpm" % |
| 489 | + (util.abs_join(topdir, 'RPMS', 'noarch')))) |
| 490 | + globs.extend(glob.glob("%s/*.rpm" % |
| 491 | + (util.abs_join(topdir, 'RPMS', 'x86_64')))) |
| 492 | + globs.extend(glob.glob("%s/*.rpm" % |
| 493 | + (util.abs_join(topdir, 'RPMS')))) |
| 494 | + globs.extend(glob.glob("%s/*.rpm" % |
| 495 | + (util.abs_join(topdir, 'SRPMS')))) |
| 496 | + for rpm_fn in globs: |
| 497 | + tgt_fn = util.abs_join(os.getcwd(), os.path.basename(rpm_fn)) |
| 498 | + shutil.move(rpm_fn, tgt_fn) |
| 499 | + print("Wrote out %s package %r" % (args.distro, tgt_fn)) |
| 500 | + finally: |
| 501 | + if workdir is not None: |
| 502 | + shutil.rmtree(workdir) |
| 503 | |
| 504 | return 0 |
| 505 | |
| 506 | diff --git a/packages/redhat/cloud-init.spec.in b/packages/redhat/cloud-init.spec.in |
| 507 | index 254d209..c30d33c 100644 |
| 508 | --- a/packages/redhat/cloud-init.spec.in |
| 509 | +++ b/packages/redhat/cloud-init.spec.in |
| 510 | @@ -1,17 +1,13 @@ |
| 511 | -## This is a cheetah template |
| 512 | +## template: cheetah |
| 513 | %{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} |
| 514 | |
| 515 | # See: http://www.zarb.org/~jasonc/macros.php |
| 516 | # Or: http://fedoraproject.org/wiki/Packaging:ScriptletSnippets |
| 517 | # Or: http://www.rpm.org/max-rpm/ch-rpm-inside.html |
| 518 | |
| 519 | -#for $d in $defines |
| 520 | -%define ${d} |
| 521 | -#end for |
| 522 | - |
| 523 | Name: cloud-init |
| 524 | Version: ${version} |
| 525 | -Release: ${release}${subrelease}%{?dist} |
| 526 | +Release: 1${subrelease}%{?dist} |
| 527 | Summary: Cloud instance init scripts |
| 528 | |
| 529 | Group: System Environment/Base |
| 530 | @@ -22,9 +18,9 @@ Source0: ${archive_name} |
| 531 | BuildArch: noarch |
| 532 | BuildRoot: %{_tmppath} |
| 533 | |
| 534 | -BuildRequires: python-devel |
| 535 | -BuildRequires: python-setuptools |
| 536 | -BuildRequires: python-cheetah |
| 537 | +BuildRequires: python-devel |
| 538 | +BuildRequires: python-setuptools |
| 539 | +BuildRequires: python-cheetah |
| 540 | |
| 541 | # System util packages needed |
| 542 | Requires: shadow-utils |
| 543 | @@ -68,7 +64,7 @@ need special scripts to run during initialization to retrieve and install |
| 544 | ssh keys and to let the user run various scripts. |
| 545 | |
| 546 | %prep |
| 547 | -%setup -q -n %{name}-%{version}~${release} |
| 548 | +%setup -q -n ${source_name} |
| 549 | |
| 550 | # Custom patches activation |
| 551 | #set $size = 0 |
| 552 | @@ -198,7 +194,3 @@ fi |
| 553 | |
| 554 | # Python code is here... |
| 555 | %{python_sitelib}/* |
| 556 | - |
| 557 | -%changelog |
| 558 | - |
| 559 | -${changelog} |
| 560 | diff --git a/packages/suse/cloud-init.spec.in b/packages/suse/cloud-init.spec.in |
| 561 | index 53e6ad1..f994a0c 100644 |
| 562 | --- a/packages/suse/cloud-init.spec.in |
| 563 | +++ b/packages/suse/cloud-init.spec.in |
| 564 | @@ -1,16 +1,12 @@ |
| 565 | -## This is a cheetah template |
| 566 | +## template: cheetah |
| 567 | |
| 568 | # See: http://www.zarb.org/~jasonc/macros.php |
| 569 | # Or: http://fedoraproject.org/wiki/Packaging:ScriptletSnippets |
| 570 | # Or: http://www.rpm.org/max-rpm/ch-rpm-inside.html |
| 571 | |
| 572 | -#for $d in $defines |
| 573 | -%define ${d} |
| 574 | -#end for |
| 575 | - |
| 576 | Name: cloud-init |
| 577 | Version: ${version} |
| 578 | -Release: ${release}${subrelease}%{?dist} |
| 579 | +Release: 1${subrelease}%{?dist} |
| 580 | Summary: Cloud instance init scripts |
| 581 | |
| 582 | Group: System/Management |
| 583 | @@ -63,7 +59,7 @@ need special scripts to run during initialization to retrieve and install |
| 584 | ssh keys and to let the user run various scripts. |
| 585 | |
| 586 | %prep |
| 587 | -%setup -q -n %{name}-%{version}~${release} |
| 588 | +%setup -q -n ${source_name} |
| 589 | |
| 590 | # Custom patches activation |
| 591 | #set $size = 0 |
| 592 | @@ -157,7 +153,3 @@ mkdir -p %{buildroot}/var/lib/cloud |
| 593 | %{python_sitelib}/* |
| 594 | |
| 595 | /var/lib/cloud |
| 596 | - |
| 597 | -%changelog |
| 598 | - |
| 599 | -${changelog} |
| 600 | diff --git a/tools/make-dist-tarball b/tools/make-dist-tarball |
| 601 | deleted file mode 100755 |
| 602 | index 5b07851..0000000 |
| 603 | --- a/tools/make-dist-tarball |
| 604 | +++ /dev/null |
| 605 | @@ -1,21 +0,0 @@ |
| 606 | -#!/bin/sh |
| 607 | - |
| 608 | -Usage() { |
| 609 | - cat <<EOF |
| 610 | -Usage: ${0##*/} version |
| 611 | - make a tarball of 'version' |
| 612 | - must be in a bzr directory, and 'version' must be a tag |
| 613 | - |
| 614 | -EOF |
| 615 | -} |
| 616 | - |
| 617 | -topdir="$PWD" |
| 618 | -tag="$1" |
| 619 | - |
| 620 | -[ -n "$tag" ] || { Usage 1>&2 ; exit 1; } |
| 621 | - |
| 622 | -out="${topdir}/cloud-init-${tag}.tar.gz" |
| 623 | - |
| 624 | -bzr export --format=tgz --root="cloud-init-$tag" \ |
| 625 | - "--revision=tag:${tag}" "$out" "$topdir" && |
| 626 | - echo "Wrote ${out}" |
| 627 | diff --git a/tools/make-tarball b/tools/make-tarball |
| 628 | index b703915..25d6f93 100755 |
| 629 | --- a/tools/make-tarball |
| 630 | +++ b/tools/make-tarball |
| 631 | @@ -1,39 +1,31 @@ |
| 632 | #!/bin/sh |
| 633 | set -e |
| 634 | |
| 635 | -find_root() { |
| 636 | - local topd |
| 637 | - if [ -z "${CLOUD_INIT_TOP_D}" ]; then |
| 638 | - topd=$(cd "$(dirname "${0}")" && cd .. && pwd) |
| 639 | - else |
| 640 | - topd=$(cd "${CLOUD_INIT_TOP_D}" && pwd) |
| 641 | - fi |
| 642 | - [ $? -eq 0 -a -f "${topd}/setup.py" ] || return |
| 643 | - ROOT_DIR="$topd" |
| 644 | -} |
| 645 | - |
| 646 | -if ! find_root; then |
| 647 | - echo "Unable to locate 'setup.py' file that should" \ |
| 648 | - "exist in the cloud-init root directory." 1>&2 |
| 649 | - exit 1; |
| 650 | -fi |
| 651 | - |
| 652 | -REVNO=$(bzr revno "$ROOT_DIR") |
| 653 | - |
| 654 | -if [ ! -z "$1" ]; then |
| 655 | - ARCHIVE_FN="$1" |
| 656 | +rev=${1:-HEAD} |
| 657 | +if [ "$rev" = HEAD ]; then |
| 658 | + revname=$(git describe --tags) |
| 659 | else |
| 660 | - VERSION=$("$ROOT_DIR/tools/read-version") |
| 661 | - ARCHIVE_FN="$PWD/cloud-init-$VERSION~bzr$REVNO.tar.gz" |
| 662 | + revname="$rev" |
| 663 | fi |
| 664 | |
| 665 | -export_uncommitted="" |
| 666 | -if [ "${UNCOMMITTED:-0}" != "0" ]; then |
| 667 | - export_uncommitted="--uncommitted" |
| 668 | +archive_base="cloud-init-$revname" |
| 669 | + |
| 670 | +# when building an archiving from HEAD, ensure that there aren't any |
| 671 | +# uncomitted changes in the working directory (because these would not |
| 672 | +# end up in the archive). |
| 673 | +if [ "$rev" = HEAD ] && ! git diff-index --quiet HEAD --; then |
| 674 | + if [ -z "$SKIP_UNCOMITTED_CHANGES_CHECK" ]; then |
| 675 | + echo "ERROR: There are uncommitted changes in your working directory." >&2 |
| 676 | + exit 1 |
| 677 | + else |
| 678 | + echo "WARNING: There are uncommitted changes in your working directory." >&2 |
| 679 | + echo " This changes will not be included in the archive." >&2 |
| 680 | + fi |
| 681 | fi |
| 682 | |
| 683 | -bzr export ${export_uncommitted} \ |
| 684 | - --format=tgz --root="cloud-init-$VERSION~bzr$REVNO" \ |
| 685 | - "--revision=${REVNO}" "${ARCHIVE_FN}" "$ROOT_DIR" |
| 686 | +git archive \ |
| 687 | + --format=tar \ |
| 688 | + --prefix "$archive_base/" $rev > "$archive_base.tar" |
| 689 | +gzip -f9 ${archive_base}.tar |
| 690 | |
| 691 | -echo "$ARCHIVE_FN" |
| 692 | +echo ${archive_base}.tar.gz |
| 693 | diff --git a/tools/read-dependencies b/tools/read-dependencies |
| 694 | index 6a6f3e1..c8a5d23 100755 |
| 695 | --- a/tools/read-dependencies |
| 696 | +++ b/tools/read-dependencies |
| 697 | @@ -1,13 +1,21 @@ |
| 698 | #!/usr/bin/env python |
| 699 | |
| 700 | +# You might be tempted to rewrite this as a shell script, but you |
| 701 | +# would be surprised to discover that things like 'egrep' or 'sed' may |
| 702 | +# differ between Linux and *BSD. |
| 703 | + |
| 704 | import os |
| 705 | import re |
| 706 | import sys |
| 707 | +import subprocess |
| 708 | |
| 709 | if 'CLOUD_INIT_TOP_D' in os.environ: |
| 710 | topd = os.path.realpath(os.environ.get('CLOUD_INIT_TOP_D')) |
| 711 | else: |
| 712 | - topd = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) |
| 713 | + p = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], |
| 714 | + stdout=subprocess.PIPE) |
| 715 | + out, err = p.communicate() |
| 716 | + topd = out.splitlines()[0] |
| 717 | |
| 718 | for fname in ("setup.py", "requirements.txt"): |
| 719 | if not os.path.isfile(os.path.join(topd, fname)): |
| 720 | @@ -16,14 +24,21 @@ for fname in ("setup.py", "requirements.txt"): |
| 721 | sys.exit(1) |
| 722 | |
| 723 | if len(sys.argv) > 1: |
| 724 | - reqfile = sys.argv[1] |
| 725 | + reqfile = sys.argv[1] |
| 726 | else: |
| 727 | - reqfile = "requirements.txt" |
| 728 | - |
| 729 | + reqfile = "requirements.txt" |
| 730 | + |
| 731 | with open(os.path.join(topd, reqfile), "r") as fp: |
| 732 | for line in fp: |
| 733 | - if not line.strip() or line.startswith("#"): |
| 734 | + line = line.strip() |
| 735 | + if not line or line.startswith("#"): |
| 736 | continue |
| 737 | - sys.stdout.write(re.split("[>=.<]*", line)[0].strip() + "\n") |
| 738 | + |
| 739 | + # remove pip-style markers |
| 740 | + dep = line.split(';')[0] |
| 741 | + |
| 742 | + # remove version requirements |
| 743 | + dep = re.split("[>=.<]*", dep)[0].strip() |
| 744 | + print dep |
| 745 | |
| 746 | sys.exit(0) |

