Make CommandsCache play well with Windows

This commit is contained in:
Burak Yigit Kaya 2016-06-24 01:00:42 +03:00
parent e2dece482c
commit ce93945de3
2 changed files with 30 additions and 18 deletions

View file

@ -823,31 +823,27 @@ def _yield_executables(directory, name):
def locate_binary(name): def locate_binary(name):
"""Locates an executable on the file system.""" """Locates an executable on the file system."""
cc = builtins.__xonsh_commands_cache__
if ON_WINDOWS: if ON_WINDOWS:
# Windows users expect to be able to execute files in the same # Windows users expect to be able to execute files in the same
# directory without `./` # directory without `./`
cwd = _get_cwd() cwd = _get_cwd()
if os.path.isfile(name): if os.path.isfile(name):
return os.path.abspath(os.path.relpath(name, cwd)) return os.path.abspath(os.path.relpath(name, cwd))
exts = builtins.__xonsh_env__['PATHEXT'] exts = builtins.__xonsh_env__['PATHEXT']
for ext in exts: for ext in exts:
namext = name + ext namext = name + ext
if os.path.isfile(namext): if os.path.isfile(namext):
return os.path.abspath(os.path.relpath(namext, cwd)) return os.path.abspath(os.path.relpath(namext, cwd))
elif os.path.isfile(name) and name != os.path.basename(name):
return name if name in cc:
cc = builtins.__xonsh_commands_cache__
if ON_WINDOWS:
upname = name.upper()
if upname in cc:
return cc.lazyget(upname)[0]
for ext in exts:
upnamext = upname + ext
if cc.lazyin(upnamext):
return cc.lazyget(upnamext)[0]
elif name in cc:
# can be lazy here since we know name is already available # can be lazy here since we know name is already available
return cc.lazyget(name)[0] return cc.lazyget(name)[0]
elif os.path.isfile(name) and name != os.path.basename(name):
return name
def get_git_branch(): def get_git_branch():
@ -1037,7 +1033,7 @@ def dirty_working_directory(cwd=None):
def branch_color(): def branch_color():
"""Return red if the current branch is dirty, yellow if the dirtiness can """Return red if the current branch is dirty, yellow if the dirtiness can
not be determined, and green if it clean. Thes are bold, intesnse colors not be determined, and green if it clean. These are bold, intense colors
for the foreground. for the foreground.
""" """
dwd = dirty_working_directory() dwd = dirty_working_directory()

View file

@ -1564,8 +1564,18 @@ class CommandsCache(abc.Mapping):
self._alias_checksum = None self._alias_checksum = None
self._path_mtime = -1 self._path_mtime = -1
def __get_possible_names(self, key):
if ON_WINDOWS:
return {
name + ext
for ext in ([''] + builtins.__xonsh_env__['PATHEXT'])
for name in (key, key.upper())
}
else:
return { key, }
def __contains__(self, key): def __contains__(self, key):
return key in self.all_commands return bool(self.__get_possible_names(key) & self.all_commands.keys())
def __iter__(self): def __iter__(self):
return iter(self.all_commands) return iter(self.all_commands)
@ -1574,7 +1584,8 @@ class CommandsCache(abc.Mapping):
return len(self.all_commands) return len(self.all_commands)
def __getitem__(self, key): def __getitem__(self, key):
return self.all_commands[key] possibilities = self.__get_possible_names(key)
return self.all_commands[next(possibilities & self.all_commands.keys())]
@property @property
def all_commands(self): def all_commands(self):
@ -1599,6 +1610,7 @@ class CommandsCache(abc.Mapping):
self._path_mtime = max_mtime self._path_mtime = max_mtime
if cache_valid: if cache_valid:
return self._cmds_cache return self._cmds_cache
allcmds = {} allcmds = {}
for path in reversed(paths): for path in reversed(paths):
# iterate backwards so that entries at the front of PATH overwrite # iterate backwards so that entries at the front of PATH overwrite
@ -1606,6 +1618,7 @@ class CommandsCache(abc.Mapping):
for cmd in executables_in(path): for cmd in executables_in(path):
key = cmd.upper() if ON_WINDOWS else cmd key = cmd.upper() if ON_WINDOWS else cmd
allcmds[key] = (os.path.join(path, cmd), cmd in alss) allcmds[key] = (os.path.join(path, cmd), cmd in alss)
only_alias = (None, True) only_alias = (None, True)
for cmd in alss: for cmd in alss:
if cmd not in allcmds: if cmd not in allcmds:
@ -1613,12 +1626,13 @@ class CommandsCache(abc.Mapping):
self._cmds_cache = allcmds self._cmds_cache = allcmds
return allcmds return allcmds
def lazyin(self, value): def lazyin(self, key):
"""Checks if the value is in the current cache without the potential to """Checks if the value is in the current cache without the potential to
update the cache. It just says whether the value is known *now*. This update the cache. It just says whether the value is known *now*. This
may not reflect precisely what is on the $PATH. may not reflect precisely what is on the $PATH.
""" """
return value in self._cmds_cache
return bool(self.__get_possible_names(key) & self._cmds_cache.keys())
def lazyiter(self): def lazyiter(self):
"""Returns an iterator over the current cache contents without the """Returns an iterator over the current cache contents without the
@ -1636,7 +1650,9 @@ class CommandsCache(abc.Mapping):
def lazyget(self, key, default=None): def lazyget(self, key, default=None):
"""A lazy value getter.""" """A lazy value getter."""
return self._cmds_cache.get(key, default) possibilities = self.__get_possible_names(key)
matches = possibilities & self._cmds_cache.keys()
return self._cmds_cache[matches.pop()] if matches else default
WINDOWS_DRIVE_MATCHER = LazyObject(lambda: re.compile(r'^\w:'), WINDOWS_DRIVE_MATCHER = LazyObject(lambda: re.compile(r'^\w:'),