#!/usr/bin/env python # Copyright (c) 2007 RADLogic # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """Generate NSIS file statements for all files under a given directory. NSIS is the Nullsoft Scriptable Installer System. It is an open source program for generating installers/uninstallers for Windows. See http://nsis.sourceforge.net/ for details. The easiest way to use this is to make a release directory and create symlinks in it that point to the files that are to be released. This script can then be called on the release directory, and every file gets added explicitly to the installer (as opposed to using globs) which makes uninstall smarter. Usage: python make_nsis_file_section.py [uninstall] > file_list.nsi """ __author__ = 'Tim Wegener ' __version__ = '$Revision: 0.4 $' __date__ = '$Date: 2007/03/27 03:29:23 $' import os import sys def generate_nsis_file_list(base_dir, uninstall=False, f_out=None): """Generate NSIS file statements for all files under a given directory. Arguments: base_dir -- this directory will be treated as $INSTDIR, and File statements will be generated for every file in it (including subdirs) uninstall -- set this to True to generate file list for uninstall (default: False) f_out -- (default: stdout) """ if f_out is None: f_out = sys.stdout relative_path = base_dir.replace('/', '\\') uninstall_dirs = [] # Use a custom directory walking function, so that symlinks can be # handled properly. def walk(dirname, f_out=f_out, uninstall=uninstall, relative_path=relative_path, uninstall_dirs=uninstall_dirs): names = os.listdir(dirname) # Create windows-style dirname for inserting into NSIS script, # which will be run on Windows. win_dirname = dirname.replace(base_dir, '').replace('/', '\\') if names: if not uninstall: f_out.write(' SetOutPath $INSTDIR%s\n' % win_dirname) else: uninstall_dirs.append(win_dirname) subdirs = [] for name in names: path = os.path.join(dirname, name) # Note: Need to follow symlink when checking if it is a directory. realpath = os.path.realpath(path) if os.path.isdir(realpath): subdirs.append(path) else: if not uninstall: f_out.write(' File %s%s\%s\n' % (relative_path, win_dirname, name)) else: f_out.write(' Delete $INSTDIR%s\%s\n' % (win_dirname, name)) for subdir in subdirs: walk(subdir) walk(base_dir, uninstall=uninstall, uninstall_dirs=uninstall_dirs) if uninstall: # Reverse the directory list so that children get removed first. uninstall_dirs.reverse() for uninstall_dir in uninstall_dirs: # Note: The RMDir command without any options only deletes the # directory if it is empty, which is what we want. f_out.write(' RMDir "$INSTDIR%s"\n' % uninstall_dir) def main(): """Command line front-end""" try: base_dir = sys.argv[1] except IndexError: sys.stderr.write(__doc__) sys.exit(2) uninstall = False if len(sys.argv) > 2: uninstall_arg = sys.argv[2] if uninstall_arg == 'uninstall': uninstall = True generate_nsis_file_list(base_dir=base_dir, uninstall=uninstall) if __name__ == '__main__': main()