From 3afc21546f4580bfe2e85988699a3357c707fc50 Mon Sep 17 00:00:00 2001 From: Tom van Dijck Date: Mon, 24 Aug 2015 08:44:09 -0700 Subject: [PATCH] Allow querying values without combining values from parent configs. --- src/base/configset.lua | 129 ++++++++++++++++++++++++----------------- src/base/context.lua | 15 ++++- 2 files changed, 88 insertions(+), 56 deletions(-) diff --git a/src/base/configset.lua b/src/base/configset.lua index 7a142d43..20f7e30d 100644 --- a/src/base/configset.lua +++ b/src/base/configset.lua @@ -63,23 +63,31 @@ -- the context filtering case-insensitive. -- @param ctx -- The context that will be used for detoken.expand +-- @param origin +-- The originating configset if set. -- @return -- The requested value. --- - function configset.fetch(cset, field, filter, ctx) + function configset.fetch(cset, field, filter, ctx, origin) filter = filter or {} ctx = ctx or {} if p.field.merges(field) then - return configset._fetchMerged(cset, field, filter, ctx) + return configset._fetchMerged(cset, field, filter, ctx, origin) else - return configset._fetchDirect(cset, field, filter, ctx) + return configset._fetchDirect(cset, field, filter, ctx, origin) end end - function configset._fetchDirect(cset, field, filter, ctx) + function configset._fetchDirect(cset, field, filter, ctx, origin) + -- If the originating configset hasn't been compiled, then the value will still + -- be on that configset. + if origin and origin ~= cset and not origin.compiled then + return configset._fetchDirect(origin, field, filter, ctx, origin) + end + local abspath = filter.files local basedir @@ -88,40 +96,48 @@ local n = #blocks for i = n, 1, -1 do local block = blocks[i] - local value = block[key] - -- If the filter contains a file path, make it relative to - -- this block's basedir - if value ~= nil and abspath and not cset.compiled and block._basedir and block._basedir ~= basedir then - basedir = block._basedir - filter.files = path.getrelative(basedir, abspath) - end + if not origin or block._origin == origin then + local value = block[key] - if value ~= nil and (cset.compiled or criteria.matches(block._criteria, filter)) then - -- If value is an object, return a copy of it so that any - -- changes later made to it by the caller won't alter the - -- original value (that was a tough bug to find) - if type(value) == "table" then - value = table.deepcopy(value) - end - -- Detoken - if field.tokens and ctx.environ then - value = p.detoken.expand(value, ctx.environ, field, ctx._basedir) + -- If the filter contains a file path, make it relative to + -- this block's basedir + if value ~= nil and abspath and not cset.compiled and block._basedir and block._basedir ~= basedir then + basedir = block._basedir + filter.files = path.getrelative(basedir, abspath) end - return value + if value ~= nil and (cset.compiled or criteria.matches(block._criteria, filter)) then + -- If value is an object, return a copy of it so that any + -- changes later made to it by the caller won't alter the + -- original value (that was a tough bug to find) + if type(value) == "table" then + value = table.deepcopy(value) + end + -- Detoken + if field.tokens and ctx.environ then + value = p.detoken.expand(value, ctx.environ, field, ctx._basedir) + end + return value + end end end filter.files = abspath if cset.parent then - return configset._fetchDirect(cset.parent, field, filter, ctx) + return configset._fetchDirect(cset.parent, field, filter, ctx, origin) end end - function configset._fetchMerged(cset, field, filter, ctx) + function configset._fetchMerged(cset, field, filter, ctx, origin) + -- If the originating configset hasn't been compiled, then the value will still + -- be on that configset. + if origin and origin ~= cset and not origin.compiled then + return configset._fetchMerged(origin, field, filter, ctx, origin) + end + local result = {} local function remove(patterns) @@ -146,7 +162,7 @@ end if cset.parent then - result = configset._fetchMerged(cset.parent, field, filter, ctx) + result = configset._fetchMerged(cset.parent, field, filter, ctx, origin) end local abspath = filter.files @@ -157,38 +173,39 @@ local n = #blocks for i = 1, n do local block = blocks[i] - - -- If the filter contains a file path, make it relative to - -- this block's basedir - if abspath and block._basedir and block._basedir ~= basedir and not cset.compiled then - basedir = block._basedir - filter.files = path.getrelative(basedir, abspath) - end - - if cset.compiled or criteria.matches(block._criteria, filter) then - if block._removes and block._removes[key] then - remove(block._removes[key]) + if not origin or block._origin == origin then + -- If the filter contains a file path, make it relative to + -- this block's basedir + if abspath and block._basedir and block._basedir ~= basedir and not cset.compiled then + basedir = block._basedir + filter.files = path.getrelative(basedir, abspath) end - local value = block[key] - -- If value is an object, return a copy of it so that any - -- changes later made to it by the caller won't alter the - -- original value (that was a tough bug to find) - if type(value) == "table" then - value = table.deepcopy(value) - end - - if value then - -- Detoken - if field.tokens and ctx.environ then - value = p.detoken.expand(value, ctx.environ, field, ctx._basedir) - end - -- Translate - if field and p.field.translates(field) then - value = p.field.translate(field, value) + if cset.compiled or criteria.matches(block._criteria, filter) then + if block._removes and block._removes[key] then + remove(block._removes[key]) end - result = p.field.merge(field, result, value) + local value = block[key] + -- If value is an object, return a copy of it so that any + -- changes later made to it by the caller won't alter the + -- original value (that was a tough bug to find) + if type(value) == "table" then + value = table.deepcopy(value) + end + + if value then + -- Detoken + if field.tokens and ctx.environ then + value = p.detoken.expand(value, ctx.environ, field, ctx._basedir) + end + -- Translate + if field and p.field.translates(field) then + value = p.field.translate(field, value) + end + + result = p.field.merge(field, result, value) + end end end end @@ -283,6 +300,7 @@ local block = {} block._criteria = crit + block._origin = cset if basedir then block._basedir = basedir:lower() @@ -309,6 +327,7 @@ local block = {} block._criteria = filter._criteria block._basedir = filter._basedir + block._origin = cset table.insert(cset.blocks, block) cset.current = block; end @@ -373,6 +392,7 @@ local block = {} block._basedir = cset.current._basedir block._criteria = cset.current._criteria + block._origin = cset table.insert(cset.blocks, block) cset.current = block @@ -447,6 +467,9 @@ for i = 1, n do local block = blocks[i] + if block._origin == cset then + block._origin = result + end -- If the filter contains a file path, make it relative to -- this block's basedir diff --git a/src/base/context.lua b/src/base/context.lua index 1762fb1e..a3e0e357 100644 --- a/src/base/context.lua +++ b/src/base/context.lua @@ -168,26 +168,35 @@ -- The context to query. -- @param key -- The property key to query. +-- @param onlylocal +-- If true, don't combine values from parent contexts. -- @return -- The value of the key, as determined by the configuration set. If -- there is a corresponding Premake field, and it the field is enabled -- for tokens, any contained tokens will be expanded. -- - function context.fetchvalue(ctx, key) + function context.fetchvalue(ctx, key, onlylocal) + if not onlylocal then + local value = rawget(ctx, key) + if value ~= nil then + return value + end + end + -- The underlying configuration set will only hold registered fields. -- If the requested key doesn't have a corresponding field, it is just -- a regular value to be stored and fetched from the table. local field = p.field.get(key) if not field then - return rawget(ctx, key) + return nil end -- If there is a matching field, then go fetch the aggregated value -- from my configuration set, and then cache it future lookups. - local value = configset.fetch(ctx._cfgset, field, ctx.terms, ctx) + local value = configset.fetch(ctx._cfgset, field, ctx.terms, ctx, onlylocal and ctx._cfgset) if value then -- store the result for later lookups ctx[key] = value