summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/gitano/util.lua70
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/gitano/util.lua b/lib/gitano/util.lua
index 44ad5ed..51c5bc2 100644
--- a/lib/gitano/util.lua
+++ b/lib/gitano/util.lua
@@ -8,6 +8,7 @@
local luxio = require 'luxio'
local sio = require 'luxio.simple'
+local log = require 'gitano.log'
local tconcat = table.concat
@@ -251,6 +252,71 @@ local function copy_symlink(from, to)
return true
end
+local function copy_pathname_filter(exclude_set)
+ return function(parent_path, filename, fileinfo)
+ return exclude_set[filename]
+ end
+end
+local _exclude_builtin = { ["."] = true, [".."] = true }
+local copy_dir_filter_base = copy_pathname_filter(_exclude_builtin)
+
+local copy_dir_copy_callbacks
+-- filter_cb is a function, which takes (parent_path, filename, fileinfo)
+-- and returns true if the component should not be copied
+-- parent_path is required, since filter_cb is passed on to subdirectories
+-- copy_cbs is an optional table of callbacks
+local function copy_dir(from, to, copy_cbs, filter_cb)
+ filter_cb = filter_cb or copy_dir_filter_base
+ copy_cbs = copy_cbs or copy_dir_copy_callbacks
+ local ret, err, dirp
+ ret, err = mkdir_p(to)
+ if not ret then
+ return ret, err
+ end
+ dirp, err, ret = sio.opendir(from)
+ if not dirp then
+ return ret, err
+ end
+ for filename, fileinfo in dirp:iterate() do
+ local copycb = copy_cbs[fileinfo.d_type]
+ local filefrom = path_join(from, filename)
+ local fileto = path_join(to, filename)
+ if filter_cb(from, filename, fileinfo) then
+ log.ddebug("Skipping file", filename)
+ elseif fileinfo.d_type == luxio.DT_REG then
+ log.ddebug("Copying file", filefrom, "to", fileto)
+ ret, err = copycb(filefrom, fileto)
+ if not ret then
+ log.critical("Copy file", filefrom, "to", fileto, "failed:", err)
+ return false, err
+ end
+ elseif fileinfo.d_type == luxio.DT_LNK then
+ log.ddebug("Copying symlink", filefrom, "to", fileto)
+ ret, err = copycb(filefrom, fileto)
+ if not ret then
+ log.critical("Copy symlink", filefrom, "to", fileto, "failed:", err)
+ return false, err
+ end
+ elseif fileinfo.d_type == luxio.DT_DIR then
+ log.ddebug("Copying dir", filefrom, "to", fileto)
+ ret, err = copycb(filefrom, fileto, copy_cbs, filter_cb)
+ if not ret then
+ log.critical("Copy dir", filefrom, "to", fileto, "failed:", err)
+ return ret, err
+ end
+ else
+ return false, ("Unsupported file type %d"):format(fileinfo.d_type)
+ end
+ end
+ return true
+end
+
+copy_dir_copy_callbacks = {
+ [luxio.DT_DIR] = copy_dir,
+ [luxio.DT_REG] = copy_file,
+ [luxio.DT_LNK] = copy_symlink,
+}
+
local function html_escape(s)
return (s:gsub("&", "&"):
gsub("<", "&lt;"):
@@ -399,6 +465,10 @@ return {
copy_file = copy_file,
mkdir_p = mkdir_p,
rm_rf = rm_rf,
+ copy_pathname_filter = copy_pathname_filter,
+ copy_dir_filter_base = copy_dir_filter_base,
+ copy_dir_copy_callbacks = copy_dir_copy_callbacks,
+ copy_dir = copy_dir,
html_escape = html_escape,