~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
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())