summaryrefslogtreecommitdiffstats
path: root/acf
diff options
context:
space:
mode:
authorKaarle Ritvanen <kaarle.ritvanen@datakunkku.fi>2013-05-09 15:23:21 +0300
committerKaarle Ritvanen <kaarle.ritvanen@datakunkku.fi>2013-05-09 15:24:56 +0300
commitbd7b76e3316959028fc7686357fc916f56a4d10b (patch)
tree97578057c66848c158e185492aa810e42f42a09a /acf
parente8e8338ce1493e6eda04d6d745b449b9475ded30 (diff)
downloadaconf-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.lua2
-rw-r--r--acf/persistence/backends/augeas.lua116
-rw-r--r--acf/persistence/backends/volatile.lua13
-rw-r--r--acf/util.lua6
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