source: trunk/create_win_installer.py @ 7900

Last change on this file since 7900 was 7900, checked in by wilsonr, 13 years ago

Initial version.

File size: 8.7 KB
Line 
1"""
2Create a Windows installer EXE.
3
4usage: create_win_installer  [<revision>]
5
6where <revision> is an optional revision number - if not supplied then
7                 update through svn and use latest revision
8                 
9This program expects to be run from the root directory of the ANUGA branch
10being released.
11
12This script works only on Windows!
13"""
14
15
16import sys
17import os
18import getopt
19import tempfile
20import shutil
21
22import dirs_to_distribute
23from anuga.utilities.data_audit_wrapper import IP_verified
24
25from anuga.utilities.system_tools import get_user_name, get_host_name
26from anuga.abstract_2d_finite_volumes.util import get_revision_number
27from anuga.abstract_2d_finite_volumes.util import store_version_info
28from anuga.config import major_revision
29
30
31# name of 'home' directory containing releases
32ANUGA_RELEASE_DIR = 'anuga_releases'
33
34# prefix for temporary directory
35TEMP_DIR_PREFIX = 'anuga_release_'
36
37# path to and required contents of documentation directory
38DOC_PATH = os.path.join('anuga_core', 'documentation', 'user_manual')
39DOC_FILES = ['anuga_user_manual.pfd',
40             'anuga_installation_guide.pdf',
41             'anuga_whats_new.pdf']
42
43
44# path to NSIS install directory
45NSIS_PATH = r'C:\Program Files\NSIS'
46NSIS_EXE = os.path.join(NSIS_PATH, 'makensis.exe')
47
48# the name of the subversion commandline client
49SVN_CLIENT = 'svn'
50
51
52def abort(msg, stop=True):
53    """Some sort of error, report and abort."""
54
55    print('abort: stop=%s' % str(stop))
56   
57    xlog('*' * 80)
58    xlog(msg)
59    xlog('*' * 80)
60    if stop:
61        sys.exit(10)
62
63
64def check_doc(temp_dir, release_name):
65    """Make sure all the documentation is present.
66
67    temp_dir      released code working directory
68    release_name  ANUGA release name
69
70    Returns if everything OK.
71    """
72
73    bad = False
74   
75    for file in DOC_FILES:
76        doc_file = os.path.join(DOC_PATH, file)
77        if not os.path.isfile(doc_file):
78            xlog('Documentation file %s is missing.' % doc_file)
79            bad = True
80
81    if bad and not Force:
82        abort('Sorry, documentation files are missing.\n'
83              'You must release on Linux before Windows.', stop=False)
84
85
86def check_IP(temp_dir, verbose=False):
87    """Check IP statements in release directories."""
88
89    if not IP_verified(temp_dir, verbose=verbose):
90        if not Force:
91            abort('Files have not been verified for IP.\n'
92                  'Each data file must have a licence file with it.')
93
94
95def compile_nsi_file():
96    """Compile the installer NSI file."""
97
98    # figure out where the *.nsi file actually is
99    nsi_file = os.path.join(BranchDir, 'installation_files', 'windows',
100                            'installer.nsi')
101   
102    do_cmd('"%s" /V2 %s' % (NSIS_EXE, nsi_file))
103
104
105def copy_release_directories(revision, temp_dir):
106    """Get release dirs (correct version) into release directory."""
107   
108    for src in dirs_to_distribute.dirmap:
109        dst = os.path.join(temp_dir, dirs_to_distribute.dirmap[src])
110        do_cmd('%s export -r %s --quiet %s %s'
111               % (SVN_CLIENT, revision, src, dst))
112
113
114def do_cmd(cmd, ignore_errors=False):
115    """Execute a command, optionally ignore errors."""
116
117    try:
118        xlog(cmd)
119        os.system(cmd)
120    except:
121        if not ignore_errors:
122            raise
123
124
125def get_directories(rel_name):
126    """Create release and temporary directories, return paths.
127
128    rel_name  the ANUGA release name
129    """
130
131    # create the release directory
132    rel_area = os.path.join('~', ANUGA_RELEASE_DIR)
133    rel_area = os.path.expanduser(rel_area)
134
135    rel_dir = os.path.join(rel_area, rel_name)
136    if os.path.isdir(rel_dir):
137        if Force:
138            os.removedirs(rel_dir)
139        else:
140            abort("Sorry, release directory '%s' already exists.\n"
141                  "Please delete that directory first." % rel_dir)
142       
143    os.makedirs(rel_dir)
144
145    # create a temporary scratch directory
146    temp_dir = tempfile.mkdtemp(suffix='', prefix=TEMP_DIR_PREFIX)
147
148    return (rel_dir, temp_dir)
149   
150
151def get_release_name():
152    """Get release information and create release name.
153
154    Get release numbers from the current directory.
155
156    Returns a string which is of the form 'anuga-X.Y.Z' where X is the
157    major release number, Y is the minor and Z is the bug number.
158    """
159   
160    curr_dir = os.getcwd()
161    curr_dir = os.path.basename(curr_dir)
162    split_dir = curr_dir.split('_')
163    if len(split_dir) < 2:
164        abort('You must run this script in an ANUGA branch directory.')
165    if split_dir[0] != 'anuga':
166        abort('You must run this script in an ANUGA branch directory.')
167
168    major = split_dir[1]
169    if len(split_dir) < 3:
170        minor = '0'
171    else:
172        minor = split_dir[2]
173       
174    if len(split_dir) < 4:
175        bug = '0'
176    else:
177        bug = split_dir[3]
178
179    return 'anuga-%s.%s.%s' % (major, minor, bug)
180   
181
182def get_svn_revision():
183    """Get the current revision number from svn.
184
185    This uses the CollabNet subversion client.
186    """
187
188    try:
189        fid = os.popen('%s info' % SVN_CLIENT)
190    except:
191        abort('Subversion commandline client not found')
192
193    lines = fid.readlines()
194    fid.close()
195
196    for l in lines:
197        l = l.strip()
198        if l.startswith('Last Changed Rev:'):
199            (_, revision) = l.split(':', 1)
200            try:
201                revision = int(revision)
202            except ValueError:
203                abort('"svn info" did not return expected line: ' + l)
204            return revision
205
206    abort('"svn info" did not return expected line "Last Changed Rev:"')
207
208
209def make_installer(revision):
210    """Make a windows installer.
211
212    revision  the revision number (string) to release
213              (may be None, meaning 'use latest')
214    """
215
216    global BranchDir
217
218    # get the current branch directory path
219    BranchDir = os.getcwd()
220   
221    # if revision is None (not supplied) do update and get latest revision
222    if revision is None:
223        do_cmd('%s up' % SVN_CLIENT)
224        revision = get_svn_revision()
225       
226    # get release name from current directory
227    release_name = get_release_name()
228
229    # get working directory paths (directories have been created)
230    (release_dir, temp_dir) = get_directories(release_name)
231
232    # get the ANUGA directories that are being released
233    copy_release_directories(revision, temp_dir)
234
235    # check IP data for release directories
236    check_IP(temp_dir, verbose=True)
237
238    # generate the LaTeX documentation
239    check_doc(temp_dir, release_name)
240
241    # create ZIP release file, put into release dir
242    make_zip_file(temp_dir, release_name, release_dir)
243
244    # compile Windows *.nsi file
245    # creates EXE in <BranchDir>\installation_files\windows
246    # check we have required files/directories
247    # remove all generated *.exe files
248    anuga_dir = os.path.join(BranchDir, 'installation_files', 'windows',
249                             'files', release_name)
250    if not os.path.isdir(anuga_dir):
251        abort("Sorry, directory %s doesn't exist.\n"
252              "You need to run the Linux create distribution first."
253              % anuga_dir)
254       
255       
256    src = os.path.join(BranchDir, 'installation_files', 'windows', '*.exe')
257    do_cmd('del /Q %s' % src)   
258    compile_nsi_file()
259
260    # copy the create EXE to the release directory
261    do_cmd('move /Y %s %s' % (src, release_dir))
262
263    # clean up
264    shutil.rmtree(temp_dir)
265
266
267def make_zip_file(temp_dir, release_name, release_dir):
268    """Make a ZIP file, copy to release directory.
269
270    temp_dir      directory where we copied release files
271    release_name  the release name
272    release_dir   destination for the ZIP file
273    """
274
275    # create .tgz file in temp_dir
276   
277   
278   
279def usage(msg=None):
280    """Give befuddled user some help."""
281
282    if msg:
283        print(msg)
284    print('usage: create_win_installer [<revision_number>]\n'
285          'where <revision_number> is an optional revision number to release.')
286
287
288def xlog(msg):
289    """Print and log a message."""
290
291    print(msg)
292   
293    # uncomment this to get file logging
294##    log(msg)
295   
296
297if __name__ == '__main__':
298    global Force
299   
300    if sys.platform != 'win32':
301        msg = ('This script is not written for Linux.  '
302               'Please run it on a Windows platform.')
303        raise Exception(msg)
304
305    argv = sys.argv[1:]
306
307    try:
308        opts, args = getopt.getopt(argv, 'hf', ['help', 'force'])
309    except getopt.error, msg:
310        usage()
311        sys.exit(10)
312
313    Force = False
314    for (opt, param) in opts:
315        if opt in ['-h', '--help']:
316            usage()
317            sys.exit(0)
318        elif opt in ['-f', '--force']:
319            Force = True
320
321    if len(args) > 1:
322        usage()
323        sys.exit(10)
324
325    revision = None
326    if len(args) == 1:
327        try:
328            revision = int(args[0])
329        except ValueError:
330            usage()
331            sys.exit(10)
332
333    make_installer(revision)
Note: See TracBrowser for help on using the repository browser.