diff --git a/lib/homesick.rb b/lib/homesick.rb index 1e32c91..8d84601 100644 --- a/lib/homesick.rb +++ b/lib/homesick.rb @@ -7,7 +7,7 @@ require 'homesick/cli' # Homesick's top-level module module Homesick - GITHUB_NAME_REPO_PATTERN = /\A([A-Za-z0-9_-]+\/[A-Za-z0-9_-]+)\Z/ + GITHUB_NAME_REPO_PATTERN = %r{\A([A-Za-z0-9_-]+/[A-Za-z0-9_-]+)\Z} SUBDIR_FILENAME = '.homesick_subdir' DEFAULT_CASTLE_NAME = 'dotfiles' diff --git a/lib/homesick/actions/file_actions.rb b/lib/homesick/actions/file_actions.rb index ec1b851..27e77f7 100644 --- a/lib/homesick/actions/file_actions.rb +++ b/lib/homesick/actions/file_actions.rb @@ -3,16 +3,14 @@ module Homesick module Actions # File-related helper methods for Homesick module FileActions - def mv(source, destination, config = {}) + def mv(source, destination) source = Pathname.new(source) destination = Pathname.new(destination + source.basename) - - if destination.exist? + case + when destination.exist? && (options[:force] || shell.file_collision(destination) { source }) say_status :conflict, "#{destination} exists", :red - - FileUtils.mv source, destination if (options[:force] || shell.file_collision(destination) { source }) && !options[:pretend] + FileUtils.mv source, destination unless options[:pretend] else - # this needs some sort of message here. FileUtils.mv source, destination unless options[:pretend] end end @@ -43,7 +41,7 @@ module Homesick FileUtils.rm_r dir end - def ln_s(source, destination, config = {}) + def ln_s(source, destination) source = Pathname.new(source) destination = Pathname.new(destination) FileUtils.mkdir_p destination.dirname diff --git a/lib/homesick/actions/git_actions.rb b/lib/homesick/actions/git_actions.rb index 803c67f..a5b8cc4 100644 --- a/lib/homesick/actions/git_actions.rb +++ b/lib/homesick/actions/git_actions.rb @@ -14,7 +14,7 @@ module Homesick def git_version_correct? info = `git --version`.scan(/(\d+)\.(\d+)\.(\d+)/).flatten.map(&:to_i) return false unless info.count == 3 - current_version = Hash[ [:major, :minor, :patch].zip(info) ] + current_version = Hash[[:major, :minor, :patch].zip(info)] return true if current_version.eql?(MIN_VERSION) return true if current_version[:major] > MIN_VERSION[:major] return true if current_version[:major] == MIN_VERSION[:major] && current_version[:minor] > MIN_VERSION[:minor] @@ -27,7 +27,7 @@ module Homesick config ||= {} destination = config[:destination] || File.basename(repo, '.git') - destination = Pathname.new(destination) unless destination.kind_of?(Pathname) + destination = Pathname.new(destination) unless destination.is_a?(Pathname) FileUtils.mkdir_p destination.dirname if destination.directory? @@ -65,22 +65,22 @@ module Homesick end end - def git_submodule_init(config = {}) + def git_submodule_init say_status 'git submodule', 'init', :green system 'git submodule --quiet init' end - def git_submodule_update(config = {}) + def git_submodule_update say_status 'git submodule', 'update', :green system 'git submodule --quiet update --init --recursive >/dev/null 2>&1' end - def git_pull(config = {}) + def git_pull say_status 'git pull', '', :green system 'git pull --quiet' end - def git_push(config = {}) + def git_push say_status 'git push', '', :green system 'git push' end @@ -88,23 +88,23 @@ module Homesick def git_commit_all(config = {}) say_status 'git commit all', '', :green if config[:message] - system %Q(git commit -a -m "#{config[:message]}") + system %(git commit -a -m "#{config[:message]}") else system 'git commit -v -a' end end - def git_add(file, config = {}) + def git_add(file) say_status 'git add file', '', :green system "git add '#{file}'" end - def git_status(config = {}) + def git_status say_status 'git status', '', :green system 'git status' end - def git_diff(config = {}) + def git_diff say_status 'git diff', '', :green system 'git diff' end diff --git a/lib/homesick/cli.rb b/lib/homesick/cli.rb index 91c3265..f86c443 100644 --- a/lib/homesick/cli.rb +++ b/lib/homesick/cli.rb @@ -25,17 +25,12 @@ module Homesick exit(1) end # Hack in support for diffing symlinks - self.shell = Thor::Shell::Color.new - class << shell - def show_diff(destination, content) - destination = Pathname.new(destination) - if destination.symlink? - say "- #{destination.readlink}", :red, true - say "+ #{content.expand_path}", :green, true - else - super - end - end + shell_metaclass = class << shell; self; end + shell_metaclass.send(:define_method, :show_diff) do |destination, content| + destination = Pathname.new(destination) + return super unless destination.symlink? + say "- #{destination.readlink}", :red, true + say "+ #{content.expand_path}", :green, true end end @@ -55,7 +50,7 @@ module Homesick 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 + destination = Pathname.new(Regexp.last_match[1].gsub(/\.git$/, '')).basename git_clone uri, destination: destination else fail "Unknown URI format: #{uri}" @@ -73,18 +68,12 @@ module Homesick inside repos_dir do destination = Pathname.new(name) homesickrc = destination.join('.homesickrc').expand_path - if homesickrc.exist? - proceed = options[:force] || shell.yes?("#{name} has a .homesickrc. Proceed with evaling it? (This could be destructive)") - if proceed - say_status 'eval', homesickrc - inside destination do - eval homesickrc.read, binding, homesickrc.expand_path.to_s - end - else - say_status 'eval skip', - "not evaling #{homesickrc}, #{destination} may need manual configuration", - :blue - end + 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 @@ -252,11 +241,10 @@ module Homesick desc 'destroy CASTLE', 'Delete all symlinks and remove the cloned repository' def destroy(name) check_castle_existance name, 'destroy' + return unless 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) - rm_rf repos_dir.join(name) - end + unlink(name) + rm_rf repos_dir.join(name) end desc 'cd CASTLE', 'Open a new shell in the root of the given castle' diff --git a/lib/homesick/utils.rb b/lib/homesick/utils.rb index a69ab6d..1afe266 100644 --- a/lib/homesick/utils.rb +++ b/lib/homesick/utils.rb @@ -35,12 +35,11 @@ module Homesick end def check_castle_existance(name, action) - unless castle_dir(name).exist? - say_status :error, - "Could not #{action} #{name}, expected #{castle_dir(name)} exist and contain dotfiles", - :red - exit(1) - end + return if castle_dir(name).exist? + say_status :error, + "Could not #{action} #{name}, expected #{castle_dir(name)} exist and contain dotfiles", + :red + exit(1) end def all_castles @@ -53,7 +52,7 @@ module Homesick end end - def inside_each_castle(&block) + def inside_each_castle all_castles.each do |git_dir| castle = git_dir.dirname Dir.chdir castle do # so we can call git config from the right contxt @@ -130,7 +129,6 @@ module Homesick def move_dir_contents(target, dir_path) child_files = dir_path.children child_files.each do |child| - target_path = target.join(child.basename) if target_path.exist? if more_recent?(child, target_path) && target.file? @@ -193,7 +191,7 @@ module Homesick end def unsymlink_each(castle, basedir, subdirs) - each_file(castle, basedir, subdirs) do |absolute_path, home_path| + each_file(castle, basedir, subdirs) do |_absolute_path, home_path| rm_link home_path end end diff --git a/spec/homesick_cli_spec.rb b/spec/homesick_cli_spec.rb index a9ba3b8..db1c1f6 100644 --- a/spec/homesick_cli_spec.rb +++ b/spec/homesick_cli_spec.rb @@ -26,10 +26,10 @@ describe Homesick::CLI do context 'when a git version that doesn\'t meet the minimum required is installed' do before do - expect_any_instance_of(Homesick::Actions::GitActions).to receive(:`).and_return("git version 1.7.6") + expect_any_instance_of(Homesick::Actions::GitActions).to receive(:`).and_return('git version 1.7.6') end it 'should raise an exception' do - output = Capture.stdout{ expect{Homesick::CLI.new}.to raise_error SystemExit } + output = Capture.stdout { expect { Homesick::CLI.new }.to raise_error SystemExit } expect(output.chomp).to include(Homesick::Actions::GitActions::STRING) end end @@ -39,20 +39,19 @@ describe Homesick::CLI do expect_any_instance_of(Homesick::Actions::GitActions).to receive(:`).at_least(:once).and_return("git version #{Homesick::Actions::GitActions::STRING}") end it 'should not raise an exception' do - output = Capture.stdout{ expect{Homesick::CLI.new}.not_to raise_error } + output = Capture.stdout { expect { Homesick::CLI.new }.not_to raise_error } expect(output.chomp).not_to include(Homesick::Actions::GitActions::STRING) end end context 'when a git version that is greater than the minimum required is installed' do before do - expect_any_instance_of(Homesick::Actions::GitActions).to receive(:`).at_least(:once).and_return("git version 3.9.8") + expect_any_instance_of(Homesick::Actions::GitActions).to receive(:`).at_least(:once).and_return('git version 3.9.8') end it 'should not raise an exception' do - output = Capture.stdout{ expect{Homesick::CLI.new}.not_to raise_error } + output = Capture.stdout { expect { Homesick::CLI.new }.not_to raise_error } expect(output.chomp).not_to include(Homesick::Actions::GitActions::STRING) end - end end @@ -112,32 +111,28 @@ describe Homesick::CLI do it 'clones git repo like git://host/path/to.git' do expect(homesick).to receive(:git_clone) - .with('git://github.com/technicalpickles/pickled-vim.git', - destination: Pathname.new('pickled-vim')) + .with('git://github.com/technicalpickles/pickled-vim.git', destination: Pathname.new('pickled-vim')) homesick.clone 'git://github.com/technicalpickles/pickled-vim.git' end it 'clones git repo like git@host:path/to.git' do expect(homesick).to receive(:git_clone) - .with('git@github.com:technicalpickles/pickled-vim.git', - destination: Pathname.new('pickled-vim')) + .with('git@github.com:technicalpickles/pickled-vim.git', destination: Pathname.new('pickled-vim')) homesick.clone 'git@github.com:technicalpickles/pickled-vim.git' end it 'clones git repo like http://host/path/to.git' do expect(homesick).to receive(:git_clone) - .with('http://github.com/technicalpickles/pickled-vim.git', - destination: Pathname.new('pickled-vim')) + .with('http://github.com/technicalpickles/pickled-vim.git', destination: Pathname.new('pickled-vim')) homesick.clone 'http://github.com/technicalpickles/pickled-vim.git' end it 'clones git repo like http://host/path/to' do expect(homesick).to receive(:git_clone) - .with('http://github.com/technicalpickles/pickled-vim', - destination: Pathname.new('pickled-vim')) + .with('http://github.com/technicalpickles/pickled-vim', destination: Pathname.new('pickled-vim')) homesick.clone 'http://github.com/technicalpickles/pickled-vim' end @@ -156,8 +151,7 @@ describe Homesick::CLI do it 'clones a github repo' do expect(homesick).to receive(:git_clone) - .with('https://github.com/wfarr/dotfiles.git', - destination: Pathname.new('dotfiles')) + .with('https://github.com/wfarr/dotfiles.git', destination: Pathname.new('dotfiles')) homesick.clone 'wfarr/dotfiles' end @@ -225,7 +219,7 @@ describe Homesick::CLI do end end - describe 'link' do + describe 'link_castle' do let(:castle) { given_castle('glencairn') } it 'links dotfiles from a castle to the home folder' do @@ -313,11 +307,9 @@ describe Homesick::CLI do home_config_dir = home.join('.config') home_someapp_dir = home_config_dir.join('someapp') expect(home_config_dir.symlink?).to eq(false) - expect(home_config_dir.join('.some_dotfile').readlink) - .to eq(config_dotfile) + expect(home_config_dir.join('.some_dotfile').readlink).to eq(config_dotfile) expect(home_someapp_dir.symlink?).to eq(false) - expect(home_someapp_dir.join('.some_appfile').readlink) - .to eq(someapp_dotfile) + expect(home_someapp_dir.join('.some_appfile').readlink).to eq(someapp_dotfile) end end @@ -426,13 +418,9 @@ describe Homesick::CLI do given_castle('wtf/zomg') expect(homesick).to receive(:say_status) - .with('zomg', - 'git://github.com/technicalpickles/zomg.git', - :cyan) + .with('zomg', 'git://github.com/technicalpickles/zomg.git', :cyan) expect(homesick).to receive(:say_status) - .with('wtf/zomg', - 'git://github.com/technicalpickles/zomg.git', - :cyan) + .with('wtf/zomg', 'git://github.com/technicalpickles/zomg.git', :cyan) homesick.list end @@ -442,7 +430,7 @@ describe Homesick::CLI do it 'says "nothing to commit" when there are no changes' do given_castle('castle_repo') text = Capture.stdout { homesick.status('castle_repo') } - expect(text).to match(/nothing to commit \(create\/copy files and use "git add" to track\)$/) + expect(text).to match(%r{nothing to commit \(create/copy files and use "git add" to track\)$}) end it 'says "Changes to be committed" when there are changes' do @@ -450,9 +438,7 @@ describe Homesick::CLI do some_rc_file = home.file '.some_rc_file' homesick.track(some_rc_file.to_s, 'castle_repo') text = Capture.stdout { homesick.status('castle_repo') } - expect(text).to match( - /Changes to be committed:.*new file:\s*home\/.some_rc_file/m - ) + expect(text).to match(%r{Changes to be committed:.*new file:\s*home\/.some_rc_file}m) end end @@ -524,7 +510,6 @@ describe Homesick::CLI do end end end - end describe 'push' do @@ -536,9 +521,7 @@ describe Homesick::CLI do it 'prints an error message when trying to push a non-existant castle' do expect(homesick).to receive('say_status').once - .with(:error, - /Could not push castle_repo, expected .* exist and contain dotfiles/, - :red) + .with(:error, /Could not push castle_repo, expected .* exist and contain dotfiles/, :red) expect { homesick.push 'castle_repo' }.to raise_error(SystemExit) end end @@ -622,7 +605,6 @@ describe Homesick::CLI do # 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 - it 'adds the nested files parent to the subdir_file' do castle = given_castle('castle_repo') @@ -697,9 +679,7 @@ describe Homesick::CLI do it 'returns an error message when the given castle does not exist' do expect(homesick).to receive('say_status').once - .with(:error, - /Could not cd castle_repo, expected .* exist and contain dotfiles/, - :red) + .with(:error, /Could not cd castle_repo, expected .* exist and contain dotfiles/, :red) expect { homesick.cd 'castle_repo' }.to raise_error(SystemExit) end end @@ -720,9 +700,7 @@ describe Homesick::CLI do # Set the default editor to make sure it fails. allow(ENV).to receive(:[]).with('EDITOR').and_return(nil) expect(homesick).to receive('say_status').once - .with(:error, - 'The $EDITOR environment variable must be set to use this command', - :red) + .with(:error, 'The $EDITOR environment variable must be set to use this command', :red) expect { homesick.open 'castle_repo' }.to raise_error(SystemExit) end @@ -730,9 +708,7 @@ describe Homesick::CLI do # Set a default just in case none is set allow(ENV).to receive(:[]).with('EDITOR').and_return('vim') allow(homesick).to receive('say_status').once - .with(:error, - /Could not open castle_repo, expected .* exist and contain dotfiles/, - :red) + .with(:error, /Could not open castle_repo, expected .* exist and contain dotfiles/, :red) expect { homesick.open 'castle_repo' }.to raise_error(SystemExit) end end @@ -751,9 +727,7 @@ describe Homesick::CLI do it 'executes a single command with no arguments inside a given castle' do allow(homesick).to receive('inside').once.with(kind_of(Pathname)).and_yield allow(homesick).to receive('say_status').once - .with(be_a(String), - be_a(String), - :green) + .with(be_a(String), be_a(String), :green) allow(homesick).to receive('system').once.with('ls') Capture.stdout { homesick.exec 'castle_repo', 'ls' } end @@ -761,18 +735,14 @@ describe Homesick::CLI do it 'executes a single command with arguments inside a given castle' do allow(homesick).to receive('inside').once.with(kind_of(Pathname)).and_yield allow(homesick).to receive('say_status').once - .with(be_a(String), - be_a(String), - :green) + .with(be_a(String), be_a(String), :green) allow(homesick).to receive('system').once.with('ls -la') Capture.stdout { homesick.exec 'castle_repo', 'ls', '-la' } end it 'raises an error when the method is called without a command' do allow(homesick).to receive('say_status').once - .with(:error, - be_a(String), - :red) + .with(:error, be_a(String), :red) allow(homesick).to receive('exit').once.with(1) Capture.stdout { homesick.exec 'castle_repo' } end @@ -780,9 +750,7 @@ describe Homesick::CLI do context 'pretend' do it 'does not execute a command when the pretend option is passed' do allow(homesick).to receive('say_status').once - .with(be_a(String), - match(/.*Would execute.*/), - :green) + .with(be_a(String), match(/.*Would execute.*/), :green) expect(homesick).to receive('system').never Capture.stdout { homesick.invoke 'exec', %w(castle_repo ls -la), pretend: true } end @@ -792,7 +760,7 @@ describe Homesick::CLI do it 'does not print status information when quiet is passed' do expect(homesick).to receive('say_status').never allow(homesick).to receive('system').once - .with('ls -la') + .with('ls -la') Capture.stdout { homesick.invoke 'exec', %w(castle_repo ls -la), quiet: true } end end @@ -807,9 +775,7 @@ describe Homesick::CLI do it 'executes a command without arguments inside the root of each cloned castle' do allow(homesick).to receive('inside_each_castle').exactly(:twice).and_yield('castle_repo').and_yield('another_castle_repo') allow(homesick).to receive('say_status').at_least(:once) - .with(be_a(String), - be_a(String), - :green) + .with(be_a(String), be_a(String), :green) allow(homesick).to receive('system').at_least(:once).with('ls') Capture.stdout { homesick.exec_all 'ls' } end @@ -817,18 +783,14 @@ describe Homesick::CLI do it 'executes a command with arguments inside the root of each cloned castle' do allow(homesick).to receive('inside_each_castle').exactly(:twice).and_yield('castle_repo').and_yield('another_castle_repo') allow(homesick).to receive('say_status').at_least(:once) - .with(be_a(String), - be_a(String), - :green) + .with(be_a(String), be_a(String), :green) allow(homesick).to receive('system').at_least(:once).with('ls -la') Capture.stdout { homesick.exec_all 'ls', '-la' } end it 'raises an error when the method is called without a command' do allow(homesick).to receive('say_status').once - .with(:error, - be_a(String), - :red) + .with(:error, be_a(String), :red) allow(homesick).to receive('exit').once.with(1) Capture.stdout { homesick.exec_all } end @@ -836,9 +798,7 @@ describe Homesick::CLI do context 'pretend' do it 'does not execute a command when the pretend option is passed' do allow(homesick).to receive('say_status').at_least(:once) - .with(be_a(String), - match(/.*Would execute.*/), - :green) + .with(be_a(String), match(/.*Would execute.*/), :green) expect(homesick).to receive('system').never Capture.stdout { homesick.invoke 'exec_all', %w(ls -la), pretend: true } end @@ -848,7 +808,7 @@ describe Homesick::CLI do it 'does not print status information when quiet is passed' do expect(homesick).to receive('say_status').never allow(homesick).to receive('system').at_least(:once) - .with('ls -la') + .with('ls -la') Capture.stdout { homesick.invoke 'exec_all', %w(ls -la), quiet: true } end end