aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2019-11-01 12:47:09 +0000
committers-ol <s-ol@users.noreply.github.com>2019-11-01 12:47:09 +0000
commit053e607a49989b2d4491c20ff14c839b7161d713 (patch)
tree2397569c518c2de29f6de73d589bb80e84616821
parentbrowsing, adding, removing fileders in inspector (diff)
downloadmmm-053e607a49989b2d4491c20ff14c839b7161d713.tar.gz
mmm-053e607a49989b2d4491c20ff14c839b7161d713.zip
add proper order handling, fsck for stores.fs
-rw-r--r--build/fsck.moon37
-rw-r--r--mmm/mmmfs/stores/fs.moon78
-rw-r--r--mmm/mmmfs/stores/init.moon3
3 files changed, 104 insertions, 14 deletions
diff --git a/build/fsck.moon b/build/fsck.moon
new file mode 100644
index 0000000..df882a9
--- /dev/null
+++ b/build/fsck.moon
@@ -0,0 +1,37 @@
+add = (tmpl) ->
+ package.path ..= ";#{tmpl}.lua"
+ package.moonpath ..= ";#{tmpl}.moon"
+
+add '?'
+add '?.server'
+add '?/init'
+add '?/init.server'
+
+require 'mmm'
+
+import get_store from require 'mmm.mmmfs.stores'
+
+-- usage:
+-- moon server.moon [FLAGS] [STORE] [host] [port]
+-- * FLAGS - any of the following:
+-- --[no-]rw - enable/disable POST?PUT/DELETE operations (default: on if local)
+-- --[no-]unsafe - enable/disable server-side code execution when writable is on (default: on if local or --no-rw)
+-- * STORE - see mmm/mmmfs/stores/init.moon:get_store
+-- * host - interface to bind to (default localhost, set to 0.0.0.0 for public hosting)
+-- * port - port to serve from, default 8000
+
+flags = {}
+arguments = for a in *arg
+ if flag = a\match '^%-%-no%-(.*)$'
+ flags[flag] = false
+ continue
+ elseif flag = a\match '^%-%-(.*)$'
+ flags[flag] = true
+ continue
+ else
+ a
+
+{ store, host, port } = arguments
+
+store = get_store store, verbose: true
+store\fsck!
diff --git a/mmm/mmmfs/stores/fs.moon b/mmm/mmmfs/stores/fs.moon
index d4d5bd4..edcca3b 100644
--- a/mmm/mmmfs/stores/fs.moon
+++ b/mmm/mmmfs/stores/fs.moon
@@ -21,38 +21,63 @@ class FSStore extends Store
@log "opening '#{opts.root}'..."
-- fileders
- list_fileders_in: (path='') =>
+ get_order: (path, forgiving=false) =>
entries = {}
- for entry_name in lfs.dir @root .. path
- continue if '.' == entry_name\sub 1, 1
- entry_path = @root .. "#{path}/#{entry_name}"
+ for name in lfs.dir @root .. path
+ continue if '.' == name\sub 1, 1
+ entry_path = @root .. "#{path}/#{name}"
if 'directory' ~= lfs.attributes entry_path, 'mode'
continue
- entries[entry_name] = "#{path}/#{entry_name}"
+ entries[name] = :name, path: "#{path}/#{name}"
sorted = {}
-
order_file = @root .. "#{path}/$order"
if 'file' == lfs.attributes order_file, 'mode'
for line in io.lines order_file
- path = assert entries[line], "entry in $order but not on disk: #{line}"
- table.insert sorted, path
+ entry = entries[line]
+ if not entry
+ if forgiving
+ @log "removed stale entry '#{line}' from #{path}/$order"
+ continue
+ error "entry in $order but not on disk: #{line}"
+
+ table.insert sorted, entry
sorted[line] = true
- entries = [path for entry, path in pairs entries when not sorted[entry]]
- table.sort entries
- for path in *entries
- table.insert sorted, path
+ unsorted = [entry for name, entry in pairs entries when not sorted[entry.name]]
+ if forgiving
+ for entry in *unsorted
+ @log "adding new entry '#{entry.name}' in #{path}/$order"
+ table.insert sorted, entry
+ else
+ assert #unsorted == 0, unsorted[1] and "entry on disk but not in $order: #{unsorted[1].path}"
+
+ sorted
+
+ write_order: (path, order=@get_order path, true) =>
+ order_file = @root .. "#{path}/$order"
+ if #order == 0
+ os.remove order_file
+ return
+
+ file = assert io.open order_file, 'w'
+ for { :name } in *order
+ file\write "#{name}\n"
+ file\close!
+
+ list_fileders_in: (path='') =>
+ sorted = @get_order path
coroutine.wrap ->
- for path in *sorted
+ for { :path } in *sorted
coroutine.yield path
create_fileder: (parent, name) =>
path = "#{parent}/#{name}"
@log "creating fileder #{path}"
assert lfs.mkdir @root .. path
+ @write_order parent
path
remove_fileder: (path) =>
@@ -73,6 +98,9 @@ class FSStore extends Store
rmdir @root .. path
+ parent = dir_base path
+ @write_order parent
+
rename_fileder: (path, next_name) =>
@log "renaming fileder #{path} -> '#{next_name}'"
parent, name = dir_base path
@@ -83,6 +111,22 @@ class FSStore extends Store
parent, name = dir_base path
assert os.rename @root .. path, @root .. "#{next_parent}/#{name}"
+ -- swap two childrens' order
+ swap_fileders: (parent, name_a, name_b) =>
+ @log "swapping #{name_a} and #{name_b} in #{parent}"
+ order = @get_order parent
+ local a, b
+ for i, entry in ipairs order
+ a = i if entry.name == name_a
+ b = i if entry.name == name_b
+ break if a and b
+
+ assert a, "couldn't find #{parent}/#{name_a} in $order"
+ assert b, "couldn't find #{parent}/#{name_b} in $order"
+
+ order[a], order[b] = order[b], order[a]
+ @write_order parent, order
+
-- facets
list_facets: (path) =>
coroutine.wrap ->
@@ -161,6 +205,14 @@ class FSStore extends Store
file\write blob
file\close!
+ -- fsck
+ fsck: (path='') =>
+ order = @get_order path, true
+ @write_order path, order
+
+ for { :path } in *order
+ @fsck path
+
{
:FSStore
}
diff --git a/mmm/mmmfs/stores/init.moon b/mmm/mmmfs/stores/init.moon
index 905188f..3d8480f 100644
--- a/mmm/mmmfs/stores/init.moon
+++ b/mmm/mmmfs/stores/init.moon
@@ -42,13 +42,14 @@ class Store
@remove_facet path, name, type update_facet: => error "not implemented"
close: =>
+ fsck: =>
log: (...) =>
print "[#{@@__name}]", ...
-- instantiate a store from a CLI arg
-- e.g.: sql, fs:/path/to/root, sql:MEMORY, sql:db.sqlite3
-get_store = (args='sql', opts={verbose: true}) ->
+get_store = (args='sql', opts={}) ->
type, arg = args\match '(%w+):(.*)'
type = args unless type