@@ -11,9 +11,15 @@ struct Dependency {
1111 an<ConfigItemRef> target;
1212
1313 virtual bool blocking () const = 0;
14+ virtual string repr () const = 0;
1415 virtual bool Resolve (ConfigCompiler* compiler) = 0;
1516};
1617
18+ template <class StreamT >
19+ StreamT& operator << (StreamT& stream, const Dependency& dep) {
20+ return stream << dep.repr () << (dep.blocking () ? " (blocking)" : " " );
21+ }
22+
1723struct PendingChild : Dependency {
1824 string child_path;
1925 an<ConfigItemRef> child_ref;
@@ -24,12 +30,19 @@ struct PendingChild : Dependency {
2430 bool blocking () const override {
2531 return false ;
2632 }
33+ string repr () const override {
34+ return " PendingChild(" + child_path + " )" ;
35+ }
2736 bool Resolve (ConfigCompiler* compiler) override ;
2837};
2938
39+ string Reference::repr () const {
40+ return resource_id + " :" + local_path;
41+ }
42+
3043template <class StreamT >
3144StreamT& operator << (StreamT& stream, const Reference& reference) {
32- return stream << reference.resource_id << " : " << reference. local_path ;
45+ return stream << reference.repr () ;
3346}
3447
3548struct IncludeReference : Dependency {
@@ -38,6 +51,9 @@ struct IncludeReference : Dependency {
3851 bool blocking () const override {
3952 return true ;
4053 }
54+ string repr () const override {
55+ return " Include(" + reference.repr () + " )" ;
56+ }
4157 bool Resolve (ConfigCompiler* compiler) override ;
4258
4359 Reference reference;
@@ -49,6 +65,9 @@ struct PatchReference : Dependency {
4965 bool blocking () const override {
5066 return true ;
5167 }
68+ string repr () const override {
69+ return " Patch(" + reference.repr () + " )" ;
70+ }
5271 bool Resolve (ConfigCompiler* compiler) override ;
5372
5473 Reference reference;
@@ -62,6 +81,9 @@ struct PatchLiteral : Dependency {
6281 bool blocking () const override {
6382 return true ;
6483 }
84+ string repr () const override {
85+ return " Patch(<literal>)" ;
86+ }
6587 bool Resolve (ConfigCompiler* compiler) override ;
6688};
6789
@@ -107,6 +129,7 @@ bool IncludeReference::Resolve(ConfigCompiler* compiler) {
107129}
108130
109131bool PatchReference::Resolve (ConfigCompiler* compiler) {
132+ LOG (INFO) << " PatchReference::Resolve(reference = " << reference << " )" ;
110133 auto item = ResolveReference (compiler, reference);
111134 if (!item) {
112135 return false ;
@@ -125,10 +148,12 @@ bool TraverseCopyOnWrite(an<ConfigItemRef> root, const string& path,
125148 an<ConfigItem> item);
126149
127150bool PatchLiteral::Resolve (ConfigCompiler* compiler) {
151+ LOG (INFO) << " PatchLiteral::Resolve()" ;
128152 bool success = true ;
129153 for (const auto & entry : *patch) {
130154 const auto & path = entry.first ;
131155 const auto & value = entry.second ;
156+ LOG (INFO) << " patching " << path;
132157 if (!TraverseCopyOnWrite (target, path, value)) {
133158 LOG (ERROR) << " error applying patch to " << path;
134159 success = false ;
@@ -143,25 +168,29 @@ void ConfigDependencyGraph::Add(an<Dependency> dependency) {
143168 const auto & target = node_stack.back ();
144169 dependency->target = target;
145170 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+ }
148179 // The current pending node becomes a prioritized dependency of parent node
149- auto child = target;
150180 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 ) {
152182 auto last_key = keys.back ();
153183 keys.pop_back ();
154184 auto parent_path = ConfigData::JoinPath (keys);
155185 auto & parent_deps = deps[parent_path];
156186 bool parent_was_pending = !parent_deps.empty ();
157187 // 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));
159189 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 ;
163193 }
164- child = *prev;
165194 }
166195}
167196
@@ -244,7 +273,7 @@ static bool ResolveBlockingDependencies(ConfigCompiler* compiler,
244273static an<ConfigItem> GetResolvedItem (ConfigCompiler* compiler,
245274 an<ConfigResource> resource,
246275 const string& path) {
247- LOG (INFO) << " GetResolvedItem(" << resource->resource_id << " :/ " << path << " )" ;
276+ LOG (INFO) << " GetResolvedItem(" << resource->resource_id << " :" << path << " )" ;
248277 string node_path = resource->resource_id + " :" ;
249278 if (!resource || compiler->blocking (node_path)) {
250279 return nullptr ;
@@ -364,7 +393,7 @@ static bool ParsePatch(ConfigCompiler* compiler,
364393}
365394
366395bool ConfigCompiler::Parse (const string& key, const an<ConfigItem>& item) {
367- LOG (INFO) << " ConfigCompiler::Parse(" << key << " )" ;
396+ DLOG (INFO) << " ConfigCompiler::Parse(" << key << " )" ;
368397 if (key == INCLUDE_DIRECTIVE) {
369398 return ParseInclude (this , item);
370399 }
@@ -389,10 +418,10 @@ bool ConfigCompiler::ResolveDependencies(const string& path) {
389418 auto & deps = graph_->deps [path];
390419 for (auto iter = deps.begin (); iter != deps.end (); ) {
391420 if (!(*iter)->Resolve (this )) {
392- LOG (INFO ) << " unesolved dependency! " ;
421+ LOG (ERROR ) << " unesolved dependency: " << **iter ;
393422 return false ;
394423 }
395- LOG (INFO) << " resolved. " ;
424+ LOG (INFO) << " resolved " << **iter ;
396425 iter = deps.erase (iter);
397426 }
398427 LOG (INFO) << " all dependencies resolved." ;
0 commit comments