class Homesick::CLI

Homesick's command line interface

Public Class Methods

new(args = [], options = {}, config = {}) click to toggle source
Calls superclass method
# File lib/homesick/cli.rb, line 20
def initialize(args = [], options = {}, config = {})
  super
  # Check if git is installed
  unless git_version_correct?
    say_status :error, "Git version >= #{Homesick::Actions::GitActions::STRING} must be installed to use Homesick", :red
    exit(1)
  end
  # Hack in support for diffing symlinks
  # Also adds support for checking if destination or content is a directory
  shell_metaclass = class << shell; self; end
  shell_metaclass.send(:define_method, :show_diff) do |destination, source|
    destination = Pathname.new(destination)
    source = Pathname.new(source)
    return 'Unable to create diff: destination or content is a directory' if destination.directory? || source.directory?
    return super(destination, File.binread(source)) unless destination.symlink?
    say "- #{destination.readlink}", :red, true
    say "+ #{source.expand_path}", :green, true
  end
end

Public Instance Methods

cd(castle = DEFAULT_CASTLE_NAME) click to toggle source
# File lib/homesick/cli.rb, line 257
def cd(castle = DEFAULT_CASTLE_NAME)
  check_castle_existance castle, 'cd'
  castle_dir = repos_dir.join(castle)
  say_status "cd #{castle_dir.realpath}",
             "Opening a new shell in castle '#{castle}'. To return to the original one exit from the new shell.",
             :green
  inside castle_dir do
    system(ENV['SHELL'])
  end
end
clone(uri, destination=nil) click to toggle source
# File lib/homesick/cli.rb, line 41
def clone(uri, destination=nil)
  destination = Pathname.new(destination) unless destination.nil?

  inside repos_dir do
    if File.exist?(uri)
      uri = Pathname.new(uri).expand_path
      fail "Castle already cloned to #{uri}" if uri.to_s.start_with?(repos_dir.to_s)

      destination = uri.basename if destination.nil?

      ln_s uri, destination
    elsif uri =~ GITHUB_NAME_REPO_PATTERN
      destination = Pathname.new(uri).basename if destination.nil?
      git_clone "https://github.com/#{Regexp.last_match[1]}.git",
                destination: destination
    elsif uri =~ /%r([^%r]*?)(\.git)?\Z/ || uri =~ /[^:]+:([^:]+)(\.git)?\Z/
      destination = Pathname.new(Regexp.last_match[1].gsub(/\.git$/, '')).basename if destination.nil?
      git_clone uri, destination: destination
    else
      fail "Unknown URI format: #{uri}"
    end

    setup_castle(destination)
  end
end
commit(name = DEFAULT_CASTLE_NAME, message = nil) click to toggle source
# File lib/homesick/cli.rb, line 104
def commit(name = DEFAULT_CASTLE_NAME, message = nil)
  commit_castle name, message
end
destroy(name) click to toggle source
# File lib/homesick/cli.rb, line 248
def destroy(name)
  check_castle_existance name, 'destroy'
  return unless shell.yes?('This will destroy your castle irreversible! Are you sure?')

  unlink(name)
  rm_rf repos_dir.join(name)
end
diff(castle = DEFAULT_CASTLE_NAME) click to toggle source
# File lib/homesick/cli.rb, line 214
def diff(castle = DEFAULT_CASTLE_NAME)
  check_castle_existance(castle, 'diff')
  inside repos_dir.join(castle) do
    git_diff
  end
end
exec(castle, *args) click to toggle source
# File lib/homesick/cli.rb, line 290
def exec(castle, *args)
  check_castle_existance castle, 'exec'
  unless args.count > 0
    say_status :error,
               'You must pass a shell command to execute',
               :red
    exit(1)
  end
  full_command = args.join(' ')
  say_status "exec '#{full_command}'",
             "#{options[:pretend] ? 'Would execute' : 'Executing command'} '#{full_command}' in castle '#{castle}'",
             :green
  inside repos_dir.join(castle) do
    system(full_command)
  end
end
exec_all(*args) click to toggle source
# File lib/homesick/cli.rb, line 309
def exec_all(*args)
  unless args.count > 0
    say_status :error,
               'You must pass a shell command to execute',
               :red
    exit(1)
  end
  full_command = args.join(' ')
  inside_each_castle do |castle|
    say_status "exec '#{full_command}'",
               "#{options[:pretend] ? 'Would execute' : 'Executing command'} '#{full_command}' in castle '#{castle}'",
               :green
    system(full_command)
  end
end
generate(castle) click to toggle source
# File lib/homesick/cli.rb, line 228
def generate(castle)
  castle = Pathname.new(castle).expand_path

  github_user = `git config github.user`.chomp
  github_user = nil if github_user == ''
  github_repo = castle.basename

  empty_directory castle
  inside castle do
    git_init
    if github_user
      url = "git@github.com:#{github_user}/#{github_repo}.git"
      git_remote_add 'origin', url
    end

    empty_directory 'home'
  end
end
list() click to toggle source
# File lib/homesick/cli.rb, line 197
def list
  inside_each_castle do |castle|
    say_status castle.relative_path_from(repos_dir).to_s,
               `git config remote.origin.url`.chomp,
               :cyan
  end
end
open(castle = DEFAULT_CASTLE_NAME) click to toggle source
# File lib/homesick/cli.rb, line 270
def open(castle = DEFAULT_CASTLE_NAME)
  unless ENV['EDITOR']
    say_status :error,
               'The $EDITOR environment variable must be set to use this command',
               :red

    exit(1)
  end
  check_castle_existance castle, 'open'
  castle_dir = repos_dir.join(castle)
  say_status "#{castle_dir.realpath}: #{ENV['EDITOR']} .",
             "Opening the root directory of castle '#{castle}' in editor '#{ENV['EDITOR']}'.",
             :green
  inside castle_dir do
    system("#{ENV['EDITOR']} .")
  end
end
pull(name = DEFAULT_CASTLE_NAME) click to toggle source
# File lib/homesick/cli.rb, line 92
def pull(name = DEFAULT_CASTLE_NAME)
  if options[:all]
    inside_each_castle do |castle|
      say castle.to_s.gsub(repos_dir.to_s + '/', '') + ':'
      update_castle castle
    end
  else
    update_castle name
  end
end
push(name = DEFAULT_CASTLE_NAME) click to toggle source
# File lib/homesick/cli.rb, line 109
def push(name = DEFAULT_CASTLE_NAME)
  push_castle name
end
rc(name = DEFAULT_CASTLE_NAME) click to toggle source
# File lib/homesick/cli.rb, line 72
def rc(name = DEFAULT_CASTLE_NAME)
  inside repos_dir do
    destination = Pathname.new(name)
    homesickrc = destination.join('.homesickrc').expand_path
    return unless homesickrc.exist?
    proceed = options[:force] || shell.yes?("#{name} has a .homesickrc. Proceed with evaling it? (This could be destructive)")
    return say_status 'eval skip', "not evaling #{homesickrc}, #{destination} may need manual configuration", :blue unless proceed
    say_status 'eval', homesickrc
    inside destination do
      eval homesickrc.read, binding, homesickrc.expand_path.to_s
    end
  end
end
show_path(castle = DEFAULT_CASTLE_NAME) click to toggle source
# File lib/homesick/cli.rb, line 222
def show_path(castle = DEFAULT_CASTLE_NAME)
  check_castle_existance(castle, 'show_path')
  say repos_dir.join(castle)
end
status(castle = DEFAULT_CASTLE_NAME) click to toggle source
# File lib/homesick/cli.rb, line 206
def status(castle = DEFAULT_CASTLE_NAME)
  check_castle_existance(castle, 'status')
  inside repos_dir.join(castle) do
    git_status
  end
end
track(file, castle = DEFAULT_CASTLE_NAME) click to toggle source
# File lib/homesick/cli.rb, line 152
def track(file, castle = DEFAULT_CASTLE_NAME)
  castle = Pathname.new(castle)
  file = Pathname.new(file.chomp('/'))
  check_castle_existance(castle, 'track')

  absolute_path = file.expand_path
  relative_dir = absolute_path.relative_path_from(home_dir).dirname
  castle_path = Pathname.new(castle_dir(castle)).join(relative_dir)
  FileUtils.mkdir_p castle_path

  # Are we already tracking this or anything inside it?
  target = Pathname.new(castle_path.join(file.basename))
  if target.exist?
    if absolute_path.directory?
      move_dir_contents(target, absolute_path)
      absolute_path.rmtree
      subdir_remove(castle, relative_dir + file.basename)

    elsif more_recent? absolute_path, target
      target.delete
      mv absolute_path, castle_path
    else
      say_status(:track,
                 "#{target} already exists, and is more recent than #{file}. Run 'homesick SYMLINK CASTLE' to create symlinks.",
                 :blue)
    end
  else
    mv absolute_path, castle_path
  end

  inside home_dir do
    absolute_path = castle_path + file.basename
    home_path = home_dir + relative_dir + file.basename
    ln_s absolute_path, home_path
  end

  inside castle_path do
    git_add absolute_path
  end

  # are we tracking something nested? Add the parent dir to the manifest
  subdir_add(castle, relative_dir) unless relative_dir.eql?(Pathname.new('.'))
end
version() click to toggle source
# File lib/homesick/cli.rb, line 326
def version
  say Homesick::Version::STRING
end