Browse Source

Drop inotify-based watch that was always flaky. Fixes #886

Jelmer Vernooij 2 years ago
parent
commit
cef367d5a3
4 changed files with 3 additions and 115 deletions
  1. 3 0
      NEWS
  2. 0 81
      dulwich/refs.py
  3. 0 33
      dulwich/tests/test_refs.py
  4. 0 1
      setup.py

+ 3 - 0
NEWS

@@ -1,5 +1,8 @@
 0.20.42	UNRELEASED
 
+ * Drop ``RefsContainer.watch`` that was always flaky.
+   (Jelmer Vernooij, #886)
+
 0.20.41	2022-05-24
 
  * Fix wheel uploading, properly. (Ruslan Kuprieiev)

+ 0 - 81
dulwich/refs.py

@@ -430,35 +430,6 @@ class RefsContainer(object):
                 ret[src] = dst
         return ret
 
-    def watch(self):
-        """Watch for changes to the refs in this container.
-
-        Returns a context manager that yields tuples with (refname, new_sha)
-        """
-        raise NotImplementedError(self.watch)
-
-
-class _DictRefsWatcher(object):
-    def __init__(self, refs):
-        self._refs = refs
-
-    def __enter__(self):
-        from queue import Queue
-
-        self.queue = Queue()
-        self._refs._watchers.add(self)
-        return self
-
-    def __next__(self):
-        return self.queue.get()
-
-    def _notify(self, entry):
-        self.queue.put_nowait(entry)
-
-    def __exit__(self, exc_type, exc_val, exc_tb):
-        self._refs._watchers.remove(self)
-        return False
-
 
 class DictRefsContainer(RefsContainer):
     """RefsContainer backed by a simple dict.
@@ -486,9 +457,6 @@ class DictRefsContainer(RefsContainer):
         for watcher in self._watchers:
             watcher._notify((ref, newsha))
 
-    def watch(self):
-        return _DictRefsWatcher(self)
-
     def set_symbolic_ref(
         self,
         name,
@@ -642,50 +610,6 @@ class InfoRefsContainer(RefsContainer):
             return self._refs[name]
 
 
-class _InotifyRefsWatcher(object):
-    def __init__(self, path):
-        import pyinotify
-        from queue import Queue
-
-        self.path = os.fsdecode(path)
-        self.manager = pyinotify.WatchManager()
-        self.manager.add_watch(
-            self.path,
-            pyinotify.IN_DELETE | pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO,
-            rec=True,
-            auto_add=True,
-        )
-
-        self.notifier = pyinotify.ThreadedNotifier(
-            self.manager, default_proc_fun=self._notify
-        )
-        self.queue = Queue()
-
-    def _notify(self, event):
-        if event.dir:
-            return
-        if event.pathname.endswith(".lock"):
-            return
-        ref = os.fsencode(os.path.relpath(event.pathname, self.path))
-        if event.maskname == "IN_DELETE":
-            self.queue.put_nowait((ref, None))
-        elif event.maskname in ("IN_CLOSE_WRITE", "IN_MOVED_TO"):
-            with open(event.pathname, "rb") as f:
-                sha = f.readline().rstrip(b"\n\r")
-                self.queue.put_nowait((ref, sha))
-
-    def __next__(self):
-        return self.queue.get()
-
-    def __enter__(self):
-        self.notifier.start()
-        return self
-
-    def __exit__(self, exc_type, exc_val, exc_tb):
-        self.notifier.stop()
-        return False
-
-
 class DiskRefsContainer(RefsContainer):
     """Refs container that reads refs from disk."""
 
@@ -1085,11 +1009,6 @@ class DiskRefsContainer(RefsContainer):
 
         return True
 
-    def watch(self):
-        import pyinotify  # noqa: F401
-
-        return _InotifyRefsWatcher(self.path)
-
 
 def _split_ref_line(line):
     """Split a single ref line into a tuple of SHA1 and name."""

+ 0 - 33
dulwich/tests/test_refs.py

@@ -355,39 +355,6 @@ class RefsContainerTests(object):
         )
         self.assertNotIn(b"refs/remotes/origin/other", self._refs)
 
-    def test_watch(self):
-        self.skipTest("watch sometimes hangs")
-        try:
-            watcher = self._refs.watch()
-        except (NotImplementedError, ImportError):
-            self.skipTest("watching not supported")
-        with watcher:
-            self._refs[
-                b"refs/remotes/origin/other"
-            ] = b"48d01bd4b77fed026b154d16493e5deab78f02ec"
-            change = next(watcher)
-            self.assertEqual(
-                (
-                    b"refs/remotes/origin/other",
-                    b"48d01bd4b77fed026b154d16493e5deab78f02ec",
-                ),
-                change,
-            )
-            self._refs[
-                b"refs/remotes/origin/other"
-            ] = b"48d01bd4b77fed026b154d16493e5deab78f02ed"
-            change = next(watcher)
-            self.assertEqual(
-                (
-                    b"refs/remotes/origin/other",
-                    b"48d01bd4b77fed026b154d16493e5deab78f02ed",
-                ),
-                change,
-            )
-            del self._refs[b"refs/remotes/origin/other"]
-            change = next(watcher)
-            self.assertEqual((b"refs/remotes/origin/other", None), change)
-
 
 class DictRefsContainerTests(RefsContainerTests, TestCase):
     def setUp(self):

+ 0 - 1
setup.py

@@ -78,7 +78,6 @@ if has_setuptools:
         'fastimport': ['fastimport'],
         'https': ['urllib3[secure]>=1.24.1'],
         'pgp': ['gpg'],
-        'watch': ['pyinotify'],
         'paramiko': ['paramiko'],
         }
     setup_kwargs['install_requires'] = ['urllib3>=1.24.1', 'certifi']