|
11 | 11 | import getpass
|
12 | 12 | import os
|
13 | 13 | import sys
|
| 14 | +import time |
14 | 15 |
|
15 | 16 | from bindings import tracing
|
16 | 17 | from edenscm.mercurial import blackbox, encoding, json, progress, pycompat, util
|
| 18 | +from edenscm.mercurial.i18n import _ |
17 | 19 | from edenscm.mercurial.node import hex
|
18 | 20 |
|
19 | 21 | from .. import pywatchman
|
@@ -101,6 +103,7 @@ def __init__(self, repo, timeout=1.0):
|
101 | 103 | self._resolved_root = getcanonicalpath(self._root)
|
102 | 104 | self._ui = repo.ui
|
103 | 105 | self._firsttime = True
|
| 106 | + self._approx_total_file_count = len(repo.dirstate._map) |
104 | 107 |
|
105 | 108 | def settimeout(self, timeout):
|
106 | 109 | self._timeout = timeout
|
@@ -197,9 +200,97 @@ def _retrycommand(self, span, retry, *args):
|
197 | 200 | if needretry:
|
198 | 201 | return self._retrycommand(span, retry + 1, *args)
|
199 | 202 |
|
| 203 | + def debug_status(self): |
| 204 | + """Return the RootDebugStatus, which might look like: |
| 205 | +
|
| 206 | + { |
| 207 | + "recrawl_info": { |
| 208 | + "count": 0, |
| 209 | + "should-recrawl": true, |
| 210 | + "warning": null, |
| 211 | + "reason": "startup", |
| 212 | + "completed": null, |
| 213 | + "started": -20162, |
| 214 | + "stats": 295541 |
| 215 | + } |
| 216 | + "crawl-status": "crawling for ...", |
| 217 | + "enable_parallel_crawl": false, |
| 218 | + "cookie_list": [], |
| 219 | + "path": "...", |
| 220 | + "queries": [], |
| 221 | + "fstype": "btrfs", |
| 222 | + "cookie_prefix": ["..."], |
| 223 | + "watcher": "inotify", |
| 224 | + "uptime": ..., |
| 225 | + "done_initial": false, |
| 226 | + "cookie_dir": [".../.hg"], |
| 227 | + "case_sensitive": true, |
| 228 | + "cancelled": false, |
| 229 | + } |
| 230 | +
|
| 231 | + Return an empty dict if watchman does not support debug-root-status. |
| 232 | + """ |
| 233 | + try: |
| 234 | + # use _command to bypass progress and util.timefuntion |
| 235 | + root_status = self._command("debug-root-status")["root_status"] |
| 236 | + except (Unavailable, AttributeError): |
| 237 | + # watchman does not support this command |
| 238 | + root_status = {} |
| 239 | + return root_status |
| 240 | + |
| 241 | + def recrawl_info(self): |
| 242 | + """Return the RootRecrawlInfo in the RootDebugStatus. |
| 243 | +
|
| 244 | + Return an empty dict if watchman does not support getting the recrawl |
| 245 | + info. |
| 246 | + """ |
| 247 | + debug_status = self.debug_status() |
| 248 | + info = {} |
| 249 | + try: |
| 250 | + info = debug_status["recrawl_info"] |
| 251 | + except AttributeError: |
| 252 | + pass |
| 253 | + return info |
| 254 | + |
| 255 | + def recrawl_stat_count(self): |
| 256 | + """Return the count of files stat()-ed by watchman during a full crawl |
| 257 | + Return None if watchman does not provide the information, or watchman |
| 258 | + is not in a full crawl state. |
| 259 | + """ |
| 260 | + stats = None |
| 261 | + try: |
| 262 | + stats = self.recrawl_info()["stats"] |
| 263 | + except AttributeError: |
| 264 | + pass |
| 265 | + return stats |
| 266 | + |
| 267 | + def wait_for_full_crawl(self): |
| 268 | + """Wait for watchman to complete a full recrawl. Blocking. |
| 269 | + Show a progress bar. |
| 270 | + """ |
| 271 | + ui = self._ui |
| 272 | + if not ui.configbool("fsmonitor", "wait-full-crawl"): |
| 273 | + return |
| 274 | + |
| 275 | + stats = self.recrawl_stat_count() |
| 276 | + if stats is None: |
| 277 | + # Not in full recrawl |
| 278 | + return |
| 279 | + |
| 280 | + # Show progress bar. |
| 281 | + total = self._approx_total_file_count |
| 282 | + with progress.bar(ui, _("crawling"), _("files (approx)"), total) as prog: |
| 283 | + while stats is not None: |
| 284 | + prog.value = stats |
| 285 | + stats = self.recrawl_stat_count() |
| 286 | + if stats is not None: |
| 287 | + time.sleep(0.1) |
| 288 | + |
200 | 289 | @util.timefunction("watchmanquery", 0, "_ui")
|
201 | 290 | def command(self, *args, **kwargs):
|
202 | 291 | ignoreerrors = kwargs.get("ignoreerrors", False)
|
| 292 | + if args and args[0] in {"clock", "query"}: |
| 293 | + self.wait_for_full_crawl() |
203 | 294 | with progress.spinner(self._ui, "querying watchman"):
|
204 | 295 | try:
|
205 | 296 | try:
|
|
0 commit comments