lk.FileResource

:moveChild (child, dest_parent, dest_name)

local lib = {type='lk.FileResource', IGNORE = '^%.'} lib.__index = lib lk.FileResource = lib -- Only store in cache if the body is less then this local CACHE_MAX_SIZE = 30000 local private = {}

setmetatable(lib, { -- new method -- Create a FileResource. The path MUST be relative to root -- if root is provided and must start with a '/'. __call = function(lib, url, root) local self if root then self = root.cache[url] if self then return self end self = { root = root, path = root.path .. url, url = url, } else self = { path = url, url = '', } self.root = self -- keep all resources cached self.cache = {} end if not lk.exist(self.path) then return nil else self.root.cache[self.url] = self end self.callbacks = {} setmetatable(self, lib) return self:sync() end})

-- accessor for WebDAV properties lib.davProperty = rawget

local stat, err = lfs.attributes(self.path) if not stat then -- does not exist (removed) return nil end self.name = string.match(self.path, '/([^/]+)$') self.children_list = nil self.body_cache = nil local url = self.url if self.root == self then self.url = '' self.cache[self.url] = self else self.url = string.sub(self.path, string.len(self.root.path) + 1) if url ~= self.url then if self.root.cache[url] == self then self.root.cache[url] = nil end self.root.cache[self.url] = self end end if stat.mode == 'directory' then self.is_dir = true self.resourcetype = {xml = 'collection'} -- TODO: we could keep the getlastmodified in sync (must change -- on add/removal of children and/or subchildren) self.getlastmodified = stat.modification -- FIXME: find creation date through lfs ? self.creationdate = self.getlastmodified else self.is_dir = false self.resourcetype = nil self.contenttype = private.contentType(self) self.getcontentlength = stat.size self.getlastmodified = stat.modification -- FIXME: find creation date through lfs ? self.creationdate = self.getlastmodified end return self end

if self.body_cache then return self.body_cache elseif self.getcontentlength < CACHE_MAX_SIZE then self.body_cache = lk.content(self.path) return self.body_cache else -- TODO: something that reads by chunks... (io.read func wrapper?) return lk.content(self.path) end end

if self.is_dir then return false else lk.writeall(self.path, content or '') self:sync() self:triggerCallbacks('update') return true end end

if self.is_dir then lk.rmTree(self.path, true) local url = self.url local len = string.len(url) for surl, _ in pairs(self.root.cache) do if string.sub(surl, 1, len) == url then self.root.cache[surl] = nil end end else lk.rmFile(self.path) self.root.cache[self.url] = nil end return true end

if lk.move(self.path, new_path) then self.path = new_path self:sync() return true end return false end

--- LOCK the resource. The lock has a default timeout of -- FileResource.LOCK_TIMEOUT in ms and is linked to a user. -- -- @return 'nil' if the lock cannot be granted (already locked, parent lock) -- a new lock token on succes end

end

--=============================================== Callbacks -- These are manually triggered by the controllers (typically -- the WebDAV controller when it updates files.

local clb = {...} table.insert(clb, self) local callbacks = self.callbacks[op] if not callbacks then callbacks = {} self.callbacks[op] = callbacks end table.insert(callbacks, {func, clb}) end

local callbacks = self.callbacks[op] if callbacks then for _, clbk in ipairs(callbacks) do clbk1) end end end

--=============================================== Children if not self.is_dir or not lk.exist(self.path) then return {} end local list = self.children_list if not list then -- build and store in cache list = {} self.children_list = list for file in lfs.dir(self.path) do -- IGNORE if not string.match(file, self.IGNORE) then local f = self.url..'/'..file table.insert(list, lib(f, self.root)) end end end return list end

local fullpath = self.path .. '/' .. name if body then lk.writeall(fullpath, body) else lk.makePath(fullpath) end self:sync() return lk.FileResource(self.url .. '/' .. name, self.root) end

local rez if type(res_or_name) == 'string' then local url = self.url.. '/' .. res_or_name rez = lib(url, self.root) else rez = res_or_name end if not rez or rez:delete() then self:sync() return true end return false end

local new_path = dest_parent.path .. '/' .. dest_name if child:move(new_path) then self:sync() dest_parent:sync() return true end return false end

--=============================================== PRIVATE

local EXT_TO_CONTENT_TYPE = { lkp = 'text/yaml', yml = 'text/yaml', lua = 'text/plain', }