/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2009, 2010, 2011 Canonical Ltd
4584.3.21 by Martin Pool
Start adding tests for apport
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
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
17
"""A collection of commonly used 'Features' to optionally run tests.
18
"""
5241.2.1 by Robert Collins
Merge up from 2.0/2.1:
19
6803.3.1 by Martin
Use importlib for ModuleAvailableFeature
20
import importlib
5036.3.8 by Parth Malwankar
closed review comments from vila
21
import os
6060.1.1 by John Arbash Meinel
import subprocess in 'bzrlib.tests.features' so that certain features can properly probe.
22
import subprocess
5036.3.8 by Parth Malwankar
closed review comments from vila
23
import stat
5609.47.1 by Alexander Belchenko
Win32Feature
24
import sys
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
25
import tempfile
6760.1.1 by Jelmer Vernooij
Ignore DeprecationWarning/PendingDeprecationWarning during module probes. We can't do anything about these anyway.
26
import warnings
4584.3.21 by Martin Pool
Start adding tests for apport
27
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
28
from .. import (
5321.2.1 by Vincent Ladeuil
Fix style issues, including vertical spaces, lines too long and multi lines imports.
29
    osutils,
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
30
    symbol_versioning,
5321.2.1 by Vincent Ladeuil
Fix style issues, including vertical spaces, lines too long and multi lines imports.
31
    )
4913.2.19 by John Arbash Meinel
Compatibly rename ApportFeature to features.apport.
32
33
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
34
class Feature(object):
35
    """An operating system Feature."""
36
37
    def __init__(self):
38
        self._available = None
39
40
    def available(self):
41
        """Is the feature available?
42
43
        :return: True if the feature is available.
44
        """
45
        if self._available is None:
46
            self._available = self._probe()
47
        return self._available
48
49
    def _probe(self):
50
        """Implement this method in concrete features.
51
52
        :return: True if the feature is available.
53
        """
54
        raise NotImplementedError
55
56
    def __str__(self):
57
        if getattr(self, 'feature_name', None):
58
            return self.feature_name()
59
        return self.__class__.__name__
60
61
62
class _SymlinkFeature(Feature):
63
64
    def _probe(self):
65
        return osutils.has_symlinks()
66
67
    def feature_name(self):
68
        return 'symlinks'
69
7143.15.2 by Jelmer Vernooij
Run autopep8.
70
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
71
SymlinkFeature = _SymlinkFeature()
72
73
74
class _HardlinkFeature(Feature):
75
76
    def _probe(self):
77
        return osutils.has_hardlinks()
78
79
    def feature_name(self):
80
        return 'hardlinks'
81
7143.15.2 by Jelmer Vernooij
Run autopep8.
82
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
83
HardlinkFeature = _HardlinkFeature()
84
85
86
class _OsFifoFeature(Feature):
87
88
    def _probe(self):
89
        return getattr(os, 'mkfifo', None)
90
91
    def feature_name(self):
92
        return 'filesystem fifos'
93
7143.15.2 by Jelmer Vernooij
Run autopep8.
94
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
95
OsFifoFeature = _OsFifoFeature()
96
97
98
class _UnicodeFilenameFeature(Feature):
99
    """Does the filesystem support Unicode filenames?"""
100
101
    def _probe(self):
102
        try:
103
            # Check for character combinations unlikely to be covered by any
104
            # single non-unicode encoding. We use the characters
105
            # - greek small letter alpha (U+03B1) and
106
            # - braille pattern dots-123456 (U+283F).
107
            os.stat(u'\u03b1\u283f')
108
        except UnicodeEncodeError:
109
            return False
110
        except (IOError, OSError):
111
            # The filesystem allows the Unicode filename but the file doesn't
112
            # exist.
113
            return True
114
        else:
115
            # The filesystem allows the Unicode filename and the file exists,
116
            # for some reason.
117
            return True
118
7143.15.2 by Jelmer Vernooij
Run autopep8.
119
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
120
UnicodeFilenameFeature = _UnicodeFilenameFeature()
121
122
123
class _CompatabilityThunkFeature(Feature):
124
    """This feature is just a thunk to another feature.
125
126
    It issues a deprecation warning if it is accessed, to let you know that you
127
    should really use a different feature.
128
    """
129
130
    def __init__(self, dep_version, module, name,
131
                 replacement_name, replacement_module=None):
132
        super(_CompatabilityThunkFeature, self).__init__()
133
        self._module = module
134
        if replacement_module is None:
135
            replacement_module = module
136
        self._replacement_module = replacement_module
137
        self._name = name
138
        self._replacement_name = replacement_name
139
        self._dep_version = dep_version
140
        self._feature = None
141
142
    def _ensure(self):
143
        if self._feature is None:
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
144
            from breezy import pyutils
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
145
            depr_msg = self._dep_version % ('%s.%s'
146
                                            % (self._module, self._name))
147
            use_msg = ' Use %s.%s instead.' % (self._replacement_module,
148
                                               self._replacement_name)
6325.3.1 by Vincent Ladeuil
Give meaningful deprecation warnings for deprecated test features
149
            symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning,
150
                                   stacklevel=5)
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
151
            # Import the new feature and use it as a replacement for the
152
            # deprecated one.
153
            self._feature = pyutils.get_named_object(
154
                self._replacement_module, self._replacement_name)
155
156
    def _probe(self):
157
        self._ensure()
158
        return self._feature._probe()
159
160
161
class ModuleAvailableFeature(Feature):
162
    """This is a feature than describes a module we want to be available.
163
164
    Declare the name of the module in __init__(), and then after probing, the
165
    module will be available as 'self.module'.
166
167
    :ivar module: The module if it is available, else None.
168
    """
169
6760.1.1 by Jelmer Vernooij
Ignore DeprecationWarning/PendingDeprecationWarning during module probes. We can't do anything about these anyway.
170
    def __init__(self, module_name, ignore_warnings=None):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
171
        super(ModuleAvailableFeature, self).__init__()
172
        self.module_name = module_name
6760.1.3 by Jelmer Vernooij
Martin's review comments.
173
        if ignore_warnings is None:
174
            ignore_warnings = ()
6760.1.1 by Jelmer Vernooij
Ignore DeprecationWarning/PendingDeprecationWarning during module probes. We can't do anything about these anyway.
175
        self.ignore_warnings = ignore_warnings
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
176
177
    def _probe(self):
5642.4.3 by Vincent Ladeuil
Rework the fix taking mgz remarks into account and rebasing against trunk.
178
        sentinel = object()
179
        module = sys.modules.get(self.module_name, sentinel)
180
        if module is sentinel:
6760.1.1 by Jelmer Vernooij
Ignore DeprecationWarning/PendingDeprecationWarning during module probes. We can't do anything about these anyway.
181
            with warnings.catch_warnings():
6760.1.3 by Jelmer Vernooij
Martin's review comments.
182
                for warning_category in self.ignore_warnings:
6760.1.1 by Jelmer Vernooij
Ignore DeprecationWarning/PendingDeprecationWarning during module probes. We can't do anything about these anyway.
183
                    warnings.simplefilter('ignore', warning_category)
184
                try:
6803.3.1 by Martin
Use importlib for ModuleAvailableFeature
185
                    self._module = importlib.import_module(self.module_name)
6760.1.1 by Jelmer Vernooij
Ignore DeprecationWarning/PendingDeprecationWarning during module probes. We can't do anything about these anyway.
186
                except ImportError:
187
                    return False
6760.1.3 by Jelmer Vernooij
Martin's review comments.
188
                return True
5642.4.3 by Vincent Ladeuil
Rework the fix taking mgz remarks into account and rebasing against trunk.
189
        else:
190
            self._module = module
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
191
            return True
192
193
    @property
194
    def module(self):
195
        if self.available():
196
            return self._module
197
        return None
198
199
    def feature_name(self):
200
        return self.module_name
201
202
6703.1.1 by Jelmer Vernooij
Add a ``PluginLoadedFeature``.
203
class PluginLoadedFeature(Feature):
204
    """Check whether a plugin with specific name is loaded.
205
206
    This is different from ModuleAvailableFeature, because
207
    plugins can be available but explicitly disabled
208
    (e.g. through BRZ_DISABLE_PLUGINS=blah).
209
210
    :ivar plugin_name: The name of the plugin
211
    """
212
213
    def __init__(self, plugin_name):
214
        super(PluginLoadedFeature, self).__init__()
215
        self.plugin_name = plugin_name
216
217
    def _probe(self):
6759.4.3 by Jelmer Vernooij
Avoid accessing global state.
218
        from breezy.plugin import get_loaded_plugin
219
        return (get_loaded_plugin(self.plugin_name) is not None)
6703.1.1 by Jelmer Vernooij
Add a ``PluginLoadedFeature``.
220
221
    @property
222
    def plugin(self):
6759.4.3 by Jelmer Vernooij
Avoid accessing global state.
223
        from breezy.plugin import get_loaded_plugin
224
        return get_loaded_plugin(self.plugin_name)
6703.1.1 by Jelmer Vernooij
Add a ``PluginLoadedFeature``.
225
226
    def feature_name(self):
6703.1.2 by Jelmer Vernooij
Change feature name to '... plugin'.
227
        return '%s plugin' % self.plugin_name
6703.1.1 by Jelmer Vernooij
Add a ``PluginLoadedFeature``.
228
229
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
230
class _HTTPSServerFeature(Feature):
231
    """Some tests want an https Server, check if one is available.
232
233
    Right now, the only way this is available is under python2.6 which provides
234
    an ssl module.
235
    """
236
237
    def _probe(self):
238
        try:
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
239
            import ssl  # noqa: F401
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
240
            return True
241
        except ImportError:
242
            return False
243
244
    def feature_name(self):
245
        return 'HTTPSServer'
246
247
248
HTTPSServerFeature = _HTTPSServerFeature()
249
250
251
class _ByteStringNamedFilesystem(Feature):
252
    """Is the filesystem based on bytes?"""
253
254
    def _probe(self):
255
        if os.name == "posix":
256
            return True
257
        return False
258
7143.15.2 by Jelmer Vernooij
Run autopep8.
259
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
260
ByteStringNamedFilesystem = _ByteStringNamedFilesystem()
261
262
263
class _UTF8Filesystem(Feature):
264
    """Is the filesystem UTF-8?"""
265
266
    def _probe(self):
267
        if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
268
            return True
269
        return False
270
7143.15.2 by Jelmer Vernooij
Run autopep8.
271
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
272
UTF8Filesystem = _UTF8Filesystem()
273
274
275
class _BreakinFeature(Feature):
276
    """Does this platform support the breakin feature?"""
277
278
    def _probe(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
279
        from breezy import breakin
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
280
        if breakin.determine_signal() is None:
281
            return False
282
        if sys.platform == 'win32':
283
            # Windows doesn't have os.kill, and we catch the SIGBREAK signal.
284
            # We trigger SIGBREAK via a Console api so we need ctypes to
285
            # access the function
286
            try:
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
287
                import ctypes  # noqa: F401
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
288
            except OSError:
289
                return False
290
        return True
291
292
    def feature_name(self):
293
        return "SIGQUIT or SIGBREAK w/ctypes on win32"
294
295
296
BreakinFeature = _BreakinFeature()
297
298
299
class _CaseInsCasePresFilenameFeature(Feature):
300
    """Is the file-system case insensitive, but case-preserving?"""
301
302
    def _probe(self):
303
        fileno, name = tempfile.mkstemp(prefix='MixedCase')
304
        try:
305
            # first check truly case-preserving for created files, then check
306
            # case insensitive when opening existing files.
307
            name = osutils.normpath(name)
308
            base, rel = osutils.split(name)
309
            found_rel = osutils.canonical_relpath(base, name)
7143.15.2 by Jelmer Vernooij
Run autopep8.
310
            return (found_rel == rel and
311
                    os.path.isfile(name.upper()) and
312
                    os.path.isfile(name.lower()))
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
313
        finally:
314
            os.close(fileno)
315
            os.remove(name)
316
317
    def feature_name(self):
318
        return "case-insensitive case-preserving filesystem"
319
7143.15.2 by Jelmer Vernooij
Run autopep8.
320
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
321
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
322
323
324
class _CaseInsensitiveFilesystemFeature(Feature):
325
    """Check if underlying filesystem is case-insensitive but *not* case
326
    preserving.
327
    """
328
    # Note that on Windows, Cygwin, MacOS etc, the file-systems are far
329
    # more likely to be case preserving, so this case is rare.
330
331
    def _probe(self):
332
        if CaseInsCasePresFilenameFeature.available():
333
            return False
334
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
335
        from breezy import tests
6280.1.1 by Martin Pool
Restore old name for bzrlib.tests.feature to unbreak bzr fastimport etc
336
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
337
        if tests.TestCaseWithMemoryTransport.TEST_ROOT is None:
338
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
339
            tests.TestCaseWithMemoryTransport.TEST_ROOT = root
340
        else:
341
            root = tests.TestCaseWithMemoryTransport.TEST_ROOT
342
        tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
7143.15.2 by Jelmer Vernooij
Run autopep8.
343
                               dir=root)
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
344
        name_a = osutils.pathjoin(tdir, 'a')
345
        name_A = osutils.pathjoin(tdir, 'A')
346
        os.mkdir(name_a)
347
        result = osutils.isdir(name_A)
6280.1.2 by Martin Pool
Fix NameError
348
        tests._rmtree_temp_dir(tdir)
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
349
        return result
350
351
    def feature_name(self):
352
        return 'case-insensitive filesystem'
353
7143.15.2 by Jelmer Vernooij
Run autopep8.
354
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
355
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
356
357
358
class _CaseSensitiveFilesystemFeature(Feature):
359
360
    def _probe(self):
361
        if CaseInsCasePresFilenameFeature.available():
362
            return False
363
        elif CaseInsensitiveFilesystemFeature.available():
364
            return False
365
        else:
366
            return True
367
368
    def feature_name(self):
369
        return 'case-sensitive filesystem'
370
7143.15.2 by Jelmer Vernooij
Run autopep8.
371
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
372
# new coding style is for feature instances to be lowercase
373
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
374
375
376
class _NotRunningAsRoot(Feature):
4797.70.1 by Vincent Ladeuil
Skip chmodbits dependent tests when running as root
377
378
    def _probe(self):
379
        try:
380
            uid = os.getuid()
381
        except AttributeError:
382
            # If there is no uid, chances are there is no root either
383
            return True
384
        return uid != 0
385
386
    def feature_name(self):
387
        return 'Not running as root'
388
389
390
not_running_as_root = _NotRunningAsRoot()
5448.5.9 by Vincent Ladeuil
Make the test depends on a feature so it's skipped if meliae is not installed
391
6760.1.2 by Jelmer Vernooij
Add note.
392
# Apport uses deprecated imp module on python3.
6760.1.1 by Jelmer Vernooij
Ignore DeprecationWarning/PendingDeprecationWarning during module probes. We can't do anything about these anyway.
393
apport = ModuleAvailableFeature(
394
    'apport.report',
395
    ignore_warnings=[DeprecationWarning, PendingDeprecationWarning])
6728.1.1 by Jelmer Vernooij
Use python-gpg rather than python-gpgme.
396
gpg = ModuleAvailableFeature('gpg')
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
397
lzma = ModuleAvailableFeature('lzma')
6091.2.2 by Max Bowsher
Per jam's review comments, get rid of features.meliae_feature, which is new in
398
meliae = ModuleAvailableFeature('meliae.scanner')
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
399
paramiko = ModuleAvailableFeature('paramiko')
400
pywintypes = ModuleAvailableFeature('pywintypes')
401
subunit = ModuleAvailableFeature('subunit')
5967.12.3 by Martin Pool
Unify duplicated UnicodeFilename and _PosixPermissionsFeature
402
testtools = ModuleAvailableFeature('testtools')
7167.1.4 by Jelmer Vernooij
Test for flake8.api.legacy.
403
flake8 = ModuleAvailableFeature('flake8.api.legacy')
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
404
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
405
lsprof_feature = ModuleAvailableFeature('breezy.lsprof')
7236.3.4 by Jelmer Vernooij
Add tests.
406
pkg_resources_feature = ModuleAvailableFeature('pkg_resources')
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
407
408
409
class _BackslashDirSeparatorFeature(Feature):
5241.2.1 by Robert Collins
Merge up from 2.0/2.1:
410
411
    def _probe(self):
412
        try:
413
            os.lstat(os.getcwd() + '\\')
414
        except OSError:
415
            return False
416
        else:
417
            return True
418
419
    def feature_name(self):
420
        return "Filesystem treats '\\' as a directory separator."
421
7143.15.2 by Jelmer Vernooij
Run autopep8.
422
5241.2.1 by Robert Collins
Merge up from 2.0/2.1:
423
backslashdir_feature = _BackslashDirSeparatorFeature()
424
425
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
426
class _ChownFeature(Feature):
5051.4.10 by Parth Malwankar
moved ChownFeature to tests/features.py
427
    """os.chown is supported"""
428
429
    def _probe(self):
430
        return os.name == 'posix' and hasattr(os, 'chown')
431
7143.15.2 by Jelmer Vernooij
Run autopep8.
432
5051.4.11 by Parth Malwankar
closed Martins review comments.
433
chown_feature = _ChownFeature()
5051.4.10 by Parth Malwankar
moved ChownFeature to tests/features.py
434
5147.5.20 by Martin von Gagern
Move ExecutableFeature class from bash_completion plugin to bzrlib tests.
435
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
436
class ExecutableFeature(Feature):
5147.5.20 by Martin von Gagern
Move ExecutableFeature class from bash_completion plugin to bzrlib tests.
437
    """Feature testing whether an executable of a given name is on the PATH."""
438
439
    def __init__(self, name):
440
        super(ExecutableFeature, self).__init__()
441
        self.name = name
5147.5.23 by Martin von Gagern
Have ExecutableFeature implement and use _probe.
442
        self._path = None
5147.5.20 by Martin von Gagern
Move ExecutableFeature class from bash_completion plugin to bzrlib tests.
443
444
    @property
445
    def path(self):
5147.5.23 by Martin von Gagern
Have ExecutableFeature implement and use _probe.
446
        # This is a property, so accessing path ensures _probe was called
447
        self.available()
448
        return self._path
5147.5.20 by Martin von Gagern
Move ExecutableFeature class from bash_completion plugin to bzrlib tests.
449
5147.5.23 by Martin von Gagern
Have ExecutableFeature implement and use _probe.
450
    def _probe(self):
5321.1.82 by Gordon Tyler
Changed ExecutableFeature to use osutils.find_executable_on_path.
451
        self._path = osutils.find_executable_on_path(self.name)
452
        return self._path is not None
5147.5.20 by Martin von Gagern
Move ExecutableFeature class from bash_completion plugin to bzrlib tests.
453
454
    def feature_name(self):
455
        return '%s executable' % self.name
5147.5.24 by Martin von Gagern
Move ExecutableFeature instances to tests.features module.
456
457
458
bash_feature = ExecutableFeature('bash')
6282.3.1 by Vincent Ladeuil
First cut at a working plugin to avoid conflicts in .po files by shelling out to msgmerge.
459
diff_feature = ExecutableFeature('diff')
5147.5.24 by Martin von Gagern
Move ExecutableFeature instances to tests.features module.
460
sed_feature = ExecutableFeature('sed')
6282.3.1 by Vincent Ladeuil
First cut at a working plugin to avoid conflicts in .po files by shelling out to msgmerge.
461
msgmerge_feature = ExecutableFeature('msgmerge')
5609.47.1 by Alexander Belchenko
Win32Feature
462
463
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
464
class _PosixPermissionsFeature(Feature):
465
466
    def _probe(self):
467
        def has_perms():
468
            # Create temporary file and check if specified perms are
469
            # maintained.
470
            write_perms = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
471
            f = tempfile.mkstemp(prefix='bzr_perms_chk_')
472
            fd, name = f
473
            os.close(fd)
6344.1.1 by Martin Packman
Merge 2.4 into bzr.dev
474
            osutils.chmod_if_possible(name, write_perms)
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
475
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
476
            read_perms = os.stat(name).st_mode & 0o777
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
477
            os.unlink(name)
478
            return (write_perms == read_perms)
479
480
        return (os.name == 'posix') and has_perms()
481
482
    def feature_name(self):
483
        return 'POSIX permissions support'
484
485
486
posix_permissions_feature = _PosixPermissionsFeature()
487
488
489
class _StraceFeature(Feature):
490
491
    def _probe(self):
492
        try:
493
            proc = subprocess.Popen(['strace'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
494
                                    stderr=subprocess.PIPE,
495
                                    stdout=subprocess.PIPE)
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
496
            proc.communicate()
497
            return True
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
498
        except OSError as e:
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
499
            import errno
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
500
            if e.errno == errno.ENOENT:
501
                # strace is not installed
502
                return False
503
            else:
504
                raise
505
506
    def feature_name(self):
507
        return 'strace'
508
509
510
strace_feature = _StraceFeature()
511
512
513
class _AttribFeature(Feature):
514
515
    def _probe(self):
516
        if (sys.platform not in ('cygwin', 'win32')):
517
            return False
518
        try:
519
            proc = subprocess.Popen(['attrib', '.'], stdout=subprocess.PIPE)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
520
        except OSError:
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
521
            return False
522
        return (0 == proc.wait())
523
524
    def feature_name(self):
525
        return 'attrib Windows command-line tool'
526
527
528
AttribFeature = _AttribFeature()
5967.12.2 by Martin Pool
Move all features to bzrlib.tests.features in 2.5
529
530
5967.12.3 by Martin Pool
Unify duplicated UnicodeFilename and _PosixPermissionsFeature
531
class Win32Feature(Feature):
5609.47.1 by Alexander Belchenko
Win32Feature
532
    """Feature testing whether we're running selftest on Windows
5609.47.4 by Alexander Belchenko
fixed typo
533
    or Windows-like platform.
5609.47.1 by Alexander Belchenko
Win32Feature
534
    """
535
536
    def _probe(self):
537
        return sys.platform == 'win32'
538
539
    def feature_name(self):
540
        return "win32 platform"
541
5967.12.4 by Martin Pool
Support (but deprecated) old feature names
542
5609.47.1 by Alexander Belchenko
Win32Feature
543
win32_feature = Win32Feature()
6478.3.1 by Jelmer Vernooij
Add backslashfilenamefeature.
544
545
546
class _BackslashFilenameFeature(Feature):
547
    """Does the filesystem support backslashes in filenames?"""
548
549
    def _probe(self):
6478.3.4 by Jelmer Vernooij
Merge trunk.
550
6478.3.1 by Jelmer Vernooij
Add backslashfilenamefeature.
551
        try:
552
            fileno, name = tempfile.mkstemp(prefix='bzr\\prefix')
553
        except (IOError, OSError):
554
            return False
555
        else:
556
            try:
557
                os.stat(name)
558
            except (IOError, OSError):
559
                # mkstemp succeeded but the file wasn't actually created
560
                return False
561
            os.close(fileno)
562
            os.remove(name)
563
            return True
564
6478.3.4 by Jelmer Vernooij
Merge trunk.
565
6478.3.1 by Jelmer Vernooij
Add backslashfilenamefeature.
566
BackslashFilenameFeature = _BackslashFilenameFeature()
7290.11.4 by Jelmer Vernooij
Check whether git-remote-bzr actually exists.
567
568
569
class PathFeature(Feature):
570
    """Feature testing whether a particular path exists."""
571
572
    def __init__(self, path):
573
        super(PathFeature, self).__init__()
574
        self.path = path
575
576
    def _probe(self):
577
        return os.path.exists(self.path)
578
579
    def feature_name(self):
580
        return "%s exists" % self.path