Class: Babushka::Resource

Inherits:
Object show all
Extended by:
LogHelpers, PathHelpers, ShellHelpers
Includes:
LogHelpers, PathHelpers, ShellHelpers
Defined in:
lib/babushka/resource.rb,
lib/babushka/resource.rb

Direct Known Subclasses

DmgResource, FileResource, TarResource, ZipResource

Constant Summary

TYPES =
{
  :deb => {:file_match => 'Debian binary package', :exts => %w[deb]},
  :pkg => {:file_match => 'xar archive', :exts => %w[pkg]},
  :tar => {:file_match => 'tar archive', :exts => %w[tar]},
  :gzip => {:file_match => 'gzip compressed data', :exts => %w[tgz tar.gz]},
  :bzip2 => {:file_match => 'bzip2 compressed data', :exts => %w[tbz2 tar.bz2]},
  :zip => {:file_match => 'Zip archive data', :exts => %w[zip]},
  :dmg => {:file_match => 'VAX COFF executable not stripped', :exts => %w[dmg]}
}
CLASSES =
{
  :deb => FileResource,
  :pkg => FileResource,
  :tar => TarResource,
  :gzip => TarResource,
  :bzip2 => TarResource,
  :zip => ZipResource,
  :dmg => DmgResource
}

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from PathHelpers

cd, in_build_dir, in_dir, in_download_dir

Methods included from ShellHelpers

cmd_dir, failable_shell, log_shell, login_shell, raw_shell, shell, shell!, shell?, sudo, which

Methods included from LogHelpers

debug, log, log_block, log_error, log_ok, log_verbose, log_warn

Constructor Details

- (Resource) initialize(path, opts = {})

A new instance of Resource



85
86
87
88
# File 'lib/babushka/resource.rb', line 85

def initialize path, opts = {}
  @path = path.p
  @name = TYPES[type][:exts].inject(filename) {|fn,t| fn.gsub(/\.#{t}$/, '') }
end

Instance Attribute Details

- (Object) name (readonly)

Returns the value of attribute name



83
84
85
# File 'lib/babushka/resource.rb', line 83

def name
  @name
end

- (Object) path (readonly)

Returns the value of attribute path



83
84
85
# File 'lib/babushka/resource.rb', line 83

def path
  @path
end

Class Method Details

+ (Object) detect_type_by_contents(path)



63
64
65
66
67
# File 'lib/babushka/resource.rb', line 63

def self.detect_type_by_contents path
  TYPES.keys.detect {|key|
    shell("file '#{path}'")[TYPES[key][:file_match]]
  }
end

+ (Object) detect_type_by_extension(path)



55
56
57
58
59
60
61
# File 'lib/babushka/resource.rb', line 55

def self.detect_type_by_extension path
  TYPES.keys.detect {|key|
    TYPES[key][:exts].any? {|extension|
      path.has_extension? extension
    }
  }
end

+ (Object) download(url, filename = url.to_s.p.basename)



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/babushka/resource.rb', line 33

def self.download url, filename = url.to_s.p.basename
  if filename.p.exists? && !filename.p.empty?
    log_ok "Already downloaded #{filename}."
    filename
  elsif (result = shell(%Q{curl -I -X GET "#{url}"})).nil?
    log_error "Couldn't download #{url}: `curl` exited with non-zero status."
  else
    response_code = result.val_for(/HTTP\/1\.\d/) # not present for ftp://, etc.
    if response_code && response_code[/^[23]/].nil?
      log_error "Couldn't download #{url}: #{response_code}."
    elsif !(location = result.val_for('Location')).nil?
      log "Following redirect from #{url}"
      download URI.escape(location), location.p.basename
    else
      success = log_block "Downloading #{url}" do
        shell %Q{curl -# -o "#{filename}.tmp" "#{url}" && mv -f "#{filename}.tmp" "#{filename}"}, :progress => /[\d\.]+%/
      end
      filename if success
    end
  end
end

+ (Object) extract(url, &block)



25
26
27
28
29
30
31
# File 'lib/babushka/resource.rb', line 25

def self.extract url, &block
  get url do |download_path|
    in_build_dir {
      Resource.for(download_path).extract(&block)
    }
  end
end

+ (Object) for(path, opts = {})

Raises:



206
207
208
209
210
211
212
213
# File 'lib/babushka/resource.rb', line 206

def self.for path, opts = {}
  path = path.p
  filename = path.basename.to_s
  raise ResourceError, "The archive #{filename} does not exist." unless path.exists?
  klass = CLASSES[type(path)]
  raise ResourceError, "Don't know how to extract #{filename}." if klass.nil?
  klass.new(path, opts)
end

+ (Object) get(url, &block)



12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/babushka/resource.rb', line 12

def self.get url, &block
  filename = URI.unescape(url.to_s).p.basename
  if filename.to_s.blank?
    log_error "Not a valid URL to download: #{url}"
  else
    download_path = in_download_dir {|path|
      downloaded_file = download(url, filename)
      path / downloaded_file if downloaded_file
    }
    block.call download_path unless download_path.nil?
  end
end

+ (Object) type(path)



69
70
71
# File 'lib/babushka/resource.rb', line 69

def self.type path
  detect_type_by_extension(path) || detect_type_by_contents(path)
end

Instance Method Details

- (Object) archive_prefix



140
141
142
# File 'lib/babushka/resource.rb', line 140

def archive_prefix
  BuildPrefix
end

- (Object) content_subdir



119
120
121
122
123
124
125
126
127
# File 'lib/babushka/resource.rb', line 119

def content_subdir
  identity_dirs.reject {|dir|
    %w[app pkg bundle tmbundle prefPane].map {|i|
      /\.#{i}$/
    }.any? {|dont_descend|
      dir[dont_descend]
    }
  }.first
end

- (Object) extract(&block)



102
103
104
# File 'lib/babushka/resource.rb', line 102

def extract &block
  cd(archive_prefix, :create => true) { process_extract(&block) }
end

- (Object) filename



90
91
92
# File 'lib/babushka/resource.rb', line 90

def filename
  path.basename.to_s
end

- (Object) identity_dirs



129
130
131
132
133
134
135
136
137
138
# File 'lib/babushka/resource.rb', line 129

def identity_dirs
  everything = Dir.glob('*')
  if everything.length == 1 && File.directory?(everything.first)
    everything
  else
    Dir.glob('*/').map {|dir| dir.chomp('/') }.select {|dir|
      dir.downcase.gsub(/[ \-_\.]/, '') == name.downcase.gsub(/[ \-_\.]/, '')
    }
  end
end

- (Object) process_extract(&block)



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/babushka/resource.rb', line 106

def process_extract &block
  shell("mkdir -p '#{name}'") and
  cd(name) {
    unless log_shell("Extracting #{filename}", extract_command)
      log_error "Couldn't extract #{path} - probably a bad download."
    else
      cd(content_subdir) {
        block.nil? or block.call(self)
      }
    end
  }
end

- (Boolean) supported?

Returns:

  • (Boolean)


98
99
100
# File 'lib/babushka/resource.rb', line 98

def supported?
  !type.nil?
end

- (Object) type



94
95
96
# File 'lib/babushka/resource.rb', line 94

def type
  self.class.type path
end