""" Create a Windows installer EXE. usage: create_win_installer [] where is an optional revision number - if not supplied then update through svn and use latest revision This program expects to be run from the root directory of the ANUGA branch being released. This script works only on Windows! """ import sys import os import getopt import tempfile import shutil import dirs_to_distribute from anuga.utilities.data_audit_wrapper import IP_verified from anuga.utilities.system_tools import get_user_name, get_host_name from anuga.abstract_2d_finite_volumes.util import get_revision_number from anuga.abstract_2d_finite_volumes.util import store_version_info from anuga.config import major_revision # name of 'home' directory containing releases ANUGA_RELEASE_DIR = 'anuga_releases' # prefix for temporary directory TEMP_DIR_PREFIX = 'anuga_release_' # path to and required contents of documentation directory DOC_PATH = os.path.join('anuga_core', 'documentation', 'user_manual') DOC_FILES = ['anuga_user_manual.pdf', 'anuga_installation_guide.pdf', 'anuga_whats_new.pdf'] # path to NSIS install directory NSIS_PATH = r'C:\Program Files\NSIS' NSIS_EXE = os.path.join(NSIS_PATH, 'makensis.exe') # the name of the subversion commandline client SVN_CLIENT = 'svn' def abort(msg, stop=True): """Some sort of error, report and abort.""" xlog('*' * 80) xlog(msg) xlog('*' * 80) if stop: sys.exit(10) def check_doc(temp_dir, release_name): """Make sure all the documentation is present. temp_dir released code working directory release_name ANUGA release name Returns if everything OK. """ bad = False for file in DOC_FILES: doc_file = os.path.join(DOC_PATH, file) if not os.path.isfile(doc_file): xlog('Documentation file %s is missing.' % doc_file) bad = True if bad and not Force: abort('Sorry, documentation files are missing.\n' 'You must release on Linux before Windows.') def check_IP(temp_dir, verbose=False): """Check IP statements in release directories.""" if not IP_verified(temp_dir, verbose=verbose): if not Force: abort('Files have not been verified for IP.\n' 'Each data file must have a licence file with it.') def compile_nsi_file(): """Compile the installer NSI file.""" # figure out where the *.nsi file actually is nsi_file = os.path.join(BranchDir, 'installation_files', 'windows', 'installer.nsi') do_cmd('"%s" /V2 %s' % (NSIS_EXE, nsi_file)) def copy_release_directories(revision, temp_dir): """Get release dirs (correct version) into release directory.""" for src in dirs_to_distribute.dirmap: dst = os.path.join(temp_dir, dirs_to_distribute.dirmap[src]) do_cmd('%s export -r %s --quiet %s %s' % (SVN_CLIENT, revision, src, dst)) def do_cmd(cmd, ignore_errors=False): """Execute a command, optionally ignore errors.""" try: xlog(cmd) os.system(cmd) except: if not ignore_errors: raise def get_directories(rel_name): """Create release and temporary directories, return paths. rel_name the ANUGA release name """ # create the release directory rel_area = os.path.join('~', ANUGA_RELEASE_DIR) rel_area = os.path.expanduser(rel_area) rel_dir = os.path.join(rel_area, rel_name) if os.path.isdir(rel_dir): if Force: os.removedirs(rel_dir) else: abort("Sorry, release directory '%s' already exists.\n" "Please delete that directory first." % rel_dir) os.makedirs(rel_dir) # create a temporary scratch directory temp_dir = tempfile.mkdtemp(suffix='', prefix=TEMP_DIR_PREFIX) return (rel_dir, temp_dir) def get_release_name(): """Get release information and create release name. Get release numbers from the current directory. Returns a string which is of the form 'anuga-X.Y.Z' where X is the major release number, Y is the minor and Z is the bug number. """ curr_dir = os.getcwd() curr_dir = os.path.basename(curr_dir) split_dir = curr_dir.split('_') if len(split_dir) < 2: abort('You must run this script in an ANUGA branch directory.') if split_dir[0] != 'anuga': abort('You must run this script in an ANUGA branch directory.') major = split_dir[1] if len(split_dir) < 3: minor = '0' else: minor = split_dir[2] if len(split_dir) < 4: bug = '0' else: bug = split_dir[3] return 'anuga-%s.%s.%s' % (major, minor, bug) def get_svn_revision(): """Get the current revision number from svn. This uses the CollabNet subversion client. """ try: fid = os.popen('%s info' % SVN_CLIENT) except: abort('Subversion commandline client not found') lines = fid.readlines() fid.close() for l in lines: l = l.strip() if l.startswith('Last Changed Rev:'): (_, revision) = l.split(':', 1) try: revision = int(revision) except ValueError: abort('"svn info" did not return expected line: ' + l) return revision abort('"svn info" did not return expected line "Last Changed Rev:"') def make_installer(revision): """Make a windows installer. revision the revision number (string) to release (may be None, meaning 'use latest') """ global BranchDir # get the current branch directory path BranchDir = os.getcwd() # if revision is None (not supplied) do update and get latest revision if revision is None: do_cmd('%s up' % SVN_CLIENT) revision = get_svn_revision() # get release name from current directory release_name = get_release_name() # get working directory paths (directories have been created) (release_dir, temp_dir) = get_directories(release_name) # get the ANUGA directories that are being released copy_release_directories(revision, temp_dir) # check IP data for release directories check_IP(temp_dir, verbose=True) # generate the LaTeX documentation check_doc(temp_dir, release_name) # create ZIP release file, put into release dir make_zip_file(temp_dir, release_name, release_dir) # compile Windows *.nsi file # creates EXE in \installation_files\windows # check we have required files/directories # remove all generated *.exe files anuga_dir = os.path.join(BranchDir, 'installation_files', 'windows', 'files', release_name) if not os.path.isdir(anuga_dir): abort("Sorry, directory %s doesn't exist.\n" "You need to run the Linux create distribution first." % anuga_dir) src = os.path.join(BranchDir, 'installation_files', 'windows', '*.exe') do_cmd('del /Q %s' % src) compile_nsi_file() # copy the create EXE to the release directory do_cmd('move /Y %s %s' % (src, release_dir)) # clean up shutil.rmtree(temp_dir) def make_zip_file(temp_dir, release_name, release_dir): """Make a ZIP file, copy to release directory. temp_dir directory where we copied release files release_name the release name release_dir destination for the ZIP file """ # create .tgz file in temp_dir def usage(msg=None): """Give befuddled user some help.""" if msg: print(msg) print('usage: create_win_installer []\n' 'where is an optional revision number to release.') def xlog(msg): """Print and log a message.""" print(msg) # uncomment this to get file logging ## log(msg) if __name__ == '__main__': global Force if sys.platform != 'win32': msg = ('This script is not written for Linux. ' 'Please run it on a Windows platform.') raise Exception(msg) argv = sys.argv[1:] try: opts, args = getopt.getopt(argv, 'hf', ['help', 'force']) except getopt.error, msg: usage() sys.exit(10) Force = False for (opt, param) in opts: if opt in ['-h', '--help']: usage() sys.exit(0) elif opt in ['-f', '--force']: Force = True if len(args) > 1: usage() sys.exit(10) revision = None if len(args) == 1: try: revision = int(args[0]) except ValueError: usage() sys.exit(10) make_installer(revision)