~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to tools/win32/bzr_postinstall.py

merge with bzr.dev revno.1860

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
19
"""
 
20
 
 
21
import os
 
22
import sys
 
23
 
 
24
 
 
25
##
 
26
# CONSTANTS
 
27
 
 
28
VERSION = "1.3.20060513"
 
29
 
 
30
USAGE = """Bzr postinstall helper for win32 installation
 
31
Usage: %s [options]
 
32
 
 
33
OPTIONS:
 
34
    -h, --help                  - help message
 
35
    -v, --version               - version info
 
36
 
 
37
    -n, --dry-run               - print actions rather than execute them
 
38
    -q, --silent                - no messages for user
 
39
 
 
40
    --start-bzr                 - update start_bzr.bat
 
41
    --add-path                  - add bzr directory to environment PATH
 
42
    --delete-path               - delete bzr directory to environment PATH
 
43
    --add-shell-menu            - add shell context menu to start bzr session
 
44
    --delete-shell-menu         - delete context menu from shell
 
45
    --check-mfc71               - check if MFC71.DLL present in system
 
46
""" % os.path.basename(sys.argv[0])
 
47
 
 
48
##
 
49
# INTERNAL VARIABLES
 
50
 
 
51
(OK, ERROR) = range(2)
 
52
VERSION_FORMAT = "%-50s%s"
 
53
 
 
54
 
 
55
def main():
 
56
    import getopt
 
57
    import re
 
58
    import _winreg
 
59
 
 
60
    import locale
 
61
    user_encoding = locale.getpreferredencoding() or 'ascii'
 
62
 
 
63
    import ctypes
 
64
 
 
65
    hkey_str = {_winreg.HKEY_LOCAL_MACHINE: 'HKEY_LOCAL_MACHINE',
 
66
                _winreg.HKEY_CURRENT_USER: 'HKEY_CURRENT_USER',
 
67
                _winreg.HKEY_CLASSES_ROOT: 'HKEY_CLASSES_ROOT',
 
68
               }
 
69
 
 
70
    dry_run = False
 
71
    silent = False
 
72
    start_bzr = False
 
73
    add_path = False
 
74
    delete_path = False
 
75
    add_shell_menu = False
 
76
    delete_shell_menu = False
 
77
    check_mfc71 = False
 
78
 
 
79
    try:
 
80
        opts, args = getopt.getopt(sys.argv[1:], "hvnq",
 
81
                                   ["help", "version",
 
82
                                    "dry-run",
 
83
                                    "silent",
 
84
                                    "start-bzr",
 
85
                                    "add-path",
 
86
                                    "delete-path",
 
87
                                    "add-shell-menu",
 
88
                                    "delete-shell-menu",
 
89
                                    "check-mfc71",
 
90
                                   ])
 
91
 
 
92
        for o, a in opts:
 
93
            if o in ("-h", "--help"):
 
94
                print USAGE
 
95
                return OK
 
96
            elif o in ("-v", "--version"):
 
97
                print VERSION_FORMAT % (USAGE.splitlines()[0], VERSION)
 
98
                return OK
 
99
 
 
100
            elif o in ('-n', "--dry-run"):
 
101
                dry_run = True
 
102
            elif o in ('-q', '--silent'):
 
103
                silent = True
 
104
 
 
105
            elif o == "--start-bzr":
 
106
                start_bzr = True
 
107
            elif o == "--add-path":
 
108
                add_path = True
 
109
            elif o == "--delete-path":
 
110
                delete_path = True
 
111
            elif o == "--add-shell-menu":
 
112
                add_shell_menu = True
 
113
            elif o == "--delete-shell-menu":
 
114
                delete_shell_menu = True
 
115
            elif o == "--check-mfc71":
 
116
                check_mfc71 = True
 
117
 
 
118
    except getopt.GetoptError, msg:
 
119
        print str(msg)
 
120
        print USAGE
 
121
        return ERROR
 
122
 
 
123
    # message box from Win32API
 
124
    MessageBoxA = ctypes.windll.user32.MessageBoxA
 
125
    MB_OK = 0
 
126
    MB_ICONERROR = 16
 
127
    MB_ICONEXCLAMATION = 48
 
128
 
 
129
    bzr_dir = os.path.dirname(sys.argv[0])
 
130
 
 
131
    if start_bzr:
 
132
        fname = os.path.join(bzr_dir, "start_bzr.bat")
 
133
        if os.path.isfile(fname):
 
134
            f = file(fname, "r")
 
135
            content = f.readlines()
 
136
            f.close()
 
137
        else:
 
138
            content = ["bzr.exe help\n"]
 
139
 
 
140
        for ix in xrange(len(content)):
 
141
            s = content[ix]
 
142
            if re.match(r'.*(?<!\\)bzr\.exe([ "].*)?$',
 
143
                        s.rstrip('\r\n'),
 
144
                        re.IGNORECASE):
 
145
                content[ix] = s.replace('bzr.exe',
 
146
                                        '"%s"' % os.path.join(bzr_dir,
 
147
                                                              'bzr.exe'))
 
148
 
 
149
        if dry_run:
 
150
            print "*** Write file: start_bzr.bat"
 
151
            print "*** File content:"
 
152
            print ''.join(content)
 
153
        else:
 
154
            f = file(fname, 'w')
 
155
            f.write(''.join(content))
 
156
            f.close()
 
157
 
 
158
    if add_path or delete_path:
 
159
        # find appropriate registry key:
 
160
        # 1. HKLM\System\CurrentControlSet\Control\SessionManager\Environment
 
161
        # 2. HKCU\Environment
 
162
        keys = ((_winreg.HKEY_LOCAL_MACHINE, (r'System\CurrentControlSet\Control'
 
163
                                              r'\Session Manager\Environment')),
 
164
                (_winreg.HKEY_CURRENT_USER, r'Environment'),
 
165
               )
 
166
 
 
167
        hkey = None
 
168
        for key, subkey in keys:
 
169
            try:
 
170
                hkey = _winreg.OpenKey(key, subkey, 0, _winreg.KEY_ALL_ACCESS)
 
171
                try:
 
172
                    path_u, type_ = _winreg.QueryValueEx(hkey, 'Path')
 
173
                except WindowsError:
 
174
                    if key != _winreg.HKEY_CURRENT_USER:
 
175
                        _winreg.CloseKey(hkey)
 
176
                        hkey = None
 
177
                        continue
 
178
                    else:
 
179
                        path_u = u''
 
180
                        type_ = _winreg.REG_SZ
 
181
            except EnvironmentError:
 
182
                continue
 
183
            break
 
184
 
 
185
        if hkey is None:
 
186
            print "Cannot find appropriate registry key for PATH"
 
187
        else:
 
188
            path_list = [i for i in path_u.split(os.pathsep) if i != '']
 
189
            f_change = False
 
190
            for ix, item in enumerate(path_list[:]):
 
191
                if item == bzr_dir:
 
192
                    if delete_path:
 
193
                        del path_list[ix]
 
194
                        f_change = True
 
195
                    elif add_path:
 
196
                        print "*** Bzr already in PATH"
 
197
                    break
 
198
            else:
 
199
                if add_path and not delete_path:
 
200
                    path_list.append(bzr_dir.decode(user_encoding))
 
201
                    f_change = True
 
202
 
 
203
            if f_change:
 
204
                path_u = os.pathsep.join(path_list)
 
205
                if dry_run:
 
206
                    print "*** Registry key %s\\%s" % (hkey_str[key], subkey)
 
207
                    print "*** Modify PATH variable. New value:"
 
208
                    print path_u
 
209
                else:
 
210
                    _winreg.SetValueEx(hkey, 'Path', 0, type_, path_u)
 
211
                    _winreg.FlushKey(hkey)
 
212
 
 
213
        if not hkey is None:
 
214
            _winreg.CloseKey(hkey)
 
215
 
 
216
    if add_shell_menu and not delete_shell_menu:
 
217
        hkey = None
 
218
        try:
 
219
            hkey = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT,
 
220
                                     r'Folder\shell\bzr')
 
221
        except EnvironmentError:
 
222
            if not silent:
 
223
                MessageBoxA(None,
 
224
                            'Unable to create registry key for context menu',
 
225
                            'EnvironmentError',
 
226
                            MB_OK | MB_ICONERROR)
 
227
 
 
228
        if not hkey is None:
 
229
            _winreg.SetValue(hkey, '', _winreg.REG_SZ, 'Bzr Here')
 
230
            hkey2 = _winreg.CreateKey(hkey, 'command')
 
231
            _winreg.SetValue(hkey2, '', _winreg.REG_SZ,
 
232
                             'cmd /K "%s"' % os.path.join(bzr_dir,
 
233
                                                          'start_bzr.bat'))
 
234
            _winreg.CloseKey(hkey2)
 
235
            _winreg.CloseKey(hkey)
 
236
 
 
237
    if delete_shell_menu:
 
238
        try:
 
239
            _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT,
 
240
                              r'Folder\shell\bzr\command')
 
241
        except EnvironmentError:
 
242
            pass
 
243
 
 
244
        try:
 
245
            _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT,
 
246
                              r'Folder\shell\bzr')
 
247
        except EnvironmentError:
 
248
            pass
 
249
 
 
250
    if check_mfc71:
 
251
        try:
 
252
            ctypes.windll.LoadLibrary('mfc71.dll')
 
253
        except WindowsError:
 
254
            MessageBoxA(None,
 
255
                        ("Library MFC71.DLL is not found on your system.\n"
 
256
                         "This library needed for SFTP transport.\n"
 
257
                         "If you need to work via SFTP you should download\n"
 
258
                         "this library manually and put it to directory\n"
 
259
                         "where Bzr installed.\n"
 
260
                         "For detailed instructions see:\n"
 
261
                         "http://bazaar-vcs.org/BzrOnPureWindows"
 
262
                        ),
 
263
                        "Warning",
 
264
                        MB_OK | MB_ICONEXCLAMATION)
 
265
 
 
266
    return OK
 
267
 
 
268
 
 
269
if __name__ == "__main__":
 
270
    sys.exit(main())