Skip to content

Instantly share code, notes, and snippets.

@dvv
Created December 7, 2011 20:16
Show Gist options
  • Save dvv/1444440 to your computer and use it in GitHub Desktop.
Save dvv/1444440 to your computer and use it in GitHub Desktop.
failing fibers
#!/usr/bin/env luvit
local Fiber = require('fiber')
local Fs = require('fs')
local Path = require('path')
--
-- mimicks find
--
local function find(path, match_fn, callback)
path = Path.normalize(path)
Fiber.new(function(resume, wait)
local err, files
-- match
match_fn(path)
-- read sub-files, if any
Fs.readdir(path, resume)
err, files = wait()
-- read error -> bail out
if err then
-- ENOTDIR: current path is not directory. reset error and proceed
-- ENOENT: e.g. broken symlink
if err.code == 'ENOTDIR' or err.code == 'ENOENT' then
err = nil
end
callback(err)
return
end
-- recursively iterate thru files
local i, file
for i, file in ipairs(files) do
-- FIXME: this is very dumb way to cope with self-pointing symlinks
if #path > 255 then
debug('TRIMMED', path)
else
find(Path.join(path, file), match_fn, resume)
-- bail out on any error
err = wait()
if (err) then break end
end
end
callback(err)
end)
end
find('/home', function(path, stat)
--debug('MATCH?', path)
end, function(err)
debug('DONE', err)
end)
local remove = require('table').remove
local normalize = Path.normalize
local inos = {}
local function find(path, match_fn, callback)
assert(type(path) == 'string')
assert(type(match_fn) == 'function')
assert(type(callback) == 'function')
path = normalize(path)
Fiber.new(function(resume, wait)
local err, stat, files
-- stat resolving symlinks
Fs.stat(path, resume)
err, stat = wait()
-- stat failed -> bail out
if err then
callback(err)
return
end
if stat and stat.ino and inos[stat.ino] then
p('SEEN', path, inos[stat.ino])
inos[stat.ino] = inos[stat.ino] + 1
callback()
return
end
if stat and stat.ino then
inos[stat.ino] = 1
end
-- match
match_fn(path, stat)
-- path is not directory?
if not stat.is_directory then
callback()
return
end
-- path is directory. read files
Fs.readdir(path, resume)
err, files = wait()
-- read error -> bail out
if err then
callback(err)
return
end
-- recursively iterate thru files
while #files do
local file = remove(files)
find(Path.join(path, file), match_fn, resume)
-- bail out on any error
err = wait()
--if (err) then break end
end
callback(err)
end)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment