# Copyright 2010 Baptiste Lepilleur and The JsonCpp Authors# Distributed under MIT license, or public domain if desired and# recognized in your jurisdiction.# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE"""Tag the sandbox for release, make source and doc tarballs.Requires Python 2.6Example of invocation (use to test the script):python makerelease.py --platform=msvc6,msvc71,msvc80,msvc90,mingw -ublep 0.6.0 0.7.0-devWhen testing this script:python makerelease.py --force --retag --platform=msvc6,msvc71,msvc80,mingw -ublep test-0.6.0 test-0.6.1-devExample of invocation when doing a release:python makerelease.py 0.5.0 0.6.0-devNote: This was for Subversion. Now that we are in GitHub, we do notneed to build versioned tarballs anymore, so makerelease.py is defunct."""from __future__ import print_functionimport os.pathimport subprocessimport sysimport doxybuildimport subprocessimport xml.etree.ElementTree as ElementTreeimport shutilimport urllib2import tempfileimport osimport timefrom devtools import antglob, fixeol, tarballimport amalgamateSVN_ROOT = 'https://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/'SVN_TAG_ROOT = SVN_ROOT + 'tags/jsoncpp'SCONS_LOCAL_URL = 'http://sourceforge.net/projects/scons/files/scons-local/1.2.0/scons-local-1.2.0.tar.gz/download'SOURCEFORGE_PROJECT = 'jsoncpp'def set_version(version):with open('version','wb') as f:f.write(version.strip())def rmdir_if_exist(dir_path):if os.path.isdir(dir_path):shutil.rmtree(dir_path)class SVNError(Exception):passdef svn_command(command, *args):cmd = ['svn', '--non-interactive', command] + list(args)print('Running:', ' '.join(cmd))process = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)stdout = process.communicate()[0]if process.returncode:error = SVNError('SVN command failed:\n' + stdout)error.returncode = process.returncoderaise errorreturn stdoutdef check_no_pending_commit():"""Checks that there is no pending commit in the sandbox."""stdout = svn_command('status', '--xml')etree = ElementTree.fromstring(stdout)msg = []for entry in etree.getiterator('entry'):path = entry.get('path')status = entry.find('wc-status').get('item')if status != 'unversioned' and path != 'version':msg.append('File "%s" has pending change (status="%s")' % (path, status))if msg:msg.insert(0, 'Pending change to commit found in sandbox. Commit them first!')return '\n'.join(msg)def svn_join_url(base_url, suffix):if not base_url.endswith('/'):base_url += '/'if suffix.startswith('/'):suffix = suffix[1:]return base_url + suffixdef svn_check_if_tag_exist(tag_url):"""Checks if a tag exist.Returns: True if the tag exist, False otherwise."""try:list_stdout = svn_command('list', tag_url)except SVNError as e:if e.returncode != 1 or not str(e).find('tag_url'):raise e# otherwise ignore error, meaning tag does not existreturn Falsereturn Truedef svn_commit(message):"""Commit the sandbox, providing the specified comment."""svn_command('ci', '-m', message)def svn_tag_sandbox(tag_url, message):"""Makes a tag based on the sandbox revisions."""svn_command('copy', '-m', message, '.', tag_url)def svn_remove_tag(tag_url, message):"""Removes an existing tag."""svn_command('delete', '-m', message, tag_url)def svn_export(tag_url, export_dir):"""Exports the tag_url revision to export_dir.Target directory, including its parent is created if it does not exist.If the directory export_dir exist, it is deleted before export proceed."""rmdir_if_exist(export_dir)svn_command('export', tag_url, export_dir)def fix_sources_eol(dist_dir):"""Set file EOL for tarball distribution."""print('Preparing exported source file EOL for distribution...')prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist'win_sources = antglob.glob(dist_dir,includes = '**/*.sln **/*.vcproj',prune_dirs = prune_dirs)unix_sources = antglob.glob(dist_dir,includes = '''**/*.h **/*.cpp **/*.inl **/*.txt **/*.dox **/*.py **/*.html **/*.insconscript *.json *.expected AUTHORS LICENSE''',excludes = antglob.default_excludes + 'scons.py sconsign.py scons-*',prune_dirs = prune_dirs)for path in win_sources:fixeol.fix_source_eol(path, is_dry_run = False, verbose = True, eol = '\r\n')for path in unix_sources:fixeol.fix_source_eol(path, is_dry_run = False, verbose = True, eol = '\n')def download(url, target_path):"""Download file represented by url to target_path."""f = urllib2.urlopen(url)try:data = f.read()finally:f.close()fout = open(target_path, 'wb')try:fout.write(data)finally:fout.close()def check_compile(distcheck_top_dir, platform):cmd = [sys.executable, 'scons.py', 'platform=%s' % platform, 'check']print('Running:', ' '.join(cmd))log_path = os.path.join(distcheck_top_dir, 'build-%s.log' % platform)flog = open(log_path, 'wb')try:process = subprocess.Popen(cmd,stdout=flog,stderr=subprocess.STDOUT,cwd=distcheck_top_dir)stdout = process.communicate()[0]status = (process.returncode == 0)finally:flog.close()return (status, log_path)def write_tempfile(content, **kwargs):fd, path = tempfile.mkstemp(**kwargs)f = os.fdopen(fd, 'wt')try:f.write(content)finally:f.close()return pathclass SFTPError(Exception):passdef run_sftp_batch(userhost, sftp, batch, retry=0):path = write_tempfile(batch, suffix='.sftp', text=True)# psftp -agent -C blep,jsoncpp@web.sourceforge.net -batch -b batch.sftp -bccmd = [sftp, '-agent', '-C', '-batch', '-b', path, '-bc', userhost]error = Nonefor retry_index in range(0, max(1,retry)):heading = retry_index == 0 and 'Running:' or 'Retrying:'print(heading, ' '.join(cmd))process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)stdout = process.communicate()[0]if process.returncode != 0:error = SFTPError('SFTP batch failed:\n' + stdout)else:breakif error:raise errorreturn stdoutdef sourceforge_web_synchro(sourceforge_project, doc_dir,user=None, sftp='sftp'):"""Notes: does not synchronize sub-directory of doc-dir."""userhost = '%s,%s@web.sourceforge.net' % (user, sourceforge_project)stdout = run_sftp_batch(userhost, sftp, """cd htdocsdirexit""")existing_paths = set()collect = 0for line in stdout.split('\n'):line = line.strip()if not collect and line.endswith('> dir'):collect = Trueelif collect and line.endswith('> exit'):breakelif collect == 1:collect = 2elif collect == 2:path = line.strip().split()[-1:]if path and path[0] not in ('.', '..'):existing_paths.add(path[0])upload_paths = set([os.path.basename(p) for p in antglob.glob(doc_dir)])paths_to_remove = existing_paths - upload_pathsif paths_to_remove:print('Removing the following file from web:')print('\n'.join(paths_to_remove))stdout = run_sftp_batch(userhost, sftp, """cd htdocsrm %sexit""" % ' '.join(paths_to_remove))print('Uploading %d files:' % len(upload_paths))batch_size = 10upload_paths = list(upload_paths)start_time = time.time()for index in range(0,len(upload_paths),batch_size):paths = upload_paths[index:index+batch_size]file_per_sec = (time.time() - start_time) / (index+1)remaining_files = len(upload_paths) - indexremaining_sec = file_per_sec * remaining_filesprint('%d/%d, ETA=%.1fs' % (index+1, len(upload_paths), remaining_sec))run_sftp_batch(userhost, sftp, """cd htdocslcd %smput %sexit""" % (doc_dir, ' '.join(paths)), retry=3)def sourceforge_release_tarball(sourceforge_project, paths, user=None, sftp='sftp'):userhost = '%s,%s@frs.sourceforge.net' % (user, sourceforge_project)run_sftp_batch(userhost, sftp, """mput %sexit""" % (' '.join(paths),))def main():usage = """%prog release_version next_dev_versionUpdate 'version' file to release_version and commit.Generates the document tarball.Tags the sandbox revision with release_version.Update 'version' file to next_dev_version and commit.Performs an svn export of tag release version, and build a source tarball.Must be started in the project top directory.Warning: --force should only be used when developing/testing the release script."""from optparse import OptionParserparser = OptionParser(usage=usage)parser.allow_interspersed_args = Falseparser.add_option('--dot', dest="dot_path", action='store', default=doxybuild.find_program('dot'),help="""Path to GraphViz dot tool. Must be full qualified path. [Default: %default]""")parser.add_option('--doxygen', dest="doxygen_path", action='store', default=doxybuild.find_program('doxygen'),help="""Path to Doxygen tool. [Default: %default]""")parser.add_option('--force', dest="ignore_pending_commit", action='store_true', default=False,help="""Ignore pending commit. [Default: %default]""")parser.add_option('--retag', dest="retag_release", action='store_true', default=False,help="""Overwrite release existing tag if it exist. [Default: %default]""")parser.add_option('-p', '--platforms', dest="platforms", action='store', default='',help="""Comma separated list of platform passed to scons for build check.""")parser.add_option('--no-test', dest="no_test", action='store_true', default=False,help="""Skips build check.""")parser.add_option('--no-web', dest="no_web", action='store_true', default=False,help="""Do not update web site.""")parser.add_option('-u', '--upload-user', dest="user", action='store',help="""Sourceforge user for SFTP documentation upload.""")parser.add_option('--sftp', dest='sftp', action='store', default=doxybuild.find_program('psftp', 'sftp'),help="""Path of the SFTP compatible binary used to upload the documentation.""")parser.enable_interspersed_args()options, args = parser.parse_args()if len(args) != 2:parser.error('release_version missing on command-line.')release_version = args[0]next_version = args[1]if not options.platforms and not options.no_test:parser.error('You must specify either --platform or --no-test option.')if options.ignore_pending_commit:msg = ''else:msg = check_no_pending_commit()if not msg:print('Setting version to', release_version)set_version(release_version)svn_commit('Release ' + release_version)tag_url = svn_join_url(SVN_TAG_ROOT, release_version)if svn_check_if_tag_exist(tag_url):if options.retag_release:svn_remove_tag(tag_url, 'Overwriting previous tag')else:print('Aborting, tag %s already exist. Use --retag to overwrite it!' % tag_url)sys.exit(1)svn_tag_sandbox(tag_url, 'Release ' + release_version)print('Generated doxygen document...')## doc_dirname = r'jsoncpp-api-html-0.5.0'## doc_tarball_path = r'e:\prg\vc\Lib\jsoncpp-trunk\dist\jsoncpp-api-html-0.5.0.tar.gz'doc_tarball_path, doc_dirname = doxybuild.build_doc(options, make_release=True)doc_distcheck_dir = 'dist/doccheck'tarball.decompress(doc_tarball_path, doc_distcheck_dir)doc_distcheck_top_dir = os.path.join(doc_distcheck_dir, doc_dirname)export_dir = 'dist/export'svn_export(tag_url, export_dir)fix_sources_eol(export_dir)source_dir = 'jsoncpp-src-' + release_versionsource_tarball_path = 'dist/%s.tar.gz' % source_dirprint('Generating source tarball to', source_tarball_path)tarball.make_tarball(source_tarball_path, [export_dir], export_dir, prefix_dir=source_dir)amalgamation_tarball_path = 'dist/%s-amalgamation.tar.gz' % source_dirprint('Generating amalgamation source tarball to', amalgamation_tarball_path)amalgamation_dir = 'dist/amalgamation'amalgamate.amalgamate_source(export_dir, '%s/jsoncpp.cpp' % amalgamation_dir, 'json/json.h')amalgamation_source_dir = 'jsoncpp-src-amalgamation' + release_versiontarball.make_tarball(amalgamation_tarball_path, [amalgamation_dir],amalgamation_dir, prefix_dir=amalgamation_source_dir)# Decompress source tarball, download and install scons-localdistcheck_dir = 'dist/distcheck'distcheck_top_dir = distcheck_dir + '/' + source_dirprint('Decompressing source tarball to', distcheck_dir)rmdir_if_exist(distcheck_dir)tarball.decompress(source_tarball_path, distcheck_dir)scons_local_path = 'dist/scons-local.tar.gz'print('Downloading scons-local to', scons_local_path)download(SCONS_LOCAL_URL, scons_local_path)print('Decompressing scons-local to', distcheck_top_dir)tarball.decompress(scons_local_path, distcheck_top_dir)# Run compilationprint('Compiling decompressed tarball')all_build_status = Truefor platform in options.platforms.split(','):print('Testing platform:', platform)build_status, log_path = check_compile(distcheck_top_dir, platform)print('see build log:', log_path)print(build_status and '=> ok' or '=> FAILED')all_build_status = all_build_status and build_statusif not build_status:print('Testing failed on at least one platform, aborting...')svn_remove_tag(tag_url, 'Removing tag due to failed testing')sys.exit(1)if options.user:if not options.no_web:print('Uploading documentation using user', options.user)sourceforge_web_synchro(SOURCEFORGE_PROJECT, doc_distcheck_top_dir, user=options.user, sftp=options.sftp)print('Completed documentation upload')print('Uploading source and documentation tarballs for release using user', options.user)sourceforge_release_tarball(SOURCEFORGE_PROJECT,[source_tarball_path, doc_tarball_path],user=options.user, sftp=options.sftp)print('Source and doc release tarballs uploaded')else:print('No upload user specified. Web site and download tarball were not uploaded.')print('Tarball can be found at:', doc_tarball_path)# Set next version number and commitset_version(next_version)svn_commit('Released ' + release_version)else:sys.stderr.write(msg + '\n')if __name__ == '__main__':main()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。