rubycut-babushka 0.10.8 → 0.15.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/Gemfile +1 -0
  2. data/Gemfile.lock +17 -15
  3. data/README.markdown +163 -41
  4. data/Rakefile +1 -1
  5. data/bin/babushka +1 -1
  6. data/deps/apt.rb +44 -0
  7. data/deps/babushka.rb +54 -42
  8. data/deps/deprecated.rb +16 -0
  9. data/deps/dev.rb +28 -3
  10. data/deps/git.rb +27 -12
  11. data/deps/homebrew.rb +2 -2
  12. data/deps/packages.rb +14 -15
  13. data/deps/pkg_managers.rb +21 -75
  14. data/deps/ruby.rb +5 -19
  15. data/deps/rubygems.rb +3 -3
  16. data/deps/system.rb +2 -2
  17. data/deps/templates/app.rb +60 -41
  18. data/deps/templates/bin.rb +16 -0
  19. data/deps/templates/installer.rb +9 -9
  20. data/deps/templates/lib.rb +17 -0
  21. data/deps/templates/managed.rb +1 -38
  22. data/deps/templates/src.rb +16 -8
  23. data/deps/templates/task.rb +11 -0
  24. data/deps/templates/tmbundle.rb +16 -2
  25. data/lib/babushka.rb +2 -3
  26. data/lib/babushka/accepts_block_for.rb +5 -3
  27. data/lib/babushka/asset.rb +172 -0
  28. data/lib/babushka/base.rb +37 -8
  29. data/lib/babushka/bug_reporter.rb +6 -6
  30. data/lib/babushka/cmdline.rb +11 -10
  31. data/lib/babushka/cmdline/handler.rb +7 -3
  32. data/lib/babushka/cmdline/helpers.rb +15 -23
  33. data/lib/babushka/cmdline/parser.rb +1 -1
  34. data/lib/babushka/core_patches/object.rb +1 -1
  35. data/lib/babushka/core_patches/string.rb +8 -3
  36. data/lib/babushka/current_ruby.rb +44 -0
  37. data/lib/babushka/dep.rb +111 -185
  38. data/lib/babushka/dep_context.rb +8 -3
  39. data/lib/babushka/dep_definer.rb +45 -15
  40. data/lib/babushka/dep_pool.rb +5 -8
  41. data/lib/babushka/{meta_dep.rb → dep_template.rb} +21 -2
  42. data/lib/babushka/dsl.rb +3 -0
  43. data/lib/babushka/git_repo.rb +143 -49
  44. data/lib/babushka/helpers/git_helpers.rb +7 -6
  45. data/lib/babushka/helpers/log_helpers.rb +51 -13
  46. data/lib/babushka/helpers/path_helpers.rb +5 -7
  47. data/lib/babushka/helpers/run_helpers.rb +15 -55
  48. data/lib/babushka/helpers/shell_helpers.rb +18 -26
  49. data/lib/babushka/helpers/uri_helpers.rb +9 -18
  50. data/lib/babushka/lambda_chooser.rb +20 -13
  51. data/lib/babushka/parameter.rb +20 -4
  52. data/lib/babushka/path_checker.rb +72 -0
  53. data/lib/babushka/pkg_helper.rb +38 -13
  54. data/lib/babushka/pkg_helpers/apt_helper.rb +15 -8
  55. data/lib/babushka/pkg_helpers/binpkgsrc_helper.rb +15 -14
  56. data/lib/babushka/pkg_helpers/binports_helper.rb +7 -7
  57. data/lib/babushka/pkg_helpers/brew_helper.rb +17 -25
  58. data/lib/babushka/pkg_helpers/gem_helper.rb +36 -27
  59. data/lib/babushka/pkg_helpers/npm_helper.rb +9 -9
  60. data/lib/babushka/pkg_helpers/pacman_helper.rb +5 -4
  61. data/lib/babushka/pkg_helpers/pip_helper.rb +14 -10
  62. data/lib/babushka/pkg_helpers/unknown_pkg_helper.rb +19 -0
  63. data/lib/babushka/pkg_helpers/yum_helper.rb +1 -1
  64. data/lib/babushka/popen.rb +13 -10
  65. data/lib/babushka/prompt.rb +14 -1
  66. data/lib/babushka/renderable.rb +11 -9
  67. data/lib/babushka/resource.rb +5 -166
  68. data/lib/babushka/run_reporter.rb +12 -3
  69. data/lib/babushka/shell.rb +54 -44
  70. data/lib/babushka/source.rb +41 -20
  71. data/lib/babushka/source_pool.rb +20 -13
  72. data/lib/babushka/system_definitions.rb +11 -3
  73. data/lib/babushka/system_detector.rb +31 -0
  74. data/lib/babushka/system_matcher.rb +53 -0
  75. data/lib/babushka/system_profile.rb +67 -89
  76. data/lib/babushka/task.rb +36 -8
  77. data/lib/babushka/{meta_dep_context.rb → templated_dep_context.rb} +1 -1
  78. data/lib/babushka/vars.rb +46 -4
  79. data/lib/babushka/version_of.rb +35 -17
  80. data/lib/babushka/version_str.rb +12 -8
  81. data/lib/components.rb +9 -8
  82. data/lib/fancypath/fancypath.rb +109 -83
  83. data/lib/inkan/inkan.rb +14 -14
  84. data/lib/{babushka → levenshtein}/levenshtein.rb +0 -0
  85. data/spec/acceptance/acceptance.rb +4 -4
  86. data/spec/acceptance_helper.rb +10 -6
  87. data/spec/babushka/accepts_for_spec.rb +137 -142
  88. data/spec/babushka/accepts_for_support.rb +13 -6
  89. data/spec/babushka/asset_spec.rb +165 -0
  90. data/spec/babushka/cmdline/help_spec.rb +11 -9
  91. data/spec/babushka/cmdline/meet_spec.rb +15 -0
  92. data/spec/babushka/cmdline/version_spec.rb +1 -1
  93. data/spec/babushka/core_patches_spec.rb +9 -0
  94. data/spec/babushka/current_ruby_spec.rb +73 -0
  95. data/spec/babushka/dep_context_spec.rb +27 -13
  96. data/spec/babushka/dep_definer_spec.rb +108 -16
  97. data/spec/babushka/dep_spec.rb +87 -104
  98. data/spec/babushka/dep_template_spec.rb +176 -0
  99. data/spec/babushka/deps_spec.rb +48 -19
  100. data/spec/babushka/gem_helper_spec.rb +46 -59
  101. data/spec/babushka/git_repo_spec.rb +242 -51
  102. data/spec/babushka/ip_spec.rb +11 -11
  103. data/spec/babushka/lambda_chooser_spec.rb +47 -9
  104. data/spec/babushka/parameter_spec.rb +21 -0
  105. data/spec/babushka/path_checker_spec.rb +35 -0
  106. data/spec/babushka/path_helpers_spec.rb +51 -50
  107. data/spec/babushka/prompt_spec.rb +4 -4
  108. data/spec/babushka/renderable_spec.rb +61 -28
  109. data/spec/babushka/shell_helpers_spec.rb +110 -85
  110. data/spec/babushka/shell_spec.rb +15 -0
  111. data/spec/babushka/source_pool_spec.rb +204 -210
  112. data/spec/babushka/source_spec.rb +125 -42
  113. data/spec/babushka/source_support.rb +1 -1
  114. data/spec/babushka/system_profile_spec.rb +86 -49
  115. data/spec/babushka/task_spec.rb +80 -13
  116. data/spec/babushka/vars_spec.rb +2 -1
  117. data/spec/babushka/version_of_spec.rb +29 -2
  118. data/spec/babushka/version_str_spec.rb +91 -65
  119. data/spec/babushka/xml_string_spec.rb +1 -1
  120. data/spec/deps/bad/broken.rb +2 -2
  121. data/spec/deps/bad/working.rb +0 -1
  122. data/spec/deps/good/{meta.rb → template.rb} +0 -0
  123. data/spec/deps/good/test.rb +0 -3
  124. data/spec/deps/outer/deps.rb +0 -2
  125. data/spec/fancypath/fancypath_spec.rb +30 -0
  126. data/spec/inkan/inkan_spec.rb +34 -32
  127. data/spec/spec_helper.rb +7 -50
  128. data/spec/system_detector_spec.rb +70 -0
  129. metadata +163 -177
  130. data/deps/os_x.rb +0 -33
  131. data/deps/templates/ppa.rb +0 -24
  132. data/lib/babushka/core_patches/io.rb +0 -8
  133. data/lib/babushka/dep_runner.rb +0 -85
  134. data/lib/babushka/helpers/suggest_helpers.rb +0 -16
  135. data/lib/babushka/pkg_helpers/base_helper.rb +0 -19
  136. data/lib/babushka/pkg_helpers/macports_helper.rb +0 -22
  137. data/spec/babushka/dep_definer_support.rb +0 -36
  138. data/spec/babushka/meta_dep_definer_spec.rb +0 -127
  139. data/spec/babushka/meta_dep_wrapper_spec.rb +0 -32
  140. data/spec/babushka/resource_spec.rb +0 -141
  141. data/spec/babushka/run_helpers_spec.rb +0 -26
  142. data/spec/babushka/source_pool_support.rb +0 -31
data/lib/babushka/task.rb CHANGED
@@ -5,20 +5,23 @@ module Babushka
5
5
  include PathHelpers
6
6
  include ShellHelpers
7
7
 
8
- attr_reader :opts, :vars, :persistent_log
8
+ attr_reader :opts, :vars, :caches, :persistent_log
9
9
  attr_accessor :reportable
10
10
 
11
11
  def initialize
12
- @vars = Vars.new
13
12
  @opts = Base.cmdline.opts.dup
14
13
  @running = false
14
+ @caching = false
15
15
  end
16
16
 
17
- def process dep_names, with_vars = {}
17
+ def process dep_names, with_vars
18
18
  raise "A task is already running." if running?
19
+ @vars = Vars.new
19
20
  @running = true
20
21
  Base.in_thread { RunReporter.post_reports }
21
22
  dep_names.all? {|dep_name| process_dep dep_name, with_vars }
23
+ rescue SourceLoadError => e
24
+ Babushka::Logging.log_exception(e)
22
25
  ensure
23
26
  @running = false
24
27
  end
@@ -27,22 +30,41 @@ module Babushka
27
30
  Dep.find_or_suggest dep_name do |dep|
28
31
  log_dep(dep) {
29
32
  load_run_info_for dep, with_vars
30
- dep.with(task_args_for(dep, with_vars)).process(:top_level => true).tap {|result|
33
+ dep.with(task_args_for(dep, with_vars)).process.tap {|result|
31
34
  save_run_info_for dep, result
32
35
  }
33
36
  }.tap {|result|
34
- log "You can view #{opt(:debug) ? 'the' : 'a more detailed'} log at '#{log_path_for(dep)}'." unless result
37
+ log_stderr "You can view #{opt(:debug) ? 'the' : 'a more detailed'} log at '#{log_path_for(dep)}'." unless result
35
38
  RunReporter.queue dep, result, reportable
36
39
  BugReporter.report dep if reportable
37
40
  }
38
41
  end
39
42
  end
40
43
 
44
+ def cache &block
45
+ was_caching, @caching, @caches = @caching, true, {}
46
+ block.call
47
+ ensure
48
+ @caching = was_caching
49
+ end
50
+
51
+ def cached key, opts = {}, &block
52
+ if !@caching
53
+ block.call
54
+ elsif @caches.has_key?(key)
55
+ @caches[key].tap {|value|
56
+ opts[:hit].call(value) if opts.has_key?(:hit)
57
+ }
58
+ else
59
+ @caches[key] = block.call
60
+ end
61
+ end
62
+
41
63
  def task_info dep, result
42
64
  {
43
- :version => VERSION,
65
+ :version => Base.ref,
44
66
  :run_at => Time.now,
45
- :system_info => Base.host.description,
67
+ :system_info => Babushka.host.description,
46
68
  :dep_name => dep.name,
47
69
  :source_uri => dep.dep_source.uri,
48
70
  :result => result
@@ -88,8 +110,14 @@ module Babushka
88
110
  log_path_for(dep).open('w') {|f|
89
111
  f.sync = true
90
112
  @persistent_log = f
91
- yield.tap { @persistent_log = nil }
113
+
114
+ # Note the current babushka & ruby versions at the top of the log.
115
+ LogHelpers.debug(Base.runtime_info)
116
+
117
+ yield
92
118
  }
119
+ ensure
120
+ @persistent_log = nil
93
121
  end
94
122
 
95
123
  def log_prefix
@@ -1,5 +1,5 @@
1
1
  module Babushka
2
- class MetaDepContext < DepContext
2
+ class TemplatedDepContext < DepContext
3
3
 
4
4
  def self.template &block
5
5
  @template = block unless block.nil?
data/lib/babushka/vars.rb CHANGED
@@ -5,10 +5,51 @@ module Babushka
5
5
  attr_reader :vars, :saved_vars
6
6
 
7
7
  module Helpers
8
- def set(key, value) Base.task.vars.set(key, value) end
9
- def merge(key, value) Base.task.vars.merge(key, value) end
10
- def var(name, opts = {}) Base.task.vars.var(name, opts) end
11
- def define_var(name, opts = {}) Base.task.vars.define_var(name, opts) end
8
+ def set(key, value)
9
+ deprecated! '2012-12-12', :instead => 'an argument for a dep parameter', :example => "requires 'some dep'.with(:#{key} => '#{value}')"
10
+ Base.task.vars.set(key, value)
11
+ end
12
+
13
+ def merge(key, value)
14
+ deprecated! '2012-12-12', :instead => 'an argument for a dep parameter', :example => "requires 'some dep'.with(:#{key} => '#{value}')"
15
+ Base.task.vars.merge(key, value)
16
+ end
17
+
18
+ def var(name, opts = {})
19
+ print_var_deprecation_for('#var', name, opts)
20
+ Base.task.vars.var(name, opts)
21
+ end
22
+
23
+ def define_var(name, opts = {})
24
+ print_var_deprecation_for('#define_var', name, opts)
25
+ Base.task.vars.define_var(name, opts)
26
+ end
27
+
28
+ def print_var_deprecation_for method_name, var_name, opts
29
+ option_names_map = {
30
+ :default => :default,
31
+ :message => :ask,
32
+ :choices => :choose,
33
+ :choice_descriptions => :choose
34
+ }
35
+ param_opts = opts.slice(*option_names_map.keys).keys.map {|key|
36
+ opt_value = opts[key].respond_to?(:call) ? '...' : opts[key].inspect
37
+ "#{option_names_map[key]}(#{opt_value})"
38
+ }
39
+ example = if param_opts.empty?
40
+ "dep 'blah', :#{name} do ... end"
41
+ else
42
+ "
43
+ dep 'blah', :#{var_name} do
44
+ #{[var_name].concat(param_opts).join('.')}
45
+ end"
46
+ end
47
+ deprecated! '2012-12-12',
48
+ :skip => 2,
49
+ :method_name => method_name,
50
+ :instead => 'a dep parameter',
51
+ :example => example
52
+ end
12
53
  end
13
54
 
14
55
  def initialize
@@ -19,6 +60,7 @@ module Babushka
19
60
  def set key, value
20
61
  vars[key.to_s][:value] = value
21
62
  end
63
+
22
64
  def merge key, value
23
65
  set key, ((vars[key.to_s] || {})[:value] || {}).merge(value)
24
66
  end
@@ -1,28 +1,40 @@
1
1
  module Babushka
2
+
3
+ def VersionOf first, *rest
4
+ # Convert the arguments into a VersionOf. If a single string argument is
5
+ # passed, try splitting it on space to separate name and version. Otherwise,
6
+ # pass the arguments as-is, splatting if required.
7
+ if rest.any?
8
+ Babushka::VersionOf.new(*[first].concat(rest))
9
+ elsif first.is_a?(String)
10
+ name, version = first.split(' ', 2)
11
+ if version && VersionStr.parseable_version?(version)
12
+ Babushka::VersionOf.new(name, version)
13
+ else
14
+ Babushka::VersionOf.new(first)
15
+ end
16
+ elsif first.is_a?(Array)
17
+ Babushka::VersionOf.new(*first)
18
+ else
19
+ Babushka::VersionOf.new(first)
20
+ end
21
+ end
22
+
23
+ module_function :VersionOf
24
+
2
25
  class VersionOf
3
26
  module Helpers
4
- module_function
5
-
6
27
  def VersionOf first, *rest
7
- # Convert the arguments into a VersionOf. If a single string argument is
8
- # passed, try splitting it on space to separate name and version. Otherwise,
9
- # pass the arguments as-is, splatting if required.
10
- if rest.any?
11
- Babushka::VersionOf.new(*[first].concat(rest))
12
- elsif first.is_a?(String)
13
- Babushka::VersionOf.new(*first.split(' ', 2))
14
- elsif first.is_a?(Array)
15
- Babushka::VersionOf.new(*first)
16
- else
17
- Babushka::VersionOf.new(first)
18
- end
28
+ # TODO: decide on the form for this and deprecate the others.
29
+ Babushka.VersionOf(first, *rest)
19
30
  end
31
+ module_function :VersionOf
20
32
  end
21
33
 
22
34
  attr_accessor :name, :version
23
35
 
24
36
  def initialize name, version = nil
25
- @name = name.respond_to?(:name) ? name.name : name
37
+ @name = name.is_a?(VersionOf) ? name.name : name
26
38
  @version = if version.nil?
27
39
  name.version if name.respond_to?(:version)
28
40
  elsif version.is_a? VersionStr
@@ -54,8 +66,14 @@ module Babushka
54
66
  end
55
67
  end
56
68
 
57
- def to_s joinery = '-'
58
- [name, version].compact * joinery
69
+ def to_s
70
+ # == joins with a dash to produce versions like 'rack-1.4.1'; anything
71
+ # else joins with space like 'rack >= 1.4'.
72
+ [name, version].compact * (exact? ? '-' : ' ')
73
+ end
74
+
75
+ def exact?
76
+ !version.nil? && version.operator == '=='
59
77
  end
60
78
 
61
79
  def inspect
@@ -8,13 +8,8 @@ module Babushka
8
8
  attr_reader :pieces, :operator, :version
9
9
  GemVersionOperators = %w[= == != > < >= <= ~>].freeze
10
10
 
11
- def <=> other
12
- other = other.to_version unless other.is_a? VersionStr
13
- max_length = [pieces.length, other.pieces.length].max
14
- (0...max_length).to_a.pick {|index|
15
- result = compare_pieces pieces[index], other.pieces[index]
16
- result unless result == 0
17
- } || 0
11
+ def self.parseable_version? str
12
+ !str.nil? && !str[/\d|HEAD/].nil?
18
13
  end
19
14
 
20
15
  def initialize str
@@ -22,7 +17,7 @@ module Babushka
22
17
 
23
18
  if !(@operator.nil? || GemVersionOperators.include?(@operator))
24
19
  raise InvalidVersionOperator, "VersionStr.new('#{str}'): invalid operator '#{@operator}'."
25
- elsif @version.nil?
20
+ elsif !self.class.parseable_version?(@version)
26
21
  raise InvalidVersionStr, "VersionStr.new('#{str}'): couldn't parse a version number."
27
22
  else
28
23
  @pieces = @version.strip.scan(/\d+|[a-zA-Z]+|\w+/).map {|piece|
@@ -36,6 +31,15 @@ module Babushka
36
31
  @operator == '==' ? @version : "#{@operator} #{@version}"
37
32
  end
38
33
 
34
+ def <=> other
35
+ other = other.to_version unless other.is_a? VersionStr
36
+ max_length = [pieces.length, other.pieces.length].max
37
+ (0...max_length).to_a.pick {|index|
38
+ result = compare_pieces pieces[index], other.pieces[index]
39
+ result unless result == 0
40
+ } || 0
41
+ end
42
+
39
43
  define_method "!=" do |other|
40
44
  !(self == other)
41
45
  end
data/lib/components.rb CHANGED
@@ -4,6 +4,7 @@ module Babushka
4
4
  ExternalComponents = %w[
5
5
  fancypath/fancypath
6
6
  inkan/inkan
7
+ levenshtein/levenshtein
7
8
  ]
8
9
 
9
10
  Components = %w[
@@ -13,7 +14,6 @@ module Babushka
13
14
  core_patches/hash
14
15
  core_patches/hashish
15
16
  core_patches/integer
16
- core_patches/io
17
17
  core_patches/numeric
18
18
  core_patches/bytes
19
19
  core_patches/object
@@ -25,13 +25,13 @@ module Babushka
25
25
  helpers/shell_helpers
26
26
  helpers/path_helpers
27
27
  helpers/run_helpers
28
- helpers/suggest_helpers
29
28
  helpers/git_helpers
30
29
  helpers/uri_helpers
31
30
  popen
32
31
  shell
33
32
  git_repo
34
33
  resource
34
+ asset
35
35
  prompt
36
36
  lambda_chooser
37
37
  ip
@@ -41,24 +41,25 @@ module Babushka
41
41
  accepts_value_for
42
42
  accepts_block_for
43
43
  colorizer
44
- levenshtein
45
44
  cmdline/parser
46
45
  cmdline/handler
47
46
  cmdline/helpers
48
47
  cmdline
49
48
  base
50
49
  renderable
50
+ current_ruby
51
51
  system_definitions
52
52
  system_profile
53
+ system_detector
54
+ system_matcher
53
55
  run_reporter
54
56
  bug_reporter
55
57
  pkg_helper
56
- pkg_helpers/base_helper
58
+ pkg_helpers/unknown_pkg_helper
57
59
  pkg_helpers/apt_helper
58
60
  pkg_helpers/yum_helper
59
61
  pkg_helpers/brew_helper
60
62
  pkg_helpers/gem_helper
61
- pkg_helpers/macports_helper
62
63
  pkg_helpers/src_helper
63
64
  pkg_helpers/pip_helper
64
65
  pkg_helpers/binpkgsrc_helper
@@ -73,10 +74,10 @@ module Babushka
73
74
  source_pool
74
75
  vars
75
76
  parameter
76
- dep_runner
77
+ path_checker
77
78
  dep_definer
78
79
  dep_context
79
- meta_dep
80
- meta_dep_context
80
+ dep_template
81
+ templated_dep_context
81
82
  ]
82
83
  end
@@ -3,20 +3,21 @@ require 'pathname'
3
3
  class Fancypath < Pathname
4
4
  module Helpers
5
5
  require 'etc'
6
+
6
7
  def to_fancypath
7
8
  Fancypath.new to_tilde_expanded_path
8
9
  end
10
+
9
11
  def to_expanded_fancypath
10
12
  Fancypath.new File.expand_path(to_tilde_expanded_path)
11
13
  end
14
+ alias :p :to_expanded_fancypath
15
+
12
16
  def to_tilde_expanded_path
13
17
  sub(/^\~\/|^\~$/) {|_| Etc.getpwuid(Process.euid).dir.end_with('/') }
14
18
  end
15
- alias :p :to_expanded_fancypath
16
19
  end
17
20
 
18
- # methods are chainable and do what you think they do
19
-
20
21
  alias_method :to_str, :to_s unless method_defined? :to_str
21
22
 
22
23
  alias_method :dir, :dirname
@@ -31,6 +32,17 @@ class Fancypath < Pathname
31
32
  alias_method :exists?, :exist?
32
33
  alias_method :rename_to, :rename
33
34
 
35
+
36
+ # About this Fancypath object.
37
+
38
+ def inspect
39
+ super.sub('Pathname','Fancypath')
40
+ end
41
+
42
+ def to_fancypath
43
+ self
44
+ end
45
+
34
46
  def == other
35
47
  if other.is_a? String
36
48
  to_s == other
@@ -43,51 +55,45 @@ class Fancypath < Pathname
43
55
  to_s.length
44
56
  end
45
57
 
46
- def join(path)
47
- path_str = path.to_s
48
- super(path_str[0..0] == '/' ? path_str[1..-1] : path_str).p
49
- end
50
58
 
51
- alias_method :/, :join
59
+ # Querying the path.
52
60
 
53
- # This method returns true if the path is writable (i.e. and already
54
- # exists), or if the current user would be able to create it (i.e. if
55
- # its closest existing parent is writable).
56
- def hypothetically_writable?
57
- writable? || (!exists? && !root? && parent.hypothetically_writable?)
61
+ def empty?
62
+ directory? ? children.size == 0 : self.size == 0
58
63
  end
59
64
 
60
- # make file
61
- def touch
62
- `touch '#{self}'`
63
- self
65
+ def owner
66
+ Etc.getpwuid(File.stat(to_s).uid).name
64
67
  end
65
68
 
66
- def create_dir
67
- mkpath unless exist?
68
- self
69
+ def group
70
+ Etc.getgrgid(File.stat(to_s).gid).name
69
71
  end
70
72
 
71
- alias_method :create, :create_dir
72
-
73
- def copy(dest)
74
- `cp -pPR '#{self}' '#{dest}'`
75
- self
73
+ # True if the path is writable (and already exists), or createable by the
74
+ # current user (i.e. if its closest existing parent is writable).
75
+ def hypothetically_writable?
76
+ writable? || (!exists? && !root? && parent.hypothetically_writable?)
76
77
  end
77
78
 
78
- alias_method :cp, :copy
79
79
 
80
- # file or dir
81
- def remove
82
- directory? ? rmtree : delete if exist?
83
- self
80
+ # Path traversal & manipulation.
81
+
82
+ def join(path)
83
+ path_str = path.to_s
84
+ super(path_str[0..0] == '/' ? path_str[1..-1] : path_str).p
84
85
  end
85
- alias_method :rm, :remove
86
+ alias_method :/, :join
86
87
 
87
- def read
88
- super.chomp if exists?
88
+ def parent
89
+ super.p
89
90
  end
90
91
 
92
+ def children
93
+ super.reject { |c| c.basename.to_s =~ /^\./ }
94
+ end
95
+ alias_method :all_children, :children
96
+
91
97
  def readlink
92
98
  if !symlink?
93
99
  self
@@ -97,29 +103,13 @@ class Fancypath < Pathname
97
103
  end
98
104
  end
99
105
 
100
- def mkdir
101
- `mkdir -p '#{self}'`
102
- self
103
- end
104
-
105
- def glob expr = nil, flags = File::FNM_CASEFOLD, &block
106
- Dir.glob((expr.nil? ? self : (self / expr)).to_s, flags, &block)
107
- end
108
106
 
109
- def write(contents, mode='wb')
110
- dirname.create
111
- open(mode) { |f| f.write contents }
112
- self
113
- end
107
+ # Querying the file the path refers to.
114
108
 
115
- def append(contents)
116
- write(contents,'a+')
117
- self
118
- end
109
+ alias_method :read!, :read
119
110
 
120
- def move(dest)
121
- self.rename(dest)
122
- dest.p
111
+ def read
112
+ super if exists?
123
113
  end
124
114
 
125
115
  def tail(bytes)
@@ -130,34 +120,27 @@ class Fancypath < Pathname
130
120
  end
131
121
  end
132
122
 
133
- alias_method :mv, :move
134
-
135
- def set_extension(ext)
136
- "#{without_extension}.#{ext}".p
123
+ def yaml
124
+ require 'yaml'
125
+ YAML.load_file self
137
126
  end
138
127
 
139
- alias_method :change_extension, :set_extension
140
-
141
- def without_extension
142
- to_s[/^ (.+?) (\. ([^\.]+))? $/x, 1].p
143
- end
144
128
 
145
- def has_extension?(ext)
146
- !!(self.to_s =~ /\.#{ext}$/)
147
- end
129
+ # Querying the tree below the dir the path refers to.
148
130
 
149
- def parent
150
- super.p
131
+ def grep *args
132
+ if exists?
133
+ matches = read.split("\n").grep(*args)
134
+ matches unless matches.empty?
135
+ end
151
136
  end
152
137
 
153
- alias_method :all_children, :children
154
-
155
- def children
156
- super.reject { |c| c.basename.to_s =~ /^\./ }
138
+ def glob expr = nil, flags = File::FNM_CASEFOLD, &block
139
+ Dir.glob((expr.nil? ? self : (self / expr)).to_s, flags, &block)
157
140
  end
158
141
 
159
- # only takes sym atm
160
142
  def select(*args)
143
+ Babushka::LogHelpers.deprecated! '2012-10-23', :instead => 'Fancypath#glob', :example => "#{to_s.inspect}.p.glob(#{args.first.inspect})"
161
144
  return args.map { |arg| select(arg) }.flatten.uniq if args.size > 1
162
145
 
163
146
  case arg = args.first
@@ -169,24 +152,67 @@ class Fancypath < Pathname
169
152
  Dir["#{self}/#{arg}"].map { |p| self.class.new(p) }
170
153
  end
171
154
  end
172
-
173
- def empty?
174
- directory? ? children.size == 0 : self.size == 0
155
+
156
+
157
+ # Filename manupulation.
158
+
159
+ def set_extension(ext)
160
+ "#{without_extension}.#{ext}".p
175
161
  end
176
-
177
- def owner
178
- Etc.getpwuid(File.stat(to_s).uid).name
162
+ alias_method :change_extension, :set_extension
163
+
164
+ def without_extension
165
+ to_s[/^ (.+?) (\. ([^\.]+))? $/x, 1].p
179
166
  end
180
167
 
181
- def group
182
- Etc.getgrgid(File.stat(to_s).gid).name
168
+ def has_extension?(ext)
169
+ !!(self.to_s =~ /\.#{ext}$/)
183
170
  end
184
171
 
185
- def inspect
186
- super.sub('Pathname','Fancypath')
172
+
173
+ # Changing the file or dir the path refers to.
174
+
175
+ def touch
176
+ `touch '#{self}'`
177
+ self
187
178
  end
188
179
 
189
- def to_fancypath
180
+ def create_dir
181
+ mkpath unless exist?
182
+ self
183
+ end
184
+ alias_method :create, :create_dir
185
+ alias_method :mkdir, :create_dir
186
+
187
+ def copy(dest)
188
+ `cp -pPR '#{self}' '#{dest}'`
189
+ self
190
+ end
191
+ alias_method :cp, :copy
192
+
193
+ def move(dest)
194
+ self.rename(dest)
195
+ dest.p
196
+ end
197
+ alias_method :mv, :move
198
+
199
+ def remove
200
+ directory? ? rmtree : delete if exist?
201
+ self
202
+ end
203
+ alias_method :rm, :remove
204
+
205
+
206
+ # Changing the contents of the file the path refers to.
207
+
208
+ def write(contents, mode='wb')
209
+ dirname.create
210
+ open(mode) { |f| f.write contents }
211
+ self
212
+ end
213
+
214
+ def append(contents)
215
+ write(contents,'a+')
190
216
  self
191
217
  end
192
218