diff options
author | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2013-05-09 15:23:21 +0300 |
---|---|---|
committer | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2013-05-09 15:24:56 +0300 |
commit | bd7b76e3316959028fc7686357fc916f56a4d10b (patch) | |
tree | 97578057c66848c158e185492aa810e42f42a09a /acf | |
parent | e8e8338ce1493e6eda04d6d745b449b9475ded30 (diff) | |
download | aconf-bd7b76e3316959028fc7686357fc916f56a4d10b.tar.bz2 aconf-bd7b76e3316959028fc7686357fc916f56a4d10b.tar.xz |
persistence: Augeas back-end rewritten
map identically named nodes to collections
implement set function
Diffstat (limited to 'acf')
-rw-r--r-- | acf/modules/generic.lua | 2 | ||||
-rw-r--r-- | acf/persistence/backends/augeas.lua | 116 | ||||
-rw-r--r-- | acf/persistence/backends/volatile.lua | 13 | ||||
-rw-r--r-- | acf/util.lua | 6 |
4 files changed, 118 insertions, 19 deletions
diff --git a/acf/modules/generic.lua b/acf/modules/generic.lua index 9ec95bf..c8abb9b 100644 --- a/acf/modules/generic.lua +++ b/acf/modules/generic.lua @@ -12,5 +12,5 @@ local M = require('acf.model') M.register('proc', M.Mixed, '/files/proc') M.permission.defaults('/proc') -M.register('augeas', M.Mixed, '/augeas/files') +M.register('augeas', M.Mixed, '/augeas') M.permission.defaults('/augeas') diff --git a/acf/persistence/backends/augeas.lua b/acf/persistence/backends/augeas.lua index d3fff0f..e25a568 100644 --- a/acf/persistence/backends/augeas.lua +++ b/acf/persistence/backends/augeas.lua @@ -6,21 +6,121 @@ See LICENSE file for license details module(..., package.seeall) local pth = require('acf.path') -local map = require('acf.util').map + +local util = require('acf.util') +local copy = util.copy + + +local function aug_path(path) return pth.join('/files', unpack(path)) end + +local function strip_name(name) + return type(name) == 'string' and string.match(name, '^[^][/=)%s]+') or name +end + +local function ipath(path, index) return path..'['..index..']' end + backend = require('acf.object').class() function backend:init() self.aug = require('augeas').init() end +function backend:find(path, tpe) + util.map( + function(comp) + return comp == strip_name(comp) and not string.match(comp, '^%.+$') + end, + path + ) + local res = aug_path(path) + + if #self.aug:match(res) == 0 and #path > 1 and tpe ~= 'table' then + local index = path[#path] + if type(index) == 'number' then + local ppath = copy(path) + table.remove(ppath) + ppath = aug_path(ppath) + + if #self.aug:match(ppath) > 0 and #self.aug:match( + ppath..'/*' + ) == 0 then + return ipath(ppath, index), ppath, index + end + end + end + + return res +end + function backend:get(path, tpe) - path = pth.join('/', unpack(path)) - local _, count = self.aug:match(path) - if count == 0 then return end + local leaf = tpe and tpe ~= 'table' + local apath, mvpath = self:find(path, tpe) - local value = self.aug:get(path) - if value ~= nil then return value end + local matches = self.aug:match(apath) + if mvpath then + assert(#matches < 2) + leaf = true + end - return map(pth.name, self.aug:match(path..'/*')) + if #matches == 0 then return end + + if #matches > 1 then + assert(not leaf) + local res = {} + path = copy(path) + for i, _ in ipairs(matches) do + table.insert(path, i) + if self:get(path) then table.insert(res, i) end + table.remove(path) + end + return res + end + + local value = self.aug:get(matches[1]) + if value then return tpe == 'table' and {1} or value end + if leaf then return end + + local names = {} + for _, child in ipairs(self.aug:match(apath..'/*')) do + names[strip_name(pth.name(child))] = true + end + return util.keys(names) end --- TODO implement set function +function backend:set(mods) + local gcpaths = {} + + for _, mod in ipairs(mods) do + local path, tpe, value = unpack(mod) + + self.aug:rm(aug_path(path)..(tpe and '/*' or '')) + + local apath, mvpath, index = self:find(path, tpe) + + if tpe and mvpath then + local size = #self.aug:match(mvpath) + while size < index do + self.aug:insert(ipath(mvpath, size), pth.name(mvpath)) + size = size + 1 + end + end + + if tpe or mvpath then self.aug:set(apath, value) + elseif apath > '/' then apath = pth.parent(apath) end + + if value == nil or value == '' then gcpaths[mvpath or apath] = true end + end + + local function gc(path) + if path == '/' or #self.aug:match(path..'/*') > 0 then return end + if self.aug:rm(path.."[. = '']") > 0 then gc(pth.parent(path)) end + end + for p, _ in pairs(gcpaths) do gc(p) end + + if self.aug:save() ~= 0 then + print('Augeas save failed') + for _, ep in ipairs(self.aug:match('/augeas//error')) do + print(ep, self.aug:get(ep)) + end + assert(false) + end +end diff --git a/acf/persistence/backends/volatile.lua b/acf/persistence/backends/volatile.lua index 339f937..7322323 100644 --- a/acf/persistence/backends/volatile.lua +++ b/acf/persistence/backends/volatile.lua @@ -5,14 +5,7 @@ See LICENSE file for license details module(..., package.seeall) -local copy = require('acf.util').copy - - -local function keys(tbl) - local res = {} - for k, v in pairs(tbl) do table.insert(res, k) end - return res -end +local util = require('acf.util') backend = require('acf.object').class() @@ -31,7 +24,7 @@ end function backend:get(path, tpe) local res = self:_get(path) - return type(res) == 'table' and keys(res) or res + return type(res) == 'table' and util.keys(res) or res end function backend:_set(path, tpe, value) @@ -40,7 +33,7 @@ function backend:_set(path, tpe, value) if #path == 0 then self.data = value else - local comps = copy(path) + local comps = util.copy(path) local name = comps[#comps] table.remove(comps) self:_get(comps)[name] = value diff --git a/acf/util.lua b/acf/util.lua index 8dd54cc..adb1e31 100644 --- a/acf/util.lua +++ b/acf/util.lua @@ -23,6 +23,12 @@ function copy(var) return type(var) == 'table' and setdefaults({}, var) or var end +function keys(tbl) + local res = {} + for k, v in pairs(tbl) do table.insert(res, k) end + return res +end + function map(func, tbl) local res = {} for k, v in pairs(tbl) do res[k] = func(copy(v)) end |