Merge pull request #82 from thenickperson/rubocop-fixes

Reduce Rubocop errors
This commit is contained in:
Christian Bundy
2014-01-23 12:19:57 -08:00
6 changed files with 251 additions and 131 deletions

19
.rubocop.yml Normal file
View File

@@ -0,0 +1,19 @@
# TODO: Eval is required for the .homesickrc feature. This should eventually be
# removed if the feature is implemented in a more secure way.
Eval:
Enabled: false
# TODO: The following settings disable reports about issues that can be fixed
# through refactoring. Remove these as offenses are removed from the code base.
ClassLength:
Enabled: false
CyclomaticComplexity:
Max: 13
LineLength:
Enabled: false
MethodLength:
Max: 36

View File

@@ -1,6 +1,7 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
require 'thor' require 'thor'
# Homesick's command line interface (with some helper methods)
class Homesick < Thor class Homesick < Thor
autoload :Shell, 'homesick/shell' autoload :Shell, 'homesick/shell'
autoload :Actions, 'homesick/actions' autoload :Actions, 'homesick/actions'
@@ -33,34 +34,23 @@ class Homesick < Thor
destination = nil destination = nil
if File.exist?(uri) if File.exist?(uri)
uri = Pathname.new(uri).expand_path uri = Pathname.new(uri).expand_path
if uri.to_s.start_with?(repos_dir.to_s) fail "Castle already cloned to #{uri}" if uri.to_s.start_with?(repos_dir.to_s)
raise "Castle already cloned to #{uri}"
end
destination = uri.basename destination = uri.basename
ln_s uri, destination ln_s uri, destination
elsif uri =~ GITHUB_NAME_REPO_PATTERN elsif uri =~ GITHUB_NAME_REPO_PATTERN
destination = Pathname.new(uri).basename destination = Pathname.new(uri).basename
git_clone "https://github.com/#{$1}.git", :destination => destination git_clone "https://github.com/#{Regexp.last_match[1]}.git",
elsif uri =~ /%r([^%r]*?)(\.git)?\Z/ destination: destination
destination = Pathname.new($1) elsif uri =~ /%r([^%r]*?)(\.git)?\Z/ || uri =~ /[^:]+:([^:]+)(\.git)?\Z/
git_clone uri destination = Pathname.new(Regexp.last_match[1])
elsif uri =~ /[^:]+:([^:]+)(\.git)?\Z/
destination = Pathname.new($1)
git_clone uri git_clone uri
else else
raise "Unknown URI format: #{uri}" fail "Unknown URI format: #{uri}"
end end
if destination.join('.gitmodules').exist? setup_castle(destination)
inside destination do
git_submodule_init
git_submodule_update
end
end
rc(destination)
end end
end end
@@ -77,14 +67,20 @@ class Homesick < Thor
eval homesickrc.read, binding, homesickrc.expand_path.to_s eval homesickrc.read, binding, homesickrc.expand_path.to_s
end end
else else
shell.say_status 'eval skip', "not evaling #{homesickrc}, #{destination} may need manual configuration", :blue shell.say_status 'eval skip',
"not evaling #{homesickrc}, #{destination} may need manual configuration",
:blue
end end
end end
end end
end end
desc 'pull CASTLE', 'Update the specified castle' desc 'pull CASTLE', 'Update the specified castle'
method_option :all, :type => :boolean, :default => false, :required => false, :desc => 'Update all cloned castles' method_option :all,
type: :boolean,
default: false,
required: false,
desc: 'Update all cloned castles'
def pull(name = DEFAULT_CASTLE_NAME) def pull(name = DEFAULT_CASTLE_NAME)
if options[:all] if options[:all]
inside_each_castle do |castle| inside_each_castle do |castle|
@@ -94,13 +90,11 @@ class Homesick < Thor
else else
update_castle name update_castle name
end end
end end
desc 'commit CASTLE MESSAGE', "Commit the specified castle's changes" desc 'commit CASTLE MESSAGE', "Commit the specified castle's changes"
def commit(name = DEFAULT_CASTLE_NAME, message = nil) def commit(name = DEFAULT_CASTLE_NAME, message = nil)
commit_castle name, message commit_castle name, message
end end
desc 'push CASTLE', 'Push the specified castle' desc 'push CASTLE', 'Push the specified castle'
@@ -126,7 +120,9 @@ class Homesick < Thor
end end
desc 'link CASTLE', 'Symlinks all dotfiles from the specified castle' desc 'link CASTLE', 'Symlinks all dotfiles from the specified castle'
method_option :force, :default => false, :desc => 'Overwrite existing conflicting symlinks without prompting.' method_option :force,
default: false,
desc: 'Overwrite existing conflicting symlinks without prompting.'
def link(name = DEFAULT_CASTLE_NAME) def link(name = DEFAULT_CASTLE_NAME)
check_castle_existance(name, 'symlink') check_castle_existance(name, 'symlink')
@@ -166,7 +162,9 @@ class Homesick < Thor
target.delete target.delete
mv absolute_path, castle_path mv absolute_path, castle_path
else else
shell.say_status(:track, "#{target} already exists, and is more recent than #{file}. Run 'homesick SYMLINK CASTLE' to create symlinks.", :blue) unless options[:quiet] shell.say_status(:track,
"#{target} already exists, and is more recent than #{file}. Run 'homesick SYMLINK CASTLE' to create symlinks.",
:blue) unless options[:quiet]
end end
else else
mv absolute_path, castle_path mv absolute_path, castle_path
@@ -189,7 +187,9 @@ class Homesick < Thor
desc 'list', 'List cloned castles' desc 'list', 'List cloned castles'
def list def list
inside_each_castle do |castle| inside_each_castle do |castle|
say_status castle.relative_path_from(repos_dir).to_s, `git config remote.origin.url`.chomp, :cyan say_status castle.relative_path_from(repos_dir).to_s,
`git config remote.origin.url`.chomp,
:cyan
end end
end end
@@ -235,37 +235,43 @@ class Homesick < Thor
end end
end end
desc "destroy CASTLE", "Delete all symlinks and remove the cloned repository" desc 'destroy CASTLE', 'Delete all symlinks and remove the cloned repository'
def destroy(name) def destroy(name)
check_castle_existance name, "destroy" check_castle_existance name, 'destroy'
if shell.yes?("This will destroy your castle irreversible! Are you sure?") if shell.yes?('This will destroy your castle irreversible! Are you sure?')
unlink(name) unlink(name)
rm_rf repos_dir.join(name) rm_rf repos_dir.join(name)
end end
end end
desc "cd CASTLE", "Open a new shell in the root of the given castle" desc 'cd CASTLE', 'Open a new shell in the root of the given castle'
def cd(castle = DEFAULT_CASTLE_NAME) def cd(castle = DEFAULT_CASTLE_NAME)
check_castle_existance castle, "cd" check_castle_existance castle, 'cd'
castle_dir = repos_dir.join(castle) 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 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 inside castle_dir do
system(ENV['SHELL']) system(ENV['SHELL'])
end end
end end
desc "open CASTLE", "Open your default editor in the root of the given castle" desc 'open CASTLE',
'Open your default editor in the root of the given castle'
def open(castle = DEFAULT_CASTLE_NAME) def open(castle = DEFAULT_CASTLE_NAME)
if ! ENV['EDITOR'] unless ENV['EDITOR']
say_status :error,"The $EDITOR environment variable must be set to use this command", :red say_status :error,
'The $EDITOR environment variable must be set to use this command',
:red
exit(1) exit(1)
end end
check_castle_existance castle, "open" check_castle_existance castle, 'open'
castle_dir = repos_dir.join(castle) castle_dir = repos_dir.join(castle)
say_status "#{ENV['EDITOR']} #{castle_dir.realpath}", "Opening the root directory of castle '#{castle}' in editor '#{ENV['EDITOR']}'.", :green say_status "#{ENV['EDITOR']} #{castle_dir.realpath}",
"Opening the root directory of castle '#{castle}' in editor '#{ENV['EDITOR']}'.",
:green
inside castle_dir do inside castle_dir do
system(ENV['EDITOR']) system(ENV['EDITOR'])
end end
@@ -292,7 +298,9 @@ class Homesick < Thor
def check_castle_existance(name, action) def check_castle_existance(name, action)
unless castle_dir(name).exist? unless castle_dir(name).exist?
say_status :error, "Could not #{action} #{name}, expected #{castle_dir(name)} exist and contain dotfiles", :red say_status :error,
"Could not #{action} #{name}, expected #{castle_dir(name)} exist and contain dotfiles",
:red
exit(1) exit(1)
end end
@@ -301,7 +309,7 @@ class Homesick < Thor
def all_castles def all_castles
dirs = Pathname.glob("#{repos_dir}/**/.git", File::FNM_DOTMATCH) dirs = Pathname.glob("#{repos_dir}/**/.git", File::FNM_DOTMATCH)
# reject paths that lie inside another castle, like git submodules # reject paths that lie inside another castle, like git submodules
return dirs.reject do |dir| dirs.reject do |dir|
dirs.any? do |other| dirs.any? do |other|
dir != other && dir.fnmatch(other.parent.join('*').to_s) dir != other && dir.fnmatch(other.parent.join('*').to_s)
end end
@@ -329,7 +337,7 @@ class Homesick < Thor
def commit_castle(castle, message) def commit_castle(castle, message)
check_castle_existance(castle, 'commit') check_castle_existance(castle, 'commit')
inside repos_dir.join(castle) do inside repos_dir.join(castle) do
git_commit_all :message => message git_commit_all message: message
end end
end end
@@ -371,7 +379,9 @@ class Homesick < Thor
def subdir_remove(castle, path) def subdir_remove(castle, path)
subdir_filepath = subdir_file(castle) subdir_filepath = subdir_file(castle)
if subdir_filepath.exist? if subdir_filepath.exist?
lines = IO.readlines(subdir_filepath).delete_if { |line| line == "#{path}\n" } lines = IO.readlines(subdir_filepath).delete_if do |line|
line == "#{path}\n"
end
File.open(subdir_filepath, 'w') { |manfile| manfile.puts lines } File.open(subdir_filepath, 'w') { |manfile| manfile.puts lines }
end end
@@ -403,10 +413,16 @@ class Homesick < Thor
first_p.mtime > second_p.mtime && !first_p.symlink? first_p.mtime > second_p.mtime && !first_p.symlink?
end end
def collision_accepted?
options[:force] || shell.file_collision(destination) { source }
end
def each_file(castle, basedir, subdirs) def each_file(castle, basedir, subdirs)
absolute_basedir = Pathname.new(basedir).expand_path absolute_basedir = Pathname.new(basedir).expand_path
inside basedir do inside basedir do
files = Pathname.glob('{.*,*}').reject{ |a| ['.', '..'].include?(a.to_s) } files = Pathname.glob('{.*,*}').reject do |a|
['.', '..'].include?(a.to_s)
end
files.each do |path| files.each do |path|
absolute_path = path.expand_path absolute_path = path.expand_path
castle_home = castle_dir(castle) castle_home = castle_dir(castle)
@@ -434,7 +450,7 @@ class Homesick < Thor
home_path = home_dir.join(relative_dir).join(path) home_path = home_dir.join(relative_dir).join(path)
yield(absolute_path, home_path) yield(absolute_path, home_path)
end end
end end
end end
@@ -449,4 +465,15 @@ class Homesick < Thor
ln_s absolute_path, home_path ln_s absolute_path, home_path
end end
end end
def setup_castle(path)
if path.join('.gitmodules').exist?
inside path do
git_submodule_init
git_submodule_update
end
end
rc(path)
end
end end

View File

@@ -1,7 +1,8 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
class Homesick class Homesick
# Git-related and file-related helper methods for the Homesick class
module Actions module Actions
# TODO move this to be more like thor's template, empty_directory, etc # TODO: move this to be more like thor's template, empty_directory, etc
def git_clone(repo, config = {}) def git_clone(repo, config = {})
config ||= {} config ||= {}
destination = config[:destination] || File.basename(repo, '.git') destination = config[:destination] || File.basename(repo, '.git')
@@ -9,11 +10,13 @@ class Homesick
destination = Pathname.new(destination) unless destination.kind_of?(Pathname) destination = Pathname.new(destination) unless destination.kind_of?(Pathname)
FileUtils.mkdir_p destination.dirname FileUtils.mkdir_p destination.dirname
if ! destination.directory? if destination.directory?
say_status 'git clone', "#{repo} to #{destination.expand_path}", :green unless options[:quiet]
system "git clone -q --config push.default=upstream --recursive #{repo} #{destination}" unless options[:pretend]
else
say_status :exist, destination.expand_path, :blue unless options[:quiet] say_status :exist, destination.expand_path, :blue unless options[:quiet]
else
say_status 'git clone',
"#{repo} to #{destination.expand_path}",
:green unless options[:quiet]
system "git clone -q --config push.default=upstream --recursive #{repo} #{destination}" unless options[:pretend]
end end
end end
@@ -21,11 +24,11 @@ class Homesick
path = Pathname.new(path) path = Pathname.new(path)
inside path do inside path do
if !path.join('.git').exist? if path.join('.git').exist?
say_status 'git init', 'already initialized', :blue unless options[:quiet]
else
say_status 'git init', '' unless options[:quiet] say_status 'git init', '' unless options[:quiet]
system 'git init >/dev/null' unless options[:pretend] system 'git init >/dev/null' unless options[:pretend]
else
say_status 'git init', 'already initialized', :blue unless options[:quiet]
end end
end end
end end
@@ -34,11 +37,11 @@ class Homesick
existing_remote = `git config remote.#{name}.url`.chomp existing_remote = `git config remote.#{name}.url`.chomp
existing_remote = nil if existing_remote == '' existing_remote = nil if existing_remote == ''
if !existing_remote if existing_remote
say_status 'git remote', "#{name} already exists", :blue unless options[:quiet]
else
say_status 'git remote', "add #{name} #{url}" unless options[:quiet] say_status 'git remote', "add #{name} #{url}" unless options[:quiet]
system "git remote add #{name} #{url}" unless options[:pretend] system "git remote add #{name} #{url}" unless options[:pretend]
else
say_status 'git remote', "#{name} already exists", :blue unless options[:quiet]
end end
end end
@@ -78,12 +81,12 @@ class Homesick
def git_status(config = {}) def git_status(config = {})
say_status 'git status', '', :green unless options[:quiet] say_status 'git status', '', :green unless options[:quiet]
system "git status" unless options[:pretend] system 'git status' unless options[:pretend]
end end
def git_diff(config = {}) def git_diff(config = {})
say_status 'git diff', '', :green unless options[:quiet] say_status 'git diff', '', :green unless options[:quiet]
system "git diff" unless options[:pretend] system 'git diff' unless options[:pretend]
end end
def mv(source, destination, config = {}) def mv(source, destination, config = {})
@@ -93,9 +96,7 @@ class Homesick
if destination.exist? if destination.exist?
say_status :conflict, "#{destination} exists", :red unless options[:quiet] say_status :conflict, "#{destination} exists", :red unless options[:quiet]
if options[:force] || shell.file_collision(destination) { source } system "mv '#{source}' '#{destination}'" if (options[:force] || shell.file_collision(destination) { source }) && !options[:pretend]
system "mv '#{source}' '#{destination}'" unless options[:pretend]
end
else else
# this needs some sort of message here. # this needs some sort of message here.
system "mv '#{source}' '#{destination}'" unless options[:pretend] system "mv '#{source}' '#{destination}'" unless options[:pretend]
@@ -133,25 +134,40 @@ class Homesick
destination = Pathname.new(destination) destination = Pathname.new(destination)
FileUtils.mkdir_p destination.dirname FileUtils.mkdir_p destination.dirname
if destination.symlink? action = if destination.symlink? && destination.readlink == source
if destination.readlink == source :identical
say_status :identical, destination.expand_path, :blue unless options[:quiet] elsif destination.symlink?
else :symlink_conflict
say_status :conflict, "#{destination} exists and points to #{destination.readlink}", :red unless options[:quiet] elsif destination.exist?
:conflict
else
:success
end
if options[:force] || shell.file_collision(destination) { source } handle_symlink_action action, source, destination
system "ln -nsf '#{source}' '#{destination}'" unless options[:pretend] end
end
end def handle_symlink_action(action, source, destination)
elsif destination.exist? case action
when :identical
say_status :identical, destination.expand_path, :blue unless options[:quiet]
when :symlink_conflict
say_status :conflict,
"#{destination} exists and points to #{destination.readlink}",
:red unless options[:quiet]
system "ln -nsf '#{source}' '#{destination}'" if collision_accepted?
when :conflict
say_status :conflict, "#{destination} exists", :red unless options[:quiet] say_status :conflict, "#{destination} exists", :red unless options[:quiet]
if options[:force] || shell.file_collision(destination) { source } if collision_accepted?
system "rm -rf '#{destination}'" unless options[:pretend] system "rm -rf '#{destination}'" unless options[:pretend]
system "ln -sf '#{source}' '#{destination}'" unless options[:pretend] system "ln -sf '#{source}' '#{destination}'" unless options[:pretend]
end end
else else
say_status :symlink, "#{source.expand_path} to #{destination.expand_path}", :green unless options[:quiet] say_status :symlink,
"#{source.expand_path} to #{destination.expand_path}",
:green unless options[:quiet]
system "ln -s '#{source}' '#{destination}'" unless options[:pretend] system "ln -s '#{source}' '#{destination}'" unless options[:pretend]
end end
end end

View File

@@ -1,7 +1,6 @@
class Homesick class Homesick
# Hack in support for diffing symlinks # Hack in support for diffing symlinks
class Shell < Thor::Shell::Color class Shell < Thor::Shell::Color
def show_diff(destination, content) def show_diff(destination, content)
destination = Pathname.new(destination) destination = Pathname.new(destination)
@@ -12,6 +11,5 @@ class Homesick
super super
end end
end end
end end
end end

View File

@@ -1,5 +1,7 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
class Homesick class Homesick
# A representation of Homesick's version number in constants, including a
# String of the entire version number
module Version module Version
MAJOR = 1 MAJOR = 1
MINOR = 0 MINOR = 0

View File

@@ -18,7 +18,9 @@ describe 'homesick' do
somewhere = create_construct somewhere = create_construct
local_repo = somewhere.directory('some_repo') local_repo = somewhere.directory('some_repo')
local_repo.file('.homesickrc') do |file| local_repo.file('.homesickrc') do |file|
file << "File.open(Dir.pwd + '/testing', 'w') { |f| f.print 'testing' }" file << "File.open(Dir.pwd + '/testing', 'w') do |f|
f.print 'testing'
end"
end end
expect($stdout).to receive(:print) expect($stdout).to receive(:print)
@@ -56,33 +58,39 @@ describe 'homesick' do
it 'should clone git repo like file:///path/to.git' do it 'should clone git repo like file:///path/to.git' do
bare_repo = File.join(create_construct.to_s, 'dotfiles.git') bare_repo = File.join(create_construct.to_s, 'dotfiles.git')
system "git init --bare #{bare_repo} >/dev/null 2>&1" system "git init --bare #{bare_repo} >/dev/null 2>&1"
# Capture stderr to suppress message about cloning an empty repo. # Capture stderr to suppress message about cloning an empty repo.
Capture.stderr do Capture.stderr do
homesick.clone "file://#{bare_repo}" homesick.clone "file://#{bare_repo}"
end end
File.directory?(File.join(home.to_s, '.homesick/repos/dotfiles')).should be_true File.directory?(File.join(home.to_s, '.homesick/repos/dotfiles'))
.should be_true
end end
it 'should clone git repo like git://host/path/to.git' do it 'should clone git repo like git://host/path/to.git' do
homesick.should_receive(:git_clone).with('git://github.com/technicalpickles/pickled-vim.git') homesick.should_receive(:git_clone)
.with('git://github.com/technicalpickles/pickled-vim.git')
homesick.clone 'git://github.com/technicalpickles/pickled-vim.git' homesick.clone 'git://github.com/technicalpickles/pickled-vim.git'
end end
it 'should clone git repo like git@host:path/to.git' do it 'should clone git repo like git@host:path/to.git' do
homesick.should_receive(:git_clone).with('git@github.com:technicalpickles/pickled-vim.git') homesick.should_receive(:git_clone)
.with('git@github.com:technicalpickles/pickled-vim.git')
homesick.clone 'git@github.com:technicalpickles/pickled-vim.git' homesick.clone 'git@github.com:technicalpickles/pickled-vim.git'
end end
it 'should clone git repo like http://host/path/to.git' do it 'should clone git repo like http://host/path/to.git' do
homesick.should_receive(:git_clone).with('http://github.com/technicalpickles/pickled-vim.git') homesick.should_receive(:git_clone)
.with('http://github.com/technicalpickles/pickled-vim.git')
homesick.clone 'http://github.com/technicalpickles/pickled-vim.git' homesick.clone 'http://github.com/technicalpickles/pickled-vim.git'
end end
it 'should clone git repo like http://host/path/to' do it 'should clone git repo like http://host/path/to' do
homesick.should_receive(:git_clone).with('http://github.com/technicalpickles/pickled-vim') homesick.should_receive(:git_clone)
.with('http://github.com/technicalpickles/pickled-vim')
homesick.clone 'http://github.com/technicalpickles/pickled-vim' homesick.clone 'http://github.com/technicalpickles/pickled-vim'
end end
@@ -99,7 +107,9 @@ describe 'homesick' do
end end
it 'should clone a github repo' do it 'should clone a github repo' do
homesick.should_receive(:git_clone).with('https://github.com/wfarr/dotfiles.git', :destination => Pathname.new('dotfiles')) homesick.should_receive(:git_clone)
.with('https://github.com/wfarr/dotfiles.git',
destination: Pathname.new('dotfiles'))
homesick.clone 'wfarr/dotfiles' homesick.clone 'wfarr/dotfiles'
end end
@@ -116,7 +126,9 @@ describe 'homesick' do
it 'executes the .homesickrc' do it 'executes the .homesickrc' do
castle.file('.homesickrc') do |file| castle.file('.homesickrc') do |file|
file << "File.open(Dir.pwd + '/testing', 'w') { |f| f.print 'testing' }" file << "File.open(Dir.pwd + '/testing', 'w') do |f|
f.print 'testing'
end"
end end
expect_any_instance_of(Thor::Shell::Basic).to receive(:say_status).with('eval', kind_of(Pathname)) expect_any_instance_of(Thor::Shell::Basic).to receive(:say_status).with('eval', kind_of(Pathname))
@@ -134,7 +146,9 @@ describe 'homesick' do
it 'does not execute the .homesickrc' do it 'does not execute the .homesickrc' do
castle.file('.homesickrc') do |file| castle.file('.homesickrc') do |file|
file << "File.open(Dir.pwd + '/testing', 'w') { |f| f.print 'testing' }" file << "File.open(Dir.pwd + '/testing', 'w') do |f|
f.print 'testing'
end"
end end
expect_any_instance_of(Thor::Shell::Basic).to receive(:say_status).with('eval skip', /not evaling.+/, :blue) expect_any_instance_of(Thor::Shell::Basic).to receive(:say_status).with('eval skip', /not evaling.+/, :blue)
@@ -165,7 +179,7 @@ describe 'homesick' do
end end
context 'when forced' do context 'when forced' do
let(:homesick) { Homesick.new [], :force => true } let(:homesick) { Homesick.new [], force: true }
it 'can override symlinks to directories' do it 'can override symlinks to directories' do
somewhere_else = create_construct somewhere_else = create_construct
@@ -219,7 +233,9 @@ describe 'homesick' do
end end
context "with '.config' and '.config/someapp' in .homesick_subdir" do context "with '.config' and '.config/someapp' in .homesick_subdir" do
let(:castle) { given_castle('glencairn', ['.config', '.config/someapp']) } let(:castle) do
given_castle('glencairn', ['.config', '.config/someapp'])
end
it 'can symlink under both of .config and .config/someapp' do it 'can symlink under both of .config and .config/someapp' do
config_dir = castle.directory('.config') config_dir = castle.directory('.config')
config_dotfile = config_dir.file('.some_dotfile') config_dotfile = config_dir.file('.some_dotfile')
@@ -231,13 +247,15 @@ describe 'homesick' do
home_config_dir = home.join('.config') home_config_dir = home.join('.config')
home_someapp_dir = home_config_dir.join('someapp') home_someapp_dir = home_config_dir.join('someapp')
home_config_dir.symlink?.should be == false home_config_dir.symlink?.should be == false
home_config_dir.join('.some_dotfile').readlink.should be == config_dotfile home_config_dir.join('.some_dotfile').readlink
.should be == config_dotfile
home_someapp_dir.symlink?.should be == false home_someapp_dir.symlink?.should be == false
home_someapp_dir.join('.some_appfile').readlink.should == someapp_dotfile home_someapp_dir.join('.some_appfile').readlink
.should == someapp_dotfile
end end
end end
context "when call with no castle name" do context 'when call with no castle name' do
let(:castle) { given_castle('dotfiles') } let(:castle) { given_castle('dotfiles') }
it 'using default castle name: "dotfiles"' do it 'using default castle name: "dotfiles"' do
dotfile = castle.file('.some_dotfile') dotfile = castle.file('.some_dotfile')
@@ -301,7 +319,9 @@ describe 'homesick' do
end end
context "with '.config' and '.config/someapp' in .homesick_subdir" do context "with '.config' and '.config/someapp' in .homesick_subdir" do
let(:castle) { given_castle('glencairn', ['.config', '.config/someapp']) } let(:castle) do
given_castle('glencairn', ['.config', '.config/someapp'])
end
it 'can unsymlink under both of .config and .config/someapp' do it 'can unsymlink under both of .config and .config/someapp' do
config_dir = castle.directory('.config') config_dir = castle.directory('.config')
@@ -320,7 +340,7 @@ describe 'homesick' do
end end
end end
context "when call with no castle name" do context 'when call with no castle name' do
let(:castle) { given_castle('dotfiles') } let(:castle) { given_castle('dotfiles') }
it 'using default castle name: "dotfiles"' do it 'using default castle name: "dotfiles"' do
@@ -339,8 +359,14 @@ describe 'homesick' do
given_castle('zomg') given_castle('zomg')
given_castle('wtf/zomg') given_castle('wtf/zomg')
homesick.should_receive(:say_status).with('zomg', 'git://github.com/technicalpickles/zomg.git', :cyan) homesick.should_receive(:say_status)
homesick.should_receive(:say_status).with('wtf/zomg', 'git://github.com/technicalpickles/zomg.git', :cyan) .with('zomg',
'git://github.com/technicalpickles/zomg.git',
:cyan)
homesick.should_receive(:say_status)
.with('wtf/zomg',
'git://github.com/technicalpickles/zomg.git',
:cyan)
homesick.list homesick.list
end end
@@ -358,7 +384,8 @@ describe 'homesick' do
some_rc_file = home.file '.some_rc_file' some_rc_file = home.file '.some_rc_file'
homesick.track(some_rc_file.to_s, 'castle_repo') homesick.track(some_rc_file.to_s, 'castle_repo')
text = Capture.stdout { homesick.status('castle_repo') } text = Capture.stdout { homesick.status('castle_repo') }
text.should =~ /Changes to be committed:.*new file:\s*home\/.some_rc_file/m text.should =~
/Changes to be committed:.*new file:\s*home\/.some_rc_file/m
end end
end end
@@ -367,7 +394,9 @@ describe 'homesick' do
given_castle('castle_repo') given_castle('castle_repo')
some_rc_file = home.file '.some_rc_file' some_rc_file = home.file '.some_rc_file'
homesick.track(some_rc_file.to_s, 'castle_repo') homesick.track(some_rc_file.to_s, 'castle_repo')
Capture.stdout { homesick.commit 'castle_repo', 'Adding a file to the test' } Capture.stdout do
homesick.commit 'castle_repo', 'Adding a file to the test'
end
text = Capture.stdout { homesick.diff('castle_repo') } text = Capture.stdout { homesick.diff('castle_repo') }
text.should eq('') text.should eq('')
end end
@@ -376,9 +405,11 @@ describe 'homesick' do
given_castle('castle_repo') given_castle('castle_repo')
some_rc_file = home.file '.some_rc_file' some_rc_file = home.file '.some_rc_file'
homesick.track(some_rc_file.to_s, 'castle_repo') homesick.track(some_rc_file.to_s, 'castle_repo')
Capture.stdout { homesick.commit 'castle_repo', 'Adding a file to the test' } Capture.stdout do
homesick.commit 'castle_repo', 'Adding a file to the test'
end
File.open(some_rc_file.to_s, 'w') do |file| File.open(some_rc_file.to_s, 'w') do |file|
file.puts "Some test text" file.puts 'Some test text'
end end
text = Capture.stdout { homesick.diff('castle_repo') } text = Capture.stdout { homesick.diff('castle_repo') }
text.should =~ /diff --git.+Some test text$/m text.should =~ /diff --git.+Some test text$/m
@@ -405,8 +436,11 @@ describe 'homesick' do
end end
it 'should print an error message when trying to pull a non-existant castle' do it 'should print an error message when trying to pull a non-existant castle' do
homesick.should_receive("say_status").once.with(:error, /Could not pull castle_repo, expected \/tmp\/construct_container.* exist and contain dotfiles/, :red) homesick.should_receive('say_status').once
expect { homesick.pull "castle_repo" }.to raise_error(SystemExit) .with(:error,
%r{Could not pull castle_repo, expected /tmp/construct_container.* exist and contain dotfiles},
:red)
expect { homesick.pull 'castle_repo' }.to raise_error(SystemExit)
end end
describe '--all' do describe '--all' do
@@ -414,9 +448,13 @@ describe 'homesick' do
given_castle('castle_repo') given_castle('castle_repo')
given_castle('glencairn') given_castle('glencairn')
homesick.stub(:system).exactly(2).times.with('git pull --quiet') homesick.stub(:system).exactly(2).times.with('git pull --quiet')
homesick.stub(:system).exactly(2).times.with('git submodule --quiet init') homesick.stub(:system).exactly(2).times
homesick.stub(:system).exactly(2).times.with('git submodule --quiet update --init --recursive >/dev/null 2>&1') .with('git submodule --quiet init')
Capture.stdout { Capture.stderr { homesick.invoke 'pull', [], all: true } } homesick.stub(:system).exactly(2).times
.with('git submodule --quiet update --init --recursive >/dev/null 2>&1')
Capture.stdout do
Capture.stderr { homesick.invoke 'pull', [], all: true }
end
end end
end end
@@ -430,8 +468,11 @@ describe 'homesick' do
end end
it 'should print an error message when trying to push a non-existant castle' do it 'should print an error message when trying to push a non-existant castle' do
homesick.should_receive("say_status").once.with(:error, /Could not push castle_repo, expected \/tmp\/construct_container.* exist and contain dotfiles/, :red) homesick.should_receive('say_status').once
expect { homesick.push "castle_repo" }.to raise_error(SystemExit) .with(:error,
%r{Could not push castle_repo, expected /tmp/construct_container.* exist and contain dotfiles},
:red)
expect { homesick.push 'castle_repo' }.to raise_error(SystemExit)
end end
end end
@@ -484,7 +525,7 @@ describe 'homesick' do
some_nested_dir.realpath.should == tracked_file.realpath some_nested_dir.realpath.should == tracked_file.realpath
end end
context "when call with no castle name" do context 'when call with no castle name' do
it 'using default castle name: "dotfiles"' do it 'using default castle name: "dotfiles"' do
castle = given_castle('dotfiles') castle = given_castle('dotfiles')
@@ -504,11 +545,15 @@ describe 'homesick' do
given_castle('castle_repo') given_castle('castle_repo')
some_rc_file = home.file '.a_random_rc_file' some_rc_file = home.file '.a_random_rc_file'
homesick.track(some_rc_file.to_s, 'castle_repo') homesick.track(some_rc_file.to_s, 'castle_repo')
text = Capture.stdout { homesick.commit('castle_repo', 'Test message') } text = Capture.stdout do
homesick.commit('castle_repo', 'Test message')
end
text.should =~ /^\[master \(root-commit\) \w+\] Test message/ text.should =~ /^\[master \(root-commit\) \w+\] Test message/
end end
end end
# Note that this is a test for the subdir_file related feature of track,
# not for the subdir_file method itself.
describe 'subdir_file' do describe 'subdir_file' do
it 'should add the nested files parent to the subdir_file' do it 'should add the nested files parent to the subdir_file' do
@@ -553,62 +598,75 @@ describe 'homesick' do
end end
end end
describe "destroy" do describe 'destroy' do
it "removes the symlink files" do it 'removes the symlink files' do
expect_any_instance_of(Thor::Shell::Basic).to receive(:yes?).and_return('y') expect_any_instance_of(Thor::Shell::Basic).to receive(:yes?).and_return('y')
given_castle("stronghold") given_castle('stronghold')
some_rc_file = home.file '.some_rc_file' some_rc_file = home.file '.some_rc_file'
homesick.track(some_rc_file.to_s, "stronghold") homesick.track(some_rc_file.to_s, 'stronghold')
homesick.destroy('stronghold') homesick.destroy('stronghold')
some_rc_file.should_not be_exist some_rc_file.should_not be_exist
end end
it "deletes the cloned repository" do it 'deletes the cloned repository' do
expect_any_instance_of(Thor::Shell::Basic).to receive(:yes?).and_return('y') expect_any_instance_of(Thor::Shell::Basic).to receive(:yes?).and_return('y')
castle = given_castle("stronghold") castle = given_castle('stronghold')
some_rc_file = home.file '.some_rc_file' some_rc_file = home.file '.some_rc_file'
homesick.track(some_rc_file.to_s, "stronghold") homesick.track(some_rc_file.to_s, 'stronghold')
homesick.destroy('stronghold') homesick.destroy('stronghold')
castle.should_not be_exist castle.should_not be_exist
end end
end end
describe "cd" do describe 'cd' do
it "cd's to the root directory of the given castle" do it "cd's to the root directory of the given castle" do
given_castle('castle_repo') given_castle('castle_repo')
homesick.should_receive("inside").once.with(kind_of(Pathname)).and_yield homesick.should_receive('inside').once.with(kind_of(Pathname)).and_yield
homesick.should_receive("system").once.with(ENV["SHELL"]) homesick.should_receive('system').once.with(ENV['SHELL'])
Capture.stdout { homesick.cd 'castle_repo' } Capture.stdout { homesick.cd 'castle_repo' }
end end
it "returns an error message when the given castle does not exist" do it 'returns an error message when the given castle does not exist' do
homesick.should_receive("say_status").once.with(:error, /Could not cd castle_repo, expected \/tmp\/construct_container.* exist and contain dotfiles/, :red) homesick.should_receive('say_status').once
expect { homesick.cd "castle_repo" }.to raise_error(SystemExit) .with(:error,
%r{Could not cd castle_repo, expected /tmp/construct_container.* exist and contain dotfiles},
:red)
expect { homesick.cd 'castle_repo' }.to raise_error(SystemExit)
end end
end end
describe "open" do describe 'open' do
it "opens the system default editor in the root of the given castle" do it 'opens the system default editor in the root of the given castle' do
ENV.stub(:[]).and_call_original # Make sure calls to ENV use default values for most things... # Make sure calls to ENV use default values for most things...
ENV.stub(:[]).with('EDITOR').and_return('vim') # Set a default value for 'EDITOR' just in case none is set ENV.stub(:[]).and_call_original
# Set a default value for 'EDITOR' just in case none is set
ENV.stub(:[]).with('EDITOR').and_return('vim')
given_castle 'castle_repo' given_castle 'castle_repo'
homesick.should_receive("inside").once.with(kind_of(Pathname)).and_yield homesick.should_receive('inside').once.with(kind_of(Pathname)).and_yield
homesick.should_receive("system").once.with('vim') homesick.should_receive('system').once.with('vim')
Capture.stdout { homesick.open 'castle_repo' } Capture.stdout { homesick.open 'castle_repo' }
end end
it "returns an error message when the $EDITOR environment variable is not set" do it 'returns an error message when the $EDITOR environment variable is not set' do
ENV.stub(:[]).with('EDITOR').and_return(nil) # Set the default editor to make sure it fails. # Set the default editor to make sure it fails.
homesick.should_receive("say_status").once.with(:error, "The $EDITOR environment variable must be set to use this command", :red) ENV.stub(:[]).with('EDITOR').and_return(nil)
expect { homesick.open "castle_repo" }.to raise_error(SystemExit) homesick.should_receive('say_status').once
.with(:error,
'The $EDITOR environment variable must be set to use this command',
:red)
expect { homesick.open 'castle_repo' }.to raise_error(SystemExit)
end end
it "returns an error message when the given castle does not exist" do it 'returns an error message when the given castle does not exist' do
ENV.stub(:[]).with('EDITOR').and_return('vim') # Set a default just in case none is set # Set a default just in case none is set
homesick.should_receive("say_status").once.with(:error, /Could not open castle_repo, expected \/tmp\/construct_container.* exist and contain dotfiles/, :red) ENV.stub(:[]).with('EDITOR').and_return('vim')
expect { homesick.open "castle_repo" }.to raise_error(SystemExit) homesick.should_receive('say_status').once
.with(:error,
%r{Could not open castle_repo, expected /tmp/construct_container.* exist and contain dotfiles},
:red)
expect { homesick.open 'castle_repo' }.to raise_error(SystemExit)
end end
end end