rubycut-babushka 0.10.6
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.
- data/Gemfile +8 -0
- data/Gemfile.lock +31 -0
- data/README.markdown +246 -0
- data/Rakefile +26 -0
- data/bin/babushka +11 -0
- data/deps/babushka.rb +101 -0
- data/deps/dev.rb +12 -0
- data/deps/fhs.rb +31 -0
- data/deps/git.rb +29 -0
- data/deps/homebrew.rb +30 -0
- data/deps/os_x.rb +33 -0
- data/deps/packages.rb +22 -0
- data/deps/pkg_managers.rb +110 -0
- data/deps/ruby.rb +23 -0
- data/deps/rubygems.rb +24 -0
- data/deps/system.rb +10 -0
- data/deps/templates/app.rb +68 -0
- data/deps/templates/external.rb +12 -0
- data/deps/templates/installer.rb +31 -0
- data/deps/templates/managed.rb +105 -0
- data/deps/templates/ppa.rb +24 -0
- data/deps/templates/src.rb +42 -0
- data/deps/templates/tmbundle.rb +15 -0
- data/lib/babushka.rb +28 -0
- data/lib/babushka/accepts_block_for.rb +72 -0
- data/lib/babushka/accepts_list_for.rb +49 -0
- data/lib/babushka/accepts_value_for.rb +24 -0
- data/lib/babushka/base.rb +78 -0
- data/lib/babushka/bug_reporter.rb +55 -0
- data/lib/babushka/cmdline.rb +133 -0
- data/lib/babushka/cmdline/handler.rb +41 -0
- data/lib/babushka/cmdline/helpers.rb +127 -0
- data/lib/babushka/cmdline/parser.rb +69 -0
- data/lib/babushka/colorizer.rb +59 -0
- data/lib/babushka/core_patches/array.rb +171 -0
- data/lib/babushka/core_patches/blank.rb +22 -0
- data/lib/babushka/core_patches/bytes.rb +52 -0
- data/lib/babushka/core_patches/hash.rb +107 -0
- data/lib/babushka/core_patches/hashish.rb +14 -0
- data/lib/babushka/core_patches/integer.rb +25 -0
- data/lib/babushka/core_patches/io.rb +8 -0
- data/lib/babushka/core_patches/numeric.rb +16 -0
- data/lib/babushka/core_patches/object.rb +27 -0
- data/lib/babushka/core_patches/string.rb +116 -0
- data/lib/babushka/core_patches/symbol.rb +12 -0
- data/lib/babushka/core_patches/try.rb +15 -0
- data/lib/babushka/core_patches/uri.rb +24 -0
- data/lib/babushka/dep.rb +470 -0
- data/lib/babushka/dep_context.rb +18 -0
- data/lib/babushka/dep_definer.rb +115 -0
- data/lib/babushka/dep_pool.rb +49 -0
- data/lib/babushka/dep_runner.rb +85 -0
- data/lib/babushka/dsl.rb +26 -0
- data/lib/babushka/git_repo.rb +185 -0
- data/lib/babushka/helpers/git_helpers.rb +32 -0
- data/lib/babushka/helpers/log_helpers.rb +176 -0
- data/lib/babushka/helpers/path_helpers.rb +34 -0
- data/lib/babushka/helpers/run_helpers.rb +145 -0
- data/lib/babushka/helpers/shell_helpers.rb +229 -0
- data/lib/babushka/helpers/suggest_helpers.rb +16 -0
- data/lib/babushka/helpers/uri_helpers.rb +36 -0
- data/lib/babushka/ip.rb +160 -0
- data/lib/babushka/lambda_chooser.rb +40 -0
- data/lib/babushka/levenshtein.rb +125 -0
- data/lib/babushka/meta_dep.rb +65 -0
- data/lib/babushka/meta_dep_context.rb +15 -0
- data/lib/babushka/parameter.rb +143 -0
- data/lib/babushka/pkg_helper.rb +81 -0
- data/lib/babushka/pkg_helpers/apt_helper.rb +61 -0
- data/lib/babushka/pkg_helpers/base_helper.rb +19 -0
- data/lib/babushka/pkg_helpers/binpkgsrc_helper.rb +48 -0
- data/lib/babushka/pkg_helpers/binports_helper.rb +34 -0
- data/lib/babushka/pkg_helpers/brew_helper.rb +110 -0
- data/lib/babushka/pkg_helpers/gem_helper.rb +120 -0
- data/lib/babushka/pkg_helpers/macports_helper.rb +22 -0
- data/lib/babushka/pkg_helpers/npm_helper.rb +45 -0
- data/lib/babushka/pkg_helpers/pacman_helper.rb +27 -0
- data/lib/babushka/pkg_helpers/pip_helper.rb +45 -0
- data/lib/babushka/pkg_helpers/src_helper.rb +16 -0
- data/lib/babushka/pkg_helpers/yum_helper.rb +25 -0
- data/lib/babushka/popen.rb +40 -0
- data/lib/babushka/prompt.rb +176 -0
- data/lib/babushka/renderable.rb +67 -0
- data/lib/babushka/resource.rb +215 -0
- data/lib/babushka/run_reporter.rb +60 -0
- data/lib/babushka/shell.rb +108 -0
- data/lib/babushka/source.rb +216 -0
- data/lib/babushka/source_pool.rb +146 -0
- data/lib/babushka/system_definitions.rb +97 -0
- data/lib/babushka/system_profile.rb +210 -0
- data/lib/babushka/task.rb +142 -0
- data/lib/babushka/vars.rb +108 -0
- data/lib/babushka/version_of.rb +65 -0
- data/lib/babushka/version_str.rb +57 -0
- data/lib/babushka/xml_string.rb +28 -0
- data/lib/components.rb +82 -0
- data/lib/fancypath/fancypath.rb +200 -0
- data/lib/inkan/inkan.rb +76 -0
- data/spec/acceptance/acceptance.rb +43 -0
- data/spec/acceptance_helper.rb +113 -0
- data/spec/archives/Blah.app.zip +0 -0
- data/spec/archives/archive.tar +0 -0
- data/spec/archives/archive.tar.bz2 +0 -0
- data/spec/archives/archive.tar.gz +0 -0
- data/spec/archives/archive.tbz2 +0 -0
- data/spec/archives/archive.tgz +0 -0
- data/spec/archives/archive.zip +0 -0
- data/spec/archives/content.txt +5 -0
- data/spec/archives/invalid_archive +5 -0
- data/spec/archives/nested archive/content.txt +5 -0
- data/spec/archives/nested_archive.tar +0 -0
- data/spec/archives/really_a_gzip.zip +0 -0
- data/spec/archives/test-0.3.1.tgz +0 -0
- data/spec/archives/tgz_archive +0 -0
- data/spec/archives/zip_without_extension +0 -0
- data/spec/babushka/accepts_for_spec.rb +174 -0
- data/spec/babushka/accepts_for_support.rb +72 -0
- data/spec/babushka/cmdline/console_spec.rb +11 -0
- data/spec/babushka/cmdline/help_spec.rb +61 -0
- data/spec/babushka/cmdline/version_spec.rb +10 -0
- data/spec/babushka/core_patches_spec.rb +171 -0
- data/spec/babushka/dep_context_spec.rb +58 -0
- data/spec/babushka/dep_definer_spec.rb +152 -0
- data/spec/babushka/dep_definer_support.rb +36 -0
- data/spec/babushka/dep_spec.rb +567 -0
- data/spec/babushka/dep_support.rb +29 -0
- data/spec/babushka/deps_spec.rb +113 -0
- data/spec/babushka/gem_helper_spec.rb +90 -0
- data/spec/babushka/git_repo_spec.rb +396 -0
- data/spec/babushka/ip_spec.rb +131 -0
- data/spec/babushka/lambda_chooser_spec.rb +115 -0
- data/spec/babushka/meta_dep_definer_spec.rb +127 -0
- data/spec/babushka/meta_dep_wrapper_spec.rb +32 -0
- data/spec/babushka/parameter_spec.rb +135 -0
- data/spec/babushka/path_helpers_spec.rb +102 -0
- data/spec/babushka/prompt_spec.rb +188 -0
- data/spec/babushka/renderable_spec.rb +100 -0
- data/spec/babushka/resource_spec.rb +141 -0
- data/spec/babushka/run_helpers_spec.rb +26 -0
- data/spec/babushka/shell_helpers_spec.rb +244 -0
- data/spec/babushka/shell_spec.rb +19 -0
- data/spec/babushka/source_pool_spec.rb +320 -0
- data/spec/babushka/source_pool_support.rb +31 -0
- data/spec/babushka/source_spec.rb +382 -0
- data/spec/babushka/source_support.rb +17 -0
- data/spec/babushka/system_profile_spec.rb +61 -0
- data/spec/babushka/task_spec.rb +141 -0
- data/spec/babushka/uri_spec.rb +13 -0
- data/spec/babushka/vars_spec.rb +59 -0
- data/spec/babushka/version_of_spec.rb +110 -0
- data/spec/babushka/version_str_spec.rb +130 -0
- data/spec/babushka/version_str_support.rb +37 -0
- data/spec/babushka/xml_string_spec.rb +98 -0
- data/spec/deps/bad/broken.rb +7 -0
- data/spec/deps/bad/working.rb +3 -0
- data/spec/deps/good/meta.rb +14 -0
- data/spec/deps/good/test.rb +11 -0
- data/spec/deps/outer/deps.rb +19 -0
- data/spec/deps/outer/more deps.rb +11 -0
- data/spec/deps/params/params.rb +10 -0
- data/spec/fancypath/fancypath_spec.rb +272 -0
- data/spec/fancypath_support.rb +10 -0
- data/spec/inkan/inkan_spec.rb +217 -0
- data/spec/renderable/different_example.conf.erb +4 -0
- data/spec/renderable/example.conf.erb +3 -0
- data/spec/renderable/example.sh +6 -0
- data/spec/renderable/with_binding.conf.erb +4 -0
- data/spec/renderable/xml_example.conf.erb +8 -0
- data/spec/repos/remote.git.tgz +0 -0
- data/spec/spec_helper.rb +87 -0
- metadata +238 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class DepContext < DepDefiner
|
|
3
|
+
include DepRunner
|
|
4
|
+
|
|
5
|
+
accepts_list_for :desc
|
|
6
|
+
accepts_list_for :requires
|
|
7
|
+
accepts_list_for :requires_when_unmet
|
|
8
|
+
accepts_value_for :run_in
|
|
9
|
+
|
|
10
|
+
accepts_block_for :setup
|
|
11
|
+
accepts_block_for :met?
|
|
12
|
+
|
|
13
|
+
accepts_block_for :prepare
|
|
14
|
+
accepts_block_for :before
|
|
15
|
+
accepts_block_for :meet
|
|
16
|
+
accepts_block_for :after
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class DepDefiner
|
|
3
|
+
include LogHelpers
|
|
4
|
+
extend LogHelpers
|
|
5
|
+
include ShellHelpers
|
|
6
|
+
extend ShellHelpers
|
|
7
|
+
include PathHelpers
|
|
8
|
+
extend PathHelpers
|
|
9
|
+
include RunHelpers
|
|
10
|
+
extend RunHelpers
|
|
11
|
+
|
|
12
|
+
include Prompt::Helpers
|
|
13
|
+
extend Prompt::Helpers
|
|
14
|
+
include VersionOf::Helpers
|
|
15
|
+
extend VersionOf::Helpers
|
|
16
|
+
|
|
17
|
+
include AcceptsListFor
|
|
18
|
+
include AcceptsValueFor
|
|
19
|
+
include AcceptsBlockFor
|
|
20
|
+
|
|
21
|
+
attr_reader :dependency, :payload, :block
|
|
22
|
+
|
|
23
|
+
def name; dependency.name end
|
|
24
|
+
def basename; dependency.basename end
|
|
25
|
+
def load_path; dependency.load_path end
|
|
26
|
+
|
|
27
|
+
include Vars::Helpers
|
|
28
|
+
extend Vars::Helpers
|
|
29
|
+
|
|
30
|
+
def initialize dep, &block
|
|
31
|
+
@dependency = dep
|
|
32
|
+
@payload = {}
|
|
33
|
+
@block = block
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def define!
|
|
37
|
+
define_params!
|
|
38
|
+
|
|
39
|
+
unless block.nil?
|
|
40
|
+
raise "Dep block arguments aren't supported anymore. Instead, specify parameter names as symbols after the dep name. More details here: http://github.com/benhoskings/babushka/commit/40054c2" if block.arity > 0
|
|
41
|
+
instance_eval(&block)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def result message, opts = {}
|
|
46
|
+
opts[:result].tap {
|
|
47
|
+
dependency.result_message = message
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def met message
|
|
52
|
+
result message, :result => true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def unmet message
|
|
56
|
+
result message, :result => false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def unmeetable message
|
|
60
|
+
raise Babushka::UnmeetableDep, message
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def file_and_line
|
|
64
|
+
get_file_and_line_for(block)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def file_and_line_for block_name
|
|
68
|
+
get_file_and_line_for send(block_name) if has_block? block_name
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def get_file_and_line_for blk
|
|
72
|
+
blk.inspect.scan(/\#\<Proc\:0x[0-9a-f]+\@([^:]+):(\d+)>/).flatten
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def define_params!
|
|
78
|
+
dependency.params.each {|param|
|
|
79
|
+
if respond_to?(param)
|
|
80
|
+
raise DepParameterError, "You can't use #{param.inspect} as a parameter (on '#{dependency.name}'), because that's already a method on #{method(param).owner}."
|
|
81
|
+
else
|
|
82
|
+
metaclass.send :define_method, param do
|
|
83
|
+
dependency.args[param] ||= Parameter.new(param)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def pkg_manager
|
|
90
|
+
BaseHelper
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def on platform, &blk
|
|
94
|
+
if [*chooser].include? platform
|
|
95
|
+
@current_platform = platform
|
|
96
|
+
blk.call.tap {
|
|
97
|
+
@current_platform = nil
|
|
98
|
+
}
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def chooser
|
|
103
|
+
Base.host.match_list
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def chooser_choices
|
|
107
|
+
SystemDefinitions.all_tokens
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def self.source_template
|
|
111
|
+
Dep.base_template
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class DepPool
|
|
3
|
+
|
|
4
|
+
def initialize source
|
|
5
|
+
clear!
|
|
6
|
+
@source = source
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def count
|
|
10
|
+
@pool.length
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def names
|
|
14
|
+
@pool.keys
|
|
15
|
+
end
|
|
16
|
+
def items
|
|
17
|
+
@pool.values
|
|
18
|
+
end
|
|
19
|
+
def for spec
|
|
20
|
+
spec.respond_to?(:name) ? @pool[spec.name] : @pool[spec]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def add_dep name, params, block
|
|
24
|
+
if self.for name
|
|
25
|
+
self.for name
|
|
26
|
+
else
|
|
27
|
+
opts = params.extract_options!
|
|
28
|
+
Dep.new name, @source, params, opts, block
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def add_template name, in_opts, block
|
|
33
|
+
MetaDep.for name, @source, in_opts, &block
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def clear!
|
|
37
|
+
@pool = {}
|
|
38
|
+
end
|
|
39
|
+
def uncache!
|
|
40
|
+
items.each {|i| i.send :uncache! }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def register item
|
|
44
|
+
raise "Already registered '#{item.name}'." if @pool.has_key?(item.name)
|
|
45
|
+
@pool[item.name] = item
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
module DepRunner
|
|
3
|
+
include GitHelpers
|
|
4
|
+
include UriHelpers
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
# TODO: solve cmd/app and string/version handling better.
|
|
9
|
+
def in_path? provided_list
|
|
10
|
+
apps, command_names = [*provided_list].partition {|i| i.to_s[/\.app\/?$/] }
|
|
11
|
+
commands = command_names.versions
|
|
12
|
+
apps_in_path?(apps) and cmds_in_path?(commands) and matching_versions?(commands)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def apps_in_path? apps
|
|
16
|
+
present, missing = [*apps].partition {|app_name| app_dir(app_name) }
|
|
17
|
+
|
|
18
|
+
missing.empty?.tap {|result|
|
|
19
|
+
if result
|
|
20
|
+
log "#{present.map {|i| "'#{i}'" }.to_list} #{present.length == 1 ? 'is' : 'are'} present." unless present.empty?
|
|
21
|
+
else
|
|
22
|
+
log "#{missing.map {|i| "'#{i}'" }.to_list} #{missing.length == 1 ? 'is' : 'are'}n't present anywhere in $PATH."
|
|
23
|
+
end
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def cmds_in_path? commands
|
|
28
|
+
dir_hash = [*commands].group_by {|cmd| cmd_dir(cmd.name) }
|
|
29
|
+
|
|
30
|
+
if dir_hash.keys.compact.length > 1
|
|
31
|
+
unmeetable "The commands for '#{name}' run from more than one place.\n" +
|
|
32
|
+
dir_hash.values.map {|cmds|
|
|
33
|
+
cmd_location_str_for cmds
|
|
34
|
+
}.to_list(:oxford => true, :conj => 'but').end_with('.')
|
|
35
|
+
else
|
|
36
|
+
cmds = dir_hash.values.first
|
|
37
|
+
dir_hash[nil].blank?.tap {|result|
|
|
38
|
+
if result
|
|
39
|
+
log cmd_location_str_for(cmds).end_with('.') unless cmds.blank?
|
|
40
|
+
else
|
|
41
|
+
log "#{dir_hash[nil].map {|i| "'#{i}'" }.to_list} #{dir_hash[nil].length == 1 ? 'is' : 'are'} missing."
|
|
42
|
+
end
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def matching_versions? commands
|
|
48
|
+
versions = commands.select {|cmd|
|
|
49
|
+
!cmd.version.nil?
|
|
50
|
+
}.inject({}) {|hsh,cmd|
|
|
51
|
+
hsh[cmd] = (shell("#{cmd.name} --version") || '').split(/[\s\-]/).detect {|piece|
|
|
52
|
+
begin
|
|
53
|
+
cmd.matches? piece.to_version
|
|
54
|
+
rescue VersionStrError
|
|
55
|
+
false
|
|
56
|
+
end
|
|
57
|
+
}
|
|
58
|
+
log "#{cmd.name} is #{hsh[cmd]}, which is#{"n't" unless hsh[cmd]} #{cmd.version}.", :as => (:ok if hsh[cmd])
|
|
59
|
+
hsh
|
|
60
|
+
}
|
|
61
|
+
versions.values.all?
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def app_dir app_name
|
|
65
|
+
prefix.find {|app_path|
|
|
66
|
+
(app_path.to_s / app_name).glob.select {|entry|
|
|
67
|
+
(entry / 'Contents/MacOS').exists?
|
|
68
|
+
}.first
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def cmd_location_str_for cmds
|
|
73
|
+
"#{cmds.map {|i| "'#{i.name}'" }.to_list(:conj => '&')} run#{'s' if cmds.length == 1} from #{cmd_dir(cmds.first.name)}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def call_task task_name
|
|
77
|
+
if (task_block = send(task_name)).nil?
|
|
78
|
+
true
|
|
79
|
+
else
|
|
80
|
+
instance_eval(&task_block)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
end
|
data/lib/babushka/dsl.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
module DSL
|
|
3
|
+
# Use +spec+ to look up a dep. Because +spec+ might include a source
|
|
4
|
+
# prefix, the dep this method returns could be from any of the currently
|
|
5
|
+
# known sources.
|
|
6
|
+
# If no dep matching +spec+ is found, nil is returned.
|
|
7
|
+
def Dep spec, opts = {}
|
|
8
|
+
Base.sources.dep_for spec, opts
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Define and return a dep named +name+, and whose implementation is found
|
|
12
|
+
# in +block+. This is the usual top-level entry point of the babushka
|
|
13
|
+
# DSL (along with +meta+); templated or not, this is how deps are
|
|
14
|
+
# defined.
|
|
15
|
+
def dep name, *params, &block
|
|
16
|
+
Base.sources.current_load_source.deps.add_dep name, params, block
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Define and return a meta dep named +name+, and whose implementation is
|
|
20
|
+
# found in +block+. This method, along with +dep, together are the
|
|
21
|
+
# top level of babushka's DSL.
|
|
22
|
+
def meta name, opts = {}, &block
|
|
23
|
+
Base.sources.current_load_source.templates.add_template name, opts, block
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
module Babushka
|
|
2
|
+
class GitRepoError < StandardError
|
|
3
|
+
end
|
|
4
|
+
class GitRepoExists < GitRepoError
|
|
5
|
+
end
|
|
6
|
+
# This class is used for manipulating git repositories (see {#initialize} how to start). Mostly it provides shortcuts to most often used git commands.
|
|
7
|
+
# @example Example of usage:
|
|
8
|
+
# @repo ||= Babushka::GitRepo.new('.')
|
|
9
|
+
# @repo.clone "https://github.com/benhoskings/babushka"
|
|
10
|
+
# @repo.checkout! "devel"
|
|
11
|
+
#
|
|
12
|
+
# For practical example how to use GitRepo class, see Ben Hoskings {https://github.com/benhoskings/babushka-deps/blob/master/push.rb push dep}
|
|
13
|
+
#
|
|
14
|
+
# Methods for checking repositrory state:
|
|
15
|
+
#
|
|
16
|
+
# * {#clean?}
|
|
17
|
+
# * {#dirty?}
|
|
18
|
+
# * {#include?} ref
|
|
19
|
+
# * {#ahead?}
|
|
20
|
+
# * {#behind?}
|
|
21
|
+
# * {#rebasing?}
|
|
22
|
+
# * {#applying?}
|
|
23
|
+
# * {#merging?}
|
|
24
|
+
# * {#bisecting?}
|
|
25
|
+
# * {#rebase_merging?}
|
|
26
|
+
# * {#rebasing_interactively?}
|
|
27
|
+
#
|
|
28
|
+
# Methods for repository operations:
|
|
29
|
+
#
|
|
30
|
+
# * {#clone!}
|
|
31
|
+
# * {#branch!}
|
|
32
|
+
# * {#track!}
|
|
33
|
+
# * {#checkout!}
|
|
34
|
+
# * {#reset_hard!} refspec
|
|
35
|
+
|
|
36
|
+
class GitRepo
|
|
37
|
+
include ShellHelpers
|
|
38
|
+
extend ShellHelpers
|
|
39
|
+
|
|
40
|
+
def self.repo_for path
|
|
41
|
+
maybe = shell("git rev-parse --git-dir", :cd => path) if path.p.dir?
|
|
42
|
+
maybe == '.git' ? path.p : maybe / '..' unless maybe.nil?
|
|
43
|
+
end
|
|
44
|
+
# @example Initialize repo in current dir
|
|
45
|
+
# @repo ||= Babushka::GitRepo.new('.')
|
|
46
|
+
def initialize path
|
|
47
|
+
@raw_path = path
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def path
|
|
51
|
+
@path ||= @raw_path.p
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def root
|
|
55
|
+
@root ||= self.class.repo_for(path)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def git_dir
|
|
59
|
+
root / '.git'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def exists?
|
|
63
|
+
!root.nil? && root.exists?
|
|
64
|
+
end
|
|
65
|
+
# executes shell command setting current directory to repository root
|
|
66
|
+
#
|
|
67
|
+
def repo_shell cmd, opts = {}, &block
|
|
68
|
+
if !exists?
|
|
69
|
+
raise GitRepoError, "There is no repo at #{@path}."
|
|
70
|
+
else
|
|
71
|
+
shell cmd, opts.merge(:cd => root), &block
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def clean?
|
|
76
|
+
repo_shell("git status") # Sometimes git caches invalid index info; this clears it.
|
|
77
|
+
repo_shell("git diff-index --name-status HEAD", &:stdout).blank?
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def dirty?
|
|
81
|
+
!clean?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def include? ref
|
|
85
|
+
repo_shell("git rev-list -n 1 '#{ref}'")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def ahead?
|
|
89
|
+
!remote_branch_exists? ||
|
|
90
|
+
!repo_shell("git rev-list origin/#{current_branch}..").split("\n").empty?
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def behind?
|
|
94
|
+
remote_branch_exists? &&
|
|
95
|
+
!repo_shell("git rev-list ..origin/#{current_branch}").split("\n").empty?
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def rebasing?
|
|
99
|
+
%w[rebase rebase-apply ../.dotest].any? {|d|
|
|
100
|
+
(git_dir / d).exists?
|
|
101
|
+
} or rebase_merging? or rebasing_interactively?
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def applying?
|
|
105
|
+
%w[rebase rebase-apply ../.dotest].any? {|d|
|
|
106
|
+
(git_dir / d / 'applying').exists?
|
|
107
|
+
}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def merging?
|
|
111
|
+
(git_dir / 'MERGE_HEAD').exists? or rebase_merging?
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def bisecting?
|
|
115
|
+
(git_dir / 'BISECT_LOG').exists?
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def rebase_merging?
|
|
119
|
+
%w[rebase-merge .dotest-merge].any? {|d|
|
|
120
|
+
(git_dir / d).exists?
|
|
121
|
+
}
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def rebasing_interactively?
|
|
125
|
+
%w[rebase-merge .dotest-merge].any? {|d|
|
|
126
|
+
(git_dir / d / 'interactive').exists?
|
|
127
|
+
}
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def branches
|
|
131
|
+
repo_shell('git branch').split("\n").map {|l| l.sub(/^[* ]+/, '') }
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def current_branch
|
|
135
|
+
repo_shell("cat .git/HEAD").strip.sub(/^.*refs\/heads\//, '')
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def current_head
|
|
139
|
+
repo_shell("git rev-parse --short HEAD")
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def current_full_head
|
|
143
|
+
repo_shell("git rev-parse HEAD")
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def remote_branch_exists?
|
|
147
|
+
repo_shell('git branch -a').split("\n").map(&:strip).detect {|b|
|
|
148
|
+
b[/^(remotes\/)?origin\/#{current_branch}$/]
|
|
149
|
+
}
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def clone! from
|
|
153
|
+
raise GitRepoExists, "Can't clone #{from} to existing path #{path}." if exists?
|
|
154
|
+
shell("git clone '#{from}' '#{path.basename}'", :cd => path.parent, :create => true) {|shell|
|
|
155
|
+
shell.ok? || raise(GitRepoError, "Couldn't clone to #{path}: #{error_message_for shell.stderr}")
|
|
156
|
+
}
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def branch! branch
|
|
160
|
+
repo_shell("git branch '#{branch}'")
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def track! branch
|
|
164
|
+
repo_shell("git checkout -t '#{branch}'")
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def checkout! branch
|
|
168
|
+
repo_shell("git checkout '#{branch}'")
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def reset_hard! refspec = 'HEAD'
|
|
172
|
+
repo_shell("git reset --hard #{refspec}")
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def inspect
|
|
176
|
+
"#<GitRepo:#{root} : #{current_branch}@#{current_head}#{' (dirty)' if dirty?}>"
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
private
|
|
180
|
+
|
|
181
|
+
def error_message_for git_error
|
|
182
|
+
git_error.sub(/^fatal\: /, '').sub(/\n.*$/m, '').end_with('.')
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|