Sam Clegg | 6386061 | 2015-04-09 18:01:33 -0700 | [diff] [blame^] | 1 | # Copyright 2010 Baptiste Lepilleur |
| 2 | # Distributed under MIT license, or public domain if desired and |
| 3 | # recognized in your jurisdiction. |
| 4 | # See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE |
| 5 | |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 6 | """Tag the sandbox for release, make source and doc tarballs. |
| 7 | |
| 8 | Requires Python 2.6 |
| 9 | |
| 10 | Example of invocation (use to test the script): |
Baptiste Lepilleur | e1b2645 | 2010-03-13 10:59:50 +0000 | [diff] [blame] | 11 | python makerelease.py --platform=msvc6,msvc71,msvc80,msvc90,mingw -ublep 0.6.0 0.7.0-dev |
Baptiste Lepilleur | cd6cb5d | 2010-03-13 07:59:07 +0000 | [diff] [blame] | 12 | |
| 13 | When testing this script: |
Baptiste Lepilleur | bafb43c | 2011-05-01 20:36:55 +0000 | [diff] [blame] | 14 | python makerelease.py --force --retag --platform=msvc6,msvc71,msvc80,mingw -ublep test-0.6.0 test-0.6.1-dev |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 15 | |
| 16 | Example of invocation when doing a release: |
| 17 | python makerelease.py 0.5.0 0.6.0-dev |
Christopher Dunn | b789497 | 2014-09-10 18:01:10 -0700 | [diff] [blame] | 18 | |
| 19 | Note: This was for Subversion. Now that we are in GitHub, we do not |
| 20 | need to build versioned tarballs anymore, so makerelease.py is defunct. |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 21 | """ |
Sam Clegg | 6386061 | 2015-04-09 18:01:33 -0700 | [diff] [blame^] | 22 | |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 23 | from __future__ import print_function |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 24 | import os.path |
| 25 | import subprocess |
| 26 | import sys |
| 27 | import doxybuild |
| 28 | import subprocess |
| 29 | import xml.etree.ElementTree as ElementTree |
Baptiste Lepilleur | 7c171ee | 2010-02-23 08:44:52 +0000 | [diff] [blame] | 30 | import shutil |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 31 | import urllib2 |
| 32 | import tempfile |
| 33 | import os |
| 34 | import time |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 35 | from devtools import antglob, fixeol, tarball |
Baptiste Lepilleur | eadc478 | 2011-05-02 21:09:30 +0000 | [diff] [blame] | 36 | import amalgamate |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 37 | |
| 38 | SVN_ROOT = 'https://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/' |
| 39 | SVN_TAG_ROOT = SVN_ROOT + 'tags/jsoncpp' |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 40 | SCONS_LOCAL_URL = 'http://sourceforge.net/projects/scons/files/scons-local/1.2.0/scons-local-1.2.0.tar.gz/download' |
| 41 | SOURCEFORGE_PROJECT = 'jsoncpp' |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 42 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 43 | def set_version(version): |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 44 | with open('version','wb') as f: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 45 | f.write(version.strip()) |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 46 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 47 | def rmdir_if_exist(dir_path): |
| 48 | if os.path.isdir(dir_path): |
| 49 | shutil.rmtree(dir_path) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 50 | |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 51 | class SVNError(Exception): |
| 52 | pass |
| 53 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 54 | def svn_command(command, *args): |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 55 | cmd = ['svn', '--non-interactive', command] + list(args) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 56 | print('Running:', ' '.join(cmd)) |
| 57 | process = subprocess.Popen(cmd, |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 58 | stdout=subprocess.PIPE, |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 59 | stderr=subprocess.STDOUT) |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 60 | stdout = process.communicate()[0] |
| 61 | if process.returncode: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 62 | error = SVNError('SVN command failed:\n' + stdout) |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 63 | error.returncode = process.returncode |
| 64 | raise error |
| 65 | return stdout |
| 66 | |
| 67 | def check_no_pending_commit(): |
| 68 | """Checks that there is no pending commit in the sandbox.""" |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 69 | stdout = svn_command('status', '--xml') |
| 70 | etree = ElementTree.fromstring(stdout) |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 71 | msg = [] |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 72 | for entry in etree.getiterator('entry'): |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 73 | path = entry.get('path') |
| 74 | status = entry.find('wc-status').get('item') |
Baptiste Lepilleur | e6a7741 | 2010-03-11 21:02:26 +0000 | [diff] [blame] | 75 | if status != 'unversioned' and path != 'version': |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 76 | msg.append('File "%s" has pending change (status="%s")' % (path, status)) |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 77 | if msg: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 78 | msg.insert(0, 'Pending change to commit found in sandbox. Commit them first!') |
| 79 | return '\n'.join(msg) |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 80 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 81 | def svn_join_url(base_url, suffix): |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 82 | if not base_url.endswith('/'): |
| 83 | base_url += '/' |
| 84 | if suffix.startswith('/'): |
| 85 | suffix = suffix[1:] |
| 86 | return base_url + suffix |
| 87 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 88 | def svn_check_if_tag_exist(tag_url): |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 89 | """Checks if a tag exist. |
| 90 | Returns: True if the tag exist, False otherwise. |
| 91 | """ |
| 92 | try: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 93 | list_stdout = svn_command('list', tag_url) |
Christopher Dunn | 9aa6144 | 2014-11-19 23:10:02 -0600 | [diff] [blame] | 94 | except SVNError as e: |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 95 | if e.returncode != 1 or not str(e).find('tag_url'): |
| 96 | raise e |
| 97 | # otherwise ignore error, meaning tag does not exist |
| 98 | return False |
| 99 | return True |
| 100 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 101 | def svn_commit(message): |
Baptiste Lepilleur | e6a7741 | 2010-03-11 21:02:26 +0000 | [diff] [blame] | 102 | """Commit the sandbox, providing the specified comment. |
| 103 | """ |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 104 | svn_command('ci', '-m', message) |
Baptiste Lepilleur | e6a7741 | 2010-03-11 21:02:26 +0000 | [diff] [blame] | 105 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 106 | def svn_tag_sandbox(tag_url, message): |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 107 | """Makes a tag based on the sandbox revisions. |
| 108 | """ |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 109 | svn_command('copy', '-m', message, '.', tag_url) |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 110 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 111 | def svn_remove_tag(tag_url, message): |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 112 | """Removes an existing tag. |
| 113 | """ |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 114 | svn_command('delete', '-m', message, tag_url) |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 115 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 116 | def svn_export(tag_url, export_dir): |
Baptiste Lepilleur | 7c171ee | 2010-02-23 08:44:52 +0000 | [diff] [blame] | 117 | """Exports the tag_url revision to export_dir. |
| 118 | Target directory, including its parent is created if it does not exist. |
| 119 | If the directory export_dir exist, it is deleted before export proceed. |
| 120 | """ |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 121 | rmdir_if_exist(export_dir) |
| 122 | svn_command('export', tag_url, export_dir) |
Baptiste Lepilleur | 7c171ee | 2010-02-23 08:44:52 +0000 | [diff] [blame] | 123 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 124 | def fix_sources_eol(dist_dir): |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 125 | """Set file EOL for tarball distribution. |
| 126 | """ |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 127 | print('Preparing exported source file EOL for distribution...') |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 128 | prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist' |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 129 | win_sources = antglob.glob(dist_dir, |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 130 | includes = '**/*.sln **/*.vcproj', |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 131 | prune_dirs = prune_dirs) |
| 132 | unix_sources = antglob.glob(dist_dir, |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 133 | includes = '''**/*.h **/*.cpp **/*.inl **/*.txt **/*.dox **/*.py **/*.html **/*.in |
| 134 | sconscript *.json *.expected AUTHORS LICENSE''', |
| 135 | excludes = antglob.default_excludes + 'scons.py sconsign.py scons-*', |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 136 | prune_dirs = prune_dirs) |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 137 | for path in win_sources: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 138 | fixeol.fix_source_eol(path, is_dry_run = False, verbose = True, eol = '\r\n') |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 139 | for path in unix_sources: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 140 | fixeol.fix_source_eol(path, is_dry_run = False, verbose = True, eol = '\n') |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 141 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 142 | def download(url, target_path): |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 143 | """Download file represented by url to target_path. |
| 144 | """ |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 145 | f = urllib2.urlopen(url) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 146 | try: |
| 147 | data = f.read() |
| 148 | finally: |
| 149 | f.close() |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 150 | fout = open(target_path, 'wb') |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 151 | try: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 152 | fout.write(data) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 153 | finally: |
| 154 | fout.close() |
| 155 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 156 | def check_compile(distcheck_top_dir, platform): |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 157 | cmd = [sys.executable, 'scons.py', 'platform=%s' % platform, 'check'] |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 158 | print('Running:', ' '.join(cmd)) |
| 159 | log_path = os.path.join(distcheck_top_dir, 'build-%s.log' % platform) |
| 160 | flog = open(log_path, 'wb') |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 161 | try: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 162 | process = subprocess.Popen(cmd, |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 163 | stdout=flog, |
| 164 | stderr=subprocess.STDOUT, |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 165 | cwd=distcheck_top_dir) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 166 | stdout = process.communicate()[0] |
| 167 | status = (process.returncode == 0) |
| 168 | finally: |
| 169 | flog.close() |
| 170 | return (status, log_path) |
| 171 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 172 | def write_tempfile(content, **kwargs): |
| 173 | fd, path = tempfile.mkstemp(**kwargs) |
| 174 | f = os.fdopen(fd, 'wt') |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 175 | try: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 176 | f.write(content) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 177 | finally: |
| 178 | f.close() |
| 179 | return path |
| 180 | |
| 181 | class SFTPError(Exception): |
| 182 | pass |
| 183 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 184 | def run_sftp_batch(userhost, sftp, batch, retry=0): |
| 185 | path = write_tempfile(batch, suffix='.sftp', text=True) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 186 | # psftp -agent -C blep,jsoncpp@web.sourceforge.net -batch -b batch.sftp -bc |
| 187 | cmd = [sftp, '-agent', '-C', '-batch', '-b', path, '-bc', userhost] |
| 188 | error = None |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 189 | for retry_index in range(0, max(1,retry)): |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 190 | heading = retry_index == 0 and 'Running:' or 'Retrying:' |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 191 | print(heading, ' '.join(cmd)) |
| 192 | process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 193 | stdout = process.communicate()[0] |
| 194 | if process.returncode != 0: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 195 | error = SFTPError('SFTP batch failed:\n' + stdout) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 196 | else: |
| 197 | break |
| 198 | if error: |
| 199 | raise error |
| 200 | return stdout |
| 201 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 202 | def sourceforge_web_synchro(sourceforge_project, doc_dir, |
| 203 | user=None, sftp='sftp'): |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 204 | """Notes: does not synchronize sub-directory of doc-dir. |
| 205 | """ |
| 206 | userhost = '%s,%s@web.sourceforge.net' % (user, sourceforge_project) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 207 | stdout = run_sftp_batch(userhost, sftp, """ |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 208 | cd htdocs |
| 209 | dir |
| 210 | exit |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 211 | """) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 212 | existing_paths = set() |
| 213 | collect = 0 |
| 214 | for line in stdout.split('\n'): |
| 215 | line = line.strip() |
| 216 | if not collect and line.endswith('> dir'): |
| 217 | collect = True |
| 218 | elif collect and line.endswith('> exit'): |
| 219 | break |
| 220 | elif collect == 1: |
| 221 | collect = 2 |
| 222 | elif collect == 2: |
| 223 | path = line.strip().split()[-1:] |
| 224 | if path and path[0] not in ('.', '..'): |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 225 | existing_paths.add(path[0]) |
| 226 | upload_paths = set([os.path.basename(p) for p in antglob.glob(doc_dir)]) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 227 | paths_to_remove = existing_paths - upload_paths |
| 228 | if paths_to_remove: |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 229 | print('Removing the following file from web:') |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 230 | print('\n'.join(paths_to_remove)) |
| 231 | stdout = run_sftp_batch(userhost, sftp, """cd htdocs |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 232 | rm %s |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 233 | exit""" % ' '.join(paths_to_remove)) |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 234 | print('Uploading %d files:' % len(upload_paths)) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 235 | batch_size = 10 |
| 236 | upload_paths = list(upload_paths) |
| 237 | start_time = time.time() |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 238 | for index in range(0,len(upload_paths),batch_size): |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 239 | paths = upload_paths[index:index+batch_size] |
| 240 | file_per_sec = (time.time() - start_time) / (index+1) |
| 241 | remaining_files = len(upload_paths) - index |
| 242 | remaining_sec = file_per_sec * remaining_files |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 243 | print('%d/%d, ETA=%.1fs' % (index+1, len(upload_paths), remaining_sec)) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 244 | run_sftp_batch(userhost, sftp, """cd htdocs |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 245 | lcd %s |
| 246 | mput %s |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 247 | exit""" % (doc_dir, ' '.join(paths)), retry=3) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 248 | |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 249 | def sourceforge_release_tarball(sourceforge_project, paths, user=None, sftp='sftp'): |
Baptiste Lepilleur | d89d796 | 2010-02-25 08:30:09 +0000 | [diff] [blame] | 250 | userhost = '%s,%s@frs.sourceforge.net' % (user, sourceforge_project) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 251 | run_sftp_batch(userhost, sftp, """ |
Baptiste Lepilleur | d89d796 | 2010-02-25 08:30:09 +0000 | [diff] [blame] | 252 | mput %s |
| 253 | exit |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 254 | """ % (' '.join(paths),)) |
Baptiste Lepilleur | d89d796 | 2010-02-25 08:30:09 +0000 | [diff] [blame] | 255 | |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 256 | |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 257 | def main(): |
| 258 | usage = """%prog release_version next_dev_version |
| 259 | Update 'version' file to release_version and commit. |
| 260 | Generates the document tarball. |
| 261 | Tags the sandbox revision with release_version. |
| 262 | Update 'version' file to next_dev_version and commit. |
| 263 | |
| 264 | Performs an svn export of tag release version, and build a source tarball. |
| 265 | |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 266 | Must be started in the project top directory. |
| 267 | |
| 268 | Warning: --force should only be used when developping/testing the release script. |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 269 | """ |
| 270 | from optparse import OptionParser |
| 271 | parser = OptionParser(usage=usage) |
| 272 | parser.allow_interspersed_args = False |
| 273 | parser.add_option('--dot', dest="dot_path", action='store', default=doxybuild.find_program('dot'), |
| 274 | help="""Path to GraphViz dot tool. Must be full qualified path. [Default: %default]""") |
| 275 | parser.add_option('--doxygen', dest="doxygen_path", action='store', default=doxybuild.find_program('doxygen'), |
| 276 | help="""Path to Doxygen tool. [Default: %default]""") |
| 277 | parser.add_option('--force', dest="ignore_pending_commit", action='store_true', default=False, |
| 278 | help="""Ignore pending commit. [Default: %default]""") |
| 279 | parser.add_option('--retag', dest="retag_release", action='store_true', default=False, |
| 280 | help="""Overwrite release existing tag if it exist. [Default: %default]""") |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 281 | parser.add_option('-p', '--platforms', dest="platforms", action='store', default='', |
| 282 | help="""Comma separated list of platform passed to scons for build check.""") |
Baptiste Lepilleur | d89d796 | 2010-02-25 08:30:09 +0000 | [diff] [blame] | 283 | parser.add_option('--no-test', dest="no_test", action='store_true', default=False, |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 284 | help="""Skips build check.""") |
Baptiste Lepilleur | d89d796 | 2010-02-25 08:30:09 +0000 | [diff] [blame] | 285 | parser.add_option('--no-web', dest="no_web", action='store_true', default=False, |
| 286 | help="""Do not update web site.""") |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 287 | parser.add_option('-u', '--upload-user', dest="user", action='store', |
| 288 | help="""Sourceforge user for SFTP documentation upload.""") |
| 289 | parser.add_option('--sftp', dest='sftp', action='store', default=doxybuild.find_program('psftp', 'sftp'), |
| 290 | help="""Path of the SFTP compatible binary used to upload the documentation.""") |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 291 | parser.enable_interspersed_args() |
| 292 | options, args = parser.parse_args() |
| 293 | |
Baptiste Lepilleur | e6a7741 | 2010-03-11 21:02:26 +0000 | [diff] [blame] | 294 | if len(args) != 2: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 295 | parser.error('release_version missing on command-line.') |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 296 | release_version = args[0] |
Baptiste Lepilleur | e6a7741 | 2010-03-11 21:02:26 +0000 | [diff] [blame] | 297 | next_version = args[1] |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 298 | |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 299 | if not options.platforms and not options.no_test: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 300 | parser.error('You must specify either --platform or --no-test option.') |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 301 | |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 302 | if options.ignore_pending_commit: |
| 303 | msg = '' |
| 304 | else: |
| 305 | msg = check_no_pending_commit() |
| 306 | if not msg: |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 307 | print('Setting version to', release_version) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 308 | set_version(release_version) |
| 309 | svn_commit('Release ' + release_version) |
| 310 | tag_url = svn_join_url(SVN_TAG_ROOT, release_version) |
| 311 | if svn_check_if_tag_exist(tag_url): |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 312 | if options.retag_release: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 313 | svn_remove_tag(tag_url, 'Overwriting previous tag') |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 314 | else: |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 315 | print('Aborting, tag %s already exist. Use --retag to overwrite it!' % tag_url) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 316 | sys.exit(1) |
| 317 | svn_tag_sandbox(tag_url, 'Release ' + release_version) |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 318 | |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 319 | print('Generated doxygen document...') |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 320 | ## doc_dirname = r'jsoncpp-api-html-0.5.0' |
| 321 | ## doc_tarball_path = r'e:\prg\vc\Lib\jsoncpp-trunk\dist\jsoncpp-api-html-0.5.0.tar.gz' |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 322 | doc_tarball_path, doc_dirname = doxybuild.build_doc(options, make_release=True) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 323 | doc_distcheck_dir = 'dist/doccheck' |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 324 | tarball.decompress(doc_tarball_path, doc_distcheck_dir) |
| 325 | doc_distcheck_top_dir = os.path.join(doc_distcheck_dir, doc_dirname) |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 326 | |
| 327 | export_dir = 'dist/export' |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 328 | svn_export(tag_url, export_dir) |
| 329 | fix_sources_eol(export_dir) |
Baptiste Lepilleur | e94d2f4 | 2010-02-23 21:00:30 +0000 | [diff] [blame] | 330 | |
| 331 | source_dir = 'jsoncpp-src-' + release_version |
| 332 | source_tarball_path = 'dist/%s.tar.gz' % source_dir |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 333 | print('Generating source tarball to', source_tarball_path) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 334 | tarball.make_tarball(source_tarball_path, [export_dir], export_dir, prefix_dir=source_dir) |
Baptiste Lepilleur | 35bdc07 | 2010-02-24 08:05:41 +0000 | [diff] [blame] | 335 | |
Baptiste Lepilleur | eadc478 | 2011-05-02 21:09:30 +0000 | [diff] [blame] | 336 | amalgamation_tarball_path = 'dist/%s-amalgamation.tar.gz' % source_dir |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 337 | print('Generating amalgamation source tarball to', amalgamation_tarball_path) |
Baptiste Lepilleur | eadc478 | 2011-05-02 21:09:30 +0000 | [diff] [blame] | 338 | amalgamation_dir = 'dist/amalgamation' |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 339 | amalgamate.amalgamate_source(export_dir, '%s/jsoncpp.cpp' % amalgamation_dir, 'json/json.h') |
Baptiste Lepilleur | eadc478 | 2011-05-02 21:09:30 +0000 | [diff] [blame] | 340 | amalgamation_source_dir = 'jsoncpp-src-amalgamation' + release_version |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 341 | tarball.make_tarball(amalgamation_tarball_path, [amalgamation_dir], |
| 342 | amalgamation_dir, prefix_dir=amalgamation_source_dir) |
Baptiste Lepilleur | bafb43c | 2011-05-01 20:36:55 +0000 | [diff] [blame] | 343 | |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 344 | # Decompress source tarball, download and install scons-local |
Baptiste Lepilleur | 35bdc07 | 2010-02-24 08:05:41 +0000 | [diff] [blame] | 345 | distcheck_dir = 'dist/distcheck' |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 346 | distcheck_top_dir = distcheck_dir + '/' + source_dir |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 347 | print('Decompressing source tarball to', distcheck_dir) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 348 | rmdir_if_exist(distcheck_dir) |
| 349 | tarball.decompress(source_tarball_path, distcheck_dir) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 350 | scons_local_path = 'dist/scons-local.tar.gz' |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 351 | print('Downloading scons-local to', scons_local_path) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 352 | download(SCONS_LOCAL_URL, scons_local_path) |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 353 | print('Decompressing scons-local to', distcheck_top_dir) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 354 | tarball.decompress(scons_local_path, distcheck_top_dir) |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 355 | |
| 356 | # Run compilation |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 357 | print('Compiling decompressed tarball') |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 358 | all_build_status = True |
| 359 | for platform in options.platforms.split(','): |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 360 | print('Testing platform:', platform) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 361 | build_status, log_path = check_compile(distcheck_top_dir, platform) |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 362 | print('see build log:', log_path) |
| 363 | print(build_status and '=> ok' or '=> FAILED') |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 364 | all_build_status = all_build_status and build_status |
| 365 | if not build_status: |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 366 | print('Testing failed on at least one platform, aborting...') |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 367 | svn_remove_tag(tag_url, 'Removing tag due to failed testing') |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 368 | sys.exit(1) |
| 369 | if options.user: |
Baptiste Lepilleur | d89d796 | 2010-02-25 08:30:09 +0000 | [diff] [blame] | 370 | if not options.no_web: |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 371 | print('Uploading documentation using user', options.user) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 372 | sourceforge_web_synchro(SOURCEFORGE_PROJECT, doc_distcheck_top_dir, user=options.user, sftp=options.sftp) |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 373 | print('Completed documentation upload') |
| 374 | print('Uploading source and documentation tarballs for release using user', options.user) |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 375 | sourceforge_release_tarball(SOURCEFORGE_PROJECT, |
Baptiste Lepilleur | d89d796 | 2010-02-25 08:30:09 +0000 | [diff] [blame] | 376 | [source_tarball_path, doc_tarball_path], |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 377 | user=options.user, sftp=options.sftp) |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 378 | print('Source and doc release tarballs uploaded') |
Baptiste Lepilleur | 64ba062 | 2010-02-24 23:08:47 +0000 | [diff] [blame] | 379 | else: |
Christopher Dunn | bd1e895 | 2014-11-19 23:30:47 -0600 | [diff] [blame] | 380 | print('No upload user specified. Web site and download tarbal were not uploaded.') |
| 381 | print('Tarball can be found at:', doc_tarball_path) |
Baptiste Lepilleur | e6a7741 | 2010-03-11 21:02:26 +0000 | [diff] [blame] | 382 | |
| 383 | # Set next version number and commit |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 384 | set_version(next_version) |
| 385 | svn_commit('Released ' + release_version) |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 386 | else: |
Christopher Dunn | 494950a | 2015-01-24 15:29:52 -0600 | [diff] [blame] | 387 | sys.stderr.write(msg + '\n') |
Baptiste Lepilleur | 1f4847c | 2010-02-23 07:57:38 +0000 | [diff] [blame] | 388 | |
| 389 | if __name__ == '__main__': |
| 390 | main() |