| 51 | |
| 52 | |
| 53 | class State(object): |
| 54 | def __init__(self, root_path: str, cache_path, new_version): |
| 55 | """ |
| 56 | pass in path should be absolute and normalized |
| 57 | :param new_version: if LSP is new version and support target prepare |
| 58 | """ |
| 59 | self.root_path = root_path |
| 60 | self.cache_path = cache_path |
| 61 | self.new_version = new_version |
| 62 | os.makedirs(cache_path, exist_ok=True) |
| 63 | |
| 64 | # buildServer.json used as config dict |
| 65 | config_path = os.path.join(root_path, "buildServer.json") |
| 66 | self.config = ServerConfig(config_path) |
| 67 | |
| 68 | # opened files need to be notified when flags changed |
| 69 | self.observed_uri = set() |
| 70 | # background thread to observe changes |
| 71 | self.observed_thread: Optional[Thread] = None |
| 72 | |
| 73 | # {path: mtime} cache. use to find changes |
| 74 | self.observed_info = {self.config.path: get_mtime(self.config.path)} |
| 75 | |
| 76 | self.reinit_compile_info() |
| 77 | # NOTE:thread-safety: for state shared by main and background watch thread, |
| 78 | # can only changed in sync_compile_file, which block all thread and no one access it. |
| 79 | # other time, the shared state is readonly and safe.. |
| 80 | |
| 81 | def get_compile_file(self, config: ServerConfig): |
| 82 | # isolate xcode generate compile file and manual compile_file |
| 83 | if config.kind == "xcode": |
| 84 | hash = hashlib.md5(config.build_root.encode("utf-8")).hexdigest() |
| 85 | name = ["compile_file", config.scheme or "_last", hash] |
| 86 | if config.skip_validate_bin: |
| 87 | name[0] = "compile_file1" |
| 88 | return os.path.join(self.cache_path, "-".join(name)) |
| 89 | # manual compile_file |
| 90 | return os.path.join(self.root_path, ".compile") |
| 91 | |
| 92 | def reinit_compile_info(self): |
| 93 | """all the compile information may change in background""" |
| 94 | |
| 95 | # store use to save compile_datainfo. it will be reload when config changes. |
| 96 | self.store = {} # main-thread |
| 97 | self._compile_file = self.get_compile_file(self.config) |
| 98 | if os.path.exists(self._compile_file): |
| 99 | self.compile_file = self._compile_file |
| 100 | logger.info(f"use flags from {self._compile_file}") |
| 101 | else: |
| 102 | self.compile_file = None |
| 103 | |
| 104 | # self._compile_file may change. need to init mtime to avoid trigger a change event |
| 105 | self.observed_info[self._compile_file] = get_mtime(self._compile_file) |
| 106 | |
| 107 | @property |
| 108 | def indexStorePath(self) -> Optional[str]: |
| 109 | if self.config.kind == "xcode": |
| 110 | if not (root := self.config.build_root): |