/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
1
# Copyright (C) 2006, 2007 Canonical Ltd
2
#
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
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
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
17
"""Win32-specific helper functions
18
19
Only one dependency: ctypes should be installed.
20
"""
21
22
import os
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
23
import struct
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
24
import sys
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
25
import _winreg
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
26
27
28
# Windows version
29
if sys.platform == 'win32':
30
    _major,_minor,_build,_platform,_text = sys.getwindowsversion()
2245.4.11 by Alexander Belchenko
Small fixes after John's review; added NEWS entry
31
    # from MSDN:
32
    # dwPlatformId
33
    #   The operating system platform.
34
    #   This member can be one of the following values.
35
    #   ==========================  ======================================
36
    #   Value                       Meaning
37
    #   --------------------------  --------------------------------------
38
    #   VER_PLATFORM_WIN32_NT       The operating system is Windows Vista,
39
    #   2                           Windows Server "Longhorn",
40
    #                               Windows Server 2003, Windows XP,
41
    #                               Windows 2000, or Windows NT.
42
    #
43
    #   VER_PLATFORM_WIN32_WINDOWS  The operating system is Windows Me,
44
    #   1                           Windows 98, or Windows 95.
45
    #   ==========================  ======================================
46
    if _platform == 2:
47
        winver = 'Windows NT'
48
    else:
49
        # don't care about real Windows name, just to force safe operations
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
50
        winver = 'Windows 98'
51
else:
52
    winver = None
53
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
54
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
55
# We can cope without it; use a separate variable to help pyflakes
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
56
try:
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
57
    import ctypes
58
    has_ctypes = True
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
59
except ImportError:
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
60
    has_ctypes = False
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
61
else:
62
    if winver == 'Windows 98':
63
        create_buffer = ctypes.create_string_buffer
64
        suffix = 'A'
65
    else:
66
        create_buffer = ctypes.create_unicode_buffer
67
        suffix = 'W'
68
69
70
# Special Win32 API constants
71
# Handles of std streams
1704.2.3 by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander)
72
WIN32_STDIN_HANDLE = -10
73
WIN32_STDOUT_HANDLE = -11
74
WIN32_STDERR_HANDLE = -12
75
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
76
# CSIDL constants (from MSDN 2003)
77
CSIDL_APPDATA = 0x001A      # Application Data folder
78
CSIDL_PERSONAL = 0x0005     # My Documents folder
79
80
# from winapi C headers
81
MAX_PATH = 260
82
UNLEN = 256
83
MAX_COMPUTERNAME_LENGTH = 31
84
1704.2.3 by Martin Pool
(win32) Detect terminal width using GetConsoleScreenBufferInfo (Alexander)
85
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
86
def get_console_size(defaultx=80, defaulty=25):
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
87
    """Return size of current console.
88
89
    This function try to determine actual size of current working
90
    console window and return tuple (sizex, sizey) if success,
91
    or default size (defaultx, defaulty) otherwise.
92
    """
93
    if not has_ctypes:
94
        # no ctypes is found
95
        return (defaultx, defaulty)
96
97
    # To avoid problem with redirecting output via pipe
98
    # need to use stderr instead of stdout
99
    h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
100
    csbi = ctypes.create_string_buffer(22)
101
    res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
102
103
    if res:
104
        (bufx, bufy, curx, cury, wattr,
1185.16.86 by mbp at sourcefrog
- win32 get_console_size from Alexander
105
        left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
106
        sizex = right - left + 1
107
        sizey = bottom - top + 1
108
        return (sizex, sizey)
109
    else:
110
        return (defaultx, defaulty)
111
112
113
def get_appdata_location():
114
    """Return Application Data location.
115
    Return None if we cannot obtain location.
116
117
    Returned value can be unicode or plain sring.
118
    To convert plain string to unicode use
119
    s.decode(bzrlib.user_encoding)
120
    """
121
    if has_ctypes:
122
        try:
123
            SHGetSpecialFolderPath = \
124
                ctypes.windll.shell32.SHGetSpecialFolderPathW
125
        except AttributeError:
126
            pass
127
        else:
128
            buf = ctypes.create_unicode_buffer(MAX_PATH)
129
            if SHGetSpecialFolderPath(None,buf,CSIDL_APPDATA,0):
130
                return buf.value
131
    # from env variable
132
    appdata = os.environ.get('APPDATA')
133
    if appdata:
134
        return appdata
135
    # if we fall to this point we on win98
136
    # at least try C:/WINDOWS/Application Data
137
    windir = os.environ.get('windir')
138
    if windir:
139
        appdata = os.path.join(windir, 'Application Data')
140
        if os.path.isdir(appdata):
141
            return appdata
142
    # did not find anything
143
    return None
144
145
146
def get_home_location():
147
    """Return user's home location.
148
    Assume on win32 it's the <My Documents> folder.
149
    If location cannot be obtained return system drive root,
150
    i.e. C:\
151
152
    Returned value can be unicode or plain sring.
153
    To convert plain string to unicode use
154
    s.decode(bzrlib.user_encoding)
155
    """
156
    if has_ctypes:
157
        try:
158
            SHGetSpecialFolderPath = \
159
                ctypes.windll.shell32.SHGetSpecialFolderPathW
160
        except AttributeError:
161
            pass
162
        else:
163
            buf = ctypes.create_unicode_buffer(MAX_PATH)
164
            if SHGetSpecialFolderPath(None,buf,CSIDL_PERSONAL,0):
165
                return buf.value
166
    # try for HOME env variable
167
    home = os.path.expanduser('~')
168
    if home != '~':
169
        return home
170
    # at least return windows root directory
171
    windir = os.environ.get('windir')
172
    if windir:
2610.1.1 by Martin Pool
Fix get_home_location on Win98 (gzlist,r=john,r=alexander)
173
        return os.path.splitdrive(windir)[0] + '/'
2245.4.1 by Alexander Belchenko
win32utils: Windows-specific functions that use Win32 API via ctypes
174
    # otherwise C:\ is good enough for 98% users
175
    return 'C:/'
176
177
178
def get_user_name():
179
    """Return user name as login name.
180
    If name cannot be obtained return None.
181
182
    Returned value can be unicode or plain sring.
183
    To convert plain string to unicode use
184
    s.decode(bzrlib.user_encoding)
185
    """
186
    if has_ctypes:
187
        try:
188
            advapi32 = ctypes.windll.advapi32
189
            GetUserName = getattr(advapi32, 'GetUserName'+suffix)
190
        except AttributeError:
191
            pass
192
        else:
193
            buf = create_buffer(UNLEN+1)
194
            n = ctypes.c_int(UNLEN+1)
195
            if GetUserName(buf, ctypes.byref(n)):
196
                return buf.value
197
    # otherwise try env variables
198
    return os.environ.get('USERNAME', None)
199
200
201
def get_host_name():
202
    """Return host machine name.
203
    If name cannot be obtained return None.
204
205
    Returned value can be unicode or plain sring.
206
    To convert plain string to unicode use
207
    s.decode(bzrlib.user_encoding)
208
    """
209
    if has_ctypes:
210
        try:
211
            kernel32 = ctypes.windll.kernel32
212
            GetComputerName = getattr(kernel32, 'GetComputerName'+suffix)
213
        except AttributeError:
214
            pass
215
        else:
216
            buf = create_buffer(MAX_COMPUTERNAME_LENGTH+1)
217
            n = ctypes.c_int(MAX_COMPUTERNAME_LENGTH+1)
218
            if GetComputerName(buf, ctypes.byref(n)):
219
                return buf.value
220
    # otherwise try env variables
221
    return os.environ.get('COMPUTERNAME', None)
222
223
224
def _ensure_unicode(s):
225
    if s and type(s) != unicode:
226
        import bzrlib
227
        s = s.decode(bzrlib.user_encoding)
228
    return s
229
    
230
231
def get_appdata_location_unicode():
232
    return _ensure_unicode(get_appdata_location())
233
234
def get_home_location_unicode():
235
    return _ensure_unicode(get_home_location())
236
237
def get_user_name_unicode():
238
    return _ensure_unicode(get_user_name())
239
240
def get_host_name_unicode():
241
    return _ensure_unicode(get_host_name())
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
242
243
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
244
def _ensure_with_dir(path):
245
    if not os.path.split(path)[0] or path.startswith(u'*') or path.startswith(u'?'):
246
        return u'./' + path, True
247
    else:
248
        return path, False
249
    
250
def _undo_ensure_with_dir(path, corrected):
251
    if corrected:
252
        return path[2:]
253
    else:
254
        return path
255
256
257
2598.3.1 by Kuno Meyer
fix method rename glob_expand_for_win32 -> win32utils.glob_expand
258
def glob_expand(file_list):
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
259
    """Replacement for glob expansion by the shell.
260
261
    Win32's cmd.exe does not do glob expansion (eg ``*.py``), so we do our own
262
    here.
263
264
    :param file_list: A list of filenames which may include shell globs.
265
    :return: An expanded list of filenames.
266
267
    Introduced in bzrlib 0.18.
268
    """
269
    if not file_list:
270
        return []
271
    import glob
272
    expanded_file_list = []
273
    for possible_glob in file_list:
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
274
        
275
        # work around bugs in glob.glob()
276
        # - Python bug #1001604 ("glob doesn't return unicode with ...")
277
        # - failing expansion for */* with non-iso-8859-* chars
278
        possible_glob, corrected = _ensure_with_dir(possible_glob)
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
279
        glob_files = glob.glob(possible_glob)
280
281
        if glob_files == []:
282
            # special case to let the normal code path handle
283
            # files that do not exists
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
284
            expanded_file_list.append(
285
                _undo_ensure_with_dir(possible_glob, corrected))
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
286
        else:
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
287
            glob_files = [_undo_ensure_with_dir(elem, corrected) for elem in glob_files]
2568.2.2 by Robert Collins
* New method ``_glob_expand_file_list_if_needed`` on the ``Command`` class
288
            expanded_file_list += glob_files
2617.5.8 by Kuno Meyer
Extended tests for unicode chars outside of the iso-8859-* range
289
            
290
    return [elem.replace(u'\\', u'/') for elem in expanded_file_list] 
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
291
292
293
def get_app_path(appname):
294
    """Look up in Windows registry for full path to application executable.
295
    Typicaly, applications create subkey with their basename
296
    in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
297
298
    :param  appname:    name of application (if no filename extension
299
                        is specified, .exe used)
300
    :return:    full path to aplication executable from registry,
301
                or appname itself if nothing found.
302
    """
303
    try:
304
        hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
305
                               r'SOFTWARE\Microsoft\Windows'
306
                               r'\CurrentVersion\App Paths')
307
    except EnvironmentError:
308
        return appname
309
310
    basename = appname
311
    if not os.path.splitext(basename)[1]:
312
        basename = appname + '.exe'
313
    try:
314
        try:
315
            fullpath = _winreg.QueryValue(hkey, basename)
316
        except WindowsError:
317
            fullpath = appname
318
    finally:
319
        _winreg.CloseKey(hkey)
320
321
    return fullpath