Show More
@@ -99,6 +99,7 b' from mercurial import (' | |||
|
99 | 99 | context, |
|
100 | 100 | extensions, |
|
101 | 101 | localrepo, |
|
102 | merge, | |
|
102 | 103 | pathutil, |
|
103 | 104 | scmutil, |
|
104 | 105 | util, |
@@ -547,6 +548,8 b' def extsetup(ui):' | |||
|
547 | 548 | # An assist for avoiding the dangling-symlink fsevents bug |
|
548 | 549 | extensions.wrapfunction(os, 'symlink', wrapsymlink) |
|
549 | 550 | |
|
551 | extensions.wrapfunction(merge, 'update', wrapupdate) | |
|
552 | ||
|
550 | 553 | def wrapsymlink(orig, source, link_name): |
|
551 | 554 | ''' if we create a dangling symlink, also touch the parent dir |
|
552 | 555 | to encourage fsevents notifications to work more correctly ''' |
@@ -558,6 +561,71 b' def wrapsymlink(orig, source, link_name)' | |||
|
558 | 561 | except OSError: |
|
559 | 562 | pass |
|
560 | 563 | |
|
564 | class state_update(object): | |
|
565 | ''' This context mananger is responsible for dispatching the state-enter | |
|
566 | and state-leave signals to the watchman service ''' | |
|
567 | ||
|
568 | def __init__(self, repo, node, distance, partial): | |
|
569 | self.repo = repo | |
|
570 | self.node = node | |
|
571 | self.distance = distance | |
|
572 | self.partial = partial | |
|
573 | ||
|
574 | def __enter__(self): | |
|
575 | self._state('state-enter') | |
|
576 | return self | |
|
577 | ||
|
578 | def __exit__(self, type_, value, tb): | |
|
579 | status = 'ok' if type_ is None else 'failed' | |
|
580 | self._state('state-leave', status=status) | |
|
581 | ||
|
582 | def _state(self, cmd, status='ok'): | |
|
583 | if not util.safehasattr(self.repo, '_watchmanclient'): | |
|
584 | return | |
|
585 | try: | |
|
586 | commithash = self.repo[self.node].hex() | |
|
587 | self.repo._watchmanclient.command(cmd, { | |
|
588 | 'name': 'hg.update', | |
|
589 | 'metadata': { | |
|
590 | # the target revision | |
|
591 | 'rev': commithash, | |
|
592 | # approximate number of commits between current and target | |
|
593 | 'distance': self.distance, | |
|
594 | # success/failure (only really meaningful for state-leave) | |
|
595 | 'status': status, | |
|
596 | # whether the working copy parent is changing | |
|
597 | 'partial': self.partial, | |
|
598 | }}) | |
|
599 | except Exception as e: | |
|
600 | # Swallow any errors; fire and forget | |
|
601 | self.repo.ui.log( | |
|
602 | 'watchman', 'Exception %s while running %s\n', e, cmd) | |
|
603 | ||
|
604 | # Bracket working copy updates with calls to the watchman state-enter | |
|
605 | # and state-leave commands. This allows clients to perform more intelligent | |
|
606 | # settling during bulk file change scenarios | |
|
607 | # https://facebook.github.io/watchman/docs/cmd/subscribe.html#advanced-settling | |
|
608 | def wrapupdate(orig, repo, node, branchmerge, force, ancestor=None, | |
|
609 | mergeancestor=False, labels=None, matcher=None, **kwargs): | |
|
610 | ||
|
611 | distance = 0 | |
|
612 | partial = True | |
|
613 | if matcher is None or matcher.always(): | |
|
614 | partial = False | |
|
615 | wc = repo[None] | |
|
616 | parents = wc.parents() | |
|
617 | if len(parents) == 2: | |
|
618 | anc = repo.changelog.ancestor(parents[0].node(), parents[1].node()) | |
|
619 | ancrev = repo[anc].rev() | |
|
620 | distance = abs(repo[node].rev() - ancrev) | |
|
621 | elif len(parents) == 1: | |
|
622 | distance = abs(repo[node].rev() - parents[0].rev()) | |
|
623 | ||
|
624 | with state_update(repo, node, distance, partial): | |
|
625 | return orig( | |
|
626 | repo, node, branchmerge, force, ancestor, mergeancestor, | |
|
627 | labels, matcher, *kwargs) | |
|
628 | ||
|
561 | 629 | def reposetup(ui, repo): |
|
562 | 630 | # We don't work with largefiles or inotify |
|
563 | 631 | exts = extensions.enabled() |
General Comments 0
You need to be logged in to leave comments.
Login now