tests/hghave.py
changeset 1103 9459951761fb
parent 1102 51afb47e2399
child 1105 9b2932ca75fd
equal deleted inserted replaced
1097:7f458d071b49 1103:9459951761fb
       
     1 import os, stat, socket
       
     2 import re
       
     3 import sys
       
     4 import tempfile
       
     5 
       
     6 tempprefix = 'hg-hghave-'
       
     7 
       
     8 def matchoutput(cmd, regexp, ignorestatus=False):
       
     9     """Return True if cmd executes successfully and its output
       
    10     is matched by the supplied regular expression.
       
    11     """
       
    12     r = re.compile(regexp)
       
    13     fh = os.popen(cmd)
       
    14     s = fh.read()
       
    15     try:
       
    16         ret = fh.close()
       
    17     except IOError:
       
    18         # Happen in Windows test environment
       
    19         ret = 1
       
    20     return (ignorestatus or ret is None) and r.search(s)
       
    21 
       
    22 def has_baz():
       
    23     return matchoutput('baz --version 2>&1', r'baz Bazaar version')
       
    24 
       
    25 def has_bzr():
       
    26     try:
       
    27         import bzrlib
       
    28         return bzrlib.__doc__ is not None
       
    29     except ImportError:
       
    30         return False
       
    31 
       
    32 def has_bzr114():
       
    33     try:
       
    34         import bzrlib
       
    35         return (bzrlib.__doc__ is not None
       
    36                 and bzrlib.version_info[:2] >= (1, 14))
       
    37     except ImportError:
       
    38         return False
       
    39 
       
    40 def has_cvs():
       
    41     re = r'Concurrent Versions System.*?server'
       
    42     return matchoutput('cvs --version 2>&1', re) and not has_msys()
       
    43 
       
    44 def has_darcs():
       
    45     return matchoutput('darcs --version', r'2\.[2-9]', True)
       
    46 
       
    47 def has_mtn():
       
    48     return matchoutput('mtn --version', r'monotone', True) and not matchoutput(
       
    49         'mtn --version', r'monotone 0\.', True)
       
    50 
       
    51 def has_eol_in_paths():
       
    52     try:
       
    53         fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
       
    54         os.close(fd)
       
    55         os.remove(path)
       
    56         return True
       
    57     except (IOError, OSError):
       
    58         return False
       
    59 
       
    60 def has_executablebit():
       
    61     try:
       
    62         EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
       
    63         fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
       
    64         try:
       
    65             os.close(fh)
       
    66             m = os.stat(fn).st_mode & 0777
       
    67             new_file_has_exec = m & EXECFLAGS
       
    68             os.chmod(fn, m ^ EXECFLAGS)
       
    69             exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0777) == m)
       
    70         finally:
       
    71             os.unlink(fn)
       
    72     except (IOError, OSError):
       
    73         # we don't care, the user probably won't be able to commit anyway
       
    74         return False
       
    75     return not (new_file_has_exec or exec_flags_cannot_flip)
       
    76 
       
    77 def has_icasefs():
       
    78     # Stolen from mercurial.util
       
    79     fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
       
    80     os.close(fd)
       
    81     try:
       
    82         s1 = os.stat(path)
       
    83         d, b = os.path.split(path)
       
    84         p2 = os.path.join(d, b.upper())
       
    85         if path == p2:
       
    86             p2 = os.path.join(d, b.lower())
       
    87         try:
       
    88             s2 = os.stat(p2)
       
    89             return s2 == s1
       
    90         except OSError:
       
    91             return False
       
    92     finally:
       
    93         os.remove(path)
       
    94 
       
    95 def has_inotify():
       
    96     try:
       
    97         import hgext.inotify.linux.watcher
       
    98     except ImportError:
       
    99         return False
       
   100     name = tempfile.mktemp(dir='.', prefix=tempprefix)
       
   101     sock = socket.socket(socket.AF_UNIX)
       
   102     try:
       
   103         sock.bind(name)
       
   104     except socket.error, err:
       
   105         return False
       
   106     sock.close()
       
   107     os.unlink(name)
       
   108     return True
       
   109 
       
   110 def has_fifo():
       
   111     if getattr(os, "mkfifo", None) is None:
       
   112         return False
       
   113     name = tempfile.mktemp(dir='.', prefix=tempprefix)
       
   114     try:
       
   115         os.mkfifo(name)
       
   116         os.unlink(name)
       
   117         return True
       
   118     except OSError:
       
   119         return False
       
   120 
       
   121 def has_cacheable_fs():
       
   122     from mercurial import util
       
   123 
       
   124     fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
       
   125     os.close(fd)
       
   126     try:
       
   127         return util.cachestat(path).cacheable()
       
   128     finally:
       
   129         os.remove(path)
       
   130 
       
   131 def has_lsprof():
       
   132     try:
       
   133         import _lsprof
       
   134         return True
       
   135     except ImportError:
       
   136         return False
       
   137 
       
   138 def has_gettext():
       
   139     return matchoutput('msgfmt --version', 'GNU gettext-tools')
       
   140 
       
   141 def has_git():
       
   142     return matchoutput('git --version 2>&1', r'^git version')
       
   143 
       
   144 def has_docutils():
       
   145     try:
       
   146         from docutils.core import publish_cmdline
       
   147         return True
       
   148     except ImportError:
       
   149         return False
       
   150 
       
   151 def getsvnversion():
       
   152     m = matchoutput('svn --version 2>&1', r'^svn,\s+version\s+(\d+)\.(\d+)')
       
   153     if not m:
       
   154         return (0, 0)
       
   155     return (int(m.group(1)), int(m.group(2)))
       
   156 
       
   157 def has_svn15():
       
   158     return getsvnversion() >= (1, 5)
       
   159 
       
   160 def has_svn13():
       
   161     return getsvnversion() >= (1, 3)
       
   162 
       
   163 def has_svn():
       
   164     return matchoutput('svn --version 2>&1', r'^svn, version') and \
       
   165         matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
       
   166 
       
   167 def has_svn_bindings():
       
   168     try:
       
   169         import svn.core
       
   170         version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
       
   171         if version < (1, 4):
       
   172             return False
       
   173         return True
       
   174     except ImportError:
       
   175         return False
       
   176 
       
   177 def has_p4():
       
   178     return (matchoutput('p4 -V', r'Rev\. P4/') and
       
   179             matchoutput('p4d -V', r'Rev\. P4D/'))
       
   180 
       
   181 def has_symlink():
       
   182     if getattr(os, "symlink", None) is None:
       
   183         return False
       
   184     name = tempfile.mktemp(dir='.', prefix=tempprefix)
       
   185     try:
       
   186         os.symlink(".", name)
       
   187         os.unlink(name)
       
   188         return True
       
   189     except (OSError, AttributeError):
       
   190         return False
       
   191 
       
   192 def has_hardlink():
       
   193     from mercurial import util
       
   194     fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
       
   195     os.close(fh)
       
   196     name = tempfile.mktemp(dir='.', prefix=tempprefix)
       
   197     try:
       
   198         try:
       
   199             util.oslink(fn, name)
       
   200             os.unlink(name)
       
   201             return True
       
   202         except OSError:
       
   203             return False
       
   204     finally:
       
   205         os.unlink(fn)
       
   206 
       
   207 def has_tla():
       
   208     return matchoutput('tla --version 2>&1', r'The GNU Arch Revision')
       
   209 
       
   210 def has_gpg():
       
   211     return matchoutput('gpg --version 2>&1', r'GnuPG')
       
   212 
       
   213 def has_unix_permissions():
       
   214     d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
       
   215     try:
       
   216         fname = os.path.join(d, 'foo')
       
   217         for umask in (077, 007, 022):
       
   218             os.umask(umask)
       
   219             f = open(fname, 'w')
       
   220             f.close()
       
   221             mode = os.stat(fname).st_mode
       
   222             os.unlink(fname)
       
   223             if mode & 0777 != ~umask & 0666:
       
   224                 return False
       
   225         return True
       
   226     finally:
       
   227         os.rmdir(d)
       
   228 
       
   229 def has_pyflakes():
       
   230     return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
       
   231                        r"<stdin>:1: 're' imported but unused",
       
   232                        True)
       
   233 
       
   234 def has_pygments():
       
   235     try:
       
   236         import pygments
       
   237         return True
       
   238     except ImportError:
       
   239         return False
       
   240 
       
   241 def has_outer_repo():
       
   242     return matchoutput('hg root 2>&1', r'')
       
   243 
       
   244 def has_ssl():
       
   245     try:
       
   246         import ssl
       
   247         import OpenSSL
       
   248         OpenSSL.SSL.Context
       
   249         return True
       
   250     except ImportError:
       
   251         return False
       
   252 
       
   253 def has_windows():
       
   254     return os.name == 'nt'
       
   255 
       
   256 def has_system_sh():
       
   257     return os.name != 'nt'
       
   258 
       
   259 def has_serve():
       
   260     return os.name != 'nt' # gross approximation
       
   261 
       
   262 def has_tic():
       
   263     return matchoutput('test -x "`which tic`"', '')
       
   264 
       
   265 def has_msys():
       
   266     return os.getenv('MSYSTEM')
       
   267 
       
   268 checks = {
       
   269     "true": (lambda: True, "yak shaving"),
       
   270     "false": (lambda: False, "nail clipper"),
       
   271     "baz": (has_baz, "GNU Arch baz client"),
       
   272     "bzr": (has_bzr, "Canonical's Bazaar client"),
       
   273     "bzr114": (has_bzr114, "Canonical's Bazaar client >= 1.14"),
       
   274     "cacheable": (has_cacheable_fs, "cacheable filesystem"),
       
   275     "cvs": (has_cvs, "cvs client/server"),
       
   276     "darcs": (has_darcs, "darcs client"),
       
   277     "docutils": (has_docutils, "Docutils text processing library"),
       
   278     "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"),
       
   279     "execbit": (has_executablebit, "executable bit"),
       
   280     "fifo": (has_fifo, "named pipes"),
       
   281     "gettext": (has_gettext, "GNU Gettext (msgfmt)"),
       
   282     "git": (has_git, "git command line client"),
       
   283     "gpg": (has_gpg, "gpg client"),
       
   284     "hardlink": (has_hardlink, "hardlinks"),
       
   285     "icasefs": (has_icasefs, "case insensitive file system"),
       
   286     "inotify": (has_inotify, "inotify extension support"),
       
   287     "lsprof": (has_lsprof, "python lsprof module"),
       
   288     "mtn": (has_mtn, "monotone client (>= 1.0)"),
       
   289     "outer-repo": (has_outer_repo, "outer repo"),
       
   290     "p4": (has_p4, "Perforce server and client"),
       
   291     "pyflakes": (has_pyflakes, "Pyflakes python linter"),
       
   292     "pygments": (has_pygments, "Pygments source highlighting library"),
       
   293     "serve": (has_serve, "platform and python can manage 'hg serve -d'"),
       
   294     "ssl": (has_ssl, "python >= 2.6 ssl module and python OpenSSL"),
       
   295     "svn": (has_svn, "subversion client and admin tools"),
       
   296     "svn13": (has_svn13, "subversion client and admin tools >= 1.3"),
       
   297     "svn15": (has_svn15, "subversion client and admin tools >= 1.5"),
       
   298     "svn-bindings": (has_svn_bindings, "subversion python bindings"),
       
   299     "symlink": (has_symlink, "symbolic links"),
       
   300     "system-sh": (has_system_sh, "system() uses sh"),
       
   301     "tic": (has_tic, "terminfo compiler"),
       
   302     "tla": (has_tla, "GNU Arch tla client"),
       
   303     "unix-permissions": (has_unix_permissions, "unix-style permissions"),
       
   304     "windows": (has_windows, "Windows"),
       
   305     "msys": (has_msys, "Windows with MSYS"),
       
   306 }