#
# h2. lib/imw/files/archive.rb -- describes archives of files
#
# == About
#
# Module for describing known archive types. An including archive
# type's class must define an instance variable +archive+ which is a
# hash with the following required keys:
#
# :program:: a symbol naming the program to be used. It
# should match one of the symbols in IMW::EXTERNAL_PROGRAMS
#
# :create_flags:: a string of flags to pass to the archiving
# program when creating the archive
#
# :append_flags:: a string of flags to pass to the archiving
# program when appending files to the archive
#
# :extract_flags:: a string of flags to pass to the archiving
# program when extracting the archive
#
# :list_flags:: a string of flags to pass to the archiving
# program when listing the archive's contents
#
# THe +archive+ hash may also contain the entry:
#
# :unarchiving_program:: a symbol naming the program to be
# used to list/extract the archive. Useful only if this program
# differs from the program used to create the archive in the first
# place (i.e. - zip & unzip).
#
# Author:: (Philip flip Kromer, Dhruv Bansal) for Infinite Monkeywrench Project (mailto:coders@infochimps.org)
# Copyright:: Copyright (c) 2008 infochimps.org
# License:: GPL 3.0
# Website:: http://infinitemonkeywrench.org/
#
# puts "#{File.basename(__FILE__)}: Put it all in one place so that when something goes wrong you'll know it immediately. You'll regret it, but at least you'll know." # at bottom
module IMW
module Files
module BasicFile
# Is this file an archive?
def archive?
false
end
end
module Archive
attr_reader :archive
# Is this file an archive?
def archive?
true
end
public
# Create this archive containing the given +paths+, which can be
# either a string or list of strings to be interpreted as paths
# to files/directories by the shell.
#
# Options:
# :force (false):: overwrite any existing archive at this path.
def create paths, opts = {}
opts = opts.reverse_merge({:force => false})
raise IMW::Error.new("An archive already exists at #{@path}.") if exist? and not opts[:force]
raise IMW::Error.new("Cannot create an archive of type #{@extname}") unless @archive[:create_flags]
paths = [paths] if paths.class == String
IMW.system IMW::EXTERNAL_PROGRAMS[@archive[:program]], @archive[:create_flags], @path, *paths
self
end
# Append to this archive the given +paths+, which can be
# either a string or list of strings to be interpreted as paths
# to files/directories by the shell.
def append paths
raise IMW::Error.new("Cannot append to an archive of type #{@archive[:program]}.") unless @archive[:append_flags]
paths = [paths] if paths.class == String
IMW.system IMW::EXTERNAL_PROGRAMS[@archive[:program]], @archive[:append_flags], @path, *paths
self
end
# Extract the files from this archive to the current directory.
def extract
raise IMW::Error.new("Cannot extract, #{@path} does not exist.") unless exist?
program = (@archive[:unarchiving_program] or @archive[:program])
IMW.system IMW::EXTERNAL_PROGRAMS[program], @archive[:extract_flags], @path
end
# Return a (sorted) list of contents in this archive.
def contents
raise IMW::Error.new("Cannot list contents, #{@path} does not exist.") unless exist?
program = (@archive[:unarchiving_program] or @archive[:program])
output = ''
command = [IMW::EXTERNAL_PROGRAMS[program], @archive[:list_flags], @path].join ' '
output += `#{command}`
archive_contents_string_to_array(output)
end
# Parse and format the output from the archive program's "list"
# command into an array of filenames.
#
# An including class can customize this method to match the
# output from the archiving program of that class.
def archive_contents_string_to_array string
string.split("\n")
end
end
end
end