local dir = require "opendirectory" app.on('init', function() print("scanning experiences (this make take a while..)") app.opts.plugin_diskscan_dirname = app.opts.plugin_diskscan_dir:gsub("^[.]?[/]?","") 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 }