forked from pantsbuild/pants
/
watchman_launcher.py
103 lines (89 loc) · 4.18 KB
/
watchman_launcher.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# coding=utf-8
# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).
from __future__ import absolute_import, division, print_function, unicode_literals
import logging
from builtins import object
from pants.binaries.binary_util import BinaryToolFetcher, BinaryUtil
from pants.pantsd.watchman import Watchman
from pants.util.memo import testable_memoized_property
class WatchmanLauncher(object):
"""An object that manages the configuration and lifecycle of Watchman."""
@classmethod
def create(cls, bootstrap_options):
"""
:param Options bootstrap_options: The bootstrap options bag.
"""
binary_tool_fetcher = BinaryToolFetcher(
bootstrap_dir=bootstrap_options.pants_bootstrapdir,
timeout_secs=bootstrap_options.binaries_fetch_timeout_secs)
binary_util = BinaryUtil(
baseurls=bootstrap_options.binaries_baseurls,
binary_tool_fetcher=binary_tool_fetcher,
path_by_id=bootstrap_options.binaries_path_by_id,
# TODO(cosmicexplorer): do we need to test this?
allow_external_binary_tool_downloads=bootstrap_options.allow_external_binary_tool_downloads)
return WatchmanLauncher(
binary_util,
bootstrap_options.level,
bootstrap_options.watchman_version,
bootstrap_options.watchman_supportdir,
bootstrap_options.watchman_startup_timeout,
bootstrap_options.watchman_socket_timeout,
bootstrap_options.watchman_socket_path,
bootstrap_options.pants_subprocessdir
)
def __init__(self, binary_util, log_level, watchman_version, watchman_supportdir,
startup_timeout, socket_timeout, socket_path_override=None, metadata_base_dir=None):
"""
:param binary_util: The BinaryUtil subsystem instance for binary retrieval.
:param log_level: The current log level of pants.
:param watchman_version: The watchman binary version to retrieve using BinaryUtil.
:param watchman_supportdir: The supportdir for BinaryUtil.
:param socket_timeout: The watchman client socket timeout (in seconds).
:param socket_path_override: The overridden target path of the watchman socket, if any.
:param metadata_base_dir: The ProcessManager metadata base directory.
"""
self._binary_util = binary_util
self._watchman_version = watchman_version
self._watchman_supportdir = watchman_supportdir
self._startup_timeout = startup_timeout
self._socket_timeout = socket_timeout
self._socket_path_override = socket_path_override
self._log_level = log_level
self._logger = logging.getLogger(__name__)
self._metadata_base_dir = metadata_base_dir
@staticmethod
def _convert_log_level(level):
"""Convert a given pants log level string into a watchman log level string."""
# N.B. Enabling true Watchman debug logging (log level 2) can generate an absurd amount of log
# data (10s of gigabytes over the course of an ~hour for an active fs) and is not particularly
# helpful except for debugging Watchman itself. Thus, here we intentionally avoid this level
# in the mapping of pants log level -> watchman.
return {'warn': '0', 'info': '1', 'debug': '1'}.get(level, '1')
@testable_memoized_property
def watchman(self):
watchman_binary = self._binary_util.select_binary(self._watchman_supportdir,
self._watchman_version,
'watchman')
return Watchman(
watchman_binary,
self._metadata_base_dir,
self._convert_log_level(self._log_level),
self._startup_timeout,
self._socket_timeout,
self._socket_path_override,
)
def maybe_launch(self):
if not self.watchman.is_alive():
self._logger.debug('launching watchman')
try:
self.watchman.launch()
except (Watchman.ExecutionError, Watchman.InvalidCommandOutput) as e:
self._logger.fatal('failed to launch watchman: {!r})'.format(e))
raise
self._logger.debug('watchman is running, pid={pid} socket={socket}'
.format(pid=self.watchman.pid, socket=self.watchman.socket))
return self.watchman
def terminate(self):
self.watchman.terminate()