Changed license for _mailfilterrc from Public Domain to GPLv2+
[be.git] / release.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2009-2010 W. Trevor King <wking@drexel.edu>
4 #
5 # This file is part of Bugs Everywhere.
6 #
7 # Bugs Everywhere is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by the
9 # Free Software Foundation, either version 2 of the License, or (at your
10 # option) any later version.
11 #
12 # Bugs Everywhere is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Bugs Everywhere.  If not, see <http://www.gnu.org/licenses/>.
19
20 import os
21 import os.path
22 import shutil
23 import string
24 import sys
25
26 from libbe.subproc import Pipe, invoke
27 from update_copyright import update_authors, update_files
28
29 def validate_tag(tag):
30     """
31     >>> validate_tag('1.0.0')
32     >>> validate_tag('A.B.C-r7')
33     >>> validate_tag('A.B.C r7')
34     Traceback (most recent call last):
35       ...
36     Exception: Invalid character ' ' in tag 'A.B.C r7'
37     >>> validate_tag('"')
38     Traceback (most recent call last):
39       ...
40     Exception: Invalid character '"' in tag '"'
41     >>> validate_tag("'")
42     Traceback (most recent call last):
43       ...
44     Exception: Invalid character ''' in tag '''
45     """
46     for char in tag:
47         if char in string.digits:
48             continue
49         elif char in string.letters:
50             continue
51         elif char in ['.','-']:
52             continue
53         raise Exception("Invalid character '%s' in tag '%s'" % (char, tag))
54
55 def bzr_pending_changes():
56     """Use `bzr diff`s exit status to detect change:
57     1 - changed
58     2 - unrepresentable changes
59     3 - error
60     0 - no change
61     """
62     p = Pipe([['bzr', 'diff']])
63     if p.status == 0:
64         return False
65     elif p.status in [1,2]:
66         return True
67     raise Exception("Error in bzr diff %d\n%s" % (p.status, p.stderrs[-1]))
68
69 def set_release_version(tag):
70     print "set libbe.version._VERSION = '%s'" % tag
71     p = Pipe([['sed', '-i', "s/^# *_VERSION *=.*/_VERSION = '%s'/" % tag,
72                os.path.join('libbe', 'version.py')]])
73     assert p.status == 0, p.statuses
74
75 def bzr_commit(commit_message):
76     print 'commit current status:', commit_message
77     p = Pipe([['bzr', 'commit', '-m', commit_message]])
78     assert p.status == 0, p.statuses
79
80 def bzr_tag(tag):
81     print 'tag current revision', tag
82     p = Pipe([['bzr', 'tag', tag]])
83     assert p.status == 0, p.statuses
84
85 def bzr_export(target_dir):
86     print 'export current revision to', target_dir
87     p = Pipe([['bzr', 'export', target_dir]])
88     assert p.status == 0, p.statuses
89
90 def make_version():
91     print 'generate libbe/_version.py'
92     p = Pipe([['make', os.path.join('libbe', '_version.py')]])
93     assert p.status == 0, p.statuses
94
95 def make_changelog(filename, tag):
96     print 'generate ChangeLog file', filename, 'up to tag', tag
97     p = invoke(['bzr', 'log', '--gnu-changelog', '-n1', '-r',
98                 '..tag:%s' % tag], stdout=file(filename, 'w'))
99     status = p.wait()
100     assert status == 0, status
101
102 def set_vcs_name(filename, vcs_name='None'):
103     """Exported directory is not a bzr repository, so set vcs_name to
104     something that will work.
105       vcs_name: new_vcs_name
106     """
107     print 'set vcs_name in', filename, 'to', vcs_name
108     p = Pipe([['sed', '-i', "s/^vcs_name:.*/vcs_name: %s/" % vcs_name,
109                filename]])
110     assert p.status == 0, p.statuses
111
112 def create_tarball(tag):
113     release_name='be-%s' % tag
114     export_dir = release_name
115     bzr_export(export_dir)
116     make_version()
117     print 'copy libbe/_version.py to %s/libbe/_version.py' % export_dir
118     shutil.copy(os.path.join('libbe', '_version.py'),
119                 os.path.join(export_dir, 'libbe', '_version.py'))
120     make_changelog(os.path.join(export_dir, 'ChangeLog'), tag)
121     set_vcs_name(os.path.join(export_dir, '.be', 'settings'))
122     tarball_file = '%s.tar.gz' % release_name
123     print 'create tarball', tarball_file
124     p = Pipe([['tar', '-czf', tarball_file, export_dir]])
125     assert p.status == 0, p.statuses
126     print 'remove', export_dir
127     shutil.rmtree(export_dir)
128
129 def test():
130     import doctest
131     doctest.testmod() 
132
133 if __name__ == '__main__':
134     import optparse
135     usage = """%prog [options] TAG
136
137 Create a bzr tag and a release tarball from the current revision.
138 For example
139   %prog 1.0.0
140 """
141     p = optparse.OptionParser(usage)
142     p.add_option('--test', dest='test', default=False,
143                  action='store_true', help='Run internal tests and exit')
144     options,args = p.parse_args()
145
146     if options.test == True:
147         test()
148         sys.exit(0)
149
150     assert len(args) == 1, '%d (!= 1) arguments: %s' % (len(args), args)
151     tag = args[0]
152     validate_tag(tag)
153
154     if bzr_pending_changes() == True:
155         print "Handle pending changes before releasing."
156         sys.exit(1)
157     set_release_version(tag)
158     update_authors()
159     update_files()
160     bzr_commit("Bumped to version %s" % tag)
161     bzr_tag(tag)
162     create_tarball(tag)