# Copyright (C) 2006-2014 Derrick Moser # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the licence, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. You may also obtain a copy of the GNU General Public License # from the Free Software Foundation by visiting their web site # (http://www.fsf.org/) or by writing to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # This program builds a Windows installer for Diffuse. import codecs import glob import os import platform import subprocess import sys VERSION = '0.8.1' PACKAGE = '1' PLATFORM = 'win' + ''.join([c for c in platform.architecture()[0] if c.isdigit()]) INSTALLER = 'diffuse-%s-%s.%s' % (VERSION, PACKAGE, PLATFORM) # makes a directory without complaining if it already exists def mkdir(s): if not os.path.isdir(s): os.mkdir(s) # copies a file to 'dest' def copyFile(src, dest, use_text_mode=False, enc=None): print('copying "%s" to "%s"' % (src, dest)) if use_text_mode: r, w = 'r', 'w' else: r, w = 'rb', 'wb' f = open(src, r) s = f.read() f.close() if enc is not None: s = codecs.encode(str(s, encoding='utf_8'), enc) f = open(dest, w) f.write(s) f.close() # recursively copies a directory to 'dest' def copyDir(src, dest): print('copying "%s" to "%s"' % (src, dest)) mkdir(dest) for f in os.listdir(src): s = os.path.join(src, f) d = os.path.join(dest, f) if os.path.isfile(s): copyFile(s, d) elif os.path.isdir(s): copyDir(s, d) # helper to clean up the resulting HTML def extract_tag(s, start, end): i = s.find(start) if i >= 0: pre = s[:i] i += len(start) j = s.find(end, i) if j >= 0: return pre, start, s[i:j], end, s[j+len(end):] # # Make sure we are in the correct directory. # path = os.path.dirname(sys.argv[0]) if path != '': os.chdir(path) # # Build EXE versions of the Diffuse Python script. # # make a temp directory mkdir('temp') # copy script into temp directory under two names for p in 'temp\\diffuse.py', 'temp\\diffusew.pyw': copyFile('..\\src\\usr\\bin\\diffuse', p, True) # build executable in 'dist' from diffuse.py and diffusew.pyw args = [sys.executable, 'setup.py', 'py2exe'] if os.spawnv(os.P_WAIT, args[0], args) != 0: raise OSError('Could not run setup.py') # include Microsoft redistributables needed by Python 2.6 and above for f in 'msvcm90.dll', 'msvcp90.dll', 'msvcr90.dll': copyFile( os.path.join( os.environ['SYSTEMROOT'], 'WinSxS\\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375\\' + f ), 'dist\\' + f ) copyFile( os.path.join( os.environ['SYSTEMROOT'], 'WinSxS\\Manifests\\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375.manifest' # noqa: E501 ), 'dist\\Microsoft.VC90.CRT.manifest' ) # include GTK dependencies gtk_dir = os.environ['GTK_BASEPATH'] copyDir(os.path.join(gtk_dir, 'etc'), 'dist\\etc') copyDir(os.path.join(gtk_dir, 'lib'), 'dist\\lib') mkdir('dist\\share') copyDir(os.path.join(gtk_dir, 'share\\icons'), 'dist\\share\\icons') copyDir(os.path.join(gtk_dir, 'share\\themes'), 'dist\\share\\themes') # # Add all support files. # # syntax highlighting support mkdir('dist\\syntax') for p in glob.glob('..\\src\\usr\\share\\diffuse\\syntax\\*.syntax'): copyFile(p, os.path.join('dist\\syntax', os.path.basename(p)), True) copyFile('diffuserc', 'dist\\diffuserc') # application icon copyDir('..\\src\\usr\\share\\icons', 'dist\\share\\icons') # translations mkdir('dist\\share\\locale') locale_dir = os.path.join(gtk_dir, 'share\\locale') for s in glob.glob('..\\po\\*.po'): lang = s[16:-3] # Diffuse localisations print('Compiling %s translation' % (lang, )) d = 'dist' for p in ['locale', lang, 'LC_MESSAGES']: d = os.path.join(d, p) mkdir(d) d = os.path.join(d, 'diffuse.mo') if subprocess.Popen(['msgfmt', '-o', d, s]).wait() != 0: raise OSError('Failed to compile "%s" into "%s".' % (s, d)) # GTK localisations d = os.path.join(locale_dir, lang) if os.path.isdir(d): copyDir(d, os.path.join('dist\\share\\locale', lang)) # # Add all documentation. # # license and other documentation for p in 'AUTHORS', 'ChangeLog', 'COPYING', 'README': copyFile(os.path.join('..', p), os.path.join('dist', p + '.txt'), True) for p, enc in [('ChangeLog_ru', 'cp1251'), ('README_ru', 'cp1251')]: copyFile(os.path.join('..', p), os.path.join('dist', p + '.txt'), True, enc) # fetch translations for English text hard coded in the stylesheets translations = {} f = open('translations.txt', 'rb') for v in f.read().split('\n'): v = v.split(':') if len(v) == 3: lang = v[0] if lang not in translations: translations[lang] = [] translations[lang].append(v[1:]) f.close() # convert the manual from DocBook to HTML d = '..\\src\\usr\\share\\gnome\\help\\diffuse' for lang in os.listdir(d): p = os.path.join(os.path.join(d, lang), 'diffuse.xml') if os.path.isfile(p): cmd = ['xsltproc', '/usr/share/sgml/docbook/xsl-stylesheets/html/docbook.xsl', p] info = subprocess.STARTUPINFO() info.dwFlags |= subprocess.STARTF_USESHOWWINDOW info.wShowWindow = subprocess.SW_HIDE proc = subprocess.Popen( cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=info) proc.stdin.close() proc.stderr.close() fd = proc.stdout s = fd.read() fd.close() if proc.wait() != 0: raise OSError('Could not run xsltproc') # add link to style sheet s = s.replace( '', '' ) s = s.replace('

\n

', '') s = s.replace('

\n

', '') # cleanup HTML to simpler UTF-8 form s = s.replace( '', '' ) a, idx = [], 0 while True: i = s.find('&#', idx) if i < 0: a.append(str(s[idx:], encoding='latin_1')) break a.append(str(s[idx:i], encoding='latin_1')) i += 2 j = s.find(';', i) a.append(chr(int(s[i:j]))) idx = j + 1 s = ''.join(a) s = codecs.encode(s, 'utf-8') # clean up translator credit portion div = extract_tag(s, '
', '
') if div is not None: firstname = extract_tag(div[2], '', '') surname = extract_tag(div[2], '', '') contrib = extract_tag(div[2], '', '') email = extract_tag(div[2], '', '') copyright = extract_tag(div[4], '') if ( firstname is not None and surname is not None and contrib is not None and email is not None and copyright is not None ): s = ( '%s%s

%s: ' '%s ' '%s ' '

%s' ) % ( div[0], ''.join(copyright[:4]), contrib[2], firstname[2], surname[2], email[2], copyright[4] ) # translate extra text for k, v in translations.get(lang, []): s = s.replace(k, v) # save HTML version of the manual fn = 'manual' if lang != 'C': fn += '_' + lang # update the document language s = s.replace(' lang="en" ', ' lang="%s" ' % (lang,)) f = open(os.path.join('dist', fn + '.html'), 'w') f.write(s) f.close() copyFile('style.css', 'dist\\style.css') # # Package everything into a single EXE installer. # # build binary installer copyFile(os.path.join(os.environ['ADD_PATH_HOME'], 'add_path.exe'), 'dist\\add_path.exe') if os.system('iscc diffuse.iss /F%s' % (INSTALLER, )) != 0: raise OSError('Could not run iscc') # # Declare success. # print('Successfully created "%s".' % (INSTALLER, ))