#!/usr/bin/python
#
-# Copyright (C) 2009-2010 W. Trevor King <wking@drexel.edu>
+# Copyright (C) 2009-2011 Chris Ball <cjb@laptop.org>
+# W. Trevor King <wking@drexel.edu>
#
# This file is part of Bugs Everywhere.
#
import sys
from libbe.util.subproc import Pipe, invoke
-from libbe.util.encoding import set_file_contents
from update_copyright import update_authors, update_files
def pending_changes():
"""Use `git diff`s output to detect change.
"""
- p = Pipe([['git', 'diff', 'HEAD']])
- assert p.status == 0, p.statuses
- if len(p.stdout) == 0:
+ status,stdout,stderr = invoke(['git', 'diff', 'HEAD'])
+ if len(stdout) == 0:
return False
return True
def set_release_version(tag):
print "set libbe.version._VERSION = '%s'" % tag
- p = Pipe([['sed', '-i', "s/^# *_VERSION *=.*/_VERSION = '%s'/" % tag,
- os.path.join('libbe', 'version.py')]])
- assert p.status == 0, p.statuses
+ invoke(['sed', '-i', "s/^# *_VERSION *=.*/_VERSION = '%s'/" % tag,
+ os.path.join('libbe', 'version.py')])
-def remove_makefile_libbe_version_dependencies():
- print "set Makefile LIBBE_VERSION :="
- p = Pipe([['sed', '-i', "s/^LIBBE_VERSION *:=.*/LIBBE_VERSION :=/",
- 'Makefile']])
- assert p.status == 0, p.statuses
+def remove_makefile_libbe_version_dependencies(filename):
+ print "set %s LIBBE_VERSION :=" % filename
+ invoke(['sed', '-i', "s/^LIBBE_VERSION *:=.*/LIBBE_VERSION :=/",
+ filename])
def commit(commit_message):
print 'commit current status:', commit_message
- p = Pipe([['git', 'commit', '-m', commit_message]])
- assert p.status == 0, p.statuses
+ invoke(['git', 'commit', '-a', '-m', commit_message])
def tag(tag):
print 'tag current revision', tag
- p = Pipe([['git', 'tag', tag]])
- assert p.status == 0, p.statuses
+ invoke(['git', 'tag', tag])
def export(target_dir):
+ if not target_dir.endswith(os.path.sep):
+ target_dir += os.path.sep
print 'export current revision to', target_dir
p = Pipe([['git', 'archive', '--prefix', target_dir, 'HEAD'],
['tar', '-xv']])
def make_version():
print 'generate libbe/_version.py'
- p = Pipe([['make', os.path.join('libbe', '_version.py')]])
- assert p.status == 0, p.statuses
+ invoke(['make', os.path.join('libbe', '_version.py')])
def make_changelog(filename, tag):
"""Generate a ChangeLog from the git history.
- Based on
- http://stackoverflow.com/questions/2976665/git-changelog-day-by-day
+ Not the most ChangeLog-esque format, but iterating through commits
+ by hand is just too slow.
"""
print 'generate ChangeLog file', filename, 'up to tag', tag
- p = invoke(['git', 'log', '--no-merges', '--format="%cd"', '--date=short',
- '%s..%s' % (INITIAL_COMMIT, tag)])
- days = sorted(set(p.stdout.split('\n')), reverse=True)
- log = []
- next = None
- for day in days:
- args = ['git', 'log', '--no-merges', '--format=" * s"', '--since', day]
- if next != None:
- args.extend(['--until', next])
- p = invoke(args)
- log.extend(['', day, p.stdout])
- next = day
- set_file_contents(filename, '\n'.join(log), encoding='utf-8')
-
-def set_vcs_name(filename, vcs_name='None'):
+ invoke(['git', 'log', '--no-merges',
+ '%s..%s' % (INITIAL_COMMIT, tag)],
+ stdout=open(filename, 'w')),
+
+def set_vcs_name(be_dir, vcs_name='None'):
"""Exported directory is not a git repository, so set vcs_name to
something that will work.
vcs_name: new_vcs_name
"""
- print 'set vcs_name in', filename, 'to', vcs_name
- p = Pipe([['sed', '-i', "s/^vcs_name:.*/vcs_name: %s/" % vcs_name,
- filename]])
- assert p.status == 0, p.statuses
+ for directory in os.listdir(be_dir):
+ if not os.path.isdir(os.path.join(be_dir, directory)):
+ continue
+ filename = os.path.join(be_dir, directory, 'settings')
+ if os.path.exists(filename):
+ print 'set vcs_name in', filename, 'to', vcs_name
+ invoke(['sed', '-i', "s/^vcs_name:.*/vcs_name: %s/" % vcs_name,
+ filename])
+
+def make_id_cache():
+ """Generate .be/id-cache so users won't need to.
+ """
+ invoke(['./be', 'list'])
def create_tarball(tag):
release_name='be-%s' % tag
export_dir = release_name
export(export_dir)
make_version()
+ remove_makefile_libbe_version_dependencies(
+ os.path.join(export_dir, 'Makefile'))
print 'copy libbe/_version.py to %s/libbe/_version.py' % export_dir
shutil.copy(os.path.join('libbe', '_version.py'),
os.path.join(export_dir, 'libbe', '_version.py'))
make_changelog(os.path.join(export_dir, 'ChangeLog'), tag)
- set_vcs_name(os.path.join(export_dir, '.be', 'settings'))
+ make_id_cache()
+ print 'copy .be/id-cache to %s/.be/id-cache' % export_dir
+ shutil.copy(os.path.join('.be', 'id-cache'),
+ os.path.join(export_dir, '.be', 'id-cache'))
+ set_vcs_name(os.path.join(export_dir, '.be'))
+ os.remove(os.path.join(export_dir, 'update_copyright.py'))
tarball_file = '%s.tar.gz' % release_name
print 'create tarball', tarball_file
- p = Pipe([['tar', '-czf', tarball_file, export_dir]])
- assert p.status == 0, p.statuses
+ invoke(['tar', '-czf', tarball_file, export_dir])
print 'remove', export_dir
shutil.rmtree(export_dir)
For example
%prog 1.0.0
-You may wish to test this out in a dummy branch first to make sure it
-works as expected to avoid the tedium of unwinding the version-bump
-commit if it fails.
+If you don't like what got committed, you can undo the release with
+ $ git tag -d 1.0.0
+ $ git reset --hard HEAD^
"""
p = optparse.OptionParser(usage)
p.add_option('--test', dest='test', default=False,
sys.exit(0)
assert len(args) == 1, '%d (!= 1) arguments: %s' % (len(args), args)
- tag = args[0]
- validate_tag(tag)
+ _tag = args[0]
+ validate_tag(_tag)
if pending_changes() == True:
print "Handle pending changes before releasing."
sys.exit(1)
- set_release_version(tag)
+ set_release_version(_tag)
+ print "Update copyright information..."
update_authors()
update_files()
- commit("Bumped to version %s" % tag)
- tag(tag)
- create_tarball(tag)
+ commit("Bumped to version %s" % _tag)
+ tag(_tag)
+ create_tarball(_tag)