git.s-ol.nu mmm / 86bbe80
add lfs driver, spec s-ol 3 years ago
4 changed file(s) with 194 addition(s) and 72 deletion(s). Raw diff Collapse all Expand all
0 lfs = require 'lfs'
1
2 -- split filename into dirname + basename
3 dir_base = (path) ->
4 dir, base = path\match '(.-)([^/]-)$'
5 if dir and #dir > 0
6 dir = dir\sub 1, #dir - 1
7
8 dir, base
9
10
11 class LFSStore
12 new: (opts = {}) =>
13 opts.root or= 'root'
14 opts.verbose or= false
15
16 if not opts.verbose
17 @log = ->
18
19 -- ensure path doesnt end with a slash
20 @root = opts.root\match '^(.-)/?$'
21 @log "opening '#{opts.root}'..."
22
23 log: (...) =>
24 print "[DB]", ...
25
26 -- fileders
27 list_fileders_in: (path='') =>
28 coroutine.wrap ->
29 for entry_name in lfs.dir @root .. path
30 continue if '.' == entry_name\sub 1, 1
31 entry_path = @root .. "#{path}/#{entry_name}"
32 if 'directory' == lfs.attributes entry_path, 'mode'
33 coroutine.yield "#{path}/#{entry_name}"
34
35 list_all_fileders: (path='') =>
36 coroutine.wrap ->
37 for path in @list_fileders_in path
38 coroutine.yield path
39 for p in @list_all_fileders path
40 coroutine.yield p
41
42 create_fileder: (parent, name) =>
43 @log "creating fileder #{path}"
44 path = "#{parent}/#{name}"
45 assert lfs.mkdir @root .. path
46 path
47
48 remove_fileder: (path) =>
49 @log "removing fileder #{path}"
50
51 rmdir = (path) ->
52 for file in lfs.dir path
53 continue if '.' == file\sub 1, 1
54
55 file_path = "#{path}/#{file}"
56 switch lfs.attributes file_path, 'mode'
57 when 'file'
58 assert os.remove file_path
59 when 'directory'
60 assert rmdir file_path
61
62 lfs.rmdir path
63
64 rmdir @root .. path
65
66 rename_fileder: (path, next_name) =>
67 @log "renaming fileder #{path} -> '#{next_name}'"
68 parent, name = dir_base path
69 assert os.rename path, @root .. "#{parent}/#{next_name}"
70
71 move_fileder: (path, next_parent) =>
72 @log "moving fileder #{path} -> #{next_parent}/"
73 parent, name = dir_base path
74 assert os.rename @root .. path, @root .. "#{next_parent}/#{name}"
75
76 -- facets
77 list_facets: (path) =>
78 coroutine.wrap ->
79 for entry_name in lfs.dir @root .. path
80 entry_path = "#{@root .. path}/#{entry_name}"
81 if 'file' == lfs.attributes entry_path, 'mode'
82 entry_name = (entry_name\match '(.*)%.%w+') or entry_name
83 entry_name = entry_name\gsub '%$', '/'
84 name, type = entry_name\match '(%w+): *(.+)'
85 if not name
86 name = ''
87 type = entry_name
88
89 coroutine.yield name, type
90
91 tofp: (path, name, type) =>
92 type = "#{name}: #{type}" if #name > 0
93 type = type\gsub '%/', '$'
94 @root .. "#{path}/#{type}"
95
96 locate: (path, name, type) =>
97 return unless lfs.attributes @root .. path, 'mode'
98
99 type = type\gsub '%/', '$'
100 name = "#{name}: " if #name > 0
101 name = name .. type
102 name = name\gsub '([^%w])', '%%%1'
103
104 local file_name
105 for entry_name in lfs.dir @root .. path
106 if (entry_name\match "^#{name}$") or entry_name\match "^#{name}%.%w+$"
107 if file_name
108 error "two files match #{name}: #{file_name} and #{entry_name}!"
109 file_name = entry_name
110
111
112 file_name and @root .. "#{path}/#{file_name}"
113
114 load_facet: (path, name, type) =>
115 filepath = @locate path, name, type
116 return unless filepath
117 file = assert (io.open filepath, 'rb'), "couldn't open facet file '#{filepath}'"
118 with file\read '*all'
119 file\close!
120
121 create_facet: (path, name, type, blob) =>
122 @log "creating facet #{path} | #{name}: #{type}"
123 assert blob, "cant create facet without value!"
124
125 filepath = @tofp path, name, type
126 if lfs.attributes filepath, 'mode'
127 error "facet file already exists!"
128
129 file = assert (io.open filepath, 'wb'), "couldn't open facet file '#{filepath}'"
130 file\write blob
131 file\close!
132
133 remove_facet: (path, name, type) =>
134 @log "removing facet #{path} | #{name}: #{type}"
135
136 filepath = @locate path, name, type
137 assert filepath, "couldn't locate facet!"
138 assert os.remove filepath
139
140 rename_facet: (path, name, type, next_name) =>
141 @log "renaming facet #{path} | #{name}: #{type} -> #{next_name}"
142 filepath = @locate path, name, type
143 assert filepath, "couldn't locate facet!"
144 assert os.rename filepath, @tofp path, next_name, type
145
146 update_facet: (path, name, type, blob) =>
147 @log "updating facet #{path} | #{name}: #{type}"
148 filepath = @locate path, name, type
149 assert filepath, "couldn't locate facet!"
150 file = assert (io.open filepath, 'wb'), "couldn't open facet file '#{filepath}'"
151 file\write blob
152 file\close!
153
154 {
155 :LFSStore
156 }
00 sqlite = require 'sqlite3'
1 root = os.tmpname!
12
23 class SQLStore
34 new: (opts = {}) =>
9596 OR path = :path', path
9697
9798 rename_fileder: (path, next_name) =>
99 @log "renaming fileder #{path} -> '#{next_name}'"
98100 error 'not implemented'
99101
100102 @exec 'UPDATE fileder
104106
105107 -- @TODO: rename all children, child-children...
106108
107 move_fileder: (path, new_parent) =>
109 move_fileder: (path, next_parent) =>
110 @log "moving fileder #{path} -> #{next_parent}/"
108111 error 'not implemented'
109112
110113 -- @TODO: remove all children, child-children...
+0
-59
mmm/mmmfs/drivers/zip.moon less more
0 require = relative ..., 1
1 import Fileder, Key from require '.fileder'
2 zip = require 'brimworks.zip'
3
4 -- split filename into dirname + basename
5 dir_base = (path) ->
6 dir, base = path\match '(.-)([^/]-)$'
7 if dir and #dir > 0
8 dir = dir\sub 1, #dir - 1
9
10 dir, base
11
12 -- insert into array unless contained
13 table_add = (tbl, entry) ->
14 for _, v in ipairs tbl
15 if v == entry
16 return
17
18 table.insert tbl, entry
19
20 -- strip facet formatting
21 load_facet = (filename) ->
22 key = (filename\match '(.*)%.%w+') or filename
23 key = Key key\gsub '%$', '/'
24 key.filename = filename
25
26 key
27
28 load_tree = (file='root.zip') ->
29 archive = zip.open file
30
31 fileders = setmetatable {},
32 __index: (path) =>
33 with val = Fileder {}
34 .path = path
35 rawset @, path, val
36
37 fileders['/root'].facets['name: alpha'] = -> 'root'
38
39 for i = 1, #archive
40 { :name, :size } = archive\stat i
41
42 path, facet = dir_base "/#{name}"
43 parent, name = dir_base path
44
45 key = load_facet facet
46
47 this = fileders[path]
48 this.facets['name: alpha'] = -> name
49 this.facets[key] = ->
50 file = archive\open i
51 with file\read size
52 file\close!
53
54 table_add fileders[parent].children, this
55
56 fileders['/root']
57
58 { :load_tree }
0 import SQLStore from require 'mmm.mmmfs.drivers.sql'
1
20 sort2 = (a, b) ->
31 {ax, ay}, {bx, by} = a, b
42 "#{ax}//#{ay}" < "#{bx}//#{by}"
5 toseq = (iter) -> with v = [x for x in iter]
6 table.sort v
7 toseq2 = (iter) -> with v = [{x, y} for x, y in iter]
8 table.sort v, sort2
93
10 describe "sql driver", ->
4 toseq = (iter) ->
5 with v = [x for x in iter]
6 table.sort v
7
8 toseq2 = (iter) ->
9 with v = [{x, y} for x, y in iter]
10 table.sort v, sort2
11
12 test_driver = (ts) ->
1113 randomize false
12
13 ts = SQLStore memory: true
1414
1515 it "starts out empty", ->
1616 assert.are.same {}, toseq ts\list_fileders_in!
4343 ts\create_facet '/hello/world', 'name', 'alpha', 'world'
4444 ts\create_facet '/hello/world', '', 'text/markdown', '# Helau World!'
4545
46 it "can't create facet for nonexistant fileders", ->
46 it "but can't create facet for nonexistant fileders", ->
4747 assert.has_error -> ts\create_facet '/hello/orldw', 'name', 'alpha', 'foo'
4848
49 it "can't create facet without value", ->
49 it "but can't create facet without value", ->
5050 assert.has_error -> ts\create_facet '/hello/world', 'other', 'alpha', nil
5151
52 it "can't create facet for duplicate keys", ->
52 it "but can't create facet for duplicate keys", ->
5353 assert.has_error -> ts\create_facet '/hello/world', 'name', 'alpha', 'foo'
5454
5555 assert.are.same {{'name', 'alpha'}}, toseq2 ts\list_facets '/hello'
8787
8888 ts\remove_fileder '/hello'
8989 assert.are.same {}, toseq ts\list_all_fileders!
90
91 describe "SQL driver", ->
92 import SQLStore from require 'mmm.mmmfs.drivers.sql'
93
94 test_driver SQLStore memory: true
95
96 describe "LFS driver", ->
97 import LFSStore from require 'mmm.mmmfs.drivers.lfs'
98
99 lfs = require 'lfs'
100
101 root = os.tmpname!
102
103 setup ->
104 assert os.remove root
105 assert lfs.mkdir root
106
107 test_driver LFSStore :root
108
109 teardown ->
110 assert lfs.rmdir root