~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to tools/win32/bzr_postinstall.py

  • Committer: Patch Queue Manager
  • Date: 2014-04-09 13:36:25 UTC
  • mfrom: (6592.1.2 1303879-py27-issues)
  • Revision ID: pqm@pqm.ubuntu.com-20140409133625-s24spv3kha2w2860
(vila) Fix python-2.7.6 test failures. (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006, 2007, 2009, 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""bzr postinstall helper for win32 installation
 
18
Written by Alexander Belchenko
 
19
 
 
20
Dependency: ctypes
 
21
"""
 
22
 
 
23
import os
 
24
import shutil
 
25
import sys
 
26
 
 
27
 
 
28
##
 
29
# CONSTANTS
 
30
 
 
31
VERSION = "1.5.20070131"
 
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
 
 
51
# Windows version
 
52
_major,_minor,_build,_platform,_text = sys.getwindowsversion()
 
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
 
72
    winver = 'Windows 98'
 
73
 
 
74
 
 
75
##
 
76
# INTERNAL VARIABLES
 
77
 
 
78
(OK, ERROR) = range(2)
 
79
VERSION_FORMAT = "%-50s%s"
 
80
 
 
81
 
 
82
def main():
 
83
    import ctypes
 
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
 
 
157
    bzr_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
 
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
            elif s.find(r'C:\Program Files\Bazaar') != -1:
 
177
                content[ix] = s.replace(r'C:\Program Files\Bazaar',
 
178
                                        bzr_dir)
 
179
 
 
180
        if dry_run:
 
181
            print "*** Write file: start_bzr.bat"
 
182
            print "*** File content:"
 
183
            print ''.join(content)
 
184
        else:
 
185
            f = file(fname, 'w')
 
186
            f.write(''.join(content))
 
187
            f.close()
 
188
 
 
189
    if (add_path or delete_path) and winver == 'Windows NT':
 
190
        # find appropriate registry key:
 
191
        # 1. HKLM\System\CurrentControlSet\Control\SessionManager\Environment
 
192
        # 2. HKCU\Environment
 
193
        keys = ((_winreg.HKEY_LOCAL_MACHINE, (r'System\CurrentControlSet\Control'
 
194
                                              r'\Session Manager\Environment')),
 
195
                (_winreg.HKEY_CURRENT_USER, r'Environment'),
 
196
               )
 
197
 
 
198
        hkey = None
 
199
        for key, subkey in keys:
 
200
            try:
 
201
                hkey = _winreg.OpenKey(key, subkey, 0, _winreg.KEY_ALL_ACCESS)
 
202
                try:
 
203
                    path_u, type_ = _winreg.QueryValueEx(hkey, 'Path')
 
204
                except WindowsError:
 
205
                    if key != _winreg.HKEY_CURRENT_USER:
 
206
                        _winreg.CloseKey(hkey)
 
207
                        hkey = None
 
208
                        continue
 
209
                    else:
 
210
                        path_u = u''
 
211
                        type_ = _winreg.REG_SZ
 
212
            except EnvironmentError:
 
213
                continue
 
214
            break
 
215
 
 
216
        if hkey is None:
 
217
            print "Cannot find appropriate registry key for PATH"
 
218
        else:
 
219
            path_list = [i for i in path_u.split(os.pathsep) if i != '']
 
220
            f_change = False
 
221
            for ix, item in enumerate(path_list[:]):
 
222
                if item == bzr_dir:
 
223
                    if delete_path:
 
224
                        del path_list[ix]
 
225
                        f_change = True
 
226
                    elif add_path:
 
227
                        print "*** Bzr already in PATH"
 
228
                    break
 
229
            else:
 
230
                if add_path and not delete_path:
 
231
                    path_list.append(bzr_dir.decode(user_encoding))
 
232
                    f_change = True
 
233
 
 
234
            if f_change:
 
235
                path_u = os.pathsep.join(path_list)
 
236
                if dry_run:
 
237
                    print "*** Registry key %s\\%s" % (hkey_str[key], subkey)
 
238
                    print "*** Modify PATH variable. New value:"
 
239
                    print path_u
 
240
                else:
 
241
                    _winreg.SetValueEx(hkey, 'Path', 0, type_, path_u)
 
242
                    _winreg.FlushKey(hkey)
 
243
 
 
244
        if not hkey is None:
 
245
            _winreg.CloseKey(hkey)
 
246
 
 
247
    if (add_path or delete_path) and winver == 'Windows 98':
 
248
        # mutating autoexec.bat
 
249
        # adding or delete string:
 
250
        # SET PATH=%PATH%;C:\PROGRA~1\Bazaar
 
251
        abat = 'C:\\autoexec.bat'
 
252
        abak = 'C:\\autoexec.bak'
 
253
 
 
254
        def backup_autoexec_bat(name, backupname, dry_run):
 
255
            # backup autoexec.bat
 
256
            if os.path.isfile(name):
 
257
                if not dry_run:
 
258
                    shutil.copyfile(name, backupname)
 
259
                else:
 
260
                    print '*** backup copy of autoexec.bat created'
 
261
 
 
262
        GetShortPathName = ctypes.windll.kernel32.GetShortPathNameA
 
263
        buf = ctypes.create_string_buffer(260)
 
264
        if GetShortPathName(bzr_dir, buf, 260):
 
265
            bzr_dir_8_3 = buf.value
 
266
        else:
 
267
            bzr_dir_8_3 = bzr_dir
 
268
        pattern = 'SET PATH=%PATH%;' + bzr_dir_8_3
 
269
 
 
270
        # search pattern
 
271
        f = file(abat, 'r')
 
272
        lines = f.readlines()
 
273
        f.close()
 
274
        found = False
 
275
        for i in lines:
 
276
            if i.rstrip('\r\n') == pattern:
 
277
                found = True
 
278
                break
 
279
 
 
280
        if delete_path and found:
 
281
            backup_autoexec_bat(abat, abak, dry_run)
 
282
            if not dry_run:
 
283
                f = file(abat, 'w')
 
284
                for i in lines:
 
285
                    if i.rstrip('\r\n') != pattern:
 
286
                        f.write(i)
 
287
                f.close()
 
288
            else:
 
289
                print '*** Remove line <%s> from autoexec.bat' % pattern
 
290
                    
 
291
        elif add_path and not found:
 
292
            backup_autoexec_bat(abat, abak, dry_run)
 
293
            if not dry_run:
 
294
                f = file(abat, 'a')
 
295
                f.write(pattern)
 
296
                f.write('\n')
 
297
                f.close()
 
298
            else:
 
299
                print '*** Add line <%s> to autoexec.bat' % pattern
 
300
 
 
301
    if add_shell_menu and not delete_shell_menu:
 
302
        hkey = None
 
303
        try:
 
304
            hkey = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT,
 
305
                                     r'Folder\shell\bzr')
 
306
        except EnvironmentError:
 
307
            if not silent:
 
308
                MessageBoxA(None,
 
309
                            'Unable to create registry key for context menu',
 
310
                            'EnvironmentError',
 
311
                            MB_OK | MB_ICONERROR)
 
312
 
 
313
        if not hkey is None:
 
314
            _winreg.SetValue(hkey, '', _winreg.REG_SZ, 'Bzr Here')
 
315
            hkey2 = _winreg.CreateKey(hkey, 'command')
 
316
            _winreg.SetValue(hkey2, '', _winreg.REG_SZ,
 
317
                             '%s /K "%s"' % (
 
318
                                    os.environ.get('COMSPEC', '%COMSPEC%'),
 
319
                                    os.path.join(bzr_dir, 'start_bzr.bat')))
 
320
            _winreg.CloseKey(hkey2)
 
321
            _winreg.CloseKey(hkey)
 
322
 
 
323
    if delete_shell_menu:
 
324
        try:
 
325
            _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT,
 
326
                              r'Folder\shell\bzr\command')
 
327
        except EnvironmentError:
 
328
            pass
 
329
 
 
330
        try:
 
331
            _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT,
 
332
                              r'Folder\shell\bzr')
 
333
        except EnvironmentError:
 
334
            pass
 
335
 
 
336
    if check_mfc71:
 
337
        try:
 
338
            ctypes.windll.LoadLibrary('mfc71.dll')
 
339
        except WindowsError:
 
340
            MessageBoxA(None,
 
341
                        ("Library MFC71.DLL is not found on your system.\n"
 
342
                         "This library needed for SFTP transport.\n"
 
343
                         "If you need to work via SFTP you should download\n"
 
344
                         "this library manually and put it to directory\n"
 
345
                         "where Bzr installed.\n"
 
346
                         "For detailed instructions see:\n"
 
347
                         "http://wiki.bazaar.canonical.com/BzrOnPureWindows"
 
348
                        ),
 
349
                        "Warning",
 
350
                        MB_OK | MB_ICONEXCLAMATION)
 
351
 
 
352
    return OK
 
353
 
 
354
 
 
355
if __name__ == "__main__":
 
356
    sys.exit(main())