65 Commits

Author SHA1 Message Date
Jeremy Cook
0d60ae9d1a Regenerate gemspec for version 1.1.4 2017-03-22 17:14:09 -04:00
Jeremy Cook
3b8a5b4be4 Merge pull request #159 from mruwek/refactor-conflict-actions
Wrap symlink and regular conflicts into one case
2017-03-20 16:07:19 -04:00
Jacek Sowiński
6590a1eeff Wrap symlink and regular conflicts into one case
This way we're not duplicating collision-related code.
2017-03-20 20:26:14 +01:00
Jeremy Cook
693ae5f05e Merge pull request #157 from mruwek/verbose-symlink-conflicts
Don't overwrite silently on symlink conflicts
2017-03-19 22:02:41 -04:00
Jeremy Cook
da3002f199 Merge pull request #154 from singular0/symlink_realpath
Use real paths of symlinks when linking castle into home
2017-03-19 22:02:01 -04:00
Jeremy Cook
feaaab2fa4 Merge pull request #158 from JCook21/master
Minor updates
2017-03-19 22:00:34 -04:00
Jeremy Cook
59f75711a4 Changed strings to use symbols. 2017-03-19 15:57:44 -04:00
Jeremy Cook
f24030b51f Updates to Gemfile to clean it up. 2017-03-19 15:57:22 -04:00
Jeremy Cook
71bb120a12 Update to dependency. 2017-03-19 14:44:44 -04:00
Jacek Sowiński
85f46e01b1 Don't overwrite silently on symlink conflicts
Symlink conflicts are now handled in similar fashion as normal
file-conflicts.
2017-03-17 19:31:23 +01:00
Jeremy Cook
c5b24b9b38 Merge pull request #155 from danielbayerlein/ruby-2.4.0
Add support for Ruby 2.4.0
2016-12-26 07:08:38 -05:00
Daniel Bayerlein
68460af45e Add support for Ruby 2.4.0 2016-12-26 10:31:34 +01:00
Denis Yantarev
5614b6b8b3 Use real paths of symlinks when linking castle into home 2016-12-25 18:34:33 +03:00
Jeremy Cook
570b063632 Merge pull request #152 from singular0/master
Thanks for taking care of this.
2016-12-24 12:13:55 -05:00
Jeremy Cook
1d398587d0 Remove config for removed ruby versions.
Deleted config for unused ruby versions.
2016-12-24 12:11:01 -05:00
Jeremy Cook
085853faaa Merge branch 'master' into master 2016-12-24 12:05:54 -05:00
Jeremy Cook
21b4e344a9 Merge pull request #153 from danielbayerlein/ruby-version
Looks good to me, thanks!
2016-12-24 12:03:51 -05:00
Daniel Bayerlein
a6194dfe8b Update RSpec 2016-12-23 11:59:44 +01:00
Daniel Bayerlein
5692194fa2 Add support for Ruby 2.2.6 and 2.3.3 2016-12-23 11:37:47 +01:00
Daniel Bayerlein
11745098c2 Support Ruby 2.1.0, 2.2.0, 2.3.0 2016-12-23 11:23:11 +01:00
Denis Yantarev
b1bb0c996c Add Ruby 2.2 & 2.3 to Travis config and fix GEM dependencies 2016-12-05 03:34:57 +03:00
Denis Yantarev
a62039da50 Ignore rbenv configuration files 2016-12-05 03:34:14 +03:00
Denis Yantarev
4bfd1c60c2 Fix default option value type warning 2016-12-03 15:56:22 +03:00
Jeremy Cook
f0e11abb5b Merge pull request #149 from mail6543210/master
Use source content instead of source path (fixes: #148). Thanks for fixing this!
2016-01-21 20:05:33 -05:00
mail6543210
ed397bdaf8 Use source content instead of source path (fixes: #148) 2016-01-21 18:36:52 +08:00
Jeremy Cook
2f5e20d963 Fixed formatting in Changelog file. 2015-10-31 09:54:41 -04:00
Jeremy Cook
cc83a4e1fa Preparing for 1.1.3 release. 2015-10-31 09:48:10 -04:00
Jeremy Cook
dcc5cb0bc1 Merge pull request #146 from JCook21/issue134
Fix for issue134
2015-10-25 15:21:26 -04:00
Jeremy Cook
978416d1e4 Fixing diff problems by providing source block and checking for
directories in diff
2015-10-20 21:47:43 -04:00
Jeremy Cook
1c12c73e4b Merge branch 'rweng-named_castles' 2015-10-14 22:31:20 -04:00
Jeremy Cook
1016002638 Merge branch 'named_castles' of https://github.com/rweng/homesick into rweng-named_castles 2015-10-14 22:30:46 -04:00
Jeremy Cook
6431a864ad Merge pull request #145 from JCook21/master
Maintenance fixes
2015-10-13 22:43:07 -04:00
Jeremy Cook
42f661cfbf Update to use new travis container infrastructure (see
http://docs.travis-ci.com/user/migrating-from-legacy/?utm_source=legacy-notice&utm_medium=banner&utm_campaign=legacy-upgrade)
2015-10-12 19:30:29 -04:00
Jeremy Cook
7632591681 Coding standards fixes based off of Rubocop and minor edits to make
logic flow easier to understand.
2015-10-12 19:30:29 -04:00
Jeremy Cook
a9a5b81dc5 Adding system notifications to development gems. 2015-10-12 19:30:29 -04:00
Jeremy Cook
721c10cffd Merge pull request #143 from rweng/fix-open
Fix homesick open
2015-10-12 11:06:10 -04:00
Robin Wenglewski
332aad8ad0 change 'homesick open' to run '$EDITOR .' instead of '$EDITOR' in castle_dir #142 2015-10-12 16:39:52 +02:00
Robin Wenglewski
171b4c1fb8 add option to pass in destination to homesick clone 2015-10-11 18:21:22 +02:00
Jeremy Cook
60d4458bbc Merge pull request #124 from shioyama/clone_destination
Pass destination when cloning url.
2015-03-22 14:12:41 -04:00
Chris Salzberg
9ad171ab78 Pass destination when cloning url. 2015-03-05 22:26:41 +09:00
Jeremy Cook
5918746059 Merge pull request #137 from gerasiov/master
Thanks!
2015-02-23 23:00:22 -05:00
Alexander GQ Gerasiov
4641843ffd Add "requite 'pathname'" to lib/homesick/utils.rb
Since Pathname is used in lib/homesick/utils.rb, it should require this module
itself.

Signed-off-by: Alexander GQ Gerasiov <gq@cs.msu.su>
2015-02-22 23:09:18 +03:00
Jeremy Cook
1a181b907c Merge pull request #136 from williamboman/patch-1
Thanks for fixing this!
2015-02-20 09:19:15 -05:00
William Boman
fb7595d254 Escape message correctly on git_commit_all. 2015-02-19 16:51:53 +01:00
Jeremy Cook
c8f0999035 Preparing for new release. 2015-01-02 00:06:20 -05:00
Jeremy Cook
46faec7857 Bug fix to make sure git check works properly. 2015-01-01 21:21:27 -05:00
Jeremy Cook
e35d3fe6ba Merge pull request #128 from wireframe/force-rc 2014-12-13 08:12:04 -05:00
Jeremy Cook
ba620e0f7f Merge pull request #127 from JCook21/CheckGit
In lieu of other comments I'm going to go ahead and merge this.
2014-12-02 20:53:42 -05:00
Ryan Sonnek
5700f55dc3 Add --force option to homesick rc command
Support automatically eval-ing .homesickrc file without prompting for user input.
This is particularly useful for headless scripts that do not support
user input.
2014-12-01 13:38:43 -06:00
Jeremy Cook
2c92010093 Fix to make tests pass in Ruby 1.9.3 2014-11-25 21:18:13 -05:00
Jeremy Cook
03490531d8 Changed name of git check method to be more descriptive. 2014-11-24 08:49:17 -05:00
Jeremy Cook
7bd9759e81 Added tests for a minimumGit version of 1.8.0. 2014-11-23 22:22:44 -05:00
Jeremy Cook
a808f56caf Tightened up git checking to check for a minimum installed version of
Git.
2014-11-23 14:32:47 -05:00
Jeremy Cook
b7e2b45e69 Added simple implementation to check if git is installed before
executing commands.
2014-11-20 21:25:47 -05:00
Jeremy Cook
63c45d7c3a Removed unneeded config line. 2014-11-09 11:44:09 -05:00
Jeremy Cook
096067ac62 Merge pull request #125 from JCook21/master
Updated to use Rspec 3.1
2014-10-01 21:37:44 -04:00
Jeremy Cook
8d6bf4c0c5 Updated to use Rspec 3.1 2014-09-30 19:39:16 -04:00
Jeremy Cook
882b862780 Merge pull request #123 from JCook21/SymlinkedHomes
I'm merging this as it seems to be harmless and hasn't elicited any responses.
2014-09-27 17:37:21 -04:00
Jeremy Cook
e06a5d6300 Merge pull request #122 from JCook21/SmokeTest
Added basic smoke test
2014-09-19 14:38:44 -04:00
Jeremy Cook
7451e8c739 Bug fix to cover cases where homes are symlinked. 2014-09-19 14:36:32 -04:00
Jeremy Cook
f034f773c5 Added a smoke test to ensure that calling bin/homesick outputs some text 2014-09-19 14:19:09 -04:00
Jeremy Cook
681fd98dc3 Merge pull request #121 from PeterDaveHello/patch-1
Looks good to me, thanks.
2014-09-19 12:10:34 -04:00
Jeremy Cook
e57b139e32 Merge pull request #117 from JCook21/Shell
Merging as there doesn't seem to be any comments or issues with this.
2014-09-19 12:08:54 -04:00
Peter Dave Hello
b64bfe2bb6 Use svg instead of png to get better image quality 2014-09-08 15:42:54 +08:00
Jeremy Cook
ee04b5788a Removed the homesick shell module and folded its code in elsewhere. 2014-06-14 15:03:57 -04:00
15 changed files with 324 additions and 238 deletions

5
.gitignore vendored
View File

@@ -46,3 +46,8 @@ pkg
Gemfile.lock Gemfile.lock
vendor/ vendor/
homesick*.gem
# rbenv configuration
.ruby-version

View File

@@ -1,5 +1,6 @@
language: ruby language: ruby
rvm: rvm:
- 2.1.0 - 2.4.0
- 2.0.0 - 2.3.3
- 1.9.3 - 2.2.6
sudo: false

View File

@@ -1,3 +1,15 @@
#1.1.3
* Allow a destinaton to be passed when cloning a castle
* Make sure `homesick edit` opens default editor in the root of the given castle
* Fixed bug when diffing edited files
* Fixed crashing bug when attempting to diff directories
* Ensure that messages are escaped correctly on `git commit all`
#1.1.2
* Added '--force' option to the rc command to bypass confirmation checks when running a .homesickrc file
* Added a check to make sure that a minimum of Git 1.8.0 is installed. This stops Homesick failing silently if Git is not installed.
* Code refactoring and fixes.
#1.1.0 #1.1.0
* Added exec and exec_all commands to run commands inside one or all clones castles. * Added exec and exec_all commands to run commands inside one or all clones castles.
* Code refactoring. * Code refactoring.
@@ -34,11 +46,11 @@
* Introduce .homesick_subdir #39 * Introduce .homesick_subdir #39
# 0.8.1 # 0.8.1
*Fixed `homesick list` bug on ruby 2.0 #37 * Fixed `homesick list` bug on ruby 2.0 #37
# 0.8.0 # 0.8.0
* Introduce commit & push command * Introduce commit & push command
* commit changes in castle and push to remote * commit changes in castle and push to remote
* Enable recursive submodule update * Enable recursive submodule update
* Git add when track * Git add when track

38
Gemfile
View File

@@ -1,26 +1,36 @@
require 'rbconfig'
source 'https://rubygems.org' source 'https://rubygems.org'
this_ruby = Gem::Version.new(RUBY_VERSION)
ruby_230 = Gem::Version.new('2.3.0')
# Add dependencies required to use your gem here. # Add dependencies required to use your gem here.
gem "thor", ">= 0.14.0" gem 'thor', '>= 0.14.0'
# Add dependencies to develop your gem here. # Add dependencies to develop your gem here.
# Include everything needed to run rake, tests, features, etc. # Include everything needed to run rake, tests, features, etc.
group :development do group :development do
gem "rake", ">= 0.8.7" gem 'capture-output', '~> 1.0.0'
gem "rspec", "~> 2.10"
gem "guard"
gem "guard-rspec"
gem "rb-readline", "~> 0.5.0"
gem "jeweler", ">= 1.6.2"
#gem "simplecov"
gem 'coveralls', require: false gem 'coveralls', require: false
gem "test_construct" gem 'guard'
gem "capture-output", "~> 1.0.0" gem 'guard-rspec'
if RbConfig::CONFIG['host_os'] =~ /linux|freebsd|openbsd|sunos|solaris/ gem 'jeweler', '>= 1.6.2', '< 2.2' if this_ruby < ruby_230
gem 'jeweler', '>= 1.6.2' if this_ruby >= ruby_230
gem 'rake', '>= 0.8.7'
gem 'rb-readline', '~> 0.5.0'
gem 'rspec', '~> 3.5.0'
gem 'rubocop'
gem 'test_construct'
install_if -> { RUBY_PLATFORM =~ /linux|freebsd|openbsd|sunos|solaris/ } do
gem 'libnotify' gem 'libnotify'
end end
if RUBY_VERSION >= '1.9.2'
gem "rubocop" install_if -> { RUBY_PLATFORM =~ /darwin/ } do
gem 'terminal-notifier-guard', '~> 1.7.0'
end
install_if -> { this_ruby < ruby_230 } do
gem 'listen', '< 3'
gem 'rack', '< 2'
end end
end end

View File

@@ -1,11 +1,11 @@
# homesick # homesick
[![Gem Version](https://badge.fury.io/rb/homesick.png)](http://badge.fury.io/rb/homesick) [![Gem Version](https://badge.fury.io/rb/homesick.svg)](http://badge.fury.io/rb/homesick)
[![Build Status](https://travis-ci.org/technicalpickles/homesick.png?branch=master)](https://travis-ci.org/technicalpickles/homesick) [![Build Status](https://travis-ci.org/technicalpickles/homesick.svg?branch=master)](https://travis-ci.org/technicalpickles/homesick)
[![Dependency Status](https://gemnasium.com/technicalpickles/homesick.png)](https://gemnasium.com/technicalpickles/homesick) [![Dependency Status](https://gemnasium.com/technicalpickles/homesick.svg)](https://gemnasium.com/technicalpickles/homesick)
[![Coverage Status](https://coveralls.io/repos/technicalpickles/homesick/badge.png)](https://coveralls.io/r/technicalpickles/homesick) [![Coverage Status](https://coveralls.io/repos/technicalpickles/homesick/badge.png)](https://coveralls.io/r/technicalpickles/homesick)
[![Code Climate](https://codeclimate.com/github/technicalpickles/homesick.png)](https://codeclimate.com/github/technicalpickles/homesick) [![Code Climate](https://codeclimate.com/github/technicalpickles/homesick.svg)](https://codeclimate.com/github/technicalpickles/homesick)
[![Gitter chat](https://badges.gitter.im/technicalpickles/homesick.png)](https://gitter.im/technicalpickles/homesick) [![Gitter chat](https://badges.gitter.im/technicalpickles/homesick.svg)](https://gitter.im/technicalpickles/homesick)
Your home directory is your castle. Don't leave your dotfiles behind. Your home directory is your castle. Don't leave your dotfiles behind.
@@ -40,7 +40,7 @@ If you need to add further configuration steps you can add these in a file calle
homesick rc CASTLE homesick rc CASTLE
The contents of the .homesickrc file must be valid Ruby code as the file will be executed with Ruby's eval construct. The .homesickrc is also passed the current homesick object during its execution and this is available within the .homesickrc file as the 'self' variable. The contents of the .homesickrc file must be valid Ruby code as the file will be executed with Ruby's eval construct. The .homesickrc is also passed the current homesick object during its execution and this is available within the .homesickrc file as the 'self' variable. As the rc operation can be destructive the command normally asks for confirmation before proceeding. You can bypass this by passing the '--force' option, for example `homesick rc --force CASTLE`.
If you're not sure what castles you have around, you can easily list them: If you're not sure what castles you have around, you can easily list them:
@@ -164,9 +164,9 @@ and castle
Homesick is tested on the following Ruby versions: Homesick is tested on the following Ruby versions:
* 1.9.3 * 2.2.6
* 2.0.0 * 2.3.3
* 2.1.0 * 2.4.0
## Note on Patches/Pull Requests ## Note on Patches/Pull Requests

View File

@@ -2,19 +2,19 @@
# DO NOT EDIT THIS FILE DIRECTLY # DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
# stub: homesick 1.1.1 ruby lib # stub: homesick 1.1.4 ruby lib
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = "homesick" s.name = "homesick".freeze
s.version = "1.1.1" s.version = "1.1.4"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib"] s.require_paths = ["lib".freeze]
s.authors = ["Joshua Nichols", "Yusuke Murata"] s.authors = ["Joshua Nichols".freeze, "Yusuke Murata".freeze]
s.date = "2014-05-22" s.date = "2017-03-22"
s.description = "\n Your home directory is your castle. Don't leave your dotfiles behind.\n \n\n Homesick is sorta like rip, but for dotfiles. It uses git to clone a repository containing dotfiles, and saves them in ~/.homesick. It then allows you to symlink all the dotfiles into place with a single command. \n\n " s.description = "\n Your home directory is your castle. Don't leave your dotfiles behind.\n \n\n Homesick is sorta like rip, but for dotfiles. It uses git to clone a repository containing dotfiles, and saves them in ~/.homesick. It then allows you to symlink all the dotfiles into place with a single command. \n\n ".freeze
s.email = ["josh@technicalpickles.com", "info@muratayusuke.com"] s.email = ["josh@technicalpickles.com".freeze, "info@muratayusuke.com".freeze]
s.executables = ["homesick"] s.executables = ["homesick".freeze]
s.extra_rdoc_files = [ s.extra_rdoc_files = [
"ChangeLog.markdown", "ChangeLog.markdown",
"LICENSE", "LICENSE",
@@ -37,58 +37,69 @@ Gem::Specification.new do |s|
"lib/homesick/actions/file_actions.rb", "lib/homesick/actions/file_actions.rb",
"lib/homesick/actions/git_actions.rb", "lib/homesick/actions/git_actions.rb",
"lib/homesick/cli.rb", "lib/homesick/cli.rb",
"lib/homesick/shell.rb",
"lib/homesick/utils.rb", "lib/homesick/utils.rb",
"lib/homesick/version.rb", "lib/homesick/version.rb",
"spec/homesick_cli_spec.rb", "spec/homesick_cli_spec.rb",
"spec/spec.opts", "spec/spec.opts",
"spec/spec_helper.rb" "spec/spec_helper.rb"
] ]
s.homepage = "http://github.com/technicalpickles/homesick" s.homepage = "http://github.com/technicalpickles/homesick".freeze
s.licenses = ["MIT"] s.licenses = ["MIT".freeze]
s.rubygems_version = "2.2.2" s.rubygems_version = "2.6.11".freeze
s.summary = "Your home directory is your castle. Don't leave your dotfiles behind." s.summary = "Your home directory is your castle. Don't leave your dotfiles behind.".freeze
if s.respond_to? :specification_version then if s.respond_to? :specification_version then
s.specification_version = 4 s.specification_version = 4
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<thor>, [">= 0.14.0"]) s.add_runtime_dependency(%q<thor>.freeze, [">= 0.14.0"])
s.add_development_dependency(%q<rake>, [">= 0.8.7"]) s.add_development_dependency(%q<capture-output>.freeze, ["~> 1.0.0"])
s.add_development_dependency(%q<rspec>, ["~> 2.10"]) s.add_development_dependency(%q<coveralls>.freeze, [">= 0"])
s.add_development_dependency(%q<guard>, [">= 0"]) s.add_development_dependency(%q<guard>.freeze, [">= 0"])
s.add_development_dependency(%q<guard-rspec>, [">= 0"]) s.add_development_dependency(%q<guard-rspec>.freeze, [">= 0"])
s.add_development_dependency(%q<rb-readline>, ["~> 0.5.0"]) s.add_development_dependency(%q<jeweler>.freeze, [">= 1.6.2"])
s.add_development_dependency(%q<jeweler>, [">= 1.6.2"]) s.add_development_dependency(%q<rake>.freeze, [">= 0.8.7"])
s.add_development_dependency(%q<coveralls>, [">= 0"]) s.add_development_dependency(%q<rb-readline>.freeze, ["~> 0.5.0"])
s.add_development_dependency(%q<test_construct>, [">= 0"]) s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
s.add_development_dependency(%q<capture-output>, ["~> 1.0.0"]) s.add_development_dependency(%q<rubocop>.freeze, [">= 0"])
s.add_development_dependency(%q<rubocop>, [">= 0"]) s.add_development_dependency(%q<test_construct>.freeze, [">= 0"])
s.add_development_dependency(%q<libnotify>.freeze, [">= 0"])
s.add_development_dependency(%q<terminal-notifier-guard>.freeze, ["~> 1.7.0"])
s.add_development_dependency(%q<listen>.freeze, ["< 3"])
s.add_development_dependency(%q<rack>.freeze, ["< 2"])
else else
s.add_dependency(%q<thor>, [">= 0.14.0"]) s.add_dependency(%q<thor>.freeze, [">= 0.14.0"])
s.add_dependency(%q<rake>, [">= 0.8.7"]) s.add_dependency(%q<capture-output>.freeze, ["~> 1.0.0"])
s.add_dependency(%q<rspec>, ["~> 2.10"]) s.add_dependency(%q<coveralls>.freeze, [">= 0"])
s.add_dependency(%q<guard>, [">= 0"]) s.add_dependency(%q<guard>.freeze, [">= 0"])
s.add_dependency(%q<guard-rspec>, [">= 0"]) s.add_dependency(%q<guard-rspec>.freeze, [">= 0"])
s.add_dependency(%q<rb-readline>, ["~> 0.5.0"]) s.add_dependency(%q<jeweler>.freeze, [">= 1.6.2"])
s.add_dependency(%q<jeweler>, [">= 1.6.2"]) s.add_dependency(%q<rake>.freeze, [">= 0.8.7"])
s.add_dependency(%q<coveralls>, [">= 0"]) s.add_dependency(%q<rb-readline>.freeze, ["~> 0.5.0"])
s.add_dependency(%q<test_construct>, [">= 0"]) s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
s.add_dependency(%q<capture-output>, ["~> 1.0.0"]) s.add_dependency(%q<rubocop>.freeze, [">= 0"])
s.add_dependency(%q<rubocop>, [">= 0"]) s.add_dependency(%q<test_construct>.freeze, [">= 0"])
s.add_dependency(%q<libnotify>.freeze, [">= 0"])
s.add_dependency(%q<terminal-notifier-guard>.freeze, ["~> 1.7.0"])
s.add_dependency(%q<listen>.freeze, ["< 3"])
s.add_dependency(%q<rack>.freeze, ["< 2"])
end end
else else
s.add_dependency(%q<thor>, [">= 0.14.0"]) s.add_dependency(%q<thor>.freeze, [">= 0.14.0"])
s.add_dependency(%q<rake>, [">= 0.8.7"]) s.add_dependency(%q<capture-output>.freeze, ["~> 1.0.0"])
s.add_dependency(%q<rspec>, ["~> 2.10"]) s.add_dependency(%q<coveralls>.freeze, [">= 0"])
s.add_dependency(%q<guard>, [">= 0"]) s.add_dependency(%q<guard>.freeze, [">= 0"])
s.add_dependency(%q<guard-rspec>, [">= 0"]) s.add_dependency(%q<guard-rspec>.freeze, [">= 0"])
s.add_dependency(%q<rb-readline>, ["~> 0.5.0"]) s.add_dependency(%q<jeweler>.freeze, [">= 1.6.2"])
s.add_dependency(%q<jeweler>, [">= 1.6.2"]) s.add_dependency(%q<rake>.freeze, [">= 0.8.7"])
s.add_dependency(%q<coveralls>, [">= 0"]) s.add_dependency(%q<rb-readline>.freeze, ["~> 0.5.0"])
s.add_dependency(%q<test_construct>, [">= 0"]) s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
s.add_dependency(%q<capture-output>, ["~> 1.0.0"]) s.add_dependency(%q<rubocop>.freeze, [">= 0"])
s.add_dependency(%q<rubocop>, [">= 0"]) s.add_dependency(%q<test_construct>.freeze, [">= 0"])
s.add_dependency(%q<libnotify>.freeze, [">= 0"])
s.add_dependency(%q<terminal-notifier-guard>.freeze, ["~> 1.7.0"])
s.add_dependency(%q<listen>.freeze, ["< 3"])
s.add_dependency(%q<rack>.freeze, ["< 2"])
end end
end end

View File

@@ -1,5 +1,4 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
require 'homesick/shell'
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'
@@ -8,7 +7,7 @@ require 'homesick/cli'
# Homesick's top-level module # Homesick's top-level module
module Homesick 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' SUBDIR_FILENAME = '.homesick_subdir'
DEFAULT_CASTLE_NAME = 'dotfiles' DEFAULT_CASTLE_NAME = 'dotfiles'

View File

@@ -3,16 +3,14 @@ module Homesick
module Actions module Actions
# File-related helper methods for Homesick # File-related helper methods for Homesick
module FileActions module FileActions
def mv(source, destination, config = {}) 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
if destination.exist? when destination.exist? && (options[:force] || shell.file_collision(destination) { source })
say_status :conflict, "#{destination} exists", :red say_status :conflict, "#{destination} exists", :red
FileUtils.mv source, destination unless options[:pretend]
FileUtils.mv source, destination if (options[:force] || shell.file_collision(destination) { source }) && !options[:pretend]
else else
# this needs some sort of message here.
FileUtils.mv source, destination unless options[:pretend] FileUtils.mv source, destination unless options[:pretend]
end end
end end
@@ -43,8 +41,8 @@ module Homesick
FileUtils.rm_r dir FileUtils.rm_r dir
end end
def ln_s(source, destination, config = {}) def ln_s(source, destination)
source = Pathname.new(source) source = Pathname.new(source).realpath
destination = Pathname.new(destination) destination = Pathname.new(destination)
FileUtils.mkdir_p destination.dirname FileUtils.mkdir_p destination.dirname
@@ -65,17 +63,15 @@ module Homesick
case action case action
when :identical when :identical
say_status :identical, destination.expand_path, :blue say_status :identical, destination.expand_path, :blue
when :symlink_conflict when :symlink_conflict, :conflict
say_status :conflict, if action == :conflict
"#{destination} exists and points to #{destination.readlink}", say_status :conflict, "#{destination} exists", :red
:red else
say_status :conflict,
FileUtils.rm destination "#{destination} exists and points to #{destination.readlink}",
FileUtils.ln_s source, destination, force: true unless options[:pretend] :red
when :conflict end
say_status :conflict, "#{destination} exists", :red if collision_accepted?(destination, source)
if collision_accepted?(destination)
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] FileUtils.ln_s source, destination, force: true unless options[:pretend]
end end

View File

@@ -3,12 +3,31 @@ module Homesick
module Actions module Actions
# Git-related helper methods for Homesick # Git-related helper methods for Homesick
module GitActions module GitActions
# Information on the minimum git version required for Homesick
MIN_VERSION = {
major: 1,
minor: 8,
patch: 0
}
STRING = MIN_VERSION.values.join('.')
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)]
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]
return true if current_version[:major] == MIN_VERSION[:major] && current_version[:minor] == MIN_VERSION[:minor] && current_version[:patch] >= MIN_VERSION[:patch]
false
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
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')
destination = Pathname.new(destination) unless destination.kind_of?(Pathname) destination = Pathname.new(destination) unless destination.is_a?(Pathname)
FileUtils.mkdir_p destination.dirname FileUtils.mkdir_p destination.dirname
if destination.directory? if destination.directory?
@@ -46,22 +65,22 @@ module Homesick
end end
end end
def git_submodule_init(config = {}) def git_submodule_init
say_status 'git submodule', 'init', :green say_status 'git submodule', 'init', :green
system 'git submodule --quiet init' system 'git submodule --quiet init'
end end
def git_submodule_update(config = {}) def git_submodule_update
say_status 'git submodule', 'update', :green say_status 'git submodule', 'update', :green
system 'git submodule --quiet update --init --recursive >/dev/null 2>&1' system 'git submodule --quiet update --init --recursive >/dev/null 2>&1'
end end
def git_pull(config = {}) def git_pull
say_status 'git pull', '', :green say_status 'git pull', '', :green
system 'git pull --quiet' system 'git pull --quiet'
end end
def git_push(config = {}) def git_push
say_status 'git push', '', :green say_status 'git push', '', :green
system 'git push' system 'git push'
end end
@@ -69,23 +88,23 @@ module Homesick
def git_commit_all(config = {}) def git_commit_all(config = {})
say_status 'git commit all', '', :green say_status 'git commit all', '', :green
if config[:message] if config[:message]
system "git commit -a -m '#{config[:message]}'" system %(git commit -a -m "#{config[:message]}")
else else
system 'git commit -v -a' system 'git commit -v -a'
end end
end end
def git_add(file, config = {}) def git_add(file)
say_status 'git add file', '', :green say_status 'git add file', '', :green
system "git add '#{file}'" system "git add '#{file}'"
end end
def git_status(config = {}) def git_status
say_status 'git status', '', :green say_status 'git status', '', :green
system 'git status' system 'git status'
end end
def git_diff(config = {}) def git_diff
say_status 'git diff', '', :green say_status 'git diff', '', :green
system 'git diff' system 'git diff'
end end

View File

@@ -19,27 +19,43 @@ module Homesick
def initialize(args = [], options = {}, config = {}) def initialize(args = [], options = {}, config = {})
super super
self.shell = Homesick::Shell.new # 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, content|
destination = Pathname.new(destination)
content = Pathname.new(content)
return 'Unable to create diff: destination or content is a directory' if destination.directory? || content.directory?
return super(destination, content) unless destination.symlink?
say "- #{destination.readlink}", :red, true
say "+ #{content.expand_path}", :green, true
end
end end
desc 'clone URI', 'Clone +uri+ as a castle for homesick' desc 'clone URI CASTLE_NAME', 'Clone +uri+ as a castle with name CASTLE_NAME for homesick'
def clone(uri) def clone(uri, destination=nil)
destination = Pathname.new(destination) unless destination.nil?
inside repos_dir do inside repos_dir do
destination = nil
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) fail "Castle already cloned to #{uri}" if uri.to_s.start_with?(repos_dir.to_s)
destination = uri.basename destination = uri.basename if destination.nil?
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 if destination.nil?
git_clone "https://github.com/#{Regexp.last_match[1]}.git", git_clone "https://github.com/#{Regexp.last_match[1]}.git",
destination: destination destination: destination
elsif uri =~ /%r([^%r]*?)(\.git)?\Z/ || uri =~ /[^:]+:([^:]+)(\.git)?\Z/ elsif uri =~ /%r([^%r]*?)(\.git)?\Z/ || uri =~ /[^:]+:([^:]+)(\.git)?\Z/
destination = Pathname.new(Regexp.last_match[1]) destination = Pathname.new(Regexp.last_match[1].gsub(/\.git$/, '')).basename if destination.nil?
git_clone uri git_clone uri, destination: destination
else else
fail "Unknown URI format: #{uri}" fail "Unknown URI format: #{uri}"
end end
@@ -49,22 +65,20 @@ module Homesick
end end
desc 'rc CASTLE', 'Run the .homesickrc for the specified castle' desc 'rc CASTLE', 'Run the .homesickrc for the specified castle'
method_option :force,
type: :boolean,
default: false,
desc: 'Evaluate .homesickrc without prompting.'
def rc(name = DEFAULT_CASTLE_NAME) def rc(name = DEFAULT_CASTLE_NAME)
inside repos_dir do inside repos_dir do
destination = Pathname.new(name) destination = Pathname.new(name)
homesickrc = destination.join('.homesickrc').expand_path homesickrc = destination.join('.homesickrc').expand_path
if homesickrc.exist? return unless homesickrc.exist?
proceed = 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)")
if 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
end
else
say_status 'eval skip',
"not evaling #{homesickrc}, #{destination} may need manual configuration",
:blue
end
end end
end end
end end
@@ -115,6 +129,7 @@ module Homesick
desc 'link CASTLE', 'Symlinks all dotfiles from the specified castle' desc 'link CASTLE', 'Symlinks all dotfiles from the specified castle'
method_option :force, method_option :force,
type: :boolean,
default: false, default: false,
desc: 'Overwrite existing conflicting symlinks without prompting.' desc: 'Overwrite existing conflicting symlinks without prompting.'
def link(name = DEFAULT_CASTLE_NAME) def link(name = DEFAULT_CASTLE_NAME)
@@ -232,11 +247,10 @@ module Homesick
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'
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)
unlink(name) rm_rf repos_dir.join(name)
rm_rf repos_dir.join(name)
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'
@@ -263,11 +277,11 @@ module Homesick
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}", say_status "#{castle_dir.realpath}: #{ENV['EDITOR']} .",
"Opening the root directory of castle '#{castle}' in editor '#{ENV['EDITOR']}'.", "Opening the root directory of castle '#{castle}' in editor '#{ENV['EDITOR']}'.",
:green :green
inside castle_dir do inside castle_dir do
system(ENV['EDITOR']) system("#{ENV['EDITOR']} .")
end end
end end

View File

@@ -1,17 +0,0 @@
require 'thor'
module Homesick
# Hack in support for diffing symlinks
class Shell < Thor::Shell::Color
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
end
end

View File

@@ -1,10 +1,12 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
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'] QUIETABLE = [:say_status]
PRETENDABLE = ['system'] PRETENDABLE = [:system]
QUIETABLE.each do |method_name| QUIETABLE.each do |method_name|
define_method(method_name) do |*args| define_method(method_name) do |*args|
@@ -21,7 +23,7 @@ module Homesick
protected protected
def home_dir def home_dir
@home_dir ||= Pathname.new(ENV['HOME'] || '~').expand_path @home_dir ||= Pathname.new(ENV['HOME'] || '~').realpath
end end
def repos_dir def repos_dir
@@ -33,12 +35,11 @@ module Homesick
end end
def check_castle_existance(name, action) def check_castle_existance(name, action)
unless castle_dir(name).exist? return if castle_dir(name).exist?
say_status :error, say_status :error,
"Could not #{action} #{name}, expected #{castle_dir(name)} exist and contain dotfiles", "Could not #{action} #{name}, expected #{castle_dir(name)} exist and contain dotfiles",
:red :red
exit(1) exit(1)
end
end end
def all_castles def all_castles
@@ -51,7 +52,7 @@ module Homesick
end end
end end
def inside_each_castle(&block) def inside_each_castle
all_castles.each do |git_dir| all_castles.each do |git_dir|
castle = git_dir.dirname castle = git_dir.dirname
Dir.chdir castle do # so we can call git config from the right contxt Dir.chdir castle do # so we can call git config from the right contxt
@@ -128,7 +129,6 @@ module Homesick
def move_dir_contents(target, dir_path) def move_dir_contents(target, dir_path)
child_files = dir_path.children child_files = dir_path.children
child_files.each do |child| child_files.each do |child|
target_path = target.join(child.basename) target_path = target.join(child.basename)
if target_path.exist? if target_path.exist?
if more_recent?(child, target_path) && target.file? if more_recent?(child, target_path) && target.file?
@@ -148,9 +148,9 @@ module Homesick
first_p.mtime > second_p.mtime && !first_p.symlink? first_p.mtime > second_p.mtime && !first_p.symlink?
end end
def collision_accepted?(destination) def collision_accepted?(destination, source)
fail "Argument must be an instance of Pathname, #{destination.class.name} given" unless destination.instance_of?(Pathname) fail "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) { File.binread(source) }
end end
def each_file(castle, basedir, subdirs) def each_file(castle, basedir, subdirs)
@@ -191,7 +191,7 @@ module Homesick
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
end end
end end

View File

@@ -5,7 +5,7 @@ module Homesick
module Version module Version
MAJOR = 1 MAJOR = 1
MINOR = 1 MINOR = 1
PATCH = 1 PATCH = 3
STRING = [MAJOR, MINOR, PATCH].compact.join('.') STRING = [MAJOR, MINOR, PATCH].compact.join('.')
end end

View File

@@ -1,6 +1,7 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
require 'spec_helper' require 'spec_helper'
require 'capture-output' require 'capture-output'
require 'pathname'
describe Homesick::CLI do describe Homesick::CLI do
let(:home) { create_construct } let(:home) { create_construct }
@@ -12,6 +13,48 @@ describe Homesick::CLI do
before { allow(homesick).to receive(:repos_dir).and_return(castles) } before { allow(homesick).to receive(:repos_dir).and_return(castles) }
describe 'smoke tests' do
context 'when running bin/homesick' do
before do
bin_path = Pathname.new(__FILE__).parent.parent
@output = `#{bin_path.expand_path}/bin/homesick`
end
it 'should output some text when bin/homesick is called' do
expect(@output.length).to be > 0
end
end
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')
end
it 'should raise an exception' do
output = Capture.stdout { expect { Homesick::CLI.new }.to raise_error SystemExit }
expect(output.chomp).to include(Homesick::Actions::GitActions::STRING)
end
end
context 'when a git version that is the same as the minimum required is installed' do
before 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 }
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')
end
it 'should not raise an exception' do
output = Capture.stdout { expect { Homesick::CLI.new }.not_to raise_error }
expect(output.chomp).not_to include(Homesick::Actions::GitActions::STRING)
end
end
end
describe 'clone' do describe 'clone' do
context 'has a .homesickrc' do context 'has a .homesickrc' do
it 'runs the .homesickrc' do it 'runs the .homesickrc' do
@@ -63,55 +106,63 @@ describe Homesick::CLI do
homesick.clone "file://#{bare_repo}" homesick.clone "file://#{bare_repo}"
end end
expect(File.directory?(File.join(home.to_s, '.homesick/repos/dotfiles'))) expect(File.directory?(File.join(home.to_s, '.homesick/repos/dotfiles')))
.to be_true .to be_truthy
end end
it 'clones git repo like git://host/path/to.git' do it 'clones git repo like git://host/path/to.git' do
expect(homesick).to receive(:git_clone) expect(homesick).to receive(:git_clone)
.with('git://github.com/technicalpickles/pickled-vim.git') .with('git://github.com/technicalpickles/pickled-vim.git', destination: Pathname.new('pickled-vim'))
homesick.clone 'git://github.com/technicalpickles/pickled-vim.git' homesick.clone 'git://github.com/technicalpickles/pickled-vim.git'
end end
it 'clones git repo like git@host:path/to.git' do it 'clones git repo like git@host:path/to.git' do
expect(homesick).to receive(:git_clone) expect(homesick).to receive(:git_clone)
.with('git@github.com:technicalpickles/pickled-vim.git') .with('git@github.com:technicalpickles/pickled-vim.git', destination: Pathname.new('pickled-vim'))
homesick.clone 'git@github.com:technicalpickles/pickled-vim.git' homesick.clone 'git@github.com:technicalpickles/pickled-vim.git'
end end
it 'clones git repo like http://host/path/to.git' do it 'clones git repo like http://host/path/to.git' do
expect(homesick).to receive(:git_clone) expect(homesick).to receive(:git_clone)
.with('http://github.com/technicalpickles/pickled-vim.git') .with('http://github.com/technicalpickles/pickled-vim.git', destination: Pathname.new('pickled-vim'))
homesick.clone 'http://github.com/technicalpickles/pickled-vim.git' homesick.clone 'http://github.com/technicalpickles/pickled-vim.git'
end end
it 'clones git repo like http://host/path/to' do it 'clones git repo like http://host/path/to' do
expect(homesick).to receive(:git_clone) expect(homesick).to receive(:git_clone)
.with('http://github.com/technicalpickles/pickled-vim') .with('http://github.com/technicalpickles/pickled-vim', destination: Pathname.new('pickled-vim'))
homesick.clone 'http://github.com/technicalpickles/pickled-vim' homesick.clone 'http://github.com/technicalpickles/pickled-vim'
end end
it 'clones git repo like host-alias:repos.git' do it 'clones git repo like host-alias:repos.git' do
expect(homesick).to receive(:git_clone).with('gitolite:pickled-vim.git') expect(homesick).to receive(:git_clone).with('gitolite:pickled-vim.git',
destination: Pathname.new('pickled-vim'))
homesick.clone 'gitolite:pickled-vim.git' homesick.clone 'gitolite:pickled-vim.git'
end end
it 'throws an exception when trying to clone a malformed uri like malformed' do it 'throws an exception when trying to clone a malformed uri like malformed' do
expect(homesick).not_to receive(:git_clone) expect(homesick).not_to receive(:git_clone)
expect { homesick.clone 'malformed' }.to raise_error expect { homesick.clone 'malformed' }.to raise_error(RuntimeError)
end end
it 'clones a github repo' do it 'clones a github repo' 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('dotfiles'))
destination: Pathname.new('dotfiles'))
homesick.clone 'wfarr/dotfiles' homesick.clone 'wfarr/dotfiles'
end end
it 'accepts a destination', :focus do
expect(homesick).to receive(:git_clone)
.with('https://github.com/wfarr/dotfiles.git',
destination: Pathname.new('other-name'))
homesick.clone 'wfarr/dotfiles', 'other-name'
end
end end
describe 'rc' do describe 'rc' do
@@ -136,6 +187,26 @@ describe Homesick::CLI do
end end
end end
context 'when options[:force] == true' do
let(:homesick) { Homesick::CLI.new [], force: true }
before do
expect_any_instance_of(Thor::Shell::Basic).to_not receive(:yes?)
end
it 'executes the .homesickrc' do
castle.file('.homesickrc') do |file|
file << "File.open(Dir.pwd + '/testing', 'w') do |f|
f.print 'testing'
end"
end
expect(homesick).to receive(:say_status).with('eval', kind_of(Pathname))
homesick.rc castle
expect(castle.join('testing')).to exist
end
end
context 'when told not to do so' do context 'when told not to do so' do
before do before do
expect_any_instance_of(Thor::Shell::Basic).to receive(:yes?).with(be_a(String)).and_return(false) expect_any_instance_of(Thor::Shell::Basic).to receive(:yes?).with(be_a(String)).and_return(false)
@@ -156,7 +227,7 @@ describe Homesick::CLI do
end end
end end
describe 'link' do describe 'link_castle' do
let(:castle) { given_castle('glencairn') } let(:castle) { given_castle('glencairn') }
it 'links dotfiles from a castle to the home folder' do it 'links dotfiles from a castle to the home folder' do
@@ -244,11 +315,9 @@ describe Homesick::CLI 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')
expect(home_config_dir.symlink?).to eq(false) expect(home_config_dir.symlink?).to eq(false)
expect(home_config_dir.join('.some_dotfile').readlink) expect(home_config_dir.join('.some_dotfile').readlink).to eq(config_dotfile)
.to eq(config_dotfile)
expect(home_someapp_dir.symlink?).to eq(false) expect(home_someapp_dir.symlink?).to eq(false)
expect(home_someapp_dir.join('.some_appfile').readlink) expect(home_someapp_dir.join('.some_appfile').readlink).to eq(someapp_dotfile)
.to eq(someapp_dotfile)
end end
end end
@@ -357,13 +426,9 @@ describe Homesick::CLI do
given_castle('wtf/zomg') given_castle('wtf/zomg')
expect(homesick).to receive(:say_status) expect(homesick).to receive(:say_status)
.with('zomg', .with('zomg', 'git://github.com/technicalpickles/zomg.git', :cyan)
'git://github.com/technicalpickles/zomg.git',
:cyan)
expect(homesick).to receive(:say_status) expect(homesick).to receive(:say_status)
.with('wtf/zomg', .with('wtf/zomg', 'git://github.com/technicalpickles/zomg.git', :cyan)
'git://github.com/technicalpickles/zomg.git',
:cyan)
homesick.list homesick.list
end end
@@ -373,7 +438,7 @@ describe Homesick::CLI do
it 'says "nothing to commit" when there are no changes' do it 'says "nothing to commit" when there are no changes' do
given_castle('castle_repo') given_castle('castle_repo')
text = Capture.stdout { homesick.status('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 end
it 'says "Changes to be committed" when there are changes' do it 'says "Changes to be committed" when there are changes' do
@@ -381,9 +446,7 @@ describe Homesick::CLI 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') }
expect(text).to match( expect(text).to match(%r{Changes to be committed:.*new file:\s*home\/.some_rc_file}m)
/Changes to be committed:.*new file:\s*home\/.some_rc_file/m
)
end end
end end
@@ -455,7 +518,6 @@ describe Homesick::CLI do
end end
end end
end end
end end
describe 'push' do describe 'push' do
@@ -467,9 +529,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, .with(:error, /Could not push castle_repo, expected .* exist and contain dotfiles/, :red)
/Could not push castle_repo, expected .* 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
@@ -553,7 +613,6 @@ describe Homesick::CLI do
# Note that this is a test for the subdir_file related feature of track, # Note that this is a test for the subdir_file related feature of track,
# not for the subdir_file method itself. # not for the subdir_file method itself.
describe 'subdir_file' do describe 'subdir_file' do
it 'adds the nested files parent to the subdir_file' do it 'adds the nested files parent to the subdir_file' do
castle = given_castle('castle_repo') castle = given_castle('castle_repo')
@@ -628,9 +687,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, .with(:error, /Could not cd castle_repo, expected .* exist and contain dotfiles/, :red)
/Could not cd castle_repo, expected .* 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
@@ -643,7 +700,7 @@ describe Homesick::CLI do
allow(ENV).to receive(:[]).with('EDITOR').and_return('vim') allow(ENV).to receive(:[]).with('EDITOR').and_return('vim')
given_castle 'castle_repo' given_castle 'castle_repo'
expect(homesick).to receive('inside').once.with(kind_of(Pathname)).and_yield expect(homesick).to receive('inside').once.with(kind_of(Pathname)).and_yield
expect(homesick).to receive('system').once.with('vim') expect(homesick).to receive('system').once.with('vim .')
Capture.stdout { homesick.open 'castle_repo' } Capture.stdout { homesick.open 'castle_repo' }
end end
@@ -651,9 +708,7 @@ describe Homesick::CLI do
# 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, .with(:error, 'The $EDITOR environment variable must be set to use this command', :red)
'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
@@ -661,9 +716,7 @@ describe Homesick::CLI do
# 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, .with(:error, /Could not open castle_repo, expected .* exist and contain dotfiles/, :red)
/Could not open castle_repo, expected .* 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
@@ -671,7 +724,7 @@ describe Homesick::CLI do
describe 'version' do describe 'version' do
it 'prints the current version of homesick' do it 'prints the current version of homesick' do
text = Capture.stdout { homesick.version } text = Capture.stdout { homesick.version }
expect(text.chomp).to match(/\d+\.\d+\.\d+/) expect(text.chomp).to match(/#{Regexp.escape(Homesick::Version::STRING)}/)
end end
end end
@@ -682,9 +735,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), .with(be_a(String), be_a(String), :green)
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
@@ -692,18 +743,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), .with(be_a(String), be_a(String), :green)
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, .with(:error, be_a(String), :red)
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
@@ -711,9 +758,7 @@ 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), .with(be_a(String), match(/.*Would execute.*/), :green)
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
@@ -723,7 +768,7 @@ 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
@@ -738,9 +783,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), .with(be_a(String), be_a(String), :green)
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
@@ -748,18 +791,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), .with(be_a(String), be_a(String), :green)
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, .with(:error, be_a(String), :red)
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
@@ -767,9 +806,7 @@ 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), .with(be_a(String), match(/.*Would execute.*/), :green)
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
@@ -779,7 +816,7 @@ 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

View File

@@ -5,7 +5,6 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require 'homesick' require 'homesick'
require 'rspec' require 'rspec'
require 'rspec/autorun'
require 'test_construct' require 'test_construct'
require 'tempfile' require 'tempfile'