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.
Files changed (171) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +31 -0
  3. data/README.markdown +246 -0
  4. data/Rakefile +26 -0
  5. data/bin/babushka +11 -0
  6. data/deps/babushka.rb +101 -0
  7. data/deps/dev.rb +12 -0
  8. data/deps/fhs.rb +31 -0
  9. data/deps/git.rb +29 -0
  10. data/deps/homebrew.rb +30 -0
  11. data/deps/os_x.rb +33 -0
  12. data/deps/packages.rb +22 -0
  13. data/deps/pkg_managers.rb +110 -0
  14. data/deps/ruby.rb +23 -0
  15. data/deps/rubygems.rb +24 -0
  16. data/deps/system.rb +10 -0
  17. data/deps/templates/app.rb +68 -0
  18. data/deps/templates/external.rb +12 -0
  19. data/deps/templates/installer.rb +31 -0
  20. data/deps/templates/managed.rb +105 -0
  21. data/deps/templates/ppa.rb +24 -0
  22. data/deps/templates/src.rb +42 -0
  23. data/deps/templates/tmbundle.rb +15 -0
  24. data/lib/babushka.rb +28 -0
  25. data/lib/babushka/accepts_block_for.rb +72 -0
  26. data/lib/babushka/accepts_list_for.rb +49 -0
  27. data/lib/babushka/accepts_value_for.rb +24 -0
  28. data/lib/babushka/base.rb +78 -0
  29. data/lib/babushka/bug_reporter.rb +55 -0
  30. data/lib/babushka/cmdline.rb +133 -0
  31. data/lib/babushka/cmdline/handler.rb +41 -0
  32. data/lib/babushka/cmdline/helpers.rb +127 -0
  33. data/lib/babushka/cmdline/parser.rb +69 -0
  34. data/lib/babushka/colorizer.rb +59 -0
  35. data/lib/babushka/core_patches/array.rb +171 -0
  36. data/lib/babushka/core_patches/blank.rb +22 -0
  37. data/lib/babushka/core_patches/bytes.rb +52 -0
  38. data/lib/babushka/core_patches/hash.rb +107 -0
  39. data/lib/babushka/core_patches/hashish.rb +14 -0
  40. data/lib/babushka/core_patches/integer.rb +25 -0
  41. data/lib/babushka/core_patches/io.rb +8 -0
  42. data/lib/babushka/core_patches/numeric.rb +16 -0
  43. data/lib/babushka/core_patches/object.rb +27 -0
  44. data/lib/babushka/core_patches/string.rb +116 -0
  45. data/lib/babushka/core_patches/symbol.rb +12 -0
  46. data/lib/babushka/core_patches/try.rb +15 -0
  47. data/lib/babushka/core_patches/uri.rb +24 -0
  48. data/lib/babushka/dep.rb +470 -0
  49. data/lib/babushka/dep_context.rb +18 -0
  50. data/lib/babushka/dep_definer.rb +115 -0
  51. data/lib/babushka/dep_pool.rb +49 -0
  52. data/lib/babushka/dep_runner.rb +85 -0
  53. data/lib/babushka/dsl.rb +26 -0
  54. data/lib/babushka/git_repo.rb +185 -0
  55. data/lib/babushka/helpers/git_helpers.rb +32 -0
  56. data/lib/babushka/helpers/log_helpers.rb +176 -0
  57. data/lib/babushka/helpers/path_helpers.rb +34 -0
  58. data/lib/babushka/helpers/run_helpers.rb +145 -0
  59. data/lib/babushka/helpers/shell_helpers.rb +229 -0
  60. data/lib/babushka/helpers/suggest_helpers.rb +16 -0
  61. data/lib/babushka/helpers/uri_helpers.rb +36 -0
  62. data/lib/babushka/ip.rb +160 -0
  63. data/lib/babushka/lambda_chooser.rb +40 -0
  64. data/lib/babushka/levenshtein.rb +125 -0
  65. data/lib/babushka/meta_dep.rb +65 -0
  66. data/lib/babushka/meta_dep_context.rb +15 -0
  67. data/lib/babushka/parameter.rb +143 -0
  68. data/lib/babushka/pkg_helper.rb +81 -0
  69. data/lib/babushka/pkg_helpers/apt_helper.rb +61 -0
  70. data/lib/babushka/pkg_helpers/base_helper.rb +19 -0
  71. data/lib/babushka/pkg_helpers/binpkgsrc_helper.rb +48 -0
  72. data/lib/babushka/pkg_helpers/binports_helper.rb +34 -0
  73. data/lib/babushka/pkg_helpers/brew_helper.rb +110 -0
  74. data/lib/babushka/pkg_helpers/gem_helper.rb +120 -0
  75. data/lib/babushka/pkg_helpers/macports_helper.rb +22 -0
  76. data/lib/babushka/pkg_helpers/npm_helper.rb +45 -0
  77. data/lib/babushka/pkg_helpers/pacman_helper.rb +27 -0
  78. data/lib/babushka/pkg_helpers/pip_helper.rb +45 -0
  79. data/lib/babushka/pkg_helpers/src_helper.rb +16 -0
  80. data/lib/babushka/pkg_helpers/yum_helper.rb +25 -0
  81. data/lib/babushka/popen.rb +40 -0
  82. data/lib/babushka/prompt.rb +176 -0
  83. data/lib/babushka/renderable.rb +67 -0
  84. data/lib/babushka/resource.rb +215 -0
  85. data/lib/babushka/run_reporter.rb +60 -0
  86. data/lib/babushka/shell.rb +108 -0
  87. data/lib/babushka/source.rb +216 -0
  88. data/lib/babushka/source_pool.rb +146 -0
  89. data/lib/babushka/system_definitions.rb +97 -0
  90. data/lib/babushka/system_profile.rb +210 -0
  91. data/lib/babushka/task.rb +142 -0
  92. data/lib/babushka/vars.rb +108 -0
  93. data/lib/babushka/version_of.rb +65 -0
  94. data/lib/babushka/version_str.rb +57 -0
  95. data/lib/babushka/xml_string.rb +28 -0
  96. data/lib/components.rb +82 -0
  97. data/lib/fancypath/fancypath.rb +200 -0
  98. data/lib/inkan/inkan.rb +76 -0
  99. data/spec/acceptance/acceptance.rb +43 -0
  100. data/spec/acceptance_helper.rb +113 -0
  101. data/spec/archives/Blah.app.zip +0 -0
  102. data/spec/archives/archive.tar +0 -0
  103. data/spec/archives/archive.tar.bz2 +0 -0
  104. data/spec/archives/archive.tar.gz +0 -0
  105. data/spec/archives/archive.tbz2 +0 -0
  106. data/spec/archives/archive.tgz +0 -0
  107. data/spec/archives/archive.zip +0 -0
  108. data/spec/archives/content.txt +5 -0
  109. data/spec/archives/invalid_archive +5 -0
  110. data/spec/archives/nested archive/content.txt +5 -0
  111. data/spec/archives/nested_archive.tar +0 -0
  112. data/spec/archives/really_a_gzip.zip +0 -0
  113. data/spec/archives/test-0.3.1.tgz +0 -0
  114. data/spec/archives/tgz_archive +0 -0
  115. data/spec/archives/zip_without_extension +0 -0
  116. data/spec/babushka/accepts_for_spec.rb +174 -0
  117. data/spec/babushka/accepts_for_support.rb +72 -0
  118. data/spec/babushka/cmdline/console_spec.rb +11 -0
  119. data/spec/babushka/cmdline/help_spec.rb +61 -0
  120. data/spec/babushka/cmdline/version_spec.rb +10 -0
  121. data/spec/babushka/core_patches_spec.rb +171 -0
  122. data/spec/babushka/dep_context_spec.rb +58 -0
  123. data/spec/babushka/dep_definer_spec.rb +152 -0
  124. data/spec/babushka/dep_definer_support.rb +36 -0
  125. data/spec/babushka/dep_spec.rb +567 -0
  126. data/spec/babushka/dep_support.rb +29 -0
  127. data/spec/babushka/deps_spec.rb +113 -0
  128. data/spec/babushka/gem_helper_spec.rb +90 -0
  129. data/spec/babushka/git_repo_spec.rb +396 -0
  130. data/spec/babushka/ip_spec.rb +131 -0
  131. data/spec/babushka/lambda_chooser_spec.rb +115 -0
  132. data/spec/babushka/meta_dep_definer_spec.rb +127 -0
  133. data/spec/babushka/meta_dep_wrapper_spec.rb +32 -0
  134. data/spec/babushka/parameter_spec.rb +135 -0
  135. data/spec/babushka/path_helpers_spec.rb +102 -0
  136. data/spec/babushka/prompt_spec.rb +188 -0
  137. data/spec/babushka/renderable_spec.rb +100 -0
  138. data/spec/babushka/resource_spec.rb +141 -0
  139. data/spec/babushka/run_helpers_spec.rb +26 -0
  140. data/spec/babushka/shell_helpers_spec.rb +244 -0
  141. data/spec/babushka/shell_spec.rb +19 -0
  142. data/spec/babushka/source_pool_spec.rb +320 -0
  143. data/spec/babushka/source_pool_support.rb +31 -0
  144. data/spec/babushka/source_spec.rb +382 -0
  145. data/spec/babushka/source_support.rb +17 -0
  146. data/spec/babushka/system_profile_spec.rb +61 -0
  147. data/spec/babushka/task_spec.rb +141 -0
  148. data/spec/babushka/uri_spec.rb +13 -0
  149. data/spec/babushka/vars_spec.rb +59 -0
  150. data/spec/babushka/version_of_spec.rb +110 -0
  151. data/spec/babushka/version_str_spec.rb +130 -0
  152. data/spec/babushka/version_str_support.rb +37 -0
  153. data/spec/babushka/xml_string_spec.rb +98 -0
  154. data/spec/deps/bad/broken.rb +7 -0
  155. data/spec/deps/bad/working.rb +3 -0
  156. data/spec/deps/good/meta.rb +14 -0
  157. data/spec/deps/good/test.rb +11 -0
  158. data/spec/deps/outer/deps.rb +19 -0
  159. data/spec/deps/outer/more deps.rb +11 -0
  160. data/spec/deps/params/params.rb +10 -0
  161. data/spec/fancypath/fancypath_spec.rb +272 -0
  162. data/spec/fancypath_support.rb +10 -0
  163. data/spec/inkan/inkan_spec.rb +217 -0
  164. data/spec/renderable/different_example.conf.erb +4 -0
  165. data/spec/renderable/example.conf.erb +3 -0
  166. data/spec/renderable/example.sh +6 -0
  167. data/spec/renderable/with_binding.conf.erb +4 -0
  168. data/spec/renderable/xml_example.conf.erb +8 -0
  169. data/spec/repos/remote.git.tgz +0 -0
  170. data/spec/spec_helper.rb +87 -0
  171. 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
@@ -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