forked from facebook/watchman
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauto.cpp
152 lines (133 loc) · 4.25 KB
/
auto.cpp
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* Copyright 2012-present Facebook, Inc.
* Licensed under the Apache License, Version 2.0 */
#include "watchman.h"
WatcherRegistry::WatcherRegistry(
const std::string& name,
std::function<std::shared_ptr<watchman::QueryableView>(w_root_t*)> init,
int priority)
: name_(name), init_(init), pri_(priority) {
registerFactory(*this);
}
std::unordered_map<std::string, WatcherRegistry>&
WatcherRegistry::getRegistry() {
// Meyers singleton
static std::unordered_map<std::string, WatcherRegistry> registry;
return registry;
}
void WatcherRegistry::registerFactory(const WatcherRegistry& factory) {
auto& reg = getRegistry();
reg.emplace(factory.name_, factory);
auto capname = folly::to<std::string>("watcher-", factory.name_);
w_capability_register(capname.c_str());
}
const WatcherRegistry* WatcherRegistry::getWatcherByName(
const std::string& name) {
auto& reg = getRegistry();
const auto& it = reg.find(name);
if (it == reg.end()) {
return nullptr;
}
return &it->second;
}
// Helper to DRY in the two success paths in the function below
static inline std::shared_ptr<watchman::QueryableView> reportWatcher(
const std::string& watcherName,
w_root_t* root,
std::shared_ptr<watchman::QueryableView>&& watcher) {
if (!watcher) {
throw std::runtime_error(folly::to<std::string>(
"watcher ",
watcherName,
" returned nullptr, but should throw an exception"
" to correctly report initialization issues"));
}
watchman::log(
watchman::ERR,
"root ",
root->root_path,
" using watcher mechanism ",
watcher->getName(),
" (",
watcherName,
" was requested)\n");
return std::move(watcher);
}
std::shared_ptr<watchman::QueryableView> WatcherRegistry::initWatcher(
w_root_t* root) {
std::string failureReasons;
std::string watcherName = root->config.getString("watcher", "auto");
if (watcherName != "auto") {
// If they asked for a specific one, let's try to find it
auto watcher = getWatcherByName(watcherName);
if (!watcher) {
failureReasons.append(
std::string("no watcher named ") + watcherName + std::string(". "));
} else {
try {
return reportWatcher(watcherName, root, watcher->init_(root));
} catch (const std::exception& e) {
failureReasons.append(
watcherName + std::string(": ") + e.what() + std::string(". "));
}
}
}
// If we get here, let's do auto-selection; build up a list of the
// watchers that we didn't try already...
std::vector<const WatcherRegistry*> watchers;
for (const auto& it : getRegistry()) {
if (it.first != watcherName) {
watchers.emplace_back(&it.second);
}
}
// ... and sort with the highest priority first
std::sort(
watchers.begin(),
watchers.end(),
[](const WatcherRegistry* a, const WatcherRegistry* b) {
return a->pri_ > b->pri_;
});
// and then work through them, taking the first one that sticks
for (auto& watcher : watchers) {
try {
watchman::log(
watchman::DBG,
"attempting to use watcher ",
watcher->getName(),
" on ",
root->root_path,
"\n");
return reportWatcher(watcherName, root, watcher->init_(root));
} catch (const watchman::TerminalWatcherError& e) {
failureReasons.append(
watcher->getName() + std::string(": ") + e.what() +
std::string(". "));
// Don't continue our attempt to use other registered watchers
// in this case
break;
} catch (const std::exception& e) {
watchman::log(
watchman::ERR,
"failed to use watcher ",
watcher->getName(),
": ",
e.what(),
".\n");
failureReasons.append(
watcher->getName() + std::string(": ") + e.what() +
std::string(". "));
}
}
// Nothing worked, report the errors
throw std::runtime_error(failureReasons);
}
Watcher::Watcher(const char* name, unsigned flags) : name(name), flags(flags) {}
Watcher::~Watcher() {}
bool Watcher::startWatchFile(struct watchman_file*) {
return true;
}
bool Watcher::start(const std::shared_ptr<w_root_t>&) {
return true;
}
void Watcher::signalThreads() {}
/* vim:ts=2:sw=2:et:
*/