Merge pull request #667 from kovidgoyal/fix-git-branch-name

Fix git branch name sometimes getting stuck with inotify
This commit is contained in:
ZyX-I 2014-01-17 10:20:25 -08:00
commit 2a525ae4f8
3 changed files with 38 additions and 4 deletions

View File

@ -53,6 +53,23 @@ class INotifyWatch(INotify):
self.watches.pop(path, None) self.watches.pop(path, None)
self.modified.pop(path, None) self.modified.pop(path, None)
self.last_query.pop(path, None) self.last_query.pop(path, None)
else:
if mask & self.ATTRIB:
# The watched file could have had its inode changed, in
# which case we will not get any more events for this
# file, so re-register the watch. For example by some
# other file being renamed as this file.
try:
self.unwatch(path)
except OSError:
pass
try:
self.watch(path)
except OSError as e:
if getattr(e, 'errno', None) != errno.ENOENT:
raise
else:
self.modified[path] = True
else: else:
self.modified[path] = True self.modified[path] = True

View File

@ -33,6 +33,15 @@ def file_watcher():
_file_watcher = create_file_watcher() _file_watcher = create_file_watcher()
return _file_watcher return _file_watcher
_branch_watcher = None
def branch_watcher():
global _branch_watcher
if _branch_watcher is None:
from powerline.lib.file_watcher import create_file_watcher
_branch_watcher = create_file_watcher()
return _branch_watcher
branch_name_cache = {} branch_name_cache = {}
branch_lock = Lock() branch_lock = Lock()
file_status_lock = Lock() file_status_lock = Lock()
@ -41,7 +50,7 @@ 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() fw = branch_watcher()
is_watched = fw.is_watched(directory) is_watched = fw.is_watched(directory)
try: try:
changed = fw(directory) changed = fw(directory)

View File

@ -54,9 +54,10 @@ class TestFilesystemWatchers(TestCase):
w = create_file_watcher(use_stat=False) w = create_file_watcher(use_stat=False)
if w.is_stat_based: if w.is_stat_based:
raise SkipTest('This test is not suitable for a stat based file watcher') raise SkipTest('This test is not suitable for a stat based file watcher')
f1, f2 = os.path.join(INOTIFY_DIR, 'file1'), os.path.join(INOTIFY_DIR, 'file2') f1, f2, f3 = map(lambda x: os.path.join(INOTIFY_DIR, 'file%d' % x), (1, 2, 3))
with open(f1, 'wb'): with open(f1, 'wb'):
with open(f2, 'wb'): with open(f2, 'wb'):
with open(f3, 'wb'):
pass pass
ne = os.path.join(INOTIFY_DIR, 'notexists') ne = os.path.join(INOTIFY_DIR, 'notexists')
self.assertRaises(OSError, w, ne) self.assertRaises(OSError, w, ne)
@ -85,6 +86,13 @@ class TestFilesystemWatchers(TestCase):
# Check that deleting a file registers as a change # Check that deleting a file registers as a change
os.unlink(f1) os.unlink(f1)
self.do_test_for_change(w, f1) self.do_test_for_change(w, f1)
# Test that changing the inode of a file does not cause it to stop
# being watched
os.rename(f3, f2)
self.do_test_for_change(w, f2)
self.assertFalse(w(f2), 'Spurious change detected')
os.utime(f2, None)
self.do_test_for_change(w, f2)
def test_tree_watcher(self): def test_tree_watcher(self):
from powerline.lib.tree_watcher import TreeWatcher from powerline.lib.tree_watcher import TreeWatcher