class State

Encapsulates the session state of the client.

Attributes

argv[R]

The actual/original command-line arguments

cache[R]

Hash of remote file paths to cached file metadata.

debug_enabled[RW]

true if the –debug option was given, false otherwise.

exit_requested[RW]

true if the client has requested to quit, false otherwise.

exit_status[RW]

integer.

interactive[R]

Whether the session is interactive.

local_oldpwd[RW]

The previous local working directory path.

oldpwd[R]

The previous remote working directory path.

pwd[R]

The remote working directory path.

Public Class Methods

new(client, interactive = true, argv = ARGV) click to toggle source

Return a new application state that uses the given client. Starts at the Dropbox root and with an empty cache.

# File lib/droxi/state.rb, line 38
def initialize(client, interactive = true, argv = ARGV)
  @interactive = interactive
  @argv = argv
  @cache = Cache.new
  @client = client
  @exit_requested = false
  @debug_enabled = false
  @pwd = '/'
  @oldpwd = Settings[:oldpwd] || '/'
  @local_oldpwd = Dir.pwd
  @exit_status = 0
end

Public Instance Methods

contents(path) click to toggle source

Return an Array of paths of files in a Dropbox directory.

# File lib/droxi/state.rb, line 67
def contents(path)
  path = path.downcase
  path = resolve_path(path)
  metadata(path)
  path = "#{path}/".sub('//', '/')
  keys = @cache.keys.select do |key|
    key.start_with?(path) && key != path && !key.sub(path, '').include?('/')
  end
  keys.map { |key| @cache[key]['path'] }
end
directory?(path) click to toggle source

Return true if the Dropbox path is a directory, false otherwise.

# File lib/droxi/state.rb, line 79
def directory?(path)
  path = path.downcase
  path = resolve_path(path)
  metadata(File.dirname(path))
  @cache.include?(path) && @cache[path]['is_dir']
end
expand_patterns(patterns, preserve_root = false) click to toggle source

Expand an Array of file globs into an an Array of Dropbox file paths and return the result.

# File lib/droxi/state.rb, line 108
def expand_patterns(patterns, preserve_root = false)
  patterns.flat_map do |pattern|
    path = resolve_path(pattern)
    if directory?(path)
      preserve_root ? pattern : path
    else
      get_matches(pattern, path, preserve_root)
    end
  end
end
forget_contents(partial_path) { |"forget: #{partial_path}: nothing to forget"| ... } click to toggle source

Recursively remove directory contents from metadata cache. Yield lines of (error) output if a block is given.

# File lib/droxi/state.rb, line 121
def forget_contents(partial_path)
  path = resolve_path(partial_path).downcase
  if @cache.fetch(path, {}).include?('contents')
    @cache[path]['contents'].dup.each { |m| @cache.remove(m['path']) }
    @cache[path].delete('contents')
  elsif block_given?
    yield "forget: #{partial_path}: nothing to forget"
  end
end
metadata(path, require_contents = true) click to toggle source

Return a Hash of the Dropbox metadata for a file, or nil if the file does not exist.

# File lib/droxi/state.rb, line 53
def metadata(path, require_contents = true)
  path = path.downcase
  tokens = path.split('/').drop(1)

  (0..tokens.size).each do |i|
    partial_path = '/' + tokens.take(i).join('/')
    next if @cache.full_info?(partial_path, require_contents)
    return nil unless fetch_metadata(partial_path)
  end

  @cache[path]
end
pwd=(value) click to toggle source

Set the remote working directory, and set the previous remote working directory to the old value.

# File lib/droxi/state.rb, line 88
def pwd=(value)
  @oldpwd, @pwd = @pwd, value
  Settings[:oldpwd] = @oldpwd
end
resolve_path(arg) click to toggle source

Expand a Dropbox file path and return the result.

# File lib/droxi/state.rb, line 94
def resolve_path(arg)
  # REVIEW: See if we can do this in fewer lines (e.g. without two gsub!s).
  path = arg.start_with?('/') ? arg.dup : "#{@pwd}/#{arg}"
  path.gsub!('//', '/')
  nil while path.sub!(%r{/([^/]+?)/\.\.}, '')
  nil while path.sub!('./', '')
  path.sub!(%r{/\.$}, '')
  path.chomp!('/')
  path.gsub!('//', '/')
  path.empty? ? '/' : path
end

Private Instance Methods

fetch_metadata(path) click to toggle source

Cache metadata for the remote file for a given path. Return true if successful, false otherwise.

# File lib/droxi/state.rb, line 135
def fetch_metadata(path)
  data = @client.metadata(path.downcase)
  return true if data['is_deleted']
  @cache.add(data)
  true
rescue DropboxError
  false
end
get_matches(pattern, path, preserve_root) click to toggle source

Return an Array of file paths matching a glob pattern, or a GlobError if no files were matched.

# File lib/droxi/state.rb, line 146
def get_matches(pattern, path, preserve_root)
  path = path.downcase
  dir = File.dirname(path)
  matches = contents(dir).select do |entry|
    File.fnmatch(path, entry.downcase)
  end
  return GlobError.new(pattern) if matches.empty?
  return matches unless preserve_root
  prefix = pattern.rpartition('/')[0, 2].join
  matches.map { |match| prefix + match.rpartition('/')[2] }
end