xrforge-v2/src/plugin/diskscan.lua

122 lines
3.9 KiB
Lua
Raw Normal View History

local dir = require "opendirectory"
2026-07-28 08:50:24 +02:00
app.on('init', function()
print("scanning experiences (this make take a while..)")
app.opts.plugin_diskscan_dirname = app.opts.plugin_diskscan_dir:gsub("^[.]?[/]?","")
2026-07-28 08:50:24 +02:00
app.plugin.diskscan.scan(app.opts.plugin_diskscan_dir)
end)
-- this registers the plugin UI /funcs
return {
name = "Content (from disk)",
info = '',
opts = {
{
key='app.opts.plugin_diskscan_dir',
title='Directory',
info="Directory to scan for experiences (use '.' for current) ",
default="./myverse",
values=''
}
},
shouldHideFile = function(name)
return name == ".." -- parent
or name == "util" -- repository
or name:match("^%.") -- hidden
or name == "src" -- repository
or name == "result" -- repository
end,
scan = function(scandir,parent,seen)
local seen = seen or {}
local me = app.plugin.diskscan
-- ensure rootdir as experience
app.cache.items[ scandir ] = {
path = scandir,
url = util.stripPath(scandir),
name = scandir:gsub(".*/",""),
title = scandir:gsub(".*/",""),
file = { ino = scandir },
id = scandir
}
parent = parent or app.cache.items[scandir]
-- scan dirs
local scanFile = function(symlinksOnly)
return function(path,stat,state,name,kind,ino,off,attr,fullpath)
if seen[ino] then return end
local experience = {
path = fullpath,
url = util.stripPath(fullpath),
name = name,
title = name,
sidecarfile = {},
tag = {},
id = ino,
file = {stat=stat,state=state,kind=kind,ino=ino,off=off,attr=attr,fullpath=fullpath,name=name,path=path}
}
experience.parent = parent
if (symlinksOnly and kind == unix.DT_LNK)
and not me.shouldHideFile(name) then
--seen[ino] = experience.file -- prevent recursion with symlinks
local stat, err = unix.stat(fullpath)
local refItem = seen[stat:ino()]
if refItem then
print("ℹ️ ".. fullpath)
print("✅ └─ plugin/diskscan: detected circular symlink..creating portal")
experience.file = refItem.file
experience.portal = refItem
app.pub("scan_experience", nil, experience)
app.cache.items[ino] = experience
else
print(":(")
print("symlink: " .. fullpath)
print_r(experience)
end
end
if symlinksOnly then return end
-- found directory
if (kind == unix.DT_DIR and kind ~= unix.DT_LNK)
and not me.shouldHideFile(name) then
seen[ino] = experience -- prevent recursion with symlinks
print("✅ ".. fullpath)
experience.dir = true
app.pub("scan_experience", nil, experience)
app.cache.items[ino] = experience
me.scan(fullpath,experience,seen)
end
---- found file
if (kind ~= unix.DT_DIR and kind ~= unix.DT_LNK)
and not me.shouldHideFile(name) then
seen[ino] = experience.file -- prevent recursion with symlinks
trace("ℹ️ ".. fullpath)
experience.tag.file = true
app.pub("scan_experience_file", nil, experience)
local size = attr:size()
end
end
end
-- first we scan real files, afterwards symlinks (to deal with circular symlinks)
local dref, derr;
print("--- no symlink")
dref, derr = dir.foreach( scandir, scanFile(false) )
if not derr then dref:close() end
print("--- symlink")
dref, derr = dir.foreach( scandir, scanFile(true) )
if not derr then dref:close() end
-- cleanup file handles
foreach( app.cache.items, function(k,v)
-- remove file attributes (which are closed already)
v.file.stat = nil
v.file.attr = nil
v.file.state = nil
end)
end
}