/[wryebash]/branches/upstream-master/scripts/package_for_release.py
ViewVC logotype

Contents of /branches/upstream-master/scripts/package_for_release.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (show annotations) (download) (as text)
Mon Sep 19 03:20:26 2016 UTC (3 years, 9 months ago) by william
File MIME type: text/x-python
File size: 30308 byte(s)
add upstream git branches for dev and master
1 #!/usr/bin/env python2.7-32
2 # -*- coding: utf-8 -*-
3 #
4 # GPL License and Copyright Notice ============================================
5 # This file is part of Wrye Bash.
6 #
7 # Wrye Bash is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
11 #
12 # Wrye Bash is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Wrye Bash; if not, write to the Free Software Foundation,
19 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #
21 # Wrye Bash copyright (C) 2005-2009 Wrye, 2010-2015 Wrye Bash Team
22 # https://github.com/wrye-bash
23 #
24 # =============================================================================
25
26 """Python script to package up the various Wrye Bash files into archives for
27 release. More detailed help can be found by passing the --help or -h
28 command line arguments.
29
30 It is assumed that if you have multiple version of Python installed on your
31 computer, then you also have Python Launcher for Windows installed. This
32 will ensure that this script will be launched with the correct version of
33 Python, via shebang lines. Python Launcher for Windows comes with Python
34 3.3+, but will need to be installed manually otherwise."""
35
36
37 # Imports ---------------------------------------------------------------------
38 from __future__ import print_function
39 import subprocess
40 import os
41 import shutil
42 import sys
43 import argparse
44 import binascii
45 import textwrap
46 import traceback
47
48 # environment detection
49 try:
50 #--Needed for the Installer version to find NSIS
51 import _winreg
52 except ImportError:
53 _winreg = False
54
55 try:
56 #--Needed for the StandAlone version
57 import py2exe
58 except:
59 py2exe = False
60
61 try:
62 #--Needed to ensure non-repo file don't get packaged
63 import git
64 have_git = True
65 except:
66 have_git = False
67
68
69 # ensure we are in the correct directory so relative paths will work properly
70 scriptDir = os.path.dirname(unicode(sys.argv[0], sys.getfilesystemencoding()))
71 if scriptDir:
72 os.chdir(scriptDir)
73 os.chdir(u'..')
74
75
76 # Setup some global paths that all functions will use
77 root = os.getcwdu()
78 scripts = os.path.join(root, u'scripts')
79 mopy = os.path.join(root, u'Mopy')
80 apps = os.path.join(mopy, u'Apps')
81 if sys.platform.lower().startswith('linux'):
82 exe7z = u'7z'
83 else:
84 exe7z = os.path.join(mopy, u'bash', u'compiled', u'7z.exe')
85 dest = os.path.join(scripts, u'dist')
86
87 # global pipe file for log output
88 pipe = None
89
90
91 def GetVersionInfo(version, padding=4):
92 """Gets generates version strings from the passed parameter.
93 Returns the a string used for the 'File Version' property
94 of the built WBSA.
95 For example, a
96 version of 291 would with default padding would return:
97 ('291','0.2.9.1')"""
98 file_version = (u'0.' * abs(padding))[:-1]
99
100 v = version
101 v = v.replace(u'.', u'')
102 if padding < 0:
103 file_version = u'.'.join(c for c in v.ljust(-padding, u'0'))
104 else:
105 file_version = u'.'.join(c for c in v.rjust(padding, u'0'))
106
107 return file_version
108
109
110 def rm(node):
111 """Removes a file or directory if it exitsts"""
112 if os.path.isfile(node): os.remove(node)
113 elif os.path.isdir(node): shutil.rmtree(node)
114
115
116 def mv(node, dst):
117 """Moves a file or directory if it exists"""
118 if os.path.exists(node):
119 shutil.move(node, dst)
120
121
122 def lprint(*args, **kwdargs):
123 """Helper function to print to both the build log file and the console.
124 Needs the print function to work properly."""
125 print(*args, **kwdargs)
126 if pipe:
127 kwdargs['file'] = pipe
128 print('[package_for_release]:', *args, **kwdargs)
129 pipe.flush()
130
131
132 def VerifyPy2Exe():
133 """Checks for presense of the modified zipextimporter.py. We no longer want
134 the modified version, and need the original."""
135 # CRCs of the correct version, from both 'r', and 'rb' mode
136 crcGood = [0xA56E66A6, 0x57925DA8]
137 path = os.path.join(sys.prefix, u'Lib', u'site-packages',
138 u'zipextimporter.py')
139 # First we'll test using 'r' mode, this way if the line endings differ,
140 # but the contents are the same, the crc will still be equal
141 with open(os.path.join(scripts, u'zipextimporter.py'), 'r') as ins:
142 crcBad = binascii.crc32(ins.read())
143 crcBad &= 0xFFFFFFFFL
144 with open(path, 'r') as ins:
145 crcTest = binascii.crc32(ins.read())
146 crcTest &= 0xFFFFFFFFL
147 if crcTest == crcBad:
148 # Definitely using the old modified version, need to reinstall
149 return False
150 if crcTest in crcGood:
151 # Definitely using the un-modified version, good to go
152 return True
153 # Now check if the current file's crc in 'rb' mode matches a known "good"
154 # crc.
155 with open(path, 'rb') as ins:
156 crcTest = binascii.crc32(ins.read())
157 crcTest &= 0xFFFFFFFFL
158 if crcTest in crcGood:
159 # Definitely using the un-modified version
160 return True
161 # Last test: see if the modified lines are present
162 with open(path, 'r') as ins:
163 return 'filename = fullname.replace(".","\\")' in ins.read()
164
165
166 def BuildManualVersion(args, all_files):
167 """Creates the standard python manual install version"""
168 version = args.version
169 archive = os.path.join(dest, u'Wrye Bash %s - Python Source.7z' % version)
170 listFile = os.path.join(dest, u'manual_list.txt')
171 with open(listFile, 'wb') as out:
172 # We want every file for the manual version
173 for file in all_files:
174 out.write(file)
175 out.write('\n')
176 cmd_7z = [exe7z, 'a', '-mx9', archive, '@%s' % listFile]
177 subprocess.call(cmd_7z, stdout=pipe, stderr=pipe)
178 rm(listFile)
179
180
181 def CleanupStandaloneFiles():
182 """Removes standalone exe files that are not needed after packaging"""
183 rm(os.path.join(mopy, u'Wrye Bash.exe'))
184 rm(os.path.join(mopy, u'w9xpopen.exe'))
185
186
187 def CreateStandaloneExe(args, file_version):
188 """Builds the standalone exe"""
189 # Check for build requirements
190 if not py2exe:
191 lprint(" Could not find python module 'py2exe', aborting standalone "
192 "creation.")
193 return False
194 if not VerifyPy2Exe():
195 lprint(" You have the replacement zipextimporter.py installed. The "
196 "replacement is not longer used. Please re-install py2exe to"
197 " get the original file back.")
198 return False
199 # Some paths we'll use
200 wbsa = os.path.join(scripts, u'build', u'standalone')
201 reshacker = os.path.join(wbsa, u'Reshacker.exe')
202 upx = os.path.join(wbsa, u'upx.exe')
203 icon = os.path.join(wbsa, u'bash.ico')
204 manifest = os.path.join(wbsa, u'manifest.template')
205 script = os.path.join(wbsa, u'setup.template')
206 exe = os.path.join(mopy, u'Wrye Bash.exe')
207 w9xexe = os.path.join(mopy, u'w9xpopen.exe')
208 setup = os.path.join(mopy, u'setup.py')
209 #--For l10n
210 msgfmt = os.path.join(sys.prefix, u'Tools', u'i18n', u'msgfmt.py')
211 pygettext = os.path.join(sys.prefix, u'Tools', u'i18n', u'pygettext.py')
212 msgfmtTo = os.path.join(mopy, u'bash', u'msgfmt.py')
213 pygettextTo = os.path.join(mopy, u'bash', u'pygettext.py')
214 #--Output folders/files
215 dist = os.path.join(mopy, u'dist')
216
217 if not os.path.isfile(script):
218 lprint(" Could not find 'setup.template', aborting standalone "
219 "creation.")
220 if not os.path.isfile(manifest):
221 lprint(" Could not find 'manifest.template', aborting standalone "
222 "creation.")
223 return False
224
225 # Read in the manifest file
226 with open(manifest, 'r') as man:
227 manifest = '"""\n' + man.read() + '\n"""'
228
229 # Include the game package and subpackages (because py2exe wont
230 # automatically detect these)
231 packages = "'bash.game'" # notice the double quotes
232
233 try:
234 # Ensure comtypes is generated, so the required files for wx.lib.iewin
235 # will get pulled in by py2exe
236 lprint(' Generating comtypes...')
237 try:
238 import wx
239 import wx.lib.iewin
240 except ImportError:
241 lprint(' ERROR: Could not import comtypes. Aborting Standalone '
242 'creation.')
243 return False
244 # Write the setup script
245 with open(script, 'r') as ins:
246 script = ins.read()
247 script = script % dict(version=args.version, file_version=file_version,
248 manifest=manifest, upx=None,
249 upx_compression='-9', packages=packages,
250 )
251 with open(setup, 'w') as out:
252 out.write(script)
253
254 # Copy the l10n files over
255 shutil.copy(msgfmt, msgfmtTo)
256 shutil.copy(pygettext, pygettextTo)
257
258 # Call the setup script
259 os.chdir(mopy)
260 subprocess.call([setup, 'py2exe', '-q'], shell=True, stdout=pipe,
261 stderr=pipe)
262 os.chdir(root)
263
264 # Copy the exe's to the Mopy folder
265 mv(os.path.join(dist, u'Wrye Bash Launcher.exe'), exe)
266 mv(os.path.join(dist, u'w9xpopen.exe'), w9xexe)
267
268 # Insert the icon
269 subprocess.call([reshacker, '-addoverwrite', exe+',', exe+',',
270 icon+',', 'icon,', '101,', '0'], stdout=pipe,
271 stderr=pipe)
272
273 # Compress with UPX
274 subprocess.call([upx, '-9', exe], stdout=pipe, stderr=pipe)
275 subprocess.call([upx, '-9', w9xexe], stdout=pipe, stderr=pipe)
276 except:
277 # On error, don't keep the built exe's
278 rm(exe)
279 rm(w9xexe)
280 raise
281 finally:
282 # Clean up left over files
283 rm(msgfmtTo)
284 rm(pygettextTo)
285 rm(dist)
286 rm(os.path.join(mopy, u'build'))
287 rm(os.path.join(wbsa, u'ResHacker.ini'))
288 rm(os.path.join(wbsa, u'ResHacker.log'))
289 rm(setup)
290 rm(os.path.join(mopy, u'Wrye Bash.upx'))
291
292 return True
293
294
295 def PackStandaloneVersion(args, all_files):
296 """Packages the standalone manual install version"""
297 version = args.version
298 archive = os.path.join(
299 dest,
300 u'Wrye Bash %s - Standalone Executable.7z' % version
301 )
302
303 listFile = os.path.join(dest, u'standalone_list.txt')
304 with open(listFile, 'wb') as out:
305 # We do not want any python files with the standalone
306 # version, and we need to include the built EXEs
307 all_files = [x for x in all_files
308 if os.path.splitext(x)[1] not in (u'.py',
309 u'.pyw',
310 u'.bat')
311 ]
312 all_files.extend([u'Mopy\\Wrye Bash.exe',
313 u'Mopy\\w9xPopen.exe'])
314 for file in all_files:
315 out.write(file)
316 out.write('\n')
317 cmd_7z = [exe7z, 'a', '-mx9', archive, '@%s' % listFile]
318 subprocess.call(cmd_7z, stdout=pipe, stderr=pipe)
319 rm(listFile)
320
321
322 def RelocateNonRepoFiles(all_files):
323 """Moves any non-repository files/directories to scripts/temp"""
324 tmpDir = os.path.join(u'scripts', u'temp')
325 rm(tmpDir)
326 os.makedirs(tmpDir)
327
328 non_repo = GetNonRepoFiles(all_files)
329 if non_repo:
330 lprint(" Relocating non-repository files:")
331 for path in non_repo:
332 lprint(" ", path)
333 src = os.path.join(mopy, path)
334 dst = os.path.join(tmpDir, path)
335 if os.path.isdir(src):
336 shutil.move(src, dst)
337 elif os.path.isfile(src):
338 dirname = os.path.dirname(dst)
339 if not os.path.exists(dirname):
340 os.makedirs(dirname)
341 shutil.move(src, dst)
342
343
344 def WarnNonRepoFiles(all_files):
345 """Prints a warning if non-repository files are detected."""
346 non_repo = GetNonRepoFiles(all_files)
347 if non_repo:
348 lprint(" WARNING: Non-repository files are present in your source "
349 "directory, and you have chosen to not relocate them. "
350 "These files will be included in the installer!")
351 for file in non_repo:
352 lprint(" ", file)
353
354
355 def RestoreNonRepoFiles():
356 """Returns non-repository files scripts/temp to their proper locations"""
357 failed = []
358 tmpDir = os.path.join(u'scripts', u'temp')
359 if os.listdir(tmpDir):
360 lprint(" Restoring non-repository files")
361 for top, dirs, files in os.walk(tmpDir):
362 for dir_ in dirs:
363 src = os.path.join(top, dir_)
364 dst = os.path.join(mopy, src[13:])
365 if not os.path.isdir(dst):
366 try:
367 os.makedirs(dst)
368 except:
369 failed.append(src)
370 for file_ in files:
371 src = os.path.join(top, file_)
372 dst = os.path.join(mopy, src[13:])
373 try:
374 shutil.move(src, dst)
375 except:
376 failed.append(src)
377 if failed:
378 lprint(" Failed to restore the following moved files:")
379 for file_ in sorted(failed):
380 lprint(" ", file_)
381 else:
382 try:
383 rm(tmpDir)
384 except:
385 pass
386
387
388 def BuildInstallerVersion(args, all_files, file_version):
389 """Compiles the NSIS script, creating the installer version"""
390 nsis = args.nsis
391 if not _winreg and nsis is None:
392 lprint(" Could not find python module '_winreg', aborting installer "
393 "creation.")
394 return
395
396 script = os.path.join(scripts, u'build', u'installer', u'main.nsi')
397 if not os.path.exists(script):
398 lprint(" Could not find nsis script '%s', aborting installer "
399 "creation." % script)
400 return
401
402 try:
403 if nsis is None:
404 # Need NSIS version 3.0+, so we can use the Inetc plugin
405 # Older versions of NSIS 2.x key was located here:
406 nsis = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE,
407 r'Software\NSIS')
408 inetc = os.path.join(nsis, u'Plugins', u'x86-unicode', u'inetc.dll')
409 nsis = os.path.join(nsis, u'makensis.exe')
410 if not os.path.isfile(nsis):
411 lprint(" Could not find 'makensis.exe', aborting installer "
412 "creation.")
413 return
414 if not os.path.isfile(inetc):
415 lprint(" Could not find NSIS Inetc plugin, aborting installer "
416 "creation.")
417 return
418
419 try:
420 if not args.no_reloc:
421 RelocateNonRepoFiles(all_files)
422 else:
423 WarnNonRepoFiles(all_files)
424
425 # Build the installer
426 lprint(" Calling makensis.exe...")
427 ret = subprocess.call([nsis, '/NOCD',
428 '/DWB_NAME=Wrye Bash %s' % args.version,
429 '/DWB_FILEVERSION=%s' % file_version,
430 script],
431 shell=True, stdout=pipe, stderr=pipe)
432 if ret != 0:
433 lprint(' makensis exited with error code %s. Check the output'
434 ' log for errors in the NSIS script.' % ret)
435 finally:
436 if not args.no_reloc:
437 RestoreNonRepoFiles()
438 except KeyboardInterrupt:
439 raise
440 except Exception as e:
441 lprint(" Error calling creating installer, aborting creation.")
442 traceback.print_exc(file=pipe)
443
444
445 def ShowTutorial():
446 """Prints some additional information that may be needed to run this script
447 that would be too much to fit into the default --help page."""
448 wrapper = textwrap.TextWrapper()
449 list = textwrap.TextWrapper(initial_indent=' * ',
450 subsequent_indent=' ',
451 replace_whitespace=False)
452 listExt = textwrap.TextWrapper(initial_indent=' ',
453 subsequent_indent=' ',
454 replace_whitespace=False)
455 lines = [
456 '',
457 wrapper.fill('This is the packaging script for Wrye Bash. It can be '
458 'used to build all versions of Wrye Bash that are '
459 'released:'),
460 list.fill('''Manual install (archive) of the Python version'''),
461 list.fill('''Manual install (archive) of the Standalone version'''),
462 list.fill('''Automated Installer'''),
463 '',
464 wrapper.fill('In addition to the default requirements to run Wrye Bash'
465 ' in Python mode, you will need five additional things:'),
466 list.fill('NSIS: Used to create the Automated Installer. The latest '
467 '3.x release is recommended, as the instructions below for '
468 'Inetc are based on 3.0.'''),
469 list.fill('Inetc: An NSIS plugin for downloading files, this is needed'
470 ' due to the Python website using redirects that the built '
471 'in NSISdl plugin can not handle. Get it from:'),
472 '',
473 ' http://nsis.sourceforge.net/Inetc_plug-in',
474 '',
475 listExt.fill('And install by copying the provided unicode dll into '
476 'your NSIS/Plugins/x86-unicode directory.'),
477 list.fill('''py2exe: Used to create the Standalone EXE.'''),
478 list.fill('Modified zipextimporter.py: Copy the modified version from'
479 " this directory into your Python's Lib\\site-packages "
480 'directory. This is needed for custom zipextimporter '
481 'functionality that the Wrye Bash Standalone uses.'),
482 list.fill('GitPython: This is used to parse the repository information'
483 ' to ensure non-repo files are not included in the built'
484 ' packages. Get version 0.2.0 or newer. In addition, this '
485 'script needs to be able to locate your git executable. Do '
486 'this by either adding its directory to the PATH environment'
487 ' variable, or passing the directory via the --git command '
488 'line argument.'),
489 '',
490 ' https://pypi.python.org/pypi/GitPython/',
491 ''
492 ]
493 print(*lines, sep='\n')
494
495
496 def GetGitFiles(gitDir, version):
497 """Using git.exe, parses the repository information to get a list of all
498 files that belong in the repository. Returns a dict of files with paths
499 relative to the Mopy directory, which can be used to ensure no non-repo
500 files get included in the installers. This function will also print a
501 warning if there are non-committed changes.
502
503 The dictionary format is:
504 { case_insensitive_file_name: real_file_name}
505 """
506 # First, ensure GitPython will be able to call git. On windows, this means
507 # ensuring that the Git/bin directory is in the PATH variable.
508 if not have_git:
509 lprint("ERROR: Could not locate GitPython.")
510 return False
511
512 try:
513 if sys.platform == 'win32':
514 # Windows, check all the PATH options first
515 for path in os.environ['PATH'].split(u';'):
516 if os.path.isfile(os.path.join(path, u'git.exe')):
517 # Found, no changes necessary
518 break
519 else:
520 # Not found in PATH, try user supplied directory, as well as
521 # common install paths
522 pfiles = os.path.join(os.path.expandvars(u'%PROGRAMFILES%'),
523 u'Git', u'bin')
524 if u'(x86)' in pfiles:
525 # On a 64-bit system, running 32-bit Python, there is
526 # no environment variable that expands to the 64-bit
527 # program files location, so do a hacky workaround
528 pfilesx64 = pfiles.replace(u'Program Files (x86)',
529 u'Program Files')
530 else:
531 pfilesx64 = None
532 for path in (gitDir, pfiles, pfilesx64):
533 if path is None:
534 continue
535 if os.path.isfile(os.path.join(path, u'git.exe')):
536 # Found it, put the path into PATH
537 os.environ['PATH'] += u';' + path
538 break
539 # Test out if git can be launched now
540 try:
541 with open(os.devnull, 'wb') as devnull:
542 subprocess.Popen('git', stdout=devnull, stderr=devnull)
543 except:
544 lprint('ERROR: Could not locate git. Try adding the path to your'
545 ' git directory to the PATH environment variable.')
546 return False
547
548 # Git is working good, now use it
549 repo = git.Repo()
550 if repo.is_dirty():
551 lprint('WARNING: Your wrye-bash repository is dirty (you have '
552 'uncommitted changes).')
553 branchName = repo.active_branch.name.lower()
554 if (not branchName.startswith('rel-') or
555 not branchName.startswith('release-') or
556 not version in branchName):
557 lprint('WARNING: You are building off branch "%s", which does not'
558 ' appear to be a release branch for %s.'
559 % (branchName, version))
560 else:
561 lprint('Building from branch "%s".' % branchName)
562 files = [os.path.normpath(os.path.normcase(x.path))
563 for x in repo.tree().traverse()
564 if x.path.lower().startswith(u'mopy')
565 and os.path.isfile(x.path)
566 ]
567 # Special case: we want the Apps folder to be included, even though
568 # it's not in the repository
569 files.append(os.path.join(u'mopy', u'apps'))
570 return files
571 except:
572 lprint('An error occured while attempting to interface with '
573 'git.')
574 traceback.print_exc(file=pipe)
575 return False
576
577
578 def GetNonRepoFiles(repo_files):
579 """Return a list of all files in the Mopy folder that should not be
580 included in the installer. This list can be used to temporarily
581 remove these files prior to running the NSIS scripts.
582 """
583 non_repo = []
584 # Get a list of every directory and file actually present
585 all_files = []
586 all_dirs = []
587 for root, dirs, files in os.walk(u'Mopy'):
588 all_files.extend((os.path.join(root, x) for x in files))
589 all_dirs.extend((os.path.join(root, x) for x in dirs))
590 all_files = (os.path.normcase(os.path.normpath(x)) for x in all_files)
591 # We can ignore .pyc and .pyo files, since the NSIS scripts skip those
592 all_files = (x for x in all_files
593 if os.path.splitext(x)[1] not in (u'.pyc', u'.pyo'))
594 # We can also ignore w9xpopen and Wrye Bash.exe, for the same reason
595 all_files = [x for x in all_files
596 if os.path.basename(x) not in (u'w9xpopen.exe',
597 u'wrye bash.exe')]
598 all_dirs = [os.path.normcase(os.path.normpath(x)) for x in all_dirs]
599 # Pick out every file that doesn't belong
600 non_repo.extend((x for x in all_files if x not in repo_files))
601 # Pick out every directory that doesn't belong
602 for dir in all_dirs:
603 for file in repo_files:
604 if file.startswith(dir):
605 # It's good to keep
606 break
607 else:
608 # It's not good to keep
609 # Insert these at the beginning so they get handled first when
610 # relocating
611 non_repo.insert(0, dir)
612 # Lop off the "mopy/" part
613 non_repo = [x[5:] for x in non_repo]
614 return non_repo
615
616
617 def main():
618 parser = argparse.ArgumentParser(
619 description='''
620 Packaging script for Wrye Bash, used to create the release modules.
621
622 If you need more detailed help beyond what is listed below, use the
623 --tutorial or -t switch.
624
625 This script requires at least Python 2.7.8 to run, due to improvements
626 made to py2exe executables in regards to MSVC redistributable packages.
627 ''',
628 )
629 parser.add_argument(
630 '-r', '--release',
631 default=None,
632 action='store',
633 type=str,
634 dest='version',
635 help='''Specifies the release number for Wrye Bash that you are
636 packaging.''',
637 )
638 wbsa_group = parser.add_mutually_exclusive_group()
639 wbsa_group.add_argument(
640 '-w', '--wbsa',
641 action='store_true',
642 default=False,
643 dest='wbsa',
644 help='''Build and package the standalone version of Wrye Bash''',
645 )
646 wbsa_group.add_argument(
647 '-e', '--exe',
648 action='store_true',
649 default=False,
650 dest='exe',
651 help='''Create the WBSA exe. This option does not package it into the
652 standalone archive.''',
653 )
654 parser.add_argument(
655 '-m', '--manual',
656 action='store_true',
657 default=False,
658 dest='manual',
659 help='''Package the manual install Python version of Wrye Bash''',
660 )
661 parser.add_argument(
662 '-i', '--installer',
663 action='store_true',
664 default=False,
665 dest='installer',
666 help='''Build the installer version of Wrye Bash.''',
667 )
668 parser.add_argument(
669 '-a', '--all',
670 action='store_true',
671 default=False,
672 dest='all',
673 help='''Build and package all version of Wrye Bash. This is equivalent
674 to -w -i -m''',
675 )
676 parser.add_argument(
677 '-n', '--nsis',
678 default=None,
679 dest='nsis',
680 help='''Specify the path to the NSIS root directory. Use this if the
681 script cannot locate NSIS automatically.''',
682 )
683 parser.add_argument(
684 '-g', '--git',
685 default=None,
686 dest='git',
687 help='''Specify the path to the git bin directory. Use this if the
688 script cannot locate git automatically.''',
689 )
690 parser.add_argument(
691 '--no-reloc',
692 default=False,
693 dest='no_reloc',
694 action='store_true',
695 help='''If specified, the packaging script will NOT attempt to move
696 non-repository files out of the source directory prior to
697 creating the installer. Moved files are moved back after.''',
698 )
699 parser.add_argument(
700 '-v', '--verbose',
701 default=False,
702 action='store_true',
703 dest='verbose',
704 help='''Verbose mode. Directs output from 7z, py2exe, etc. to the
705 console instead of the build log''',
706 )
707 parser.add_argument(
708 '-t', '--tutorial',
709 default=False,
710 action='store_true',
711 dest='tutorial',
712 help='''Prints a more detailed description of requirements and things
713 you need to know before building a release.''',
714 )
715 # Parse command line, show help if invalid arguments are present
716 try:
717 args, extra = parser.parse_known_args()
718 except:
719 parser.print_help()
720 return
721 if len(extra) > 0:
722 parser.print_help()
723 return
724 if args.tutorial:
725 ShowTutorial()
726 return
727 if sys.version_info[0:3] < (2,7,8):
728 lprint('You must run at least Python 2.7.8 to use this script.')
729 lprint('Your Python:', sys.version)
730 return
731 if not args.version:
732 print('No release version specified, please enter it now.')
733 args.version = raw_input('>')
734
735 print (sys.version)
736
737 # See if Mopy/Apps is already present, if it is, we won't
738 # remove it at the end
739 appsPresent = os.path.isdir(apps)
740
741 global pipe
742 try:
743 # Setup output log
744 if args.verbose:
745 pipe = None
746 else:
747 logFile = os.path.join(scripts, 'build.log')
748 pipe = open(logFile, 'w')
749
750 # If no build arguments passed, it's the same as --all
751 if (not args.wbsa and not args.manual
752 and not args.installer and not args.exe) or args.all:
753 # Build everything
754 args.wbsa = True
755 args.manual = True
756 args.installer = True
757
758 # Create the Mopy/Apps folder if it's not present
759 if not appsPresent:
760 os.makedirs(apps)
761
762 # Get repository files
763 all_files = GetGitFiles(args.git, args.version)
764 if all_files is False:
765 lprint('GitPython is not set up correctly, aborting.')
766 return
767
768 file_version = GetVersionInfo(args.version)
769
770 # clean and create distributable directory
771 if os.path.exists(dest):
772 shutil.rmtree(dest)
773 os.makedirs(dest)
774
775 if args.manual:
776 lprint('Creating Python archive distributable...')
777 BuildManualVersion(args, all_files)
778
779 exe_made = False
780
781 if args.exe or args.wbsa or args.installer:
782 lprint('Building standalone exe...')
783 exe_made = CreateStandaloneExe(args, file_version)
784
785 if args.wbsa and exe_made:
786 lprint('Creating standalone distributable...')
787 PackStandaloneVersion(args, all_files)
788
789 if args.installer:
790 lprint('Creating installer distributable...')
791 if exe_made:
792 BuildInstallerVersion(args, all_files, file_version)
793 else:
794 lprint(' Standalone exe not found, aborting installer '
795 'creation.')
796
797 except KeyboardInterrupt:
798 lprint('Build aborted by user.')
799 except Exception as e:
800 print('Error:', e)
801 traceback.print_exc()
802 finally:
803 # Clean up Mopy/Apps if it was not present to begin with
804 if not appsPresent:
805 rm(apps)
806 if not args.exe:
807 # Clean up the WBSA exe's if necessary
808 CleanupStandaloneFiles()
809
810 if not args.verbose:
811 if pipe:
812 pipe.close()
813
814
815 if __name__=='__main__':
816 main()

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.22