~bzr-pqm/bzr/bzr.dev

1821.1.1 by Alexander Belchenko
win32 installer for bzr.dev.0.9
1
# Copyright (C) 2005 by Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""bzr postinstall helper for win32 installation
18
Written by Alexander Belchenko
2245.4.8 by Alexander Belchenko
bzr_postinstall.py: on win98 path added to autoexec.bat should have 8.3 form
19
20
Dependency: ctypes
1821.1.1 by Alexander Belchenko
win32 installer for bzr.dev.0.9
21
"""
22
23
import os
2245.4.7 by Alexander Belchenko
standalone installer: win98 support
24
import shutil
1821.1.1 by Alexander Belchenko
win32 installer for bzr.dev.0.9
25
import sys
26
27
28
##
29
# CONSTANTS
30
2245.4.8 by Alexander Belchenko
bzr_postinstall.py: on win98 path added to autoexec.bat should have 8.3 form
31
VERSION = "1.5.20070131"
1821.1.1 by Alexander Belchenko
win32 installer for bzr.dev.0.9
32
33
USAGE = """Bzr postinstall helper for win32 installation
34
Usage: %s [options]
35
36
OPTIONS:
37
    -h, --help                  - help message
38
    -v, --version               - version info
39
40
    -n, --dry-run               - print actions rather than execute them
41
    -q, --silent                - no messages for user
42
43
    --start-bzr                 - update start_bzr.bat
44
    --add-path                  - add bzr directory to environment PATH
45
    --delete-path               - delete bzr directory to environment PATH
46
    --add-shell-menu            - add shell context menu to start bzr session
47
    --delete-shell-menu         - delete context menu from shell
48
    --check-mfc71               - check if MFC71.DLL present in system
49
""" % os.path.basename(sys.argv[0])
50
2245.4.7 by Alexander Belchenko
standalone installer: win98 support
51
# Windows version
52
_major,_minor,_build,_platform,_text = sys.getwindowsversion()
2245.4.11 by Alexander Belchenko
Small fixes after John's review; added NEWS entry
53
# from MSDN:
54
# dwPlatformId
55
#   The operating system platform.
56
#   This member can be one of the following values.
57
#   ==========================  ======================================
58
#   Value                       Meaning
59
#   --------------------------  --------------------------------------
60
#   VER_PLATFORM_WIN32_NT       The operating system is Windows Vista,
61
#   2                           Windows Server "Longhorn",
62
#                               Windows Server 2003, Windows XP,
63
#                               Windows 2000, or Windows NT.
64
#
65
#   VER_PLATFORM_WIN32_WINDOWS  The operating system is Windows Me,
66
#   1                           Windows 98, or Windows 95.
67
#   ==========================  ======================================
68
if _platform == 2:
69
    winver = 'Windows NT'
70
else:
71
    # don't care about real Windows name, just to force safe operations
2245.4.7 by Alexander Belchenko
standalone installer: win98 support
72
    winver = 'Windows 98'
73
74
1821.1.1 by Alexander Belchenko
win32 installer for bzr.dev.0.9
75
##
76
# INTERNAL VARIABLES
77
78
(OK, ERROR) = range(2)
79
VERSION_FORMAT = "%-50s%s"
80
81
82
def main():
2245.4.8 by Alexander Belchenko
bzr_postinstall.py: on win98 path added to autoexec.bat should have 8.3 form
83
    import ctypes
1821.1.1 by Alexander Belchenko
win32 installer for bzr.dev.0.9
84
    import getopt
85
    import re
86
    import _winreg
87
88
    import locale
89
    user_encoding = locale.getpreferredencoding() or 'ascii'
90
91
    import ctypes
92
93
    hkey_str = {_winreg.HKEY_LOCAL_MACHINE: 'HKEY_LOCAL_MACHINE',
94
                _winreg.HKEY_CURRENT_USER: 'HKEY_CURRENT_USER',
95
                _winreg.HKEY_CLASSES_ROOT: 'HKEY_CLASSES_ROOT',
96
               }
97
98
    dry_run = False
99
    silent = False
100
    start_bzr = False
101
    add_path = False
102
    delete_path = False
103
    add_shell_menu = False
104
    delete_shell_menu = False
105
    check_mfc71 = False
106
107
    try:
108
        opts, args = getopt.getopt(sys.argv[1:], "hvnq",
109
                                   ["help", "version",
110
                                    "dry-run",
111
                                    "silent",
112
                                    "start-bzr",
113
                                    "add-path",
114
                                    "delete-path",
115
                                    "add-shell-menu",
116
                                    "delete-shell-menu",
117
                                    "check-mfc71",
118
                                   ])
119
120
        for o, a in opts:
121
            if o in ("-h", "--help"):
122
                print USAGE
123
                return OK
124
            elif o in ("-v", "--version"):
125
                print VERSION_FORMAT % (USAGE.splitlines()[0], VERSION)
126
                return OK
127
128
            elif o in ('-n', "--dry-run"):
129
                dry_run = True
130
            elif o in ('-q', '--silent'):
131
                silent = True
132
133
            elif o == "--start-bzr":
134
                start_bzr = True
135
            elif o == "--add-path":
136
                add_path = True
137
            elif o == "--delete-path":
138
                delete_path = True
139
            elif o == "--add-shell-menu":
140
                add_shell_menu = True
141
            elif o == "--delete-shell-menu":
142
                delete_shell_menu = True
143
            elif o == "--check-mfc71":
144
                check_mfc71 = True
145
146
    except getopt.GetoptError, msg:
147
        print str(msg)
148
        print USAGE
149
        return ERROR
150
151
    # message box from Win32API
152
    MessageBoxA = ctypes.windll.user32.MessageBoxA
153
    MB_OK = 0
154
    MB_ICONERROR = 16
155
    MB_ICONEXCLAMATION = 48
156
2245.4.8 by Alexander Belchenko
bzr_postinstall.py: on win98 path added to autoexec.bat should have 8.3 form
157
    bzr_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
1821.1.1 by Alexander Belchenko
win32 installer for bzr.dev.0.9
158
159
    if start_bzr:
160
        fname = os.path.join(bzr_dir, "start_bzr.bat")
161
        if os.path.isfile(fname):
162
            f = file(fname, "r")
163
            content = f.readlines()
164
            f.close()
165
        else:
166
            content = ["bzr.exe help\n"]
167
168
        for ix in xrange(len(content)):
169
            s = content[ix]
170
            if re.match(r'.*(?<!\\)bzr\.exe([ "].*)?$',
171
                        s.rstrip('\r\n'),
172
                        re.IGNORECASE):
173
                content[ix] = s.replace('bzr.exe',
174
                                        '"%s"' % os.path.join(bzr_dir,
175
                                                              'bzr.exe'))
176
177
        if dry_run:
178
            print "*** Write file: start_bzr.bat"
179
            print "*** File content:"
180
            print ''.join(content)
181
        else:
182
            f = file(fname, 'w')
183
            f.write(''.join(content))
184
            f.close()
185
2245.4.7 by Alexander Belchenko
standalone installer: win98 support
186
    if (add_path or delete_path) and winver == 'Windows NT':
1821.1.1 by Alexander Belchenko
win32 installer for bzr.dev.0.9
187
        # find appropriate registry key:
188
        # 1. HKLM\System\CurrentControlSet\Control\SessionManager\Environment
189
        # 2. HKCU\Environment
190
        keys = ((_winreg.HKEY_LOCAL_MACHINE, (r'System\CurrentControlSet\Control'
191
                                              r'\Session Manager\Environment')),
192
                (_winreg.HKEY_CURRENT_USER, r'Environment'),
193
               )
194
195
        hkey = None
196
        for key, subkey in keys:
197
            try:
198
                hkey = _winreg.OpenKey(key, subkey, 0, _winreg.KEY_ALL_ACCESS)
199
                try:
200
                    path_u, type_ = _winreg.QueryValueEx(hkey, 'Path')
201
                except WindowsError:
202
                    if key != _winreg.HKEY_CURRENT_USER:
203
                        _winreg.CloseKey(hkey)
204
                        hkey = None
205
                        continue
206
                    else:
207
                        path_u = u''
208
                        type_ = _winreg.REG_SZ
209
            except EnvironmentError:
210
                continue
211
            break
212
213
        if hkey is None:
214
            print "Cannot find appropriate registry key for PATH"
215
        else:
216
            path_list = [i for i in path_u.split(os.pathsep) if i != '']
217
            f_change = False
218
            for ix, item in enumerate(path_list[:]):
219
                if item == bzr_dir:
220
                    if delete_path:
221
                        del path_list[ix]
222
                        f_change = True
223
                    elif add_path:
224
                        print "*** Bzr already in PATH"
225
                    break
226
            else:
227
                if add_path and not delete_path:
228
                    path_list.append(bzr_dir.decode(user_encoding))
229
                    f_change = True
230
231
            if f_change:
232
                path_u = os.pathsep.join(path_list)
233
                if dry_run:
234
                    print "*** Registry key %s\\%s" % (hkey_str[key], subkey)
235
                    print "*** Modify PATH variable. New value:"
236
                    print path_u
237
                else:
238
                    _winreg.SetValueEx(hkey, 'Path', 0, type_, path_u)
239
                    _winreg.FlushKey(hkey)
240
241
        if not hkey is None:
242
            _winreg.CloseKey(hkey)
243
2245.4.7 by Alexander Belchenko
standalone installer: win98 support
244
    if (add_path or delete_path) and winver == 'Windows 98':
245
        # mutating autoexec.bat
246
        # adding or delete string:
247
        # SET PATH=%PATH%;C:\PROGRA~1\Bazaar
248
        abat = 'C:\\autoexec.bat'
249
        abak = 'C:\\autoexec.bak'
250
251
        def backup_autoexec_bat(name, backupname, dry_run):
252
            # backup autoexec.bat
253
            if os.path.isfile(name):
254
                if not dry_run:
255
                    shutil.copyfile(name, backupname)
256
                else:
257
                    print '*** backup copy of autoexec.bat created'
258
2245.4.8 by Alexander Belchenko
bzr_postinstall.py: on win98 path added to autoexec.bat should have 8.3 form
259
        GetShortPathName = ctypes.windll.kernel32.GetShortPathNameA
260
        buf = ctypes.create_string_buffer(260)
261
        if GetShortPathName(bzr_dir, buf, 260):
262
            bzr_dir_8_3 = buf.value
263
        else:
264
            bzr_dir_8_3 = bzr_dir
265
        pattern = 'SET PATH=%PATH%;' + bzr_dir_8_3
266
267
        # search pattern
268
        f = file(abat, 'r')
269
        lines = f.readlines()
270
        f.close()
271
        found = False
272
        for i in lines:
273
            if i.rstrip('\r\n') == pattern:
274
                found = True
275
                break
276
277
        if delete_path and found:
2245.4.7 by Alexander Belchenko
standalone installer: win98 support
278
            backup_autoexec_bat(abat, abak, dry_run)
279
            if not dry_run:
280
                f = file(abat, 'w')
281
                for i in lines:
282
                    if i.rstrip('\r\n') != pattern:
283
                        f.write(i)
284
                f.close()
285
            else:
286
                print '*** Remove line <%s> from autoexec.bat' % pattern
287
                    
2245.4.8 by Alexander Belchenko
bzr_postinstall.py: on win98 path added to autoexec.bat should have 8.3 form
288
        elif add_path and not found:
2245.4.7 by Alexander Belchenko
standalone installer: win98 support
289
            backup_autoexec_bat(abat, abak, dry_run)
290
            if not dry_run:
291
                f = file(abat, 'a')
292
                f.write(pattern)
293
                f.write('\n')
294
                f.close()
295
            else:
296
                print '*** Add line <%s> to autoexec.bat' % pattern
297
1821.1.1 by Alexander Belchenko
win32 installer for bzr.dev.0.9
298
    if add_shell_menu and not delete_shell_menu:
299
        hkey = None
300
        try:
301
            hkey = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT,
302
                                     r'Folder\shell\bzr')
303
        except EnvironmentError:
304
            if not silent:
305
                MessageBoxA(None,
306
                            'Unable to create registry key for context menu',
307
                            'EnvironmentError',
308
                            MB_OK | MB_ICONERROR)
309
310
        if not hkey is None:
311
            _winreg.SetValue(hkey, '', _winreg.REG_SZ, 'Bzr Here')
312
            hkey2 = _winreg.CreateKey(hkey, 'command')
313
            _winreg.SetValue(hkey2, '', _winreg.REG_SZ,
2245.4.7 by Alexander Belchenko
standalone installer: win98 support
314
                             '%s /K "%s"' % (
315
                                    os.environ.get('COMSPEC', '%COMSPEC%'),
2245.4.8 by Alexander Belchenko
bzr_postinstall.py: on win98 path added to autoexec.bat should have 8.3 form
316
                                    os.path.join(bzr_dir, 'start_bzr.bat')))
1821.1.1 by Alexander Belchenko
win32 installer for bzr.dev.0.9
317
            _winreg.CloseKey(hkey2)
318
            _winreg.CloseKey(hkey)
319
320
    if delete_shell_menu:
321
        try:
322
            _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT,
323
                              r'Folder\shell\bzr\command')
324
        except EnvironmentError:
325
            pass
326
327
        try:
328
            _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT,
329
                              r'Folder\shell\bzr')
330
        except EnvironmentError:
331
            pass
332
333
    if check_mfc71:
334
        try:
335
            ctypes.windll.LoadLibrary('mfc71.dll')
336
        except WindowsError:
337
            MessageBoxA(None,
338
                        ("Library MFC71.DLL is not found on your system.\n"
339
                         "This library needed for SFTP transport.\n"
340
                         "If you need to work via SFTP you should download\n"
341
                         "this library manually and put it to directory\n"
342
                         "where Bzr installed.\n"
343
                         "For detailed instructions see:\n"
344
                         "http://bazaar-vcs.org/BzrOnPureWindows"
345
                        ),
346
                        "Warning",
347
                        MB_OK | MB_ICONEXCLAMATION)
348
349
    return OK
350
351
352
if __name__ == "__main__":
353
    sys.exit(main())