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.
10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/async/caldav/storage/filesystem.rb', line 10 def initialize(root) @root = root @sync_snapshots = {} FileUtils.mkdir_p(@root) @root_normalized = ::File.(@root) if @root_normalized.end_with?(::File::SEPARATOR) @root_with_separator = @root_normalized else @root_with_separator = "#{@root_normalized}#{::File::SEPARATOR}" end end |
Instance Method Details
#collection_exists?(path) ⇒ Boolean
104 105 106 |
# File 'lib/async/caldav/storage/filesystem.rb', line 104 def collection_exists?(path) File.exist?(File.join(full_path(path), ".collection.json")) end |
#create_collection(path, props = {}) ⇒ Object
--- Collections ---
24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/async/caldav/storage/filesystem.rb', line 24 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
47 48 49 50 51 52 53 54 55 |
# File 'lib/async/caldav/storage/filesystem.rb', line 47 def delete_collection(path) s = stat(path) if s && s.directory? FileUtils.rm_rf(full_path(path)) true else false end end |
#delete_item(path) ⇒ Object
132 133 134 135 136 137 138 139 140 |
# File 'lib/async/caldav/storage/filesystem.rb', line 132 def delete_item(path) s = stat(path) if s && s.file? File.delete(full_path(path)) true else false end end |
#etag(path) ⇒ Object
191 192 193 194 |
# File 'lib/async/caldav/storage/filesystem.rb', line 191 def etag(path) item = get_item(path) item ? item[:etag] : nil end |
#exists?(path) ⇒ Boolean
--- General ---
183 184 185 186 187 188 189 |
# File 'lib/async/caldav/storage/filesystem.rb', line 183 def exists?(path) if stat(path) true else collection_exists?(path) end end |
#get_collection(path) ⇒ Object
38 39 40 41 42 43 44 45 |
# File 'lib/async/caldav/storage/filesystem.rb', line 38 def get_collection(path) = File.join(full_path(path), ".collection.json") if File.exist?() symbolize(JSON.parse(File.read())) else nil end end |
#get_item(path) ⇒ Object
--- Items ---
110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/async/caldav/storage/filesystem.rb', line 110 def get_item(path) s = stat(path) if s && s.file? body = File.read(full_path(path)) content_type = guess_content_type(path) etag = Protocol::Caldav::ETag.compute(body) { body: body, content_type: content_type, etag: etag } else nil end end |
#get_multi(paths) ⇒ Object
177 178 179 |
# File 'lib/async/caldav/storage/filesystem.rb', line 177 def get_multi(paths) paths.map { |p| [p, get_item(p)] } end |
#list_collections(parent_path) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/async/caldav/storage/filesystem.rb', line 57 def list_collections(parent_path) dir = full_path(parent_path) if File.directory?(dir) Dir.children(dir).filter_map do |name| child_dir = File.join(dir, name) = File.join(child_dir, ".collection.json") unless File.directory?(child_dir) && File.exist?() next end child_path = File.join(parent_path, name).sub(%r{/*$}, "/") [child_path, symbolize(JSON.parse(File.read()))] end else [] end end |
#list_items(collection_path) ⇒ Object
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/async/caldav/storage/filesystem.rb', line 142 def list_items(collection_path) dir = full_path(collection_path) if File.directory?(dir) Dir.children(dir).filter_map do |name| if name.start_with?(".") next end file = File.join(dir, name) unless File.file?(file) next end 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 else [] end end |
#move_item(from_path, to_path) ⇒ Object
165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/async/caldav/storage/filesystem.rb', line 165 def move_item(from_path, to_path) s = stat(from_path) if s && s.file? dst = full_path(to_path) FileUtils.mkdir_p(File.dirname(dst)) FileUtils.mv(full_path(from_path), dst) get_item(to_path) else nil end end |
#put_item(path, body, content_type) ⇒ Object
122 123 124 125 126 127 128 129 130 |
# File 'lib/async/caldav/storage/filesystem.rb', line 122 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 ---
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/async/caldav/storage/filesystem.rb', line 198 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
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/async/caldav/storage/filesystem.rb', line 217 def sync_changes(collection_path, token) old_snapshot_entry = @sync_snapshots[token] if 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| unless current.key?(path) changes << [path, :deleted] end end [new_token, changes] else nil end end |
#update_collection(path, props) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/async/caldav/storage/filesystem.rb', line 75 def update_collection(path, props) col = get_collection(path) if col if props.key?(:displayname) col[:displayname] = props[:displayname] end if props.key?(:description) col[:description] = props[:description] end if props.key?(:color) col[:color] = props[:color] end if props.key?(:props) col[:props] = (col[:props] || {}).merge(props[:props]) end = { "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 else nil end end |