class RedmineInstaller::Package
Constants
- SUPPORTED_ARCHIVE_FORMATS
- TAR_LONGLINK
Attributes
package[R]
temp_dir[R]
Public Class Methods
new(task, package)
click to toggle source
Calls superclass method
# File lib/redmine-installer/package.rb, line 14 def initialize(task, package) super(task) @package = package.to_s end
Public Instance Methods
clean_up()
click to toggle source
# File lib/redmine-installer/package.rb, line 80 def clean_up @temp_dir && FileUtils.remove_entry_secure(@temp_dir) @temp_file && FileUtils.remove_entry_secure(@temp_file) end
ensure_and_valid_package()
click to toggle source
# File lib/redmine-installer/package.rb, line 19 def ensure_and_valid_package if package.empty? @package = prompt.ask('Path to package:', required: true) end if !File.exist?(@package) if @package =~ /\Av?(\d\.\d\.\d)\Z/ @package = download_redmine_version($1) elsif valid_url?(@package) @package = download_from_url(@package) else error "File doesn't exist #{@package}" end end @type = File.extname(@package) unless SUPPORTED_ARCHIVE_FORMATS.include?(@type) error "File #{@package} must have format: #{SUPPORTED_ARCHIVE_FORMATS.join(', ')}" end end
extract()
click to toggle source
# File lib/redmine-installer/package.rb, line 40 def extract print_title('Extracting redmine package') @temp_dir = Dir.mktmpdir case @type when '.zip' extract_zip when '.gz', '.tgz' extract_tar_gz end logger.info("Package was loaded into #{@temp_dir}.") end
redmine_root()
click to toggle source
Move files from temp dir to target. First check if folder contains redmine or contains folder which contains redmine.
Package
can have format: |– redmine-2
|-- app `-- config
…
# File lib/redmine-installer/package.rb, line 64 def redmine_root root = @temp_dir loop { ls = Dir.glob(File.join(root, '*')) if ls.size == 1 root = ls.first else break end } root end
Private Instance Methods
download_from_url(url)
click to toggle source
# File lib/redmine-installer/package.rb, line 99 def download_from_url(url) uri = URI.parse(url) @temp_file = Tempfile.new(['redmine', '.zip']) @temp_file.binmode Net::HTTP.start(uri.host, uri.port) do |http| head = http.request_head(uri) unless head.is_a?(Net::HTTPSuccess) error "Cannot download #{uri}" end print_title("Downloading #{uri}") progressbar = TTY::ProgressBar.new(PROGRESSBAR_FORMAT, total: head['content-length'].to_i, frequency: 2, clear: true) http.get(uri) do |data| @temp_file.write(data) progressbar.advance(data.size) end progressbar.finish end logger.info("#{uri} downloaded") @temp_file.close @temp_file.path end
download_redmine_version(version)
click to toggle source
# File lib/redmine-installer/package.rb, line 94 def download_redmine_version(version) url = "http://www.redmine.org/releases/redmine-#{version}.zip" download_from_url(url) end
extract_tar_gz()
click to toggle source
Extract .tar.gz archive based on dracoater.blogspot.cz/2013/10/extracting-files-from-targz-with-ruby.html
Originally tar did not support paths longer than 100 chars. GNU tar is better and they implemented support for longer paths, but it was made through a hack called ././@LongLink. Shortly speaking, if you stumble upon an entry in tar archive which path equals to above mentioned ././@LongLink, that means that the following entry path is longer than 100 chars and is truncated. The full path of the following entry is actually the value of the current entry.
# File lib/redmine-installer/package.rb, line 156 def extract_tar_gz Gem::Package::TarReader.new(Zlib::GzipReader.open(@package)) do |tar| # Progressbar progressbar = TTY::ProgressBar.new(PROGRESSBAR_FORMAT, total: tar.count, frequency: 2, clear: true) # tar.count move position pointer to end tar.rewind dest_file = nil tar.each do |entry| if entry.full_name == TAR_LONGLINK dest_file = File.join(@temp_dir, entry.read.strip) next end # Pax header # "%d %s=%s\n", <length>, <keyword>, <value> if entry.header.typeflag == 'x' pax_headers = entry.read.split("\n") pax_headers.each do |header| meta, value = header.split('=', 2) length, keyword = meta.split(' ', 2) if keyword == 'path' dest_file = File.join(@temp_dir, value) next end end # If there is no header with keyword "path" next end dest_file ||= File.join(@temp_dir, entry.full_name) if entry.directory? FileUtils.rm_rf(dest_file) unless File.directory?(dest_file) FileUtils.mkdir_p(dest_file, mode: entry.header.mode, verbose: false) elsif entry.file? FileUtils.rm_rf(dest_file) unless File.file?(dest_file) File.open(dest_file, 'wb') do |f| f.write(entry.read) end FileUtils.chmod(entry.header.mode, dest_file, verbose: false) elsif entry.header.typeflag == '2' # symlink File.symlink(entry.header.linkname, dest_file) end dest_file = nil progressbar.advance(1) end progressbar.finish end end
extract_zip()
click to toggle source
# File lib/redmine-installer/package.rb, line 129 def extract_zip Zip::File.open(@package) do |zip_file| # Progressbar progressbar = TTY::ProgressBar.new(PROGRESSBAR_FORMAT, total: zip_file.size, frequency: 2, clear: true) zip_file.each do |entry| dest_file = File.join(@temp_dir, entry.name) FileUtils.mkdir_p(File.dirname(dest_file)) entry.extract(dest_file) progressbar.advance(1) end progressbar.finish end end
valid_url?(string)
click to toggle source
# File lib/redmine-installer/package.rb, line 87 def valid_url?(string) uri = URI.parse(string) ['http', 'https'].include?(uri.scheme) rescue URI::BadURIError, URI::InvalidURIError false end