2005-05-02 19:39:12 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
import shutil
|
2012-06-17 16:30:17 +02:00
|
|
|
import subprocess
|
2005-05-02 19:39:12 +02:00
|
|
|
|
2012-06-09 20:38:50 +02:00
|
|
|
from optparse import OptionParser
|
|
|
|
|
2005-05-02 19:39:12 +02:00
|
|
|
def firstLines(filename, n):
|
|
|
|
fd = file(filename)
|
|
|
|
lines = []
|
|
|
|
while n:
|
|
|
|
n -= 1
|
|
|
|
lines.append(fd.readline().rstrip('\r\n'))
|
2012-06-17 16:30:17 +02:00
|
|
|
fd.close()
|
2005-05-02 19:39:12 +02:00
|
|
|
return lines
|
|
|
|
|
|
|
|
def firstLine(filename):
|
|
|
|
return firstLines(filename, 1)[0]
|
|
|
|
|
|
|
|
def error(s):
|
|
|
|
sys.stderr.write(s+'\n')
|
|
|
|
sys.exit(-1)
|
|
|
|
|
2012-06-17 16:30:17 +02:00
|
|
|
def system(sh, errmsg=None, **kwargs):
|
2005-05-02 19:39:12 +02:00
|
|
|
if errmsg is None:
|
2015-08-10 20:24:11 +02:00
|
|
|
if isinstance(sh, minisix.string_types):
|
2012-06-17 16:30:17 +02:00
|
|
|
errmsg = repr(sh)
|
|
|
|
else:
|
|
|
|
errmsg = repr(' '.join(sh))
|
|
|
|
ret = subprocess.call(sh, **kwargs)
|
2005-05-02 19:39:12 +02:00
|
|
|
if ret:
|
|
|
|
error(errmsg + ' (error code: %s)' % ret)
|
|
|
|
|
2009-03-16 22:33:34 +01:00
|
|
|
def checkGitRepo():
|
2009-05-18 09:02:52 +02:00
|
|
|
system('test "$(git rev-parse --is-inside-work-tree)" = "true"',
|
2012-06-17 16:30:17 +02:00
|
|
|
'Must be run from a git checkout.',
|
|
|
|
shell=True)
|
2009-03-16 22:33:34 +01:00
|
|
|
system('test "$(git rev-parse --show-cdup >/dev/null)" = ""',
|
2012-06-17 16:30:17 +02:00
|
|
|
'Must be run from the top-level directory of the git checkout.',
|
|
|
|
shell=True)
|
2009-03-16 22:33:34 +01:00
|
|
|
system('git rev-parse --verify HEAD >/dev/null '
|
|
|
|
'&& git update-index --refresh'
|
|
|
|
'&& git diff-files --quiet'
|
2009-05-18 09:02:52 +02:00
|
|
|
'&& git diff-index --cached --quiet HEAD --',
|
2012-06-17 16:30:17 +02:00
|
|
|
'Your tree is unclean. Can\'t run from here.',
|
|
|
|
shell=True)
|
2009-02-27 21:06:04 +01:00
|
|
|
|
2005-05-02 19:39:12 +02:00
|
|
|
if __name__ == '__main__':
|
2012-06-09 20:38:50 +02:00
|
|
|
usage = 'usage: %prog [options] <username> <version>'
|
|
|
|
parser = OptionParser(usage=usage)
|
2012-06-17 15:36:29 +02:00
|
|
|
parser.set_defaults(sign=False, verbose=False, branch='master')
|
2012-06-09 20:38:50 +02:00
|
|
|
parser.add_option('-s', '--sign', action='store_true', dest='sign',
|
|
|
|
help='Pass on -s to relevant git commands')
|
|
|
|
parser.add_option('-n', '--dry-run', action='store_true', dest='dry_run',
|
|
|
|
help='Build the release, but do not push to the git '
|
|
|
|
'remote or upload the release archives.')
|
2012-06-17 15:36:29 +02:00
|
|
|
parser.add_option('-b', '--branch', metavar='BRANCH', dest='branch',
|
|
|
|
help='Branch to use for the release. Default: %default')
|
2012-06-09 20:38:50 +02:00
|
|
|
(options, args) = parser.parse_args()
|
2009-03-16 22:33:34 +01:00
|
|
|
|
2012-06-09 20:38:50 +02:00
|
|
|
if len(args) != 2:
|
|
|
|
parser.error('Both username and version must be specified')
|
2005-05-02 19:39:12 +02:00
|
|
|
|
2012-06-09 20:38:50 +02:00
|
|
|
(u, v) = args
|
2009-05-25 19:32:02 +02:00
|
|
|
if not re.match(r'^\d+\.\d+\.\d+(\.\d+)?\w*$', v):
|
2012-06-09 20:38:50 +02:00
|
|
|
parser.error('Invalid version string: '
|
|
|
|
'must be of the form MAJOR.MINOR.PATCHLEVEL')
|
|
|
|
|
|
|
|
checkGitRepo()
|
|
|
|
|
|
|
|
sign = options.sign
|
|
|
|
dryrun = options.dry_run
|
2012-06-17 15:36:29 +02:00
|
|
|
branch = options.branch
|
2005-05-02 19:39:12 +02:00
|
|
|
|
|
|
|
if os.path.exists('supybot'):
|
|
|
|
error('I need to make the directory "supybot" but it already exists.'
|
2009-02-27 21:06:04 +01:00
|
|
|
' Change to an appropriate directory or remove the supybot '
|
2005-05-02 19:39:12 +02:00
|
|
|
'directory to continue.')
|
2009-02-27 21:06:04 +01:00
|
|
|
print 'Checking out fresh tree from git.'
|
2012-06-17 16:34:23 +02:00
|
|
|
repo = 'git+ssh://%s@supybot.git.sourceforge.net/gitroot/supybot/supybot' % u
|
|
|
|
system(['git', 'clone', '-b', branch, repo])
|
2005-05-02 19:39:12 +02:00
|
|
|
os.chdir('supybot')
|
|
|
|
|
|
|
|
print 'Checking RELNOTES version line.'
|
|
|
|
if firstLine('RELNOTES') != 'Version %s' % v:
|
|
|
|
error('Invalid first line in RELNOTES.')
|
|
|
|
|
|
|
|
print 'Checking ChangeLog version line.'
|
|
|
|
(first, _, third) = firstLines('ChangeLog', 3)
|
2009-02-27 21:06:04 +01:00
|
|
|
if not re.match(r'^20\d\d-\d{2}-\d{2}\s+\w+.*<\S+@\S+>$', first):
|
2005-05-02 19:39:12 +02:00
|
|
|
error('Invalid first line in ChangeLog.')
|
|
|
|
if not re.match(r'^\t\* Version %s!$' % v, third):
|
|
|
|
error('Invalid third line in ChangeLog.')
|
|
|
|
|
|
|
|
print 'Updating version in version files.'
|
2010-08-20 16:31:05 +02:00
|
|
|
versionFiles = ['src/version.py']
|
2005-05-02 19:39:12 +02:00
|
|
|
for fn in versionFiles:
|
2012-06-17 16:30:17 +02:00
|
|
|
sh = ['perl', '-pi', '-e', 's/^version\s*=.*/version = \'%s\'/' % v, fn]
|
2005-05-02 19:39:12 +02:00
|
|
|
system(sh, 'Error changing version in %s' % fn)
|
2012-06-17 16:30:17 +02:00
|
|
|
commit = ['git', 'commit']
|
|
|
|
if sign:
|
|
|
|
commit.append('-s')
|
|
|
|
system(commit + ['-m', 'Updated to %s.' % v] + versionFiles)
|
2005-05-02 19:39:12 +02:00
|
|
|
|
|
|
|
print 'Tagging release.'
|
2012-06-17 16:30:17 +02:00
|
|
|
tag = ['git', 'tag']
|
|
|
|
if sign:
|
|
|
|
tag.append('-s')
|
|
|
|
system(tag + ['-m', "Release %s" % v, 'v%s' % v])
|
2009-03-16 22:33:34 +01:00
|
|
|
|
2009-03-17 04:44:14 +01:00
|
|
|
print 'Committing %s+git to version files.' % v
|
|
|
|
for fn in versionFiles:
|
2012-06-17 16:30:17 +02:00
|
|
|
system(['perl', '-pi', '-e',
|
|
|
|
's/^version\s*=.*/version = \'%s+git\'/' % v, fn],
|
|
|
|
'Error changing version in %s' % fn)
|
|
|
|
system(commit + ['-m', 'Updated to %s+git.' % v] + versionFiles)
|
2009-03-17 04:44:14 +01:00
|
|
|
|
2009-05-18 08:55:23 +02:00
|
|
|
if not dryrun:
|
|
|
|
print 'Pushing commits and tag.'
|
2012-06-17 16:30:17 +02:00
|
|
|
system(['git', 'push', 'origin', branch])
|
|
|
|
system(['git', 'push', '--tags'])
|
2005-05-02 19:39:12 +02:00
|
|
|
|
2012-06-17 16:30:17 +02:00
|
|
|
archive = ['git', 'archive', '--prefix=Supybot-%s/' % v]
|
2005-05-02 19:39:12 +02:00
|
|
|
print 'Creating tarball (gzip).'
|
2012-06-17 16:30:17 +02:00
|
|
|
system(archive + ['-o', '../Supybot-%s.tar.gz' % v,
|
|
|
|
'--format=tgz', 'v%s' % v])
|
|
|
|
|
|
|
|
system(['git', 'config', 'tar.bz2.command', 'bzip2 -c'])
|
|
|
|
|
2005-05-02 19:39:12 +02:00
|
|
|
print 'Creating tarball (bzip2).'
|
2012-06-17 16:30:17 +02:00
|
|
|
system(archive + ['-o', '../Supybot-%s.tar.bz2' % v,
|
|
|
|
'--format=bz2', 'v%s' % v])
|
|
|
|
|
2005-05-02 19:39:12 +02:00
|
|
|
print 'Creating zip.'
|
2012-06-17 16:30:17 +02:00
|
|
|
system(archive + ['-o', '../Supybot-%s.zip' % v,
|
|
|
|
'--format=zip', 'v%s' % v])
|
2009-03-17 04:44:14 +01:00
|
|
|
|
|
|
|
os.chdir('..')
|
|
|
|
shutil.rmtree('supybot')
|
2005-05-02 19:39:12 +02:00
|
|
|
|
2009-05-18 08:55:23 +02:00
|
|
|
if not dryrun:
|
|
|
|
print 'Uploading package files to upload.sf.net.'
|
|
|
|
system('scp Supybot-%s.tar.gz Supybot-%s.tar.bz2 Supybot-%s.zip '
|
|
|
|
'%s@frs.sourceforge.net:uploads' % (v, v, v, u))
|
2009-05-25 19:50:05 +02:00
|
|
|
os.unlink('Supybot-%s.tar.gz' % v)
|
|
|
|
os.unlink('Supybot-%s.tar.bz2' % v)
|
|
|
|
os.unlink('Supybot-%s.zip' % v)
|
2009-02-27 21:06:04 +01:00
|
|
|
|
2009-05-18 08:55:23 +02:00
|
|
|
print 'Copying new version.txt over to project webserver.'
|
|
|
|
system('echo %s > version.txt' % v)
|
2009-05-18 09:56:05 +02:00
|
|
|
system('scp version.txt %s@web.sf.net:/home/groups/s/su/supybot/htdocs'
|
|
|
|
%u)
|
2009-05-25 19:50:05 +02:00
|
|
|
os.unlink('version.txt')
|
2005-05-02 19:39:12 +02:00
|
|
|
|
|
|
|
# print 'Generating documentation.'
|
|
|
|
# # docFiles is in the format {directory: files}
|
|
|
|
# docFiles = {'.': ('README', 'INSTALL', 'ChangeLog'),
|
|
|
|
# 'docs': ('config.html', 'CAPABILITIES', 'commands.html',
|
|
|
|
# 'CONFIGURATION', 'FAQ', 'GETTING_STARTED',
|
|
|
|
# 'INTERFACES', 'OVERVIEW', 'PLUGIN-EXAMPLE',
|
|
|
|
# 'plugins', 'plugins.html', 'STYLE'),
|
|
|
|
# }
|
|
|
|
# system('python scripts/supybot-plugin-doc')
|
|
|
|
# pwd = os.getcwd()
|
|
|
|
# os.chmod('docs/plugins', 0775)
|
|
|
|
# sh = 'tar rf %s/docs.tar %%s' % pwd
|
|
|
|
# for (dir, L) in docFiles.iteritems():
|
|
|
|
# os.chdir(os.path.join(pwd, dir))
|
|
|
|
# system(sh % ' '.join(L))
|
|
|
|
# os.chdir(pwd)
|
|
|
|
# system('bzip2 docs.tar')
|
|
|
|
#
|
|
|
|
# print 'Uploading documentation to webspace.'
|
|
|
|
# system('scp docs.tar.bz2 %s@supybot.sf.net:/home/groups/s/su/supybot'
|
|
|
|
# '/htdocs/docs/.' % u)
|
|
|
|
# system('ssh %s@supybot.sf.net "cd /home/groups/s/su/supybot/htdocs/docs; '
|
|
|
|
# 'tar jxf docs.tar.bz2"' % u)
|
|
|
|
#
|
|
|
|
# print 'Cleaning up generated documentation.'
|
|
|
|
# shutil.rmtree('docs/plugins')
|
|
|
|
# configFiles = ('docs/config.html', 'docs/plugins.html',
|
|
|
|
# 'docs/commands.html', 'docs.tar.bz2', 'test-conf',
|
|
|
|
# 'test-data', 'test-logs', 'tmp')
|
|
|
|
# for fn in configFiles:
|
|
|
|
# os.remove(fn)
|