33 Commits

Author SHA1 Message Date
muratayusuke
e07f3f0658 Regenerate gemspec for version 0.9.1 2013-06-17 12:36:14 +00:00
muratayusuke
b21aef09be bump up version 2013-06-17 12:35:39 +00:00
Yusuke Murata
d964e65a7e Merge pull request #40 from fnichol/fix-clone-destination
Remove .git suffix on destination directory if URL ends with it.
2013-06-17 04:47:20 -07:00
Fletcher Nichol
024856e538 Remove .git suffix on destination directory if URL ends with it.
For example, the following:

    homesick clone git://github.com/technicalpickles/pickled-vim.git

should produce a castle directory of:

    $HOME/.homesick/repos/pickled-vim
2013-06-16 10:47:53 -06:00
muratayusuke
e530df7239 fix #35 2013-06-09 23:10:21 +00:00
muratayusuke
e817c816c9 Regenerate gemspec for version 0.9.0 2013-06-06 12:59:00 +00:00
muratayusuke
14f0f8c121 bump up version and update changelog 2013-06-06 12:58:36 +00:00
Yusuke Murata
4c97948e04 Merge pull request #39 from technicalpickles/feature/merge_directory
Merge directories
2013-06-06 05:47:43 -07:00
muratayusuke
360e8185f7 move castle/home/.homesick_subdir to castle/.homesick_subdir 2013-06-06 12:39:41 +00:00
Yusuke Murata
da0958d455 fix typo 2013-06-06 21:19:21 +09:00
Yusuke Murata
70f5d24e0a fix style of README 2013-06-05 03:18:40 +09:00
Yusuke Murata
6b281ef001 fix style of README 2013-06-05 03:15:44 +09:00
muratayusuke
3ddd3207b3 add .homesick_subdir explanation to README 2013-06-04 18:14:20 +00:00
muratayusuke
8e58a3f5e2 deal with edge case: the parent and descendant are both listed in the manifest 2013-06-04 17:36:47 +00:00
muratayusuke
a95c4b2446 refactor symlink 2013-06-03 18:17:38 +00:00
muratayusuke
97fe1686f5 refactor given_castle 2013-05-30 17:38:06 +00:00
muratayusuke
76fcf5d0b7 add ruby-2.0.0 to travis 2013-05-30 14:33:45 +00:00
muratayusuke
bf1fc58e10 fix spec for ruby-1.8.7 2013-05-30 14:33:08 +00:00
muratayusuke
3559d825ca replace .manifest to .homesick_subdir 2013-05-27 18:08:09 +00:00
muratayusuke
2d54086d89 Merge remote-tracking branch 'edubkendo/nested_dirs' into feature/merge_directory 2013-05-27 16:13:31 +00:00
muratayusuke
c31c67a3eb support nested dir in .homesick_subdir 2013-05-26 17:12:28 +00:00
Eric West
e924cbefda refactor, cleanup and tweak 2013-05-24 21:57:12 -05:00
Eric West
6867ef78dc Handling edge cases
Covers only edge cases related to tracking, not yet
handling linking or updating. Getting a bit hairy,
must be refactored.
2013-05-24 16:24:42 -05:00
muratayusuke
a76d09d3f6 symlink subdirs with .homesick_subdir 2013-05-24 17:40:35 +00:00
Eric West
b93eea0e24 Track makes entries in .manifest
When a user tracks a file or directory that is in
a nested folder, Homesick creates a .manifest in the
user's castle (if there isn't one already) and adds
an entry listing the file or directory's parent
directory (if it isn't already listed).
2013-05-24 07:52:54 -05:00
Eric West
7332aa4acd Specs for track 2013-05-20 21:06:31 -05:00
Eric West
49e4d2844b Track now properly traverses folder structure 2013-05-20 19:11:48 -05:00
muratayusuke
236373b7d7 Regenerate gemspec for version 0.8.1 2013-05-19 13:42:49 +00:00
muratayusuke
21a9e4312d update changelog 2013-05-19 13:42:32 +00:00
muratayusuke
628d9bc0c1 update rake version
"rake spec" showed following warning
/home/muratayusuke/.rvm/gems/ruby-1.9.3-p392/gems/rake-0.8.7/lib/rake/alt_system.rb:32: Use RbConfig instead of obsolete and deprecated Config.
(in /mnt/projects/homesick)
/home/muratayusuke/.rvm/rubies/ruby-1.9.3-p392/bin/ruby -S rspec spec/homesick_spec.rb
so update rake version to fix it.
2013-05-19 13:37:54 +00:00
Yusuke Murata
caf5ca04f5 Merge pull request #37 from edubkendo/glob_fix
Fixes glob to work with 2.0.0
2013-05-18 01:15:56 -07:00
Eric West
7cbbf2bdd7 Fixes glob to work with 2.0.0
homesick list fails on ruby 2.0.0-rc2, I think because they fixed this
bug: https://bugs.ruby-lang.org/issues/6977, changing the way recursive
globs work. Test case:

```ruby
require "homesick"
require "pathname"

repos = Homesick.new.send :repos_dir

Dir.glob("#{repos}/**/*/.git") # => []

Dir.glob("#{repos}/**/*/.git", File::FNM_DOTMATCH) # => ["/home/eric/.homesick/repos/dotfiles/.git"]

```
This change, however, then broke 1.9.3, but removing the extra "/*"
works on both 1.9 and 2.0.
2013-05-17 02:37:44 -05:00
muratayusuke
9d6e77fd5a add build status to README 2013-04-06 03:23:40 +09:00
12 changed files with 415 additions and 60 deletions

4
.gitignore vendored
View File

@@ -39,3 +39,7 @@ pkg
# #
# For vim: # For vim:
*.swp *.swp
#
# For IDEA:
.idea/
*.iml

View File

@@ -1,4 +1,5 @@
language: ruby language: ruby
rvm: rvm:
- 2.0.0
- 1.9.3 - 1.9.3
- 1.8.7 - 1.8.7

View File

@@ -1,3 +1,12 @@
# 0.9.1
* Fixed small bugs: #35, #40
# 0.9.0
* Introduce .homesick_subdir #39
# 0.8.1
*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

View File

@@ -1,4 +1,4 @@
source :gemcutter source 'https://rubygems.org'
# 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"
@@ -6,7 +6,7 @@ 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 "rake", ">= 0.8.7"
gem "rspec", "~> 2.10" gem "rspec", "~> 2.10"
gem "jeweler", ">= 1.6.2" gem "jeweler", ">= 1.6.2"
gem "rcov", :platforms => :mri_18 gem "rcov", :platforms => :mri_18

View File

@@ -1,40 +1,40 @@
GEM GEM
remote: http://rubygems.org/ remote: https://rubygems.org/
specs: specs:
diff-lcs (1.1.3) diff-lcs (1.2.4)
git (1.2.5) git (1.2.5)
jeweler (1.8.3) jeweler (1.8.4)
bundler (~> 1.0) bundler (~> 1.0)
git (>= 1.2.5) git (>= 1.2.5)
rake rake
rdoc rdoc
json (1.7.3) json (1.8.0)
multi_json (1.3.6) multi_json (1.7.3)
rake (0.8.7) rake (10.0.4)
rcov (1.0.0) rcov (1.0.0)
rdoc (3.12) rdoc (4.0.1)
json (~> 1.4) json (~> 1.4)
rspec (2.10.0) rspec (2.13.0)
rspec-core (~> 2.10.0) rspec-core (~> 2.13.0)
rspec-expectations (~> 2.10.0) rspec-expectations (~> 2.13.0)
rspec-mocks (~> 2.10.0) rspec-mocks (~> 2.13.0)
rspec-core (2.10.1) rspec-core (2.13.1)
rspec-expectations (2.10.0) rspec-expectations (2.13.0)
diff-lcs (~> 1.1.3) diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.10.1) rspec-mocks (2.13.1)
simplecov (0.6.4) simplecov (0.7.1)
multi_json (~> 1.0) multi_json (~> 1.0)
simplecov-html (~> 0.5.3) simplecov-html (~> 0.7.1)
simplecov-html (0.5.3) simplecov-html (0.7.1)
test-construct (1.2.0) test-construct (1.2.0)
thor (0.15.2) thor (0.18.1)
PLATFORMS PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
jeweler (>= 1.6.2) jeweler (>= 1.6.2)
rake (~> 0.8.7) rake (>= 0.8.7)
rcov rcov
rspec (~> 2.10) rspec (~> 2.10)
simplecov simplecov

View File

@@ -1,5 +1,7 @@
# homesick # homesick
[![Build Status](https://travis-ci.org/technicalpickles/homesick.png?branch=master)](https://travis-ci.org/technicalpickles/homesick)
A man's home (directory) is his castle, so don't leave home with out it. A man's home (directory) is his castle, so don't leave home with out it.
Homesick is sorta like [rip](http://github.com/defunkt/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. Homesick is sorta like [rip](http://github.com/defunkt/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.
@@ -49,6 +51,84 @@ Not sure what else homesick has up its sleeve? There's always the built in help:
homesick help homesick help
## .homesick_subdir
`homesick symlink` basically makes symlink to only first depth in `castle/home`. If you want to link nested files/directories, please use .homesick_subdir.
For example, when you have castle like this:
castle/home
`-- .config
`-- fooapp
|-- config1
|-- config2
`-- config3
and have home like this:
$ tree -a
~
|-- .config
| `-- barapp
| |-- config1
| |-- config2
| `-- config3
`-- .emacs.d
|-- elisp
`-- inits
You may want to symlink only to `castle/home/.config/fooapp` instead of `castle/home/.config` because you already have `~/.config/barapp`. In this case, you can use .homesick_subdir. Please write "directories you want to look up sub direcoties (instead of just first depth)" in this file.
castle/home/.homesick_subdir
.config
and run `homesick symlink CASTLE`. The result is:
~
|-- .config
| |-- barapp
| | |-- config1
| | |-- config2
| | `-- config3
| `-- fooapp -> castle/home/.config/fooapp
`-- .emacs.d
|-- elisp
`-- inits
Or `homesick track NESTED_FILE CASTLE` adds a line automatically. For example:
homesick track .emacs.d/elisp castle
castle/home/.homesick_subdir
.config
.emacs.d
home directory
~
|-- .config
| |-- barapp
| | |-- config1
| | |-- config2
| | `-- config3
| `-- fooapp -> castle/home/.config/fooapp
`-- .emacs.d
|-- elisp -> castle/home/.emacs.d/elisp
`-- inits
and castle
castle/home
|-- .config
| `-- fooapp
| |-- config1
| |-- config2
| `-- config3
`-- .emacs.d
`-- elisp
## Note on Patches/Pull Requests ## Note on Patches/Pull Requests
* Fork the project. * Fork the project.

View File

@@ -22,7 +22,7 @@ Jeweler::Tasks.new do |gem|
gem.email = ["josh@technicalpickles.com", "info@muratayusuke.com"] gem.email = ["josh@technicalpickles.com", "info@muratayusuke.com"]
gem.homepage = "http://github.com/technicalpickles/homesick" gem.homepage = "http://github.com/technicalpickles/homesick"
gem.authors = ["Joshua Nichols", "Yusuke Murata"] gem.authors = ["Joshua Nichols", "Yusuke Murata"]
gem.version = "0.8.0" gem.version = "0.9.1"
gem.license = "MIT" gem.license = "MIT"
# Have dependencies? Add them to Gemfile # Have dependencies? Add them to Gemfile
@@ -44,7 +44,7 @@ end
task :default => :spec task :default => :spec
require 'rake/rdoctask' require 'rdoc/task'
Rake::RDocTask.new do |rdoc| Rake::RDocTask.new do |rdoc|
version = File.exist?('VERSION') ? File.read('VERSION') : "" version = File.exist?('VERSION') ? File.read('VERSION') : ""

View File

@@ -4,15 +4,20 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = "homesick" s.name = %q{homesick}
s.version = "0.8.0" s.version = "0.9.1"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Joshua Nichols", "Yusuke Murata"] s.authors = [%q{Joshua Nichols}, %q{Yusuke Murata}]
s.date = "2013-04-05" s.date = %q{2013-06-17}
s.description = "\n A man's home (directory) is his castle, so don't leave home with out it.\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 = %q{
s.email = ["josh@technicalpickles.com", "info@muratayusuke.com"] A man's home (directory) is his castle, so don't leave home with out it.
s.executables = ["homesick"]
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.
}
s.email = [%q{josh@technicalpickles.com}, %q{info@muratayusuke.com}]
s.executables = [%q{homesick}]
s.extra_rdoc_files = [ s.extra_rdoc_files = [
"ChangeLog.markdown", "ChangeLog.markdown",
"LICENSE", "LICENSE",
@@ -37,18 +42,18 @@ Gem::Specification.new do |s|
"spec/spec.opts", "spec/spec.opts",
"spec/spec_helper.rb" "spec/spec_helper.rb"
] ]
s.homepage = "http://github.com/technicalpickles/homesick" s.homepage = %q{http://github.com/technicalpickles/homesick}
s.licenses = ["MIT"] s.licenses = [%q{MIT}]
s.require_paths = ["lib"] s.require_paths = [%q{lib}]
s.rubygems_version = "1.8.24" s.rubygems_version = %q{1.8.5}
s.summary = "A man's home is his castle. Never leave your dotfiles behind." s.summary = %q{A man's home is his castle. Never leave your dotfiles behind.}
if s.respond_to? :specification_version then if s.respond_to? :specification_version then
s.specification_version = 3 s.specification_version = 3
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>, [">= 0.14.0"])
s.add_development_dependency(%q<rake>, ["~> 0.8.7"]) s.add_development_dependency(%q<rake>, [">= 0.8.7"])
s.add_development_dependency(%q<rspec>, ["~> 2.10"]) s.add_development_dependency(%q<rspec>, ["~> 2.10"])
s.add_development_dependency(%q<jeweler>, [">= 1.6.2"]) s.add_development_dependency(%q<jeweler>, [">= 1.6.2"])
s.add_development_dependency(%q<rcov>, [">= 0"]) s.add_development_dependency(%q<rcov>, [">= 0"])
@@ -56,7 +61,7 @@ Gem::Specification.new do |s|
s.add_development_dependency(%q<test-construct>, [">= 0"]) s.add_development_dependency(%q<test-construct>, [">= 0"])
else else
s.add_dependency(%q<thor>, [">= 0.14.0"]) s.add_dependency(%q<thor>, [">= 0.14.0"])
s.add_dependency(%q<rake>, ["~> 0.8.7"]) s.add_dependency(%q<rake>, [">= 0.8.7"])
s.add_dependency(%q<rspec>, ["~> 2.10"]) s.add_dependency(%q<rspec>, ["~> 2.10"])
s.add_dependency(%q<jeweler>, [">= 1.6.2"]) s.add_dependency(%q<jeweler>, [">= 1.6.2"])
s.add_dependency(%q<rcov>, [">= 0"]) s.add_dependency(%q<rcov>, [">= 0"])
@@ -65,7 +70,7 @@ Gem::Specification.new do |s|
end end
else else
s.add_dependency(%q<thor>, [">= 0.14.0"]) s.add_dependency(%q<thor>, [">= 0.14.0"])
s.add_dependency(%q<rake>, ["~> 0.8.7"]) s.add_dependency(%q<rake>, [">= 0.8.7"])
s.add_dependency(%q<rspec>, ["~> 2.10"]) s.add_dependency(%q<rspec>, ["~> 2.10"])
s.add_dependency(%q<jeweler>, [">= 1.6.2"]) s.add_dependency(%q<jeweler>, [">= 1.6.2"])
s.add_dependency(%q<rcov>, [">= 0"]) s.add_dependency(%q<rcov>, [">= 0"])

View File

@@ -10,6 +10,7 @@ class Homesick < Thor
add_runtime_options! add_runtime_options!
GITHUB_NAME_REPO_PATTERN = /\A([A-Za-z_-]+\/[A-Za-z_-]+)\Z/ GITHUB_NAME_REPO_PATTERN = /\A([A-Za-z_-]+\/[A-Za-z_-]+)\Z/
SUBDIR_FILENAME = ".homesick_subdir"
def initialize(args=[], options={}, config={}) def initialize(args=[], options={}, config={})
super super
@@ -96,15 +97,14 @@ class Homesick < Thor
check_castle_existance(name, "symlink") check_castle_existance(name, "symlink")
inside castle_dir(name) do inside castle_dir(name) do
files = Pathname.glob('{.*,*}').reject{|a| [".",".."].include?(a.to_s)} subdirs = subdirs(name)
files.each do |path|
absolute_path = path.expand_path
inside home_dir do # link files
adjusted_path = (home_dir + path).basename symlink_each(name, castle_dir(name), subdirs)
ln_s absolute_path, adjusted_path # link files in subdirs
end subdirs.each do |subdir|
symlink_each(name, subdir, subdirs)
end end
end end
end end
@@ -112,22 +112,46 @@ class Homesick < Thor
desc "track FILE CASTLE", "add a file to a castle" desc "track FILE CASTLE", "add a file to a castle"
def track(file, castle) def track(file, castle)
castle = Pathname.new(castle) castle = Pathname.new(castle)
file = Pathname.new(file) file = Pathname.new(file.chomp('/'))
check_castle_existance(castle, 'track') check_castle_existance(castle, 'track')
absolute_path = file.expand_path absolute_path = file.expand_path
castle_path = castle_dir(castle) relative_dir = absolute_path.relative_path_from(home_dir).dirname
castle_path = Pathname.new(castle_dir(castle)).join(relative_dir)
FileUtils.mkdir_p castle_path
# Are we already tracking this or anything inside it?
target = Pathname.new(castle_path.join(file.basename))
if target.exist?
if absolute_path.directory?
move_dir_contents(target, absolute_path)
absolute_path.rmtree
subdir_remove(castle, relative_dir + file.basename)
elsif more_recent? absolute_path, target
target.delete
mv absolute_path, castle_path mv absolute_path, castle_path
else
shell.say_status(:track, "#{target} already exists, and is more recent than #{file}. Run 'homesick SYMLINK CASTLE' to create symlinks.", :blue) unless options[:quiet]
end
else
mv absolute_path, castle_path
end
inside home_dir do inside home_dir do
absolute_path = castle_dir(castle) + file.basename absolute_path = castle_path + file.basename
home_path = home_dir + file home_path = home_dir + relative_dir + file.basename
ln_s absolute_path, home_path ln_s absolute_path, home_path
end end
inside castle_path do inside castle_path do
git_add absolute_path git_add absolute_path
end end
# are we tracking something nested? Add the parent dir to the manifest
unless relative_dir.eql?(Pathname.new('.'))
subdir_add(castle, relative_dir)
end
end end
desc "list", "List cloned castles" desc "list", "List cloned castles"
@@ -181,7 +205,7 @@ class Homesick < Thor
end end
def all_castles def all_castles
dirs = Pathname.glob("#{repos_dir}/**/*/.git") dirs = Pathname.glob("#{repos_dir}/**/.git", File::FNM_DOTMATCH)
# reject paths that lie inside another castle, like git submodules # reject paths that lie inside another castle, like git submodules
return dirs.reject do |dir| return dirs.reject do |dir|
dirs.any? {|other| dir != other && dir.fnmatch(other.parent.join('*').to_s) } dirs.any? {|other| dir != other && dir.fnmatch(other.parent.join('*').to_s) }
@@ -219,4 +243,99 @@ class Homesick < Thor
git_push git_push
end end
end end
def subdir_file(castle)
repos_dir.join(castle, SUBDIR_FILENAME)
end
def subdirs(castle)
subdir_filepath = subdir_file(castle)
subdirs = []
if subdir_filepath.exist?
subdir_filepath.readlines.each do |subdir|
subdirs.push(subdir.chomp)
end
end
subdirs
end
def subdir_add(castle, path)
subdir_filepath = subdir_file(castle)
File.open(subdir_filepath, 'a+') do |subdir|
subdir.puts path unless subdir.readlines.inject(false) { |memo, line| line.eql?("#{path.to_s}\n") || memo }
end
inside castle_dir(castle) do
git_add subdir_filepath
end
end
def subdir_remove(castle, path)
subdir_filepath = subdir_file(castle)
if subdir_filepath.exist?
lines = IO.readlines(subdir_filepath).delete_if { |line| line == "#{path}\n" }
File.open(subdir_filepath, 'w') { |manfile| manfile.puts lines }
end
inside castle_dir(castle) do
git_add subdir_filepath
end
end
def move_dir_contents(target, dir_path)
child_files = dir_path.children
child_files.each do |child|
target_path = target.join(child.basename)
if target_path.exist?
if more_recent?(child, target_path) && target.file?
target_path.delete
mv child, target
end
next
end
mv child, target
end
end
def more_recent?(first, second)
first_p = Pathname.new(first)
second_p = Pathname.new(second)
first_p.mtime > second_p.mtime && !first_p.symlink?
end
def symlink_each(castle, basedir, subdirs)
absolute_basedir = Pathname.new(basedir).expand_path
inside basedir do
files = Pathname.glob('{.*,*}').reject{|a| [".", ".."].include?(a.to_s)}
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)
ln_s absolute_path, home_path
end
end
end
end end

View File

@@ -3,10 +3,7 @@ class Homesick
# 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] || begin destination = config[:destination] || File.basename(repo, '.git')
repo =~ /([^\/]+)(?:\.git)?$/
$1
end
destination = Pathname.new(destination) unless destination.kind_of?(Pathname) destination = Pathname.new(destination) unless destination.kind_of?(Pathname)
FileUtils.mkdir_p destination.dirname FileUtils.mkdir_p destination.dirname
@@ -93,6 +90,7 @@ class Homesick
def ln_s(source, destination, config = {}) def ln_s(source, destination, config = {})
source = Pathname.new(source) source = Pathname.new(source)
destination = Pathname.new(destination) destination = Pathname.new(destination)
FileUtils.mkdir_p destination.dirname
if destination.symlink? if destination.symlink?
if destination.readlink == source if destination.readlink == source
@@ -108,6 +106,7 @@ class Homesick
say_status :conflict, "#{destination} exists", :red unless options[:quiet] say_status :conflict, "#{destination} exists", :red unless options[:quiet]
if options[:force] || shell.file_collision(destination) { source } if options[:force] || shell.file_collision(destination) { source }
system "rm -rf #{destination}" unless options[:pretend]
system "ln -sf #{source} #{destination}" unless options[:pretend] system "ln -sf #{source} #{destination}" unless options[:pretend]
end end
else else

View File

@@ -39,6 +39,14 @@ describe "homesick" do
end end
end end
it "should clone git repo like file:///path/to.git" do
bare_repo = File.join(create_construct.to_s, "dotfiles.git")
system "git init --bare #{bare_repo} >/dev/null 2>&1"
homesick.clone "file://#{bare_repo}"
File.directory?(File.join(home.to_s, '.homesick/repos/dotfiles')).should be_true
end
it "should clone git repo like git://host/path/to.git" do it "should clone git repo like git://host/path/to.git" do
homesick.should_receive(:git_clone).with('git://github.com/technicalpickles/pickled-vim.git') homesick.should_receive(:git_clone).with('git://github.com/technicalpickles/pickled-vim.git')
@@ -119,13 +127,71 @@ describe "homesick" do
existing_dotdir_link.readlink.should == dotdir existing_dotdir_link.readlink.should == dotdir
end end
it "can override existing directory" do
somewhere_else = create_construct
existing_dotdir = home.directory(".vim")
dotdir = castle.directory(".vim")
homesick.symlink("glencairn")
existing_dotdir.readlink.should == dotdir
end
end
context "with '.config' in .homesick_subdir" do
let(:castle) { given_castle("glencairn", [".config"]) }
it "can symlink in sub directory" do
dotdir = castle.directory(".config")
dotfile = dotdir.file(".some_dotfile")
homesick.symlink("glencairn")
home_dotdir = home.join(".config")
home_dotdir.symlink?.should == false
home_dotdir.join(".some_dotfile").readlink.should == dotfile
end
end
context "with '.config/appA' in .homesick_subdir" do
let(:castle) { given_castle("glencairn", [".config/appA"]) }
it "can symlink in nested sub directory" do
dotdir = castle.directory(".config").directory("appA")
dotfile = dotdir.file(".some_dotfile")
homesick.symlink("glencairn")
home_dotdir = home.join(".config").join("appA")
home_dotdir.symlink?.should == false
home_dotdir.join(".some_dotfile").readlink.should == dotfile
end
end
context "with '.config' and '.config/appA' in .homesick_subdir" do
let(:castle) { given_castle("glencairn", [".config", ".config/appA"]) }
it "can symlink under both of .config and .config/appA" do
config_dir = castle.directory(".config")
config_dotfile = config_dir.file(".some_dotfile")
appA_dir = config_dir.directory("appA")
appA_dotfile = appA_dir.file(".some_appfile")
homesick.symlink("glencairn")
home_config_dir = home.join(".config")
home_appA_dir = home_config_dir.join("appA")
home_config_dir.symlink?.should == false
home_config_dir.join(".some_dotfile").readlink.should == config_dotfile
home_appA_dir.symlink?.should == false
home_appA_dir.join(".some_appfile").readlink.should == appA_dotfile
end
end end
end end
describe "list" do describe "list" do
it "should say each castle in the castle directory" do it "should say each castle in the castle directory" do
given_castle('zomg') given_castle('zomg')
given_castle('zomg', 'wtf/zomg') given_castle('wtf/zomg')
homesick.should_receive(:say_status).with("zomg", "git://github.com/technicalpickles/zomg.git", :cyan) homesick.should_receive(:say_status).with("zomg", "git://github.com/technicalpickles/zomg.git", :cyan)
homesick.should_receive(:say_status).with("wtf/zomg", "git://github.com/technicalpickles/zomg.git", :cyan) homesick.should_receive(:say_status).with("wtf/zomg", "git://github.com/technicalpickles/zomg.git", :cyan)
@@ -169,5 +235,70 @@ describe "homesick" do
some_rc_file.readlink.should == tracked_file some_rc_file.readlink.should == tracked_file
end end
it 'should track a file in nested folder structure' do
castle = given_castle('castle_repo')
some_nested_file = home.file('some/nested/file.txt')
homesick.track(some_nested_file.to_s, 'castle_repo')
tracked_file = castle.join('some/nested/file.txt')
tracked_file.should exist
some_nested_file.readlink.should == tracked_file
end
it 'should track a nested directory' do
castle = given_castle('castle_repo')
some_nested_dir = home.directory('some/nested/directory/')
homesick.track(some_nested_dir.to_s, 'castle_repo')
tracked_file = castle.join('some/nested/directory/')
tracked_file.should exist
some_nested_dir.realpath.should == tracked_file.realpath
end
describe "subdir_file" do
it 'should add the nested files parent to the subdir_file' do
castle = given_castle('castle_repo')
some_nested_file = home.file('some/nested/file.txt')
homesick.track(some_nested_file.to_s, 'castle_repo')
subdir_file = castle.parent.join(Homesick::SUBDIR_FILENAME)
File.open(subdir_file, 'r') do |f|
f.readline.should == "some/nested\n"
end
end
it 'should NOT add anything if the files parent is already listed' do
castle = given_castle('castle_repo')
some_nested_file = home.file('some/nested/file.txt')
other_nested_file = home.file('some/nested/other.txt')
homesick.track(some_nested_file.to_s, 'castle_repo')
homesick.track(other_nested_file.to_s, 'castle_repo')
subdir_file = castle.parent.join(Homesick::SUBDIR_FILENAME)
File.open(subdir_file, 'r') do |f|
f.readlines.size.should == 1
end
end
it 'should remove the parent of a tracked file from the subdir_file if the parent itself is tracked' do
castle = given_castle('castle_repo')
some_nested_file = home.file('some/nested/file.txt')
nested_parent = home.directory('some/nested/')
homesick.track(some_nested_file.to_s, 'castle_repo')
homesick.track(nested_parent.to_s, 'castle_repo')
subdir_file = castle.parent.join(Homesick::SUBDIR_FILENAME)
File.open(subdir_file, 'r') do |f|
f.each_line { |line| line.should_not == "some/nested\n" }
end
end
end
end end
end end

View File

@@ -16,11 +16,18 @@ RSpec.configure do |config|
homesick.stub(:say_status) homesick.stub(:say_status)
end end
def given_castle(name, path=name) def given_castle(path, subdirs=[])
name = Pathname.new(path).basename
castles.directory(path) do |castle| castles.directory(path) do |castle|
Dir.chdir(castle) do Dir.chdir(castle) do
system "git init >/dev/null 2>&1" system "git init >/dev/null 2>&1"
system "git remote add origin git://github.com/technicalpickles/#{name}.git >/dev/null 2>&1" system "git remote add origin git://github.com/technicalpickles/#{name}.git >/dev/null 2>&1"
if subdirs then
subdir_file = castle.join(Homesick::SUBDIR_FILENAME)
subdirs.each do |subdir|
system "echo #{subdir} >> #{subdir_file}"
end
end
return castle.directory("home") return castle.directory("home")
end end
end end