git.s-ol.nu mmm / 053e607
add proper order handling, fsck for stores.fs s-ol 2 years ago
3 changed file(s) with 104 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
0 add = (tmpl) ->
1 package.path ..= ";#{tmpl}.lua"
2 package.moonpath ..= ";#{tmpl}.moon"
3
4 add '?'
5 add '?.server'
6 add '?/init'
7 add '?/init.server'
8
9 require 'mmm'
10
11 import get_store from require 'mmm.mmmfs.stores'
12
13 -- usage:
14 -- moon server.moon [FLAGS] [STORE] [host] [port]
15 -- * FLAGS - any of the following:
16 -- --[no-]rw - enable/disable POST?PUT/DELETE operations (default: on if local)
17 -- --[no-]unsafe - enable/disable server-side code execution when writable is on (default: on if local or --no-rw)
18 -- * STORE - see mmm/mmmfs/stores/init.moon:get_store
19 -- * host - interface to bind to (default localhost, set to 0.0.0.0 for public hosting)
20 -- * port - port to serve from, default 8000
21
22 flags = {}
23 arguments = for a in *arg
24 if flag = a\match '^%-%-no%-(.*)$'
25 flags[flag] = false
26 continue
27 elseif flag = a\match '^%-%-(.*)$'
28 flags[flag] = true
29 continue
30 else
31 a
32
33 { store, host, port } = arguments
34
35 store = get_store store, verbose: true
36 store\fsck!
2020 @log "opening '#{opts.root}'..."
2121
2222 -- fileders
23 list_fileders_in: (path='') =>
23 get_order: (path, forgiving=false) =>
2424 entries = {}
25 for entry_name in lfs.dir @root .. path
26 continue if '.' == entry_name\sub 1, 1
27 entry_path = @root .. "#{path}/#{entry_name}"
25 for name in lfs.dir @root .. path
26 continue if '.' == name\sub 1, 1
27 entry_path = @root .. "#{path}/#{name}"
2828 if 'directory' ~= lfs.attributes entry_path, 'mode'
2929 continue
3030
31 entries[entry_name] = "#{path}/#{entry_name}"
31 entries[name] = :name, path: "#{path}/#{name}"
3232
3333 sorted = {}
34
3534 order_file = @root .. "#{path}/$order"
3635 if 'file' == lfs.attributes order_file, 'mode'
3736 for line in io.lines order_file
38 path = assert entries[line], "entry in $order but not on disk: #{line}"
39 table.insert sorted, path
37 entry = entries[line]
38 if not entry
39 if forgiving
40 @log "removed stale entry '#{line}' from #{path}/$order"
41 continue
42 error "entry in $order but not on disk: #{line}"
43
44 table.insert sorted, entry
4045 sorted[line] = true
4146
42 entries = [path for entry, path in pairs entries when not sorted[entry]]
43 table.sort entries
44 for path in *entries
45 table.insert sorted, path
47 unsorted = [entry for name, entry in pairs entries when not sorted[entry.name]]
48 if forgiving
49 for entry in *unsorted
50 @log "adding new entry '#{entry.name}' in #{path}/$order"
51 table.insert sorted, entry
52 else
53 assert #unsorted == 0, unsorted[1] and "entry on disk but not in $order: #{unsorted[1].path}"
54
55 sorted
56
57 write_order: (path, order=@get_order path, true) =>
58 order_file = @root .. "#{path}/$order"
59 if #order == 0
60 os.remove order_file
61 return
62
63 file = assert io.open order_file, 'w'
64 for { :name } in *order
65 file\write "#{name}\n"
66 file\close!
67
68 list_fileders_in: (path='') =>
69 sorted = @get_order path
4670
4771 coroutine.wrap ->
48 for path in *sorted
72 for { :path } in *sorted
4973 coroutine.yield path
5074
5175 create_fileder: (parent, name) =>
5276 path = "#{parent}/#{name}"
5377 @log "creating fileder #{path}"
5478 assert lfs.mkdir @root .. path
79 @write_order parent
5580 path
5681
5782 remove_fileder: (path) =>
7297
7398 rmdir @root .. path
7499
100 parent = dir_base path
101 @write_order parent
102
75103 rename_fileder: (path, next_name) =>
76104 @log "renaming fileder #{path} -> '#{next_name}'"
77105 parent, name = dir_base path
81109 @log "moving fileder #{path} -> #{next_parent}/"
82110 parent, name = dir_base path
83111 assert os.rename @root .. path, @root .. "#{next_parent}/#{name}"
112
113 -- swap two childrens' order
114 swap_fileders: (parent, name_a, name_b) =>
115 @log "swapping #{name_a} and #{name_b} in #{parent}"
116 order = @get_order parent
117 local a, b
118 for i, entry in ipairs order
119 a = i if entry.name == name_a
120 b = i if entry.name == name_b
121 break if a and b
122
123 assert a, "couldn't find #{parent}/#{name_a} in $order"
124 assert b, "couldn't find #{parent}/#{name_b} in $order"
125
126 order[a], order[b] = order[b], order[a]
127 @write_order parent, order
84128
85129 -- facets
86130 list_facets: (path) =>
160204 file\write blob
161205 file\close!
162206
207 -- fsck
208 fsck: (path='') =>
209 order = @get_order path, true
210 @write_order path, order
211
212 for { :path } in *order
213 @fsck path
214
163215 {
164216 :FSStore
165217 }
4141 @remove_facet path, name, type update_facet: => error "not implemented"
4242
4343 close: =>
44 fsck: =>
4445
4546 log: (...) =>
4647 print "[#{@@__name}]", ...
4748
4849 -- instantiate a store from a CLI arg
4950 -- e.g.: sql, fs:/path/to/root, sql:MEMORY, sql:db.sqlite3
50 get_store = (args='sql', opts={verbose: true}) ->
51 get_store = (args='sql', opts={}) ->
5152 type, arg = args\match '(%w+):(.*)'
5253 type = args unless type
5354