[latex3-commits] [latex3/luaotfload] database-iteration-refactor: Add realpath util (e6d7f9d5)
github at latex-project.org
github at latex-project.org
Sun Jan 28 15:22:24 CET 2024
Repository : https://github.com/latex3/luaotfload
On branch : database-iteration-refactor
Link : https://github.com/latex3/luaotfload/commit/e6d7f9d5d9ed5d6f2ad8c684240d7c13a34aef48
>---------------------------------------------------------------
commit e6d7f9d5d9ed5d6f2ad8c684240d7c13a34aef48
Author: Marcel Fabian Krüger <tex at 2krueger.de>
Date: Sun Jan 28 15:19:09 2024 +0100
Add realpath util
>---------------------------------------------------------------
e6d7f9d5d9ed5d6f2ad8c684240d7c13a34aef48
src/luaotfload-realpath.lua | 99 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
diff --git a/src/luaotfload-realpath.lua b/src/luaotfload-realpath.lua
new file mode 100644
index 00000000..d2609f85
--- /dev/null
+++ b/src/luaotfload-realpath.lua
@@ -0,0 +1,99 @@
+-- Helper to resolve symlinks in paths
+
+local sub = string.sub
+local symlinkattributes = lfs.symlinkattributes
+local currentdir = lfs.currentdir
+local concat = table.concat
+local move = table.move
+local newtable = lua.newtable
+local setmetatable = setmetatable
+
+-- Marker key for elements of result_tree to indicate the path components entry and the file mode
+local path_components, file_mode = {}, {}
+local tree_root
+
+local split_path do
+ local l = lpeg
+ local separator = l.S'/'
+ -- We do not allow empty segments here because they get ignored.
+ local segment = l.C((1 - separator)^1)
+ -- Duplicate and trailing separators are dropped.
+ local path_pat = l.Ct((l.Cc'' * separator^1)^-1 * (segment * separator^1)^0 * segment^-1 * -1)
+ function split_path(path)
+ return assert(path_pat:match(path))
+ end
+end
+
+local function lookup_split_path_in_tree(components, tree)
+ if components[1] == '' then
+ tree = tree_root
+ end
+ for i=1, #components do
+ tree = tree[components[i]]
+ end
+ return tree
+end
+
+local tree_meta
+tree_meta = {
+ __index = function(parent, component)
+ local parent_components = parent[path_components]
+ local depth = #parent_components
+ local components = move(parent[path_components], 1, depth, 1, newtable(depth + 1, 0))
+ components[depth + 1] = component
+ local path = concat(components, '/')
+
+ local mode = symlinkattributes(path, 'mode')
+ if mode == 'link' then
+ local target = symlinkattributes(path, 'target')
+ local splitted_target = split_path(target)
+ local target_tree = lookup_split_path_in_tree(splitted_target, parent)
+ parent[component] = target_tree
+ return target_tree
+ end
+
+ local child = setmetatable({
+ [path_components] = components,
+ [file_mode] = mode,
+ }, tree_meta)
+ -- if mode == 'directory' then
+ child['.'] = child
+ child['..'] = parent
+ -- end
+ parent[component] = child
+ return child
+ end,
+}
+
+-- We assume that the directory structure does not change during our run.
+tree_root = {
+ [''] = setmetatable({
+ [path_components] = {''},
+ [file_mode] = 'directory', -- "If [your root is not a directory] you are having a bad problem and you will not go to space today".
+ }, tree_meta)
+}
+do
+ local root_dir = tree_root['']
+ root_dir['.'] = root_dir
+ root_dir['..'] = root_dir
+end
+
+local function resolve_path_to_tree(path)
+ local splitted = split_path(path)
+ if splitted[1] == '' then -- Optimization to avoid currentdir lookup.
+ return lookup_split_path_in_tree(splitted, tree_root)
+ else
+ local splitted_currentdir = split_path(currentdir())
+ local current_tree = lookup_split_path_in_tree(splitted_currentdir, tree_root)
+ return lookup_split_path_in_tree(splitted, current_tree)
+ end
+end
+
+local function resolve_path(path)
+ local tree = resolve_path_to_tree(path)
+ return concat(tree[path_components], '/'), tree[file_mode]
+end
+
+return {
+ realpath = resolve_path,
+}
More information about the latex3-commits
mailing list.