@@ -11,9 +11,15 @@ struct Dependency {
11
11
an<ConfigItemRef> target;
12
12
13
13
virtual bool blocking () const = 0;
14
+ virtual string repr () const = 0;
14
15
virtual bool Resolve (ConfigCompiler* compiler) = 0;
15
16
};
16
17
18
+ template <class StreamT >
19
+ StreamT& operator << (StreamT& stream, const Dependency& dep) {
20
+ return stream << dep.repr () << (dep.blocking () ? " (blocking)" : " " );
21
+ }
22
+
17
23
struct PendingChild : Dependency {
18
24
string child_path;
19
25
an<ConfigItemRef> child_ref;
@@ -24,12 +30,19 @@ struct PendingChild : Dependency {
24
30
bool blocking () const override {
25
31
return false ;
26
32
}
33
+ string repr () const override {
34
+ return " PendingChild(" + child_path + " )" ;
35
+ }
27
36
bool Resolve (ConfigCompiler* compiler) override ;
28
37
};
29
38
39
+ string Reference::repr () const {
40
+ return resource_id + " :" + local_path;
41
+ }
42
+
30
43
template <class StreamT >
31
44
StreamT& operator << (StreamT& stream, const Reference& reference) {
32
- return stream << reference.resource_id << " : " << reference. local_path ;
45
+ return stream << reference.repr () ;
33
46
}
34
47
35
48
struct IncludeReference : Dependency {
@@ -38,6 +51,9 @@ struct IncludeReference : Dependency {
38
51
bool blocking () const override {
39
52
return true ;
40
53
}
54
+ string repr () const override {
55
+ return " Include(" + reference.repr () + " )" ;
56
+ }
41
57
bool Resolve (ConfigCompiler* compiler) override ;
42
58
43
59
Reference reference;
@@ -49,6 +65,9 @@ struct PatchReference : Dependency {
49
65
bool blocking () const override {
50
66
return true ;
51
67
}
68
+ string repr () const override {
69
+ return " Patch(" + reference.repr () + " )" ;
70
+ }
52
71
bool Resolve (ConfigCompiler* compiler) override ;
53
72
54
73
Reference reference;
@@ -62,6 +81,9 @@ struct PatchLiteral : Dependency {
62
81
bool blocking () const override {
63
82
return true ;
64
83
}
84
+ string repr () const override {
85
+ return " Patch(<literal>)" ;
86
+ }
65
87
bool Resolve (ConfigCompiler* compiler) override ;
66
88
};
67
89
@@ -107,6 +129,7 @@ bool IncludeReference::Resolve(ConfigCompiler* compiler) {
107
129
}
108
130
109
131
bool PatchReference::Resolve (ConfigCompiler* compiler) {
132
+ LOG (INFO) << " PatchReference::Resolve(reference = " << reference << " )" ;
110
133
auto item = ResolveReference (compiler, reference);
111
134
if (!item) {
112
135
return false ;
@@ -125,10 +148,12 @@ bool TraverseCopyOnWrite(an<ConfigItemRef> root, const string& path,
125
148
an<ConfigItem> item);
126
149
127
150
bool PatchLiteral::Resolve (ConfigCompiler* compiler) {
151
+ LOG (INFO) << " PatchLiteral::Resolve()" ;
128
152
bool success = true ;
129
153
for (const auto & entry : *patch) {
130
154
const auto & path = entry.first ;
131
155
const auto & value = entry.second ;
156
+ LOG (INFO) << " patching " << path;
132
157
if (!TraverseCopyOnWrite (target, path, value)) {
133
158
LOG (ERROR) << " error applying patch to " << path;
134
159
success = false ;
@@ -143,25 +168,29 @@ void ConfigDependencyGraph::Add(an<Dependency> dependency) {
143
168
const auto & target = node_stack.back ();
144
169
dependency->target = target;
145
170
auto target_path = ConfigData::JoinPath (key_stack);
146
- deps[target_path].push_back (dependency);
147
- LOG (INFO) << " target_path = " << target_path << " , #deps = " << deps[target_path].size ();
171
+ auto & target_deps = deps[target_path];
172
+ bool target_was_pending = !target_deps.empty ();
173
+ target_deps.push_back (dependency);
174
+ LOG (INFO) << " target_path = " << target_path << " , #deps = " << target_deps.size ();
175
+ if (target_was_pending || // so was all ancestors
176
+ key_stack.size () == 1 ) { // this is the progenitor
177
+ return ;
178
+ }
148
179
// The current pending node becomes a prioritized dependency of parent node
149
- auto child = target;
150
180
auto keys = key_stack;
151
- for (auto prev = node_stack.rbegin () + 1 ; prev != node_stack.rend (); ++prev ) {
181
+ for (auto child = node_stack.rbegin (); child != node_stack.rend (); ++child ) {
152
182
auto last_key = keys.back ();
153
183
keys.pop_back ();
154
184
auto parent_path = ConfigData::JoinPath (keys);
155
185
auto & parent_deps = deps[parent_path];
156
186
bool parent_was_pending = !parent_deps.empty ();
157
187
// Pending children should be resolved before applying __include or __patch
158
- parent_deps.push_front (New<PendingChild>(parent_path + " /" + last_key, child));
188
+ parent_deps.push_front (New<PendingChild>(parent_path + " /" + last_key, * child));
159
189
LOG (INFO) << " parent_path = " << parent_path << " , #deps = " << parent_deps.size ();
160
- if (parent_was_pending) {
161
- // so was all ancestors
162
- break ;
190
+ if (parent_was_pending || // so was all ancestors
191
+ keys. size () == 1 ) { // this parent is the progenitor
192
+ return ;
163
193
}
164
- child = *prev;
165
194
}
166
195
}
167
196
@@ -244,7 +273,7 @@ static bool ResolveBlockingDependencies(ConfigCompiler* compiler,
244
273
static an<ConfigItem> GetResolvedItem (ConfigCompiler* compiler,
245
274
an<ConfigResource> resource,
246
275
const string& path) {
247
- LOG (INFO) << " GetResolvedItem(" << resource->resource_id << " :/ " << path << " )" ;
276
+ LOG (INFO) << " GetResolvedItem(" << resource->resource_id << " :" << path << " )" ;
248
277
string node_path = resource->resource_id + " :" ;
249
278
if (!resource || compiler->blocking (node_path)) {
250
279
return nullptr ;
@@ -364,7 +393,7 @@ static bool ParsePatch(ConfigCompiler* compiler,
364
393
}
365
394
366
395
bool ConfigCompiler::Parse (const string& key, const an<ConfigItem>& item) {
367
- LOG (INFO) << " ConfigCompiler::Parse(" << key << " )" ;
396
+ DLOG (INFO) << " ConfigCompiler::Parse(" << key << " )" ;
368
397
if (key == INCLUDE_DIRECTIVE) {
369
398
return ParseInclude (this , item);
370
399
}
@@ -389,10 +418,10 @@ bool ConfigCompiler::ResolveDependencies(const string& path) {
389
418
auto & deps = graph_->deps [path];
390
419
for (auto iter = deps.begin (); iter != deps.end (); ) {
391
420
if (!(*iter)->Resolve (this )) {
392
- LOG (INFO ) << " unesolved dependency! " ;
421
+ LOG (ERROR ) << " unesolved dependency: " << **iter ;
393
422
return false ;
394
423
}
395
- LOG (INFO) << " resolved. " ;
424
+ LOG (INFO) << " resolved " << **iter ;
396
425
iter = deps.erase (iter);
397
426
}
398
427
LOG (INFO) << " all dependencies resolved." ;
0 commit comments