--[[ Copyright (c) 2012-2013 Kaarle Ritvanen See LICENSE file for license details --]] module(..., package.seeall) local pth = require('acf.path') local util = require('acf.persistence.util') require 'posix' require 'stringy' backend = require('acf.object').class() -- TODO cache expiration function backend:init() self.cache = {} end function backend:get(path, tpe) local name = pth.join('/', 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) if not tpe then return target end assert(stringy.startswith(tpe, 'reference/files/')) local scope = string.sub(tpe, 16, -1)..'/' local slen = string.len(scope) assert(string.sub(target, 1, slen) == scope) return string.sub(target, 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, tpe, value = unpack(mod) local name = pth.join('/', unpack(path)) if not tpe 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 tpe == 'table' then assert(posix.mkdir(name)) elseif stringy.startswith(tpe, 'reference/files/') then -- TODO use relative symlink os.remove(name) assert( posix.link( pth.to_absolute(value, string.sub(tpe, 16, -1)), name, true ) ) else local file = util.open_file(name, 'w') file:write(tostring(value)) file:close() self.cache[name] = value end end end