--[[ Copyright (c) 2012-2015 Kaarle Ritvanen See LICENSE file for license details --]] local topology = require('aconf.model.root').topology local pth = require('aconf.path') local util = require('aconf.persistence.util') local posix = require('posix') local stringy = require('stringy') local function get_scope(top) if not top or top.type ~= 'reference' or not pth.is_unique(top.scope) then return end return stringy.startswith( top.scope, '/files/' ) and top.scope:sub(7, -1) or nil end local backend = require('aconf.object').class() -- TODO cache expiration function backend:init() self.cache = {} end function backend:get(path, top) local name = pth.join('/', table.unpack(path)) if not self.cache[name] then local t = posix.stat(name, 'type') if not t then return end if t == 'regular' then self.cache[name] = util.read_file(name) elseif t == 'link' then -- TODO handle relative symlinks local target = posix.readlink(name) assert(target) local scope = get_scope(top) assert(scope) scope = scope..'/' local slen = scope:len() assert(target:sub(1, slen) == scope) return target:sub(slen + 1, -1) elseif t == 'directory' then local res = {} for _, fname in ipairs(posix.dir(name)) do if not ({['.']=true, ['..']=true})[fname] then table.insert(res, pth.name(fname)) end end return res else error('Unsupported file type: '..name) end end return self.cache[name] end function backend:set(mods) for _, mod in pairs(mods) do local path, value = table.unpack(mod) local name = pth.join('/', table.unpack(path)) if value == nil then print('DEL', name) local t = posix.stat(name, 'type') if t == 'directory' then assert(posix.rmdir(name)) elseif t then assert(os.remove(name)) end self.cache[name] = nil elseif type(value) == 'table' then assert(posix.mkdir(name)) else local scope = get_scope(topology('/files'..name)) if scope then -- TODO use relative symlink os.remove(name) assert(posix.link(pth.to_absolute(value, scope), name, true)) else local file = util.open_file(name, 'w') file:write(util.tostring(value)) file:close() self.cache[name] = value end end end end return backend