homesick 1.1.5 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +9 -0
- data/.github/workflows/ci.yml +67 -0
- data/.github/workflows/mutant-nightly.yml +31 -0
- data/.github/workflows/release.yml +27 -0
- data/.gitignore +52 -0
- data/.mutant.yml +26 -0
- data/.rubocop.yml +37 -14
- data/ChangeLog.markdown +38 -6
- data/Gemfile +3 -34
- data/Gemfile.lock +128 -0
- data/Guardfile +6 -4
- data/README.markdown +10 -14
- data/Rakefile +8 -62
- data/bin/homesick +1 -0
- data/homesick.gemspec +28 -99
- data/lib/homesick/actions/file_actions.rb +31 -37
- data/lib/homesick/actions/git_actions.rb +18 -15
- data/lib/homesick/cli.rb +40 -62
- data/lib/homesick/rc.rb +30 -0
- data/lib/homesick/utils.rb +96 -54
- data/lib/homesick/version.rb +5 -4
- data/lib/homesick.rb +19 -1
- data/spec/homesick_cli_spec.rb +94 -33
- data/spec/homesick_rc_spec.rb +59 -0
- data/spec/spec_helper.rb +1 -2
- metadata +37 -120
- data/.travis.yml +0 -6
data/homesick.gemspec
CHANGED
|
@@ -1,105 +1,34 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: homesick 1.1.5 ruby lib
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/homesick/version'
|
|
6
4
|
|
|
7
5
|
Gem::Specification.new do |s|
|
|
8
|
-
s.name
|
|
9
|
-
s.version
|
|
6
|
+
s.name = 'homesick'
|
|
7
|
+
s.version = Homesick::Version::STRING
|
|
8
|
+
s.authors = ['Joshua Nichols', 'Yusuke Murata']
|
|
9
|
+
s.email = ['josh@technicalpickles.com', 'info@muratayusuke.com']
|
|
10
|
+
s.homepage = 'http://github.com/technicalpickles/homesick'
|
|
11
|
+
s.summary = "Your home directory is your castle. Don't leave your dotfiles behind."
|
|
12
|
+
s.description = 'Homesick is sorta like rip, but for dotfiles. It uses git to clone a ' \
|
|
13
|
+
'repository containing dotfiles, and saves them in ~/.homesick. It then ' \
|
|
14
|
+
'allows you to symlink all the dotfiles into place with a single command.'
|
|
15
|
+
s.license = 'MIT'
|
|
16
|
+
s.metadata = { 'rubygems_mfa_required' => 'true' }
|
|
10
17
|
|
|
11
|
-
s.
|
|
12
|
-
s.require_paths = ["lib".freeze]
|
|
13
|
-
s.authors = ["Joshua Nichols".freeze, "Yusuke Murata".freeze]
|
|
14
|
-
s.date = "2017-03-23"
|
|
15
|
-
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
|
|
16
|
-
s.email = ["josh@technicalpickles.com".freeze, "info@muratayusuke.com".freeze]
|
|
17
|
-
s.executables = ["homesick".freeze]
|
|
18
|
-
s.extra_rdoc_files = [
|
|
19
|
-
"ChangeLog.markdown",
|
|
20
|
-
"LICENSE",
|
|
21
|
-
"README.markdown"
|
|
22
|
-
]
|
|
23
|
-
s.files = [
|
|
24
|
-
".document",
|
|
25
|
-
".rspec",
|
|
26
|
-
".rubocop.yml",
|
|
27
|
-
".travis.yml",
|
|
28
|
-
"ChangeLog.markdown",
|
|
29
|
-
"Gemfile",
|
|
30
|
-
"Guardfile",
|
|
31
|
-
"LICENSE",
|
|
32
|
-
"README.markdown",
|
|
33
|
-
"Rakefile",
|
|
34
|
-
"bin/homesick",
|
|
35
|
-
"homesick.gemspec",
|
|
36
|
-
"lib/homesick.rb",
|
|
37
|
-
"lib/homesick/actions/file_actions.rb",
|
|
38
|
-
"lib/homesick/actions/git_actions.rb",
|
|
39
|
-
"lib/homesick/cli.rb",
|
|
40
|
-
"lib/homesick/utils.rb",
|
|
41
|
-
"lib/homesick/version.rb",
|
|
42
|
-
"spec/homesick_cli_spec.rb",
|
|
43
|
-
"spec/spec.opts",
|
|
44
|
-
"spec/spec_helper.rb"
|
|
45
|
-
]
|
|
46
|
-
s.homepage = "http://github.com/technicalpickles/homesick".freeze
|
|
47
|
-
s.licenses = ["MIT".freeze]
|
|
48
|
-
s.rubygems_version = "2.6.11".freeze
|
|
49
|
-
s.summary = "Your home directory is your castle. Don't leave your dotfiles behind.".freeze
|
|
18
|
+
s.required_ruby_version = '>= 3.2'
|
|
50
19
|
|
|
51
|
-
|
|
52
|
-
|
|
20
|
+
s.files = `git ls-files`.split("\n")
|
|
21
|
+
s.executables = ['homesick']
|
|
22
|
+
s.require_paths = ['lib']
|
|
53
23
|
|
|
54
|
-
|
|
55
|
-
s.add_runtime_dependency(%q<thor>.freeze, [">= 0.14.0"])
|
|
56
|
-
s.add_development_dependency(%q<capture-output>.freeze, ["~> 1.0.0"])
|
|
57
|
-
s.add_development_dependency(%q<coveralls>.freeze, [">= 0"])
|
|
58
|
-
s.add_development_dependency(%q<guard>.freeze, [">= 0"])
|
|
59
|
-
s.add_development_dependency(%q<guard-rspec>.freeze, [">= 0"])
|
|
60
|
-
s.add_development_dependency(%q<jeweler>.freeze, [">= 1.6.2"])
|
|
61
|
-
s.add_development_dependency(%q<rake>.freeze, [">= 0.8.7"])
|
|
62
|
-
s.add_development_dependency(%q<rb-readline>.freeze, ["~> 0.5.0"])
|
|
63
|
-
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
|
|
64
|
-
s.add_development_dependency(%q<rubocop>.freeze, [">= 0"])
|
|
65
|
-
s.add_development_dependency(%q<test_construct>.freeze, [">= 0"])
|
|
66
|
-
s.add_development_dependency(%q<libnotify>.freeze, [">= 0"])
|
|
67
|
-
s.add_development_dependency(%q<terminal-notifier-guard>.freeze, ["~> 1.7.0"])
|
|
68
|
-
s.add_development_dependency(%q<listen>.freeze, ["< 3"])
|
|
69
|
-
s.add_development_dependency(%q<rack>.freeze, ["< 2"])
|
|
70
|
-
else
|
|
71
|
-
s.add_dependency(%q<thor>.freeze, [">= 0.14.0"])
|
|
72
|
-
s.add_dependency(%q<capture-output>.freeze, ["~> 1.0.0"])
|
|
73
|
-
s.add_dependency(%q<coveralls>.freeze, [">= 0"])
|
|
74
|
-
s.add_dependency(%q<guard>.freeze, [">= 0"])
|
|
75
|
-
s.add_dependency(%q<guard-rspec>.freeze, [">= 0"])
|
|
76
|
-
s.add_dependency(%q<jeweler>.freeze, [">= 1.6.2"])
|
|
77
|
-
s.add_dependency(%q<rake>.freeze, [">= 0.8.7"])
|
|
78
|
-
s.add_dependency(%q<rb-readline>.freeze, ["~> 0.5.0"])
|
|
79
|
-
s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
|
|
80
|
-
s.add_dependency(%q<rubocop>.freeze, [">= 0"])
|
|
81
|
-
s.add_dependency(%q<test_construct>.freeze, [">= 0"])
|
|
82
|
-
s.add_dependency(%q<libnotify>.freeze, [">= 0"])
|
|
83
|
-
s.add_dependency(%q<terminal-notifier-guard>.freeze, ["~> 1.7.0"])
|
|
84
|
-
s.add_dependency(%q<listen>.freeze, ["< 3"])
|
|
85
|
-
s.add_dependency(%q<rack>.freeze, ["< 2"])
|
|
86
|
-
end
|
|
87
|
-
else
|
|
88
|
-
s.add_dependency(%q<thor>.freeze, [">= 0.14.0"])
|
|
89
|
-
s.add_dependency(%q<capture-output>.freeze, ["~> 1.0.0"])
|
|
90
|
-
s.add_dependency(%q<coveralls>.freeze, [">= 0"])
|
|
91
|
-
s.add_dependency(%q<guard>.freeze, [">= 0"])
|
|
92
|
-
s.add_dependency(%q<guard-rspec>.freeze, [">= 0"])
|
|
93
|
-
s.add_dependency(%q<jeweler>.freeze, [">= 1.6.2"])
|
|
94
|
-
s.add_dependency(%q<rake>.freeze, [">= 0.8.7"])
|
|
95
|
-
s.add_dependency(%q<rb-readline>.freeze, ["~> 0.5.0"])
|
|
96
|
-
s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
|
|
97
|
-
s.add_dependency(%q<rubocop>.freeze, [">= 0"])
|
|
98
|
-
s.add_dependency(%q<test_construct>.freeze, [">= 0"])
|
|
99
|
-
s.add_dependency(%q<libnotify>.freeze, [">= 0"])
|
|
100
|
-
s.add_dependency(%q<terminal-notifier-guard>.freeze, ["~> 1.7.0"])
|
|
101
|
-
s.add_dependency(%q<listen>.freeze, ["< 3"])
|
|
102
|
-
s.add_dependency(%q<rack>.freeze, ["< 2"])
|
|
103
|
-
end
|
|
104
|
-
end
|
|
24
|
+
s.add_dependency 'thor', '~> 1.0'
|
|
105
25
|
|
|
26
|
+
s.add_development_dependency 'bundler-audit', '~> 0.9'
|
|
27
|
+
s.add_development_dependency 'capture-output', '~> 1.0'
|
|
28
|
+
s.add_development_dependency 'mutant-rspec'
|
|
29
|
+
s.add_development_dependency 'rake'
|
|
30
|
+
s.add_development_dependency 'rspec', '~> 3.0'
|
|
31
|
+
s.add_development_dependency 'rubocop'
|
|
32
|
+
s.add_development_dependency 'rubocop-rake'
|
|
33
|
+
s.add_development_dependency 'test_construct'
|
|
34
|
+
end
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module Homesick
|
|
3
4
|
module Actions
|
|
4
5
|
# File-related helper methods for Homesick
|
|
5
6
|
module FileActions
|
|
7
|
+
protected
|
|
8
|
+
|
|
6
9
|
def mv(source, destination)
|
|
7
10
|
source = Pathname.new(source)
|
|
8
11
|
destination = Pathname.new(destination + source.basename)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
FileUtils.mv source, destination unless options[:pretend]
|
|
13
|
-
else
|
|
14
|
-
FileUtils.mv source, destination unless options[:pretend]
|
|
15
|
-
end
|
|
12
|
+
collision = destination.exist? && (options[:force] || shell.file_collision(destination) { source })
|
|
13
|
+
say_status :conflict, "#{destination} exists", :red if collision
|
|
14
|
+
FileUtils.mv source, destination unless options[:pretend]
|
|
16
15
|
end
|
|
17
16
|
|
|
18
17
|
def rm_rf(dir)
|
|
@@ -24,7 +23,7 @@ module Homesick
|
|
|
24
23
|
target = Pathname.new(target)
|
|
25
24
|
|
|
26
25
|
if target.symlink?
|
|
27
|
-
say_status :unlink,
|
|
26
|
+
say_status :unlink, target.expand_path.to_s, :green
|
|
28
27
|
FileUtils.rm_rf target
|
|
29
28
|
else
|
|
30
29
|
say_status :conflict, "#{target} is not a symlink", :red
|
|
@@ -42,45 +41,40 @@ module Homesick
|
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
def ln_s(source, destination)
|
|
45
|
-
source = Pathname.new(source).realpath
|
|
44
|
+
source = Pathname.new(source).realpath
|
|
46
45
|
destination = Pathname.new(destination)
|
|
47
46
|
FileUtils.mkdir_p destination.dirname
|
|
48
47
|
|
|
49
|
-
action =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
elsif destination.exist?
|
|
54
|
-
:conflict
|
|
55
|
-
else
|
|
56
|
-
:success
|
|
57
|
-
end
|
|
48
|
+
action = :success
|
|
49
|
+
action = :identical if destination.symlink? && destination.readlink == source
|
|
50
|
+
action = :symlink_conflict if destination.symlink?
|
|
51
|
+
action = :conflict if destination.exist?
|
|
58
52
|
|
|
59
53
|
handle_symlink_action action, source, destination
|
|
60
54
|
end
|
|
61
55
|
|
|
62
56
|
def handle_symlink_action(action, source, destination)
|
|
63
|
-
|
|
64
|
-
when :identical
|
|
57
|
+
if action == :identical
|
|
65
58
|
say_status :identical, destination.expand_path, :blue
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if collision_accepted?(destination, source)
|
|
75
|
-
FileUtils.rm_r destination, force: true unless options[:pretend]
|
|
76
|
-
FileUtils.ln_s source, destination, force: true unless options[:pretend]
|
|
77
|
-
end
|
|
59
|
+
return
|
|
60
|
+
end
|
|
61
|
+
message = generate_symlink_message action, source, destination
|
|
62
|
+
if %i[symlink_conflict conflict].include?(action)
|
|
63
|
+
say_status :conflict, message, :red
|
|
64
|
+
return unless collision_accepted?(destination, source)
|
|
65
|
+
|
|
66
|
+
FileUtils.rm_r destination, force: true unless options[:pretend]
|
|
78
67
|
else
|
|
79
|
-
say_status :symlink,
|
|
80
|
-
"#{source.expand_path} to #{destination.expand_path}",
|
|
81
|
-
:green
|
|
82
|
-
FileUtils.ln_s source, destination unless options[:pretend]
|
|
68
|
+
say_status :symlink, message, :green
|
|
83
69
|
end
|
|
70
|
+
FileUtils.ln_s source, destination, force: true unless options[:pretend]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def generate_symlink_message(action, source, destination)
|
|
74
|
+
message = "#{source.expand_path} to #{destination.expand_path}"
|
|
75
|
+
message = "#{destination} exists and points to #{destination.readlink}" if action == :symlink_conflict
|
|
76
|
+
message = "#{destination} exists" if action == :conflict
|
|
77
|
+
message
|
|
84
78
|
end
|
|
85
79
|
end
|
|
86
80
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module Homesick
|
|
3
4
|
module Actions
|
|
4
5
|
# Git-related helper methods for Homesick
|
|
@@ -8,35 +9,37 @@ module Homesick
|
|
|
8
9
|
major: 1,
|
|
9
10
|
minor: 8,
|
|
10
11
|
patch: 0
|
|
11
|
-
}
|
|
12
|
+
}.freeze
|
|
12
13
|
STRING = MIN_VERSION.values.join('.')
|
|
13
14
|
|
|
14
15
|
def git_version_correct?
|
|
15
16
|
info = `git --version`.scan(/(\d+)\.(\d+)\.(\d+)/).flatten.map(&:to_i)
|
|
16
17
|
return false unless info.count == 3
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
|
|
19
|
+
current_version = %i[major minor patch].zip(info).to_h
|
|
20
|
+
major_equals = current_version.eql?(MIN_VERSION)
|
|
21
|
+
major_greater = current_version[:major] > MIN_VERSION[:major]
|
|
22
|
+
minor_greater = current_version[:major] == MIN_VERSION[:major] &&
|
|
23
|
+
current_version[:minor] > MIN_VERSION[:minor]
|
|
24
|
+
patch_greater = current_version[:major] == MIN_VERSION[:major] &&
|
|
25
|
+
current_version[:minor] == MIN_VERSION[:minor] &&
|
|
26
|
+
current_version[:patch] >= MIN_VERSION[:patch]
|
|
27
|
+
|
|
28
|
+
major_equals || major_greater || minor_greater || patch_greater
|
|
23
29
|
end
|
|
24
30
|
|
|
25
|
-
# TODO: move this to be more like thor's template, empty_directory, etc
|
|
26
31
|
def git_clone(repo, config = {})
|
|
27
|
-
config ||= {}
|
|
28
32
|
destination = config[:destination] || File.basename(repo, '.git')
|
|
29
|
-
|
|
30
33
|
destination = Pathname.new(destination) unless destination.is_a?(Pathname)
|
|
31
34
|
FileUtils.mkdir_p destination.dirname
|
|
32
35
|
|
|
33
36
|
if destination.directory?
|
|
34
37
|
say_status :exist, destination.expand_path, :blue
|
|
35
38
|
else
|
|
36
|
-
say_status 'git clone',
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
say_status 'git clone', "#{repo} to #{destination.expand_path}", :green
|
|
40
|
+
unless options[:pretend]
|
|
41
|
+
system "git clone -q --config push.default=upstream --recursive #{repo} #{destination}"
|
|
42
|
+
end
|
|
40
43
|
end
|
|
41
44
|
end
|
|
42
45
|
|
data/lib/homesick/cli.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
2
4
|
require 'thor'
|
|
3
5
|
|
|
4
6
|
module Homesick
|
|
@@ -12,6 +14,10 @@ module Homesick
|
|
|
12
14
|
|
|
13
15
|
add_runtime_options!
|
|
14
16
|
|
|
17
|
+
def self.exit_on_failure?
|
|
18
|
+
true
|
|
19
|
+
end
|
|
20
|
+
|
|
15
21
|
map '-v' => :version
|
|
16
22
|
map '--version' => :version
|
|
17
23
|
# Retain a mapped version of the symlink command for compatibility.
|
|
@@ -21,45 +27,20 @@ module Homesick
|
|
|
21
27
|
super
|
|
22
28
|
# Check if git is installed
|
|
23
29
|
unless git_version_correct?
|
|
24
|
-
say_status :error,
|
|
30
|
+
say_status :error,
|
|
31
|
+
"Git version >= #{Homesick::Actions::GitActions::STRING} must be installed to use Homesick",
|
|
32
|
+
:red
|
|
25
33
|
exit(1)
|
|
26
34
|
end
|
|
27
|
-
|
|
28
|
-
# Also adds support for checking if destination or content is a directory
|
|
29
|
-
shell_metaclass = class << shell; self; end
|
|
30
|
-
shell_metaclass.send(:define_method, :show_diff) do |destination, content|
|
|
31
|
-
destination = Pathname.new(destination)
|
|
32
|
-
content = Pathname.new(content)
|
|
33
|
-
return 'Unable to create diff: destination or content is a directory' if destination.directory? || content.directory?
|
|
34
|
-
return super(destination, content) unless destination.symlink?
|
|
35
|
-
say "- #{destination.readlink}", :red, true
|
|
36
|
-
say "+ #{content.expand_path}", :green, true
|
|
37
|
-
end
|
|
35
|
+
configure_symlinks_diff
|
|
38
36
|
end
|
|
39
37
|
|
|
40
38
|
desc 'clone URI CASTLE_NAME', 'Clone +uri+ as a castle with name CASTLE_NAME for homesick'
|
|
41
|
-
def clone(uri, destination=nil)
|
|
39
|
+
def clone(uri, destination = nil)
|
|
42
40
|
destination = Pathname.new(destination) unless destination.nil?
|
|
43
41
|
|
|
44
42
|
inside repos_dir do
|
|
45
|
-
|
|
46
|
-
uri = Pathname.new(uri).expand_path
|
|
47
|
-
fail "Castle already cloned to #{uri}" if uri.to_s.start_with?(repos_dir.to_s)
|
|
48
|
-
|
|
49
|
-
destination = uri.basename if destination.nil?
|
|
50
|
-
|
|
51
|
-
ln_s uri, destination
|
|
52
|
-
elsif uri =~ GITHUB_NAME_REPO_PATTERN
|
|
53
|
-
destination = Pathname.new(uri).basename if destination.nil?
|
|
54
|
-
git_clone "https://github.com/#{Regexp.last_match[1]}.git",
|
|
55
|
-
destination: destination
|
|
56
|
-
elsif uri =~ /%r([^%r]*?)(\.git)?\Z/ || uri =~ /[^:]+:([^:]+)(\.git)?\Z/
|
|
57
|
-
destination = Pathname.new(Regexp.last_match[1].gsub(/\.git$/, '')).basename if destination.nil?
|
|
58
|
-
git_clone uri, destination: destination
|
|
59
|
-
else
|
|
60
|
-
fail "Unknown URI format: #{uri}"
|
|
61
|
-
end
|
|
62
|
-
|
|
43
|
+
destination = clone_from_uri(uri, destination)
|
|
63
44
|
setup_castle(destination)
|
|
64
45
|
end
|
|
65
46
|
end
|
|
@@ -74,11 +55,19 @@ module Homesick
|
|
|
74
55
|
destination = Pathname.new(name)
|
|
75
56
|
homesickrc = destination.join('.homesickrc').expand_path
|
|
76
57
|
return unless homesickrc.exist?
|
|
77
|
-
|
|
78
|
-
|
|
58
|
+
|
|
59
|
+
proceed = options[:force] ||
|
|
60
|
+
shell.yes?("#{name} has a .homesickrc. Proceed with evaling it? (This could be destructive)")
|
|
61
|
+
unless proceed
|
|
62
|
+
return say_status 'eval skip',
|
|
63
|
+
"not evaling #{homesickrc}, #{destination} may need manual configuration",
|
|
64
|
+
:blue
|
|
65
|
+
end
|
|
66
|
+
|
|
79
67
|
say_status 'eval', homesickrc
|
|
80
68
|
inside destination do
|
|
81
|
-
|
|
69
|
+
ctx = Homesick::RC::Context.new(destination.expand_path)
|
|
70
|
+
ctx.instance_eval(homesickrc.read, homesickrc.expand_path.to_s)
|
|
82
71
|
end
|
|
83
72
|
end
|
|
84
73
|
end
|
|
@@ -92,7 +81,7 @@ module Homesick
|
|
|
92
81
|
def pull(name = DEFAULT_CASTLE_NAME)
|
|
93
82
|
if options[:all]
|
|
94
83
|
inside_each_castle do |castle|
|
|
95
|
-
say castle.to_s.gsub(repos_dir
|
|
84
|
+
say "#{castle.to_s.gsub("#{repos_dir}/", '')}:"
|
|
96
85
|
update_castle castle
|
|
97
86
|
end
|
|
98
87
|
else
|
|
@@ -135,11 +124,12 @@ module Homesick
|
|
|
135
124
|
def link(name = DEFAULT_CASTLE_NAME)
|
|
136
125
|
check_castle_existance(name, 'symlink')
|
|
137
126
|
|
|
138
|
-
|
|
127
|
+
castle_path = castle_dir(name)
|
|
128
|
+
inside castle_path do
|
|
139
129
|
subdirs = subdirs(name)
|
|
140
130
|
|
|
141
131
|
# link files
|
|
142
|
-
symlink_each(name,
|
|
132
|
+
symlink_each(name, castle_path, subdirs)
|
|
143
133
|
|
|
144
134
|
# link files in subdirs
|
|
145
135
|
subdirs.each do |subdir|
|
|
@@ -159,22 +149,9 @@ module Homesick
|
|
|
159
149
|
castle_path = Pathname.new(castle_dir(castle)).join(relative_dir)
|
|
160
150
|
FileUtils.mkdir_p castle_path
|
|
161
151
|
|
|
162
|
-
# Are we already tracking this or anything inside it?
|
|
163
152
|
target = Pathname.new(castle_path.join(file.basename))
|
|
164
153
|
if target.exist?
|
|
165
|
-
|
|
166
|
-
move_dir_contents(target, absolute_path)
|
|
167
|
-
absolute_path.rmtree
|
|
168
|
-
subdir_remove(castle, relative_dir + file.basename)
|
|
169
|
-
|
|
170
|
-
elsif more_recent? absolute_path, target
|
|
171
|
-
target.delete
|
|
172
|
-
mv absolute_path, castle_path
|
|
173
|
-
else
|
|
174
|
-
say_status(:track,
|
|
175
|
-
"#{target} already exists, and is more recent than #{file}. Run 'homesick SYMLINK CASTLE' to create symlinks.",
|
|
176
|
-
:blue)
|
|
177
|
-
end
|
|
154
|
+
handle_existing_track_target(castle, absolute_path, castle_path, relative_dir, file, target)
|
|
178
155
|
else
|
|
179
156
|
mv absolute_path, castle_path
|
|
180
157
|
end
|
|
@@ -189,7 +166,6 @@ module Homesick
|
|
|
189
166
|
git_add absolute_path
|
|
190
167
|
end
|
|
191
168
|
|
|
192
|
-
# are we tracking something nested? Add the parent dir to the manifest
|
|
193
169
|
subdir_add(castle, relative_dir) unless relative_dir.eql?(Pathname.new('.'))
|
|
194
170
|
end
|
|
195
171
|
|
|
@@ -261,14 +237,14 @@ module Homesick
|
|
|
261
237
|
"Opening a new shell in castle '#{castle}'. To return to the original one exit from the new shell.",
|
|
262
238
|
:green
|
|
263
239
|
inside castle_dir do
|
|
264
|
-
system(ENV
|
|
240
|
+
system(ENV.fetch('SHELL', nil))
|
|
265
241
|
end
|
|
266
242
|
end
|
|
267
243
|
|
|
268
244
|
desc 'open CASTLE',
|
|
269
245
|
'Open your default editor in the root of the given castle'
|
|
270
246
|
def open(castle = DEFAULT_CASTLE_NAME)
|
|
271
|
-
unless ENV
|
|
247
|
+
unless ENV.fetch('EDITOR', nil)
|
|
272
248
|
say_status :error,
|
|
273
249
|
'The $EDITOR environment variable must be set to use this command',
|
|
274
250
|
:red
|
|
@@ -277,11 +253,11 @@ module Homesick
|
|
|
277
253
|
end
|
|
278
254
|
check_castle_existance castle, 'open'
|
|
279
255
|
castle_dir = repos_dir.join(castle)
|
|
280
|
-
say_status "#{castle_dir.realpath}: #{ENV
|
|
281
|
-
"Opening the root directory of castle '#{castle}' in editor '#{ENV
|
|
256
|
+
say_status "#{castle_dir.realpath}: #{ENV.fetch('EDITOR', nil)} .",
|
|
257
|
+
"Opening the root directory of castle '#{castle}' in editor '#{ENV.fetch('EDITOR', nil)}'.",
|
|
282
258
|
:green
|
|
283
259
|
inside castle_dir do
|
|
284
|
-
system("#{ENV
|
|
260
|
+
system("#{ENV.fetch('EDITOR', nil)} .")
|
|
285
261
|
end
|
|
286
262
|
end
|
|
287
263
|
|
|
@@ -289,15 +265,16 @@ module Homesick
|
|
|
289
265
|
'Execute a single shell command inside the root of a castle'
|
|
290
266
|
def exec(castle, *args)
|
|
291
267
|
check_castle_existance castle, 'exec'
|
|
292
|
-
unless args.
|
|
268
|
+
unless args.any?
|
|
293
269
|
say_status :error,
|
|
294
270
|
'You must pass a shell command to execute',
|
|
295
271
|
:red
|
|
296
272
|
exit(1)
|
|
297
273
|
end
|
|
298
274
|
full_command = args.join(' ')
|
|
275
|
+
action = options[:pretend] ? 'Would execute' : 'Executing command'
|
|
299
276
|
say_status "exec '#{full_command}'",
|
|
300
|
-
"#{
|
|
277
|
+
"#{action} '#{full_command}' in castle '#{castle}'",
|
|
301
278
|
:green
|
|
302
279
|
inside repos_dir.join(castle) do
|
|
303
280
|
system(full_command)
|
|
@@ -307,7 +284,7 @@ module Homesick
|
|
|
307
284
|
desc 'exec_all COMMAND',
|
|
308
285
|
'Execute a single shell command inside the root of every cloned castle'
|
|
309
286
|
def exec_all(*args)
|
|
310
|
-
unless args.
|
|
287
|
+
unless args.any?
|
|
311
288
|
say_status :error,
|
|
312
289
|
'You must pass a shell command to execute',
|
|
313
290
|
:red
|
|
@@ -315,8 +292,9 @@ module Homesick
|
|
|
315
292
|
end
|
|
316
293
|
full_command = args.join(' ')
|
|
317
294
|
inside_each_castle do |castle|
|
|
295
|
+
action = options[:pretend] ? 'Would execute' : 'Executing command'
|
|
318
296
|
say_status "exec '#{full_command}'",
|
|
319
|
-
"#{
|
|
297
|
+
"#{action} '#{full_command}' in castle '#{castle}'",
|
|
320
298
|
:green
|
|
321
299
|
system(full_command)
|
|
322
300
|
end
|
data/lib/homesick/rc.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pathname'
|
|
4
|
+
|
|
5
|
+
module Homesick
|
|
6
|
+
module RC
|
|
7
|
+
# Evaluation context for .homesickrc scripts.
|
|
8
|
+
#
|
|
9
|
+
# Runs castle setup scripts in a clean object rather than in the
|
|
10
|
+
# Homesick::CLI binding, so scripts cannot access CLI internals.
|
|
11
|
+
# Standard Ruby library methods (File, Dir, system, etc.) remain
|
|
12
|
+
# available to scripts.
|
|
13
|
+
class Context
|
|
14
|
+
# @param castle_path [Pathname, String] absolute path to the castle root
|
|
15
|
+
def initialize(castle_path)
|
|
16
|
+
@castle_path = Pathname.new(castle_path)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The absolute path of the castle being configured.
|
|
20
|
+
attr_reader :castle_path
|
|
21
|
+
|
|
22
|
+
# Execute a shell command.
|
|
23
|
+
# @param command [String]
|
|
24
|
+
# @return [Boolean] true if the command succeeded
|
|
25
|
+
def run(command)
|
|
26
|
+
system(command)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|