Class: Async::Caldav::Storage::Filesystem
- Inherits:
-
Protocol::Caldav::Storage
- Object
- Protocol::Caldav::Storage
- Async::Caldav::Storage::Filesystem
- Defined in:
- lib/async/caldav/storage/filesystem.rb
Instance Method Summary collapse
- #collection_exists?(path) ⇒ Boolean
-
#create_collection(path, props = {}) ⇒ Object
— Collections —.
- #delete_collection(path) ⇒ Object
- #delete_item(path) ⇒ Object
- #etag(path) ⇒ Object
-
#exists?(path) ⇒ Boolean
— General —.
- #get_collection(path) ⇒ Object
-
#get_item(path) ⇒ Object
— Items —.
- #get_multi(paths) ⇒ Object
-
#initialize(root) ⇒ Filesystem
constructor
A new instance of Filesystem.
- #list_collections(parent_path) ⇒ Object
- #list_items(collection_path) ⇒ Object
- #move_item(from_path, to_path) ⇒ Object
- #put_item(path, body, content_type) ⇒ Object
-
#snapshot_sync(collection_path) ⇒ Object
— Sync —.
- #sync_changes(collection_path, token) ⇒ Object
- #update_collection(path, props) ⇒ Object
Constructor Details
#initialize(root) ⇒ Filesystem
Returns a new instance of Filesystem.
13 14 15 16 17 |
# File 'lib/async/caldav/storage/filesystem.rb', line 13 def initialize(root) @root = root @sync_snapshots = {} FileUtils.mkdir_p(@root) end |
Instance Method Details
#collection_exists?(path) ⇒ Boolean
85 86 87 |
# File 'lib/async/caldav/storage/filesystem.rb', line 85 def collection_exists?(path) File.exist?(File.join(full_path(path), ".collection.json")) end |
#create_collection(path, props = {}) ⇒ Object
— Collections —
21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/async/caldav/storage/filesystem.rb', line 21 def create_collection(path, props = {}) dir = full_path(path) FileUtils.mkdir_p(dir) = { "type" => (props[:type] || :collection).to_s, "displayname" => props[:displayname], "description" => props[:description], "color" => props[:color], "props" => props[:props] || {} } File.write(File.join(dir, ".collection.json"), JSON.pretty_generate()) symbolize() end |
#delete_collection(path) ⇒ Object
41 42 43 44 45 46 47 48 49 |
# File 'lib/async/caldav/storage/filesystem.rb', line 41 def delete_collection(path) dir = full_path(path) if File.directory?(dir) FileUtils.rm_rf(dir) true else false end end |
#delete_item(path) ⇒ Object
111 112 113 114 115 116 117 118 119 |
# File 'lib/async/caldav/storage/filesystem.rb', line 111 def delete_item(path) file = full_path(path) if File.file?(file) File.delete(file) true else false end end |
#etag(path) ⇒ Object
159 160 161 162 |
# File 'lib/async/caldav/storage/filesystem.rb', line 159 def etag(path) item = get_item(path) item ? item[:etag] : nil end |
#exists?(path) ⇒ Boolean
— General —
154 155 156 157 |
# File 'lib/async/caldav/storage/filesystem.rb', line 154 def exists?(path) fp = full_path(path) File.exist?(fp) || collection_exists?(path) end |
#get_collection(path) ⇒ Object
35 36 37 38 39 |
# File 'lib/async/caldav/storage/filesystem.rb', line 35 def get_collection(path) = File.join(full_path(path), ".collection.json") return nil unless File.exist?() symbolize(JSON.parse(File.read())) end |
#get_item(path) ⇒ Object
— Items —
91 92 93 94 95 96 97 98 99 |
# File 'lib/async/caldav/storage/filesystem.rb', line 91 def get_item(path) file = full_path(path) return nil unless File.file?(file) body = File.read(file) content_type = guess_content_type(path) etag = Protocol::Caldav::ETag.compute(body) { body: body, content_type: content_type, etag: etag } end |
#get_multi(paths) ⇒ Object
148 149 150 |
# File 'lib/async/caldav/storage/filesystem.rb', line 148 def get_multi(paths) paths.map { |p| [p, get_item(p)] } end |
#list_collections(parent_path) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/async/caldav/storage/filesystem.rb', line 51 def list_collections(parent_path) dir = full_path(parent_path) return [] unless File.directory?(dir) Dir.children(dir).filter_map do |name| child_dir = File.join(dir, name) = File.join(child_dir, ".collection.json") next unless File.directory?(child_dir) && File.exist?() child_path = File.join(parent_path, name).sub(%r{/*$}, "/") [child_path, symbolize(JSON.parse(File.read()))] end end |
#list_items(collection_path) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/async/caldav/storage/filesystem.rb', line 121 def list_items(collection_path) dir = full_path(collection_path) return [] unless File.directory?(dir) Dir.children(dir).filter_map do |name| next if name.start_with?(".") file = File.join(dir, name) next unless File.file?(file) item_path = File.join(collection_path, name) body = File.read(file) content_type = guess_content_type(name) etag = Protocol::Caldav::ETag.compute(body) [item_path, { body: body, content_type: content_type, etag: etag }] end end |
#move_item(from_path, to_path) ⇒ Object
138 139 140 141 142 143 144 145 146 |
# File 'lib/async/caldav/storage/filesystem.rb', line 138 def move_item(from_path, to_path) src = full_path(from_path) dst = full_path(to_path) return nil unless File.file?(src) FileUtils.mkdir_p(File.dirname(dst)) FileUtils.mv(src, dst) get_item(to_path) end |
#put_item(path, body, content_type) ⇒ Object
101 102 103 104 105 106 107 108 109 |
# File 'lib/async/caldav/storage/filesystem.rb', line 101 def put_item(path, body, content_type) file = full_path(path) is_new = !File.exist?(file) FileUtils.mkdir_p(File.dirname(file)) File.write(file, body) etag = Protocol::Caldav::ETag.compute(body) item = { body: body, content_type: content_type, etag: etag } [item, is_new] end |
#snapshot_sync(collection_path) ⇒ Object
— Sync —
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/async/caldav/storage/filesystem.rb', line 166 def snapshot_sync(collection_path) items = list_items(collection_path) snapshot = {} items.each { |path, data| snapshot[path] = data[:etag] } col = get_collection(collection_path) || {} = items.map { |_, data| data[:etag] } ctag = Protocol::Caldav::CTag.compute( path: collection_path, displayname: col[:displayname], description: col[:description], color: col[:color], item_etags: ) token = "http://caldav.local/sync/#{ctag}" @sync_snapshots[token] = { collection_path => snapshot } token end |
#sync_changes(collection_path, token) ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/async/caldav/storage/filesystem.rb', line 185 def sync_changes(collection_path, token) old_snapshot_entry = @sync_snapshots[token] return nil unless old_snapshot_entry old_snapshot = old_snapshot_entry[collection_path] || {} new_token = snapshot_sync(collection_path) current_items = list_items(collection_path) current = {} current_items.each { |path, data| current[path] = data[:etag] } changes = [] current.each do |path, etag| if !old_snapshot.key?(path) || old_snapshot[path] != etag changes << [path, :modified] end end old_snapshot.each_key do |path| changes << [path, :deleted] unless current.key?(path) end [new_token, changes] end |
#update_collection(path, props) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/async/caldav/storage/filesystem.rb', line 65 def update_collection(path, props) col = get_collection(path) return nil unless col col[:displayname] = props[:displayname] if props.key?(:displayname) col[:description] = props[:description] if props.key?(:description) col[:color] = props[:color] if props.key?(:color) col[:props] = (col[:props] || {}).merge(props[:props]) if props.key?(:props) = { "type" => col[:type].to_s, "displayname" => col[:displayname], "description" => col[:description], "color" => col[:color], "props" => col[:props] || {} } File.write(File.join(full_path(path), ".collection.json"), JSON.pretty_generate()) col end |