mirror of
https://github.com/octoleo/lsyncd.git
synced 2024-06-04 09:20:51 +00:00
rewriting array/queue/counter prototypes. restructuring mantle
This commit is contained in:
parent
41aec3a3f8
commit
cd8ce93a1e
|
@ -35,6 +35,15 @@ include_directories("${PROJECT_BINARY_DIR}")
|
|||
# building and compiling the part of lsyncd written in Lua
|
||||
|
||||
set( LUA_CODE
|
||||
${PROJECT_SOURCE_DIR}/mantle/array.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/counter.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/queue.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/lock.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/delay.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/inotify.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/combiner.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/inlet.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/filter.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/lsyncd.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/wrapup.lua
|
||||
${PROJECT_SOURCE_DIR}/default/default.lua
|
||||
|
|
168
mantle/array.lua
Normal file
168
mantle/array.lua
Normal file
|
@ -0,0 +1,168 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- array.lua
|
||||
--
|
||||
--
|
||||
-- Array tables error if accessed with a non-number.
|
||||
-- They maintain their length as an attribute and are zero based.
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Metatable.
|
||||
--
|
||||
local mt = { }
|
||||
|
||||
--
|
||||
-- Key to native table.
|
||||
--
|
||||
local k_nt = { }
|
||||
|
||||
--
|
||||
-- Key to size entry.
|
||||
--
|
||||
local k_size = { }
|
||||
|
||||
--
|
||||
-- On accessing a nil index.
|
||||
--
|
||||
mt.__index = function
|
||||
(
|
||||
self,
|
||||
k -- key used to access
|
||||
)
|
||||
if type( k ) ~= 'number'
|
||||
then
|
||||
error( 'Array, key "'..k..'" invalid', 2 )
|
||||
end
|
||||
|
||||
if k < 0 or k >= self[ k_size ]
|
||||
then
|
||||
error( 'Array, key "'..k..'" out of bonds', 2 )
|
||||
end
|
||||
|
||||
return self[ k_nt ][ k ]
|
||||
end
|
||||
|
||||
--
|
||||
-- On assigning a new index.
|
||||
--
|
||||
mt.__newindex = function
|
||||
(
|
||||
self,
|
||||
k, -- key value to assign to
|
||||
v -- value to assign
|
||||
)
|
||||
if type( k ) ~= 'number'
|
||||
then
|
||||
error( 'Array, key "'..k..'" invalid', 2 )
|
||||
end
|
||||
|
||||
if k < 0 or k > self[ k_size ]
|
||||
then
|
||||
error( 'Array, key "'..k..'" out of bonds', 2 )
|
||||
end
|
||||
|
||||
if k == self[ k_size ]
|
||||
then
|
||||
self[ k_size ] = self[ k_size ] + 1
|
||||
end
|
||||
|
||||
self[ k_nt ][ k ] = v
|
||||
end
|
||||
|
||||
--
|
||||
-- Returns the length of the array.
|
||||
--
|
||||
mt.__len = function
|
||||
(
|
||||
self
|
||||
)
|
||||
return self[ k_size ]
|
||||
end
|
||||
|
||||
--
|
||||
-- Errors on use of pairs( )
|
||||
--
|
||||
mt.__pairs = function
|
||||
(
|
||||
self
|
||||
)
|
||||
error( 'Array, do not use pairs( )', 2 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Returns next value in iterator.
|
||||
--
|
||||
local function iter
|
||||
(
|
||||
self,
|
||||
pos
|
||||
)
|
||||
pos = pos + 1
|
||||
|
||||
if pos == self[ k_size ] then return nil end
|
||||
|
||||
return pos, self[ k_nt ][ pos ]
|
||||
end
|
||||
|
||||
--
|
||||
-- Allows walking throw the array.
|
||||
--
|
||||
mt.__ipairs = function
|
||||
(
|
||||
self
|
||||
)
|
||||
return iter, self, -1
|
||||
end
|
||||
|
||||
--
|
||||
-- Pushes a new new value on the end of the array
|
||||
--
|
||||
local function push
|
||||
(
|
||||
self,
|
||||
v
|
||||
)
|
||||
self[ k_nt ][ self[ k_size ] ] = v
|
||||
|
||||
self[ k_size ] = self[ k_size ] + 1
|
||||
end
|
||||
|
||||
--
|
||||
-- Creates a new array.
|
||||
--
|
||||
local function new
|
||||
( )
|
||||
-- k_nt is a native table, private to this object.
|
||||
local o =
|
||||
{
|
||||
push = push,
|
||||
[ k_size ] = 0,
|
||||
[ k_nt ] = { }
|
||||
}
|
||||
|
||||
setmetatable( o, mt )
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
--
|
||||
-- Exported interface.
|
||||
--
|
||||
Array = { new = new }
|
||||
|
358
mantle/combiner.lua
Normal file
358
mantle/combiner.lua
Normal file
|
@ -0,0 +1,358 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- combiner.lua Live (Mirror) Syncing Demon
|
||||
--
|
||||
--
|
||||
-- Combines delays.
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- The new delay replaces the old one if it's a file
|
||||
--
|
||||
local function refi
|
||||
(
|
||||
d1, -- old delay
|
||||
d2 -- new delay
|
||||
)
|
||||
-- but a directory blocks
|
||||
if d2.path:byte( -1 ) == 47
|
||||
then
|
||||
log(
|
||||
'Delay',
|
||||
d2.etype,': ',d2.path,
|
||||
' blocked by ',
|
||||
d1.etype,': ',d1.path
|
||||
)
|
||||
|
||||
return 'stack'
|
||||
end
|
||||
|
||||
log(
|
||||
'Delay',
|
||||
d2.etype, ': ', d2.path,
|
||||
' replaces ',
|
||||
d1.etype, ': ', d1.path
|
||||
)
|
||||
|
||||
return 'replace'
|
||||
end
|
||||
|
||||
--
|
||||
-- Table on how to combine events that dont involve a move.
|
||||
--
|
||||
local combineNoMove =
|
||||
{
|
||||
Attrib =
|
||||
{
|
||||
Attrib = 'absorb',
|
||||
Modify = 'replace',
|
||||
Create = 'replace',
|
||||
Delete = 'replace'
|
||||
},
|
||||
|
||||
Modify =
|
||||
{
|
||||
Attrib = 'absorb',
|
||||
Modify = 'absorb',
|
||||
Create = 'replace',
|
||||
Delete = 'replace'
|
||||
},
|
||||
|
||||
Create =
|
||||
{
|
||||
Attrib = 'absorb',
|
||||
Modify = 'absorb',
|
||||
Create = 'absorb',
|
||||
Delete = 'replace'
|
||||
},
|
||||
|
||||
Delete =
|
||||
{
|
||||
Attrib = 'absorb',
|
||||
Modify = 'absorb',
|
||||
Create = 'replace file,block dir',
|
||||
Delete = 'absorb'
|
||||
},
|
||||
}
|
||||
|
||||
--
|
||||
-- Returns the way two Delay should be combined.
|
||||
--
|
||||
-- Result:
|
||||
-- nil -- They don't affect each other.
|
||||
-- 'stack' -- Old Delay blocks new Delay.
|
||||
-- 'replace' -- Old Delay is replaced by new Delay.
|
||||
-- 'absorb' -- Old Delay absorbs new Delay.
|
||||
-- 'toDelete,stack' -- Old Delay is turned into a Delete
|
||||
-- and blocks the new Delay.
|
||||
-- 'split' -- New Delay a Move is to be split
|
||||
-- into a Create and Delete.
|
||||
--
|
||||
local function combine
|
||||
(
|
||||
d1, -- old delay
|
||||
d2 -- new delay
|
||||
)
|
||||
if d1.etype == 'Init' or d1.etype == 'Blanket'
|
||||
then
|
||||
return 'stack'
|
||||
end
|
||||
|
||||
-- two normal events
|
||||
if d1.etype ~= 'Move' and d2.etype ~= 'Move'
|
||||
then
|
||||
if d1.path == d2.path
|
||||
then
|
||||
-- lookups up the function in the combination matrix
|
||||
-- and calls it
|
||||
local result = combineNoMove[ d1.etype ][ d2.etype ]
|
||||
|
||||
if result == 'replace file,block dir'
|
||||
then
|
||||
if d2.path:byte( -1 ) == 47
|
||||
then
|
||||
return 'stack'
|
||||
else
|
||||
return 'replace'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- if one is a parent directory of another, events are blocking
|
||||
if d1.path:byte( -1 ) == 47 and string.starts( d2.path, d1.path )
|
||||
or d2.path:byte( -1 ) == 47 and string.starts( d1.path, d2.path )
|
||||
then
|
||||
return 'stack'
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- non-move event on a move.
|
||||
if d1.etype == 'Move' and d2.etype ~= 'Move'
|
||||
then
|
||||
-- if the move source could be damaged the events are stacked
|
||||
if d1.path == d2.path
|
||||
or d2.path:byte( -1 ) == 47 and string.starts( d1.path, d2.path )
|
||||
or d1.path:byte( -1 ) == 47 and string.starts( d2.path, d1.path )
|
||||
then
|
||||
return 'stack'
|
||||
end
|
||||
|
||||
-- the event does something with the move destination
|
||||
|
||||
if d1.path2 == d2.path
|
||||
then
|
||||
if d2.etype == 'Delete'
|
||||
or d2.etype == 'Create'
|
||||
then
|
||||
return 'toDelete,stack'
|
||||
end
|
||||
|
||||
-- on 'Attrib' or 'Modify' simply stack on moves
|
||||
return 'stack'
|
||||
end
|
||||
|
||||
if d2.path:byte( -1 ) == 47 and string.starts( d1.path2, d2.path )
|
||||
or d1.path2:byte( -1 ) == 47 and string.starts( d2.path, d1.path2 )
|
||||
then
|
||||
return 'stack'
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- a move upon a non-move event
|
||||
if d1.etype ~= 'Move' and d2.etype == 'Move'
|
||||
then
|
||||
if d1.path == d2.path
|
||||
or d1.path == d2.path2
|
||||
or d1.path:byte( -1 ) == 47 and string.starts( d2.path, d1.path )
|
||||
or d1.path:byte( -1 ) == 47 and string.starts( d2.path2, d1.path )
|
||||
or d2.path:byte( -1 ) == 47 and string.starts( d1.path, d2.path )
|
||||
or d2.path2:byte( -1 ) == 47 and string.starts( d1.path, d2.path2 )
|
||||
then
|
||||
return 'split'
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--
|
||||
-- a move event upon a move event
|
||||
--
|
||||
if d1.etype == 'Move' and d2.etype == 'Move'
|
||||
then
|
||||
-- TODO combine moves,
|
||||
if d1.path == d2.path
|
||||
or d1.path == d2.path2
|
||||
or d1.path2 == d2.path
|
||||
or d2.path2 == d2.path
|
||||
or d1.path:byte( -1 ) == 47 and string.starts( d2.path, d1.path )
|
||||
or d1.path:byte( -1 ) == 47 and string.starts( d2.path2, d1.path )
|
||||
or d1.path2:byte( -1 ) == 47 and string.starts( d2.path, d1.path2 )
|
||||
or d1.path2:byte( -1 ) == 47 and string.starts( d2.path2, d1.path2 )
|
||||
or d2.path:byte( -1 ) == 47 and string.starts( d1.path, d2.path )
|
||||
or d2.path:byte( -1 ) == 47 and string.starts( d1.path2, d2.path )
|
||||
or d2.path2:byte( -1 ) == 47 and string.starts( d1.path, d2.path2 )
|
||||
or d2.path2:byte( -1 ) == 47 and string.starts( d1.path2, d2.path2 )
|
||||
then
|
||||
return 'split'
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
error( 'reached impossible state' )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- The new delay is absorbed by an older one.
|
||||
--
|
||||
local function logAbsorb
|
||||
(
|
||||
d1, -- old delay
|
||||
d2 -- new delay
|
||||
)
|
||||
log( 'Delay', d2.etype, ': ',d2.path, ' absorbed by ', d1.etype,': ',d1.path )
|
||||
end
|
||||
|
||||
--
|
||||
-- The new delay replaces the old one if it's a file.
|
||||
--
|
||||
local function logReplace
|
||||
(
|
||||
d1, -- old delay
|
||||
d2 -- new delay
|
||||
)
|
||||
log( 'Delay', d2.etype, ': ', d2.path, ' replaces ', d1.etype, ': ', d1.path )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- The new delay splits on the old one.
|
||||
--
|
||||
local function logSplit
|
||||
(
|
||||
d1, -- old delay
|
||||
d2 -- new delay
|
||||
)
|
||||
log(
|
||||
'Delay', d2.etype, ': ', d2.path, ' -> ', d2.path2,
|
||||
' splits on ', d1.etype, ': ', d1.path
|
||||
)
|
||||
end
|
||||
|
||||
--
|
||||
-- The new delay is blocked by the old delay.
|
||||
--
|
||||
local function logStack
|
||||
(
|
||||
d1, -- old delay
|
||||
d2 -- new delay
|
||||
)
|
||||
local active = ''
|
||||
|
||||
if d1.active then active = 'active ' end
|
||||
|
||||
if d2.path2
|
||||
then
|
||||
log(
|
||||
'Delay',
|
||||
d2.etype, ': ',
|
||||
d2.path, '->', d2.path2,
|
||||
' blocked by ',
|
||||
active,
|
||||
d1.etype, ': ', d1.path
|
||||
)
|
||||
else
|
||||
log(
|
||||
'Delay',
|
||||
d2.etype, ': ', d2.path,
|
||||
' blocked by ',
|
||||
active,
|
||||
d1.etype, ': ', d1.path
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- The new delay turns the old one (a move) into a delete and is blocked.
|
||||
--
|
||||
local function logToDeleteStack
|
||||
(
|
||||
d1, -- old delay
|
||||
d2 -- new delay
|
||||
)
|
||||
if d1.path2
|
||||
then
|
||||
log(
|
||||
'Delay',
|
||||
d2.etype, ': ', d2.path,
|
||||
' turns ',
|
||||
d1.etype, ': ', d1.path, ' -> ', d1.path2,
|
||||
' into Delete: ', d1.path
|
||||
)
|
||||
else
|
||||
log(
|
||||
'Delay',
|
||||
d2.etype, ': ', d2.path,
|
||||
' turns ',
|
||||
d1.etype, ': ', d1.path,
|
||||
' into Delete: ', d1.path
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local logFuncs =
|
||||
{
|
||||
absorb = logAbsorb,
|
||||
replace = logReplace,
|
||||
split = logSplit,
|
||||
stack = logStack,
|
||||
[ 'toDelete,stack' ] = logToDeleteStack
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
-- Prints the log message for a combination result
|
||||
--
|
||||
local function log
|
||||
(
|
||||
result, -- the combination result
|
||||
d1, -- old delay
|
||||
d2 -- new delay
|
||||
)
|
||||
local lf = logFuncs[ result ]
|
||||
|
||||
if not lf
|
||||
then
|
||||
error( 'unknown combination result: ' .. result )
|
||||
end
|
||||
|
||||
lf( d1, d2 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Public interface
|
||||
--
|
||||
Combiner = { combine = combine, log = log }
|
||||
|
124
mantle/counter.lua
Normal file
124
mantle/counter.lua
Normal file
|
@ -0,0 +1,124 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- counter.lua
|
||||
--
|
||||
--
|
||||
-- Couter tables simply keep a count of the number of elements
|
||||
-- in them
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Metatable.
|
||||
--
|
||||
local mt = { }
|
||||
|
||||
--
|
||||
-- Key to native table.
|
||||
--
|
||||
local k_nt = { }
|
||||
|
||||
--
|
||||
-- Key to size entry.
|
||||
--
|
||||
local k_size = { }
|
||||
|
||||
--
|
||||
-- On accessing a nil index.
|
||||
--
|
||||
mt.__index = function
|
||||
(
|
||||
self,
|
||||
k -- key used to access
|
||||
)
|
||||
return self[ k_nt ][ k ]
|
||||
end
|
||||
|
||||
--
|
||||
-- On assigning a new index.
|
||||
--
|
||||
mt.__newindex = function
|
||||
(
|
||||
self,
|
||||
k, -- key value to assign to
|
||||
v -- value to assign
|
||||
)
|
||||
local nt = self[ k_nt ]
|
||||
|
||||
if nt[ k ] == nil
|
||||
then
|
||||
if v ~= nil then self[ k_size ] = self[ k_size ] + 1 end
|
||||
else
|
||||
if v == nil then self[ k_size ] = self[ k_size ] - 1 end
|
||||
end
|
||||
|
||||
nt[ k ] = v
|
||||
end
|
||||
|
||||
--
|
||||
-- Returns the length of the counter.
|
||||
--
|
||||
mt.__len = function
|
||||
(
|
||||
self
|
||||
)
|
||||
return self[ k_size ]
|
||||
end
|
||||
|
||||
--
|
||||
-- Allows walking throw the counter.
|
||||
--
|
||||
mt.__pairs = function
|
||||
(
|
||||
self
|
||||
)
|
||||
return pairs( self[ k_nt ] )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Allows integral walking throw the counter.
|
||||
--
|
||||
mt.__ipairs = function
|
||||
(
|
||||
self
|
||||
)
|
||||
return ipairs( self[ k_nt ] )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Creates a new counter.
|
||||
--
|
||||
local function new
|
||||
( )
|
||||
-- k_nt is a native table, private to this object.
|
||||
local o =
|
||||
{
|
||||
[ k_size ] = 0,
|
||||
[ k_nt ] = { }
|
||||
}
|
||||
|
||||
setmetatable( o, mt )
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
--
|
||||
-- Exported interface.
|
||||
--
|
||||
Counter = { new = new }
|
||||
|
162
mantle/delay.lua
Normal file
162
mantle/delay.lua
Normal file
|
@ -0,0 +1,162 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- delay.lua Live (Mirror) Syncing Demon
|
||||
--
|
||||
--
|
||||
-- Holds the information about a delayed event for one Sync.
|
||||
--
|
||||
-- Valid stati of a delay are:
|
||||
-- 'wait' ... the event is ready to be handled.
|
||||
-- 'active' ... there is process running catering for this event.
|
||||
-- 'blocked' ... this event waits for another to be handled first.
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Metatable.
|
||||
--
|
||||
local mt = { }
|
||||
|
||||
|
||||
--
|
||||
-- Secret key to native table
|
||||
--
|
||||
local k_nt = { }
|
||||
|
||||
|
||||
local assignAble =
|
||||
{
|
||||
dpos = true,
|
||||
etype = true,
|
||||
path = true,
|
||||
path2 = true,
|
||||
status = true,
|
||||
}
|
||||
|
||||
--
|
||||
-- On accessing a nil index.
|
||||
--
|
||||
mt.__index = function
|
||||
(
|
||||
self,
|
||||
k -- key value accessed
|
||||
)
|
||||
return self[ k_nt ][ k ]
|
||||
end
|
||||
|
||||
--
|
||||
-- On assigning a new index.
|
||||
--
|
||||
mt.__newindex = function
|
||||
(
|
||||
self,
|
||||
k, -- key value to assign to
|
||||
v -- value to assign
|
||||
)
|
||||
if not assignAble[ k ]
|
||||
then
|
||||
error( 'Cannot assign new key "' .. k .. '" to Delay' )
|
||||
end
|
||||
|
||||
self[ k_nt ][ k ] = v
|
||||
end
|
||||
|
||||
--
|
||||
-- This delay is being blocked by another delay
|
||||
--
|
||||
local function blockedBy
|
||||
(
|
||||
self, -- this delay
|
||||
delay -- the blocking delay
|
||||
)
|
||||
self[ k_nt ].status = 'block'
|
||||
|
||||
local blocks = delay[ k_nt ].blocks
|
||||
|
||||
if not blocks
|
||||
then
|
||||
blocks = { }
|
||||
|
||||
delay[ k_nt ].blocks = blocks
|
||||
end
|
||||
|
||||
table.insert( blocks, self )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Sets the delay status to 'active'.
|
||||
--
|
||||
local function setActive
|
||||
(
|
||||
self
|
||||
)
|
||||
self[ k_nt ].status = 'active'
|
||||
end
|
||||
|
||||
--
|
||||
-- Sets the delay status to 'wait'
|
||||
--
|
||||
local function wait
|
||||
(
|
||||
self, -- this delay
|
||||
alarm -- alarm for the delay
|
||||
)
|
||||
self[ k_nt ].status = 'wait'
|
||||
|
||||
self[ k_nt ].alarm = alarm
|
||||
end
|
||||
|
||||
--
|
||||
-- Creates a new delay.
|
||||
--
|
||||
local function new
|
||||
(
|
||||
etype, -- type of event.
|
||||
-- 'Create', 'Modify', 'Attrib', 'Delete' or 'Move'
|
||||
sync, -- the Sync this delay belongs to
|
||||
alarm, -- latest point in time this should be catered for
|
||||
path, -- path and file-/dirname of the delay relative
|
||||
-- -- to the syncs root.
|
||||
path2 -- used only in moves, path and file-/dirname of
|
||||
-- move destination
|
||||
)
|
||||
local delay =
|
||||
{
|
||||
blockedBy = blockedBy,
|
||||
setActive = setActive,
|
||||
wait = wait,
|
||||
[ k_nt ] =
|
||||
{
|
||||
etype = etype,
|
||||
sync = sync,
|
||||
alarm = alarm,
|
||||
path = path,
|
||||
path2 = path2,
|
||||
status = 'wait'
|
||||
},
|
||||
}
|
||||
|
||||
setmetatable( delay, mt )
|
||||
|
||||
return delay
|
||||
end
|
||||
|
||||
--
|
||||
-- Exported interface
|
||||
--
|
||||
Delay = { new = new }
|
||||
|
189
mantle/filter.lua
Normal file
189
mantle/filter.lua
Normal file
|
@ -0,0 +1,189 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- filter.lua
|
||||
--
|
||||
--
|
||||
-- A set of filter patterns.
|
||||
--
|
||||
-- Filters allow excludes and includes
|
||||
--
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Turns a rsync like file pattern to a lua pattern.
|
||||
-- ( at best it can )
|
||||
--
|
||||
local function toLuaPattern
|
||||
(
|
||||
p -- the rsync like pattern
|
||||
)
|
||||
local o = p
|
||||
|
||||
p = string.gsub( p, '%%', '%%%%' )
|
||||
p = string.gsub( p, '%^', '%%^' )
|
||||
p = string.gsub( p, '%$', '%%$' )
|
||||
p = string.gsub( p, '%(', '%%(' )
|
||||
p = string.gsub( p, '%)', '%%)' )
|
||||
p = string.gsub( p, '%.', '%%.' )
|
||||
p = string.gsub( p, '%[', '%%[' )
|
||||
p = string.gsub( p, '%]', '%%]' )
|
||||
p = string.gsub( p, '%+', '%%+' )
|
||||
p = string.gsub( p, '%-', '%%-' )
|
||||
p = string.gsub( p, '%?', '[^/]' )
|
||||
p = string.gsub( p, '%*', '[^/]*' )
|
||||
-- this was a ** before
|
||||
p = string.gsub( p, '%[%^/%]%*%[%^/%]%*', '.*' )
|
||||
p = string.gsub( p, '^/', '^/' )
|
||||
|
||||
if p:sub( 1, 2 ) ~= '^/'
|
||||
then
|
||||
-- if does not begin with '^/'
|
||||
-- then all matches should begin with '/'.
|
||||
p = '/' .. p;
|
||||
end
|
||||
|
||||
log( 'Filter', 'toLuaPattern "', o, '" = "', p, '"' )
|
||||
|
||||
return p
|
||||
end
|
||||
|
||||
--
|
||||
-- Appends a filter pattern
|
||||
--
|
||||
local function append
|
||||
(
|
||||
self, -- the filters object
|
||||
line -- filter line
|
||||
)
|
||||
local rule, pattern = string.match( line, '%s*([+|-])%s*(.*)' )
|
||||
|
||||
if not rule or not pattern
|
||||
then
|
||||
log( 'Error', 'Unknown filter rule: "', line, '"' )
|
||||
terminate( -1 )
|
||||
end
|
||||
|
||||
local lp = toLuaPattern( pattern )
|
||||
|
||||
table.insert( self. list, { rule = rule, pattern = pattern, lp = lp } )
|
||||
end
|
||||
|
||||
--
|
||||
-- Adds a list of patterns to filter.
|
||||
--
|
||||
local function appendList
|
||||
(
|
||||
self,
|
||||
plist
|
||||
)
|
||||
for _, v in ipairs( plist )
|
||||
do
|
||||
append( self, v )
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Loads the filters from a file.
|
||||
--
|
||||
local function loadFile
|
||||
(
|
||||
self, -- self
|
||||
file -- filename to load from
|
||||
)
|
||||
f, err = io.open( file )
|
||||
|
||||
if not f
|
||||
then
|
||||
log( 'Error', 'Cannot open filter file "', file, '": ', err )
|
||||
|
||||
terminate( -1 )
|
||||
end
|
||||
|
||||
for line in f:lines( )
|
||||
do
|
||||
if string.match( line, '^%s*#' )
|
||||
or string.match( line, '^%s*$' )
|
||||
then
|
||||
-- a comment or empty line: ignore
|
||||
else
|
||||
append( self, line )
|
||||
end
|
||||
end
|
||||
|
||||
f:close( )
|
||||
end
|
||||
|
||||
--
|
||||
-- Tests if 'path' is filtered.
|
||||
-- Returns false if it is to be filtered.
|
||||
--
|
||||
local function test
|
||||
(
|
||||
self, -- self
|
||||
path -- the path to test
|
||||
)
|
||||
if path:byte( 1 ) ~= 47
|
||||
then
|
||||
error( 'Paths for filter tests must start with \'/\'' )
|
||||
end
|
||||
|
||||
for _, entry in ipairs( self.list )
|
||||
do
|
||||
local rule = entry.rule
|
||||
local lp = entry.lp -- lua pattern
|
||||
|
||||
if lp:byte( -1 ) == 36
|
||||
then
|
||||
-- ends with $
|
||||
if path:match( lp )
|
||||
then
|
||||
return rule == '+'
|
||||
end
|
||||
else
|
||||
-- ends either end with / or $
|
||||
if path:match( lp .. '/' )
|
||||
or path:match( lp .. '$' )
|
||||
then
|
||||
return rule == '+'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--
|
||||
-- Cretes a new filter set.
|
||||
--
|
||||
local function new
|
||||
( )
|
||||
return {
|
||||
list = { },
|
||||
-- functions
|
||||
append = append,
|
||||
appendList = appendList,
|
||||
loadFile = loadFile,
|
||||
test = test,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Exported interface.
|
||||
--
|
||||
Filter = { new = new }
|
||||
|
712
mantle/inlet.lua
Normal file
712
mantle/inlet.lua
Normal file
|
@ -0,0 +1,712 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- lsyncd.lua Live (Mirror) Syncing Demon
|
||||
--
|
||||
--
|
||||
-- Creates inlets for syncs: the user interface for events.
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Table to receive the delay of an event
|
||||
-- or the delay list of an event list.
|
||||
--
|
||||
-- Keys are events and values are delays.
|
||||
--
|
||||
local e2d = { }
|
||||
|
||||
--
|
||||
-- Table to ensure the uniqueness of every event
|
||||
-- related to a delay.
|
||||
--
|
||||
-- Keys are delay and values are events.
|
||||
--
|
||||
local e2d2 = { }
|
||||
|
||||
--
|
||||
-- Allows the garbage collector to remove not refrenced
|
||||
-- events.
|
||||
--
|
||||
setmetatable( e2d, { __mode = 'k' } )
|
||||
setmetatable( e2d2, { __mode = 'v' } )
|
||||
|
||||
--
|
||||
-- Removes the trailing slash from a path.
|
||||
--
|
||||
local function cutSlash
|
||||
(
|
||||
path -- path to cut
|
||||
)
|
||||
if string.byte( path, -1 ) == 47
|
||||
then
|
||||
return string.sub( path, 1, -2 )
|
||||
else
|
||||
return path
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Gets the path of an event.
|
||||
--
|
||||
local function getPath
|
||||
(
|
||||
event
|
||||
)
|
||||
if event.move ~= 'To'
|
||||
then
|
||||
return e2d[ event ].path
|
||||
else
|
||||
return e2d[ event ].path2
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Interface for user scripts to get event fields.
|
||||
--
|
||||
local eventFields =
|
||||
{
|
||||
--
|
||||
-- Returns a copy of the configuration as called by sync.
|
||||
-- But including all inherited data and default values.
|
||||
--
|
||||
-- TODO give user a readonly version.
|
||||
--
|
||||
config = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ].sync.config
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the inlet belonging to an event.
|
||||
--
|
||||
inlet = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ].sync.inlet
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the type of the event.
|
||||
--
|
||||
-- Can be: 'Attrib', 'Create', 'Delete', 'Modify' or 'Move',
|
||||
--
|
||||
etype = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ].etype
|
||||
end,
|
||||
|
||||
--
|
||||
-- Events are not lists.
|
||||
--
|
||||
isList = function
|
||||
( )
|
||||
return false
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the status of the event.
|
||||
--
|
||||
-- Can be:
|
||||
-- 'wait', 'active', 'block'.
|
||||
--
|
||||
status = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ].status
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns true if event relates to a directory
|
||||
--
|
||||
isdir = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return string.byte( getPath( event ), -1 ) == 47
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the name of the file/dir.
|
||||
--
|
||||
-- Includes a trailing slash for dirs.
|
||||
--
|
||||
name = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return string.match( getPath( event ), '[^/]+/?$' )
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the name of the file/dir
|
||||
-- excluding a trailing slash for dirs.
|
||||
--
|
||||
basename = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return string.match( getPath( event ), '([^/]+)/?$')
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the file/dir relative to watch root
|
||||
-- including a trailing slash for dirs.
|
||||
--
|
||||
path = function
|
||||
(
|
||||
event
|
||||
)
|
||||
local p = getPath( event )
|
||||
|
||||
if string.byte( p, 1 ) == 47
|
||||
then
|
||||
p = string.sub( p, 2, -1 )
|
||||
end
|
||||
|
||||
return p
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the directory of the file/dir relative to watch root
|
||||
-- Always includes a trailing slash.
|
||||
--
|
||||
pathdir = function
|
||||
(
|
||||
event
|
||||
)
|
||||
local p = getPath( event )
|
||||
|
||||
if string.byte( p, 1 ) == 47
|
||||
then
|
||||
p = string.sub( p, 2, -1 )
|
||||
end
|
||||
|
||||
return string.match( p, '^(.*/)[^/]+/?' ) or ''
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the file/dir relativ to watch root
|
||||
-- excluding a trailing slash for dirs.
|
||||
--
|
||||
pathname = function
|
||||
(
|
||||
event
|
||||
)
|
||||
local p = getPath( event )
|
||||
|
||||
if string.byte( p, 1 ) == 47
|
||||
then
|
||||
p = string.sub( p, 2, -1 )
|
||||
end
|
||||
|
||||
return cutSlash( p )
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the absolute path of the watch root.
|
||||
-- All symlinks are resolved.
|
||||
--
|
||||
source = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ].sync.source
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the absolute path of the file/dir
|
||||
-- including a trailing slash for dirs.
|
||||
--
|
||||
sourcePath = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ].sync.source .. getPath( event )
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the absolute dir of the file/dir
|
||||
-- including a trailing slash.
|
||||
--
|
||||
sourcePathdir = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return(
|
||||
e2d[event].sync.source
|
||||
.. (
|
||||
string.match( getPath( event ), '^(.*/)[^/]+/?' )
|
||||
or ''
|
||||
)
|
||||
)
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the absolute path of the file/dir
|
||||
-- excluding a trailing slash for dirs.
|
||||
--
|
||||
sourcePathname = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ].sync.source .. cutSlash( getPath( event ) )
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the configured target.
|
||||
--
|
||||
target = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ].sync.config.target
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the relative dir/file appended to the target
|
||||
-- including a trailing slash for dirs.
|
||||
--
|
||||
targetPath = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ].sync.config.target .. getPath( event )
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the dir of the dir/file appended to the target
|
||||
-- including a trailing slash.
|
||||
--
|
||||
targetPathdir = function
|
||||
(
|
||||
event
|
||||
)
|
||||
return(
|
||||
e2d[ event ].sync.config.target
|
||||
.. (
|
||||
string.match( getPath( event ), '^(.*/)[^/]+/?' )
|
||||
or ''
|
||||
)
|
||||
)
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the relative dir/file appended to the target
|
||||
-- excluding a trailing slash for dirs.
|
||||
--
|
||||
targetPathname = function( event )
|
||||
return(
|
||||
e2d[ event ].sync.config.target
|
||||
.. cutSlash( getPath( event ) )
|
||||
)
|
||||
end,
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
-- Retrievs event fields for the user script.
|
||||
--
|
||||
local eventMeta =
|
||||
{
|
||||
__index = function
|
||||
(
|
||||
event,
|
||||
field
|
||||
)
|
||||
local f = eventFields[ field ]
|
||||
|
||||
if not f
|
||||
then
|
||||
if field == 'move'
|
||||
then
|
||||
-- possibly undefined
|
||||
return nil
|
||||
end
|
||||
|
||||
error( 'event does not have field "' .. field .. '"', 2 )
|
||||
end
|
||||
|
||||
return f( event )
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
-- Interface for user scripts to get list fields.
|
||||
--
|
||||
local eventListFuncs =
|
||||
{
|
||||
--
|
||||
-- Returns a list of paths of all events in list.
|
||||
--
|
||||
--
|
||||
getPaths = function
|
||||
(
|
||||
elist, -- handle returned by getevents( )
|
||||
mutator -- if not nil called with ( etype, path, path2 )
|
||||
-- returns one or two strings to add.
|
||||
)
|
||||
local dlist = e2d[ elist ]
|
||||
|
||||
if not dlist
|
||||
then
|
||||
error( 'cannot find delay list from event list.' )
|
||||
end
|
||||
|
||||
local result = { }
|
||||
local resultn = 1
|
||||
|
||||
for k, d in ipairs( dlist )
|
||||
do
|
||||
local s1, s2
|
||||
|
||||
if mutator
|
||||
then
|
||||
s1, s2 = mutator( d.etype, d.path, d.path2 )
|
||||
else
|
||||
s1, s2 = d.path, d.path2
|
||||
end
|
||||
|
||||
result[ resultn ] = s1
|
||||
|
||||
resultn = resultn + 1
|
||||
|
||||
if s2
|
||||
then
|
||||
result[ resultn ] = s2
|
||||
|
||||
resultn = resultn + 1
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
-- Retrievs event list fields for the user script
|
||||
--
|
||||
local eventListMeta =
|
||||
{
|
||||
__index = function
|
||||
(
|
||||
elist,
|
||||
func
|
||||
)
|
||||
if func == 'isList'
|
||||
then
|
||||
return true
|
||||
end
|
||||
|
||||
if func == 'config'
|
||||
then
|
||||
return e2d[ elist ].sync.config
|
||||
end
|
||||
|
||||
local f = eventListFuncs[ func ]
|
||||
|
||||
if not f
|
||||
then
|
||||
error(
|
||||
'event list does not have function "' .. func .. '"',
|
||||
2
|
||||
)
|
||||
end
|
||||
|
||||
return function
|
||||
( ... )
|
||||
return f( elist, ... )
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
-- Table of all inlets with their syncs.
|
||||
--
|
||||
local inlets = { }
|
||||
|
||||
--
|
||||
-- Allows the garbage collector to remove entries.
|
||||
--
|
||||
setmetatable( inlets, { __mode = 'v' } )
|
||||
|
||||
--
|
||||
-- Encapsulates a delay into an event for the user script.
|
||||
--
|
||||
local function d2e
|
||||
(
|
||||
delay -- delay to encapsulate
|
||||
)
|
||||
-- already created?
|
||||
local eu = e2d2[ delay ]
|
||||
|
||||
if delay.etype ~= 'Move'
|
||||
then
|
||||
if eu then return eu end
|
||||
|
||||
local event = { }
|
||||
|
||||
setmetatable( event, eventMeta )
|
||||
|
||||
e2d[ event ] = delay
|
||||
|
||||
e2d2[ delay ] = event
|
||||
|
||||
return event
|
||||
else
|
||||
-- moves have 2 events - origin and destination
|
||||
if eu then return eu[1], eu[2] end
|
||||
|
||||
local event = { move = 'Fr' }
|
||||
local event2 = { move = 'To' }
|
||||
|
||||
setmetatable( event, eventMeta )
|
||||
setmetatable( event2, eventMeta )
|
||||
|
||||
e2d[ event ] = delay
|
||||
e2d[ event2 ] = delay
|
||||
|
||||
e2d2[ delay ] = { event, event2 }
|
||||
|
||||
-- move events have a field 'move'
|
||||
return event, event2
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Encapsulates a delay list into an event list for the user script.
|
||||
--
|
||||
local function dl2el
|
||||
(
|
||||
dlist
|
||||
)
|
||||
local eu = e2d2[ dlist ]
|
||||
|
||||
if eu then return eu end
|
||||
|
||||
local elist = { }
|
||||
|
||||
setmetatable( elist, eventListMeta )
|
||||
|
||||
e2d [ elist ] = dlist
|
||||
|
||||
e2d2[ dlist ] = elist
|
||||
|
||||
return elist
|
||||
end
|
||||
|
||||
--
|
||||
-- The functions the inlet provides.
|
||||
--
|
||||
local inletFuncs =
|
||||
{
|
||||
--
|
||||
-- Appens a filter.
|
||||
--
|
||||
appendFilter = function
|
||||
(
|
||||
sync, -- the sync of the inlet
|
||||
rule, -- '+' or '-'
|
||||
pattern -- exlusion pattern to add
|
||||
)
|
||||
sync:appendFilter( rule, pattern )
|
||||
end,
|
||||
|
||||
--
|
||||
-- Gets the list of filters and excldues
|
||||
-- as rsync-like filter/patterns form.
|
||||
--
|
||||
getFilters = function
|
||||
(
|
||||
sync -- the sync of the inlet
|
||||
)
|
||||
-- creates a copy
|
||||
local e = { }
|
||||
local en = 1;
|
||||
|
||||
if sync.filters
|
||||
then
|
||||
for _, entry in ipairs( sync.filters.list )
|
||||
do
|
||||
e[ en ] = entry.rule .. ' ' .. entry.pattern;
|
||||
en = en + 1;
|
||||
end
|
||||
end
|
||||
|
||||
return e;
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns true if the sync has filters
|
||||
--
|
||||
hasFilters = function
|
||||
(
|
||||
sync -- the sync of the inlet
|
||||
)
|
||||
return not not sync.filters
|
||||
end,
|
||||
|
||||
--
|
||||
-- Creates a blanketEvent that blocks everything
|
||||
-- and is blocked by everything.
|
||||
--
|
||||
createBlanketEvent = function
|
||||
(
|
||||
sync -- the sync of the inlet
|
||||
)
|
||||
return d2e( sync:addBlanketDelay( ) )
|
||||
end,
|
||||
|
||||
--
|
||||
-- Discards a waiting event.
|
||||
--
|
||||
discardEvent = function
|
||||
(
|
||||
sync,
|
||||
event
|
||||
)
|
||||
local delay = e2d[ event ]
|
||||
|
||||
if delay.status ~= 'wait'
|
||||
then
|
||||
log(
|
||||
'Error',
|
||||
'Ignored cancel of a non-waiting event of type ',
|
||||
event.etype
|
||||
)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
sync:removeDelay( delay )
|
||||
end,
|
||||
|
||||
--
|
||||
-- Gets the next not blocked event from queue.
|
||||
--
|
||||
getEvent = function
|
||||
(
|
||||
sync
|
||||
)
|
||||
return d2e( sync:getNextDelay( now( ) ) )
|
||||
end,
|
||||
|
||||
--
|
||||
-- Gets all events that are not blocked by active events.
|
||||
--
|
||||
getEvents = function
|
||||
(
|
||||
sync, -- the sync of the inlet
|
||||
test -- if not nil use this function to test if to include an event
|
||||
)
|
||||
local dlist = sync:getDelays( test )
|
||||
|
||||
return dl2el( dlist )
|
||||
end,
|
||||
|
||||
--
|
||||
-- Returns the configuration table specified by sync{ }
|
||||
--
|
||||
getConfig = function( sync )
|
||||
-- TODO give a readonly handler only.
|
||||
return sync.config
|
||||
end,
|
||||
}
|
||||
|
||||
--
|
||||
-- Forwards access to inlet functions.
|
||||
--
|
||||
local inletMeta =
|
||||
{
|
||||
__index = function
|
||||
(
|
||||
inlet,
|
||||
func
|
||||
)
|
||||
local f = inletFuncs[ func ]
|
||||
|
||||
if not f
|
||||
then
|
||||
error( 'inlet does not have function "'..func..'"', 2 )
|
||||
end
|
||||
|
||||
return function( ... )
|
||||
return f( inlets[ inlet ], ... )
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
--
|
||||
-- Creates a new inlet for a sync.
|
||||
--
|
||||
local function newInlet
|
||||
(
|
||||
sync -- the sync to create the inlet for
|
||||
)
|
||||
-- Lsyncd runner controlled variables
|
||||
local inlet = { }
|
||||
|
||||
-- sets use access methods
|
||||
setmetatable( inlet, inletMeta )
|
||||
|
||||
inlets[ inlet ] = sync
|
||||
|
||||
return inlet
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Returns the delay from a event.
|
||||
--
|
||||
local function getDelayOrList
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ]
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Returns the sync from an event or list
|
||||
--
|
||||
local function getSync
|
||||
(
|
||||
event
|
||||
)
|
||||
return e2d[ event ].sync
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Exported interface.
|
||||
--
|
||||
InletFactory = {
|
||||
getDelayOrList = getDelayOrList,
|
||||
d2e = d2e,
|
||||
dl2el = dl2el,
|
||||
getSync = getSync,
|
||||
newInlet = newInlet,
|
||||
}
|
||||
|
314
mantle/inotify.lua
Normal file
314
mantle/inotify.lua
Normal file
|
@ -0,0 +1,314 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- inotify.lua
|
||||
--
|
||||
--
|
||||
-- Interface to inotify core.
|
||||
--
|
||||
-- watches recursively subdirs and sends events.
|
||||
-- All inotify specific implementation is enclosed here.
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Safes mantle stuff
|
||||
--
|
||||
local core = core
|
||||
local log = core.log
|
||||
local Syncs
|
||||
local uSettings
|
||||
|
||||
|
||||
--
|
||||
-- Returns the relative part of absolute path if it
|
||||
-- begins with root
|
||||
--
|
||||
local function splitPath
|
||||
(
|
||||
path,
|
||||
root
|
||||
)
|
||||
local rlen = #root
|
||||
|
||||
local sp = string.sub( path, 1, rlen )
|
||||
|
||||
if sp == root
|
||||
then
|
||||
return string.sub( path, rlen, -1 )
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- A list indexed by inotify watch descriptors yielding
|
||||
-- the directories absolute paths.
|
||||
--
|
||||
local wdpaths = Counter.new( )
|
||||
|
||||
--
|
||||
-- The same vice versa,
|
||||
-- all watch descriptors by their absolute paths.
|
||||
--
|
||||
local pathwds = { }
|
||||
|
||||
--
|
||||
-- A list indexed by syncs containing yielding
|
||||
-- the root paths the syncs are interested in.
|
||||
--
|
||||
local syncRoots = { }
|
||||
|
||||
--
|
||||
-- Stops watching a directory
|
||||
--
|
||||
local function removeWatch
|
||||
(
|
||||
path, -- absolute path to unwatch
|
||||
core -- if false not actually send the unwatch to the kernel
|
||||
-- ( used in moves which reuse the watch )
|
||||
)
|
||||
local wd = pathwds[ path ]
|
||||
|
||||
if not wd then return end
|
||||
|
||||
if core then core.inotify.rmwatch( wd ) end
|
||||
|
||||
wdpaths[ wd ] = nil
|
||||
pathwds[ path ] = nil
|
||||
end
|
||||
|
||||
--
|
||||
-- Adds watches for a directory (optionally) including all subdirectories.
|
||||
--
|
||||
local function addWatch
|
||||
(
|
||||
path -- absolute path of directory to observe
|
||||
)
|
||||
log( 'Function', 'Inotify.addWatch( ', path, ' )' )
|
||||
|
||||
if not Syncs.concerns( path )
|
||||
then
|
||||
log( 'Inotify', 'not concerning "', path, '"')
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- registers the watch
|
||||
local inotifyMode = ( uSettings and uSettings.inotifyMode ) or ''
|
||||
|
||||
local wd = core.inotify.addwatch( path, inotifyMode )
|
||||
|
||||
if wd < 0
|
||||
then
|
||||
log( 'Inotify', 'Unable to add watch "', path, '"' )
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
do
|
||||
-- If this watch descriptor is registered already
|
||||
-- the kernel reuses it since the old dir is gone.
|
||||
local op = wdpaths[ wd ]
|
||||
|
||||
if op and op ~= path then pathwds[ op ] = nil end
|
||||
end
|
||||
|
||||
pathwds[ path ] = wd
|
||||
|
||||
wdpaths[ wd ] = path
|
||||
|
||||
-- registers and adds watches for all subdirectories
|
||||
local entries = core.readdir( path )
|
||||
|
||||
if not entries then return end
|
||||
|
||||
for dirname, isdir in pairs( entries )
|
||||
do
|
||||
if isdir then addWatch( path .. dirname .. '/' ) end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Adds a Sync to receive events.
|
||||
--
|
||||
local function addSync
|
||||
(
|
||||
sync, -- object to receive events.
|
||||
rootdir -- root dir to watch
|
||||
)
|
||||
if syncRoots[ sync ]
|
||||
then
|
||||
error( 'duplicate sync in Inotify.addSync()' )
|
||||
end
|
||||
|
||||
syncRoots[ sync ] = rootdir
|
||||
|
||||
addWatch( rootdir )
|
||||
end
|
||||
|
||||
--
|
||||
-- Called when an event has occured.
|
||||
--
|
||||
local function event
|
||||
(
|
||||
etype, -- 'Attrib', 'Modify', 'Create', 'Delete', 'Move'
|
||||
wd, -- watch descriptor, matches core.inotifyadd()
|
||||
isdir, -- true if filename is a directory
|
||||
time, -- time of event
|
||||
filename, -- string filename without path
|
||||
wd2, -- watch descriptor for target if it's a Move
|
||||
filename2 -- string filename without path of Move target
|
||||
)
|
||||
if isdir
|
||||
then
|
||||
filename = filename .. '/'
|
||||
|
||||
if filename2 then filename2 = filename2 .. '/' end
|
||||
end
|
||||
|
||||
if filename2
|
||||
then
|
||||
log(
|
||||
'Inotify',
|
||||
'got event ', etype, ' ',
|
||||
filename, '(', wd, ') to ',
|
||||
filename2, '(', wd2 ,')'
|
||||
)
|
||||
else
|
||||
log(
|
||||
'Inotify',
|
||||
'got event ', etype, ' ',
|
||||
filename, '(', wd, ')'
|
||||
)
|
||||
end
|
||||
|
||||
-- looks up the watch descriptor id
|
||||
local path = wdpaths[ wd ]
|
||||
|
||||
if path then path = path..filename end
|
||||
|
||||
local path2 = wd2 and wdpaths[ wd2 ]
|
||||
|
||||
if path2 and filename2 then path2 = path2..filename2 end
|
||||
|
||||
if not path and path2 and etype == 'Move'
|
||||
then
|
||||
log( 'Inotify', 'Move from deleted directory ', path2, ' becomes Create.' )
|
||||
|
||||
path = path2
|
||||
|
||||
path2 = nil
|
||||
|
||||
etype = 'Create'
|
||||
end
|
||||
|
||||
if not path
|
||||
then
|
||||
-- this is normal in case of deleted subdirs
|
||||
log( 'Inotify', 'event belongs to unknown watch descriptor.' )
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
for sync, root in pairs( syncRoots )
|
||||
do repeat
|
||||
local relative = splitPath( path, root )
|
||||
|
||||
local relative2 = nil
|
||||
|
||||
if path2 then relative2 = splitPath( path2, root ) end
|
||||
|
||||
if not relative and not relative2
|
||||
then
|
||||
-- sync is not interested in this dir
|
||||
break -- continue
|
||||
end
|
||||
|
||||
-- makes a copy of etype to possibly change it
|
||||
local etyped = etype
|
||||
|
||||
if etyped == 'Move'
|
||||
then
|
||||
if not relative2
|
||||
then
|
||||
log(
|
||||
'Normal',
|
||||
'Transformed Move to Delete for ',
|
||||
sync.config.name
|
||||
)
|
||||
|
||||
etyped = 'Delete'
|
||||
elseif not relative
|
||||
then
|
||||
relative = relative2
|
||||
|
||||
relative2 = nil
|
||||
|
||||
log(
|
||||
'Normal',
|
||||
'Transformed Move to Create for ',
|
||||
sync.config.name
|
||||
)
|
||||
|
||||
etyped = 'Create'
|
||||
end
|
||||
end
|
||||
|
||||
if isdir
|
||||
then
|
||||
if etyped == 'Create'
|
||||
then
|
||||
addWatch( path )
|
||||
elseif etyped == 'Delete'
|
||||
then
|
||||
removeWatch( path, true )
|
||||
elseif etyped == 'Move'
|
||||
then
|
||||
removeWatch( path, false )
|
||||
addWatch( path2 )
|
||||
end
|
||||
end
|
||||
|
||||
sync:delay( etyped, time, relative, relative2 )
|
||||
|
||||
until true end
|
||||
end
|
||||
|
||||
--
|
||||
-- Writes a status report about inotify to a file descriptor
|
||||
--
|
||||
local function statusReport( f )
|
||||
|
||||
f:write( 'Inotify watching ', #wdpaths, ' directories\n' )
|
||||
|
||||
for wd, path in pairs( wdpaths )
|
||||
do
|
||||
f:write( ' ', wd, ': ', path, '\n' )
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Exported interface.
|
||||
--
|
||||
Inotify =
|
||||
{
|
||||
addSync = addSync,
|
||||
event = event,
|
||||
statusReport = statusReport,
|
||||
|
||||
-- FIXME
|
||||
init = function( _Syncs, _uSettings ) Syncs = _Syncs; uSettings = _uSettings end
|
||||
}
|
67
mantle/lock.lua
Normal file
67
mantle/lock.lua
Normal file
|
@ -0,0 +1,67 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- lsyncd.lua Live (Mirror) Syncing Demon
|
||||
--
|
||||
--
|
||||
-- Locks globals.
|
||||
--
|
||||
-- No more globals can be created after this!
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
local t = _G
|
||||
|
||||
local mt = getmetatable( t ) or { }
|
||||
|
||||
|
||||
-- TODO try to remove the underscore exceptions
|
||||
mt.__index = function
|
||||
(
|
||||
t, -- table being accessed
|
||||
k -- key used to access
|
||||
)
|
||||
if k ~= '_' and string.sub( k, 1, 2 ) ~= '__'
|
||||
then
|
||||
error( 'Access of non-existing global "' .. k ..'"', 2 )
|
||||
else
|
||||
rawget( t, k )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
mt.__newindex = function
|
||||
(
|
||||
t, -- table getting a new index assigned
|
||||
k, -- key value to assign to
|
||||
v -- value to assign
|
||||
)
|
||||
if k ~= '_' and string.sub( k, 1, 2 ) ~= '__'
|
||||
then
|
||||
error(
|
||||
'Lsyncd does not allow GLOBALS to be created on the fly. '
|
||||
.. 'Declare "' .. k.. '" local or declare global on load.',
|
||||
2
|
||||
)
|
||||
else
|
||||
rawset( t, k, v )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function lockGlobals( )
|
||||
setmetatable( t, mt )
|
||||
end
|
||||
|
2382
mantle/lsyncd.lua
2382
mantle/lsyncd.lua
File diff suppressed because it is too large
Load Diff
299
mantle/queue.lua
Normal file
299
mantle/queue.lua
Normal file
|
@ -0,0 +1,299 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- lsyncd.lua Live (Mirror) Syncing Demon
|
||||
--
|
||||
--
|
||||
-- The queue is optimized for FILO operation.
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Metatable.
|
||||
--
|
||||
local mt = { }
|
||||
|
||||
--
|
||||
-- Key to native table.
|
||||
--
|
||||
local k_nt = { }
|
||||
|
||||
--
|
||||
-- On accessing a nil index.
|
||||
--
|
||||
mt.__index = function
|
||||
(
|
||||
self,
|
||||
k -- key used to access
|
||||
)
|
||||
if type( k ) ~= 'number'
|
||||
then
|
||||
error( 'Queue, key "'..k..'" invalid', 2 )
|
||||
end
|
||||
|
||||
return self[ k_nt ][ k ]
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- On assigning a new index.
|
||||
--
|
||||
mt.__newindex = function
|
||||
(
|
||||
self,
|
||||
k, -- key value to assign to
|
||||
v -- value to assign
|
||||
)
|
||||
error( 'Queues are not directly assignable.', 2 )
|
||||
end
|
||||
|
||||
--
|
||||
-- Returns the size of the queue.
|
||||
--
|
||||
mt.__len = function
|
||||
(
|
||||
self
|
||||
)
|
||||
return self[ k_nt ].size
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Returns the first item of the Queue.
|
||||
--
|
||||
local function first
|
||||
(
|
||||
self
|
||||
)
|
||||
local nt = self[ k_nt ]
|
||||
|
||||
return nt[ nt.first ]
|
||||
end
|
||||
|
||||
--
|
||||
-- Returns the last item of the Queue.
|
||||
--
|
||||
local function last
|
||||
(
|
||||
self
|
||||
)
|
||||
local nt = self[ k_nt ]
|
||||
|
||||
return nt[ nt.last ]
|
||||
end
|
||||
|
||||
--
|
||||
-- Pushes a value on the queue.
|
||||
-- Returns the last value
|
||||
--
|
||||
local function push
|
||||
(
|
||||
self,
|
||||
value -- value to push
|
||||
)
|
||||
if not value
|
||||
then
|
||||
error( 'Queue pushing nil value', 2 )
|
||||
end
|
||||
|
||||
local nt = self[ k_nt ]
|
||||
|
||||
local last = nt.last + 1
|
||||
|
||||
nt.last = last
|
||||
|
||||
nt[ last ] = value
|
||||
|
||||
nt.size = nt.size + 1
|
||||
|
||||
return last
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Removes an item at pos from the Queue.
|
||||
--
|
||||
local function remove
|
||||
(
|
||||
self,
|
||||
pos -- position to remove
|
||||
)
|
||||
local nt = self[ k_nt ]
|
||||
|
||||
if nt[ pos ] == nil
|
||||
then
|
||||
error( 'Removing nonexisting item in Queue', 2 )
|
||||
end
|
||||
|
||||
nt[ pos ] = nil
|
||||
|
||||
-- if removing first or last element,
|
||||
-- the queue limits are adjusted.
|
||||
if pos == nt.first
|
||||
then
|
||||
local last = nt.last
|
||||
|
||||
while nt[ pos ] == nil and pos <= last
|
||||
do
|
||||
pos = pos + 1
|
||||
end
|
||||
|
||||
nt.first = pos
|
||||
elseif pos == nt.last
|
||||
then
|
||||
local first = nt.first
|
||||
|
||||
while nt[ pos ] == nil and pos >= first
|
||||
do
|
||||
pos = pos - 1
|
||||
end
|
||||
|
||||
nt.last = pos
|
||||
end
|
||||
|
||||
-- reset the indizies if the queue is empty
|
||||
if nt.last < nt.first
|
||||
then
|
||||
nt.first = 1
|
||||
|
||||
nt.last = 0
|
||||
end
|
||||
|
||||
nt.size = nt.size - 1
|
||||
end
|
||||
|
||||
--
|
||||
-- Replaces a value.
|
||||
--
|
||||
local function replace
|
||||
(
|
||||
self,
|
||||
pos, -- position to replace
|
||||
value -- the new entry
|
||||
)
|
||||
local nt = self[ k_nt ]
|
||||
|
||||
if nt[ pos ] == nil
|
||||
then
|
||||
error( 'Trying to replace an unset Queue entry.' )
|
||||
end
|
||||
|
||||
nt[ pos ] = value
|
||||
end
|
||||
|
||||
--
|
||||
-- Queue iterator ( stateless )
|
||||
--
|
||||
local function iter
|
||||
(
|
||||
self,
|
||||
pos
|
||||
)
|
||||
local nt = self[ k_nt ]
|
||||
|
||||
pos = pos + 1
|
||||
|
||||
while nt[ pos ] == nil and pos <= nt.last
|
||||
do
|
||||
pos = pos + 1
|
||||
end
|
||||
|
||||
if pos > nt.last then return nil end
|
||||
|
||||
return pos, nt[ pos ]
|
||||
end
|
||||
|
||||
--
|
||||
-- Reverse queue iterator (stateless)
|
||||
--
|
||||
local function revIter
|
||||
(
|
||||
self,
|
||||
pos
|
||||
)
|
||||
local nt = self[ k_nt ]
|
||||
|
||||
pos = pos - 1
|
||||
|
||||
while nt[ pos ] == nil and pos >= nt.first
|
||||
do
|
||||
pos = pos - 1
|
||||
end
|
||||
|
||||
if pos < nt.first
|
||||
then
|
||||
return nil
|
||||
end
|
||||
|
||||
return pos, nt[ pos ]
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Iteraters through the queue
|
||||
-- returning all non-nil pos-value entries.
|
||||
--
|
||||
local function qpairs
|
||||
(
|
||||
self
|
||||
)
|
||||
return iter, self, self[ k_nt ].first - 1
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Iteraters backwards through the queue
|
||||
-- returning all non-nil pos-value entries.
|
||||
--
|
||||
local function qpairsReverse
|
||||
(
|
||||
self
|
||||
)
|
||||
return revIter, self, self[ k_nt ].last + 1
|
||||
end
|
||||
|
||||
--
|
||||
-- Creates a new queue.
|
||||
--
|
||||
local function new
|
||||
( )
|
||||
local q =
|
||||
{
|
||||
first = first,
|
||||
last = last,
|
||||
push = push,
|
||||
qpairs = qpairs,
|
||||
qpairsReverse = qpairsReverse,
|
||||
remove = remove,
|
||||
replace = replace,
|
||||
|
||||
[ k_nt ] =
|
||||
{
|
||||
first = 1,
|
||||
last = 0,
|
||||
size = 0
|
||||
}
|
||||
}
|
||||
|
||||
setmetatable( q, mt )
|
||||
|
||||
return q
|
||||
end
|
||||
|
||||
--
|
||||
-- Exported interface
|
||||
--
|
||||
Queue = { new = new }
|
||||
|
|
@ -1,22 +1,35 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- lsyncd.lua Live (Mirror) Syncing Demon
|
||||
--
|
||||
--
|
||||
-- Wraps up globals of the mantle to set up the Lua
|
||||
-- space for user scripts.
|
||||
-- This must come as last mantle file.
|
||||
--
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
lsyncd.log( 'Error', 'Lsyncd mantle already loaded' )
|
||||
lsyncd.terminate( -1 )
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
-- Lets the core double check version identity with the mantle
|
||||
mantle = '3.0.0-devel'
|
||||
|
||||
|
||||
Inotify.init( Syncs, uSettings )
|
||||
|
||||
|
||||
core = nil
|
||||
lockGlobals = nil
|
||||
Inotify = nil
|
||||
Delay = nil
|
||||
InletFactory = nil
|
||||
Filter = nil
|
||||
|
|
Loading…
Reference in New Issue
Block a user