class PosthavenTheme::Cli

Constants

DEFAULT_WHITELIST
IGNORE
NON_CONFIG_COMMANDS
TIMEFORMAT

Public Class Methods

new(args = [], local_options = {}, config = {}) click to toggle source
Calls superclass method
# File lib/posthaven_theme/cli.rb, line 35
def initialize(args = [], local_options = {}, config = {})
  command = config[:current_command] || config[:current_task]
  if command && !NON_CONFIG_COMMANDS.include?(command.name)
    setup_config
    validate_config!
  end
  super
end

Public Instance Methods

check() click to toggle source
# File lib/posthaven_theme/cli.rb, line 45
def check
  say('Configuration [OK]', :green)  if PosthavenTheme.asset_list
rescue PosthavenTheme::APIError => e
  report_error('Configuration [FAIL]', e)
end
configure(api_key=nil, theme_id=nil) click to toggle source
# File lib/posthaven_theme/cli.rb, line 55
def configure(api_key=nil, theme_id=nil)
  if api_key.nil?
    say('An api key is required!', :red)
    help(:configure)
  else
    config = {api_key: api_key, theme_id: theme_id}
    PosthavenTheme.config = config
    themes = PosthavenTheme.theme_list
    config[:theme_id] ||= select_theme(themes)
    create_file('config.yml', config.to_yaml)
  end
rescue PosthavenTheme::APIError
  say('Configuration Failed – Your API Key is Likely Incorrect', :red)
end
remove(*paths) click to toggle source
# File lib/posthaven_theme/cli.rb, line 113
def remove(*paths)
  paths.each do |path|
    delete_asset(path, options['quiet'])
  end
  say("Done.", :green) unless options['quiet']
rescue PosthavenTheme::APIError => e
  report_error("Could not remove.", e)
end
replace(*paths) click to toggle source
# File lib/posthaven_theme/cli.rb, line 84
def replace(*paths)
  say('Are you sure you want to completely replace your site theme assets? ' +
      'This is not undoable.',
      :yellow)
  if ask('Continue? (Y/N): ') == 'Y'
    # only delete files on remote that are not present locally
    # files present on remote and present locally get overridden anyway
    remote_assets = if paths.empty?
                      (PosthavenTheme.asset_list.map { |a| a['path'] } - local_assets_list)
                    else
                      paths
                    end
    remote_assets.each do |asset|
      unless PosthavenTheme.ignore_files.any? { |regex| regex =~ asset }
        delete_asset(asset, options['quiet'])
      end
    end
    local_assets = paths.empty? ? local_assets_list : paths
    local_assets.each do |asset|
      send_asset(asset, options['quiet'])
    end
    say("Done.", :green) unless options['quiet']
  end
rescue PosthavenTheme::APIError => e
  report_error('Replacement failed.', e)
end
systeminfo() click to toggle source
# File lib/posthaven_theme/cli.rb, line 152
def systeminfo
  ruby_version = "#{RUBY_VERSION}"
  ruby_version += "-p#{RUBY_PATCHLEVEL}" if RUBY_PATCHLEVEL
  puts "Ruby: v#{ruby_version}"
  puts "Operating System: #{RUBY_PLATFORM}"
  %w(Thor Listen HTTParty).each do |lib|
    require "#{lib.downcase}/version"
    puts "#{lib}: v" +  Kernel.const_get("#{lib}::VERSION")
  end
end
upload(*paths) click to toggle source
# File lib/posthaven_theme/cli.rb, line 72
def upload(*paths)
  assets = paths.empty? ? local_assets_list : paths
  assets.each do |asset|
    send_asset(asset, options['quiet'])
  end
  say("Done.", :green) unless options['quiet']
rescue PosthavenTheme::APIError => e
  report_error('Upload Failed.', e)
end
watch() click to toggle source
# File lib/posthaven_theme/cli.rb, line 127
def watch
  puts "Watching current folder: #{Dir.pwd}"
  watcher do |filename, event|
    filename = filename.gsub("#{Dir.pwd}/", '')

    next unless local_assets_list.include?(filename)
    action = if [:updated, :created].include?(event)
      :send_asset
    elsif event == :deleted
      :delete_asset
    else
      raise NotImplementedError, "Unknown event -- #{event} -- #{filename}"
    end

    begin
      send(action, filename, options['quiet'])
    rescue PosthavenTheme::APIError => e
      verb = action == :send_asset ? 'save' : 'delete'
      report_error("Unable to #{verb} asset.", e)
    end
  end
end

Protected Instance Methods

config() click to toggle source
# File lib/posthaven_theme/cli.rb, line 165
def config
  @config ||= YAML.load_file 'config.yml'
end
site_theme_url() click to toggle source
# File lib/posthaven_theme/cli.rb, line 169
def site_theme_url
  url = config[:site]
  url += "?preview_theme_id=#{config[:theme_id]}" if config[:theme_id] && config[:theme_id].to_i > 0
  url
end

Private Instance Methods

ask_with_options(prompt, options) click to toggle source

Options are strings to be numbered. Index of selected option is returned.

# File lib/posthaven_theme/cli.rb, line 259
def ask_with_options(prompt, options)
  say(prompt)
  options.each.with_index do |o, idx|
    say("  %2d: %s" % [idx + 1, o])
  end
  n = ask('Select>', limited_to: (1..options.size).map(&:to_s))
  n.to_i - 1
end
binary_file?(path) click to toggle source
# File lib/posthaven_theme/cli.rb, line 290
def binary_file?(path)
  mime = MimeMagic.by_path(path)
  say("'#{path}' is an unknown file-type, uploading asset as binary", :yellow) if mime.nil? && ENV['TEST'] != 'true'
  mime.nil? || !mime.text?
end
create_theme() click to toggle source
# File lib/posthaven_theme/cli.rb, line 268
def create_theme
  name = ''
  begin
    if (name = ask('What would you like to name your theme?')).size == 0
      say('Oops, the theme needs a name (you can change it later).', :red)
    end
  end  until name.size > 0
  PosthavenTheme.create_theme(name: name)
end
delete_asset(path, quiet=false) click to toggle source
# File lib/posthaven_theme/cli.rb, line 233
def delete_asset(path, quiet=false)
  return unless valid?(path)
  response = show_during("[#{timestamp}] Removing: #{path}", quiet) do
    PosthavenTheme.delete_asset(path)
  end
  if response.success?
    say("[#{timestamp}] Removed: #{path}", :green) unless quiet
  end
end
download_asset(path) click to toggle source
# File lib/posthaven_theme/cli.rb, line 196
def download_asset(path)
  return unless valid?(path)
  asset = PosthavenTheme.get_asset(path)
  if asset['value']
    # For CRLF line endings
    content = asset['value'].gsub("\r", "")
    format = "w"
  elsif asset['attachment']
    content = Base64.decode64(asset['attachment'])
    format = "w+b"
  end

  FileUtils.mkdir_p(File.dirname(path))
  File.open(path, format) {|f| f.write content} if content
rescue PosthavenTheme::APIError => e
  report_error(Time.now, "Could not download #{path}", e)
end
local_assets_list() click to toggle source
# File lib/posthaven_theme/cli.rb, line 183
def local_assets_list
  local_files.reject do |p|
    @permitted_files ||= (DEFAULT_WHITELIST | PosthavenTheme.whitelist_files).map{|pattern| Regexp.new(pattern)}
    @permitted_files.none? { |regex| regex =~ p } || PosthavenTheme.ignore_files.any? { |regex| regex =~ p }
  end
end
local_files() click to toggle source
# File lib/posthaven_theme/cli.rb, line 190
def local_files
  Dir.glob(File.join('**', '*')).reject do |f|
    File.directory?(f)
  end
end
notify_and_sleep(message) click to toggle source
# File lib/posthaven_theme/cli.rb, line 278
def notify_and_sleep(message)
  say(message, :red)
  PosthavenTheme.sleep
end
report_error(message, error) click to toggle source
# File lib/posthaven_theme/cli.rb, line 296
def report_error(message, error)
  say("[#{timestamp(Time.now)}] Error: #{message}", :red)
  say("Error Details: #{error.message}", :yellow)
end
select_theme(existing) click to toggle source
# File lib/posthaven_theme/cli.rb, line 243
def select_theme(existing)
  opt = ask_with_options('Configure the theme to edit:', [
    'Create a new theme',
    'Select an existing theme',
  ])
  case opt
  when 0
    create_theme['id']
  when 1
    existing.sort_by! { |t| t['name'] }
    n = ask_with_options("Select from your existing themes:", existing.map { |t| t['name'] })
    existing[n]['id']
  end
end
send_asset(asset, quiet=false) click to toggle source
# File lib/posthaven_theme/cli.rb, line 214
def send_asset(asset, quiet=false)
  return unless valid?(asset)
  data = {path: asset}
  content = File.read(asset)
  if binary_file?(asset) || PosthavenTheme.is_binary_data?(content)
    content = File.open(asset, "rb") { |io| io.read }
    data.merge!(attachment: Base64.encode64(content))
  else
    data.merge!(value: content)
  end

  response = show_during("[#{timestamp}] Uploading: #{asset}", quiet) do
    PosthavenTheme.send_asset(data)
  end
  if response.success?
    say("[#{timestamp}] Uploaded: #{asset}", :green) unless quiet
  end
end
setup_config() click to toggle source
# File lib/posthaven_theme/cli.rb, line 315
def setup_config
  if File.exist?('config.yml')
    PosthavenTheme.config = YAML.load(File.read('config.yml'))
  end
end
show_during(message = '', quiet = false) { || ... } click to toggle source
# File lib/posthaven_theme/cli.rb, line 301
def show_during(message = '', quiet = false, &block)
  print(message) unless quiet
  result = yield
  print("\r#{' ' * message.length}\r") unless quiet
  result
rescue
  print("\n") unless quiet
  raise
end
timestamp(time = Time.now) click to toggle source
# File lib/posthaven_theme/cli.rb, line 311
def timestamp(time = Time.now)
  time.strftime(TIMEFORMAT)
end
valid?(path) click to toggle source
# File lib/posthaven_theme/cli.rb, line 283
def valid?(path)
  return true if DEFAULT_WHITELIST.include?(path.split('/').first + "/")
  say("'#{path}' is not in a valid file for theme uploads", :yellow)
  say("Files need to be in one of the following subdirectories: #{DEFAULT_WHITELIST.join(' ')}", :yellow)
  false
end
validate_config!() click to toggle source
# File lib/posthaven_theme/cli.rb, line 321
def validate_config!
  if PosthavenTheme.config.empty?
    say 'config.yml does not exist or is empty!', :red
    exit
  elsif %i{api_key theme_id}.any? { |k| PosthavenTheme.config[k].nil? }
    say 'config.yml must include :api_key: and :theme_id:!', :red
    exit
  end
end
watcher() { |filename, event| ... } click to toggle source
# File lib/posthaven_theme/cli.rb, line 177
def watcher
  Filewatcher.new(Dir.pwd, every: true).watch() do |filename, event|
    yield(filename, event)
  end
end