[PATCH] hgwatchman: new experimental extension
Martijn Pieters
mj at zopatista.com
Tue Mar 1 10:43:11 EST 2016
On 24 February 2016 at 18:19, Martin von Zweigbergk
<martinvonz at google.com> wrote:
> I guess the user can be expected to know or find out what watchman is,
> but maybe the commit message should explain what pywatchman is? I
> don't know what it is, even after spending a few minutes to try to
> find out. And why do we need a copy of it? (I'm guessing it is to
> avoid a config option pointing to it.)
Because this is an SDK to talk to watchman, which is installed as a
separate binary daemon that doesn't include those SDKs. By bundling it
we avoid requiring the extension user to installtwo things instead of
one (just watchman).
I'll update the commit message.
>> +def overridewalk(orig, self, match, subrepos, unknown, ignored, full=True):
>> + '''Whenever full is False, ignored is False, and the watchman client is
>> + available, use watchman combined with saved state to possibly return only a
>> + subset of files.'''
>> + def bail():
>> + return orig(match, subrepos, unknown, ignored, full=True)
>> +
>> + if full or ignored or not self._watchmanclient.available():
>> + return bail()
>> + clock, ignorehash, notefiles = self._watchmanstate.get()
>> + if not clock:
>> + if self._watchmanstate.crawl_on_invalidate:
>> + return bail()
>> + clock = 'c:0:0'
>> + notefiles = []
>> +
>> + def fwarn(f, msg):
>> + self._ui.warn('%s: %s\n' % (self.pathto(f), msg))
>> + return False
>> +
>> + def badtype(mode):
>> + kind = _('unknown')
>> + if stat.S_ISCHR(mode):
>> + kind = _('character device')
>> + elif stat.S_ISBLK(mode):
>> + kind = _('block device')
>> + elif stat.S_ISFIFO(mode):
>> + kind = _('fifo')
>> + elif stat.S_ISSOCK(mode):
>> + kind = _('socket')
>> + elif stat.S_ISDIR(mode):
>> + kind = _('directory')
>> + return _('unsupported file type (type is %s)') % kind
>> +
>> + ignore = self._ignore
>> + dirignore = self._dirignore
>> + if unknown:
>> + if _hashignore(ignore) != ignorehash and clock != 'c:0:0':
>> + # ignore list changed -- can't rely on watchman state any more
>> + if self._watchmanstate.crawl_on_invalidate:
>> + return bail()
>> + notefiles = []
>> + clock = 'c:0:0'
>> + else:
>> + # always ignore
>> + ignore = util.always
>> + dirignore = util.always
>> +
>> + matchfn = match.matchfn
>> + matchalways = match.always()
>> + dmap = self._map
>> + nonnormalset = None
>> + if util.safehasattr(self, "_nonnormalset"):
>> + nonnormalset = self._nonnormalset
>> +
>> + copymap = self._copymap
>> + getkind = stat.S_IFMT
>> + dirkind = stat.S_IFDIR
>> + regkind = stat.S_IFREG
>> + lnkkind = stat.S_IFLNK
>> + join = self._join
>> + normcase = util.normcase
>> + fresh_instance = False
>> +
>> + exact = skipstep3 = False
>> + if matchfn == match.exact: # match.exact
>> + exact = True
>> + dirignore = util.always # skip step 2
>> + elif match.files() and not match.anypats(): # match.match, no patterns
>> + skipstep3 = True
>> +
>> + if not exact and self._checkcase:
>> + # note that even though we could receive directory entries, we're only
>> + # interested in checking if a file with the same name exists. So only
>> + # normalize files if possible (Mercurial >= 3.4), not directories.
>> + normalize = getattr(self, '_normalizefile', self._normalize)
>> + skipstep3 = False
>> + else:
>> + normalize = None
>
> This function looks similar but different from dirstate.walk() (in
> both wanted and unwanted ways). I guess we'll refactor after it's in?
Yes, if you see opportunities to make this gel better, please do
refactor once we land this!
>> + try:
>> + if self._watchmanstate.crawl_on_invalidate:
>> + # Use a short timeout to query the current clock. If that
>> + # takes too long then we assume that the service will be slow
>> + # to answer our query.
>> + # crawl_on_invalidate indicates that we prefer to crawl the
>> + # tree ourselves because we can ignore portions that watchman
>
> nit: does "crawl the tree" mean the same thing as hg normally calls
> "walk the tree"? If so, use that terminology?
>
>> + # clean isn't tested since it's set to True above
>> + _cmpsets([modified, added, removed, deleted, unknown, ignored, clean],
>> + rv2)
>
> aka "_cmpsets(r, rv2)"?
Yes.
>> +class state(object):
>> + def __init__(self, repo):
>> + self._opener = repo.opener
>> + self._ui = repo.ui
>> + self._rootdir = pathutil.normasprefix(repo.root)
>> + self._lastclock = None
>> +
>> + self.mode = self._ui.config('watchman', 'mode', default='on')
>> + self.crawl_on_invalidate = self._ui.configbool(
>> + 'watchman', 'crawl_on_invalidate', True)
>
> I don't think this option was documented. Should it be?
Good catch; the mercurial style linter missed this one. It probably
should be documented.
--
Martijn Pieters
More information about the Mercurial-devel
mailing list