class Dbox::DB::DropboxDir
Attributes
contents[R]
contents_hash[R]
Public Class Methods
new(db, res)
click to toggle source
Calls superclass method
Dbox::DB::DropboxBlob::new
# File lib/dbox/db.rb, line 290 def initialize(db, res) @contents_hash = nil @contents = {} super(db, res) end
Public Instance Methods
calculate_changes(res)
click to toggle source
# File lib/dbox/db.rb, line 334 def calculate_changes(res) raise(ArgumentError, "Not a directory: #{res.inspect}") unless res["is_dir"] if @contents_hash && res["hash"] && @contents_hash == res["hash"] # dir hash hasn't changed -- no need to calculate changes [] elsif res["contents"] # dir has changed -- calculate changes on contents out = [] got_paths = [] remove_dotfiles(res["contents"]).each do |c| p = @db.remote_to_relative_path(c["path"]) c["rel_path"] = p got_paths << p if @contents.has_key?(p) # only update file if it's been modified if @contents[p].modified?(c) out << [:update, c] end else out << [:create, c] end end out += (@contents.keys.sort - got_paths.sort).map {|p| [:delete, { "rel_path" => p }] } out else raise(RuntimeError, "Trying to calculate dir changes without any contents") end end
create_local()
click to toggle source
# File lib/dbox/db.rb, line 430 def create_local log.info "Creating #{local_path}" saving_parent_timestamp do FileUtils.mkdir_p(local_path) update_file_timestamp end end
create_remote()
click to toggle source
# File lib/dbox/db.rb, line 449 def create_remote api.create_dir(remote_path) force_metadata_update_from_server end
delete_local()
click to toggle source
# File lib/dbox/db.rb, line 438 def delete_local log.info "Deleting #{local_path}" saving_parent_timestamp do FileUtils.rm_r(local_path) end end
delete_remote()
click to toggle source
# File lib/dbox/db.rb, line 454 def delete_remote api.delete_dir(remote_path) end
dir?()
click to toggle source
# File lib/dbox/db.rb, line 426 def dir? true end
execute_changes(changes, direction)
click to toggle source
# File lib/dbox/db.rb, line 366 def execute_changes(changes, direction) log.debug "executing changes: #{changes.inspect}" changelist = { :created => [], :deleted => [], :updated => [] } changes.each do |op, c| case op when :create e = smart_new(c) e.create(direction) @contents[e.path] = e changelist[:created] << e.path when :update e = @contents[c["rel_path"]] e.update_modification_info(c) if direction == :down e.update(direction) changelist[:updated] << e.path when :delete e = @contents[c["rel_path"]] e.delete(direction) @contents.delete(e.path) changelist[:deleted] << e.path else raise(RuntimeError, "Unknown operation type: #{op}") end @db.save end changelist.keys.each {|k| changelist[k].sort! } changelist end
gather_local_info(rel, list_contents=true)
click to toggle source
# File lib/dbox/db.rb, line 399 def gather_local_info(rel, list_contents=true) full = @db.relative_to_local_path(rel) remote = @db.relative_to_remote_path(rel) attrs = { "path" => remote, "is_dir" => File.directory?(full), "modified" => File.mtime(full), "revision" => @contents[rel] ? @contents[rel].revision : nil } if attrs["is_dir"] && list_contents contents = Dir.entries(full).reject {|s| s == "." || s == ".." } attrs["contents"] = contents.map do |s| p = File.join(full, s) r = @db.local_to_relative_path(p) gather_local_info(r, false) end end attrs end
merge_changelists(old, new)
click to toggle source
# File lib/dbox/db.rb, line 395 def merge_changelists(old, new) old.merge(new) {|k, v1, v2| (v1 + v2).sort } end
print()
click to toggle source
# File lib/dbox/db.rb, line 466 def print puts puts "#{path} (v#{@revision}, #{@modified_at})" contents.each do |path, c| puts " #{c.path} (v#{c.revision}, #{c.modified_at})" end puts end
pull()
click to toggle source
# File lib/dbox/db.rb, line 296 def pull # calculate changes on this dir res = api.metadata(remote_path) changes = calculate_changes(res) # execute changes on this dir changelist = execute_changes(changes, :down) # recur on subdirs, expanding changelist as we go changelist = subdirs.inject(changelist) {|c, d| merge_changelists(c, d.pull) } # only update the modification info on the directory once all descendants are updated update_modification_info(res) # return changes @db.save changelist end
push()
click to toggle source
# File lib/dbox/db.rb, line 315 def push # calculate changes on this dir res = gather_local_info(@path) changes = calculate_changes(res) # execute changes on this dir changelist = execute_changes(changes, :up) # recur on subdirs, expanding changelist as we go changelist = subdirs.inject(changelist) {|c, d| merge_changelists(c, d.push) } # only update the modification info on the directory once all descendants are updated update_modification_info(res) # return changes @db.save changelist end
remove_dotfiles(contents)
click to toggle source
# File lib/dbox/db.rb, line 422 def remove_dotfiles(contents) contents.reject {|c| File.basename(c["path"]).start_with?(".") } end
subdirs()
click to toggle source
# File lib/dbox/db.rb, line 462 def subdirs @contents.values.select {|c| c.dir? } end
update_local()
click to toggle source
# File lib/dbox/db.rb, line 445 def update_local update_file_timestamp end
update_remote()
click to toggle source
# File lib/dbox/db.rb, line 458 def update_remote # do nothing end