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
@@ -0,0 +1,16 @@
1
+ meta :bin do
2
+ accepts_list_for :installs, :basename, :choose_with => :via
3
+ accepts_list_for :provides, :basename, :choose_with => :via
4
+
5
+ template {
6
+ requires_when_unmet Babushka.host.pkg_helper.manager_dep
7
+
8
+ met? {
9
+ in_path? provides
10
+ }
11
+
12
+ meet {
13
+ Babushka.host.pkg_helper.handle_install! installs
14
+ }
15
+ }
16
+ end
@@ -1,11 +1,9 @@
1
1
  meta :installer do
2
2
  accepts_list_for :source
3
- accepts_list_for :extra_source
4
3
  accepts_list_for :provides, :basename, :choose_with => :via
5
4
  accepts_list_for :prefix, %w[~/Applications /Applications]
6
5
 
7
6
  template {
8
- prepare { setup_source_uris }
9
7
  met? { in_path?(provides) }
10
8
 
11
9
  # At the moment, we just try to install every .[m]pkg in the archive.
@@ -17,13 +15,15 @@ meta :installer do
17
15
  # end
18
16
  #
19
17
  meet {
20
- process_sources {|archive|
21
- Dir.glob("**/*pkg").select {|entry|
22
- entry[/\.m?pkg$/] # Everything ending in .pkg or .mpkg
23
- }.reject {|entry|
24
- entry[/\.m?pkg\//] # and isn't inside another package
25
- }.map {|entry|
26
- log_shell "Installing #{entry}", "installer -target / -pkg '#{entry}'", :sudo => true
18
+ source.each {|uri|
19
+ Babushka::Resource.extract(uri) {|archive|
20
+ Dir.glob("**/*pkg").select {|entry|
21
+ entry[/\.m?pkg$/] # Everything ending in .pkg or .mpkg
22
+ }.reject {|entry|
23
+ entry[/\.m?pkg\//] # and isn't inside another package
24
+ }.map {|entry|
25
+ log_shell "Installing #{entry}", "installer -target / -pkg '#{entry}'", :sudo => true
26
+ }
27
27
  }
28
28
  }
29
29
  }
@@ -0,0 +1,17 @@
1
+ meta :lib do
2
+ accepts_list_for :installs, :basename, :choose_with => :via
3
+
4
+ template {
5
+ requires Babushka.host.pkg_helper.manager_dep
6
+
7
+ met? {
8
+ installs.all? {|pkg|
9
+ Babushka.host.pkg_helper.has?(pkg)
10
+ }
11
+ }
12
+
13
+ meet {
14
+ Babushka.host.pkg_helper.handle_install! installs
15
+ }
16
+ }
17
+ end
@@ -7,28 +7,7 @@ managed_template = L{
7
7
  packages.all? {|pkg| pkg_manager.has? pkg }
8
8
  end
9
9
 
10
- def add_cfg_deps
11
- cfg.all? {|target|
12
- target_file = target.to_s
13
- source_file = load_path.dirname / name / "#{File.basename(target_file)}.erb"
14
- requires(dep("#{File.basename(target_file)} for #{name}") {
15
- met? { babushka_config? target_file }
16
- before {
17
- shell "mkdir -p #{File.dirname(target_file)}", :sudo => !File.writable?(File.dirname(File.dirname(target_file)))
18
- shell "chmod o+rx #{File.dirname(target_file)}", :sudo => !File.writable?(File.dirname(target_file))
19
- }
20
- meet { render_erb source_file, :to => target_file, :sudo => !File.writable?(File.dirname(target_file)) }
21
- on :linux do
22
- after { service_name.each {|s| sudo "/etc/init.d/#{s} restart" } }
23
- end
24
- })
25
- }
26
- end
27
-
28
10
  requires pkg_manager.manager_dep
29
- prepare {
30
- add_cfg_deps
31
- }
32
11
  met? {
33
12
  if installs.blank?
34
13
  log_ok "Nothing to install on #{pkg_manager.manager_key}-based systems."
@@ -47,19 +26,9 @@ managed_template = L{
47
26
  meta :managed do
48
27
  accepts_list_for :installs, :basename, :choose_with => :via
49
28
  accepts_list_for :provides, :basename, :choose_with => :via
50
- accepts_list_for :service_name, :name
51
- accepts_list_for :cfg
52
29
 
53
30
  def pkg_manager
54
- Babushka::Base.host.pkg_helper
55
- end
56
-
57
- def chooser
58
- Babushka::Base.host.match_list
59
- end
60
-
61
- def chooser_choices
62
- Babushka::PkgHelper.all_manager_keys + Babushka::SystemDefinitions.all_tokens
31
+ Babushka.host.pkg_helper
63
32
  end
64
33
 
65
34
  template(&managed_template)
@@ -68,8 +37,6 @@ end
68
37
  meta :gem do
69
38
  accepts_list_for :installs, :basename, :choose_with => :via
70
39
  accepts_list_for :provides, :basename, :choose_with => :via
71
- accepts_list_for :service_name, :name
72
- accepts_list_for :cfg
73
40
 
74
41
  def pkg_manager
75
42
  Babushka::GemHelper
@@ -81,8 +48,6 @@ end
81
48
  meta :pip do
82
49
  accepts_list_for :installs, :basename, :choose_with => :via
83
50
  accepts_list_for :provides, :basename, :choose_with => :via
84
- accepts_list_for :service_name, :name
85
- accepts_list_for :cfg
86
51
 
87
52
  def pkg_manager
88
53
  Babushka::PipHelper
@@ -94,8 +59,6 @@ end
94
59
  meta :npm do
95
60
  accepts_list_for :installs, :basename, :choose_with => :via
96
61
  accepts_list_for :provides, [], :choose_with => :via
97
- accepts_list_for :service_name, :name
98
- accepts_list_for :cfg
99
62
 
100
63
  def pkg_manager
101
64
  Babushka::NpmHelper
@@ -22,11 +22,11 @@ meta :src do
22
22
  accepts_block_for(:postinstall)
23
23
 
24
24
  accepts_block_for(:process_source) {
25
- call_task(:preconfigure) and
26
- call_task(:configure) and
27
- call_task(:build) and
28
- call_task(:install) and
29
- call_task(:postinstall)
25
+ invoke(:preconfigure) and
26
+ invoke(:configure) and
27
+ invoke(:build) and
28
+ invoke(:install) and
29
+ invoke(:postinstall)
30
30
  }
31
31
 
32
32
  def default_configure_command
@@ -34,9 +34,17 @@ meta :src do
34
34
  end
35
35
 
36
36
  template {
37
- requires 'build tools', 'curl.managed'
38
- prepare { setup_source_uris }
37
+ requires 'build tools', 'curl.bin'
39
38
  met? { in_path?(provides) }
40
- meet { process_sources { call_task :process_source } }
39
+ meet {
40
+ extra_source.each {|uri|
41
+ Babushka::Resource.extract(uri)
42
+ }
43
+ source.each {|uri|
44
+ Babushka::Resource.extract(uri) {|archive|
45
+ invoke(:process_source)
46
+ }
47
+ }
48
+ }
41
49
  }
42
50
  end
@@ -0,0 +1,11 @@
1
+ meta :task do
2
+ accepts_block_for :run
3
+ template {
4
+ met? {
5
+ @run
6
+ }
7
+ meet {
8
+ invoke(:run).tap {|result| @run = result }
9
+ }
10
+ }
11
+ end
@@ -5,11 +5,25 @@ meta :tmbundle, :for => :osx do
5
5
  '~/Library/Application Support/TextMate/Bundles' / name
6
6
  end
7
7
 
8
+ def repo
9
+ @repo ||= Babushka::GitRepo.new(path).tap {|r|
10
+ r.repo_shell("git fetch") if r.exists?
11
+ }
12
+ end
13
+
8
14
  template {
9
15
  requires 'benhoskings:TextMate.app'
10
- met? { path.dir? }
16
+ met? { repo.exists? && !repo.behind? }
11
17
  before { shell "mkdir -p '#{path.parent}'" }
12
- meet { git source, :to => path }
18
+ meet {
19
+ if repo.exists?
20
+ log_block "Updating to #{repo.current_remote_branch} (#{repo.resolve(repo.current_remote_branch)})" do
21
+ repo.reset_hard!(repo.current_remote_branch)
22
+ end
23
+ else
24
+ git source, :to => path
25
+ end
26
+ }
13
27
  after { log_shell "Telling TextMate to reload bundles", %Q{osascript -e 'tell app "TextMate" to reload bundles'} }
14
28
  }
15
29
  end
data/lib/babushka.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Babushka
2
- VERSION = '0.10.8'
2
+ VERSION = '0.15.6'
3
3
  WorkingPrefix = '~/.babushka'
4
4
  SourcePrefix = '~/.babushka/sources'
5
5
  BuildPrefix = '~/.babushka/build'
@@ -11,10 +11,9 @@ module Babushka
11
11
  module Path
12
12
  def self.binary() File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__ end
13
13
  def self.bin() File.dirname(binary) end
14
- # this is not correct in gem version
15
14
  def self.path() File.dirname(bin) end
16
15
  def self.lib() File.join(path, 'lib') end
17
- def self.run_from_path?() ENV['PATH'].split(':').include? File.dirname($0) end
16
+ def self.run_from_path?() ENV['PATH'].split(':').include?(File.dirname($0)) end
18
17
  end
19
18
  end
20
19
 
@@ -8,10 +8,12 @@ module Babushka
8
8
  def default_blocks
9
9
  merged_default_blocks_for self
10
10
  end
11
+
11
12
  def merged_default_blocks_for klass
12
13
  parent_values = klass == DepDefiner ? {} : merged_default_blocks_for(klass.superclass)
13
14
  parent_values.merge(default_blocks_for(klass))
14
15
  end
16
+
15
17
  def default_blocks_for klass
16
18
  (@@default_blocks ||= Hashish.hash)[klass]
17
19
  end
@@ -41,7 +43,7 @@ module Babushka
41
43
  end
42
44
 
43
45
  def default_block_for block_name
44
- differentiator = Base.host.differentiator_for payload[block_name].keys
46
+ differentiator = Babushka.host.differentiator_for payload[block_name].keys
45
47
  L{
46
48
  debug "#{block_name} not defined#{" for #{differentiator}" unless differentiator.nil?}."
47
49
  true
@@ -56,7 +58,7 @@ module Babushka
56
58
  raise "#{method_name} only accepts args like :on => :linux (as well as a block arg)." unless args.empty? || args.first.is_a?(Hash)
57
59
 
58
60
  payload[method_name] ||= {}
59
- chosen_on = (args.first || {})[:on] || @current_platform || :all
61
+ chosen_on = (args.first || {})[:on] || current_platform || :all
60
62
  payload[method_name][chosen_on] = block
61
63
  end
62
64
 
@@ -65,7 +67,7 @@ module Babushka
65
67
  end
66
68
 
67
69
  def specific_block_for method_name
68
- payload[method_name][(Base.host.match_list & payload[method_name].keys).first] ||
70
+ payload[method_name][(Babushka.host.match_list & payload[method_name].keys).first] ||
69
71
  default_blocks[method_name]
70
72
  end
71
73
  end
@@ -0,0 +1,172 @@
1
+ module Babushka
2
+ class AssetError < StandardError
3
+ end
4
+
5
+ class Asset
6
+ extend ShellHelpers
7
+ include ShellHelpers
8
+ include PathHelpers
9
+
10
+ def self.detect_type_by_extension path
11
+ ASSET_TYPES.keys.detect {|key|
12
+ ASSET_TYPES[key][:exts].any? {|extension|
13
+ path.has_extension? extension
14
+ }
15
+ }
16
+ end
17
+
18
+ def self.detect_type_by_contents path
19
+ ASSET_TYPES.keys.detect {|key|
20
+ shell("file '#{path}'")[ASSET_TYPES[key][:file_match]]
21
+ }
22
+ end
23
+
24
+ def self.type path
25
+ detect_type_by_extension(path) || detect_type_by_contents(path)
26
+ end
27
+
28
+ attr_reader :path, :name
29
+
30
+ def initialize path, opts = {}
31
+ @path = path.p
32
+ @name = ASSET_TYPES[type][:exts].inject(filename) {|fn,t| fn.gsub(/\.#{t}$/, '') }
33
+ end
34
+
35
+ def filename
36
+ path.basename.to_s
37
+ end
38
+
39
+ def type
40
+ self.class.type path
41
+ end
42
+
43
+ def supported?
44
+ !type.nil?
45
+ end
46
+
47
+ def extract &block
48
+ cd(build_prefix, :create => true) { process_extract(&block) }
49
+ end
50
+
51
+ def process_extract &block
52
+ shell("mkdir -p '#{name}'") and
53
+ cd(name) {
54
+ unless ShellHelpers.log_shell("Extracting #{filename}", extract_command)
55
+ LogHelpers.log_error "Couldn't extract #{path} - probably a bad download."
56
+ else
57
+ cd(content_subdir) {
58
+ block.nil? or block.call(self)
59
+ }
60
+ end
61
+ }.tap {|result|
62
+ if result
63
+ LogHelpers.log_block "Cleaning up" do
64
+ (build_prefix / name).p.rm
65
+ end
66
+ else
67
+ LogHelpers.log "The build artefacts are in #{build_prefix / name / content_subdir}."
68
+ end
69
+ }
70
+ end
71
+
72
+ def content_subdir
73
+ identity_dirs.reject {|dir|
74
+ %w[app pkg bundle tmbundle prefPane].map {|i|
75
+ /\.#{i}$/
76
+ }.any? {|dont_descend|
77
+ dir[dont_descend]
78
+ }
79
+ }.first
80
+ end
81
+
82
+ def identity_dirs
83
+ everything = Dir.glob('*')
84
+ if everything.length == 1 && File.directory?(everything.first)
85
+ everything
86
+ else
87
+ Dir.glob('*/').map {|dir| dir.chomp('/') }.select {|dir|
88
+ dir.downcase.gsub(/[ \-_\.]/, '') == name.downcase.gsub(/[ \-_\.]/, '')
89
+ }
90
+ end
91
+ end
92
+
93
+ def build_prefix
94
+ BuildPrefix
95
+ end
96
+ end
97
+
98
+ class FileAsset < Asset
99
+ def extract &block
100
+ in_download_dir {
101
+ block.call(self)
102
+ }
103
+ end
104
+ end
105
+
106
+ class TarAsset < Asset
107
+ def extract_command
108
+ "tar -#{extract_option(type)}xf '#{path}'"
109
+ end
110
+
111
+ def extract_option type
112
+ {
113
+ :tar => '',
114
+ :gzip => 'z',
115
+ :bzip2 => 'j'
116
+ }[type]
117
+ end
118
+ end
119
+
120
+ class ZipAsset < Asset
121
+ def extract_command
122
+ "unzip -o '#{path}'"
123
+ end
124
+ end
125
+
126
+ class DmgAsset < Asset
127
+ def extract &block
128
+ in_download_dir {
129
+ output = ShellHelpers.log_shell "Attaching #{filename}", "hdiutil attach '#{filename.p.basename}'"
130
+ if output.nil?
131
+ LogHelpers.log_error "Couldn't mount #{filename.p}."
132
+ elsif (path = mountpoint_for(output)).nil?
133
+ raise "Couldn't find where `hdiutil` mounted #{filename.p}."
134
+ else
135
+ cd(path) {
136
+ block.call(self)
137
+ }.tap {
138
+ ShellHelpers.log_shell "Detaching #{filename}", "hdiutil detach '#{path}'"
139
+ }
140
+ end
141
+ }
142
+ end
143
+
144
+ def mountpoint_for output
145
+ output.scan(/\s+(\/Volumes\/[^\n]+)/).flatten.first
146
+ end
147
+ end
148
+
149
+ class Asset
150
+ ASSET_TYPES = {
151
+ :deb => {:exts => %w[deb], :class => FileAsset, :file_match => 'Debian binary package'},
152
+ :pkg => {:exts => %w[pkg], :class => FileAsset, :file_match => 'xar archive'},
153
+ :tar => {:exts => %w[tar], :class => TarAsset, :file_match => 'tar archive'},
154
+ :gzip => {:exts => %w[tgz tar.gz], :class => TarAsset, :file_match => 'gzip compressed data'},
155
+ :bzip2 => {:exts => %w[tbz2 tar.bz2], :class => TarAsset, :file_match => 'bzip2 compressed data'},
156
+ :zip => {:exts => %w[zip], :class => ZipAsset, :file_match => 'Zip archive data'},
157
+ :dmg => {:exts => %w[dmg], :class => DmgAsset, :file_match => 'VAX COFF executable not stripped'}
158
+ }
159
+
160
+ def self.for path, opts = {}
161
+ path = path.p
162
+ filename = path.basename.to_s
163
+ raise AssetError, "The archive #{filename} does not exist." unless path.exists?
164
+ if (asset_type = ASSET_TYPES[type(path)]).nil?
165
+ raise AssetError, "Don't know how to extract #{filename}."
166
+ else
167
+ asset_type[:class].new(path, opts)
168
+ end
169
+ end
170
+ end
171
+
172
+ end