mirror of
https://github.com/flynx/features.js.git
synced 2025-10-29 10:20:09 +00:00
almost ready...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
c4e6e48756
commit
cad40b850e
161
features.js
161
features.js
@ -1019,7 +1019,7 @@ var FeatureSetProto = {
|
|||||||
// - if not ??? (XXX)
|
// - if not ??? (XXX)
|
||||||
// XXX should we report stuff here???
|
// XXX should we report stuff here???
|
||||||
// XXX TODO:
|
// XXX TODO:
|
||||||
// - resolve exclusive aliases and conflicts...
|
// - wrapper to pass in applicability filter...
|
||||||
_buildFeatureListReorder: function(lst, filter){
|
_buildFeatureListReorder: function(lst, filter){
|
||||||
var all = this.features
|
var all = this.features
|
||||||
lst = (lst == null || lst == '*') ? all : lst
|
lst = (lst == null || lst == '*') ? all : lst
|
||||||
@ -1071,10 +1071,10 @@ var FeatureSetProto = {
|
|||||||
// normalize the list -- remove non-features and resolve aliases...
|
// normalize the list -- remove non-features and resolve aliases...
|
||||||
.map(function(n){
|
.map(function(n){
|
||||||
var f = that[n]
|
var f = that[n]
|
||||||
// resolve exclusive tags...
|
// exclusive tags...
|
||||||
while(f == null && data.exclusive && n in data.exclusive){
|
if(f == null && data.exclusive && n in data.exclusive){
|
||||||
var n = data.exclusive[n][0]
|
store[n] = null
|
||||||
f = that[n]
|
return false
|
||||||
}
|
}
|
||||||
// feature not defined or is not a feature...
|
// feature not defined or is not a feature...
|
||||||
if(f == null){
|
if(f == null){
|
||||||
@ -1116,10 +1116,6 @@ var FeatureSetProto = {
|
|||||||
|
|
||||||
// traverse down...
|
// traverse down...
|
||||||
expand(target, _lst, store, data, _seen.concat([f]))
|
expand(target, _lst, store, data, _seen.concat([f]))
|
||||||
|
|
||||||
// XXX makes sense to push the dep here -- at the tail of the recursion...
|
|
||||||
data.list
|
|
||||||
&& data.list.push(f)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1143,57 +1139,121 @@ var FeatureSetProto = {
|
|||||||
// ...we need to do this on the build stage to include correct
|
// ...we need to do this on the build stage to include correct
|
||||||
// deps and suggesntions...
|
// deps and suggesntions...
|
||||||
var exclusive = {}
|
var exclusive = {}
|
||||||
|
var rev_exclusive = {}
|
||||||
all
|
all
|
||||||
.filter(function(f){ return !!that[f].exclusive })
|
.filter(function(f){ return !!that[f].exclusive })
|
||||||
.forEach(function(k){
|
.forEach(function(k){
|
||||||
(that[k].exclusive || [])
|
(that[k].exclusive || [])
|
||||||
.forEach(function(e){
|
.forEach(function(e){
|
||||||
exclusive[e] = (exclusive[e] || []).concat([k]) }) })
|
exclusive[e] = (exclusive[e] || []).concat([k])
|
||||||
|
rev_exclusive[k] = (rev_exclusive[k] || []).concat([e]) }) })
|
||||||
|
|
||||||
// feature tree...
|
// XXX revise:
|
||||||
var features = expand('depends', lst, {},
|
// - should this be this depending on closure so much???
|
||||||
{
|
var expandFeatures = function(lst, features){
|
||||||
|
features = features || {}
|
||||||
|
|
||||||
|
// feature tree...
|
||||||
|
var expand_data = {
|
||||||
loops: loops,
|
loops: loops,
|
||||||
disable_loops: disable_loops,
|
|
||||||
disabled: disabled,
|
disabled: disabled,
|
||||||
|
disable_loops: disable_loops,
|
||||||
missing: missing,
|
missing: missing,
|
||||||
exclusive: exclusive,
|
exclusive: exclusive,
|
||||||
})
|
}
|
||||||
|
|
||||||
// suggestion list...
|
features = expand('depends', lst, features, expand_data)
|
||||||
// ...this will be used to check if we need to break on missing
|
|
||||||
// features, e.g. if a feature is suggested we can silently skip
|
|
||||||
// it otherwise err...
|
|
||||||
//
|
|
||||||
// NOTE: this stage does not track suggested feature dependencies...
|
|
||||||
// NOTE: we do not need loop detection active here...
|
|
||||||
var suggested = Object.keys(
|
|
||||||
expand('suggested', Object.keys(features), {}, { disabled: disabled }))
|
|
||||||
.filter(function(f){ return !(f in features) })
|
|
||||||
// get suggestion dependencies...
|
|
||||||
suggested = expand('depends', suggested, {},
|
|
||||||
{
|
|
||||||
loops: loops,
|
|
||||||
disabled: disabled,
|
|
||||||
})
|
|
||||||
Object.keys(suggested)
|
|
||||||
.forEach(function(f){
|
|
||||||
// keep only suggested features -- diff with features...
|
|
||||||
if(f in features){
|
|
||||||
delete suggested[f]
|
|
||||||
|
|
||||||
// mix suggested into features...
|
// suggestion list...
|
||||||
} else {
|
// ...this will be used to check if we need to break on missing
|
||||||
features[f] = suggested[f]
|
// features, e.g. if a feature is suggested we can silently skip
|
||||||
|
// it otherwise err...
|
||||||
|
//
|
||||||
|
// NOTE: this stage does not track suggested feature dependencies...
|
||||||
|
// NOTE: we do not need loop detection active here...
|
||||||
|
var s = Object.keys(
|
||||||
|
expand('suggested', Object.keys(features), {}, { disabled: disabled }))
|
||||||
|
.filter(function(f){ return !(f in features) })
|
||||||
|
// get suggestion dependencies...
|
||||||
|
// NOTE: we do not care bout missing here...
|
||||||
|
s = expand('depends', s, {},
|
||||||
|
{
|
||||||
|
loops: loops,
|
||||||
|
disabled: disabled,
|
||||||
|
disable_loops: disable_loops,
|
||||||
|
exclusive: exclusive,
|
||||||
|
})
|
||||||
|
Object.keys(s)
|
||||||
|
.forEach(function(f){
|
||||||
|
// keep only suggested features -- diff with features...
|
||||||
|
if(f in features){
|
||||||
|
delete s[f]
|
||||||
|
|
||||||
|
// mix suggested into features...
|
||||||
|
} else {
|
||||||
|
features[f] = s[f]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var features = {}
|
||||||
|
expandFeatures(lst, features)
|
||||||
|
|
||||||
|
|
||||||
|
// check for exclusivity conflicts and aliases...
|
||||||
|
var conflicts = {}
|
||||||
|
Object.keys(features)
|
||||||
|
.forEach(function(f){
|
||||||
|
// alias...
|
||||||
|
while(f in exclusive){
|
||||||
|
var candidates = (exclusive[f] || [])
|
||||||
|
.filter(function(c){ return c in features })
|
||||||
|
|
||||||
|
// resolve alias to non-included feature...
|
||||||
|
if(candidates.length == 0){
|
||||||
|
var target = exclusive[f][0]
|
||||||
|
|
||||||
|
// expand target...
|
||||||
|
expandFeatures([target], features)
|
||||||
|
|
||||||
|
// link alias to existing feature...
|
||||||
|
} else {
|
||||||
|
var target = candidates[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the alias...
|
||||||
|
delete features[f]
|
||||||
|
// replace dependencies...
|
||||||
|
Object.keys(features)
|
||||||
|
.forEach(function(e){
|
||||||
|
var i = features[e].indexOf(f)
|
||||||
|
i >= 0
|
||||||
|
&& features[e].splice(i, 1, target)
|
||||||
|
})
|
||||||
|
f = target
|
||||||
|
}
|
||||||
|
|
||||||
|
// exclusive feature...
|
||||||
|
if(f in rev_exclusive){
|
||||||
|
// XXX handle multiple groups... (???)
|
||||||
|
var group = rev_exclusive[f]
|
||||||
|
var candidates = (exclusive[group] || [])
|
||||||
|
.filter(function(c){ return c in features })
|
||||||
|
|
||||||
|
if(!(group in conflicts) && candidates.length > 1){
|
||||||
|
conflicts[group] = candidates
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// resolve any conflicts found...
|
||||||
|
Object.keys(conflicts)
|
||||||
|
.forEach(function(group){
|
||||||
|
// XXX is this how we decide which feature to keep???
|
||||||
|
disabled = disabled.concat(conflicts[group].slice(1))})
|
||||||
|
|
||||||
|
|
||||||
// check/resolve for exclusivity conflicts and aliases...
|
// reverse dependency index...
|
||||||
// XXX
|
|
||||||
|
|
||||||
|
|
||||||
// reverse dependencies -- who pulled who in... (index)
|
|
||||||
// ...this is used to clear out orphaned features later and for
|
// ...this is used to clear out orphaned features later and for
|
||||||
// introspection...
|
// introspection...
|
||||||
var rev_features = {}
|
var rev_features = {}
|
||||||
@ -1289,11 +1349,12 @@ var FeatureSetProto = {
|
|||||||
// NOTE: this requires the list to be ordered from high to low
|
// NOTE: this requires the list to be ordered from high to low
|
||||||
// priority, i.e. the same order they should be loaded in...
|
// priority, i.e. the same order they should be loaded in...
|
||||||
// NOTE: dependency loops will throw this into and "infinite" loop...
|
// NOTE: dependency loops will throw this into and "infinite" loop...
|
||||||
//
|
var loop_limit = list.length + 1
|
||||||
// XXX need a better loop detection strategy...
|
|
||||||
var loop_limit = list.length
|
|
||||||
do {
|
do {
|
||||||
var moves = 0
|
var moves = 0
|
||||||
|
if(list.length == 0){
|
||||||
|
break
|
||||||
|
}
|
||||||
list
|
list
|
||||||
.slice()
|
.slice()
|
||||||
.forEach(function(e){
|
.forEach(function(e){
|
||||||
@ -1333,15 +1394,19 @@ var FeatureSetProto = {
|
|||||||
// report loop limit...
|
// report loop limit...
|
||||||
loop_limit <= 0
|
loop_limit <= 0
|
||||||
&& console.error('Hit loop limit while sorting dependencies!')
|
&& console.error('Hit loop limit while sorting dependencies!')
|
||||||
|
// report conflicts...
|
||||||
|
Object.keys(conflicts)
|
||||||
|
.forEach(function(group){
|
||||||
|
console.error('Exclusive "'+ group +'" conflict at:', conflicts[group]) })
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
list: list,
|
list: list,
|
||||||
|
|
||||||
suggested: Object.keys(suggested),
|
|
||||||
features: features,
|
features: features,
|
||||||
rev_features: rev_features,
|
rev_features: rev_features,
|
||||||
exclusive: exclusive,
|
exclusive: exclusive,
|
||||||
|
conflicts: conflicts,
|
||||||
missing: missing,
|
missing: missing,
|
||||||
loops: loops,
|
loops: loops,
|
||||||
filtered_out: filtered_out,
|
filtered_out: filtered_out,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user