Compare commits
23 Commits
v1.1.6
...
ee4388b0f4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee4388b0f4 | ||
|
|
a44a514007 | ||
|
|
9431cb78af | ||
|
|
46c52769a6 | ||
|
|
fdb57cd846 | ||
|
|
ff387280d5 | ||
|
|
f09c62d922 | ||
|
|
dd7d52a25d | ||
|
|
f1630ece79 | ||
|
|
11ee8cdc0d | ||
|
|
ceb08cbe22 | ||
|
|
057e1cfc59 | ||
|
|
89f3000d8b | ||
|
|
36e3cb6bbf | ||
|
|
9ebae75e7d | ||
|
|
35e1909790 | ||
|
|
3b633ed326 | ||
|
|
fdf2da84dd | ||
|
|
e561566b46 | ||
|
|
dcef34c17d | ||
|
|
72d11c4a47 | ||
|
|
c2457bae9f | ||
|
|
001bd32bb3 |
@@ -1,5 +1,6 @@
|
|||||||
language: ruby
|
language: ruby
|
||||||
rvm:
|
rvm:
|
||||||
|
- 2.5.0
|
||||||
- 2.4.0
|
- 2.4.0
|
||||||
- 2.3.3
|
- 2.3.3
|
||||||
- 2.2.6
|
- 2.2.6
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#1.1.6
|
# 1.1.6
|
||||||
* Makesure the FileUtils is imported correctly to avoid a potential error
|
* Makesure the FileUtils is imported correctly to avoid a potential error
|
||||||
* Fixes an issue where comparing a diff would not use the content of the new file
|
* Fixes an issue where comparing a diff would not use the content of the new file
|
||||||
* Small documentation fixes
|
* Small documentation fixes
|
||||||
|
|||||||
2
Gemfile
2
Gemfile
@@ -31,6 +31,6 @@ group :development do
|
|||||||
|
|
||||||
install_if -> { this_ruby < ruby_230 } do
|
install_if -> { this_ruby < ruby_230 } do
|
||||||
gem 'listen', '< 3'
|
gem 'listen', '< 3'
|
||||||
gem 'rack', '< 2'
|
gem 'rack', '~> 2.0.6'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,14 +1,29 @@
|
|||||||
# -*- encoding : utf-8 -*-
|
|
||||||
require 'homesick/actions/file_actions'
|
require 'homesick/actions/file_actions'
|
||||||
require 'homesick/actions/git_actions'
|
require 'homesick/actions/git_actions'
|
||||||
require 'homesick/version'
|
require 'homesick/version'
|
||||||
require 'homesick/utils'
|
require 'homesick/utils'
|
||||||
require 'homesick/cli'
|
require 'homesick/cli'
|
||||||
|
require 'fileutils'
|
||||||
|
|
||||||
# Homesick's top-level module
|
# Homesick's top-level module
|
||||||
module Homesick
|
module Homesick
|
||||||
GITHUB_NAME_REPO_PATTERN = %r{\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}.freeze
|
||||||
SUBDIR_FILENAME = '.homesick_subdir'
|
SUBDIR_FILENAME = '.homesick_subdir'.freeze
|
||||||
|
|
||||||
DEFAULT_CASTLE_NAME = 'dotfiles'
|
DEFAULT_CASTLE_NAME = 'dotfiles'.freeze
|
||||||
|
QUIETABLE = [:say_status].freeze
|
||||||
|
|
||||||
|
PRETENDABLE = [:system].freeze
|
||||||
|
|
||||||
|
QUIETABLE.each do |method_name|
|
||||||
|
define_method(method_name) do |*args|
|
||||||
|
super(*args) unless options[:quiet]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
PRETENDABLE.each do |method_name|
|
||||||
|
define_method(method_name) do |*args|
|
||||||
|
super(*args) unless options[:pretend]
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
# -*- encoding : utf-8 -*-
|
|
||||||
module Homesick
|
module Homesick
|
||||||
module Actions
|
module Actions
|
||||||
# File-related helper methods for Homesick
|
# File-related helper methods for Homesick
|
||||||
module FileActions
|
module FileActions
|
||||||
|
protected
|
||||||
|
|
||||||
def mv(source, destination)
|
def mv(source, destination)
|
||||||
source = Pathname.new(source)
|
source = Pathname.new(source)
|
||||||
destination = Pathname.new(destination + source.basename)
|
destination = Pathname.new(destination + source.basename)
|
||||||
case
|
say_status :conflict, "#{destination} exists", :red if destination.exist? && (options[:force] || shell.file_collision(destination) { source })
|
||||||
when destination.exist? && (options[:force] || shell.file_collision(destination) { source })
|
FileUtils.mv source, destination unless options[:pretend]
|
||||||
say_status :conflict, "#{destination} exists", :red
|
|
||||||
FileUtils.mv source, destination unless options[:pretend]
|
|
||||||
else
|
|
||||||
FileUtils.mv source, destination unless options[:pretend]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def rm_rf(dir)
|
def rm_rf(dir)
|
||||||
@@ -24,7 +20,7 @@ module Homesick
|
|||||||
target = Pathname.new(target)
|
target = Pathname.new(target)
|
||||||
|
|
||||||
if target.symlink?
|
if target.symlink?
|
||||||
say_status :unlink, "#{target.expand_path}", :green
|
say_status :unlink, target.expand_path.to_s, :green
|
||||||
FileUtils.rm_rf target
|
FileUtils.rm_rf target
|
||||||
else
|
else
|
||||||
say_status :conflict, "#{target} is not a symlink", :red
|
say_status :conflict, "#{target} is not a symlink", :red
|
||||||
@@ -42,45 +38,40 @@ module Homesick
|
|||||||
end
|
end
|
||||||
|
|
||||||
def ln_s(source, destination)
|
def ln_s(source, destination)
|
||||||
source = Pathname.new(source).realpath
|
source = Pathname.new(source).realpath
|
||||||
destination = Pathname.new(destination)
|
destination = Pathname.new(destination)
|
||||||
FileUtils.mkdir_p destination.dirname
|
FileUtils.mkdir_p destination.dirname
|
||||||
|
|
||||||
action = if destination.symlink? && destination.readlink == source
|
action = :success
|
||||||
:identical
|
action = :identical if destination.symlink? && destination.readlink == source
|
||||||
elsif destination.symlink?
|
action = :symlink_conflict if destination.symlink?
|
||||||
:symlink_conflict
|
action = :conflict if destination.exist?
|
||||||
elsif destination.exist?
|
|
||||||
:conflict
|
|
||||||
else
|
|
||||||
:success
|
|
||||||
end
|
|
||||||
|
|
||||||
handle_symlink_action action, source, destination
|
handle_symlink_action action, source, destination
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_symlink_action(action, source, destination)
|
def handle_symlink_action(action, source, destination)
|
||||||
case action
|
if action == :identical
|
||||||
when :identical
|
|
||||||
say_status :identical, destination.expand_path, :blue
|
say_status :identical, destination.expand_path, :blue
|
||||||
when :symlink_conflict, :conflict
|
return
|
||||||
if action == :conflict
|
end
|
||||||
say_status :conflict, "#{destination} exists", :red
|
message = generate_symlink_message action, source, destination
|
||||||
else
|
if %i[symlink_conflict conflict].include?(action)
|
||||||
say_status :conflict,
|
say_status :conflict, message, :red
|
||||||
"#{destination} exists and points to #{destination.readlink}",
|
|
||||||
:red
|
|
||||||
end
|
|
||||||
if collision_accepted?(destination, source)
|
if collision_accepted?(destination, source)
|
||||||
FileUtils.rm_r destination, force: true unless options[:pretend]
|
FileUtils.rm_r destination, force: true unless options[:pretend]
|
||||||
FileUtils.ln_s source, destination, force: true unless options[:pretend]
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
say_status :symlink,
|
say_status :symlink, message, :green
|
||||||
"#{source.expand_path} to #{destination.expand_path}",
|
|
||||||
:green
|
|
||||||
FileUtils.ln_s source, destination unless options[:pretend]
|
|
||||||
end
|
end
|
||||||
|
FileUtils.ln_s source, destination, force: true unless options[:pretend]
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_symlink_message(action, source, destination)
|
||||||
|
message = "#{source.expand_path} to #{destination.expand_path}"
|
||||||
|
message = "#{destination} exists and points to #{destination.readlink}" if action == :symlink_conflict
|
||||||
|
message = "#{destination} exists" if action == :conflict
|
||||||
|
message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- encoding : utf-8 -*-
|
|
||||||
module Homesick
|
module Homesick
|
||||||
module Actions
|
module Actions
|
||||||
# Git-related helper methods for Homesick
|
# Git-related helper methods for Homesick
|
||||||
@@ -8,18 +7,20 @@ module Homesick
|
|||||||
major: 1,
|
major: 1,
|
||||||
minor: 8,
|
minor: 8,
|
||||||
patch: 0
|
patch: 0
|
||||||
}
|
}.freeze
|
||||||
STRING = MIN_VERSION.values.join('.')
|
STRING = MIN_VERSION.values.join('.')
|
||||||
|
|
||||||
def git_version_correct?
|
def git_version_correct?
|
||||||
info = `git --version`.scan(/(\d+)\.(\d+)\.(\d+)/).flatten.map(&:to_i)
|
info = `git --version`.scan(/(\d+)\.(\d+)\.(\d+)/).flatten.map(&:to_i)
|
||||||
return false unless info.count == 3
|
return false unless info.count == 3
|
||||||
current_version = Hash[[:major, :minor, :patch].zip(info)]
|
|
||||||
return true if current_version.eql?(MIN_VERSION)
|
current_version = Hash[%i[major minor patch].zip(info)]
|
||||||
return true if current_version[:major] > MIN_VERSION[:major]
|
major_equals = current_version.eql?(MIN_VERSION)
|
||||||
return true if current_version[:major] == MIN_VERSION[:major] && current_version[:minor] > MIN_VERSION[:minor]
|
major_greater = current_version[:major] > MIN_VERSION[:major]
|
||||||
return true if current_version[:major] == MIN_VERSION[:major] && current_version[:minor] == MIN_VERSION[:minor] && current_version[:patch] >= MIN_VERSION[:patch]
|
minor_greater = current_version[:major] == MIN_VERSION[:major] && current_version[:minor] > MIN_VERSION[:minor]
|
||||||
false
|
patch_greater = current_version[:major] == MIN_VERSION[:major] && current_version[:minor] == MIN_VERSION[:minor] && current_version[:patch] >= MIN_VERSION[:patch]
|
||||||
|
|
||||||
|
major_equals || major_greater || minor_greater || patch_greater
|
||||||
end
|
end
|
||||||
|
|
||||||
# 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
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- encoding : utf-8 -*-
|
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'thor'
|
require 'thor'
|
||||||
|
|
||||||
@@ -25,27 +24,17 @@ module Homesick
|
|||||||
say_status :error, "Git version >= #{Homesick::Actions::GitActions::STRING} must be installed to use Homesick", :red
|
say_status :error, "Git version >= #{Homesick::Actions::GitActions::STRING} must be installed to use Homesick", :red
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
# Hack in support for diffing symlinks
|
configure_symlinks_diff
|
||||||
# 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
|
end
|
||||||
|
|
||||||
desc 'clone URI CASTLE_NAME', 'Clone +uri+ as a castle with name CASTLE_NAME for homesick'
|
desc 'clone URI CASTLE_NAME', 'Clone +uri+ as a castle with name CASTLE_NAME for homesick'
|
||||||
def clone(uri, destination=nil)
|
def clone(uri, destination = nil)
|
||||||
destination = Pathname.new(destination) unless destination.nil?
|
destination = Pathname.new(destination) unless destination.nil?
|
||||||
|
|
||||||
inside repos_dir do
|
inside repos_dir do
|
||||||
if File.exist?(uri)
|
if File.exist?(uri)
|
||||||
uri = Pathname.new(uri).expand_path
|
uri = Pathname.new(uri).expand_path
|
||||||
fail "Castle already cloned to #{uri}" if uri.to_s.start_with?(repos_dir.to_s)
|
raise "Castle already cloned to #{uri}" if uri.to_s.start_with?(repos_dir.to_s)
|
||||||
|
|
||||||
destination = uri.basename if destination.nil?
|
destination = uri.basename if destination.nil?
|
||||||
|
|
||||||
@@ -58,7 +47,7 @@ module Homesick
|
|||||||
destination = Pathname.new(Regexp.last_match[1].gsub(/\.git$/, '')).basename if destination.nil?
|
destination = Pathname.new(Regexp.last_match[1].gsub(/\.git$/, '')).basename if destination.nil?
|
||||||
git_clone uri, destination: destination
|
git_clone uri, destination: destination
|
||||||
else
|
else
|
||||||
fail "Unknown URI format: #{uri}"
|
raise "Unknown URI format: #{uri}"
|
||||||
end
|
end
|
||||||
|
|
||||||
setup_castle(destination)
|
setup_castle(destination)
|
||||||
@@ -75,8 +64,10 @@ module Homesick
|
|||||||
destination = Pathname.new(name)
|
destination = Pathname.new(name)
|
||||||
homesickrc = destination.join('.homesickrc').expand_path
|
homesickrc = destination.join('.homesickrc').expand_path
|
||||||
return unless homesickrc.exist?
|
return unless homesickrc.exist?
|
||||||
|
|
||||||
proceed = options[:force] || shell.yes?("#{name} has a .homesickrc. Proceed with evaling it? (This could be destructive)")
|
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
|
return say_status 'eval skip', "not evaling #{homesickrc}, #{destination} may need manual configuration", :blue unless proceed
|
||||||
|
|
||||||
say_status 'eval', homesickrc
|
say_status 'eval', homesickrc
|
||||||
inside destination do
|
inside destination do
|
||||||
eval homesickrc.read, binding, homesickrc.expand_path.to_s
|
eval homesickrc.read, binding, homesickrc.expand_path.to_s
|
||||||
@@ -136,11 +127,12 @@ module Homesick
|
|||||||
def link(name = DEFAULT_CASTLE_NAME)
|
def link(name = DEFAULT_CASTLE_NAME)
|
||||||
check_castle_existance(name, 'symlink')
|
check_castle_existance(name, 'symlink')
|
||||||
|
|
||||||
inside castle_dir(name) do
|
castle_path = castle_dir(name)
|
||||||
|
inside castle_path do
|
||||||
subdirs = subdirs(name)
|
subdirs = subdirs(name)
|
||||||
|
|
||||||
# link files
|
# link files
|
||||||
symlink_each(name, castle_dir(name), subdirs)
|
symlink_each(name, castle_path, subdirs)
|
||||||
|
|
||||||
# link files in subdirs
|
# link files in subdirs
|
||||||
subdirs.each do |subdir|
|
subdirs.each do |subdir|
|
||||||
|
|||||||
@@ -1,25 +1,8 @@
|
|||||||
# -*- encoding : utf-8 -*-
|
|
||||||
require 'pathname'
|
require 'pathname'
|
||||||
|
|
||||||
module Homesick
|
module Homesick
|
||||||
# Various utility methods that are used by Homesick
|
# Various utility methods that are used by Homesick
|
||||||
module Utils
|
module Utils
|
||||||
QUIETABLE = [:say_status]
|
|
||||||
|
|
||||||
PRETENDABLE = [:system]
|
|
||||||
|
|
||||||
QUIETABLE.each do |method_name|
|
|
||||||
define_method(method_name) do |*args|
|
|
||||||
super(*args) unless options[:quiet]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
PRETENDABLE.each do |method_name|
|
|
||||||
define_method(method_name) do |*args|
|
|
||||||
super(*args) unless options[:pretend]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def home_dir
|
def home_dir
|
||||||
@@ -36,6 +19,7 @@ module Homesick
|
|||||||
|
|
||||||
def check_castle_existance(name, action)
|
def check_castle_existance(name, action)
|
||||||
return if castle_dir(name).exist?
|
return if castle_dir(name).exist?
|
||||||
|
|
||||||
say_status :error,
|
say_status :error,
|
||||||
"Could not #{action} #{name}, expected #{castle_dir(name)} to exist and contain dotfiles",
|
"Could not #{action} #{name}, expected #{castle_dir(name)} to exist and contain dotfiles",
|
||||||
:red
|
:red
|
||||||
@@ -149,47 +133,11 @@ module Homesick
|
|||||||
end
|
end
|
||||||
|
|
||||||
def collision_accepted?(destination, source)
|
def collision_accepted?(destination, source)
|
||||||
fail "Arguments must be instances of Pathname, #{destination.class.name} and #{source.class.name} given" unless destination.instance_of?(Pathname) && source.instance_of?(Pathname)
|
raise "Arguments must be instances of Pathname, #{destination.class.name} and #{source.class.name} given" unless destination.instance_of?(Pathname) && source.instance_of?(Pathname)
|
||||||
|
|
||||||
options[:force] || shell.file_collision(destination) { source }
|
options[:force] || shell.file_collision(destination) { source }
|
||||||
end
|
end
|
||||||
|
|
||||||
def each_file(castle, basedir, subdirs)
|
|
||||||
absolute_basedir = Pathname.new(basedir).expand_path
|
|
||||||
inside basedir do
|
|
||||||
files = Pathname.glob('{.*,*}').reject do |a|
|
|
||||||
['.', '..'].include?(a.to_s)
|
|
||||||
end
|
|
||||||
files.each do |path|
|
|
||||||
absolute_path = path.expand_path
|
|
||||||
castle_home = castle_dir(castle)
|
|
||||||
|
|
||||||
# make ignore dirs
|
|
||||||
ignore_dirs = []
|
|
||||||
subdirs.each do |subdir|
|
|
||||||
# ignore all parent of each line in subdir file
|
|
||||||
Pathname.new(subdir).ascend do |p|
|
|
||||||
ignore_dirs.push(p)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# ignore dirs written in subdir file
|
|
||||||
matched = false
|
|
||||||
ignore_dirs.uniq.each do |ignore_dir|
|
|
||||||
if absolute_path == castle_home.join(ignore_dir)
|
|
||||||
matched = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
next if matched
|
|
||||||
|
|
||||||
relative_dir = absolute_basedir.relative_path_from(castle_home)
|
|
||||||
home_path = home_dir.join(relative_dir).join(path)
|
|
||||||
|
|
||||||
yield(absolute_path, home_path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def unsymlink_each(castle, basedir, subdirs)
|
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
|
rm_link home_path
|
||||||
@@ -212,5 +160,56 @@ module Homesick
|
|||||||
|
|
||||||
rc(path)
|
rc(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def each_file(castle, basedir, subdirs)
|
||||||
|
absolute_basedir = Pathname.new(basedir).expand_path
|
||||||
|
castle_home = castle_dir(castle)
|
||||||
|
inside basedir do |destination_root|
|
||||||
|
FileUtils.cd(destination_root) unless destination_root == FileUtils.pwd
|
||||||
|
files = Pathname.glob('*', File::FNM_DOTMATCH)
|
||||||
|
.reject { |a| ['.', '..'].include?(a.to_s) }
|
||||||
|
.reject { |path| matches_ignored_dir? castle_home, path.expand_path, subdirs }
|
||||||
|
files.each do |path|
|
||||||
|
absolute_path = path.expand_path
|
||||||
|
|
||||||
|
relative_dir = absolute_basedir.relative_path_from(castle_home)
|
||||||
|
home_path = home_dir.join(relative_dir).join(path)
|
||||||
|
|
||||||
|
yield(absolute_path, home_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches_ignored_dir?(castle_home, absolute_path, subdirs)
|
||||||
|
# make ignore dirs
|
||||||
|
ignore_dirs = []
|
||||||
|
subdirs.each do |subdir|
|
||||||
|
# ignore all parent of each line in subdir file
|
||||||
|
Pathname.new(subdir).ascend do |p|
|
||||||
|
ignore_dirs.push(p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# ignore dirs written in subdir file
|
||||||
|
ignore_dirs.uniq.each do |ignore_dir|
|
||||||
|
return true if absolute_path == castle_home.join(ignore_dir)
|
||||||
|
end
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def configure_symlinks_diff
|
||||||
|
# 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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- encoding : utf-8 -*-
|
|
||||||
module Homesick
|
module Homesick
|
||||||
# A representation of Homesick's version number in constants, including a
|
# A representation of Homesick's version number in constants, including a
|
||||||
# String of the entire version number
|
# String of the entire version number
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- encoding : utf-8 -*-
|
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
require 'capture-output'
|
require 'capture-output'
|
||||||
require 'pathname'
|
require 'pathname'
|
||||||
@@ -158,8 +157,8 @@ describe Homesick::CLI do
|
|||||||
|
|
||||||
it 'accepts a destination', :focus do
|
it 'accepts a destination', :focus do
|
||||||
expect(homesick).to receive(:git_clone)
|
expect(homesick).to receive(:git_clone)
|
||||||
.with('https://github.com/wfarr/dotfiles.git',
|
.with('https://github.com/wfarr/dotfiles.git',
|
||||||
destination: Pathname.new('other-name'))
|
destination: Pathname.new('other-name'))
|
||||||
|
|
||||||
homesick.clone 'wfarr/dotfiles', 'other-name'
|
homesick.clone 'wfarr/dotfiles', 'other-name'
|
||||||
end
|
end
|
||||||
@@ -334,7 +333,7 @@ describe Homesick::CLI do
|
|||||||
|
|
||||||
context 'when call and some files conflict' do
|
context 'when call and some files conflict' do
|
||||||
it 'shows differences for conflicting text files' do
|
it 'shows differences for conflicting text files' do
|
||||||
contents = {:castle => 'castle has new content', :home => 'home already has content'}
|
contents = { castle: 'castle has new content', home: 'home already has content' }
|
||||||
|
|
||||||
dotfile = castle.file('text')
|
dotfile = castle.file('text')
|
||||||
File.open(dotfile.to_s, 'w') do |f|
|
File.open(dotfile.to_s, 'w') do |f|
|
||||||
@@ -348,7 +347,7 @@ describe Homesick::CLI do
|
|||||||
end
|
end
|
||||||
it 'shows message or differences for conflicting binary files' do
|
it 'shows message or differences for conflicting binary files' do
|
||||||
# content which contains NULL character, without any parentheses, braces, ...
|
# content which contains NULL character, without any parentheses, braces, ...
|
||||||
contents = {:castle => (0..255).step(30).map{|e| e.chr}.join(), :home => (0..255).step(30).reverse_each.map{|e| e.chr}.join()}
|
contents = { castle: (0..255).step(30).map(&:chr).join, home: (0..255).step(30).reverse_each.map(&:chr).join }
|
||||||
|
|
||||||
dotfile = castle.file('binary')
|
dotfile = castle.file('binary')
|
||||||
File.open(dotfile.to_s, 'w') do |f|
|
File.open(dotfile.to_s, 'w') do |f|
|
||||||
@@ -532,9 +531,9 @@ describe Homesick::CLI do
|
|||||||
|
|
||||||
it 'prints an error message when trying to pull a non-existant castle' do
|
it 'prints an error message when trying to pull a non-existant castle' do
|
||||||
expect(homesick).to receive('say_status').once
|
expect(homesick).to receive('say_status').once
|
||||||
.with(:error,
|
.with(:error,
|
||||||
/Could not pull castle_repo, expected .* to exist and contain dotfiles/,
|
/Could not pull castle_repo, expected .* to exist and contain dotfiles/,
|
||||||
:red)
|
:red)
|
||||||
expect { homesick.pull 'castle_repo' }.to raise_error(SystemExit)
|
expect { homesick.pull 'castle_repo' }.to raise_error(SystemExit)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -544,9 +543,9 @@ describe Homesick::CLI do
|
|||||||
given_castle('glencairn')
|
given_castle('glencairn')
|
||||||
allow(homesick).to receive(:system).exactly(2).times.with('git pull --quiet')
|
allow(homesick).to receive(:system).exactly(2).times.with('git pull --quiet')
|
||||||
allow(homesick).to receive(:system).exactly(2).times
|
allow(homesick).to receive(:system).exactly(2).times
|
||||||
.with('git submodule --quiet init')
|
.with('git submodule --quiet init')
|
||||||
allow(homesick).to receive(:system).exactly(2).times
|
allow(homesick).to receive(:system).exactly(2).times
|
||||||
.with('git submodule --quiet update --init --recursive >/dev/null 2>&1')
|
.with('git submodule --quiet update --init --recursive >/dev/null 2>&1')
|
||||||
Capture.stdout do
|
Capture.stdout do
|
||||||
Capture.stderr { homesick.invoke 'pull', [], all: true }
|
Capture.stderr { homesick.invoke 'pull', [], all: true }
|
||||||
end
|
end
|
||||||
@@ -563,7 +562,7 @@ describe Homesick::CLI do
|
|||||||
|
|
||||||
it 'prints an error message when trying to push a non-existant castle' do
|
it 'prints an error message when trying to push a non-existant castle' do
|
||||||
expect(homesick).to receive('say_status').once
|
expect(homesick).to receive('say_status').once
|
||||||
.with(:error, /Could not push castle_repo, expected .* to exist and contain dotfiles/, :red)
|
.with(:error, /Could not push castle_repo, expected .* to exist and contain dotfiles/, :red)
|
||||||
expect { homesick.push 'castle_repo' }.to raise_error(SystemExit)
|
expect { homesick.push 'castle_repo' }.to raise_error(SystemExit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -721,7 +720,7 @@ describe Homesick::CLI do
|
|||||||
|
|
||||||
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
|
||||||
expect(homesick).to receive('say_status').once
|
expect(homesick).to receive('say_status').once
|
||||||
.with(:error, /Could not cd castle_repo, expected .* to exist and contain dotfiles/, :red)
|
.with(:error, /Could not cd castle_repo, expected .* to exist and contain dotfiles/, :red)
|
||||||
expect { homesick.cd 'castle_repo' }.to raise_error(SystemExit)
|
expect { homesick.cd 'castle_repo' }.to raise_error(SystemExit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -739,18 +738,22 @@ describe Homesick::CLI do
|
|||||||
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
|
||||||
|
# Return empty ENV, the test does not call it anyway
|
||||||
|
allow(ENV).to receive(:[]).and_return(nil)
|
||||||
# Set the default editor to make sure it fails.
|
# Set the default editor to make sure it fails.
|
||||||
allow(ENV).to receive(:[]).with('EDITOR').and_return(nil)
|
allow(ENV).to receive(:[]).with('EDITOR').and_return(nil)
|
||||||
expect(homesick).to receive('say_status').once
|
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)
|
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
|
||||||
|
# Return empty ENV, the test does not call it anyway
|
||||||
|
allow(ENV).to receive(:[]).and_return(nil)
|
||||||
# Set a default just in case none is set
|
# Set a default just in case none is set
|
||||||
allow(ENV).to receive(:[]).with('EDITOR').and_return('vim')
|
allow(ENV).to receive(:[]).with('EDITOR').and_return('vim')
|
||||||
allow(homesick).to receive('say_status').once
|
allow(homesick).to receive('say_status').once
|
||||||
.with(:error, /Could not open castle_repo, expected .* to exist and contain dotfiles/, :red)
|
.with(:error, /Could not open castle_repo, expected .* to exist and contain dotfiles/, :red)
|
||||||
expect { homesick.open 'castle_repo' }.to raise_error(SystemExit)
|
expect { homesick.open 'castle_repo' }.to raise_error(SystemExit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -769,7 +772,7 @@ describe Homesick::CLI do
|
|||||||
it 'executes a single command with no arguments inside a given castle' 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('inside').once.with(kind_of(Pathname)).and_yield
|
||||||
allow(homesick).to receive('say_status').once
|
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')
|
allow(homesick).to receive('system').once.with('ls')
|
||||||
Capture.stdout { homesick.exec 'castle_repo', 'ls' }
|
Capture.stdout { homesick.exec 'castle_repo', 'ls' }
|
||||||
end
|
end
|
||||||
@@ -777,14 +780,14 @@ describe Homesick::CLI do
|
|||||||
it 'executes a single command with arguments inside a given castle' 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('inside').once.with(kind_of(Pathname)).and_yield
|
||||||
allow(homesick).to receive('say_status').once
|
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')
|
allow(homesick).to receive('system').once.with('ls -la')
|
||||||
Capture.stdout { homesick.exec 'castle_repo', 'ls', '-la' }
|
Capture.stdout { homesick.exec 'castle_repo', 'ls', '-la' }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises an error when the method is called without a command' do
|
it 'raises an error when the method is called without a command' do
|
||||||
allow(homesick).to receive('say_status').once
|
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)
|
allow(homesick).to receive('exit').once.with(1)
|
||||||
Capture.stdout { homesick.exec 'castle_repo' }
|
Capture.stdout { homesick.exec 'castle_repo' }
|
||||||
end
|
end
|
||||||
@@ -792,9 +795,9 @@ describe Homesick::CLI do
|
|||||||
context 'pretend' do
|
context 'pretend' do
|
||||||
it 'does not execute a command when the pretend option is passed' do
|
it 'does not execute a command when the pretend option is passed' do
|
||||||
allow(homesick).to receive('say_status').once
|
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
|
expect(homesick).to receive('system').never
|
||||||
Capture.stdout { homesick.invoke 'exec', %w(castle_repo ls -la), pretend: true }
|
Capture.stdout { homesick.invoke 'exec', %w[castle_repo ls -la], pretend: true }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -802,8 +805,8 @@ describe Homesick::CLI do
|
|||||||
it 'does not print status information when quiet is passed' do
|
it 'does not print status information when quiet is passed' do
|
||||||
expect(homesick).to receive('say_status').never
|
expect(homesick).to receive('say_status').never
|
||||||
allow(homesick).to receive('system').once
|
allow(homesick).to receive('system').once
|
||||||
.with('ls -la')
|
.with('ls -la')
|
||||||
Capture.stdout { homesick.invoke 'exec', %w(castle_repo ls -la), quiet: true }
|
Capture.stdout { homesick.invoke 'exec', %w[castle_repo ls -la], quiet: true }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -817,7 +820,7 @@ describe Homesick::CLI do
|
|||||||
it 'executes a command without arguments inside the root of each cloned castle' 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('inside_each_castle').exactly(:twice).and_yield('castle_repo').and_yield('another_castle_repo')
|
||||||
allow(homesick).to receive('say_status').at_least(:once)
|
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')
|
allow(homesick).to receive('system').at_least(:once).with('ls')
|
||||||
Capture.stdout { homesick.exec_all 'ls' }
|
Capture.stdout { homesick.exec_all 'ls' }
|
||||||
end
|
end
|
||||||
@@ -825,14 +828,14 @@ describe Homesick::CLI do
|
|||||||
it 'executes a command with arguments inside the root of each cloned castle' 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('inside_each_castle').exactly(:twice).and_yield('castle_repo').and_yield('another_castle_repo')
|
||||||
allow(homesick).to receive('say_status').at_least(:once)
|
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')
|
allow(homesick).to receive('system').at_least(:once).with('ls -la')
|
||||||
Capture.stdout { homesick.exec_all 'ls', '-la' }
|
Capture.stdout { homesick.exec_all 'ls', '-la' }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises an error when the method is called without a command' do
|
it 'raises an error when the method is called without a command' do
|
||||||
allow(homesick).to receive('say_status').once
|
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)
|
allow(homesick).to receive('exit').once.with(1)
|
||||||
Capture.stdout { homesick.exec_all }
|
Capture.stdout { homesick.exec_all }
|
||||||
end
|
end
|
||||||
@@ -840,9 +843,9 @@ describe Homesick::CLI do
|
|||||||
context 'pretend' do
|
context 'pretend' do
|
||||||
it 'does not execute a command when the pretend option is passed' do
|
it 'does not execute a command when the pretend option is passed' do
|
||||||
allow(homesick).to receive('say_status').at_least(:once)
|
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
|
expect(homesick).to receive('system').never
|
||||||
Capture.stdout { homesick.invoke 'exec_all', %w(ls -la), pretend: true }
|
Capture.stdout { homesick.invoke 'exec_all', %w[ls -la], pretend: true }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -850,8 +853,8 @@ describe Homesick::CLI do
|
|||||||
it 'does not print status information when quiet is passed' do
|
it 'does not print status information when quiet is passed' do
|
||||||
expect(homesick).to receive('say_status').never
|
expect(homesick).to receive('say_status').never
|
||||||
allow(homesick).to receive('system').at_least(:once)
|
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 }
|
Capture.stdout { homesick.invoke 'exec_all', %w[ls -la], quiet: true }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user