Merge remote-tracking branch 'kovidgoyal/fix-482' into develop
Conflicts: powerline/lib/vcs/git.py
This commit is contained in:
commit
afe415a398
|
@ -92,6 +92,10 @@ class INotifyWatch(INotify):
|
||||||
self.watches[path] = wd
|
self.watches[path] = wd
|
||||||
self.modified[path] = False
|
self.modified[path] = False
|
||||||
|
|
||||||
|
def is_watched(self, path):
|
||||||
|
with self.lock:
|
||||||
|
return realpath(path) in self.watches
|
||||||
|
|
||||||
def __call__(self, path):
|
def __call__(self, path):
|
||||||
''' Return True if path has been modified since the last call. Can
|
''' Return True if path has been modified since the last call. Can
|
||||||
raise OSError if the path does not exist. '''
|
raise OSError if the path does not exist. '''
|
||||||
|
@ -141,6 +145,10 @@ class StatWatch(object):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.watches.pop(path, None)
|
self.watches.pop(path, None)
|
||||||
|
|
||||||
|
def is_watched(self, path):
|
||||||
|
with self.lock:
|
||||||
|
return realpath(path) in self.watches
|
||||||
|
|
||||||
def __call__(self, path):
|
def __call__(self, path):
|
||||||
path = realpath(path)
|
path = realpath(path)
|
||||||
with self.lock:
|
with self.lock:
|
||||||
|
|
|
@ -31,11 +31,12 @@ class INotifyTreeWatcher(INotify):
|
||||||
|
|
||||||
is_dummy = False
|
is_dummy = False
|
||||||
|
|
||||||
def __init__(self, basedir):
|
def __init__(self, basedir, ignore_event=None):
|
||||||
super(INotifyTreeWatcher, self).__init__()
|
super(INotifyTreeWatcher, self).__init__()
|
||||||
self.basedir = realpath(basedir)
|
self.basedir = realpath(basedir)
|
||||||
self.watch_tree()
|
self.watch_tree()
|
||||||
self.modified = True
|
self.modified = True
|
||||||
|
self.ignore_event = (lambda path, name: False) if ignore_event is None else ignore_event
|
||||||
|
|
||||||
def watch_tree(self):
|
def watch_tree(self):
|
||||||
self.watched_dirs = {}
|
self.watched_dirs = {}
|
||||||
|
@ -93,7 +94,7 @@ class INotifyTreeWatcher(INotify):
|
||||||
|
|
||||||
self.MODIFY | self.CREATE | self.DELETE |
|
self.MODIFY | self.CREATE | self.DELETE |
|
||||||
self.MOVE_SELF | self.MOVED_FROM | self.MOVED_TO |
|
self.MOVE_SELF | self.MOVED_FROM | self.MOVED_TO |
|
||||||
self.ATTRIB | self.MOVE_SELF | self.DELETE_SELF)
|
self.ATTRIB | self.DELETE_SELF)
|
||||||
if wd == -1:
|
if wd == -1:
|
||||||
eno = ctypes.get_errno()
|
eno = ctypes.get_errno()
|
||||||
if eno == errno.ENOTDIR:
|
if eno == errno.ENOTDIR:
|
||||||
|
@ -112,7 +113,7 @@ class INotifyTreeWatcher(INotify):
|
||||||
return
|
return
|
||||||
path = self.watched_rmap.get(wd, None)
|
path = self.watched_rmap.get(wd, None)
|
||||||
if path is not None:
|
if path is not None:
|
||||||
self.modified = True
|
self.modified = not self.ignore_event(path, name)
|
||||||
if mask & self.CREATE:
|
if mask & self.CREATE:
|
||||||
# A new sub-directory might have been created, monitor it.
|
# A new sub-directory might have been created, monitor it.
|
||||||
try:
|
try:
|
||||||
|
@ -152,10 +153,10 @@ class TreeWatcher(object):
|
||||||
self.last_query_times = {}
|
self.last_query_times = {}
|
||||||
self.expire_time = expire_time * 60
|
self.expire_time = expire_time * 60
|
||||||
|
|
||||||
def watch(self, path, logger=None):
|
def watch(self, path, logger=None, ignore_event=None):
|
||||||
path = realpath(path)
|
path = realpath(path)
|
||||||
try:
|
try:
|
||||||
w = INotifyTreeWatcher(path)
|
w = INotifyTreeWatcher(path, ignore_event=ignore_event)
|
||||||
except (INotifyError, DirTooLarge) as e:
|
except (INotifyError, DirTooLarge) as e:
|
||||||
if logger is not None:
|
if logger is not None:
|
||||||
logger.warn('Failed to watch path: {0} with error: {1}'.format(path, e))
|
logger.warn('Failed to watch path: {0} with error: {1}'.format(path, e))
|
||||||
|
@ -176,14 +177,14 @@ class TreeWatcher(object):
|
||||||
for path in pop:
|
for path in pop:
|
||||||
del self.last_query_times[path]
|
del self.last_query_times[path]
|
||||||
|
|
||||||
def __call__(self, path, logger=None):
|
def __call__(self, path, logger=None, ignore_event=None):
|
||||||
path = realpath(path)
|
path = realpath(path)
|
||||||
self.expire_old_queries()
|
self.expire_old_queries()
|
||||||
self.last_query_times[path] = monotonic()
|
self.last_query_times[path] = monotonic()
|
||||||
w = self.watches.get(path, None)
|
w = self.watches.get(path, None)
|
||||||
if w is None:
|
if w is None:
|
||||||
try:
|
try:
|
||||||
self.watch(path)
|
self.watch(path, logger=logger, ignore_event=ignore_event)
|
||||||
except NoSuchDir:
|
except NoSuchDir:
|
||||||
pass
|
pass
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -39,8 +39,10 @@ def get_branch_name(directory, config_file, get_func):
|
||||||
global branch_name_cache
|
global branch_name_cache
|
||||||
with branch_lock:
|
with branch_lock:
|
||||||
# Check if the repo directory was moved/deleted
|
# Check if the repo directory was moved/deleted
|
||||||
|
fw = file_watcher()
|
||||||
|
is_watched = fw.is_watched(directory)
|
||||||
try:
|
try:
|
||||||
changed = file_watcher()(directory)
|
changed = fw(directory)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if getattr(e, 'errno', None) != errno.ENOENT:
|
if getattr(e, 'errno', None) != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
|
@ -48,12 +50,13 @@ def get_branch_name(directory, config_file, get_func):
|
||||||
if changed:
|
if changed:
|
||||||
branch_name_cache.pop(config_file, None)
|
branch_name_cache.pop(config_file, None)
|
||||||
# Remove the watches for this repo
|
# Remove the watches for this repo
|
||||||
file_watcher().unwatch(directory)
|
if is_watched:
|
||||||
file_watcher().unwatch(config_file)
|
fw.unwatch(directory)
|
||||||
|
fw.unwatch(config_file)
|
||||||
else:
|
else:
|
||||||
# Check if the config file has changed
|
# Check if the config file has changed
|
||||||
try:
|
try:
|
||||||
changed = file_watcher()(config_file)
|
changed = fw(config_file)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if getattr(e, 'errno', None) != errno.ENOENT:
|
if getattr(e, 'errno', None) != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
|
@ -176,7 +179,7 @@ class TreeStatusCache(dict):
|
||||||
def __call__(self, repo, logger):
|
def __call__(self, repo, logger):
|
||||||
key = repo.directory
|
key = repo.directory
|
||||||
try:
|
try:
|
||||||
if self.tw(key):
|
if self.tw(key, logger=logger, ignore_event=getattr(repo, 'ignore_event', None)):
|
||||||
self.pop(key, None)
|
self.pop(key, None)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
logger.warn('Failed to check %s for changes, with error: %s'% key, e)
|
logger.warn('Failed to check %s for changes, with error: %s'% key, e)
|
||||||
|
@ -209,7 +212,7 @@ def debug():
|
||||||
''' To use run python -c "from powerline.lib.vcs import debug; debug()" some_file_to_watch '''
|
''' To use run python -c "from powerline.lib.vcs import debug; debug()" some_file_to_watch '''
|
||||||
import sys
|
import sys
|
||||||
dest = sys.argv[-1]
|
dest = sys.argv[-1]
|
||||||
repo = guess(dest)
|
repo = guess(os.path.abspath(dest))
|
||||||
if repo is None:
|
if repo is None:
|
||||||
print ('%s is not a recognized vcs repo' % dest)
|
print ('%s is not a recognized vcs repo' % dest)
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
@ -224,3 +227,5 @@ def debug():
|
||||||
raw_input('Press Enter to check again: ')
|
raw_input('Press Enter to check again: ')
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
except EOFError:
|
||||||
|
pass
|
||||||
|
|
|
@ -36,19 +36,29 @@ def do_status(directory, path, func):
|
||||||
with open(gitd, 'rb') as f:
|
with open(gitd, 'rb') as f:
|
||||||
raw = f.read().partition(b':')[2].strip()
|
raw = f.read().partition(b':')[2].strip()
|
||||||
gitd = os.path.abspath(os.path.join(directory, raw))
|
gitd = os.path.abspath(os.path.join(directory, raw))
|
||||||
return get_file_status(directory, os.path.join(gitd, 'index'),
|
# We need HEAD as without it using fugitive to commit causes the
|
||||||
path, '.gitignore', func, extra_ignore_files=(os.path.join(gitd, 'info/exclude'),))
|
# current file's status (and only the current file) to not be updated
|
||||||
|
# for some reason I cannot be bothered to figure out.
|
||||||
|
return get_file_status(
|
||||||
|
directory, os.path.join(gitd, 'index'),
|
||||||
|
path, '.gitignore', func, extra_ignore_files=tuple(os.path.join(gitd, x) for x in ('logs/HEAD', 'info/exclude')))
|
||||||
return func(directory, path)
|
return func(directory, path)
|
||||||
|
|
||||||
|
def ignore_event(path, name):
|
||||||
|
# Ignore changes to the index.lock file, since they happen frequently and
|
||||||
|
# dont indicate an actual change in the working tree status
|
||||||
|
return False
|
||||||
|
return path.endswith('.git') and name == 'index.lock'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pygit2 as git
|
import pygit2 as git
|
||||||
|
|
||||||
class Repository(object):
|
class Repository(object):
|
||||||
__slots__ = ('directory')
|
__slots__ = ('directory', 'ignore_event')
|
||||||
|
|
||||||
def __init__(self, directory):
|
def __init__(self, directory):
|
||||||
self.directory = os.path.abspath(directory)
|
self.directory = os.path.abspath(directory)
|
||||||
|
self.ignore_event = ignore_event
|
||||||
|
|
||||||
def do_status(self, directory, path):
|
def do_status(self, directory, path):
|
||||||
if path:
|
if path:
|
||||||
|
@ -131,10 +141,11 @@ except ImportError:
|
||||||
yield line[:-1].decode('utf-8')
|
yield line[:-1].decode('utf-8')
|
||||||
|
|
||||||
class Repository(object):
|
class Repository(object):
|
||||||
__slots__ = ('directory',)
|
__slots__ = ('directory', 'ignore_event')
|
||||||
|
|
||||||
def __init__(self, directory):
|
def __init__(self, directory):
|
||||||
self.directory = os.path.abspath(directory)
|
self.directory = os.path.abspath(directory)
|
||||||
|
self.ignore_event = ignore_event
|
||||||
|
|
||||||
def _gitcmd(self, directory, *args):
|
def _gitcmd(self, directory, *args):
|
||||||
return readlines(('git',) + args, directory)
|
return readlines(('git',) + args, directory)
|
||||||
|
|
Loading…
Reference in New Issue