Dulwich.io dulwich / f189faa
Add a RefsContainer.watch method. Jelmer Vernooń≥ 11 days ago
3 changed file(s) with 74 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
0 0.20.6 UNRELEASED
1
2 * Add a ``RefsContainer.watch`` interface.
3 (Jelmer Vernooń≥, #751)
4
05 0.20.5 2020-06-22
16
27 * Print a clearer exception when setup.py is executed on Python < 3.5.
389389 ret[src] = dst
390390 return ret
391391
392 def watch(self):
393 """Watch for changes to the refs in this container.
394
395 Returns a context manager that yields tuples with (refname, old_sha,
396 new_sha)
397 """
398 raise NotImplementedError(self.watch)
399
400
401 class _DictRefsWatcher(object):
402
403 def __init__(self, refs):
404 self._refs = refs
405
406 def __enter__(self):
407 from queue import Queue
408 self.queue = Queue()
409 self._refs._watchers.add(self)
410 return self
411
412 def __next__(self):
413 return self.queue.get()
414
415 def _notify(self, entry):
416 self.queue.put_nowait(entry)
417
418 def __exit__(self, exc_type, exc_val, exc_tb):
419 self._refs._watchers.remove(self)
420 return False
421
392422
393423 class DictRefsContainer(RefsContainer):
394424 """RefsContainer backed by a simple dict.
401431 super(DictRefsContainer, self).__init__(logger=logger)
402432 self._refs = refs
403433 self._peeled = {}
434 self._watchers = set()
404435
405436 def allkeys(self):
406437 return self._refs.keys()
410441
411442 def get_packed_refs(self):
412443 return {}
444
445 def _notify(self, ref, oldsha, newsha):
446 for watcher in self._watchers:
447 watcher._notify((ref, oldsha, newsha))
448
449 def watch(self):
450 return _DictRefsWatcher(self)
413451
414452 def set_symbolic_ref(self, name, other, committer=None,
415453 timestamp=None, timezone=None, message=None):
416454 old = self.follow(name)[-1]
417455 new = SYMREF + other
418456 self._refs[name] = new
457 self._notify(name, old, new)
419458 self._log(name, old, new, committer=committer, timestamp=timestamp,
420459 timezone=timezone, message=message)
421460
428467 self._check_refname(realname)
429468 old = self._refs.get(realname)
430469 self._refs[realname] = new_ref
470 self._notify(realname, old, new_ref)
431471 self._log(realname, old, new_ref, committer=committer,
432472 timestamp=timestamp, timezone=timezone, message=message)
433473 return True
437477 if name in self._refs:
438478 return False
439479 self._refs[name] = ref
480 self._notify(name, None, ref)
440481 self._log(name, None, ref, committer=committer, timestamp=timestamp,
441482 timezone=timezone, message=message)
442483 return True
450491 except KeyError:
451492 pass
452493 else:
494 self._notify(name, old, None)
453495 self._log(name, old, None, committer=committer,
454496 timestamp=timestamp, timezone=timezone, message=message)
455497 return True
462504 # TODO(dborowitz): replace this with a public function that uses
463505 # set_if_equal.
464506 for ref, sha in refs.items():
465 self._refs[ref] = sha
507 self.set_if_equal(ref, None, sha)
466508
467509 def _update_peeled(self, peeled):
468510 """Update cached peeled refs; intended only for testing."""
322322 self.assertNotIn(
323323 b'refs/remotes/origin/other', self._refs)
324324
325 def test_watch(self):
326 try:
327 watcher = self._refs.watch()
328 except NotImplementedError:
329 self.skipTest('watching not supported')
330 with watcher:
331 self._refs[b'refs/remotes/origin/other'] = (
332 b'48d01bd4b77fed026b154d16493e5deab78f02ec')
333 change = next(watcher)
334 self.assertEqual(
335 (b'refs/remotes/origin/other', None,
336 b'48d01bd4b77fed026b154d16493e5deab78f02ec'), change)
337 self._refs[b'refs/remotes/origin/other'] = (
338 b'48d01bd4b77fed026b154d16493e5deab78f02ed')
339 change = next(watcher)
340 self.assertEqual(
341 (b'refs/remotes/origin/other',
342 b'48d01bd4b77fed026b154d16493e5deab78f02ec',
343 b'48d01bd4b77fed026b154d16493e5deab78f02ed'), change)
344 del self._refs[b'refs/remotes/origin/other']
345 change = next(watcher)
346 self.assertEqual(
347 (b'refs/remotes/origin/other',
348 b'48d01bd4b77fed026b154d16493e5deab78f02ed',
349 None), change)
350
325351
326352 class DictRefsContainerTests(RefsContainerTests, TestCase):
327353